Next: Allerlei Dämonen
Up: Schritt für Schritt ins
Previous: Aktionen abändern
Subsections
Spielen und Erkennen: Neue Verben
und Aktionen
- Aktionen
- sind bestimmte, vom Spiel festgelegte
Handlungsmuster . Wir wissen (seit 2.12.1)
bereits, dass es Aktionen gibt, die ausser einer Rückmeldung an den
Spieler nichts bewirken (z.B. ##pray)
und solche, die eine Veränderung der Spielwelt bewirken können (z.B.
##take für das Ergreifen eines Objekts
durch die Spielerfigur).
- Verben
- sind Teile der Befehle, die der Spieler eintippt,
um Aktionen auszulösen (z.B. ,,Bete''
oder ,,Nimm den Apfel''). Verben und
Aktionen sind eng miteinander verbunden.
In der Library sind bereits die wichtigsten Verben und Aktionen vordefiniert
(siehe unten 4.2). Inform ist jedoch
nicht auf die vordefinierten Verben und Aktionen beschränkt.
Im Himmel finden sich auch Musikinstrumente: Eine Posaune und eine
Harfe. Das Verb ,,blasen'' ist standardmäßig mit einer Aktion
##blow verbunden, die zu den Klasse-3-Aktionen
gehört, also lediglich einen allgemein gehaltenen Text ausgibt. Das
lässt sich für das Objekt Posaune gut verwenden:
-
- before [; blow: "Trööööt!";
],
Die Harfe muss man spielen oder zupfen. Wir brauchen also eine Aktion
##play, die durch ,,Spiele auf
der Harfe'' oder ,,Zupfe die Harfe'' ausgelöst wird:
-
- Verb 'spiel' 'zupf'
* held -> play
* 'auf' held -> play;
[ PlaySub;
print_ret "Auf ", (dem) noun, " kannst du nichts spielen.";
];
Typischerweise deklariert man - nach dem Schlüsselwort Verb
- nicht nur ein Verb allein, sondern gleich eine Gruppe von Synonymen,
hier ,,Zupfe'' und ,,Spiele''. Die Schreibweise
im Hochkommata funktioniert genauso wie im name-property,
Umlaute und ß müssen also ausgeschrieben werden. Das auslautende -e
wird immer weggelassen.
Nach der Synonymliste kommt das eigentlich Interessante:
Die Grammatikzeilen, die während des Spiels
der Parser verwenden wird, um die Eingabe des Spielers
zu analysieren. Schauen wir erstmal nach rechts: da steht nach einem
Pfeilsymbol die Aktion, die ausgeführt werden soll, also das Ergebnis
der Analyse.
Links steht ein Asterisk als Platzhalter für jedes definierte Synonym,
danach folgen Grammatiktoken. Text in Hochkommata
steht für sich selbst, 'auf' also für den
eingegebenen Text ,,auf''. held
steht für ein beliebiges Objekt, das von der Spielerfigur gehalten
wird. (Um auf einem Musikinstrument zu spielen, muss man es zuerst
in der Hand haben.) Der Parser ordnet also Eingabesätze, die mit ,,spiele''
oder ,,zupfe'' beginnen und - mit oder ohne zwischengestelltes
,,auf'' - als (grammatisches) Objekt des Satzes ein Objekt
der Spielwelt haben, das die Spielerfigur gerade in Besitz hat, der
Aktion ##play zu - und übergibt in der
Variable noun das festgestellte
Objekt.32
Für eine vollständige Liste der Grammatiktoken siehe 3.2.8.
Zu einer neudefinierten Aktion gehört zwingend eine Routine, die das
Standardverhalten der Aktion festlegt. Die Verbindung zwischen Routine
und Aktion wird durch den Namen hergestellt: Die Routine trägt den
Namen der Aktion gefolgt von den drei Zeichen sub
- hier also play und PlaySub33. Das hier festgelegte Standardverhalten trägt dem Rechnung, dass
man auf einem x-beliebigen Gegenstand nichts wird spielen können.
Die Spielbarkeit der Harfe wird wie bei der Posaune durch einen Eintrag
in der before-property des Objekts
Harfe hergestellt, etwa:
-
- before [; play: "Plingeli-Plang.";
],
Erkenntnis ist ein zentraler Begriff in Eden. Deshalb gibt
es auch dafür ein Verb, aber mit zweierlei Bedeutung, je nachdem,
ob der Spieler sich selbst oder eine andere Person erkennen will.
Das eine ist ein eher philosophisch begründeter Vorgang, das andere
- zumindest nach dem Sprachgebrauch Martin Luthers - etwas ganz
anderes. Dazu kommt, dass geeignete vordefinierte Verben schon auf
andere Aktionen zeigen: z.B. ist das Verb ,,liebe'' zusammen
mit einigen dafür wesentlich besser geeigneten Verben (,,küsse'')
für die Aktion ##kiss definiert (siehe
4.2). Beide Probleme lassen sich lösen:
-
- Verb 'erkenn'
* creature -> Love
* 'dich'/'mich' 'selbst' -> Gnothi;
creature ist das Grammatiktoken für ein
Lebewesen (alle Objekte mit dem Attribut animate).
Der Schrägstrich zwischen 'dich' und 'mich'
zeigt an, dass diese beiden Token alternativ stehen können, der Parser
erkennt also ,,erkenne dich selbst'' und ,,erkenne
mich selbst'' als identische Eingabesätze.
-
- Extend only 'lieb' replace
* creature -> Love;
Das Schlüsselwort extend
ermöglicht die Erweiterung eines Verbs, d.h. die Definition neuer
Grammatikzeilen für dieses Verb. Mit dem Zusatz only
wird klargestellt, dass nur die ausdrücklich aufgeführten Synonyme
in ihrer Bedeutung erweitert werden sollen; stünde kein only
da, würde die gesamte ursprüngliche Liste, also auch ,,küssen''
etc. auf die Aktion ##love umgeleitet.
Das ginge zu weit.
Das Schlüsselwort replace schließlich sorgt
dafür, dass die neue Grammatikzeile anstelle der vorher definierten
verwendet wird. Die Verbindung von ,,liebe'' mit der Aktion
##kiss wird also völlig unterbrochen.
Andere Möglichkeiten böten hier die Schlüsselwörter first
(die neudefinierten Zeilen werden vom Parser vor den alten durchgesehen)
und last (die neuen Grammatikzeilen werden
an die alten angehängt).
Die vordefinierten Routinen für die neuen Aktionen bieten nichts überraschendes:34
-
- [ LoveSub;
print_ret (Gder) noun, " ist dir nicht zur Gefährtin bestimmt.";
];
[ GnothiSub;
"Das ist leichter gesagt als getan ...";
];
Letzte Feinheiten
Ein zusätzliches Synonym zu einer Verbendefinition hinzuzufügen ist
so einfach wie Blumen zu pflücken:
-
- verb 'pflueck' = 'nimm';
Ein anderes Problem macht etwas mehr Arbeit. Die Obstbäume im Garten
sehen für den Spieler so aus, als trügen sie Obst. Das Obst ist aber
- wegen der besseren Sichtbarkeit - ein selbständiges Objekt und
nicht child des jeweiligen Baumes. Das
bringt den Parser in Verwirrung, wenn ein Satz wie ,,Pflücke
einen Pfirsich vom Obstbaum'' eingegeben wird - denn er parst dann
nach der Aktion ##remove, die normalerweise
als zweites Objekt einen supporter oder
container erfordert (siehe 4.2).
Ein Obstbaum ist aber weder das eine noch das andere, denn die Früchte
liegen weder auf ihm drauf noch in ihm drin.
Das kann uns indessen nicht schrecken: Erst definieren wir zwei Funktionen,
die true oder false
zurückgeben, wenn die (implizit übergebene) Variable noun
auf Obst bzw. auf einen Obstbaum zeigt:35
-
- [ ObstP;
if ((noun ofclass(Obst)) || (noun==Apfel)) rtrue;
else rfalse;
];
[ BaumP;
if (noun ofclass(Baum)) rtrue;
else rfalse;
];
Schon können wir die Grammatik für ,,nehme'' und alle verbundenen
Synonyme ergänzen und ,,Pflücke einen Pfirsich vom Obstbaum''
wird korrekt erkannt.
-
- extend 'nimm'
* noun = ObstP 'von'/'aus'/'vom' noun = BaumP -> Remove;
Das Konstrukt noun = ObstP bildet ein
Grammatiktoken, das für alle Objekte steht,
für die die Funktion ObstP den Rückgabewert
true hat (also für alle Obstarten und den
Apfel). Mutatis mutandis steht das Token noun
= BaumP für alle Bäume.
Footnotes
- ...32
- Der Parser geht sogar noch einen Schritt weiter: Hat die Spielerfigur
das Objekt nicht in der Hand, erzeugt er zuerst ein <take
Objekt>. Ist kein Objekt angegeben, versucht er, im Besitz der Spielerfigur
ein geeignetes zu finden. Hat die Spielerfigur nichts in Besitz, fragt
er nach.
- ... COLOR="#0000ff">PlaySub33
- Das CamelCase in PlaySub verwende ich nur wegen der besseren Lesbarkeit.
Groß- und Kleinschreibung ist in Inform bis auf wenige Schlüsselwörter
unbeachtlich.
- ...34
- LoveSub ist im Original viel länger, da
ich den ganzen Code hineingeschrieben habe, der eigentlich bei Eva
hätte stehen müssen.
- ...35
- Der heilige Nikolaus (Wirth) möge mir die explizite Schreibweise der
Funktionen mit if...else verzeihen!
Aber Hand aufs Herz, liebe Leserin: Weißt du, ohne oben in 2.6.3
nachzuschauen, ob die Routinen implizites true
oder false zurückgeben würden?
Next: Allerlei Dämonen
Up: Schritt für Schritt ins
Previous: Aktionen abändern
Frank Borger
2003-05-02