next up previous contents index
Next: ,,... allerlei Bäume, lustig Up: Schritt für Schritt ins Previous: ,,...und setzte den Menschen

Und was hängt an dem Baum? (before und after)

Erwartungsgemäß hängt ein Apfel am Baum; aber es ist ein ganz spezieller Apfel: Wer davon isst, der gewinnt die Erkenntnis. Es ist aber gar nicht so einfach, ihn zu essen: zuerst muss man ihn haben. Und es ist verboten, ihn zu nehmen! Wer es aber zweimal unmittelbar hintereinander versucht, hat Erfolg15:

Object -> Apfel 
 with  name 'Apfel' 'verboten' 'Frucht' 'gross' 'schillernd' 'rund', 
       short_name "Apfel", 
       adj "verboten", 
       dekl 2, 
       initial "Am Baum hängt ein großer Apfel.", 
       description "Das also ist die verbotene Frucht:  
                    ein auffallend großer, runder Apfel. 
                    Er schillert in der Sonne, seine  
                    Farbe ist schwer auszumachen.", 
       before [; 
                take: if (self has general) 
                          print "Du fasst dir ein Herz und ... "; 
                      else 
                      { 
                          give self general; 
                          "Du lässt die verbotene Frucht 
                           lieber am Baum hängen."; 
                      } 
              ], 
       after  [; 
                take: "pflückst den Apfel mit zitternden Fingern."; 
                eat:  give Adam Erkenntnis;

                     "Du isst den Apfel vom Baum der Erkenntnis -

                      Gedanken strömen auf dich ein wie ein Fluss,  
                      der über seine Ufer tritt.  
                      Du bist einen Augenblick lang benommen.^^ 
                      Du hast etwas Verbotenes getan.  
                      Du bist böse. Und du bist nackt." 
              ],  
       react_before [; 
                take: if (noun~=self)  
                         give self ~general; 
                default: give self ~general; 
              ], 
 has   male edible;

Initial
ist eine Kurzbeschreibung, die anstelle des normalen ,,Du siehst hier einen Apfel'' ausgegeben wird, solange der Spieler den Apfel noch nicht genommen hat (d.h. solange er das in diesem Fall automatisch vergebene Attribut moved nicht besitzt).16
edible
ist ein Attribut, das den Apfel essbar macht (man muss ihn aber zuerst haben!)
general
ist ein ,,allgemeines'' Attribut, das der Autorin zur Benutzung offen steht - zu Beginn ist es immer ungesetzt; oft wird es gesetzt, sobald ein mit dem Objekt verbundenes Rätsel gelöst ist. Hier verwende ich es, um zu markieren, ob der Spieler bereits einmal versucht hat, den Apfel zu nehmen; der zweite Versuch wird dann erfolgreich sein.
self
ist ein Platzhalter, der in Code innerhalb einer Objektdefinition das jeweilige Objekt selbst meint; statt self könnte im obigen Beispiel überall auch Apfel stehen.
has
ist an dieser Stelle ein logischer Operator, der testet, ob ein Objekt ein bestimmtes Attribut hat oder nicht.
if
und else ermöglichen es, abhängig von einer Bedingung (self has general) entweder einen (hier: print "Du fasst dir ein Herz und ... ";) oder einen anderen {den in geschweiften Klammern nach else folgenden} bestimmten Teil des Programms auszuführen. Wie das genau funktioniert, ist beschrieben in 3.1.3. Es kann nicht schaden, gleich auch den folgenden Abschnitt über switch zu lesen, denn die Anweisungen in before usw. folgen derselben Syntax wie dort beschrieben.
print
ist der Befehl, die nachfolgende Zeichenkette (oder mehrere, mit Komma getrennte) zu drucken und nichts weiter zu tun. Will man danach eine neue Zeile haben, so kann man die auszudruckende Zeichenkette mit ^ enden lassen oder den Befehl new_line anhängen. Dies darf keinesfalls verwechselt werden mit print_ret.
print_ret
druckt ebenfalls den oder die nachfolgenden String(s) aus und läßt eine Zeilenschaltung folgen. Damit aber nicht genug, es enthält außerdem noch die abschließende Befehlsfolge return true.
return
bewirkt einen Rücksprung aus dem [; in eckige Klammern eingeschlossenen]; Programmblock. return kann von einem Rückgabewert gefolgt sein; die häufigst benötigten Rückgabewerte sind die logischen Werte true und false. Für ein return mit diesen Rückgabewerten gibt es die Kurzschreibweisen rtrue bzw. rfalse.
"..."
als selbständiger Befehl (also nicht nach einer Zuweisung oder nach einem print) steht tatsächlich für die häufig benötigte Kombination print "..."; newline; return true;17
Take
und
Eat
stehen für bestimmte Aktionen; hier die Aktionen, die ausgelöst werden, wenn der Spieler versucht, den Apfel zu nehmen oder ihn zu essen. Eine Übersicht über die vordefinierten Aktionen und die ,,Verben'', d.h. die Eingaben des Spielers, die die Aktionen auslösen, enthält Kapitel 4.
before
ist der Platz für eine Routine (in eckigen Klammern, aber ohne Namen, deshalb das Semikolon unmittelbar nach der öffnenden Klammer); die auf Aktionen reagiert, die der Spieler mit dem Apfel anstellt. Gibt er den Befehl ,,Nimm den Apfel'', so wird die Routine in der before-property des Apfels aufgerufen und die auszuführende Aktion auf den Wert Take gesetzt. Die Routine kann für jede Aktion einen eigenen Zweig enthalten, in dem festgelegt wird, wie der Apfel auf die Aktion des Spielers reagiert. Im Beispiel ist nur ein Zweig für Take enthalten. (Eat wird von der Library abgewiesen, wenn der Spieler den Apfel nicht hat.)

