C 64
Programmierung

Adventure-Programmiertechnik

Es ist soweit. Im nun folgenden Abschnitt erfahren Sie endlich, wie man sie programmiert: Super-Adventures, wie es sie bis jetzt noch nicht gibt. Sie erhalten alle notwendigen Grundlagen, um professionelle Adventures zu erstellen.

In meinem ersten Adventure-Kurs habe ich bereits ausführlich beschrieben, wie man eine Adventure-Idee aufgreift, diese ausarbeitet, Pläne anfertigt etc. Wir wollen uns deshalb hier gar nicht mehr erst lange mit solchen Grundlagen aufhalten, sondern gleich zur Sache kommen. Auf den nächsten Seiten programmieren wir gemeinsam die ersten Fortsetzungsszenen von Gordon Saga II. An dieser Stelle muß ich auch gleich noch einmal ein paar Worte zur Gordon Saga I verlieren. Ich möchte mich bei allen begeisterten Adventurern bedanken, die im Spiel mit mühevoller Kleinstarbeit meine Telefonnummer herausgefunden und mich dann angerufen haben. Ich erhielt zahlreiche Anrufe aus allen Teilen Deutschlands, Österreichs und der Schweiz. Bedanken möchte ich mich vor allem deshalb, weil ich bisher keinen einzigen bösen Anruf erhielt. Einige teilten mir sogar mit, daß das Spiel Fehler enthält und deshalb nicht lösbar sei. Es stimmt, es sind einige Fehler enthalten, aber ich kann versichern, daß diese Fehler in keinster Weise zur Unlösbarkeit beziehungsweise zum Absturz des Spiels führen: es sind lediglich kleine Logikfehler, wie sie bei der Programmierung eines komplexen Adventures unvermeidbar sind. An dieser Stelle sei auch die »Incredible Four« gegrüßt, die Gordon Saga I geknackt und beim Titelbild das HAPPY-SOFTWARE-Emblem durch UNHAPPY SOFTWARE ersetzt haben (PS: Wenn ich euch erwische, dreh ich euch den Hals um!). »Wo bleibt Gordon Saga, Teil II« haben mich viele gefragt. Die Programmierung von Teil II habe ich kurz vor Abschluß abgebrochen. Dies hat seinen guten Grund: Teil II ist einfach um Längen besser als Teil I in puncto Text, Grafik und Parser. Wenn jemand, der Gordon Saga I kennt, von Gordon Saga II hört, so vergleicht er unwillkürlich den zweiten mit dem ersten Teil – und dies wäre nicht gerade die beste Werbung.

Als kleinen Vorgeschmack möchte ich gemeinsam mit Ihnen nun die ersten Szenen von Gordon Saga II programmieren. Dazu ist notwendig, daß Sie wissen, wie Gordon Saga I ausgeht. Am Spielende treibt der Spieler mit einem Floß auf einem stillen unterirdischen See in einem geheimnisvollen Gebirge. Plötzlich entsteht im See ein riesiger Strudel, der den Spieler samt Floß in die Tiefe reißt – die Pforte zu einer geheimnisvollen Welt hat sich aufgetan ...

Und dies sind die ersten Szenen von Gordon Saga II: Der Spieler wacht in einer Glaskuppel am Grunde des Sees wieder auf. Von der Glaskuppel aus führt ein Tunnel in die Dunkelheit. Durch diesen Tunnel gelangt man in eine Kristallgrotte ...

Den Lageplan für diesen Teil des Spieles zeigt Bild 1.

Lageplan aus vier Räumen: 1 GLASKUPPEL, 2 TUNNEL, 3 KRISTALLGROTTE und 4 FELSPLATEAU, verbunden durch Pfeile, zwischen 3 und 4 eine gestrichelte Linie mit SCHWERT
Bild 1. Der Lageplan von Gordonsaga II (Ausschnitt)

Wir haben 4 Räume: Glaskuppel, Tunnel, Kristallgrotte und Felsplateau. Außerdem ist bei jedem Raum aufgezählt, welche Objekte sich in ihm befinden. Von Raum 3 gelangt man nicht so ohne weiteres zu Raum 4, was durch die gestrichelte Linie angedeutet ist – man braucht irgendwie das Schwert.

Wie fängt man jetzt an zu programmieren?

Nun, man muß sich erst einmal überlegen, wie man die einzelnen Programmteile – also Basic-Programm, Zeichensatzlader, Grafikbilder, relative Dateien etc. auf einer Disk unterbringt. Am besten, man entscheidet sich, eine Diskette beidseitig zu verwenden.

Auf Seite 1 bringt man das Grundprogramm, den deutschen Zeichensatz, eventuell Maschinenprogramme und Grafikbilder unter.

Das heißt, außer den Grafikbildern kommt auf Seite 1 alles, was einmal in den Rechner geladen wird und dann dort bleibt. Auf Seite 2 kommt die relative Datei, auf der alle Texte, Kommentare und Raumbeschreibungen gespeichert sind. Außerdem wird auf Seite 2 die relative Wortschatzdatei untergebracht. In der Entwicklungsphase eines Adventures eignet sich Parser 4.0 zweifellos am besten – man kann leicht neue Wörter einfügen etc. Erst ganz am Ende, wenn alle Spielszenen fertig programmiert sind – das Adventure also fertig ist -, sollte man endgültig auf Parser 5.0 umrüsten.

Nehmen Sie sich jetzt bitte eine gute Diskette her, die für beidseitiges Bespielen geeignet ist, und formatieren Sie beide Seiten. Dann nehmen Sie die Disk-Utility her und ändern die IDs der Disketten so, daß der ID der ersten Seite »1side«, der der zweiten Seite »2side« lautet. Dies ist notwendig, damit später innerhalb des Programmes festgestellt werden kann, ob die richtige Disk-Seite eingelegt ist. Jetzt brauchen wir den Relativ-Datei-Editor. Mit ihm eröffnen wir auf der 2. Diskseite eine relative Datei mit folgenden Angaben:

Satzlänge 41
Anzahl Sätze 3000
Filename »TEXTE«

Jetzt müssen Sie auf die zweite Diskseite noch die relative Wortschatzdatei überspielen. Dies geht nicht so ohne weiteres, da es nur sehr wenige Kopierprogramme gibt, die relative Files einzeln kopieren können. Sie können jedoch mit dem Editor eine neue Wortschatzdatei anlegen und dann mittels VERSETZEN-Befehl (siehe auch Anleitung zum Editor) die alte Wortschatzdatei in die neu angelegte übertragen. Eine andere Möglichkeit besteht darin, einfach die ganze Diskettenseite, auf der sich die Wortschatzdatei befindet, mit einem Diskettenkopierprogramm auf die zweite Seite unserer jetzigen Arbeitsdiskette zu kopieren und dann mittels Scratch und Validate den Rest zu löschen. Diskseite 2 muß jetzt so aussehen:

0   "gordon saga ii    "2side
492 "texte"                rel
32  "wortschatz"           rel
140 blocks free.

Jetzt können wir mit der Arbeit beginnen.

Der erste Schritt besteht darin, den Wortschatz und die Wörter zu erweitern, die für die aktuelle Spielszene, die sich in der Regel aus einigen Räumen zusammensetzt, benötigt werden. Man sollte nie zu viele Räume auf einmal behandeln.

Wortschatz erweitern

Denken Sie sich immer eine kleine Szene aus, programmieren Sie diese und arbeiten Sie erst dann weiter, wenn diese Szene einwandfrei läuft. Durch dieses Szene-für-Szene-Programmieren hält sich die Fehlersuche in engen Grenzen, und man kann sicher sein, daß das Adventure bei der Fertigstellung nur wenige Logikfehler enthält – da jede Szene für sich ausgiebig getestet wurde. Wie erweitert man den Wortschatz? Ganz einfach. Für unsere jetzige Szene müssen wir den Wortschatz um folgende Objekte ergänzen:

Glaskuppel        1
Sand              2
Tunnel            3
Kristallgrotte    4
Quader            5
Statue            6
Schwert           7
Zettel            8
Amulett           9
Grube             10
Oeffnung          11
Felsplateau       12
Kristalle         13

Der Wortschatz wird ganz einfach erweitert, indem Sie mit dem relativen Datei-Editor die neuen Wörter ans Ende des bisherigen Wortschatzes anhängen (ab Satz Nr. 198) und dann die gesamte Datei neu sortieren. Hängen Sie bitte folgende Sätze an:

198   glaskuppel      3001
199   sand            3002
200   tunnel          3003
201   kristallgrotte  3004
202   quader          3005
203   statue          3006
204   schwert         3007
205   zettel          3008
206   amulett         3009
207   grube           3010
208   oeffnung        3011
209   felsplateau     3012
210   kristalle       3013

Jetzt muß der Wortschatz neu sortiert werden. Beachten Sie bitte, daß mit der Sortierroutine des relativen Datei-Editors nur Dateien sortiert werden können, die nicht mehr als 300 Sätze haben. Übersteigt die Anzahl der Worte im Wortschatz diese Zahl, so müssen Sie zum Sortieren des Wortschatzes den Super-Sorter hernehmen, bei dem kein Limit besteht.

Nachdem der Wortschatz erweitert ist, können wir uns dem Text des Adventures zuwenden. Textadventures zeichnen sich besonders durch lange, beschreibende Texte aus. Nicht umsonst arbeiten viele Softwarehäuser bei der Erstellung ihrer Adventures mit Schriftstellern zusammen. Alleine Adventures schreiben ist langweilig. Auch sind Programmierer meistens keine guten Texter. Vielleicht tun Sie sich hier am besten mit einem Freund zusammen, der gerne schreibt. Zu zweit ein Spiel aushecken macht schließlich auch viel mehr Spaß.

Anschließend finden Sie den Text zu den ersten Szenen von Gordon Saga II. Bitte schreiben Sie ihn in die entsprechenden Sätze der Texte-Datei:

  1 Als Sie aus Ihrer Bewußlosigkeit
  2 erwachen, finden Sie sich auf einem
  3 weichen weißen Sandboden liegend
  4 wieder.
  5 Augenblicklich erinnern Sie sich an die
  6 letzten Ereignisse vor Ihrer
  7 Bewußtlosigkeit .. In Ihren Gedanken
  8 setzt sich das Abbild der riesigen
  9 Seeschlange zusammen, die Sie mit Hilfe
 10 einer goldenen Armbrust erlegt hatten.
 11 Ihre folgende Erinnerung gilt dem
 12 plötzlich aufgekommenen Strudel, durch
 13 den Ihr Floß samt Ihnen in die Tiefe
 14 gerissen worden war.
 15 Obwohl es Ihnen noch immer unbegreiflich
 16 ist, wie Sie all dies überleben konnten,
 17 machen Sie sich daran, Ihre jetzige
 18 Umgebung näher zu untersuchen .....
 19
 20 GORDON SAGA II. Die Rückkehr des Helden
 21 Ein Abenteuerspiel von Michael Nickles.
 22 Parsersystem 4.0 - Copyright 1985
 23 Auszug für Kurs im 64er-Sonderheft.     *
 24 Glaskuppel
 25 Sie befinden sich innerhalb einer
 26 Glaskuppel am Grunde eines Sees.
 27 Außerhalb der Kuppel ist das Wasser so
 28 dunkel, daß man nichts erkennen kann.
 29 Der weiße Sand am Boden strahlt ein
 30 schwaches Licht aus, das die Kuppel
 31 erhellt. Ein kleiner Tunnel führt von
 32 hier aus hinaus in die endlose
 33 Dunkelheit.                             *
 34 Tunnel
 35 Sie befinden sich in einem zwei Meter
 36 hohen und etwa drei Meter breiten
 37 Tunnel. Die Wände sind aus einem Glas
 38 angefertigt, das etwas trüber als das
 39 Glas, aus dem die Kuppel besteht, ist.
 40 Der Tunnel verläuft in nördliche
 41 Richtung. Weit entfernt in nördlicher
 42 Richtung sehen Sie ein helles Licht.    *
 43 Kristallgrotte.
 44 Dies ist eine riesige Grotte, deren Wände
 45 mit Kristallen, die in allen Farben des
 46 Lichtspektrums glitzern, besetzt sind.
 47 Der Boden besteht aus glatten, strahlend
 48 weißen Marmorplatten. Trotz zahlreicher
 49 Unebenheiten ähnelt diese Grotte dem
 50 Inneren einer Halbkugel mit einem Radius
 51 von ca. 100 Metern. Der einzige Ausgang
 52 von hier ist ein in südlicher Richtung
 53 verlaufender Tunnel.                    *
 54 Felsplateau
 55 Dieses Felsplateau außerhalb der Grotte
 56 bietet Ihnen eine fantastische Aussicht.
 57 Sie blicken über ein weites Land hinweg.
 58 das in Dunkelheit gehüllt ist. Am Himmel
 59 sehen Sie eine schwarze Scheibe, deren
 60 Ränder orangerot leuchten - es scheint,
 61 als sei die Dunkelheit durch eine
 62 andauernde Sonnenfinsternis bedingt.
 63 Etwa 300 Meter unterhalb des Plateaus
 64 befindet sich ein Wald mit einer Ihnen
 65 unbekannten Flora.
 66 All diese eindrucksvollen Anblicke
 67 verstärken in Ihnen das Gefühl, daß Sie
 68 sich in einer fremden Welt befinden.
 69 In der östlichen Gebirgswand ist ein
 70 Zugang zu einer Grotte.                 *
 71 Sie graben in dem leuchtenden Sand.     *
 72 Es ist sinnlos, noch tiefer zu graben.  *
 73 Nachdem Sie ein etwa 50 cm tiefes Loch
 74 in den Sand gegraben haben, finden Sie
 75 einen Zettel und ein Amulett.           *
 76 Im Sandboden ist eine ca. 50 cm tiefe
 77 Grube ausgehoben - es scheint so, als ob
 78 hier vor kurzem jemand gegraben hat!    *
 79 Auf dem Zettel steht etwas geschrieben! *
 80 "Supermike grüßt Captain Future,
 81 Section 8, Pink, Brutallica, Gommel,
 82 GCS (ich weiß, daß ihr genau 35 km
 83 Luftlinie von mir entfernt wohnt -
 84 Paßt bloß auf!!!), und natürlich alle
 85 Freunde, RAMBO und alle Girls, die mich
 86 besonders gut kennen!!"                 *
 87 Das Amulett ist aus massivem Gold
 88 angefertigt, mit schwarzen Edelsteinen
 89 besetzt und hängt an einer goldenen
 90 Halskette.                              *
 91 Die Grube ist völlig leer.              *
 92 Die Glaskuppel ist so groß, daß sich
 93 etwa 10 ausgewachsene Männer darin
 94 aufhalten können.                       *
 95 Der Sand ist sehr grobkörnig und
 96 leuchtet seltsamerweise.                *
 97 Die Kristalle glitzern in allen Farben
 98 des Lichtspektrums.                     *
 99 Die Kristalle sind fest in die Wände
