________________________________________________________________________
[<<] [Inhalt] [>>] III. Beispiele

9. Räume

9.1.   Wie werden Wege benutzt?
9.2.   Die Raumbeschreibung
9.3.   Tag und Nacht
9.4.   Eine Menge von Räumen als ein Raum
9.5.   Ein Labyrinth
9.6.   Verschiedene Antworten als eine
9.7.   Spiegelung der Landkarte

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 Raumbeschreibung

Raumbeschreibungen 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:

  1. Die eigentliche Raumbeschreibung:

    1. Die kurze Raumbeschreibung, d.h. der Name des Raums, wird ausgegeben. Das passiert immer, wenn knappe Beschreibungen aktiv sind und der Spieler den Raum bereits kennt oder wenn #Besch kleiner als vier ist. Das Format wird von #Besch bestimmt. Wenn der Spieler irgendwo sitzt, liegt oder steht, dann wird aSitz in Klammern angegeben.

    2. Bei ausführlichen Beschreibungen, wenn der Spieler einen Raum zum ersten Mal betritt oder bei einem Lage-Befehl wird die Beschreibung ausgegeben, die mit Besch zu diesem Raum definiert wurde.

    3. Wenn sich der Spieler in einem Behältnis befindet, wie z.B. einem Käfig (s. Kap. 12.0), dann wird die InBesch dieses Objekts ausgegeben.

  2. Liste der Objekte im Raum:

    1. Alle beweglichen Objekte im Raum, ausgenommen Personen, die eine Erst-Beschreibung haben und die entweder noch nicht bewegt wurden oder das Immer-Attribut besitzen, werden mit dem Erst-Text erwähnt. Bei Behältern oder Ablagen wird dirket im Anschluß der Inhalt aufgelistet. Jedes dieser Objekte bekommt einen eigenen Absatz.

    2. Alle beweglichen Objekte, die noch nicht erwähnt wurden und die sich direkt im Raum befinden, werden extra aufgezählt: "Du siehst hier (außerdem) ..."

    3. Der Inhalt aller beweglichen und unbeweglichen Objekten im Raum mit Ausnahme von Personen wird angezeigt.

  3. Angabe des Sitzes, wenn der Spieler irgendwo sitzt, steht oder liegt und wenn der Sitz nicht schon unter 1. genannt wurde.

  4. Liste der Personen im Raum: Alle Personen werden in einem eigenen Absatz erwähnt. Dabei wird "Hier ist..." oder die Erst-Beschreibung verwendet, wenn vorhanden. Direkt im Anschluß werden die Dinge, die diese Person bei sich hat, aufgezählt, wenn diese Person transparent ist.

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 Nacht

Nehmen 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 Raum

Man 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 Labyrinth

So 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 eine

Wenn 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 Landkarte

Ein 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.

Martin Oehm, 04.02.2000 Vorheriges KapitelInhaltsverzeichnisNächstes Kapitel