________________________________________________________________________
| ||
9. Räume
| ||
9.1. Wann werden Wege benutzt?Wozu genau ist die Weg-Definition gut? Das ist eine gute Frage. Das Konzept der Wege kommt aus den Anfangstagen von TAG. Es soll Situationen abfangen, in denen es eine besondere Regel für die Fortbewegung gibt. Die gewöhnliche Definition der Landkarte, bei der nur Räume und Antworten benutzt werden, deckt die meisten Situationen ab, selbst wenn Türen Räume voneinander trennen (s. Kap. 10.2). Manchmal gibt es aber besondere Regeln, wenn zum Beispiel ein Tunnel in zwei verschiedene Räume führen kann, jeweils mit einer Wahrscheinlichkeit von 50%:
Weg Zufallsweg
Ausf
Wenn (Proz 50) dann
GeheZu Schweizer_Käse_Raum
sonst
GeheZu Orientalischer_Raum
Ende
EndeAusf
Und das sieht doch übersichtlicher aus als dies hier:
Raum Dreckiger_Raum
[...]
VorAusf
(gehen) Wenn (aRitg = W) dann
Wenn (Proz 50) dann
GeheZu Schweizer_Käse_Raum
sonst
GeheZu Orientalischer_Raum
Ende
Stop
Ende
EndeAusf
Prinzipiell sind aber beide Methoden gleich. | ||
9.2. Die RaumbeschreibungRaumbeschreibungen sind ein wichtiger Bestandteil von Adventures. Sie tauchen häufig auf und geben dem Spieler einen ersten Eindruck von einem Ort. Deshalb hier eine Aufzählung dessen, was der Befehl Lage macht:
Eine übertriebene Raumbeschreibung, die alle Punkte oben benutzt, wäre:
Labor (auf dem Seziertisch)
Dies hier ist offensichtlich das geheime Labor des Doktor
Wassilij Saratow. Elektrische Apparate, deren Funktion du nicht
annähernd erraten kannst, Chemikalien in allen Farben und mit
absolut unverständlichen Formeln vollgekritzelte Zettel bilden
ein malerisches, wenn auch etwas beunruhigendes Chaos.
Der einzige Ausgang ist eine graue Stahltür im Norden, die
momentan geschlossen ist.
Du befindest dich in einem Metallkäfig mit sehr stabilen
Gitterstäben, der in der Mitte des Raumes steht.
Ein kleiner Labortisch mit Rollen steht hier. Auf dem
Labortisch siehst du eine Codekarte, eine Obstschale und eine
Spritze. In der Schale sind drei Apfelsinen und eine Mango.
Auf einem Tischchen in der Nähe der Tür liegt ein
Schlüsselbund.
Außerdem siehst du hier einen braunen Karton und einen
Plastikschlauch. In dem Karton sind Papierschnitzel.
In dem Käfig siehst du ein Skalpell und einen Seziertisch.
Du liegst auf dem Seziertisch.
Ein Gorilla turnt im Labor herum. Er jongliert mit einer Banane
und einem Tennisball.
Tatjana Perpetrowa, Dr. Saratows Assistentin, ist hier und
notiert ab und zu Werte, die sie von den verschiedenen
Apparaturen abliest, in ein Schulheft.
Dies ist eine Raumbeschreibung, wie man sie ohne große Probleme mit den einfachen TAG-definitionen erhalten kann, ohne Ausführungsblöcke definieren zu müssen. Manchmal ändern sich aber Räume auch. Dann sollte man diese Änderungen in der Raumbeschreibung mitteilen. Dies geht entweder mit einer Aktion, die in Besch aufgerufen wird, oder eleganter mit einer NachAusf des Lage-Befehls:
Raum Korridor
Name 'Felskorridor'
[...]
Besch 'Du befindest dich hier in einem Felskorridor, der von
Südosten nach Norden läuft.'
NachAusf
(Lage) Wenn (Fels_gesprengt) dann
Absatz
Text 'Ein kleiner Kriechgang führt über
loses Geröll hoch nach Westen. Blasses
Tageslicht kommt aus dieser Richtung.'
Ende
EndeAusf
Diese Erweiterung steht natürlich nach der Liste der Objekte im Raum, was eventuell unschön ist. Mit einer Aktion, die aus dem Besch-Text des Raums heraus aufgerufen wird, kann man das vermeiden. | ||
9.3. Tag und NachtNehmen wir einmal an, ein Spiel geht über einen Tag oder länger. Dann sollen sich Tag und Nacht abwechseln. Natürlich wirkt sich das auf die Lichtverhält- nisse aus. (Vielleicht bleibt auch der ein oder andere Troll oder Vampir auf der Strecke.) Dazu definiert man ein Raumattribut, das alle Räume besitzen, die durch Tageslicht erhellt werden. Wenn es dämmert, werden alle Räume, die außen sind mit Licht versehen, das am Abend wieder weggenommen wird.
RaumAttr Tageslicht
RaumVar xRaum
Aktion Tag_und_Nacht *
Ausf
| Morgengrauen
Wenn (Stunden = 5) und (Minuten = 30) dann
Schleife xRaum
Wenn (xRaum Tageslicht) dann
AttrWeg xRaum dunkel
Ende
Ende
Wenn (aRaum Tageslicht) dann
Text '[#]Die ersten Strahlen der Morgensonne erhellen das
Land.'
Ende
Ende
| Morgen
Wenn (Stunden = 5) und (Minuten = 45) und
(aRaum Tageslicht) dann
Text '[#]Die Sonne ist jetzt vollständig aufgegangen und
taucht das Land in ein warmes goldenes Licht.'
Ende
| Abend
Wenn (Stunden = 7) und (Minuten = 45) und
(aRaum Tageslicht) dann
Text '[#]Die Sonne beginnt, langsam hinter dem Horizont zu
verschwinden'
Ende
| Abenddämmerung
Wenn (Stunden = 8) und (Minuten = 00) dann
Schleife xRaum
Wenn (xRaum Tageslicht) dann
AttrHin xRaum dunkel
Ende
Ende
Wenn (aRaum Tageslicht) dann
Text '[#]Die letzten Strahlen der Sonne verschwinden und
das Land versinkt im Dunkel.'
Ende
Ende
EndeAusf
Die Texte um 5:45 Uhr und 8:45 Uhr sind natürlich nur schmückendes Beiwerk. Die Lichtverteilung in allen Räumen, die nicht vom Tageslicht erhellt werden, wird wie gehabt geregelt: Dunkle Räume sind immer dunkel, wie z.B. eine Höhle, und alle anderen sind immer hell, etwa ein unterirdisches Labor, das mit Neonröhren beleuchtet wird. | ||
9.4. Eine Menge von Räumen als ein RaumMan kann eine Menge von Räumen als einen Raum in TAG programmieren. So könnte man ein riesiges Schachbrett programmieren, so daß der Spieler immer genau in einem Feld ist:
Flagge Pos_X 1
Flagge Pos_Y 1
Flagge Pos_XX 1
Flagge Pos_YY 1
Flagge Aux
Raum Schachbrett
Name 'Riesen-Schachbrett ([Buchst Pos_X][Pos_Y])'
Std Schachzug
Attr Laby
Besch 'Du stehst auf einem riesigen Schachbrett. Im Moment
befindest du dich auf dem [Feld_Farbe]en Feld
[Buchst Pos_X][Pos_Y].[Schach_Ausgang]'
Aktion Feld_Farbe
Ausf
Sei Aux Pos_X
Inkr Aux Pos_Y
Mod Aux 2
Wenn (Aux) dann
Text 'schwarz/'
sonst
Text 'weiß/'
Ende
EndeAusf
Aktion Schach_Ausgang
Ausf
Wenn (Pos_X = 1) und (Pos_Y = 1) dann
Text ' Im Südwesten kannst du das große Schachbrett
verlassen.'
Ende
Wenn (Pos_X = 8) und (Pos_Y = 8) dann
Text ' Im Nordosten führt ein schmaler Pfad vom
Schachbrett.'
Ende
EndeAusf
Weg Schachzug
Ausf
Sei Aux 0
Schleife iObj
Wenn (iObj in Schachbrett) und /(iObj Figur) dann
Inkr Aux
Ende
Ende
Bed /(Aux)
'Du solltest keine Sachen auf dem Schachbrett
liegenlassen. Nimm bitte alles mit, bevor du
weitergehst.'
Sei Pos_XX Pos_X
Sei Pos_YY Pos_Y
Jenach aRitg
(N) Inkr Pos_YY
(NO) Inkr Pos_YY
Inkr Pos_XX
(O) Inkr Pos_XX
(NO) Dekr Pos_YY
Inkr Pos_XX
(S) Dekr Pos_YY
(SW) Dekr Pos_YY
Dekr Pos_XX
(W) Dekr Pos_XX
(NW) Inkr Pos_YY
Dekr Pos_XX
Ende
Wenn (Pos_XX = 0) und (Pos_YY = 0) dann
Text 'Du verläßt das Schachbrett nach Südwesten.[#]'
GeheZu SW_Eingang
Stop
Ende
Wenn (Pos_XX = 9) und (Pos_YY = 9) dann
Text 'Du verläßt das Schachbrett nach Nordosten.[#]'
GeheZu NO_Eingang
Stop
Ende
Bed /(Pos_YY = 0 9) und /(Pos_XX = 0 9)
'In diese Richtung kannst du das riesige Schachbrett
nicht verlassen. Es hat nur Ausgänge im südwestlichen
und im nordöstlichen Ende.'
Sei Pos_X Pos_XX
Sei Pos_Y Pos_YY
Ausf Figuren_setzen
Ausf Lage
EndeAusf
ObjKlasse Figur
Adj 'gross' 'riesig'
Vor 'schach'
Subst 'figur' f
Subst 'figur' f
Besch 'Es ist [ein selbst], mehr als vier Meter hoch.'
Var X
Var Y
Aktion Figuren_setzen
Ausf
Schleife iObj
Wenn (iObj Figur) dann
Wenn (iObj.x = Pos_X) und (iObj.y = Pos_Y) dann
ObjNach iObj Schachbrett
sonst
ObjNach iObj nirgendwo
Ende
Ende
Ende
EndeAusf
Obj weisser_Läufer (Figur)
Name 'riesig^ weiß^ Läufer' m
Adj 'weiss'
Subst 'läufer' m
Var X 5
Var Y 4
Obj schwarze_Dame (Figur)
Name 'riesig^ schwarz^ Dame' f
Adj 'schwarz'
Subst 'dame' f
Var X 7
Var Y 1
Auf diese Weise kann der Spieler auf den einzelnen Feldern hin- und hergehen. Die einzige Einschränkung ist, daß man keine Gegenstände liegenlassen kann, da diese auf jedem Feld zu sehen wären. Dazu gibt es die Abfrage beim Gehen, die schaut, ob sich irgendwelche Gegenstände auf dem Brett befinden. Die Ausnahme sind hier die riesigen Figuren, die jedesmal beim Betreten eines neuen Feldes berücksichtigt werden. (Man könnte dies auch auf alle Gegenstände ausweiten, indem man jedem Objekt die Positionsvariablen Pos_X und Pos_Y gäbe. Aber das wäre doch wohl ein wenig zuviel des Guten.) | ||
9.5. Ein LabyrinthSo könnte man z.B. auch ein großes Labyrinth mit bis zu 256 Räumen als einen einzigen Raum definieren. Das Labyrinth soll, sagen wir mal, 6x6 Felder besitzen. Auf einem Feld wird dann die Information, ob man von einem Feld aus in eine bestimme Richtung gehen kann, gespeichert. Dazu eignet sich das Bit-Format. Von jedem Fald des Labyrinths aus kann es Gänge in jede der vier Hauptrichtungen geben. Dabei werden die Richtungen Norden, Osten, Süden und Westen durch die Bits 0, 1, 2 und 3 bzw. den Zahlen 1, 2, 4 und 8 repräsentiert. Sind diese Bits gesetzt, so kann man in die entsprechende Richtung gehen. Das Labyrinth soll folgendermaßen aussehen:
+---+---+---+---+---+---+
| | |
+---+ + +---+---+ +
| | | |
+ + + +---+ + +
| | | | |
+---+---+---+ +---+ +
| |
+ +---+ + +---+ +
| | | | |
+ + +---+---+ + +
| | | | |
+---+---+---+---+ +---+
Um die Gänge im Labyrinth zu beschreiben, definiert man nun ein Feld und eine Aktion zum Belegen des Feldes, die am besten aus der Aktion Anfang heraus aufgerufen wird:
Feld LabyFeld (6 6)
Aktion LabyInit
Ausf
Daten LabyFeld 0 (2 12 6 10 10 12)
Daten LabyFeld 6 (12 5 5 2 14 13)
Daten LabyFeld 12 (3 11 13 4 2 5)
Daten LabyFeld 18 (6 10 15 15 10 13)
Daten LabyFeld 24 (5 6 9 3 12 5)
Daten LabyFeld 30 (1 3 10 8 5 1)
EndeAusf
Vom oberen linken Fald aus kann man nur nach Osten = 2 gehen. Vom Feld rechts daneben kann man nach Westen und Süden = 8 + 4 gehen. Von den beiden 15er Feldern in der Mitte aus führen Gänge in alle vier Richtungen. Bei der Definition sollte man darauf achten, daß die Gänge auch wieder zurückführen. Außerdem sollten die Felder am Rand keine Bewegungsmöglichkeit aus dem 6x6-Feld heraus bieten. So spart man sich eine lästige Abfrage später. Die beiden Öffnungen nach außen oben links und unten rechts sind die Ein- bzw. Ausgänge des Labyrinths. Die Definition des Raums sieht dann so aus:
Raum Labyrinth
Name 'Im Labyrinth'
Std Nur_diagonal
N im_Labyrinth
O im_Labyrinth
S im_Labyrinth
W im_Labyrinth
Besch 'Du bist in einem Labyrinth. [LabyrinthBesch].'
Attr Laby
Antwort Nur_diagonal
Besch 'Hier führt kein Gang nach [ARitg].'
Um den Spieler innerhalb des Raums zu bewegen definieren wir die Variablen X und Y, um seine Position zu bestimmen und den Weg Im_Labyrinth, um diese Position zu verändern.
Flagge X 4
Flagge Y 5
Flagge FeldXY
Flagge BitRitg
Weg im_Labyrinth
Ausf
| Ausgänge abfangen
Wenn (X = 4) und (Y = 5) und (aRitg = S) dann
GeheZu Eingang
Stop
Ende
Wenn (X = 0) und (Y = 1) und (aRitg = W) dann
GeheZu Versteck
Stop
Ende
| Bit-Äquivalent der Richtung definieren
Jenach aRitg
(N) Sei BitRitg 1
(O) Sei BitRitg 2
(S) Sei BitRitg 4
(W) Sei BitRitg 8
Ende
| Weg in diese Richtung?
Lese FeldXY LabyFeld (X Y)
BitUnd FeldXY BitRitg
Bed (FeldXY)
'Hier führt kein Gang nach [ARitg].'
| Spieler im Labyrinth bewegen
Jenach aRitg
(N) Dekr Y
(O) Inkr X
(S) Inkr Y
(W) Dekr X
Ende
Ausf Lage
EndeAusf
Obwohl diese Weg-Definition relativ lang ist, ist sie doch recht einfach: Zu- nächst werden die beiden Ausgänge abgefangen, da sie nicht mit dem Binär- Schema funktionieren. Dann wird geprüft, ob in die Richtung ein Gang führt. Wenn ja, so werden die Positionen X und Y verändert, aRaum bleibt Labyrinth. Es fehlt nur noch eine Routine, um die möglichen Gänge aufzulisten:
Flagge AnzGänge
Aktion LabyrinthBesch
Ausf
Lösche AnzGänge
Sei BitRitg 1
| Anzahl der Gänge bestimmen
Wiederhole
Lese FeldXY LabyFeld (X Y)
BitUnd FeldXY BitRitg
Wenn (FeldXY) dann
Inkr AnzGänge
Ende
Mult BitRitg 2
bis (BitRitg = 16)
Wenn (AnzGänge = 1) dann
Text 'Der einzige Gang führt'
sonst
Text 'Gänge führen'
Ende
Lösche Aux
Sei BitRitg 1
| Richtungen auflisten
Wiederhole
Lese FeldXY LabyFeld (X Y)
BitUnd FeldXY BitRitg
Wenn (FeldXY) dann
Inkr Aux
Jenach BitRitg
(1) Sei xRitg N
(2) Sei xRitg O
(4) Sei xRitg S
(8) Sei xRitg W
Ende
Wenn (Aux = 1) dann
Text 'nach [XRitg]/'
sonst
Wenn (Aux = AnzGänge) dann
Text ' und nach [XRitg]/'
sonst
Text ', nach [XRitg]/'
Ende
Ende
Ende
Mult BitRitg 2
bis (BitRitg = 16)
EndeAusf
Auch diese Routine ist wieder lang, aber nicht kompliziert. In einer ersten Schleife wird die Anzahl der möglichen Ausgänge bestimmt. Dies dient nur dazu, um die Liste im richtigen Format auszugeben. In einer zweiten Schleife wird dann die Liste geschrieben. Eine Sache, die noch abgefangen werden muß, ist das Ablegen von Gegenständen. Im Labyrinth dürfen keine Objekte liegen, da sie in allen Feldern gleichzeitig sein würden. Das macht man an besten mit einer VorAusf des Raums:
VorAusf
(hinlegen) Stop 'Du behältst [den aObj] besser bei dir,
in diesen verwinkelten Gängen würdest
du ihn nie wiederfinden und zum
Wegwerfen [ist] [er] zu schade.'
EndeAusf
(Das ist zwar eine blöde Antwort, aber beser, als in jedem Feld auf dasselbe Objekt zu stoßen. Außerdem wird so die Möglichkeit, sich im Labyrinth mit abgelegten Gegenständen zu orientieren, unterbunden.) | ||
9.6. Verschiedene Antworten als eineWenn die Anzahl der Räume, Raumklassen, Wege und Antworten sich der maximalen Anzahl von 255 nähert, kann es hilfreich sein, mehrere Antworten zu einer zusammenzufassen, um weitere Räume einfügen zu können:
Antwort geht_nicht
Besch '[allg_Antw]'
Aktion allg_Antw
Ausf
Jenach (aRaum)
(Klippe) Text 'Dort geht es hundert Meter tief
hinunter - das würde dir bestimmt nicht
guttun.'
(Ufer) Text 'In dieser Richtung ist zuviel Wasser.'
(Garten) Text 'Du solltest lieber nicht durch die
Beete trampeln.'
[...]
Ende
EndeAusf
Hier wird der auszugebende Text einfach über eine Aktion gesteuert, die passend zum Raum eine Antwort gibt. | ||
9.7. Spiegelung der LandkarteEin kleiner Trick: Der Spieler schnippt mit den Fingern und plötzlich ist die Landschaft ost-west-verkehrt gespiegelt. Das Beispiel ist zugegebenermaßen etwas akademisch, aber es funktioniert:
Flagge gespiegelt
String west 'west'
String ost 'ost'
Bef schnippen
Name 'schnippen'
Verb 'schnippe'
Ausf
Wenn (gespiegelt) dann
Lösche gespiegelt
Sei west 'west'
Sei ost 'ost'
sonst
Setze gespiegelt
Sei west 'ost'
Sei ost 'west'
Ende
Text 'Schnipp! Es scheint sich etwas verändert zu haben...'
EndeAusf
Aktion NachParser
Ausf
Wenn (gespiegelt) dann
Jenach aRitg
(NO) Sei aRitg NW
(O) Sei aRitg W
(SO) Sei aRitg SW
(NW) Sei aRitg NO
(W) Sei aRitg O
(SW) Sei aRitg SO
Ende
Ende
EndeAusf
Raum Kreuzung
Name 'Kreuzung mehrerer Wege'
O Straße_Ost
W Straße_West
N Straße_Nord
S Straße_Süd
Besch 'Hier kreuzen sich mehrere Wege: Im Norden geht es zur
wunderschönen Stadt Alamant, im Süden in die dunklen
Regionen des Königreichs. Im [West]en sehe ich ein
weites Feld voller Sonnenblumen und im [Ost]en erhebt
sich das Schattengebirge.'
[...]
Das ist zumindest das Prinzip: Die Strings werden in die Raumbeschreibungen eingesetzt, damit diese immer angepaßt werden. Die Umwandlung eines 'W' in ein 'O' erfolgt in der Routine Postparser, die nach dem abgeschlossenen Parsen des Satzes aufgerufen wird. (Die Spiegelung könnte auch in Vorher erfolgen.) Die Strings sollten nur Kleinbuchstaben besitzen, damit Sie auch in Kombinationen wie Süd[osten] verwendet werden können. Außerden sollte man noch zwei zusätzliche Strings für 'westlich' und 'östlich' einführen. | ||
|