100 eingelassen und lassen sich auch mit
101 größten Anstrengungen nicht entfernen.  *
102 Auf dem Marmorboden, exakt im Zentrum
103 des Raumes, steht ein goldener Quader,
104 von dem eine ca. 3 Meter hohe Statue
105 emporragt.                              *
106 Nur wenige Meter von der Statue entfernt
107 steckt ein goldenes Schwert zu etwa
108 einem Drittel seiner Gesamtlänge im
109 Marmorboden.                            *
110 Das Schwert ist fest im Marmorboden
111 verankert und läßt sich um keinen
112 Millimeter herausziehen.                *
113 Die Statue gibt die groben Umrisse eines
114 jungen Kriegers wieder. Er hat lange
115 Haare, ist von athletischer Körperstatur
116 und trägt eine Rüstung. Sie fühlen sich
117 von der Statue in einer seltsamen Art
118 und Weise angezogen.                    *
119 Als Sie die Statue mit Ihrer rechten
120 Hand berühren, durchfährt augenblicklich
121 eine Lähmung Ihren ganzen Körper und Sie
122 sind nicht mehr in der Lage, Ihren Arm
123 zurückzuziehen. Unmittelbar vor Ihren
124 Augen beginnt die Statue plötzlich ihr
125 Äußeres zu verändern.....
126 Die Lähmung läßt schließlich nach und
127 Sie stürzen benommen zu Boden.
128 Nachdem Sie den Schock überwunden haben,
129 stellen Sie fest, daß nicht nur die
130 Statue ihr Äußeres verändert hat -
131 während die Statue Ihre Form angenommen
132 hat, haben Sie den Körper des jungen
133 Kriegers erhalten, den die Statue noch
134 vor kurzem verkörpert hat.              *
135 Die Statue gibt jetzt die Umrisse und
136 Gesichtszüge eines Ihnen wohlvertrauten
137 Menschenkörpers wieder - ein Körper, der
138 noch vor kurzem der ihrige war!         *
139 Mit der unglaublichen Kraft, die in
140 Ihrem neuen Körper zu stecken scheint,
141 ziehen Sie das Schwert ohne jegliche
142 Anstrengung aus dem Marmorboden.
143 Kaum, daß Sie es in Ihren Händen halten,
144 beginnt der gesamte Raum um Sie herum
145 leicht zu beben und das Schwert strahlt
146 in gleißendem Licht.
147 Aus dem Nichts ertönt plötzlich eine
148 Ihnen altbekannte Stimme. "In Dir
149 erfüllt sich die alte Prophezeiung!
150 Geh, GORDON, die Macht ist mit Dir!"
151 Als die letzten Worte des Uralten
152 gerade verklingen, tut sich in der
153 westlichen Wand der Grotte eine Öffnung
154 auf und gibt den Ausgang zu einem
155 Felsplateau frei.
156 Sie stehen verwundert da und fragen sich
157 immer wieder, warum gerade Sie der
158 Auserwählte sind und zu welchem Zweck
159 der Uralte Sie in diese fremde Welt
160 geholt hat.....                         *
161 In der westlichen Wand der Grotte ist
162 eine Öffnung, die den Ausgang zu einem
163 Felsplateau ermöglicht.                 *
164 die Glaskuppel
165 der Sand
166 der Tunnel
167 die Kristallgrotte
168 der Quader
169 die Statue
170 das Schwert
171 der Zettel
172 das Amulett
173 die Grube
174 die Öffnung
175 das Felsplateau
176 die Kristalle

Sie haben sicherlich bereits bemerkt, wie Adventuretexte in einer relativen Datei untergebracht werden: Jede Raumbeschreibung oder jeder Kommentar wird mit einem Sternchen abgeschlossen. Nur die Objektnamen selbst stehen allein in einer Zeile, den Geschlechtsartikel vorangestellt.

Damit ist auch der Text für die ersten Szenen auf Disk vorhanden. Jetzt benötigen wir ein Programmiergerüst, um das herum wir unser Adventure aufbauen. Dieses Gerüst finden Sie in Listing 1.

Dieses Gerüst soll Ihnen als Grundprogramm für jedes Adventure dienen. In ihm sind nahezu alle Routinen enthalten, die für die Programmierung beziehungsweise Entwicklung eines Textadventures notwendig sind.

Dokumentation

3-4 Laden und Aktivieren des deutschen Zeichensatzes (muß sich ebenfalls auf der ersten Diskseite befinden!).
5 Floppykanal öffnen.
6 Disk Seite 2 einlegen!
15 Ab 60000 stehen alle Tabellen wie der Wortschatz-Index.
20 Anhand des Feldes WI(1)-WI(100) merkt sich das Programm, in welchem Raum der Spieler bereits war.
Genau wie bei INFOCOM erhält der Spieler von Räumen, in denen er bereits war, nur noch eine kurze Beschreibung.
30 Zähler für Punktzahl und Anzahl der Befehlseingaben werden auf Null gesetzt.
40 Der Titelvorspann des Spiels wird von der relativen Datei aufgerufen (SA ist dann meistens 1, da der Vorspann meistens beim ersten Satz der Texte-Datei beginnt).
50 Raumbeschreibung des ersten Zimmers ausgeben.
50000-52180 Hier steht Parser 4.0. Allerdings sind einige kleine Sachen hinzugefügt. Kommt im Befehlssatz das Wort »Alles« vor, so wird der Variablen SP der Wert 1 zugeordnet. Kommt »Ausser« vor, so erhält die Variable SQ den Wert 1. Dies ist nötig, damit wir auch Sätze wie zum Beispiel »NIMM ALLES AUSSER DEM SCHWERT« abhandeln können.
53000-53040 Unterprogramm zum Einblenden einer Statuszeile in der obersten Bildschirmzeile. Wie bei Infocom stehen in dieser Zeile der Name des Raumes, in dem man sich gerade befindet, sowie Punktzahl und Anzahl der Versuche. Dieses Unterprogramm wird innerhalb der erweiterten INPUT-Routine von Parser 4.0 aufgerufen (Zeile 50011).
53200-53230 Dieses Unterprogramm haben wir bereits im Kapitel Dateiverwaltung kennengelernt. Es dient dazu, festzustellen, ob die richtige Diskseite (Wert von Variable SI) eingelegt ist. Ist Disk Seite 2 eingelegt, so öffnet das Unterprogramm außerdem automatisch die relative Datei »Texte«.
Soll Disk Seite 1 eingelegt werden, so sagen Sie einfache SIDE=1:GOSUB53200. Der Rücksprung aus dem Unterprogramm erfolgt erst dann, wenn die gewünschte Seite eingelegt ist.
53400-53440 Das altbekannte Unterprogramm zum Positionieren des Zeigers auf eine relative Datei.
53500-53520 Dito, zum Einlesen eines Satzes (I$) aus einer relativen Datei.
53600-53695 Ein Text aus der relativen Texte-Datei wird eingelesen. Beginnend ab Satz SA bis zu dem nächsten Satz, der mit einem Sternchen endet. Wenn Sie also einen Text von der relativen Datei einlesen und auf dem Bildschirm ausgeben wollen, so ist ein
SA = (1. Satz des Textes): GOSUB 53600 notwendig.
53700-53710 Auf dem Bildschirm erscheint das Wort WEITER. Bei Tastendruck verschwindet es wieder, und das Unterprogramm wird mittels RETURN beendet. Dieses Unterprogramm wird zum Beispiel dann verwendet, wenn ein Text am Stück auf dem Bildschirm ausgegeben wird, der mehr als 25 Sätze enthält. Nach dem 24. Satz erscheint WEITER, damit dem Spieler genug Zeit zum Lesen bleibt und der Text nicht wegscrollt.
53800-53810 Dasselbe wie 53600-53695 nur, daß von der eigentlichen Textausgabe diesmal eine Leerzeile eingefügt wird.
53900-53945 Der altbekannte Textformer, der den String X$ per word-wrapping auf dem Bildschirm ausgibt.
53950-53970 Die Gegenstände beziehungsweise transportablen Objekte sind in der Texte-Datei mit voranstehendem Geschlechtsartikel – der, die oder das – gekennzeichnet. Am Ende der Raumbeschreibungen soll jedoch für zum Beispiel Schwert der Kommentar »Hier liegt ein Schwert« kommen. (Natürlich wieder analog zu Infocoms THERE IS A SWORD LYING HERE.)
Die Artikelwandlung ist ganz einfach:
Aus der beziehungsweise das wird EIN: Aus die wird EINE.
54000-54095 Unterprogramm zum Einlesen eines Raumtextes. Das Einlesen eines Raumtextes ist nicht ganz so einfach wie das Einlesen eines gewöhnlichen Textes, da sich ein Raumtext aus mehreren Einzelteilen zusammensetzt:

— Zuerst wird der Haupt-Raumtext ausgegeben. Das ist der Text, der sich nie ändert.
— Dann werden Textteile ausgegeben, die sich ändern können. Ein Beispiel: Eine Tür, die bei der Beschreibung sowohl als offen als auch als geschlossen beschrieben werden kann.
— Im Raum befindliche Gegenstände. Dies sind in der Regel Objekte, die transportiert werden können. In der Raumbeschreibung erscheinen diese Objekte dann als »Hier liegt ein...« etc.
63000-63440 Hier steht eine Mini-Version des Relativen-Dateien-Editors. Er wird mittels GOSUB 63000 gestartet. Beim Schreiben eines Textadventures fallen einem stets neue Kommentare ein, die man der Texte-Datei zufügen muß. Es wäre viel zu umständlich, wegen jedem neuen Kommentar die aktuelle Arbeit zu speichern, dann den Relative-Datei-Editor laden etc. Daher steht am Ende des Gerüstes eine Mini-Version, mit der nur gelesen und geschrieben werden kann. Am Ende der Programmierung kann dieser Editor entfernt werden.

Die Dokumentation ist an dieser Stelle noch nicht komplett. Sie müssen erst noch einige andere Dinge wissen.

Spielablauf der ersten Szene

So läuft die erste Spielszene ab: Der Spieler erwacht in der Glaskuppel. Er muß jetzt im Sand graben, um einen Zettel und ein Amulett zu finden. Anschließend gelangt er durch den Tunnel in eine Kristallgrotte, in der eine Statue steht. Im Marmorboden steckt ein Schwert, das sich nicht herausziehen läßt. Der Spieler muß jetzt die Statue berühren, um sich in die Figur zu verwandeln, die die Statue darstellt. Er nimmt so den Körper eines jungen Kriegers an. Jetzt kann er mühelos das Schwert aus dem Boden ziehen. Dieses Herausziehen des Schwertes wirkt gleichzeitig wie ein Schlüssel: In der westlichen Wand tut sich eine Öffnung auf, die zu einem Felsplateau hinausführt. Dort beginnt die nächste Szene.

Wir wollen jetzt gemeinsam das Gerüst um diese Szene ergänzen. Sie erfahren dabei gleichzeitig die Dokumentation zu den übrigen Gerüstteilen. Zunächst müssen ab Zeile 60000 die Tabellen fertiggestellt werden, die im Rahmen von Gordon Saga II benötigt werden: die Wortschatz-Index-Tabelle, die Landkarte und die Objekt-Logik-Tabelle. Bitte ergänzen Sie das bisherige Gerüst-Programm um die Zeilen aus Listing 2.

Anlegen der Tabellen

Auf den Wortschatz-Index brauche ich nicht lange einzugehen. Es ist der Index des modifizierten Wortschatzes – erstellt mit dem Index-Maker-Programm und anschließend in Data-Zeilen abgelegt. Anders bei der Objekttabelle. Die Objekttabelle ist das wichtigste am ganzen Programm. Zu jedem der Objekte sind mehrere Daten gespeichert. Diese Daten sind in den Feldern OB(), OX(), OA(), OU() und OS() untergebracht. Was geben diese einzelnen Felder an? Betrachten wir sie am besten einmal im einzelnen:

In der Variablen OZ ist die Anzahl der Objekte gespeichert.

OB(1)-OB(Z): OB(X) gibt an, in welchem Raum sich Objekt X befindet. Der Wert OB(X) ist immer dann größer Null, wenn sich das Objekt X in einem Raum befindet.
Ist OB(X) = 0, so heißt dies, daß das Objekt X nicht bzw. nicht mehr vorhanden ist.
Ist OB(X) kleiner als Null, so befindet sich das Objekt irgendwo anders als in einem Zimmer. Zum Beispiel im Besitz des Spielers -OB(X)=-1. Soll das Objekt in einem Schrank liegen, so kann man ihm eine für den Schrank spezifische negative Zahl zuordnen und so weiter.
OX(1)-OX(OZ): OX(X) gibt an, ab welchem Satz der relativen Datei der Beschreibungs-Text zu Objekt X steht. Ist OX(X)=0, so heißt dies, daß das Objekt X bei der Raumbeschreibung nicht anhand eines Textes erläutert wird.
OA(1)-OA(OZ): OA(OZ) gibt an, um welche Art von Objekt es sich bei Objekt X handelt. Es gibt folgende Werte:

