 |
Um mit CommandPuppets arbeiten zu können braucht man einen Editor,
der "ASCII-Texte" abspeichert (zB der normale Editor bzw. Notepad
unter Windows und etwas Web-Space (=eine eigene Web-Seite). Woher
man sowas nimmt, dazu frage man irgend einen Computer-Experten,
von denen man bestimmt einen kennt, oder schaue im Puppet-Forum.
|
|
 |
|
 |
Um mit einem einfachen Test-Puppet herauszufinden, wie man Puppets
startet, hier ein kleines Test-Puppet.
PUPPET Hallo-Puppet
ACTION start
>> Huuuuuhuuuuuuu, es hat funktioniert! *freu* *hüpf*
END
PUPPETEND
Tipp dieses Puppet einfach mal mit deinem Editor ein, speichere
es unter dem Namen "test.prog" und "uploade" es dann in deinen Web-Space.
Angenommen, dein Puppet ist unter der URL
http://www.brettspielwelt.de/Other/Puppets/test.prog
zu finden (d.h. wenn du diese URL in einen Web-Browser eingibst,
dann zeigt der dein Puppet), dann kannst du es jetzt starten,
indem du folgende Zeile eingibst:
/puppet CommandPuppet MeinErstesPuppet http://www.brettspielwelt.de/Other/Puppets/test.prog
Wenn du alles richtig gemacht hast, bekommst du folgende Ausgabe
(ohne die Zeilennummern):
(1) -- Lade CommandPuppet MeinErstesPuppet.
(2) MeinErstesPuppet materialisiert sich.
(3) MeinErstesPuppet: Huuuuuhuuuuuuu, es hat funktioniert! *freu* *hüpf*
Die erste Zeile gibt an, dass der Server versucht, das Puppet zu
laden. In der nächsten Zeile steht, dass dies erfolgreich war, denn
das Puppet erscheint (diese Zeile erhalten auch alle anderen Leute
im Raum.) Interessant ist die 3. Zeile: Das Puppet tut, was es soll,
es sagt nämlich den Spruch, den wir oben im Programm einprogrammiert
haben.
Hier noch eine kurze Erläuterung der im Hallo-Puppet benutzen
Befehle:
Am Anfang eines jeden Puppets muss der Befehl "PUPPET <name>"
stehen. (Wenn ich hier was in spitzen Klammern schreibe, dann
heisst das, dass dieser Text durch was eigenes ersetzt werden
muss, oben war dies der Name "Hallo-Puppet".) Der <name> des
Puppets ist dazu da, damit man die eigenen Puppets besser auseinanderhalten
kann. Ausserdem erscheint er im Info-Text des Puppets.
Der Befehl "PUPPET <name>" signalisiert dem Server, dass
hier die Beschreibung des Puppets beginnt. (Manche Web-Space-Leute
packen nämlich noch Werbung um das Puppet rum, und die wird dann
ignoriert.)
Weiterhin sollte das Puppet mit dem Befehl "PUPPETEND" enden.
Das ist zwar nicht zwingend erforderlich, aber wenn die Web-Space-Leute
auch Werbung hinter das Puppet packen, muss man ihn doch verwenden.
Die drei Zeilen in der Mitte des Puppets beschreiben eine Action.
Eine Action ist sowas wie eine Zusammenfassung einer Folge von
Befehlen (hier allerdings nur ein einziger.) Actions beginnen
immer mit "ACTION <name>" und enden mit "END". Unsere Action
heisst "start". Das ist eine ganz besondere Action, die wird nämlich
gleich ausgeführt, wenn das Puppet gestartet wurde.
Und was macht die letzte noch nicht betrachtete Zeile ">> Huuuuuhuuuuuuu,
es hat funktioniert! *freu* *hüpf*" ? Naja, der Befehl ">> <text>"
gibt einfach den <text> im Chatfenster aus. Die beiden Leerstellen
vor diesem Befehl sind übrigens nur dort, damit die Beschreibung
besser lesbar wird und könnten auch weggelassen werden. Die Leerstelle
nach dem ">>" ist allerdings Pflicht.
|
|
 |
Puppets die auf
die Umwelt reagieren |
|
 |
So, jetzt wollen wir ein Puppet, dass "lol" sagt, wenn ich das Wort
"Witz" benutze, das alle Leute begruesst, die vorbeischauen und
das "berni ist super!" ausgibt, wenn ich ein Spiel gewonnen habe.
Hier ist dieses Puppet (http://www.brettspielwelt.de/Other/Puppets/Puppi.prog):
PUPPET Mein-Zweites-Puppet
ACTION start
WHEN KEYWORD Witz FROM berni DO lachen
WHEN APPEAR * DO begruessen
WHEN MATCH "berni*min.)" DO grats
END
ACTION lachen
>> lol
END
ACTION begruessen
>> Hallo [WHO],
>> schön, dass du gekommen bist.
END
ACTION grats
>> berni ist super!
END
PUPPETEND
Wenn ich das Puppet starte, erhalte ich:
-- Lade CommandPuppet Puppi.
Puppi materialisiert sich.
Puppi: Hallo berni,
Puppi: schön, dass du gekommen bist.
Puppi: Hallo Hallo-Puppet,
Puppi: schön, dass du gekommen bist.
Puppi: Hallo Puppi,
Puppi: schön, dass du gekommen bist.
berni: Das ist ein Witz
Puppi: lol
-- Umwerfend, wie berni das Spiel so souverän gewonnen hat (3 min.)
Puppi: berni ist super!
Was die drei Actions "lachen", "begruessen" und "grats" machen sollte
inzwischen (fast) klar sein. Interessant ist die Action "start".
(1) WHEN KEYWORD Witz FROM berni DO lachen
(2) WHEN APPEAR * DO begruessen
(3) WHEN MATCH "berni*min.)" DO grats
Die erste Zeile besagt: Wenn das Schlüsselwort "Witz" fällt, und
zwar von "berni", dann führe die Action "lachen" aus.
Die zweite Zeile besagt, dass wenn "*" den Raum betritt, die
Action "begruessen" ausgeführt werden soll. Dabei steht "*" für
all die Leute, zu dem nix anderes angegeben wurde (hier also alle).
Und bei der dritten Zeile habe ich ein bischen in die Trickkiste
gelangt. Wenn nämlich jemand ein Spiel gewinnt, kommen ganz unterschiedliche
Texte, denen aber allen gemeinsam ist, dass sie mit "min.)" enden.
Weiterhin will ich nur, dass das Puppet reagiert, wenn ich es
war, der gewonnen hat. Das kann ich mit einer MATCH-Anweisung.
Die Matchanweisung besagt: Wenn die folgende Angabe auf die Chatzeile
passt, dann führe die Action "grats" aus.
Was heisst es nun, dass die Angabe auf die Zeile passt? Eigentlich
heisst das nur, dass jedesmal, wenn ein Sternchen in der Angabe
vorkommt, beliebig viele Zeichen in der Chatzeile stehen dürfen.
Die Angabe "berni*min.)" passt also auf "berni das Spiel so
souverän gewonnen hat (3 min.)". Dabei steht das Sternchen für
" das Spiel so souverän gewonnen hat (3 ".
Oben habe ich geschrieben, dass alle anderen Actions (fast)
klar sein sollten. Das fast, habe ich da dazu geschrieben, da
es in "begruessen" noch eine Zeile gibt, die etwas seltsam ist:
>> Hallo [WHO],
Was bedeutet das [WHO]? Jedesmal, wenn durch eine WHEN-Anweisung
eine Action ausgeführt wird, werden zuvor ein paar Dinge in Variablen
gespeichert. Im Falle der WHEN APPEAR-Anweisung ist dies die Variable
"WHO", in der der Name desjenigen gespeichert wird, der aufgetaucht
ist. Schreibt man nun eckige Klammern um eine Variable, so wird
anstelle dessen der Inhalt der Variablen ausgegeben.
Hat beispielsweise die Variable "WHO" den Wert "berni", so wird
obige Zeile so interpretiert, als stünde dort:
>> Hallo berni,
WICHTIG: Es gibt Sonderfälle, in denen man mit der Variablen [WHO]
wenig anfangen kann. In der Variablen [WHO] wird allgemen das erste
Wort der Zeile gespeichert, die das Ereignis auslöst. Beim obigen
Beispiel würde infolge der Zeile "-- unglaublich, berni das Spiel
so souverän gewonnen hat (3 min.)" der Inhalt von [WHO] nicht "berni"
sondern "--" sein. Ein Doppelpunkt am Ende des ersten Wortes wird
übrigens automatisch entfernt.
|
|
 |
Einstellungen
des Puppets ändern |
|
 |
Auf Dauer ist es langweilig, wenn sich alle Puppets immer "materialisieren"
etc. Man kann diese Texte aber auf die eigenen Puppets anpassen
(http://www.brettspielwelt.de/Other/Puppets/Hund.prog):
PUPPET hund
LOGIN: " biegt um die Ecke."
LOGOUT: " rennt hinter einem Briefträger her."
APPEAR: " kommt angerannt und sagt:""Wuff""."
DISAPPEAR: " hat einen Knochen gesehn und rennt weg."
ACTION start
>> /room 42
SLEEP 2
>> /hook berni
SLEEP 2
HARAKIRI
END
PUPPETEND
Wenn man das Puppet startet, erhält man:
-- Lade CommandPuppet Hund.
Hund biegt um die Ecke.
Hund hat einen Knochen gesehn und rennt weg.
[Hund] Hund kommt angerannt und sagt:"Wuff".
[Hund] Hund hat einen Knochen gesehn und rennt weg.
Hund kommt angerannt und sagt:"Wuff".
Hund rennt hinter einem Briefträger her.
Die Befehle "LOGIN: <string>" etc. setzen einfach die entsprechenden
Texte. Diese Befehle müssen immer direkt nach dem PUPPET-Befehl
stehen. Ausserdem haben wir noch ein paar neue Befehle in der
start-Action:
Nach ">> " kann anstelle von Text auch ein (BSW-)Befehl stehen,
den das Puppet dann ausführen soll. Hier etwa ein "/room 42",
was dazu führt, dass das Puppet in Raum 42 geht.
Der "SLEEP <sek>"-Befehl führt dazu, dass das Puppet <sek>-Sekunden
lang nichts macht (=schläft). Gerade bei längeren Puppets macht
es Sinn, diesen Befehl gelegentlich mal einzubauen, damit das
Puppet sich nicht zu sehr ansträngen muss ;-)
Am Schluss steht dann noch der "HARAKIRI"-Befehl, der, wie der
Name schon vermuten lässt, das Puppet Harakiri begehen lässt,
oder weniger blumig ausgedrückt: Das Puppet loggt sich aus.
|
|
|
 |
In vielen Städten wird man am
Marktplatz von
Puppets begrüßt. Dabei unterscheiden vie meisten Puppets
zwischen Bewohnern und Besuchern. Desweiteren werden die Begrüßungen
zufällig variiert. (http://www.brettspielwelt.de/Other/Puppets/gruss.prog):
PUPPET Empfangsdame
LOGIN: " beginnt ihre Arbeit."
LOGOUT: " hat Feierabend."
APPEAR: " taucht an der Rezeption auf."
DISAPPEAR: " verschwindet unter der dem Tresen."
INFO: "Ich begrüße was das Zeug hält."
ACTION start
WHEN APPEAR * DO gruss
END
ACTION gruss
GETINFO [WHO]
IF NOT EXISTS PUPPET # ist die Variable überhaupt belegt?
RETURN # andernfalls wird die ACTION gruss abgebrochen
IF NOT [PUPPET] # ein Puppet wird nicht begrüßt
BEGIN
IF [CITYNR] == 4 # jemand aus OldFolksTown (C4)?
DO OFT[RND2] # zufällige Begrüßung für OFTler
ELSE
DO FREMD[RND2] # zufällige Begrüßung für Fremde
END
END
ACTION OFT0
>> Guten Tag [TITEL] [WHO]! Schön sie zu sehen!
END
ACTION OFT1
>> [TITEL] [WHO], es ist immer eine Freude sie zu begrüßen!
END
ACTION FREMD0
>> Willkommen, [TITEL] [WHO]. Ich wünsche ihnen einen angenehmen Aufenthalt.
END
ACTION FREMD1
>> [TITEL] [WHO] aus [CITY], Was verschafft uns die Ehre?
END
PUPPETEND
Hier noch eine Erklärung der benutzten Befehle:
GETINFO <name>
liefert eine Reihe von Informationen über den Spieler <name>.
Diese Informationen werden in speziellen Variablen gespeichert,
die da wären:
CITY (Name der Stadt, aus der <name> kommt.)
CITYNR (Nummer der Stadt, aus der <name> kommt.)
LANGUAGE (de oder en, je nachdem, ob <name> deutsch oder englisch eingestellt hat)
PUPPET (TRUE oder FALSE, jen achdem, ob <name> ein Puppet ist, oder nicht)
PLAYING (TRUE oder FALSE, je nachdem, ob <name> gerade spielt, oder nicht)
TITEL (Der Titel von <name>, bsp. Baronin)
RANK (Der Rang von <name>, bsp. [W11])
SEX (Das Geschlecht, (m,w oder n))
TUTOR (TRUE oder FALSE, je nachdem, ob <name> ein Tutor ist)
REPORTER (TRUE oder FALSE, je nachdem, ob <name> ein Reporter ist)
AMT (Das Amt von <name>)
GILDENAMT (Das Gildenamt von <name>)
EXISTS <var>
Liefert TRUE, falls die Variable mit dem Namen <var> einen
Wert enthält, ansonsten FALSE. Hier ist zu beachten, dass es um
die Variable, nicht um ihren Inhalt geht. Daher keine eckigen
Klammern.
RETURN
Beendet die Ausführung einer Action.
IF <ausdruck>
BEGIN
<befehle1>
END
ELSE
BEGIN
<befehle2>
END
Wenn der Ausdruck <ausdruck> wahr ist, werden die Befehle <befehle1>
ausgeführt, ansonsten die Befehle <befehle2>. Auch hier kann
BEGIN und END jeweils weggelassen werden, wenn es sich nur um einen
Befehl handelt. Der ELSE-Teil ist auch optional.
DO <action>
Ruft die Action mit dem Name <action> auf.
[RND<zahl>]
Liefert eine Zufallszahl zwischen von 0 bis <zahl>-1, also [RND5]
eine 0, 1, 2, 3 oder 4.
|
|
 |
|
 |
Dieses Puppet ist dafür gedacht, die Spielräume einer Stadt zu durchlaufen
und die Spiele zurückzusetzen, wenn niemand anwesend ist. Wenn Spiele
vor dem Ende verlassen wurde werden diese Räume nämlich in der SpielpartnerVermittlung
nicht als frei angezeigt. Wenn Spieler anwesend sind, wird nicht
zurückgesetzt, da diese evtl. schon gejoint, aber nicht gestartet
haben könnten (http://www.brettspielwelt.de/Other/Puppets/reset.prog):
PUPPET Reset-Puppet
ACTION start
WHEN ERROR DO error # Falls ein Fehler auftritt...
WHEN TIMER 3600 DO rundgang # stündlich wird der Rundgang ausgelöst.
END
ACTION rundgang
SET RÄUME "0 2 3 6 7 8 10 11 17 19" # die Liste mit Spiel-Räumen
FOR RAUM IN [RÄUME] DO # Bei jedem Durchlauf wird der nächste Raum
# aus der Liste in RAUM gespeichert.
BEGIN
>> /room C4-[RAUM] # Das Puppet springt in den Raum.
DO spielerzahl # Die Anzahl der anwesenden
# Spieler wird ermittelt.
IF [x] == 0 # ausser Puppet(s) ist niemand anwesend.
>> /reset # Daraufhin wird das Spiel zurückgesetzt.
END
>> /room C4 # Nach Abarbeitung der Raumliste
# geht es in diesen Raum.
MASTERRESET # Hiermit wird das Puppet wieder
# in den Ursprungszustand zurückgesetz.
END
ACTION spielerzahl
GETWHO # liefert in [WHO] eine Liste mit
# den Namen der Anwesenden
SET x 0 # die Anzahl x wird zu Beginn auf 0 gesetzt.
FOR anwesender IN [WHO] DO # Alle Namen aus der Liste
# werden abgearbeitet.
BEGIN
GETINFO [anwesender] # Die Infos zum Namen werden gelesen.
IF NOT [PUPPET] # Puppets werden nicht gezählt.
EVAL x = [x] + 1 # Für jeden Spieler wird x erhöht.
END
END
ACTION error
>> Ein Fehler ist aufgetreten ([MESSAGE])
END
PUPPETEND
Hier noch eine Erklärung der benutzten Befehle:
WHEN ERROR DO <action>
Falls ein Fehler auftritt (etwa weil das Puppet durch Null zu teilen
versucht), so wird die Action <action> aufgerufen. Dort enthält
[MESSAGE] eine Fehlermeldung (bestehend aus einer Java-Fehlermeldung
und einer Zeilenangabe). Die Zeilenangabe beginnt übrigens immer
erst ab der Zeile zu zählen, wo der PUPPET-Befehl steht.
WHEN TIMER <int> DO <action>
Hiermit kann man nach Ablauf einer bestimmten Zeit <int> (in
Sekunden) die Action <action> aufrufen. Der TIMER beginnt jedesmal
neu zu zählen. Damit wird hier erreicht, dass der Rundgang nach
einer Stunde ausgeführt wird. Um einen TIMER zu deaktivieren benutzt
man den Befehl "IGNORE TIMER".
SET <var> <wert>
Schreibt in die Variable <var> den Wert <wert>. <wert>
kann auch eine Liste sein, wie die Raumliste im Beispiel.
FOR <var> IN <liste> DO
BEGIN
<befehle>
END
Für alle Elemente von <liste> wird <befehle> ausgeführt. Dabei
enthält die Variable <var> das entsprechende Element. Handelt
es sich bei <befehle> nur um einen Befehl kann man BEGIN und
END weglassen.
MASTERRESET
Das Puppet wird augenblicklich in seinen Ursprungszustand nach dem
Aufrufen zurückgesetzt. Das bedeutet: Die Ausführung des Programmes
wird abgebrochen, alle Ereignisse werden ignoriert, alle Variablen
werden gelöscht und die ACTION start wird im Anschluss erneut ausgeführt.
GETWHO
liefert in der Variablen [WHO] eine Liste aller im Raum Anwesenden
(auch Puppets).
EVAL <var> = <ausdruck>
Berechnet den Ausdruck <ausdruck> und schreibt das Ergebnis in
die Variable <var>.
|
|
 |
|
 |
Als letztes Puppet möchte ich noch ein etwas umfangreicheres Vorstellen,
welches in der Lage ist, phänomenale Rechenleistungen ;-) zu erbringen
(http://www.brettspielwelt.de/Other/Puppets/Rechenkünstler.prog):
PUPPET Rechenkünstler
ACTION start
WHEN ERROR DO error # Falls ein Fehler auftritt...
WHEN CHAT DO rechne # Bei jeder Chatzeile wird "rechne" aufgerufen.
# Die Chatzeile wird dabei in der
# Variablen CHAT gespeichert.
END
ACTION rechne
DO split # Zerlege den Chat in die einzelnen Wörter.
DO berechne # Berechne das Ergebnis
DO verrechnen # Damits lustiger ist, verrechnet er sich gelegentlich...
DO verkünden # Verkündet das Ergebnis
SLEEP 2 # etwas von der Ansträgung ausruhen
END
# Eingabe: der Chat in der Variablen CHAT
# Ausgabe: Die einzelnen Wörter in w0, w1, w2, etc. und die
# Anzahl der Wörter in anzahl.
ACTION split
SET x 0 # x ist eine Hilfsvariable, die die Wörter mitzählt.
# Wir beginnen mit dem Wort 0.
FOR wort IN [CHAT] DO # Alle Wörter der CHAT-Zeile der Reihe nach durchgehen
BEGIN
SET w[x] [wort] # Das Wort in w0 etc. abspeichern
EVAL x = [x] + 1 # Zu x eins dazu zählen.
END
SET anzahl [x] # Die Anzahl setzen.
END
# Eingabe: Die einzelnen Wörter in w0, w1, etc. und deren Anzahl in anzahl.
# Ausgabe: Das berechnete Ergebnis in ergebnis.
ACTION berechne
SET ergebnis [w1] # Ergebnis = 1. Zahl
SET x 2 # Ab dem zweiten Zeichen auslesen
UNSET op # Bisher kein Operator
WHILE [x] < [anzahl] DO
BEGIN
IF EXISTS op # Gibt es schon einen Operator?
BEGIN
IF [op] == plus # Ist dieser plus?
EVAL ergebnis = [ergebnis] + [w[x]]
# ... dann ausrechnen
IF [op] == minus # Ist dieser minus?
EVAL ergebnis = [ergebnis] - [w[x]]
# ... dann ausrechnen
IF ( [op] != plus ) AND ( [op] != minus )
# Ist dieser weder plus noch minus?
SET error "[op] kann ich nicht berechnen!"
# Dann Fehlermeldung setzen.
UNSET op
END
ELSE
BEGIN # Kein Operator, dann diesen
SET op [w[x]] # merken.
END
EVAL x = [x] + 1 # Die Variable x erhöhen.
END
IF EXISTS op # Oh, die Zeile endet mit einem
SET error "Nach [op] muss noch eine Zahl stehen!"
# Operator, das darf nicht sein.
END
ACTION verrechnen
IF NOT EXISTS error AND [RND3] == 0 # Etwa jedes dritte mal verrechnen
EVAL ergebnis = [ergebnis] + [RND5] - 2 # Ergebnis um maximal 2 ändern
END
ACTION verkünden
IF EXISTS error # Ist ein Fehler aufgetreten?
>> [error]
ELSE
>> Das Ergebnis ist: [ergebnis]
UNSET error # Fehlermeldung löschen.
END
ACTION error
SET error "Oh, da stimmt irgendwas nicht: [MESSAGE]"
END
PUPPETEND
Und wenn man ihn startet erhält man:
Rechenkünstler materialisiert sich.
berni: 1 plus 1
Rechenkünstler: Das Ergebnis ist: 2
berni: 100 minus 64
Rechenkünstler: Das Ergebnis ist: 35
berni: 9 hoch 17
Rechenkünstler: hoch kann ich nicht berechnen!
berni: 7 plus
Rechenkünstler: Nach plus muss noch eine Zahl stehen!
berni: drei plus drei
Rechenkünstler: Oh, da stimmt irgendwas nicht:
java.lang.NumberFormatException: drei in Zeile 44
Hier noch eine recht kurze Erklärung der benutzten Befehle:
UNSET <var>
Löscht eine Variable
WHILE <ausdruck>
BEGIN
<befehle>
END
Solange der Ausdruck <ausdruck> richtig ist, werden die Befehle
in <befehle> ausgeführt. Hier also, solange x<anzahl ist.
Handelt es sich bei <befehle> nur um einen Befehl kann man BEGIN
und END weglassen.
|
|
 |
Stand: 23.11.2002
|
Autoren: Yordan und berni, Layout:
Meijing
|
 |