Nach der Beschreibung befindet sich mitten im Garten eine Quelle, von denen Flüsse in vier Richtungen laufen. Hier greifen wir nicht zur Schiebekulisse, sondern definieren eine Klasse für die Eigenschaften der verschiedenen Gewässer. Flüssigkeiten sind immer etwas schwierig in der Handhabung, wie man sieht:
lift: "Du spritzt etwas Wasser in die ohnehin schon feuchte
Luft.";
touch: "Du greift mit deinen Händen ins klare Wasser. Die
Fische nehmen Reißaus.";
take, eat, drink, taste : "Du schöpfst mit den Händen aus dem
klaren Wasser und trinkst einige Schlucke. Das Wasser
schmeckt erquickend.";
smell: "Das Wasser riecht frisch.";
transfer, empty, emptyT: "Das könnte Ewigkeiten dauern.";
fill: "Es ist schon genug Wasser darin";
enter: if (child(player))
{
print "Du legst erst alles ab, was du bei dir
trägst.^";
while (child(player))
move (child(player)) to limbo;
}
react_before [;
fill: if (noun ~= self) "Du brauchst ein Behältnis für das Wasser.";
Exit: if (player in self)
{
print "Du gehst wieder an Land";
if (child(limbo))
{
while (child(limbo))
move (child(limbo)) to player;
print " und nimmst deine Sachen an dich.^";
}
else
print ".^";
playerto (parent(self));
return true;
}
swim: if (player notin self)
<<enter self>>;
else
"Du schwimmst ein paar Züge. Das Wasser ist
erfrischend.";
take, putOn, Wear, remove:
if ((player in self) && (noun in limbo))
"Du hast ", (den) noun , " doch erst am Ufer abgelegt,
damit ", (er) noun, " nicht nass wird.";
],
after [;
Enter: "Du gehst einige Schritte ins Wasser und lässt dich
durch das kühle Nass erfrischen.";
],
inside_description [;
print "Du bist im Wasser.^";
],
add_to_scope [ sache;
objectloop (sache in limbo)
{
AddToScope(sache);
}
],
has scenery container enterable open;
Das Wasser ist ausgestattet wie ein Behälter - container - in den auch die Spielerfigur hinein kann - enterable - und zwar - open - ohne ihn vorher aufmachen zu müssen. Man kann Behälter auch verschließen und sogar zusperren; dazu aber später mehr beim Thema ,,Türen''. Solange der Behälter offen ist, ist fällt Licht aus dem Raum in ihn hinein; wenn er geschlossen ist, geht das nur dann, wenn er auch die Eigenschaft transparent besitzt. Die capacity habe ich hier weggelassen, also ist sie auf 100 gesetzt.
Ein Behälter hat auch eine Innenansicht; sie steht in der property inside_description. Diese Beschreibung ist hier so geschrieben (mit print statt print_ret), dass sie nicht true, sondern false zurückgibt. Dies bewirkt, dass die Beschreibung des Raums und die inside_description ausgegeben werden; stünde hier nur "Du bist im Wasser.", würde implizit true zurückgegeben und die Beschreibung des Raums weggelassen werden.
Wieder legt Inform nur fest, dass sich die Spielerfigur im Behälter befindet. Was sie dort macht, ob sie schwimmt, kocht oder eingefroren wird, entscheidet die Autorin.
Beim Lesen und Schreiben von Inform-Code ist es überlebenswichtig, sich immer darüber im Klaren zu sein, ob bzw. welche Codezeile einen Rücksprung mit true oder false auslöst:23
return true, rtrue | immer | true |
return false, rfalse | immer | false |
String in Anführungszeichen | in einer Zuweisung oder nach print | ohne Rücksprung |
print_ret | immer | true |
String in Anführungszeichen | als Kurzschreibweise für print_ret | true |
Ende einer Routine ], | unselbständig, innerhalb eines Objekts | false |
Ende einer Routine ]; | selbständig, außerhalb eines Objekts | true |
In einer before-property bedeutet ein Rücksprung mit true soviel wie: Ende der Aktion - nichts passiert weiter. Es ist gängiger Programmierstil, verschiedene logisch aufeinanderfolgende Abbruchkriterien nicht in eine verschachtelte if-Anweisung zu packen, sondern mehrere if-Anweisungen mit - bedingten - Rücksprungbefehlen aufeinanderfolgen zu lassen.24
Eine Besonderheit ist die virtuelle unsichtbare Umkleidekabine. Sie ist zunächst nichts als ein freischwebendes Objekt ohne Eigenschaften:
die Regeln in before werden nur ausgeführt, wenn das Wasser direktes Objekt der Aktion ist (,,Gehe ins Wasser''); die Regeln in react_before werden bereits ausgeführt, wenn das Wasser im Blickfeld ist (die Spielerfigur das Wasser sehen kann). Einige der von react_before behandelten Aktionen sind nur sinnvoll, wenn die Spielerfigur tatsächlich im Wasser drin ist, die Abfrage (player in self) also true zurückliefert.
die Programmstellen, an denen die Besitztümer de Spielfigur hin und zurück verschoben werden, enthalten keine Definition eines Rückgabewerts (mit return true oder return false). (Es handelt sich in beiden Fällen um mit eckigen Klammern [ ] eingeschlossene Routinen innerhalb einer Objektdefinition. Solche ,,unselbständigen'' Routinen geben immer false zurück, wenn es nicht anders angegeben ist, s.o.) Das führt hier dazu, dass zwar die Besitztümer verschoben werden, der Code aber sonst nicht beeinflusst, wie die Spielfigur baden geht und welche Meldungen von anderen Programmteilen dabei ausgegeben werden.
Die abgelegten Gegenstände sind zwar ganz woanders, aber für den Spieler trotzdem sichtbar. Dies wird erreicht durch die property add_to_scope. Scope heißt soviel wie Reichweite oder Blickfeld und steuert, welche Objekte der Spieler sehen kann. Versucht er, z.B. ein Objekt zu untersuchen, das nicht im Blickfeld ist, erhält er die Rückmeldung: ,,Du kannst nichts dergleichen sehen.''
add_to_scope steuert, welche Objekte zusammen mit dem Wasser automatisch im Blickfeld sind - egal wo sie sich tatsächlich befinden. Ginge es nur um einen oder mehrere immer gleiche Gegenstände, würde es ausreichen, einfach die Namen der Objekte hier aufzuführen. Da wir im voraus nicht wissen können, welche Gegenstände der Spieler bei sich haben wird, wählen wir einen anderen Weg: Für jeden ins Blickfeld zu rückenden Gegenstand wird die Funktion AddToScope(Gegenstand) einmal aufgerufen.
Mit der oben verwendeten while-Schleife hätten wir hier kein Glück: Ihre Funktionsweise beruht darauf, dass sie die Child-Objekte nacheinander entfernt und von selbst aufhört, wenn keines mehr da ist. Macht nichts - objectloop ist ohnehin eleganter, um eine Schleife über alle Objekte mit einer bestimten Eigenschaft laufen zu lassen. Zur Syntax bitte nachschlagen: 3.1.3. Dort steht auch, warum wir nicht gleich objectloop für alle Schleifen verwendet haben.
Eine Klasse ist für den Spieler noch nicht sichtbar, wir brauchen ein von ihr abgeleitetes Objekt. Eine Quelle ist schnell herbeigezaubert:
Dort, wo ein Bach fließt, sieht der Garten anders aus. Wir definieren eine Klasse GartenW, die auf der oben schon eingeführten Klasse Garten aufbaut:
with richtung "[Fehler: Klasse GartenW.richtung geerbt, aber nicht
definiert]",
description [;
print_ret "Du bist im Garten Eden. Ringsum sind Beete, Obstbäume,
Gebüsche; alles ist gepflegt und feierlich. Ein klarer
Bach fließt durch diesen Teil des Gartens in ",
(string) self.richtung,
" Richtung.";
];
class GartenW
with richtung "nordwestliche",
se_to Mitte,
e_to EdenN,
s_to EdenW;