1. Das Objekt ist ein Raum (zum Beispiel Tunnel).
2. Das Objekt befindet sich im Raum und kann nicht transportiert werden (zum Beispiel Öffnung in der Wand).
3. Das Objekt kann transportiert werden vom Spieler (zum Beispiel Schwert).
OU(1)-OU(OZ): OU(OZ) zeigt auf den ersten Satz des Kommentars in der Texte-Datei, der ausgegeben wird, wenn das Objekt untersucht wird. Wird ein Objekt untersucht, dessen OU(X)-Wert gleich 0 ist, so erfolgt der Kommentar »DAS OBJEKT X HAT KEINE BESONDEREN MERKMALE.«
OS(1)-OS(OZ): OS(X) gibt an, in welchem Satz der Texte-Datei der Objektname von Objekt X gespeichert ist (Beispiel: die Glaskuppel = 164).

Die Objekttabelle steht nur bei der Entwicklung des Programmes in DATA-Zeilen. Sie wird später entweder als SEQ-File geladen oder als PRG-File geladen und irgendwo im RAM mit entsprechender Verwaltung untergebracht. Durch geschicktes Manipulieren der Objekttabelle ist es leicht, dem Adventure Intelligenz zu verleihen: Das Programm lacht den Spieler aus, wenn er auf die unsinnige Idee kommt, einen Raum wie den Tunnel nehmen zu wollen. Will der Spieler eine lebende Person nehmen (OA-Wert könnte zum Beispiel mit 4 definiert werden), so kann sich der Analyseteil des Adventures mit »ICH GLAUBE KAUM, DASS SICH DIE PERSON X SO OHNE WEITERES NEHMEN LÄSST« etc.

Nehmen wir einmal an, der Spieler will Objekt X nehmen – also BES=»NIMM OBJEKT X«.

Das Programm kann nun verschiedenes überprüfen und so feststellen, ob der Spieler Objekt X überhaupt nehmen kann.

Erweist sich OB(X) als -1, so meldet sich das Adventure mit »SIE HABEN OBJEKT X BEREITS«.

IST OB(X) ungleich ZN (der aktuelle Raum), so erfolgt der Kommentar »OBJEKT X IST HIER NICHT ZU SEHEN«. Außerdem läßt das Programm nur zu, Objekte zu nehmen, deren OA-Wert = 3 ist (also transportables Objekt beziehungsweise Gegenstand).

Mit den 5 Objekttabellen kann also jedes Objekt exakt analysiert werden. Ein Beispiel: Die Statue hat folgende Werte:

OB(6)=3: Das heißt, die Statue steht im Raum 3.

OX(6)=0: Das heißt, die Statue wird in der Raumbeschreibung nicht mehr besonders erwähnt. Sie kommt schließlich bereits in der Beschreibung des Quaders, auf dem sie steht, vor.

OA(6)=2: Das heißt, die Statue ist ein feststehendes Objekt und kann daher auch nicht transportiert werden.

OU(6)=113: Ab Satz 113 steht der Kommentar für die Untersuchung der Statue.

OS(6)=164: In diesem Satz der Texte-Datei steht der Objektname der Statue – die Statue.

Ganz klar wird Ihnen die Objekttabelle allerdings erst dann werden, wenn Sie sich mit der Abhandlung der Objekte im Programm selbst vertraut gemacht haben.

Zunächst möchte ich Ihnen jedoch noch einmal ganz genau zeigen, wie sich eine Raumbeschreibung zusammensetzt. Bild 2 zeigt die Raumbeschreibung der Kristallgrotte, nachdem man dort noch zwei transportable Gegenstände verloren hat.

Raumbeschreibung der Kristallgrotte, rechts mit Klammern in die Abschnitte I bis IV gegliedert
Bild 2. Aufteilung der Raumbeschreibung
I Dies ist die Statuszeile. Sie ist ständig zu sehen und gibt an, in welchem Raum man sich gerade befindet, die bisher erzielte Punktzahl und die Anzahl der Spielzüge, die man bisher gemacht hat.
II In diesem Bereich steht die Hauptraumbeschreibung – also die Beschreibung, die sich während des gesamten Verlaufs des Spieles nicht ändert.
III Hier sind alle Objekte aufgeführt, die sich zwar verändern können, jedoch (zumindest im Moment) nicht vom Spieler transportiert werden können. Der OA-Wert dieser Objekte beziehungsweise Beschreibungen ist 2. Der OA-Wert von Gegenständen (=transportable Objekte) ist in der Regel 0. Hier gibt es jedoch eine Ausnahme: Es ist möglich, ein solches Objekt bei seinem ersten Auftreten ausführlicher zu beschreiben als mit HIER LIEGT EIN ... Wird das Objekt jedoch genommen, so wird innerhalb der NIMM-Routine sein OA-Wert für immer auf Null gesetzt. Wird es wieder verloren, so taucht es in der Raumbeschreibung anschließend mit der Beschreibung HIER LIEGT EIN ... auf.
IV Ganz am Ende der Raumbeschreibung werden die Objekte aufgeführt, die dort vom Spieler verloren worden sind beziehungsweise bei denen es sich um Gegenstände handelt, deren OA-Wert von vorneherein 0 ist.

Das Unterprogramm zur Erzeugung der Raumbeschreibung steht im Programm ab Zeile 54000. Vergleichen Sie doch mal die obige Theorie mit diesem Programmteil – dann gewinnen Sie am schnellsten den Durchblick!

Die nächste Tabelle, die definiert wird, ist die Landkarte, die als Feld MAP(N,10) angelegt ist, wobei N für die Anzahl der Räume steht. In dieser Tabelle ist eingetragen, welche Verbindungen zwischen den einzelnen Räumen existieren. Dabei werden allerdings nur die stets bestehenden Verbindungen eingetragen, die nicht erst geschaffen werden müssen (zum Beispiel durch das Öffnen einer Tür mit einem Schlüssel). Die Richtungen stehen so: N,S,W,O,NW, NO,SW,SO, rauf, runter – also MAP(N,1) für wohin es nach Norden geht und MAP(N,10) für Süden. Eine nicht existente Verbindung hat den Wert 0.

Beispiel: Ist MAP(3,3)=4, so heißt dies, daß man von Raum 3 nach Westen gehen kann, um zu Raum 4 zu gelangen.

Analyseteil

Wie schon beim ersten Adventure-Kurs unterscheiden wir auch diesmal zwei Arten von Action: allgemeine und raumspezifische Action.

Allgemeine Action sind Handlungen, die man in jedem Raum, jederzeit ausführen kann – zum Beispiel Objekte untersuchen, Sachen nehmen, verlieren, Inventur etc.

Raumspezifische Action hingegen sind Handlungen, die man nur in bestimmten Räumen ausführen kann. »Berühre Statue« hat nur in dem Raum einen Effekt, in dem die Statue steht.

Im Programm steht die allgemeine Action in den Zeilen 300-800, die raumspezifische Action ab Zeile 2000.

Beim Gerüst sind in den Zeilen 300 - 700 bisher nur die Routinen untergebracht, die bei jedem Adventure unentbehrlich sind: GEH-Routine, NIMM-Routine, INVENTUR-Routine, VERLIER-Routine, UNTERSUCHE-Routine.

Ich verzichte an dieser Stelle bewußt auf eine genaue Dokumentation dieser Programmteile: Die Routinen sind sauber programmiert, und es sollte Ihnen keine Schwierigkeiten bereiten, sie selbst zu analysieren, wenn Sie bisher aufmerksam mitgearbeitet haben!

Wenn Sie das bisherige Programm um die folgenden wenigen Zeilen ergänzen, haben Sie die erste Szene von Gordon Saga Teil II komplett im Computer, da diese Zeilen die noch fehlende raumspezifische Action darstellen.

800-900 Hier ist bei der allgemeinen Action noch eine kleine Routine eingefügt, mit der man den Brief lesen kann, der in Gordon Saga Teil 2 gefunden wird. Diese Routine habe ich erst jetzt beigefügt, da sie zwar zur allgemeinen Action zählt (man kann einen Brief überall lesen – nicht raumabhängige Action), aber nicht für jedes Adventure benötigt wird.
2100-2130 Hier steht die raumspezifische Action zur Glaskuppel.
2110 Hier wird festgestellt, ob der Spieler im Sand graben will: ist Verb = 15 (graben) und Objekt = 2 (Sand)? Gräbt der Spieler zum ersten Mal, so wird der Variablen SB der Wert 71 gesetzt (Zeiger auf Satz: Sie graben in dem Sand.).
In Zeile 110 wird der Wert der Variablen SB abgefragt. Ist SB ungleich Null, so wird in der Texte-Datei der Kommentar ausgelesen, der ab Satz SB bis zum nächsten Sternchen steht. SB wird sodann auf 0 gesetzt. Mittels SB werden also Kommentare aus der Texte-Datei abgerufen.
2117 Zweites Graben. Der Spieler findet ein Amulett und einen Zettel. Diesen beiden Objekten wird jetzt der OB-Wert der Zimmernummer ZN zugeordnet, da diese beiden Objekte gefunden sind und von nun an im Spiel enthalten sind.
Außerdem wird der OB-Wert der Grube auf ZN gesetzt. Dadurch wird die Grube das nächste Mal in der Raumbeschreibung erwähnt, wenn der Spieler Raum 1 untersucht: Es scheint so, als ob hier jemand vor kurzem gegraben hat.....Durch solche Action werden die Raumbeschreibungen variabel – das Adventure gewinnt an »Leben«.
2119 Versucht der Spieler ein drittes Mal zu graben, so erfolgt der Kommentar, daß weiteres Graben sinnlos ist.
2120 Wenn Verb=geh und Objekt=Tunnel, dann ist dies gleichbedeutend mit der Befehlseingabe »Norden«, da man von der Glaskuppel nach Norden gehen muß, um in den Tunnel zu gelangen. Also einfach die RI-Variable auf Norden setzen – RI=1 – und Sprung zur GEH-Routine (GOTO 300).
2200 Im Tunnel kommt keine raumspezifische Action vor.
2300-2320 Raumspezifische Action der Kristallgrotte.
2305 Wenn Verb=berühre und Objekt=Statue then Kommentar ab Zeile 119: Die Statue hat jetzt die Form des Spielers angenommen. Beim Untersuchen derselben muß also ein anderer Kommentar als bisher erscheinen. Also OU(6)=135.

Sie sehen schon: Mit Hilfe der einzelnen Objekt- und Wortschatz-Tabellen läßt sich die raumspezifische Action nahezu in Klartext übersetzen.

Damit wäre ich mit meinen Erklärungen auch schon am Ende. Die restlichen Action-Szenen können Sie leicht selbst deuten. Adventure-Programmierung ist ein sehr kompliziertes Gebiet. Ich bin mir sicher, daß einige von Ihnen bereits jetzt Ideen haben, wo sich hier und da noch so manches verbessern läßt.

Vielleicht haben Sie auch schon die Idee zu Parser 6.0 – dem NON-PLUS-ULTRA-Parser im Kopf.

Ich hoffe, Ihnen mit diesem Kapitel neue Anregungen im Bereich der Adventure-Programmierung gegeben zu haben. Wenn Sie noch irgendwelche Fragen oder Probleme mit Adventure-Programmierung haben, dann wenden Sie sich doch mal an die 64'er, vielleicht geben Ihre Nachfragen Anlaß zu einem kleinen Folgekurs.

Ich will allerdings noch nicht zum Schlußwort kommen, denn es steht noch ein wichtiges Kapitel aus:

Der Adventure-Cracker

Das Programm im Listing 4 macht's möglich: Adventures im Schlaf gelöst. Naja, ganz im Schlaf geht's nicht, aber Sie müssen sich lediglich im Sessel zurücklehnen und am Bildschirm mitverfolgen, wie der gesamte Text des Adventures ausgegeben wird.

Im Prinzip ist der Adventure-Cracker nichts weiter als ein ultra-primitiver Disk-Monitor, mit dem sich die einzelnen Bytes einer Diskette lesen lassen. Sie müssen einfach die Diskette, auf der sich das Adventure befindet, ins Laufwerk legen und dann mittels Angabe von Track und Sector nach Text suchen.

Der Adventure-Cracker filtert automatisch alle Zeichen heraus, die keinen Text darstellen (Grafikzeichen etc.). Es ist nur eine Frage der Zeit, bis man so den gesamten Text eines Adventures herausfindet.

Der Cracker knackt alle Basic-Adventures, Adventures, die mit relativen Dateien arbeiten (also unsere), und auch professionelle Spiele. Den INFOCOMs kann man mit dem Adventure-Cracker allerdings in keinster Weise zu Leibe rücken: Ihr Text ist auf eine äußerst komplizierte Weise verschlüsselt und bringt auch harte Dechiffrierer zur Verzweiflung ...

Es ist also ratsam, Adventure-Texte nicht einfach unverschlüsselt in relativen Dateien abzulegen. Parallel zum Codieren bietet sich allerdings noch etwas anderes an:

Text-Raffung

Es gibt verschiedene Methoden, Text zu kürzen, um so letztendlich noch mehr Text auf einer Disk-Seite unterzubringen. Es bietet sich zum Beispiel an, einzelne Kürzel zu definieren. Schließlich haben wir 255 verschiedene Zeichen zur Verfügung, von denen zur reinen Textdarstellung nur ca. 70 benötigt werden (Groß-Klein-Buchstaben und diverse Satzzeichen). Man könnte nun doch eigentlich eine Tabelle anlegen, in der häufige Buchstabenkombinationen (er, die, ch, das, ng, en, .....) durch Grafikzeichen codiert werden.

