Adventure-Programmierung -------------------------- Teil 2 von Tim-Philipp Müller Diesmal soll sich alles um den Kern eines jeden Adventures drehen, den so gennannten 'Parser'. 'To parse a sentence' bedeutet, einen Satz in seine einzelnen Bestandteile, Wörter, zu zerlegen und diese grammati- kalisch zuzuordnen. Ein Parser analysiert also die Eingabe unseres Abenteurers und teilt dem Programm mit, was gemeint ist. Damit unser Parser Wörter erkennen und klassifizieren kann, muß er aber erst- mal wissen, was die Wörter eigentlich sind. Man muß also einen Wortschatz definie- ren, und zwar getrennt nach Verben, Objekten, Präpositionen, benötigten Adjektiven (z.B. zur Unterscheidung von roten und grünen Steinen) und notwendi- gen Adverbialien (z.B. schnell). Jedem Wortg wird dabei eine eigene Nummer zugewiesen, Wörter mit gleicher Bedeutung erhalten natürlich auch die gleichen Nummern. Der Aufbau solcher Wortschatz-Dateien könnte z.B. folgendermaßen aussehen: 001:nimm,grabsche,sammle-auf,stecke- ein,nehme 002:lege,wirf-weg,werfe-weg,laß-fallen. Am Anfang einer Zeile der Code mit Doppelpunkt (optimiert stünde an erster Stelle nur ein Byte, daß den jeweiligen Wert hat), danach alle Wörter dieser Bedeutung durch Kommata getrennt, am Ende der Bedeutung ein Semikolon, ein Punkt, wenn es sich um das Ende des Files handelt. 'Warum die Trennstriche ?', werden Sie sich jetzt bestimmt Fragen. Dazu ein kleines Beispiel: ZIEHE DICH AUS ZIEHE DEN MANN AUS DEM TREIBSAND Im ersten Beispiel steht das 'AUS' ohne Objekt, im zweiten mit. Eine schlaue Parse-Routine findet oben die Bedeutung 'ZIEHE-AUS' heraus, unten 'ZIEHE', wobei als Präposition 'AUS' und als Objekt dazu 'TREIBSAND' vermerkt wird. Aber mehr dazu später. Zuerst muß man sich also klarmachen, woraus der eingegebene Satz denn so be- stehen könnte: NIMM SCHNELL DIE ROTE FLASCHE AUS DEM OBEREN SCHRANK Jetzt werden erstmal die Wörter gezählt und Indices auf die einzelnen Wörter errechnet (also 0,5,13...). Bestimmte und unbestimmte Artikel wie der,die,das,dem, ein, usw. werden ohne Überprüfung einfach entfernt. Das Prädikat wird immer im Imperativ erwartet. Das hat auch gleich zwei Vor- teile, nämlich daß es immer am Satz- anfang steht und, daß der Imperativ am wenigsten Speicherplatz frißt, weil er die kürzeste Verbform ist. Als nächstes wird der Satz nach Prä- positionen durchforstet (in,auf...) und geprüft, ob sie, wenn überhaupt vorhan- den, als letztes Wort des Satzes steht. Wenn ja, gehört die Präposition als Präfix zum Verb (siehe die zwei Beispiele oben). Wenn nein, handelt es sich -wer hätte es gedacht- um eine echte Präposition! Nun ist die Frage, wieviele Wörter zwischen Prädikat und Präposition stehen (die Artikel wurden vorher weg- gekürzt). Wir erinnern uns an unser Beispiel: NIMM SCHNELL (DIE) ROTE FLASCHE AUS ... Handelt es sich nur um ein oder zwei Wörter, ist der Fall klar: das Wort vor der Präposition ist ein Objekt, das eventuell noch mit einem Adjektiv steht. Befindet sich dieses nicht im hiesigen Wortschatz, wird es schlicht und einfach ignoriert. Verzwickter wird das Ganze bei drei Wörtern: Denn ich hätte ja genauso gut NIMM (DIE) ROTE FLASCHE SCHNELL AUS ... eintippen können. Unser Sprachgefühl (äh) sagt uns natürlich, daß die erste Möglichkeit viel wahscheinlicher ist, weshalb wir auch annehmen, daß es sich bei dem ERSTEN Wort (dieser drei) um ein Adverb handelt, beim zweiten um ein Adjektiv und beim dritten um das Objekt. Ist das Adverb nicht im Wortschatz, ignorieren wir das einfach wieder. Last but not least muß ein evtl. noch hinter der Präposition vorhandener Ausdruck geprüft werden, wobei es sich eigentlich nur um ein Objekt mit oder ohne Adjektiv handeln kann. Das hört sich jetzt alles ziemlich kompliziert an, ist aber gar nicht sooo schwer zu programmieren, wenn man der eigentlichen Parse-Routine die Arbeit erleichtert, indem man angibt, wieviele Adjektive, Objekte, etc. vorhanden sind und wo diese sind. Auch sehr wichtig sind natürlich die Ein-Wort-Befehle wie Himmelsrichtungen, Inventar, etc.. Tja, und was nun, wenn die Anweisungen des Abenteurers alle schön kodiert und 'zerhackstückelt' wurden ? Dann ruft man die entsprechenden Sub- Programmme zur Bearbeitung auf. Dies erfolgt meist durch das Prädikat, was also eine eigene Routine für jedes Verb bedeutet. Dort muß man nun individuell entschei- den, wie eine weitere Einteilung am sinnvollsten ist - durch die Raumnummer oder durch das Objekt. Ich persönlich würde mich weiter am Objekt orientieren, der Übersicht halber, und, da globale Operationen leichter von welchen, die nur in bestimmten Räumen stattfinden dürden, zu trennen sind. Erst nach dieser Klassifizierung können die Routinen noch zusätzliche Wörter abfragen und bewerten (Adjektive und präpositionale Ausdrücke, etc.) Eine letzte Frage bleibt natürlich noch offen: Die Programmiersprache. Allen, die es können, würde ich wirk- lich zu Assembler raten, nicht nur wegen der Geschwindigkeit, sondern auch, weil man die Ressourcen einfacher verwalten kann, nämlich über direkten Speicherzugriff. In QUICK ist dies mit Sicherheit etwas umständlicher, obwohl die Subroutines bestimmt übersichtlicher werden, und ACTION! hat ja fast keiner mehr... Was die Unterprogramme machen und wie man mit den Objekten umgeht - das kommt nächstes Mal ... Bis dann! Da jeder den Parser auf seine eigenen Belange zuschneiden sollte, habe ich diesmal kein Beispielprogramm dabei, EURE Umsetzung wäre aber bestimmt auch für andere Leser interessant...