________________________________________________________________________
| ||
6. Die verschiedenen Aktionen im Spiel | ||
6.1. Die Aktion AnfangIn der Aktion Anfang muß alles programmiert werden, was zu Anfang des Spiels passieren soll. Es soll wahrscheinlich ein Text erscheinen und einige all- gemeine Variablen gesetzt werden: Aktion Anfang Ausf Text 'Mann, da bin ich vielleicht in eine wirre Geschichte verwickelt worden... (Hier unglaubliche Story einfügen.) So war das, und jetzt stehe ich hier mutterseelenallein abends um halb eins auf der Autobahnrastätte Aggertal. [f]T R A M P E R[n] [x]Eine interaktive Reise per Daumen, (C) 1988 Hieronymus Karpinsky ENDE eingeben, um aufzuhören, HILFE für ein paar Tips.' Sei MaxInv 6 Sei MaxGew 80 GeheZu Raststätte EndeAusf Hier wird also zunächst ein Anfangstext angegeben, um dem Spieler das Wozu und Warum des Spiels zu erläutern. Die Systemflaggen MaxInv und MaxGew werden gesetzt, um nicht die Defaultwerte zu benutzen. Dann wird der Spieler zu seiner Ausgangsposition befördert. Enthält Anfang keine GeheZu-Anweisung, so beginnt das Spiel im zuerst im Datensatz definierten Raum und es wird eine Raumbeschreibung ausgegeben. | ||
6.2. Ablauf eines ZugesDie Aktionen Vorher und Nachher werden in jedem Spielzug abgefragt. (Ein Spielzug ist hierbei alles, was zwischen zwei eingegebenen Befehlen geschieht, wenn der erste Befehl kein Steuerbefehl ist.) Die Vorgehensweise ist dabei wie folgt:
Wenn der eingegebene Befehl ein Steuerbefehl ist, werden nur die Punkte 1. und 3.e. bis 5.a. abgearbeitet. Wird der eingegebene Befehl nicht erkannt, so ist nach Punkt 1. Schluß und der nächste Zug beginnt. (Das heißt, eigentlich wird der Zug wiederholt, da nichts im Spiel passiert ist.) | ||
6.3. Zeitabhängige EreignsseViele Ereignisse im Spiel sind zeitabhängig: Die Batterien der Taschenlampe werden schwächer, die Zündschnur einer Dynamitstange brennt herunter, eine Person wartet nur eine bestimmte Zeit lang an einem Ort, der Spieler wird müde, hungrig oder erholt sich von Verwundungen - all das sind typische Dinge, die in einem Adventure passieren. In TAG werden solche Ereignisse mit Aktionen gesteuert, die am Ende jeden Zugs ausgeführt werden. (Sie werden mit einem Stern versehen, wir erinnern uns.) Bleiben wir einmal bei dem Beispiel mit dem Dynamit. Es soll 3 Züge lang brennen, bevor es explodiert. Wenn es angezündet wird, wird die Flagge Brennzeit auf 3 gesetzt. In einer Aktion, die in jedem Zug aufgerufen wird, wären dann die Anweisungen: Flagge Brennzeit 0 [...] Aktion * Ausf Wenn (Brennzeit > 0) dann Dekr Brennzeit 1 Wenn (Dynamit hier) und (Brennzeit = 2) dann Text 'Die Zündschnur des Dynamits brennt munter herunter.' Ende Wenn (Dynamit hier) und (Brennzeit = 1) dann Text 'Die Zündschnur ist beinahe abgebrannt.' Ende Wenn (Brennzeit = 0) dann Wenn (Dynamit hier) dann Text 'Die Flamme an der Zündschnur erreicht das Dynamit, welches spontan mit einem lauten Knall explodiert. Der Preis dafür, daß ich dieses Schauspiel mit ansehen durfte, ist, daß ich mit aller Wucht gegen eine Wand geschleudert werde.' Gestorben sonst Text 'In der Ferne höre ich eine Explosion.' | Was passiert, wenn gesprengt wird, hier einfügen Ende Ende Ende AusfEnde Der Zeitzünder wird also stetig heruntergezählt, bei Null wird dann die Aktion eingeleitet. Zwischendurch werden Warnsätze über die abbrennende Zündschnur losgelassen. Es gibt aber auch Variablen, die hoch- und nicht runterzählen. Z.B. ein Teekessel, der auf den Herd gestellt wird. Nach fünf Zügen soll das Wasser kochen. Voraussetzung ist, daß der Herd an ist und der Kessel mit Wasser gefüllt ist: Flagge Temperatur 0 Zust voll 'mit Wasser gefüllt' Aktion Teekessel * Ausf Wenn (Kessel auf Herd) und (Herd an) und (Kessel voll) dann Inkr Temperatur 1 Wenn (Temperatur = 5) dann Wenn (Kessel hier) dann Text 'Das Wasser kocht und der Kessel pfeift.' sonst Text 'In der Ferne höre ich ein Pfeifen.' Ende Sei Temperatur 0 ObjZust Kessel normal Ende sonst Wenn (Temperatur > 0) dann Dekr Temperatur 1 Ende Ende EndeAusf Immer, wenn der Topf auf dem Herd steht, der Herd an und der Kessel voll Wasser ist, wird die Temperatur hochgezählt. Wenn fünf Züge vergangen sind, pfeift der Kessel, und das Wasser verdampft. (Wahrscheinlich passiert noch mehr, aber es ist hier nicht berücksichtigt.) Immer wenn die Bedingung nicht erfüllt ist, etwa weil jemand den Kessel vom Herd nimmt oder den Herd abschaltet, wird die Temperatur langsam wieder auf Null zurückgezählt. Die Variable ist also hier ein Maß für die Kesseltemperatur. | ||
6.4. Wiederkehrende VerhaltensmusterManche Objekte im Spiel - meistens sind es Personen - folgen immer einem bestimmten Verhaltensschema, das meistens immer wiederkehrt. Um dieses Schema zu beschreiben, bieten sich wieder die Sternchen-Aktionen, die in jedem Zug ausgeführt werden, an. Nehmen wir einmal an, in der Altstadt patroulliert der etwas blöde Nachtwächter immer auf derselben Route: Vom Marktplatz zum Schuldturm, von dort zur Fleischergasse und weiter zum "Goldenen Becher", dem billigsten (und einzigen) Gasthaus in der Stadt. Dort beginnt seine Tour von vorne. An jedem Ort bleibt er drei bis sieben Züge, je nachdem. Dies wird in der Flagge Verweilen festgelegt: Aktion Nachtwache * Ausf Wenn (Verweildauer = 0) dann Wenn (Wächter hier) dann Text 'Der Wächter schlurft weiter seines Wegs.' Ende Stammraum nRaum Wächter Jenach nRaum (Goldener_B) ObjNach Wächter Marktplatz (Fleischerg) ObjNach Wächter Goldener_B (Schuldturm) ObjNach Wächter Fleischerg (sonst) ObjNach Wächter Schuldturm Ende Zufall Verweildauer 3 7 Wenn (Wächter hier) dann Text 'Der Nachtwächter ist soeben angekommen. Er nickt dir aufmunternd zu, gähnt und lehnt sich auf seine Hellebarde.' Ende Ende Dekr Verweildauer EndeAusf Bei jedem Zug wird Verweildauer heruntergezählt. Ist sie Null, so wird der Ort des Nachtwächters gemäß seiner Route geändert und die Verweildauer mit einem Zufallsgenerator bestimmt. Verweildauer ist also die Anzahl der Züge, bis der Wächter seinen Ort wechselt. In manchen Fällen wird das schematische Verhalten einer anderen Person im Spiel auch durch eine Aktion ausgelöst, so daß in der Aktion eine Kombination aus zeit- und verhaltensgesteurtem Ablauf ist. Es können auch Ereignisse ohne Zeitzünder definiert werden. Zum Beispiel sagt der Papagei in drei von fünf Zügen einen dummen Satz. Dieser Satz wird zufällig bestimmt: Aktion * [...] Ausf Wenn (Papagei hier) und (Proz 60) dann Text 22 1 Zufallstext 22 2 4 Zufallstext 22 5 10 end; EndeAusf Block 22 1 'Der Papagei' 2 'krächzt:' 3 'kräht:' 4 'sagt:' 5 '"Beim Klabautermann!"' 6 '"Polly will einen Keks!"' 7 '"Klar zum Entern!"' 8 '"Käpt%n Flint, Sir!"' 9 '"Fünfzehn Mann auf des Totenmanns Kiste..."' 10 '"Rrrum, ich brrrauch% mehr Rrrum!"' Dies ist übrigens ein gutes Beispiel, wo die Textausgabe aus einem Textblock einfacher und klarer ist als die direkte Textangabe als String. Das Geschwätz des Papageis könnte aber genausogut in der Ausführung NachReakt des Papageis stehen, da sie nur ausgeführt wird, wenn der Papagei im selben Raum wie der Spieler ist. Dazu aber im nächsten Abschnitt mehr. | ||
6.5. Die Ausführungsblöcke der Objekte und RäumeDie Ausführungsblöcke eines Befehls beschreiben den Regelfall dessen, was ein vom Spieler eingegebener Befehl bewirkt. Zum Beispiel prüft 'nehmen', ob ein Objekt in greifbarer Nähe ist, ob es leicht genug ist und ob es sich nicht um eine Person handelt. Ist dies nicht der Fall, so wird der Befehl schon nach der Textanalyse abgebrochen. Erfüllt das Objekt diese Bedingungen, so wird im Ausführungsblock des Befehls kontrolliert, ob noch Platz beim Spieler ist und ob er das zusätzliche Gewicht noch tragen kann. Wenn ja, dann wird das Objekt vom Aufenthaltsraum in das Inventar des Spielers befördert. Das ist die Vorgehensweise, die die Regeln zum Aufheben von Gegenständen in den meisten Fällen korrekt beschreibt. Aber - wie so oft im Leben - gibt es auch Ausnahmen. Nehmen wir einmal an, es gibt irgendwo eine Eidechse. nun wird jeder, der in seiner Jugend einmal versucht hat, ein solches Tier in die Finger zu kriegen, bestätigen, daß das nicht so einfach ist. Damit dieser Sachverhalt beim Aufheben von Gegenständen nicht in der Ausführung stehen muß, gibt es die Ausführungsblöcke, die spezielle Regeln für Objekte und Räume beschreiben. So können wir für die Eidechse folgende Objektdefinition machen: Obj Eidechse Name 'Eidechse' f Adj 'klein' 'wendig' Vor 'eid' Subst 'echse' f 'reptil' n Gew 2 Besch 'Ein kleines, wendiges Tierchen.' Erst 'Auf dem warmen Steinuntergrund sonnt sich eine Eidechse, ihr Körper ist in der typischen S-Form gekrümmt.' VorAusf (nehmen) Text 'Die Eidechse huscht schnell weiter, um deinen plumpen Fingern zu entwischen. Sie findet einen neuen Sonnenplatz in einer anderen Ecke der Terrasse.' Stop EndeAusf Damit würde es unmöglich, die Eidechse aufzuheben da vor der eigentlichen Ausführung des Befehls dieser Ausführungsblock zum Greifen käme. Das Stop nach der Textausgabe bewirkt, daß der Befehl damit vorzeitig abgeschlossen ist. Würde dieses Stop fehlen, ginge der Befehl weiter wie gewohnt: Du bist hier auf einer steingefliesten Terrasse. Auf dem warmen Steinuntergrund sonnt sich eine Eidechse, ihr Körper ist in der typischen S-Form gekrümmt. > NIMM DIE EIDECHSE Die Eidechse huscht schnell weiter, um deinen plumpen Fingern zu entwischen. Sie findet einen neuen Sonnenplatz in einer anderen Ecke der Terrasse. Du hast nun die Eidechse. Das ist sicherlich widersprüchlich, deshalb sollte auf das Stop geachtet werden. Da eine Textausgabe mit anschließendem Stop in Vorausführungen sehr häufig vorkommt, kann man den Text nach dem Schlüsselwort Stop angeben. So wird es hoffentlich nicht so oft vergessen: Stop 'Die Eidechse huscht schnell weiter, um deinen plumpen Fingern zu entwischen. Sie findet einen neuen Sonnenplatz in einer anderen Ecke der Terrasse.' Die Ausführungsblöcke der Räume und Objekte haben alle ein implizites Jenach aBef vorgeschaltet, da es hier Sinn macht, die Ausführungen befehlsabhängig zu machen. Möchte man hier eine Ausführung angeben, die immer, also befehls- unabhängig, geschehen soll, so kann man als letzte Angabe (global) angeben. Dies funktioniert nur bei diesem implizieten Jenach. Dieses (global) bedeutet natürlich nichts anderes als ein Ende der Jenach-Anweisung. Es gibt verschiedene Arten dieser Sonderregeln für Räume und Objekte. In einem komplexen Spiel machen sie den größten Teil der Objektdefinition aus. Nachfolgend sollen die verschiedenen Ausführungsblöcke beschrieben werden. 6.5.1. Ausführungen von RäumenDiese Ausführungsblöcke werden durchgeführt, wenn dieser Raum der jeweilige Aufenthaltsort ist. Der Block VorAusf wird dabei vor der eigentlichen Befehlsausführung aufgeriufen. Hier können also die Standardregeln für Befehle abgefangen werden, indem andere Regeln gegeben werden und die Flagge NullAkt explizit oder durch einen Bed- oder Stop-Befehl gesetzt wird: Raum Museum [...] VorAusf (nehmen) Text 'Die Exponate hier sind zum Anschauen, nicht zum Anfassen gedacht.' Stop (legen) Text 'Nur Kulturbanausen schmeißen Gegenstände in Museen auf den Boden.' Stop (springen singen) Text 'Die anderen Besucher würden sich bedanken.' Stop EndeAusf Der Block NachAusf wird nach der eigentlichen Befehlsausführung aufgerufen. Er dient hauptsächlich dazu, um die Standardantworten zu einem Befehl nach erfolgreicher Ausführung zu ändern: Raum Moor [...] NachAusf | | Jenach aBef | (springen) Puffer Text '(Gar nicht so einfach in diesem Morast)[#]' (singen) Text 'Es schallt hohl über das Moor.' (global) Schleife xObj (xObj in daselbst) Text 'Du schaust zu, wie [der xObj] langsam im knietiefen Schlamm versink[t].[#]' ObjNach xObj Nirwana Ende EndeAusf Die Ausführungen nach (global) werden in jedem Zug, also unabhängig vom angegebenen Befehl, behandelt. Hier wird überprüft, welche Gegenstände im Moor versinken. Die Puffer-Anweisung ohne Text bedeutet, daß die Standardantwort für 'springen' erst ausgegeben wird und dann erst der angegebene Text. Würde der Befehl fehlen, So würde die Standardantwort vom nächsten Text überschrieben. 6.5.2. Ausführungen von ObjektenHäufiger benutzt man die Vor- und Nach-Ausführungen in Objektdefinitionen. Diese werden vor bzw. nach der Befehlsausführung aufgerufen, wenn das Objekt als erstes Objekt im Befehl angesprochen wurde. Mit anderen Worten: Es werden die Vor-/Nachausführungen von aObj aufgerufen. Das Beispiel oben mit der Eid- echse gehört in diese Kategorie. Hier ein anderes: Obj Seil Name 'Hanfseil' n Vor 'hanf' Subst 'seil' n 'strick' m 'tau' n Gew 2 Vol 2 Attr bindbar Besch 'Das Hanfseil macht einen recht zuverlässigen Eindruck.' Erst 'Ein Seil liegt aufgerollt zwischen den Kisten und Fässern.' VorAusf (klettern) MutterObj xObj Seil Bed (Seil an xObj) 'Du solltest das Seil irgendwo anbinden, bevor du daran kletterst. (Es sei denn, du bist Experte für den indischen Seiltrick.)' Wenn (xObj = Haken) dann Text 'Du kletterst an dem Seil in den Schacht.[#]' GeheZu Im_Schacht sonst Text 'Wagemutig kletterst du über die Schlucht. Tief unter dir rauscht das Wasser und deine Knie sind ganz schön weich, als du auf der anderen Seite ankommst.' GeheZu Andere_Seite Ende Stop (werfen) Wenn (aObj2 = Felsnase) dann Text 'Du wirfst das Seil über die Felsnase. Mit etwas Mut und Glück kannst du wahrscheinlich auf die andere Seite klettern.' ObjNach selbst an Felsnase Stop Ende EndeAusf NachAusf (nehmen) Wenn /(selbst bewegt) dann Text 'Das Seil fühlt sich klamm und plump an, als du es aufhebst.' Ende (binden) Wenn (Selbst an Haken) dann Puffer Text 'Ein Ende des Seils baumelt jetzt in den dunklen Schacht hinunter...' Ende EndeAusf Die VorAusf wird hier benutzt, um Befehle abzufangen: Man kann an dem Seil klettern und es über die Felsnase werfen, Aktionen, die im Regelfall wahr- scheinlich nur eine dumme Antwort parat haben. ("Du kannst doch nicht auf ein Seil klettern!") Die NachAusf ändert die Antworten ein wenig ab: Beim ersten Aufheben wird gesagt, daß das Seil klamm ist und beim Binden des Seils an den Haken wird der Spieler mit der Nase auf die Möglichkeit gestoßen, in den Schacht zu klettern. Es gibt eine Besonderheit bei den Objekt-Ausführungen: Die Pseudo-Befehle. Bleiben wir einmal bei dem Beispiel mit dem Werfen. OK, ein Gegenstand wird geworfen. Mit einer VorAusf kann dan das Flugverhalten (oder was auch immer) dieses Gegenstands verändert werden. Was aber ist mit dem Ziel, dem Objekt, das den Gegenstand abbekommt? Gleiches Recht für alle: Auch er sollte die Möglichkeit bekommen, vor der Befehlsausführung dazwischenzufunken. Deshalb gibt es die Möglichkeit, zu Befehlen, die zwei Objekte verlangen, einen Pseudo-Befehl zu generieren. Im Beispiel werfen z.B. Bef werfen Name 'werfen' [...] Pseudo getroffen werfen Wenn ein solcher Pseudo-Befehl zum jetzigen Befehl existiert, dann wird auch die Vor- bzw. Nach-Ausführung des zweiten Objekts, also von aObj2, aufgerufen. Um zu unterscheiden, ob es sich um aObj oder um aObj2 handelt, wird beim Aufruf der Ausführungen von aObj2 aBef vorübergehend auf den Pseudo-Befehl gesetzt. So könnte man für eine Dartscheibe definieren: Obj Dartscheibe [...] VorAusf (getroffen) Wenn /(aObj = Dart) dann '[Der aObj] prall[t] von der Dartscheibe ab, ohne irgendwelche Punkte zu erzielen.' ObjNach aObj aRaum sonst Text 'Der Dartpfeil segelt elegant auf die Scheibe:' Wenn (Proz 2) dann Sei Dart_Pkt 50 Text 'Bulls Eye!' sonst Zufall Fakt 1 3 Jenach Fakt (2) Text 'Doppelte' (3) Text 'Dreifache' Ende Zufall Dart_Pkt Text '[Zahl Dart_Pkt]!' Mult Dart_Pkt Fakt Ende ObjNach Dart auf selbst Ende EndeAusf Die Vor- und NachAusf der Objekte sind der einzige Ort, wo aBef den Wert eines Pseudobefehls haben kann. (Außer es wird extra spezifiziert. Das ist aber gefährlich, also: Finger weg!) | ||
6.6. Neue Befehle einbauenAm besten wird das Vorgehen beim Einbinden von eigenen Befehlen an einem Beispiel deutlich. Wir wollen den Befehl 'essen' einführen, so daß eßbare Objekte komplett vertilgt werden können und sie dann aus den Spiel verschwinden. Dazu führen wir zunächst ein Attribut eßbar ein, das Lebensmittel kennzeichnet. ObjAttr eßbar Dann müssen wir uns überlegen, wie die Syntax des Befehls aussieht. Es wird ein Objekt geben, das aufgegessen werden soll, mehr nicht. Dieses Objekt muß der Spieler in der Hand halten, um es zu essen. Niemand ißt einen Apfel, der noch an einem Baum hängt oder einen Schokoriegel direkt aus der Handtasche. Zusammen mit einer Liste plausibler Verben könnte der Kopf der Befehlsdefinition dann so aussehen: Bef essen Name 'essen' Verb 'iß' 'esse' 'verspeise' 'verzehre' 'iß auf' Verb 'esse auf' 'vertilge' 'friß' 'fresse' Verb 'versuche' 'probiere' 'verleibe dir ein' Syntax das Obj (BeiMir eßbar) Mit dieser Definition haben wir zum Zeitpunkt, wo die mit diesem Befehl verbundene Ausführung aufgerufen wird, ein Objekt, das der Spieler bei sich hat. Ist das angesprochene Objekt nicht beim Spieler, so wird versucht es aufzuheben, und wenn das nicht klappt, endet der Parser mit einem Fehler und die Ausführung wird nie erreicht. Im Gegensatz zu dieser Ortsangabe wird das Attribut eßbar nicht überprüft. Der Parser läßt also den Befehl 'Vorschlaghammer essen' zu. Das Attribut muß in der Ausführung überprüft werden. Die passende Ausführung könnte folgende sein: Ausf Bed (aObj eßbar) '[Der aObj] schein[t] mir nicht besonders zum Verzehr geeignet zu sein.' Puffer 'Du ißt [den aObj] ratzeputz auf.' ObjNach aObj Nirwana EndeAusf Somit haben wir eine allgemeingültige Regel für das Essen von Gegenständen geschaffen: Wenn es ein Lebensmittel ist, so iß es und laß es von der Bildfläche des Spiels verschwinden. Wenn nicht, so breche den Befehl ab. (Die Anweisung Puffer bedeutet, daß der Text erst ausgegeben wird, wenn kein anderer Text in einer der Nachausführungen ausgegeben wurde. So ist es möglich, den Standard-Text in einer NachAusf zu ändern.) Diese Regel gilt zwar für alle Lebensmittel, aber für einige sollen spezielle Regeln gelten. Diese werden dann am besten in den Objekt-Ausführungen direkt behandelt. Einige Beispiele: Obj Erdnußriegel [...] NachAusf (essen) Text '[Der aObj] gibt dir wieder Kraft.' Inkr Power 5 EndeAusf Obj Obsttörtchen [...] NachAusf (essen) Puffer Text '(Hat gut geschmeckt!)' EndeAusf Obj Giftpilz [...] VorAusf (essen) Text 'Du knabberst an dem Pilz.' Wenn (Proz 50) dann Text 'Beim Kauen denkst du an einen Rat deiner Großmutter: keine unbekannten Pilze essen! Ein sehr, sehr unruhiges Gefühl in der Magengegend gibt deiner Großmutter Sekunden später Recht.' Gestorben sonst Text 'Er hat einen eigenartigen Geschmack.' Ende Stop EndeAusf In unserem neuen Befehl passiert tatsächlich etwas, das Objekt wird verändert. Es verschwindet nämlich, wenn es eßbar ist. Sehr viele Befehle produzieren aber nur eine Antwort, ohne irgendetwas zu bewirken. Das beste Beispiel hierfür sind wohl die Befehle untersuchen und Lage. Solche Befehle sind sehr einfach zu realisieren, da alle besonderen Regeln direkt bei den Objekten oder bei den Räumen definiert werden: Bef putzen Verb 'putze' 'säubere' 'wasche' 'mache sauber' 'staube ab' Syntax dasObj Ausf Puffer 'Du hast wohl einen Putzfimmel.' EndeAusf Obj Teekessel VorAusf (putzen) Text 'Hey! Der alte Kessel war in Wirklichkeit Aladins längst vergessene Wunderlampe!' Tausche selbst Wunderlampe Stop EndeAusf Das Einfügen von eigenen Befehlen erfolgt also ganz schematisch. Der Befehl selbst ist nur eine Regel, die für möglichst viele Objekte oder Räume gilt. Sonderregelungen werden bei den Objekten getroffen. Wenn man einmal ein paar Befehle geschrieben hat oder bestehende Befehle äbgeändert hat, wird man schnell hinter das System schauen. Zu TAG gibt es den Datensatz NORMAL.ADV, der die häufigsten Befehle enthält, die nicht standardmäßig zu TAG gehören. Wer diese benutzen möchte, kann diese Datei am Anfang seines Adventures mit #DAT 'normal.adv' einbinden. Die meisten Befehle in dieser Datei sind einfache Befehle, die nur eine Antwort produzieren. Diese Datei kann natürlich nach Belieben abgeändert werden und auf das jeweilige Projekt angepaßt werden. Die Benutzung dieser Datei empfeiehlt sich besonders für Einsteiger. | ||
|