Sie können insgesamt zirka 180 solche Kürzel definieren und dann ein Programm schreiben, das Ihre relativen Dateien automatisch kürzt und die Buchstaben anhand einer weiteren Tabelle – einem Code-Schlüssel – chiffriert.

Es gibt unglaublich viele Verschlüsselungs- und Text-Raffungsmethoden, die sich relativ einfach programmieren lassen. Denken Sie mal nach!

Bonbon zum Schluß

Zu Beginn dieses Kurses habe ich Ihnen versprochen, daß das freie RAM bis zum letzten Byte mit interessanten Routinen belegt wird. Das haben wir auch geschafft. Bis auf einen kleinen Bereich: von 1024 bis 2023 der alte Bildschirmspeicher.

Dort bringen wir jetzt noch eine Maschinenroutine unter, die in Listing 5 abgedruckt ist.

Diese Routine können Sie erst dann laden, wenn der deutsche Zeichensatz aktiviert und der Bildschirm an eine andere Stelle als 1024-2023 gelegt worden ist. Zum Laden können Sie nicht den LOAD-Befehl, sondern nur Listing 6 verwenden.

Die Routine beherbergt zwei sehr wichtige Funktionen, die bei jeder Adventure-Programmierung benötigt werden:

  1. Erweiterte INPUT-Routine
    Mittels SYS 1160,BE$ rufen Sie die erweiterte INPUT-Routine auf. Nach Rücksprung steht der eingegebene Satz in BE$ – natürlich kann anstelle von BE$ auch jeder andere beliebige String gesetzt werden.
  2. Raumbeschreibung einlesen
    Mittels SYS 1024,SA rufen Sie eine Maschinenroutine auf, die den Satzbereich einer relativen Datei von Satz SA ab bis zum nächsten Sternchen ausgibt – und das sehr, sehr schnell!

Die relative Datei muß von Basic aus per OPEN 8,8,8,»Filename« geöffnet werden, ebenso der Floppykanal mittels OPEN 15,8,15.

Nochmals sei darauf hingewiesen, daß die Routinen nur lauffähig sind, wenn der deutsche Zeichensatz verwendet wird, und daß sie nur mit den Zeilen aus Listing 6 geladen werden können.

Mit dieser Routine möchte ich mich von Ihnen verabschieden. Ich hoffe, daß Sie einige wertvolle Tips zur Programmierung von Abenteuerspielen erhalten haben. Viel Spaß beim Programmieren!

