Chapter_5: "Walking Around In Our World" $
In unserer Welt zu gehen, bedeutet einen anderen Ort aufzusuchen. Die Funktion w_a_l_k__direction, die eine Wegrichtung als Argument annimmt, verändert dann entsprechend den Ort, an dem wir uns befinden, das heißt, die globale Variable location. Auch dies entspricht demnach nicht dem funktionalen Stil.
w_a_l_k__direction(direction):= block( [ next_: assoc_( direction,rest( assoc_(location,map), 2 ) ) ], if listp(next_) then ( location: third (next_), l_o_o_k() ) else "you cant go that way. ")$
assoc_ hilft uns hier wieder, aus dem gesamten Spielfeld die passende Wegbeschreibung herauszusuchen. Gibt es einen zu der gewählten Richtung passenden Weg, finden wir den neuen Ort als dritten Eintrag in der Liste next_, andernfalls geben wir eine entsprechende Rückmeldung aus. Das Symbol next ist in Maxima reserviert, deshalb wurde hier bei der Übersetzung in Maxima der Unterstrich angefügt. Mit next kann man beschreiben, wie eine durch for definierte Schleifenvariable verändert werden soll.
Sind wir an einem neuen Ort angekommen, sehen wir uns mit l_o_o_k() erst einmal um. Mit w_a_l_k__direction(direction) gehen wir dann weiter. Zur einfacheren Eingabe definieren wir in diesem Fall einen Präfix-Operator.
prefix("walk")$ "walk"(direction):= w_a_l_k__direction(direction)$
Wir verwenden hierbei die konkrete Wegrichtung als Argument. Das sieht dann so aus.
walk west;
==> you are in a beautiful garden. there is a well in front of you. there is a door going east from here. you see a chain on the floor. you see a frog on the floor.
Eigentlich hätten wir ja 'west verwenden müssen. Da aber dem Symbol west in unserem Spiel nichts zugewiesen wird, können wir das Hochkomma ruhig weg lassen.
Wir erzeugen nun ein Kommando, das uns erlaubt, Gegenstände vom Boden aufzuheben.
prefix("pickup")$ "pickup"(object):= if is_at( object,location,object_locations ) then ( object_locations: cons([object,'body],object_locations), sconcat("you are now carrying the ",object,".") ) else "you cannot get that. "$
Wir lernen hier eigentlich nichts Neues. Anders als bei walk haben wir hier jedoch die Funktionsdefinition gleich in die Definition des Operators gesteckt. Mit 'body wurde hier der Liste object_locations ein vierter Ort hinzugefügt.
Nehmen wir doch mal die Kette.
pickup chain;
==> you are now carrying the chain.
Damit wir uns das nicht merken müssen, benötigen wir ein Kommando, dass uns jederzeit Auskunft darüber gibt, welche Gegenstände wir mit uns herumtragen. Dazu definieren wir eine Funktion, durch die wir eine Liste dieser Gegenstände erhalten.
at_body():= sublist( objects,lambda([x],is_at(x,'body,object_locations)) )$
Das Kommando inventory; schreibt diese Liste als Text ohne Listenklammer.
nofix("inventory")$ "inventory"():= apply( sconcat, map( lambda([x],sconcat(x," ")), at_body() ))$
inventory;
==> chain
Für das nächste Kapitel stellen wir noch eine Funktion bereit, die sagt, ob wir einen bestimmten Gegenstand mit uns herumtragen. Wir verwenden hierbei die Listenfunktion member, die ermittelt, ob ein bestimmtes Objekt Element einer Liste ist.
have(object):= member( object,at_body() )$