Floyd: Quelltext
So sieht der Quelltext des kleinen Jade-Adventures in Floyd aus. Wenn man mit der Maus über die rot markierten Details fährt, oder sich mit der Tabulatortaste durch den Quelltext bewegt, werden nährere Informationen angezeigt.
Alles, was zwischen /*
und */
steht, ist ein Kommentar und wird von Floyd nicht beachtet. Außerdem ignoriert Floyd alles, was nach //
auf einer Zeile steht. (Das ist der C++/Java-Kommentarstil)
Mit #include
werden andere Floyd-Dateien eingebunden.
Die Standard-Bibliothek besteht aus acht Dateien, die zu Beginn des Quelltexts eingebunden werden sollten.
Eine Klasse ist eine Instanz eines Objekts im Spiel, ob es ein Gegenstand, ein Raum, eine Person oder vielleicht nur ein Konzept ist.
Der Spieler ist nicht vordefiniert. Man muss eine stdcreature
definieren, die man dann in main
der Variable player
zuweist. Auch die Pronomen »mich«, »mir« müssen explizit bei der Spielerklasse angegeben werden.
Nach dem Namen einer Klasse kann man eine Über- oder Superklase angeben, von der die Klase alle Eigenschaften "erbt". Personen im Spiel, also auch der Spieler selbst, sind Instanzen der Superklasse stdcreature
oder deren Unterklassen.
Das Schlüsselwort void
kennzeichnet eine Funktion, die keinen Wert zurückgibt.
Die Funktion main
wird als erstes aufgerufen. Hier können Dinge, zum Beispiel der Spieler, initialisiert werden. Außerdem kann man hier einen Einleitungstext angeben.
Mit write
kann man einen Text ausgeben.
Texte stehen in Floyd in doppelten Anführungszeichen.
Ein Zeilenumbruch wird in Floyd mit einem Dach gekennzeichnet. Zwei Dächer kennzeichnen einen Absatz mit nachfolgender Leerzeile.
Die Variable player
bezeichnet das Spielerobkejt. Sie kann mit setPlayer
gesetzt werden.
Jede Klasse, die ein Objekt im Spiel repräsentiert, sollte dessen Anfangsort mit der Methode moveto
definieren.
Nach dem Namen einer Klasse kann man eine Über- oder Superklase angeben, von der die Klase alle Eigenschaften "erbt". Räume im Spiel sind Instanzen der Superklasse stdroom
oder deren Unterklassen.
Mit setShort
definiert man den Namen des Objekts im Spiel und das Vokabular, mit dem man das Objekt ansprechen kann. Räume haben kein Vokabular.
Die Methode description
eines Raums gibt die Raumbeschreibung aus. Besonderheiten wie Objekte, die zu Beginn eine andere Beschreibung haben oder Behälter müssen hier explizit behandelt werden. Außerdem muss in main
die Beschreibung des ersten Raums ausdrücklich ausgegeben werden.
Der Datentyp string
kennzeichnet eine Text, der dann mit write
ausgegeben werden kann.
Mit der Methode has
kann man prüfen, ob ein Objekt ein Attribut besitzt oder nicht.
Texte können mit +
verkettet werden. Außerdem kennt Floyd die Notation +=
, die einen Text an einen anderen anhängt: s += x
ist dasselbe wie s = s + x
.
Die lange Beschreibung wird in der Raum- oder Objektbeschreibung description
verwendet.
Mit der Methode super
erhält man die Superklasse einer Klasse. In Methoden m
, die nicht ersetzt, sondern nur erweitert werden, muss super.m()
explizit ausfgerufen werden.
Die Methode init
wird für jede Klasse zu Beginn des Spiels aufgerufen.
Mit addExit
kann man in init
(oder später) Verbindungen zu anderen Räumen definieren, die von stdexit
abgeleitet werden. Solche Verbindungen sind symmetrisch: Geht's von A Richtung Norden nach B, so geht es automatisch von B Richtung Süden wieder nach A.
Die Richtungen in Floyd werden durch Konstanten angegeben.
Die Methode goto
eines Raumes wird aufgerufen, wenn der Spieler aus diesem Raum in die angegebene Richtung geht.
Der Datentyp int
(integer) bezeichnet eine ganze Zahl.
Ein Objekt ist eine Variable, die entweder eine Klasse beschreibt oder den Wert NULL
hat.
Zwei Gleichzeichen ==
prüfen werte auf Gleichheit - nicht zu ferwechseln mit dem Zuweisungsoperator =
, der nur aus ein Gleichzeichen besteht.
Die Methode in
prüft, ob eine Klasse in einer anderen ist, ob sie also mit moveto
in diese Klasse bewegt wurde.
Die Anweisung quit
bericht das Spiel ab. Der Ausgang des Spiels muss explizit angegeben werden.
Mit dem Schglüsselwort with
setzt man ein Attribut.
Das Attribut linefeed
bewirkt in Räumne, dass zwiachen Beschreibung und Liste der Gegenstände eine Leerzeile eingefügt wird.
Gegenstände im Spiel haben die Superklasse stditem
.
Die kurze Beschreibung kennzeichnet den Namen eines Gegenstand und die Wörter, die der Spieler eingeben kann, um sich auf diesen Gegenstand zu beziehen. Der Genus wird durch ein vorangestelltes Sonderzeichen festgelegt: Plus bedeutet männlich, minus weiblich und ein Und-Zeichen kennzeichnet den Plural. Namen ohne Sonderzeichen sind sächlich.
In Namen kennzeichnet ein Stern die Endung für Adjektive, die dann gebeugt ausgegeben wird.
Das Attribut takeable
kennzeichnet Klassen, die aufgehoben werden können.
Die Variable action
zeigt an, welche Aktion der Spieler ausführt. Die Aktionen sind Konstanten, die mit A_
beginnen.
Zwei Und-Zeichen verknüpfen zwei Bedigungen so, dass das Ergebnis nur wahr ist, wenn beide Bedingungen wahr sind. Eine Oder-Veknüpfung wird mit zwei senkrechten Strichen ||
angegeben.
In with
können mit vorangestellter Tilde Attribite gelöscht werden.
In Namen können mehrere Synonyme durch Kommas getrennt angegeben werden.
Mit objectsInside
kann man prüfen, wieviele Objekte in einem Raum oder Behälter sind.
Die Funktion strLongList
erzeugt einen Text (string
), der eine Liste der Objekte in einem Raum oder Behälter anzeigt.
Die Liste wird in einem der vier Fälle ausgegeben, hier im Akkusativ (C_ACC
).
Mit der Methode onAction
kann man in jeder Klasse das übliche Verhalten überschreiben.
Mit switch
und case
kann eine Variable auf viele Werte geprüft werden.
Die momentan betrachtete Klasse kann über das Schlüsselwort this
angesprochen werden. Wenn es eindeutig ist, kann this
weggelassen werden: in(a)
ist äquivalent zu this.in(a)
.
/* =========================================================== Die Jadestatue Eine interaktives Exempel, Martin Oehm, 22.06.2003 Die Floyd-Version des Jadestatuen-Beispiels. =========================================================== */ #include <stdconst.floyd> #include <stdlist.floyd> #include <stdobject.floyd> #include <stdcreature.floyd> #include <stdroom.floyd> #include <stditem.floyd> #include <stdexit.floyd> #include <stderror.floyd> class spieler:stdcreature { setShort("mich,mir,dich,dir"); setLong("Abenteuerlustig und gutaussehend.^"); } void main() { write("Endlich! Nach tagelangem Suchen im Dschungel stößt du auf eine Lichtung. Und auf etwas mehr. Vielleicht ist dies der Ort, an dem sich die Jadestatue befindet?^^"); write("DIE JADESTATUE^"); write("Ein interaktives Exempel von Martin Oehm^^"); setPlayer(spieler); spieler.moveto(Lichtung); Lichtung.description(); } class Lichtung:stdroom { setShort("Lichtung im Dschungel"); void description() { string desc = "Du stehst auf einer Lichtung im dichten Dschungel. Im Norden steht ein alter, von Ranken überzogener Schrein. Im Süden führt ein schmaler Pfad zurück in die Zivilisation.^"; if (Stein.has(hidden)) { desc += "^In der Nähe des Schreins liegt ein glatter, runder Stein im Gras.^"; } setLong(desc); super.description(); } void init() { addExit(D_NORTH, Im_Schrein, Lichtung_Schrein); } void goto(int dir, object item) { if (dir==D_SOUTH) { if (Jadestatue.in(spieler)) { write("Du schaffst es, mit der Statue wieder zurück in die Zivilisation zu gelangen.^^"); write("*** Du hast gewonnen ***^^"); quit; } else { write("Nicht ohne die Statue!^"); } } else { if (exits[dir]==NULL) { write("Dort ist der Dschungel zu dicht, es gibt keinen Pfad in diese Richtung.^"); } else { super.goto(dir, item); } } } with(linefeed); } class Lichtung_Schrein: stdexit { with(hidden); } class Stein:stditem { setShort("+faustgroß* Stein"); setLong("Der Stein ist so groß wie eine Faust und außergewöhnlich glatt und rund.^"); moveto(Lichtung); with(hidden, takeable); int onAction(int action) { int r = super.onAction(action); if (action == A_TAKE && this.in(player)) { this.with(~hidden); } return(r); } } class Schrein:stditem { setShort("+alt Schrein,+Toltekenschrein,+Efeu,&Ranken"); setLong("Der alte Toltekenschrein ist fast komplett mit Efeu überwuchert.^"); } class Im_Schrein:stdroom { setShort("Im Schrein"); void description() { string s = "In dem kleinen Schrein ist es dunkel, nur wenig Licht fällt durch das halb verfallene Dach. Ein großer Lichtstrahl fällt auf eine Steinsäule in der Mitte des Schreins.^ ^Die Lichtung liegt im Süden.^"; int n = objectsInside(Saeule); if (n > 0) { s += "^Auf der Säule siehst du "; s += strLongList(Saeule, C_ACC); s += "^"; } setLong(s); super.description(); } with(linefeed); } class Saeule:stditem { setShort("-Steinsäule,-Säule,Podest"); setLong("Die Säule ist aus glattem Stein gehauen, etwas mehr als einen Meter hoch und oben flach, wie ein Podest.^"); moveto(Im_Schrein); with(hidden, supporter, transparent, open); } class Jadestatue:stditem { setShort("-Jadestatue,-Jadefigur,-Figur,-Statue"); setLong("Es ist die Statue einer toltekischen Gottheit, komplett aus grüner Jade geschnitzt. Sie glänzt und sieht sehr wertvoll aus.^"); int onAction(int action) { switch (action) { case(A_TAKE); if (in(Saeule) && !(Stein.in(Saeule))) { write("Als du das Gewicht der Statue von der Säule nimmst, hörst Du ein klickendes Geräusch. Kurz darauf wirst du von Giftpfeilen durchbohrt.^^"); write("*** Du bist jetzt tot. ***^^"); quit; } } return(super.onAction(action)); } moveto(Saeule); with(takeable); }