(M. Nickles/bs)
|
0 rem ***************************
1 rem gordon saga ii - 1985 by sm
2 rem ***************************
3 ifi=0theni=1:load"d.z.satz",8,1
4 poke648,204:poke53272,56:poke56576,0:print"{clr}":rem d.t.satz aktivieren
5 open15,8,15:print"{clr}{yel}";chr$(14);
6 side=2:gosub53200:print"{clr}";
15 gosub60000: rem tabellen einlesen
20 dimwi(100): rem zimmer-merker
30 sc=0:mo=0 : rem score/versuch
40 sa=1:gosub53600                                   : rem titeltext
50 zn=1:gosub54000                                   : rem beschreib. 1.raum
100 rem start ------------------------------------------------------------------
101 :
110 ifsb<>0thensa=sb:sb=0:gosub53600:rem kommentar ausgeben
120 gosub50000           :rem befehlseingabe
130 :
300 rem geh-routine -----------------
310 ifri=0then400
320 i=map(zn,ri)
330 ifi=0thenprint"Diese Richtung ist nicht m{CBM-O}glich!":goto400
340 zn=i:gosub54000
400 rem schau/untersuche ------------
410 ifve<>11then500
415 ifo1=0thengosub54000:goto500
420 sa=os(o1):gosub53400:gosub53500:ob$="D"+right$(i$,len(i$)-1)
425 ifob(o1)=-1then430
430 ifob(o1)<>znthenx$=ob$+" ist hier nicht zu sehen!":gosub53900:goto500
440 ifou(o1)=0thenx$=ob$+" hat keine besonderen Merkmale.":gosub53900
450 ifou(o1)thensa=ou(o1):gosub53800
500 rem nimm ------------------------
505 ifve<>12then600
506 ifsp=1then550:rem nimm alles
507 sa=os(o1):gosub53400:gosub53500:ob$="D"+right$(i$,len(i$)-1)
510 ifo1=0thenprint"Ihr Satz enth{CBM-A}lt kein Objekt !":goto600
514 :ifob(o1)=-1thenprint"Das haben Sie bereits !":goto600
515 :ifob(o1)<>znthenx$=ob$+" ist hier nicht zu sehen!":gosub53900:goto600
516 ifoa(o1)=0then600
520 :ifoa(o1)=1thenprint"Bizarr!":goto600
525 :ifoa(o1)=2thenx$=ob$+" ist viel zu schwer zum tragen!":gosub53900:goto600
530 :ifoa(o1)=3thenprint"Genommen.":ob(o1)=-1:goto600
550 :
554 print:fori=1tooz
555 :ifob(i)<>znthen580
556 sa=os(i):gosub53400:gosub53500:ob$="D"+right$(i$,len(i$)-1)
560 :i$=ob$+": "
565 ifsq=1andi=o1then580:rem ausser
570 :ifoa(i)=1thenprinti$;"Bizarr !"
575 :ifoa(i)=2thenprinti$;"Zu schwer zum tragen !"
577 :ifoa(i)=3thenprinti$;"Genommen.":ob(i)=-1
580 nexti
600 rem inventur -----------------
601 ifve<>13then700
605 print"{down}Sie haben: {up}"
610 ic=0:fori=1tooz
611 sa=os(i):gosub53400:gosub53500:ob$="D"+right$(i$,len(i$)-1):i$=ob$
612 :ifleft$(i$,3)="Der"thenj$=right$(i$,len(i$)-3):i$="Den"+j$
615 :ifob(i)=-1thenprint"{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}";i$:ic=1
620 nexti:ific=0thenprint"{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}{rght}Bock auf Bier !"
700 rem verliere -----------------
701 ifve<>14then800
702 ifsp=1then750: rem verlier alles
703 ifo1=0thenprint"Ihr Satz enth{CBM-A}lt kein Objekt!":goto800
705 ifob(o1)<>-1thenprint"{down}Sie haben das nicht !":goto800
715 ob(o1)=zn:print"Ok.":goto800
750 ic=0:fori=1tooz
755 :ifsq=1andi=o1then780:rem ausser
760 sa=os(i):gosub53400:gosub53500:ob$="D"+right$(i$,len(i$)-1):i$=ob$+": "
770 :ifob(i)=-1thenob(i)=zn:printi$;"Ok.":ic=1
780 nexti:ific=0andsq=1thenprint"Wie soll das gehen ?"
782 ific=0andsq=0thenprint"Sie haben doch garnichts !"
800 :
2000 rem raumspezifische action ------------------------------------------------
50000 rem *****************************
50001 rem *                           *
50002 rem *     wort-parser 4.0       *
50003 rem *                           *
50004 rem *      <c> 1986 bei         *
50005 rem *                           *
50006 rem *     michael nickles       *
50007 rem *                           *
50008 rem *****************************
50010 rem befehlssatzeingabe ---------------------------------------------------
50011 zw=0:print:gosub53000:mo=mo+1:rem titelline ausgeben
50012 ifud>0then50500:rem und
50015 sl=77: rem befehlssatzlaenge
50020 be$="":poke198,0:print"{yel}>{CBM-@}";
50030 getx$:ifpeek(203)=1then50120
50040 ifx$=""then50030
50050 iflen(be$)=0andasc(x$)=20then50030
50060 i=asc(x$):ifi<32ori>133andi<159thenifi<>20then50030
50070 iflen(be$)=slandi<>20then50030
50080 be$=be$+x$
50090 printchr$(20);x$;"{CBM-@}";
50100 ifi=20thenbe$=left$(be$,len(be$)-2):goto50030
50110 goto50030
50120 print"{left} "
50400 rem satzzeichen suchen ---------------------------------------------------
50401 :
50415 sn=0
50420 ifright$(be$,1)=" "thenbe$=left$(be$,len(be$)-1):goto50420
50430 i$=right$(be$,1)
50440 ifi$="."ori$="!"thensn=0:be$=left$(be$,len(be$)-1):goto50420
50450 ifi$="?"thensn=1:be$=left$(be$,len(be$)-1):goto50420
50500 rem be$-zeiger setzen ----------------------------------------------------
50501 :
50502 ifud=0thenve=0:ri=0:o1=0:o2=0:sp=0:sq=0
50504 ifud>0thenri=0:goto50530
50505 ifleft$(be$,1)=" "thenbe$=right$(be$,len(be$)-1):goto50505
50510 be$=be$+" "
50520 za=1 :rem zeiger a setzen
50530 zb=za+1
50540 ifmid$(be$,zb,1)=""thenud=0:close1:open1,8,3,"texte":return
50550 ifmid$(be$,zb,1)<>" "thenzb=zb+1:goto50550
50590 su$=mid$(be$,za,zb-za)
50600 rem su$ vorbehandlung ----------------------------------------------------
50601 :
50610 ifsu$="und"thenud=1:goto50630
50620 ifsu$=","thenud=2:goto50630
50625 goto50670
50630 za=zb+1
50640 ifmid$(be$,za,1)=""thenprint"Und was ?":goto50530
50650 ifmid$(be$,za,1)=" "thenza=za+1:goto50650
50660 close1:open1,8,3,"texte":return
50670 ifsu$="ihn"orsu$="sie"orsu$="es"theno1=om:goto51300
50680 ifsu$="alles"thensp=1:goto51300
50690 ifsu$="ausser"thensq=1:goto51300
51000 rem binaere suchroutine --------------------------------------------------
51001 :
51002 close1:open1,8,3,"wortschatz"
51007 rem anfang und ende des suchbereiches ermitteln
51008 i=asc(left$(su$,1))
51009 ifi-65<0ori-65>25thengosub51500:goto50000
51010 an=in(i-65):rem anfang des suchbereiches
51012 iz=64
51013 ifin(i-iz)=0theniz=iz-1:goto51013
51015 en=in(i-iz)-1:rem ende des suchbereiches
51016 ifan=0thengosub51500:ud=0:goto50000
51020 sz=197:n=int(log(en-an+1)/log(2))+1              :rem maximal-formel
51030 sa=an-1+(2^n)/2:rem mitte der ges.dat
51040 gosub52100:rem a$ lesen
51050 n=n-1     :rem 1.abfrage
51060 :
51070 rem su$ mit a$ vergleichen ------
51080 : iflen(su$)<3then51110
51090 : ifwa=1 and su$=left$(a$,len(su$)) thenve=wc:goto51300
51100 : ifwa<>3orsu$<>right$(a$,len(su$))then51110
51102 :  ifud=1orud=2thenud=3:o1=0:o2=0
51104 :   ifo1=0theno1=wc:om=o1:goto51300
51105 :   ifo2=0theno2=wc:om=o1:goto51300
51110 : ifwa=2 and su$=a$                 thenri=wc:goto51300
51115 : ifwa=5 and su$=a$                 thenad=wc:goto51300
51120 : ifwa=1 and su$=a$                 thenve=wc:goto51300
51125 : ifwa=4 and su$=a$                 then51300
51130 : ifsu$<a$thensa=sa-(2^(n-1)):gosub52100:goto51160
51140 : ifsa+(2^(n-1))>sa+en-anandn>-1thenn=n-1:goto51140:rem ''ueberlauf''
51150 : sa=sa+(2^(n-1)):gosub52100:rem ''halbieren''
51160 :
51170 :n=n-1    :rem naechst. halbieren
51180 :ifn<0thengosub51500:ud=0:goto50000
51190 rem print"sa=";sa;" n=";n                             :rem unnoetig !!
51200 :goto51060:rem naechst. such-vers.
51300 rem naechstes wort
51310 za=zb+1
51320 ifmid$(be$,za,1)=""then50530
51330 ifmid$(be$,za,1)=" "thenza=za+1:goto51330
51350 goto50530
51500 rem ich kenne su$ nicht --------------------------------------------------
51501 :
51510 i=int(3*rnd(1))+1
51520 onigoto51530,51540,51550
51530 x$=""+"Ich kenne das Wort '"+su$+"' nicht.":goto52000
51540 x$=""+"Das Wort '"+su$+"' ist mir nicht bekannt.":goto52000
51550 x$=""+"Deutsch ist leider nur meine zweite Sprache. Ich kenne das "
51555 x$=x$+"Wort '"+su$+"' nicht.":goto52000
52000 rem formatierte textausgabe ----------------------------------------------
52010 ifx$=""then52090
52020 iflen(x$)<40thenprintx$:goto52090
52030 iflen(x$)=40thenprintx$;:goto52090
52040 i$=left$(x$,41):ic=0:fori=1tolen(i$):ifmid$(i$,i,1)=" "thenic=i
52050 nexti:ific=0thenprintx$:goto52090
52060 i$=left$(i$,ic-1):iflen(i$)=40thenprinti$;
52070 iflen(i$)<40thenprinti$
52080 x$=right$(x$,len(x$)-ic):goto52010
52090 return
52100 rem satz-teilbereich lesen -----------------------------------------------
52101 :
52110 hb%=sa/256:lb%=sa-hb%*256
52112 print#15,"p";chr$(3);chr$(lb%);chr$(hb%);chr$(1)
52114 input#15,a:ifa=50thenprint"satznummer zu hoch"
52120 ifa=50thenreturn
52130 input#1,a$
52140 wa=val(mid$(a$,22,1))
52150 wc=val(mid$(a$,23,3))
52160 a$=left$(a$,21)
52170 ifright$(a$,1)="{rght}"thena$=left$(a$,len(a$)-1):goto52170
52180 return
53000 rem up - titelline -------------------------------------------------------
53001 :
53010 i1$="                                     ":t$=""
53020 t$=t$+chr$(18)+r$:i$=str$(sc)+"/"+right$(str$(mo),len(str$(mo))-1)
53030 t$=t$+right$(i1$,41-len(t$)-len(i$))+i$+chr$(146):print"{home}";t$;
53040 print"{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}";:return
53200 rem up - disk einlegen ---------------------------------------------------
53201 :
53205 ific=21thengosub53700:rem weiter
53210 print"{rvon}Bitte Disk-Seite";side;"{left} einlegen !{rvof}";:poke198,0:wait198,1
53220 print"{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}                             ";
53221 print"{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}{left}";
53222 open2,8,2,"#":print#15,"u1 2 0 18 0":print#15,"b-p";2;162:get#2,i$
53224 close2:ifside<>val(i$)then53200
53225 ifside=2thenopen1,8,3,"texte"
53230 return
53400 rem zeiger postionieren --------------------------------------------------
53401 :
53420 hb%=sa/256:lb%=sa-hb%*256:print#15,"p";chr$(3);chr$(lb%);chr$(hb%);chr$(1)
53430 input#15,ia:ifia=50thenprint"satznummer zu hoch"
53440 return
53500 rem satz einlesen --------------------------------------------------------
53501 :
53510 ifa=50then53520
53512 input#1,i$
53515 zw=zw+1:ifzw>23thengosub53700:zw=0
53520 return
53600 rem text-einlesen --------------------------------------------------------
53601 :
53610 ifside<>2thenside=2:gosub53200
53620 gosub53400:rem positonieren
53630 gosub53500:rem i$ einlesen
53640 ifright$(i$,1)<>"*"then53660
53650 :ifi$<>"*"thenprintleft$(i$,len(i$)-1)
53652 :sa=0:return
53660 iflen(i$)<40thenprinti$
53670 iflen(i$)>=40thenprinti$;
53680 sa=sa+1
53695 goto53630
53700 rem weiter ---------------------------------------------------------------
53701 :
53705 print"[weiter]";:poke198,0:wait198,1:print"{left}{left}{left}{left}{left}{left}{left}{left}        {left}{left}{left}{left}{up}
53710 return
53800 rem kommentar lesen ------------------------------------------------------
53801 :
53805 zw=1
53810 print:gosub53600:return
53900 rem textformer ------------------
53901 :
53902 ifx$<>""thenprint
53905 ifx$=""then53945
53910 iflen(x$)<40thenprintx$:goto53945
53915 iflen(x$)=40thenprintx$;:goto53945
53920 i$=left$(x$,41):ic=0:fori=1tolen(i$):ifmid$(i$,i,1)=" "thenic=i
53925 nexti:ific=0thenprintx$:goto53945
53930 i$=left$(i$,ic-1):iflen(i$)=40thenprinti$;
53935 iflen(i$)<40thenprinti$
53940 x$=right$(x$,len(x$)-ic):goto53905
53945 return
53950 rem artikel-wandler -------------
53951 :
53952 ii$=left$(ob$,3)
53955 ifii$<>"Der"andii$<>"Das"then53965
53960 x$="":x$="Hier liegt ein"+right$(ob$,len(ob$)-3)+"."
53965 ifii$<>"Die"then53970
53966 x$="":x$="Hier liegt eine"+right$(ob$(i),len(ob$)-3)+"."
53970 goto53905
54000 rem raumtext-einlesen ----------------------------------------------------
54001 :
54020 print:fori=1tooz :rem ob.tab.
54030 :ifob(i)<>znthen54080
54035 :ifox(i)<1then54080  :rem namelos
54040 :sa=ox(i):gosub53400 :rem posit.
54050 :ifoa(i)=1thengosub53500:r$=i$          :rem read i$, titelline
54060 :ifwi(zn)=1andve<>11andoa(i)=1thenprintr$:sa=0:goto54080
54070 :gosub53600          :rem lesen
54080 nexti
54081 fori=1tooz
54083 ifob(i)<>znoroa(i)<>3orox(i)<>0then54088
54084 sa=os(i):gosub53400:gosub53500:ob$="D"+right$(i$,len(i$)-1)
54085 x$="Hier liegt "+ob$+".":zw=zw+1:gosub53950
54088 nexti
54095 wi(zn)=1:print:return
60000 rem tabellen einlesen ----------------------------------------------------
60001 :
63000 rem *****************************
63005 rem * mini-texteditor v.iii.4   *
63010 rem *     <c> 1985              *
63015 rem * von michael nickles       *
63020 rem *****************************
63025 rem anfangsmenue -----------------
63030 poke198,0:input"{down}{down}dateiname  *{left}{left}{left}";d$:poke198,0
63035 input"satzlaenge  40{left}{left}{left}{left}";sl:ifsl<1orsl>254thenprint"geht nicht !":goto30
63040 open 15,8,15
63045 print#15,"i0":open 1,8,3,d$:print
63050 rem zwischenmenue ----------------
63055 print"{rvon}s / l / ende                            {rvof}";
63060 geti$:ifi$=""then63060
63065 ifi$="e"thenprint"{clr}";:goto63265
63070 ifi$<>"s"andi$<>"l"then63060
63075 input"satznr";sa:if sa<0 or sa>63000 then63070
63080 ifi$="l"thenprint"{clr}";:goto63095
63085 ifi$="s"thenprint"{clr}";:mo=1:goto63150
63090 goto 63050
63095 rem lesen ------------------------
63100 :print"{clr}{rvon}";sa;"{left}-";str$(sa+20);" {rvof}"
63105 ia=sa
63110 for sa=ia to ia+20
63115 : gosub63195:gosub63220
63120 : ifa=50thensa=ia+21:goto63135
63125 : iflen(a$)<40thenprinta$
63130 : iflen(a$)>=40thenprinta$;
63135 next:print
63140 ifa=50thenprint"satznummer zu hoch!"
63145 goto 63050
63150 rem schreiben --------------------
63155 print"eingabesatz  //=keine eingabe"
63160 gosub63195:rem positionieren
63165 ifa=50thenprint"satznummer zu hoch!":goto63050:rem fehlerkanalabfr.
63170 gosub63330:a$=be$                                   :rem input-rout.
63175 ifa$="//"thenmo=0:goto63050:rem ende
63180 gosub63240:rem a$ schreiben
63185 sa=sa+1     :rem naechster satz
63190 goto63160:rem next (loop)
63195 rem positionieren ****************
63200 hb%=sa/256:lb%=sa-hb%*256
63205 print#15,"p";chr$(3);chr$(lb%);chr$(hb%);chr$(1)
63210 input#15,a
63215 return
63220 rem satz einlesen ****************
63225 ifa=50thenreturn
63230 input#1,a$
63235 return
63240 rem satz schreiben ***************
63245 ifa=50thenreturn
63250 ifa$=""thena$=":":rem zur sicherheit !!!
63255 print#1,a$
63260 return
63265 rem beenden **********************
63270 close 1
63275 close 15
63280 print "++ ende ++"
63285 end
63290 rem korrektur-routine ------------
63295 fori=0tolen(be$):printchr$(20);:nexti:be$=""
63300 sa=sa+sc       : rem textzeiger
63305 ifsa<0thensa=0 : rem sperre
63310 gosub 63195: rem positionieren
63315 ifa=50thensa=sa-sc:goto63310
63320 input#1,a$
63325 return
63330 rem texteingabe ------------------
63335 ifar=1thenar=0:a$="{rvon}satznummer zu hoch!{rvof}":goto63345
63340 gosub63195:gosub63220
63345 print"{home}                                        ";:print"{home}{rvon}satz";sa;"{rvof}"
63350 print"                                        {up}";a$
63355 print"{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}{CBM-T}";
63360 print"{down}"
63365 be$="":poke198,0:poke211,0:poke214,22:sys58732:print"{yel}{CBM-@}";
63370 getx$:ifpeek(203)=1then63430
63375 if peek(203)=7andpeek(653)=0 then sc=1 : gosub 63290: goto 63330
63380 if peek(203)=7andpeek(653)=1 then sc=-1 : gosub 63290: goto 63330
63385 ifx$=""then63370
63390 iflen(be$)=0andasc(x$)=20then63370
63395 i=asc(x$):ifi<32ori>133andi<159thenifi<>20then63370
63400 iflen(be$)=slandi<>20then63370
63405 ifx$=" "thenx$="{rght}"
63410 be$=be$+x$
63415 printchr$(20);x$;"{CBM-@}";
63420 ifi=20thenbe$=left$(be$,len(be$)-2):goto63370
63425 goto63370
63430 print"{left} ":gosub63195
63435 ifbe$=""thenbe$=":"
63440 print"{home}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}":return
  0 REM *************************** 
  1 REM GORDON SAGA II - 1985 BY SM 
  2 REM *************************** 
  3 IF I=0 THENI=1:LOAD "D.Z.SATZ",8,1 
  4 POKE 648,204:POKE 53272,56:POKE 56576,0:PRINT"{CLR}":REM D.T.SATZ AKTIVIEREN 
  5 OPEN 15,8,15:PRINT"{CLR,YELLOW}";CHR$ (14); 
  6 SIDE=2:GOSUB 53200:PRINT"{CLR}"; 
 15 GOSUB 60000: REM TABELLEN EINLESEN 
 20 DIM WI(100): REM ZIMMER-MERKER 
 30 SC=0:MO=0 : REM SCORE/VERSUCH 
 40 SA=1:GOSUB 53600                                   : REM TITELTEXT 
 50 ZN=1:GOSUB 54000                                   : REM BESCHREIB. 1.RAUM 
 100 REM START ------------------------------------------------------------------ 
 101 : 
 110 IF SB<>0 THENSA=SB:SB=0:GOSUB 53600:REM KOMMENTAR AUSGEBEN 
 120 GOSUB 50000           :REM BEFEHLSEINGABE 
 130 : 
 300 REM GEH-ROUTINE ----------------- 
 310 IF RI=0 THEN400 
 320 I=MAP(ZN,RI) 
 330 IF I=0 THENPRINT"DIESE RICHTUNG IST NICHT MOGLICH!":GOTO 400 
 340 ZN=I:GOSUB 54000 
 400 REM SCHAU/UNTERSUCHE ------------ 
 410 IF VE<>11 THEN500 
 415 IF O1=0 THENGOSUB 54000:GOTO 500 
 420 SA=OS(O1):GOSUB 53400:GOSUB 53500:OB$="D"+RIGHT$ (I$,LEN (I$)-1) 
 425 IF OB(O1)=-1 THEN430 
 430 IF OB(O1)<>ZN THENX$=OB$+" IST HIER NICHT ZU SEHEN!":GOSUB 53900:GOTO 500 
 440 IF OU(O1)=0 THENX$=OB$+" HAT KEINE BESONDEREN MERKMALE.":GOSUB 53900 
 450 IF OU(O1) THENSA=OU(O1):GOSUB 53800 
 500 REM NIMM ------------------------ 
 505 IF VE<>12 THEN600 
 506 IF SP=1 THEN550:REM NIMM ALLES 
 507 SA=OS(O1):GOSUB 53400:GOSUB 53500:OB$="D"+RIGHT$ (I$,LEN (I$)-1) 
 510 IF O1=0 THENPRINT"IHR SATZ ENTHALT KEIN OBJEKT !":GOTO 600 
 514 :IF OB(O1)=-1 THENPRINT"DAS HABEN SIE BEREITS !":GOTO 600 
 515 :IF OB(O1)<>ZN THENX$=OB$+" IST HIER NICHT ZU SEHEN!":GOSUB 53900:GOTO 600 
 516 IF OA(O1)=0 THEN600 
 520 :IF OA(O1)=1 THENPRINT"BIZARR!":GOTO 600 
 525 :IF OA(O1)=2 THENX$=OB$+" IST VIEL ZU SCHWER ZUM TRAGEN!":GOSUB 53900:GOTO 600 
 530 :IF OA(O1)=3 THENPRINT"GENOMMEN.":OB(O1)=-1:GOTO 600 
 550 : 
 554 PRINT:FOR I=1 TOOZ 
 555 :IF OB(I)<>ZN THEN580 
 556 SA=OS(I):GOSUB 53400:GOSUB 53500:OB$="D"+RIGHT$ (I$,LEN (I$)-1) 
 560 :I$=OB$+": " 
 565 IF SQ=1AND I=O1 THEN580:REM AUSSER 
 570 :IF OA(I)=1 THENPRINTI$;"BIZARR !" 
 575 :IF OA(I)=2 THENPRINTI$;"ZU SCHWER ZUM TRAGEN !" 
 577 :IF OA(I)=3 THENPRINTI$;"GENOMMEN.":OB(I)=-1 
 580 NEXT I 
 600 REM INVENTUR ----------------- 
 601 IF VE<>13 THEN700 
 605 PRINT"{DOWN}SIE HABEN:{SPACE,UP}" 
 610 IC=0:FOR I=1 TOOZ 
 611 SA=OS(I):GOSUB 53400:GOSUB 53500:OB$="D"+RIGHT$ (I$,LEN (I$)-1):I$=OB$ 
 612 :IF LEFT$ (I$,3)="DER" THENJ$=RIGHT$ (I$,LEN (I$)-3):I$="DEN"+J$ 
 615 :IF OB(I)=-1 THENPRINT"{11RIGHT}";I$:IC=1 
 620 NEXT I:IF IC=0 THENPRINT"{11RIGHT}BOCK AUF BIER !" 
 700 REM VERLIERE ----------------- 
 701 IF VE<>14 THEN800 
 702 IF SP=1 THEN750: REM VERLIER ALLES 
 703 IF O1=0 THENPRINT"IHR SATZ ENTHALT KEIN OBJEKT!":GOTO 800 
 705 IF OB(O1)<>-1 THENPRINT"{DOWN}SIE HABEN DAS NICHT !":GOTO 800 
 715 OB(O1)=ZN:PRINT"OK.":GOTO 800 
 750 IC=0:FOR I=1 TOOZ 
 755 :IF SQ=1AND I=O1 THEN780:REM AUSSER 
 760 SA=OS(I):GOSUB 53400:GOSUB 53500:OB$="D"+RIGHT$ (I$,LEN (I$)-1):I$=OB$+": " 
 770 :IF OB(I)=-1 THENOB(I)=ZN:PRINTI$;"OK.":IC=1 
 780 NEXT I:IF IC=0AND SQ=1 THENPRINT"WIE SOLL DAS GEHEN ?" 
 782 IF IC=0AND SQ=0 THENPRINT"SIE HABEN DOCH GARNICHTS !" 
 800 : 
 2000 REM RAUMSPEZIFISCHE ACTION ------------------------------------------------ 
 50000 REM ***************************** 
 50001 REM *                           * 
 50002 REM *     WORT-PARSER 4.0       * 
 50003 REM *                           * 
 50004 REM *      <C> 1986 BEI         * 
 50005 REM *                           * 
 50006 REM *     MICHAEL NICKLES       * 
 50007 REM *                           * 
 50008 REM ***************************** 
 50010 REM BEFEHLSSATZEINGABE --------------------------------------------------- 
 50011 ZW=0:PRINT:GOSUB 53000:MO=MO+1:REM TITELLINE AUSGEBEN 
 50012 IF UD>0 THEN50500:REM UND 
 50015 SL=77: REM BEFEHLSSATZLAENGE 
 50020 BE$="":POKE 198,0:PRINT"{YELLOW}>@"; 
 50030 GET X$:IF PEEK (203)=1 THEN50120 
 50040 IF X$="" THEN50030 
 50050 IF LEN (BE$)=0AND ASC (X$)=20 THEN50030 
 50060 I=ASC (X$):IF I<32OR I>133AND I<159 THENIF I<>20 THEN50030 
 50070 IF LEN (BE$)=SLAND I<>20 THEN50030 
 50080 BE$=BE$+X$ 
 50090 PRINTCHR$ (20);X$;"@"; 
 50100 IF I=20 THENBE$=LEFT$ (BE$,LEN (BE$)-2):GOTO 50030 
 50110 GOTO 50030 
 50120 PRINT"{LEFT,SPACE}" 
 50400 REM SATZZEICHEN SUCHEN --------------------------------------------------- 
 50401 : 
 50415 SN=0 
 50420 IF RIGHT$ (BE$,1)=" " THENBE$=LEFT$ (BE$,LEN (BE$)-1):GOTO 50420 
 50430 I$=RIGHT$ (BE$,1) 
 50440 IF I$="."OR I$="!" THENSN=0:BE$=LEFT$ (BE$,LEN (BE$)-1):GOTO 50420 
 50450 IF I$="?" THENSN=1:BE$=LEFT$ (BE$,LEN (BE$)-1):GOTO 50420 
 50500 REM BE$-ZEIGER SETZEN ---------------------------------------------------- 
 50501 : 
 50502 IF UD=0 THENVE=0:RI=0:O1=0:O2=0:SP=0:SQ=0 
 50504 IF UD>0 THENRI=0:GOTO 50530 
 50505 IF LEFT$ (BE$,1)=" " THENBE$=RIGHT$ (BE$,LEN (BE$)-1):GOTO 50505 
 50510 BE$=BE$+" " 
 50520 ZA=1 :REM ZEIGER A SETZEN 
 50530 ZB=ZA+1 
 50540 IF MID$ (BE$,ZB,1)="" THENUD=0:CLOSE 1:OPEN 1,8,3,"TEXTE":RETURN 
 50550 IF MID$ (BE$,ZB,1)<>" " THENZB=ZB+1:GOTO 50550 
 50590 SU$=MID$ (BE$,ZA,ZB-ZA) 
 50600 REM SU$ VORBEHANDLUNG ---------------------------------------------------- 
 50601 : 
 50610 IF SU$="UND" THENUD=1:GOTO 50630 
 50620 IF SU$="," THENUD=2:GOTO 50630 
 50625 GOTO 50670 
 50630 ZA=ZB+1 
 50640 IF MID$ (BE$,ZA,1)="" THENPRINT"UND WAS ?":GOTO 50530 
 50650 IF MID$ (BE$,ZA,1)=" " THENZA=ZA+1:GOTO 50650 
 50660 CLOSE 1:OPEN 1,8,3,"TEXTE":RETURN 
 50670 IF SU$="IHN"OR SU$="SIE"OR SU$="ES" THENO1=OM:GOTO 51300 
 50680 IF SU$="ALLES" THENSP=1:GOTO 51300 
 50690 IF SU$="AUSSER" THENSQ=1:GOTO 51300 
 51000 REM BINAERE SUCHROUTINE -------------------------------------------------- 
 51001 : 
 51002 CLOSE 1:OPEN 1,8,3,"WORTSCHATZ" 
 51007 REM ANFANG UND ENDE DES SUCHBEREICHES ERMITTELN 
 51008 I=ASC (LEFT$ (SU$,1)) 
 51009 IF I-65<0OR I-65>25 THENGOSUB 51500:GOTO 50000 
 51010 AN=IN(I-65):REM ANFANG DES SUCHBEREICHES 
 51012 IZ=64 
 51013 IF IN(I-IZ)=0 THENIZ=IZ-1:GOTO 51013 
 51015 EN=IN(I-IZ)-1:REM ENDE DES SUCHBEREICHES 
 51016 IF AN=0 THENGOSUB 51500:UD=0:GOTO 50000 
 51020 SZ=197:N=INT (LOG (EN-AN+1)/LOG (2))+1              :REM MAXIMAL-FORMEL 
 51030 SA=AN-1+(2^N)/2:REM MITTE DER GES.DAT 
 51040 GOSUB 52100:REM A$ LESEN 
 51050 N=N-1     :REM 1.ABFRAGE 
 51060 : 
 51070 REM SU$ MIT A$ VERGLEICHEN ------ 
 51080 : IF LEN (SU$)<3 THEN51110 
 51090 : IF WA=1 AND SU$=LEFT$ (A$,LEN (SU$))  THENVE=WC:GOTO 51300 
 51100 : IF WA<>3OR SU$<>RIGHT$ (A$,LEN (SU$)) THEN51110 
 51102 :  IF UD=1OR UD=2 THENUD=3:O1=0:O2=0 
 51104 :   IF O1=0 THENO1=WC:OM=O1:GOTO 51300 
 51105 :   IF O2=0 THENO2=WC:OM=O1:GOTO 51300 
 51110 : IF WA=2 AND SU$=A$                  THENRI=WC:GOTO 51300 
 51115 : IF WA=5 AND SU$=A$                  THENAD=WC:GOTO 51300 
 51120 : IF WA=1 AND SU$=A$                  THENVE=WC:GOTO 51300 
 51125 : IF WA=4 AND SU$=A$                  THEN51300 
 51130 : IF SU$<A$ THENSA=SA-(2^(N-1)):GOSUB 52100:GOTO 51160 
 51140 : IF SA+(2^(N-1))>SA+EN-ANAND N>-1 THENN=N-1:GOTO 51140:REM ''UEBERLAUF'' 
 51150 : SA=SA+(2^(N-1)):GOSUB 52100:REM ''HALBIEREN'' 
 51160 : 
 51170 :N=N-1    :REM NAECHST. HALBIEREN 
 51180 :IF N<0 THENGOSUB 51500:UD=0:GOTO 50000 
 51190 REM PRINT"SA=";SA;" N=";N                             :REM UNNOETIG !! 
 51200 :GOTO 51060:REM NAECHST. SUCH-VERS. 
 51300 REM NAECHSTES WORT 
 51310 ZA=ZB+1 
 51320 IF MID$ (BE$,ZA,1)="" THEN50530 
 51330 IF MID$ (BE$,ZA,1)=" " THENZA=ZA+1:GOTO 51330 
 51350 GOTO 50530 
 51500 REM ICH KENNE SU$ NICHT -------------------------------------------------- 
 51501 : 
 51510 I=INT (3*RND (1))+1 
 51520 ON IGOTO 51530,51540,51550 
 51530 X$=""+"ICH KENNE DAS WORT '"+SU$+"' NICHT.":GOTO 52000 
 51540 X$=""+"DAS WORT '"+SU$+"' IST MIR NICHT BEKANNT.":GOTO 52000 
 51550 X$=""+"DEUTSCH IST LEIDER NUR MEINE ZWEITE SPRACHE. ICH KENNE DAS " 
 51555 X$=X$+"WORT '"+SU$+"' NICHT.":GOTO 52000 
 52000 REM FORMATIERTE TEXTAUSGABE ---------------------------------------------- 
 52010 IF X$="" THEN52090 
 52020 IF LEN (X$)<40 THENPRINTX$:GOTO 52090 
 52030 IF LEN (X$)=40 THENPRINTX$;:GOTO 52090 
 52040 I$=LEFT$ (X$,41):IC=0:FOR I=1 TOLEN (I$):IF MID$ (I$,I,1)=" " THENIC=I 
 52050 NEXT I:IF IC=0 THENPRINTX$:GOTO 52090 
 52060 I$=LEFT$ (I$,IC-1):IF LEN (I$)=40 THENPRINTI$; 
 52070 IF LEN (I$)<40 THENPRINTI$ 
 52080 X$=RIGHT$ (X$,LEN (X$)-IC):GOTO 52010 
 52090 RETURN 
 52100 REM SATZ-TEILBEREICH LESEN ----------------------------------------------- 
 52101 : 
 52110 HB%=SA/256:LB%=SA-HB%*256 
 52112 PRINT#15,"P";CHR$ (3);CHR$ (LB%);CHR$ (HB%);CHR$ (1) 
 52114 INPUT#15,A:IF A=50 THENPRINT"SATZNUMMER ZU HOCH" 
 52120 IF A=50 THENRETURN 
 52130 INPUT#1,A$ 
 52140 WA=VAL (MID$ (A$,22,1)) 
 52150 WC=VAL (MID$ (A$,23,3)) 
 52160 A$=LEFT$ (A$,21) 
 52170 IF RIGHT$ (A$,1)="{RIGHT}" THENA$=LEFT$ (A$,LEN (A$)-1):GOTO 52170 
 52180 RETURN 
 53000 REM UP - TITELLINE ------------------------------------------------------- 
 53001 : 
 53010 I1$="{37SPACE}":T$="" 
 53020 T$=T$+CHR$ (18)+R$:I$=STR$ (SC)+"/"+RIGHT$ (STR$ (MO),LEN (STR$ (MO))-1) 
 53030 T$=T$+RIGHT$ (I1$,41-LEN (T$)-LEN (I$))+I$+CHR$ (146):PRINT"{HOME}";T$; 
 53040 PRINT"{22DOWN}";:RETURN 
 53200 REM UP - DISK EINLEGEN --------------------------------------------------- 
 53201 : 
 53205 IF IC=21 THENGOSUB 53700:REM WEITER 
 53210 PRINT"{RVSON}BITTE DISK-SEITE";SIDE;"{LEFT,SPACE}EINLEGEN !{RVOFF}";:POKE 198,0:WAIT 198,1 
 53220 PRINT"{29LEFT,29SPACE}"; 
 53221 PRINT"{29LEFT}"; 
 53222 OPEN 2,8,2,"#":PRINT#15,"U1 2 0 18 0":PRINT#15,"B-P";2;162:GET #2,I$ 
 53224 CLOSE 2:IF SIDE<>VAL (I$) THEN53200 
 53225 IF SIDE=2 THENOPEN 1,8,3,"TEXTE" 
 53230 RETURN 
 53400 REM ZEIGER POSTIONIEREN -------------------------------------------------- 
 53401 : 
 53420 HB%=SA/256:LB%=SA-HB%*256:PRINT#15,"P";CHR$ (3);CHR$ (LB%);CHR$ (HB%);CHR$ (1) 
 53430 INPUT#15,IA:IF IA=50 THENPRINT"SATZNUMMER ZU HOCH" 
 53440 RETURN 
 53500 REM SATZ EINLESEN -------------------------------------------------------- 
 53501 : 
 53510 IF A=50 THEN53520 
 53512 INPUT#1,I$ 
 53515 ZW=ZW+1:IF ZW>23 THENGOSUB 53700:ZW=0 
 53520 RETURN 
 53600 REM TEXT-EINLESEN -------------------------------------------------------- 
 53601 : 
 53610 IF SIDE<>2 THENSIDE=2:GOSUB 53200 
 53620 GOSUB 53400:REM POSITONIEREN 
 53630 GOSUB 53500:REM I$ EINLESEN 
 53640 IF RIGHT$ (I$,1)<>"*" THEN53660 
 53650 :IF I$<>"*" THENPRINTLEFT$ (I$,LEN (I$)-1) 
 53652 :SA=0:RETURN 
 53660 IF LEN (I$)<40 THENPRINTI$ 
 53670 IF LEN (I$)>=40 THENPRINTI$; 
 53680 SA=SA+1 
 53695 GOTO 53630 
 53700 REM WEITER --------------------------------------------------------------- 
 53701 : 
 53705 PRINT"[WEITER]";:POKE 198,0:WAIT 198,1:PRINT"{8LEFT,8SPACE,4LEFT,UP} 
 53710 RETURN 
 53800 REM KOMMENTAR LESEN ------------------------------------------------------ 
 53801 : 
 53805 ZW=1 
 53810 PRINT:GOSUB 53600:RETURN 
 53900 REM TEXTFORMER ------------------ 
 53901 : 
 53902 IF X$<>"" THENPRINT 
 53905 IF X$="" THEN53945 
 53910 IF LEN (X$)<40 THENPRINTX$:GOTO 53945 
 53915 IF LEN (X$)=40 THENPRINTX$;:GOTO 53945 
 53920 I$=LEFT$ (X$,41):IC=0:FOR I=1 TOLEN (I$):IF MID$ (I$,I,1)=" " THENIC=I 
 53925 NEXT I:IF IC=0 THENPRINTX$:GOTO 53945 
 53930 I$=LEFT$ (I$,IC-1):IF LEN (I$)=40 THENPRINTI$; 
 53935 IF LEN (I$)<40 THENPRINTI$ 
 53940 X$=RIGHT$ (X$,LEN (X$)-IC):GOTO 53905 
 53945 RETURN 
 53950 REM ARTIKEL-WANDLER ------------- 
 53951 : 
 53952 II$=LEFT$ (OB$,3) 
 53955 IF II$<>"DER"AND II$<>"DAS" THEN53965 
 53960 X$="":X$="HIER LIEGT EIN"+RIGHT$ (OB$,LEN (OB$)-3)+"." 
 53965 IF II$<>"DIE" THEN53970 
 53966 X$="":X$="HIER LIEGT EINE"+RIGHT$ (OB$(I),LEN (OB$)-3)+"." 
 53970 GOTO 53905 
 54000 REM RAUMTEXT-EINLESEN ---------------------------------------------------- 
 54001 : 
 54020 PRINT:FOR I=1 TOOZ :REM OB.TAB. 
 54030 :IF OB(I)<>ZN THEN54080 
 54035 :IF OX(I)<1 THEN54080  :REM NAMELOS 
 54040 :SA=OX(I):GOSUB 53400 :REM POSIT. 
 54050 :IF OA(I)=1 THENGOSUB 53500:R$=I$          :REM READ I$, TITELLINE 
 54060 :IF WI(ZN)=1AND VE<>11AND OA(I)=1 THENPRINTR$:SA=0:GOTO 54080 
 54070 :GOSUB 53600          :REM LESEN 
 54080 NEXT I 
 54081 FOR I=1 TOOZ 
 54083 IF OB(I)<>ZNOR OA(I)<>3OR OX(I)<>0 THEN54088 
 54084 SA=OS(I):GOSUB 53400:GOSUB 53500:OB$="D"+RIGHT$ (I$,LEN (I$)-1) 
 54085 X$="HIER LIEGT "+OB$+".":ZW=ZW+1:GOSUB 53950 
 54088 NEXT I 
 54095 WI(ZN)=1:PRINT:RETURN 
 60000 REM TABELLEN EINLESEN ---------------------------------------------------- 
 60001 : 
 63000 REM ***************************** 
 63005 REM * MINI-TEXTEDITOR V.III.4   * 
 63010 REM *     <C> 1985              * 
 63015 REM * VON MICHAEL NICKLES       * 
 63020 REM ***************************** 
 63025 REM ANFANGSMENUE ----------------- 
 63030 POKE 198,0:INPUT"{2DOWN}DATEINAME{2SPACE}*{3LEFT}";D$:POKE 198,0 
 63035 INPUT"SATZLAENGE{2SPACE}40{4LEFT}";SL:IF SL<1OR SL>254 THENPRINT"GEHT NICHT !":GOTO 30 
 63040 OPEN 15,8,15 
 63045 PRINT#15,"I0":OPEN 1,8,3,D$:PRINT 
 63050 REM ZWISCHENMENUE ---------------- 
 63055 PRINT"{RVSON}S / L / ENDE{SPACE,27SPACE,RVOFF}"; 
 63060 GET I$:IF I$="" THEN63060 
 63065 IF I$="E" THENPRINT"{CLR}";:GOTO 63265 
 63070 IF I$<>"S"AND I$<>"L" THEN63060 
 63075 INPUT"SATZNR";SA:IF SA<0 OR SA>63000  THEN63070 
 63080 IF I$="L" THENPRINT"{CLR}";:GOTO 63095 
 63085 IF I$="S" THENPRINT"{CLR}";:MO=1:GOTO 63150 
 63090 GOTO 63050 
 63095 REM LESEN ------------------------ 
 63100 :PRINT"{CLR,RVSON}";SA;"{LEFT}-";STR$ (SA+20);"{SPACE,RVOFF}" 
 63105 IA=SA 
 63110 FOR SA=IA  TO IA+20 
 63115 : GOSUB 63195:GOSUB 63220 
 63120 : IF A=50 THENSA=IA+21:GOTO 63135 
 63125 : IF LEN (A$)<40 THENPRINTA$ 
 63130 : IF LEN (A$)>=40 THENPRINTA$; 
 63135 NEXT :PRINT 
 63140 IF A=50 THENPRINT"SATZNUMMER ZU HOCH!" 
 63145 GOTO 63050 
 63150 REM SCHREIBEN -------------------- 
 63155 PRINT"EINGABESATZ{2SPACE}//=KEINE EINGABE" 
 63160 GOSUB 63195:REM POSITIONIEREN 
 63165 IF A=50 THENPRINT"SATZNUMMER ZU HOCH!":GOTO 63050:REM FEHLERKANALABFR. 
 63170 GOSUB 63330:A$=BE$                                   :REM INPUT-ROUT. 
 63175 IF A$="//" THENMO=0:GOTO 63050:REM ENDE 
 63180 GOSUB 63240:REM A$ SCHREIBEN 
 63185 SA=SA+1     :REM NAECHSTER SATZ 
 63190 GOTO 63160:REM NEXT (LOOP) 
 63195 REM POSITIONIEREN **************** 
 63200 HB%=SA/256:LB%=SA-HB%*256 
 63205 PRINT#15,"P";CHR$ (3);CHR$ (LB%);CHR$ (HB%);CHR$ (1) 
 63210 INPUT#15,A 
 63215 RETURN 
 63220 REM SATZ EINLESEN **************** 
 63225 IF A=50 THENRETURN 
 63230 INPUT#1,A$ 
 63235 RETURN 
 63240 REM SATZ SCHREIBEN *************** 
 63245 IF A=50 THENRETURN 
 63250 IF A$="" THENA$=":":REM ZUR SICHERHEIT !!! 
 63255 PRINT#1,A$ 
 63260 RETURN 
 63265 REM BEENDEN ********************** 
 63270 CLOSE 1 
 63275 CLOSE 15 
 63280 PRINT "++ ENDE ++" 
 63285 END 
 63290 REM KORREKTUR-ROUTINE ------------ 
 63295 FOR I=0 TOLEN (BE$):PRINTCHR$ (20);:NEXT I:BE$="" 
 63300 SA=SA+SC       : REM TEXTZEIGER 
 63305 IF SA<0 THENSA=0 : REM SPERRE 
 63310 GOSUB 63195: REM POSITIONIEREN 
 63315 IF A=50 THENSA=SA-SC:GOTO 63310 
 63320 INPUT#1,A$ 
 63325 RETURN 
 63330 REM TEXTEINGABE ------------------ 
 63335 IF AR=1 THENAR=0:A$="{RVSON}SATZNUMMER ZU HOCH!{RVOFF}":GOTO 63345 
 63340 GOSUB 63195:GOSUB 63220 
 63345 PRINT"{HOME,40SPACE}";:PRINT"{HOME,RVSON}SATZ";SA;"{RVOFF}" 
 63350 PRINT"{40SPACE,UP}";A$ 
 63355 PRINT"TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT"; 
 63360 PRINT"{DOWN}" 
 63365 BE$="":POKE 198,0:POKE 211,0:POKE 214,22:SYS 58732:PRINT"{YELLOW}@"; 
 63370 GET X$:IF PEEK (203)=1 THEN63430 
 63375 IF PEEK (203)=7AND PEEK (653)=0  THEN SC=1 : GOSUB 63290: GOTO 63330 
 63380 IF PEEK (203)=7AND PEEK (653)=1  THEN SC=-1 : GOSUB 63290: GOTO 63330 
 63385 IF X$="" THEN63370 
 63390 IF LEN (BE$)=0AND ASC (X$)=20 THEN63370 
 63395 I=ASC (X$):IF I<32OR I>133AND I<159 THENIF I<>20 THEN63370 
 63400 IF LEN (BE$)=SLAND I<>20 THEN63370 
 63405 IF X$=" " THENX$="{RIGHT}" 
 63410 BE$=BE$+X$ 
 63415 PRINTCHR$ (20);X$;"@"; 
 63420 IF I=20 THENBE$=LEFT$ (BE$,LEN (BE$)-2):GOTO 63370 
 63425 GOTO 63370 
 63430 PRINT"{LEFT,SPACE}":GOSUB 63195 
 63435 IF BE$="" THENBE$=":" 
 63440 PRINT"{HOME,24DOWN}":RETURN 