Das Programm prüft nun das Attribut general; ist es gesetzt, gibt es mit print "..." einen einleitenden Text aus und macht nichts weiter. Die Routine gibt - wenn nicht ausdrücklich etwas anderes angegeben ist - den Wert false zurück; die Library überprüft, ob der Apfel genommen werden kann und wird ihn dem Spieler geben, weil nichts entgegensteht. Ist aber general nicht gesetzt - und zu Beginn ist es das nicht - dann wird eine andere Nachricht ausgegeben (mit der Kurzschreibweise "...", die auch für ein return true; am Ende steht!) und die Routine gibt true zurück. Das bedeutet aber für Inform soviel wie ,,Alles fertig - Schluss mit der Aktion'', der Zug ist zu Ende, der Apfel bleibt wo er war. (Vorher haben wir allerdings mit dem Befehl give self general; das Attribut für den nächsten Versuch gesetzt.)

Auch Erkenntnis ist ein Attribut, das gesetzt wird, wenn der Spieler (repräsentiert durch das Objekt Adam, wie wir noch sehen werden) den Apfel isst.

after
funktioniert nach demselben Prinzip wie before, wird aber erst aufgerufen, nachdem die Library geprüft hat, ob die Aktion ausgeführt werden kann und sie auch ausgeführt hat (z.B. bei Take den Apfel zum child des Spielers gemacht hat oder bei Eat den Apfel hat verschwinden lassen). Ein false als Rückgabewert bedeutet, dass die Library nun auch ihren vordefinierten Standardtext für die Aktion ausgeben soll; ein true als Rückgabewert bedeutet wieder ,,Alles fertig - Schluss mit der Aktion''.

Im Beispiel werden - für ein erfolgreiches Take oder Eat - Texte mit dem Befehl "..." ausgegeben, der ein implizites return true; enthält. Nach diesem Text ist also in beiden Fällen Schluss mit der jeweiligen Aktion.

react_before
funktioniert (ebenso wie eine weitere property mit dem Namen react_after) in gleicher Weise; nur wird sie nicht nur bei Befehlen aufgerufen, in denen der Apfel direktes Objekt ist (,,nimm den Apfel'') sondern bei allen Befehlen, die im Blickfeld des Apfels18 stattfinden.

Im Beispiel wird sie benutzt, um das Attribut general wieder zurückzusetzen (man beachte die vorangestellte Tilde!), wenn der Spieler einen anderen Befehl gibt als ,,nimm den Apfel''. Dies bewirkt, dass der Apfel nur genommen werden kann, wenn der Spieler seinen Befehl ,,nimm den Apfel'' zweimal unmittelbar nacheinander erteilt.

~ Die einfache Tilde wird von Inform als Modifikator verwendet. Unmittelbar vor ein Attribut gesetzt, verkehrt sie es ins Gegenteil. Nota bene: Der Operator für logisches NOT ist die doppelte Tilde ~~. Weil wir gerade dabei sind:

~= ist ein logischer Operator, der zwei Objekte auf Ungleichheit testet, der Gleichheitsoperator ist logischerweise ==. Zuweisungen erfolgen mit einem einfachen Gleichheitszeichen. Für eine vollständige Liste der Operatoren siehe 3.1.1.

noun
ist eine Variable, die das direkte (erste) Objekt des aktuellen Befehls enthält, bei ,,nimm den Apfel'' also den Apfel.
default
ist ein Schlüsselwort, das für jede andere Aktion steht.



Footnotes

... Erfolg15
Der ,,originale'' Apfel aus ,,Eden'' verhält sich anders.
...16
Tatsächlich hängt der Apfel nur aus Sicht des Spielers - der diesen Initial-Text zu lesen bekommt - am Baum. Aus Sicht der Spielerfigur und der Autorin hängt der Apfel freischwebend daneben (er ist nicht Unterobjekt des Baums, sondern Unterobjekt desselben Raums, in dem auch der Baum steht). Das hat den Vorteil, dass der Spieler nicht erst den Baum durchsuchen oder aufmachen muss, um den Apfel zu finden; aber es hat auch den Nachteil, dass das Nachmodellieren des Befehls ,,Nimm den Apfel vom Baum'' nachher noch Arbeit machen wird (2.13.3).
... true;17
Bitte lesen Sie nochmal die obige Definition: An keiner Stelle folgt nach einem eigenständigen "..."-Befehl noch irgend etwas anderes. (Stünde etwas dort, würde es wegen des enthaltenen return nie ausgeführt.)
... Apfels18
genauer: die stattfinden, während der Apfel im Blickfeld des Spielers ist.

next up previous contents index
Next: ,,... allerlei Bäume, lustig Up: Schritt für Schritt ins Previous: ,,...und setzte den Menschen
Frank Borger
2003-05-02