Listing 1. Ein vollständiges »Adventure-Programmier-Gerüst«
|
60000 rem tabellen einlesen ----------------------------------------------------
60001 :
60100 rem wortschatz-index -----------
60110 dimin(26)
60120 fori=0to26:read in(i):nexti
60130 data 1,4,0,29,32,48,53,64,72,0,74,82,0,88,96,100,107,109,124,160,167
60140 data 170,190,0,0,201
60150 data 211 : rem buchstabe nach z !
60200 rem objekt-tabelle -------------
60210 oz=13:rem anzahl der objekte
60220 dim ob(oz),ox(oz),oa(oz),ou(oz),os(oz)
60230 fori=1tooz
60240 : readob(i),ox(i),oa(i),ou(i),os(i)
60250 nexti
60260 data 1,24 ,1,24 ,164:rem glaskuppel
60262 data 1,0  ,2,95 ,165:rem sand
60264 data 2,34 ,1,34 ,166:rem tunnel
60266 data 3,43 ,1,43 ,167:rem kr.grotte
60268 data 3,102,2,0  ,168:rem quader
60270 data 3,0  ,2,113,169:rem statue
60272 data 3,106,0,0  ,170:rem schwert
60274 data 0,0  ,3,79 ,171:rem zettel
60276 data 0,0  ,3,87 ,172:rem amulett
60278 data 0,76 ,2,91 ,173:rem grube
60279 data 0,161,2,0  ,174:rem oeffnung
60280 data 4,54 ,1,54 ,175:rem felsplat.
60282 data 3,0  ,2,97 ,176:rem kristalle
60500 rem landkarte ------------------
60501 :
60510 dim map(4,10)
60520 fori=1to4
60530 : fori1=1to10
60540 :   read map(i,i1)
60550 : nexti1
60560 nexti
60570 data 2,0,0,0,0,0,0,0,0,0
60572 data 3,1,0,0,0,0,0,0,0,0
60574 data 0,2,0,0,0,0,0,0,0,0
60576 data 0,0,0,3,0,0,0,0,0,0
60600 return
 60000 REM TABELLEN EINLESEN ---------------------------------------------------- 
 60001 : 
 60100 REM WORTSCHATZ-INDEX ----------- 
 60110 DIM IN(26) 
 60120 FOR I=0 TO26:READ IN(I):NEXT I 
 60130 DATA 1,4,0,29,32,48,53,64,72,0,74,82,0,88,96,100,107,109,124,160,167 
 60140 DATA 170,190,0,0,201 
 60150 DATA 211 : REM BUCHSTABE NACH Z ! 
 60200 REM OBJEKT-TABELLE ------------- 
 60210 OZ=13:REM ANZAHL DER OBJEKTE 
 60220 DIM OB(OZ),OX(OZ),OA(OZ),OU(OZ),OS(OZ) 
 60230 FOR I=1 TOOZ 
 60240 : READ OB(I),OX(I),OA(I),OU(I),OS(I) 
 60250 NEXT I 
 60260 DATA 1,24 ,1,24 ,164:REM GLASKUPPEL 
 60262 DATA 1,0  ,2,95 ,165:REM SAND 
 60264 DATA 2,34 ,1,34 ,166:REM TUNNEL 
 60266 DATA 3,43 ,1,43 ,167:REM KR.GROTTE 
 60268 DATA 3,102,2,0  ,168:REM QUADER 
 60270 DATA 3,0  ,2,113,169:REM STATUE 
 60272 DATA 3,106,0,0  ,170:REM SCHWERT 
 60274 DATA 0,0  ,3,79 ,171:REM ZETTEL 
 60276 DATA 0,0  ,3,87 ,172:REM AMULETT 
 60278 DATA 0,76 ,2,91 ,173:REM GRUBE 
 60279 DATA 0,161,2,0  ,174:REM OEFFNUNG 
 60280 DATA 4,54 ,1,54 ,175:REM FELSPLAT. 
 60282 DATA 3,0  ,2,97 ,176:REM KRISTALLE 
 60500 REM LANDKARTE ------------------ 
 60501 : 
 60510 DIM MAP(4,10) 
 60520 FOR I=1 TO4 
 60530 : FOR I1=1 TO10 
 60540 :   READ MAP(I,I1) 
 60550 : NEXT I1 
 60560 NEXT I 
 60570 DATA 2,0,0,0,0,0,0,0,0,0 
 60572 DATA 3,1,0,0,0,0,0,0,0,0 
 60574 DATA 0,2,0,0,0,0,0,0,0,0 
 60576 DATA 0,0,0,3,0,0,0,0,0,0 
 60600 RETURN 
Listing 2. Ergänzung zu Listing 1
|
800 rem lesen --------------------
805 ifve<>16then900
810 ifo1=8andob(8)=-1thensb=80
900 :
2000 rem raumspezifische action ------------------------------------------------
2010 on zn goto 2100,2200,2300,2400
2100 rem glaskuppel
2110 ifve<>15oro1<>2then2120
2115 ifpa(0)<3thensb=71:pa(0)=pa(0)+1
2117 ifpa(0)=2thensb=73:ob(8)=zn:ob(9)=zn:ob(10)=1
2119 ifpa(0)=3thensb=72
2120 ifve=1ando1=3thenri=1:goto300
2130 goto100
2200 rem tunnel
2210 goto100
2300 rem kristallgrotte
2305 ifve=17ando1=6andou(6)=113thensb=119:ou(6)=135:goto2307
2306 ifve=17ando1=6andou(6)=135thenprint"Es passiert nichts."
2307 ifve<>12oro1<>7then2310
2308 ifou(6)=113thensb=110
2309 ifou(6)=135thensb=139:oa(7)=3:ob(7)=-1:ob(11)=3:map(3,3)=4:ox(7)=0
2310 ifve=1ando1=3thenri=3:goto300
2320 goto100
2400 rem felsplateau
2410 goto100
 800 REM LESEN -------------------- 
 805 IF VE<>16 THEN900 
 810 IF O1=8AND OB(8)=-1 THENSB=80 
 900 : 
 2000 REM RAUMSPEZIFISCHE ACTION ------------------------------------------------ 
 2010 ON ZN GOTO 2100,2200,2300,2400 
 2100 REM GLASKUPPEL 
 2110 IF VE<>15OR O1<>2 THEN2120 
 2115 IF PA(0)<3 THENSB=71:PA(0)=PA(0)+1 
 2117 IF PA(0)=2 THENSB=73:OB(8)=ZN:OB(9)=ZN:OB(10)=1 
 2119 IF PA(0)=3 THENSB=72 
 2120 IF VE=1AND O1=3 THENRI=1:GOTO 300 
 2130 GOTO 100 
 2200 REM TUNNEL 
 2210 GOTO 100 
 2300 REM KRISTALLGROTTE 
 2305 IF VE=17AND O1=6AND OU(6)=113 THENSB=119:OU(6)=135:GOTO 2307 
 2306 IF VE=17AND O1=6AND OU(6)=135 THENPRINT"ES PASSIERT NICHTS." 
 2307 IF VE<>12OR O1<>7 THEN2310 
 2308 IF OU(6)=113 THENSB=110 
 2309 IF OU(6)=135 THENSB=139:OA(7)=3:OB(7)=-1:OB(11)=3:MAP(3,3)=4:OX(7)=0 
 2310 IF VE=1AND O1=3 THENRI=3:GOTO 300 
 2320 GOTO 100 
 2400 REM FELSPLATEAU 
 2410 GOTO 100 
Listing 3. Damit ist Gordon Saga II komplett
|
0 rem *******************************
1 rem *                             *
2 rem *    adventure-cracker        *
3 rem *      version 1.0            *
4 rem *   von mright$chael nickles  *
5 rem *                             *
6 rem *******************************
10 print"{clr}{rvon}adventure-cracker version 1.0           {rvof}";
20 print"{down}bitte disk mit spiel einlegen {rvon}return{rvof}"
25 poke198,0:wait198,1
30 open1,8,15:open2,8,2,"#"
50 rem hauptmenue
51 print"{rvon}einzel / alles"
52 getx$:ifx$=""then52
55 ifx$="e"then200
57 ifx$="a"then100
58 goto52
100 rem alle daten von disk lesen
105 input"ab welchem track ";an
110 for t=an to 35: rem tracks
112 rem as=anzahl der sektoren
113 if t<18        then as=21
114 if t>17andt<25 then as=19
115 if t>24andt<31 then as=18
116 if t>30        then as=17
118 for s=1 to as: rem sectors
120 gosub1000:rem daten in buffer lesen
130 gosub2000:rem daten ausdrucken
140 next s
150 next t
200 rem einzelne daten lesen
201 print
205 input"track ";t
206 input"sektor ";s
210 ift<1ort>35then200
211 ifs<1then200
212 ift<18ands>21then200
213 ift>17andt<25ands>19then200
214 ift>24andt<31ands>18then200
215 ift>30ands>17then200
220 gosub1000
230 gosub2000
250 goto200
1000 :
1001 rem daten in buffer lesen
1002 :
1005 print#1,"u1 2 0 ";t;s
1010 return
2000 :
2001 rem buffer auslesen
2002 :m$=""
2010 fori=0to255
2020 : get#2,a$
2021 ifa$=""then2030
2022 m=asc(a$) : rem checken
2023 ifm>64andm<91thenprinta$;
2024 ifm>96andm<123thenprinta$;
2030 ifm=46orm=58orm=59orm=63orm=32orm=160orval(a$)>0thenprinta$;
2040 nexti
2050 return
  0 REM ******************************* 
  1 REM *                             * 
  2 REM *    ADVENTURE-CRACKER        * 
  3 REM *      VERSION 1.0            * 
  4 REM *   VON MRIGHT$CHAEL NICKLES  * 
  5 REM *                             * 
  6 REM ******************************* 
 10 PRINT"{CLR,RVSON}ADVENTURE-CRACKER VERSION 1.0{11SPACE,RVOFF}"; 
 20 PRINT"{DOWN}BITTE DISK MIT SPIEL EINLEGEN{SPACE,RVSON}RETURN{RVOFF}" 
 25 POKE 198,0:WAIT 198,1 
 30 OPEN 1,8,15:OPEN 2,8,2,"#" 
 50 REM HAUPTMENUE 
 51 PRINT"{RVSON}EINZEL / ALLES" 
 52 GET X$:IF X$="" THEN52 
 55 IF X$="E" THEN200 
 57 IF X$="A" THEN100 
 58 GOTO 52 
 100 REM ALLE DATEN VON DISK LESEN 
 105 INPUT"AB WELCHEM TRACK ";AN 
 110 FOR T=AN  TO 35: REM TRACKS 
 112 REM AS=ANZAHL DER SEKTOREN 
 113 IF T<18         THEN AS=21 
 114 IF T>17AND T<25  THEN AS=19 
 115 IF T>24AND T<31  THEN AS=18 
 116 IF T>30         THEN AS=17 
 118 FOR S=1  TO AS: REM SECTORS 
 120 GOSUB 1000:REM DATEN IN BUFFER LESEN 
 130 GOSUB 2000:REM DATEN AUSDRUCKEN 
 140 NEXT S 
 150 NEXT T 
 200 REM EINZELNE DATEN LESEN 
 201 PRINT 
 205 INPUT"TRACK ";T 
 206 INPUT"SEKTOR ";S 
 210 IF T<1OR T>35 THEN200 
 211 IF S<1 THEN200 
 212 IF T<18AND S>21 THEN200 
 213 IF T>17AND T<25AND S>19 THEN200 
 214 IF T>24AND T<31AND S>18 THEN200 
 215 IF T>30AND S>17 THEN200 
 220 GOSUB 1000 
 230 GOSUB 2000 
 250 GOTO 200 
 1000 : 
 1001 REM DATEN IN BUFFER LESEN 
 1002 : 
 1005 PRINT#1,"U1 2 0 ";T;S 
 1010 RETURN 
 2000 : 
 2001 REM BUFFER AUSLESEN 
 2002 :M$="" 
 2010 FOR I=0 TO255 
 2020 : GET #2,A$ 
 2021 IF A$="" THEN2030 
 2022 M=ASC (A$) : REM CHECKEN 
 2023 IF M>64AND M<91 THENPRINTA$; 
 2024 IF M>96AND M<123 THENPRINTA$; 
 2030 IF M=46OR M=58OR M=59OR M=63OR M=32OR M=160OR VAL (A$)>0 THENPRINTA$; 
 2040 NEXT I 
 2050 RETURN 
Listing 4. Der Adventure-Cracker
PROGRAMM : MS             1400 16B0
-----------------------------------
1400 : A2 0F 20 C9 FF 20 FD AE   C1
1408 : 20 8A AD 20 F7 B7 A9 50   61
1410 : 20 D2 FF A9 08 20 D2 FF   9B
1418 : A5 14 20 D2 FF A5 15 20   EB
1420 : D2 FF A9 01 20 D2 FF 20   55
1428 : CC FF A2 08 20 C6 FF A2   1B
1430 : 00 20 CF FF 9D FA 04 C9   89
1438 : 0D F0 03 E8 D0 F3 E0 28   1C
1440 : D0 05 A9 00 9D FA 04 E8   91
1448 : A9 00 9D FA 04 20 CC FF   2C
1450 : A2 FF E8 BD FA 04 D0 FA   ED
1458 : CA BD FA 04 C9 0D F0 F8   FB
1460 : C9 2A F0 2F A2 00 BD FA   77
1468 : 04 F0 06 20 D2 FF E8 D0   DC
1470 : F5 A5 14 18 69 01 85 14   1D
1478 : A5 15 69 00 85 15 EE F9   B3
1480 : 04 AD F9 04 C9 16 D0 03   F0
1488 : 20 B9 04 A2 0F 20 C9 FF   F3
1490 : 4C 0E 04 A9 0D 9D FA 04   CB
1498 : E8 A9 00 9D FA 04 A2 00   63
14A0 : BD FA 04 F0 06 20 D2 FF   A6
14A8 : E8 D0 F5 EE F9 04 AD F9   BE
14B0 : 04 C9 16 D0 03 20 B9 04   59
14B8 : 60 A9 00 8D F9 04 A2 00   E9
14C0 : BD E5 04 F0 06 20 D2 FF   3C
14C8 : E8 D0 F5 A9 00 85 C6 A5   5D
14D0 : C6 F0 FC A2 00 BD F0 04   5B
14D8 : F0 06 20 D2 FF E8 D0 F5   A4
14E0 : A9 00 85 C6 60 12 5B 57   76
14E8 : 45 49 54 45 52 5D 92 00   EA
14F0 : 14 14 14 14 14 14 14 14   F0
14F8 : 00 00 00 00 00 00 00 00   F9
1500 : 00 00 00 00 00 00 00 00   01
1508 : 00 00 00 00 00 00 00 00   09
1510 : 00 00 00 00 00 00 00 00   11
1518 : 00 00 00 00 00 00 00 00   19
1520 : 00 00 00 00 00 00 00 00   21
1528 : A9 40 8D 04 D4 A9 0F 8D   C7
1530 : 18 D4 A2 1E A0 86 8E 00   97
1538 : D4 8C 01 D4 A2 00 A0 A0   1B
1540 : 8E 05 D4 8C 06 D4 A9 00   C5
1548 : 8D F9 04 A9 3E 20 D2 FF   38
1550 : A9 A4 20 D2 FF A9 00 8D   16
1558 : AF 06 A9 00 85 C6 A5 C6   27
1560 : F0 FC AD 77 02 A2 00 DD   1A
1568 : 5D 06 F0 08 E8 E0 52 D0   86
1570 : F6 4C 77 05 4C B5 05 C9   25
1578 : 0D D0 15 AD AF 06 F0 2F   36
1580 : A9 9D 20 D2 FF A9 20 20   68
1588 : D2 FF 20 F8 05 4C 08 06   60
1590 : C9 14 D0 1B AD AF 06 F0   4D
1598 : 16 A9 14 20 D2 FF 20 D2   DF
15A0 : FF A9 A4 20 D2 FF 20 F8   41
15A8 : 05 CE AF 06 4C 5A 05 20   AD
15B0 : 36 06 4C 5A 05 AC AF 06   C8
15B8 : C0 4D F0 36 AE AF 06 9D   DD
15C0 : B0 06 A9 9D 20 D2 FF BD   A5
15C8 : B0 06 20 D2 FF A9 A4 20   FE
15D0 : D2 FF EE AF 06 BD B0 06   70
15D8 : C9 22 D0 10 20 D2 FF A9   D4
15E0 : 14 20 D2 FF 20 D2 FF A9   A5
15E8 : A4 20 D2 FF 20 F8 05 4C   C7
15F0 : 5A 05 20 36 06 4C 5A 05   D2
15F8 : A9 41 8D 04 D4 A2 00 E8   5A
1600 : D0 FD A9 80 8D 04 D4 60   56
1608 : A9 00 85 C6 20 FD AE AD   F3
1610 : AF 06 20 7D B4 A0 00 B9   3E
1618 : B0 06 91 62 C8 CC AF 06   3A
1620 : D0 F5 20 8B B0 85 FB 84   94
1628 : FC A2 02 A0 02 B5 61 91   80
1630 : FB CA 88 10 F8 60 A2 0A   E6
1638 : 8E 00 D4 8E 01 D4 A9 21   6D
1640 : 8D 04 D4 A2 B0 A0 00 C8   FA
1648 : D0 FD E8 D0 F8 A9 80 8D   65
1650 : 04 D4 A6 1E A4 86 8E 00   E4
1658 : D4 8C 01 D4 60 41 42 43   ED
1660 : 44 45 46 47 48 49 4A 4B   50
1668 : 4C 4D 4E 4F 50 51 52 53   58
1670 : 54 55 56 57 58 59 5A 30   09
1678 : 31 32 33 34 35 36 37 38   68
1680 : 39 2C 2E 20 21 23 24 25   65
1688 : 26 27 28 29 2B 2D 3A 3B   ED
1690 : 2F 3F 40 2A 22 C1 C2 C3   77
1698 : C4 C5 C6 C7 C8 C9 CA CB   87
16A0 : CC CD CE CF D0 D1 D2 D3   8F
16A8 : D4 D5 D6 D7 D8 D9 DA 00   DF
Listing 5. Einige nützliche Hilfsroutinen. Beachten Sie die Hinweise im Text.
|
10 open 1,8,0,"ms":get#1,a$:get#1,a$
20 fori=1024to1718:get#1,a$:a$=a$+chr$(0):pokei,asc(a$):nexti:close1
 10 OPEN 1,8,0,"MS":GET #1,A$:GET #1,A$ 
 20 FOR I=1024 TO1718:GET #1,A$:A$=A$+CHR$ (0):POKE I,ASC (A$):NEXT I:CLOSE 1 
Listing 6. Lader für Listing 5
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →