move() ====== Moechte ein Objekt sich selbst bewegen oder sich von anderen bewegen lassen, so muss es folgende Funktion aufrufen: ------------------------------------------------------------------------ varargs int move(mixed ziel, int wie, string verlassen, string ankommen) ------------------------------------------------------------------------ die von allen bewegbaren Objekten mittels inherit "/i/move"; inheritet werden muss. mixed ziel: ----------- Als Ziel wird eines von folgenden Typen aktzeptiert: - object raum Ein Objektpointer auf das Objekt in das dieses gemoved werden soll. OBJ("/room/church") - string Richtung Ein Richtung, in die das Objekt den Raum in dem es sich befindet, verlassen soll. "norden", "osten",... - string Filename eines Raums Der Filename des Objekts, in das dieses Objekt gemoved werden soll. "/room/church" int wie: -------- Es wird zwischen folgenden Bewegungs-Arten unterschieden: wie = MOVE_NORMAL Normale Bewegung. Es werden Bewegungsmeldungen ausgegeben. Das bewegt Objekt bekommt auch davon mit. Beispiel: Spielerbewegung wie = MOVE_MAGIC Magische Bewegung. Es werden die Bewegungsmeldungen fuer magische Bewegungen ausgegeben, sonst wie MOVE_NORMAL. Beispiel: Teleport-Faehigkeiten der Goetter wie = MOVE_SECRET Geheime Bewegung. Niemand soll etwas davon mitbekommen, nicht einmal das bewegte Objekt selbst. (D.h. just_moved() wird nicht aufgerufen.) Beispiel: in Befehl der Goetter. wie = 0 Erweiterte geheime Bewegung; Nur das bewegte Objekt bekommt eine Mitteilung. Es werden keine Bewegungsmeldungen ausgegeben. (D.h. just_moved() wird aufgerufen.) Beispiel: Fast alle Objekte werden so ins Spiel gebracht. Die Konstanten MOVE_NORMAL, MOVE_MAGIC und MOVE_SECRET sind im Include-File /sys/move.h definiert. string ankommen: string verlassen: ----------------- Hiermit koennen (muessen aber nicht) dem move explizite Regeln fuer die Bewegungsmeldungen uebergeben werden, die dann alle anderen (die des Objekts und die des Raumes) ueberlagern. Zu den Bewegungsmeldungen siehe unten. Voreinstellungen: ----------------- ziel : keine, muss angegeben werden. wie : 0 verlassen : "" ankommen : "" Returncodes: ------------ move() gibt folgende der im Include-File /sys/move.h definierten Werte zurueck: MOVE_NOT_ALLOWED Bewegung nicht erlaubt. MOVE_OK Bewegung erfolgreich. MOVE_NO_ROOM Nicht genuegend Platz im Ziel. MOVE_DEST_CLOSED Ziel ist geschlossen. (siehe /i/contain) MOVE_ENV_CLOSED Umgebung ist geschlossen. (siehe /i/contain) MOVE_NO_DEST Ziel exsistiert nicht. Funktionsweise: --------------- - Als erstes versucht move() aus dem uebergebenen Parameter 'ziel' den Raum zu bestimmen, in den das Objekt bewegt werden soll. Kann dieser nicht gefunden/geladen werden so bricht move() ab und liefert MOVE_NO_DEST zurueck. - Nach dem ERSTEN move-Aufruf wird gespeichert, wo sich das Objekt momentan befindet, um somit rauszubekommen wo ein Objekt das erste mal Hinbewegt wurde. Auf diese Weise koennen Fehler leichter gefunden werden. Abfrage geht mit query_first_room() - In lebende Objekte darf man sich nicht als lebendes Objekt hineinbewegen. -> Abbruch des move(), return wert MOVE_NOT_ALLOWED - Das Gewicht des Objekts wird im Zielraum dazuaddiert, schlaegt das fehl, weil der Raum voll ist, so wird der move() abgebrochen und MOVE_NO_ROOM zurueckgeliefert. - Im Ursprungsraum wird die Funktion int let_not_out(object zubewegendes_obj, object zielraum, string dir) aufgerufen. Liefert diese Funktion einen Wert ungleich 0, so ist die Bewegung verboten. (Unsichtbare Goetter duerfen trotzdem raus.) Anmerkung: Damit ist auch die filter_ Sache im Raum realisiert. - Im Zielraum wird die Funktion int let_not_in(object zubewegendes_obj, object ursprungsraum, string dir) aufgerufen. Liefert diese Funktion einen Wert ungleich 0, so ist die Bewegung verboten. (Unsichtbare Goetter duerfen trotzdem rein.) - Im Ursprungsraum wird das Gewicht des Objekts abgezogen. - Wenn 'wie' entsprechend gesetzt ist wird jetzt im Ursprungsraum eine Bewegungsmeldung ausgegeben. Diese haengt vom explizit ueber- gebenen string 'verlassen', von den eingestellten Bewegungsmeldungen des Objekts und des Ursprungsraums ab. Naeheres siehe unten. - Jetzt erfolgt die eigentliche Bewegung ueber den efun-call move_object(). move_object() kann nur von move() aufgerufen werden. - Wenn 'wie' entsprechend gesetzt ist wird jetzt im Zielraum eine Bewegungsmeldung ausgegeben. Diese haengt vom explizit ueber- gebenen string 'verlassen', von den eingestellten Bewegungsmeldungen des Objekts und des Ursprungsraums ab. - Objekte mit der Eigenschaft sichtbar zu werden, nach dem naechten move, werden jetzt sichtbar. (set_hidden_until_next_move) - Jetzt wird im Ursprungsraum die Funktion void moved_out(object bewegtes_obj, object wohin) aufgerufen. - Wenn 'wie' entsprechend gesetzt ist (alles ausser wie = MOVE_SECRET) wird im bewegten Objekt die Funktion void just_moved() aufgerufen. - Im Zielraum wird entsprechend die Funktion void moved_in(object bewegtes_obj, object woher) aufgerufen. - In jedem Objekt, das als Follower im bewegten Objekt eingetragen wurde (siehe add_follower()), wird jetzt die Funktion notify_follow(object bewegtes_obj, object Ursprungsraum, object Zielraum, string Richtung, int wie, string verlassen, string ankommen) aufgerufen. - Da offensichtlich alles geklappt hat, wenn die Funktion hier ankommt, wird MOVE_OK zurueckgeliefert. Das war's. Gewicht ======= Jedes bewegbare Objekt sollte ein Gewicht haben. void set_weight(int gewicht) Setzt das Gewicht diese Objektes. Voreinstellung: 1 int query_weight() Liefert das Gwicht dieses Objektes zurueck. Jedes Objekt, dass ein Gewicht hat, addiert bei Betreten oder subtrahiert beim Verlassen einer Umgebung sein eigenes Gewicht in der Encumbrance der Umgebung (siehe /i/contain). remove() ======== Grundsaetzlich sollten Objekte nicht mit destruct(..) beseitigt werden, sondern mit der Funktion remove(). Programmierer koennen dann noch Aktionen (Schatten zerstoeren, Variablen setzen etc) durchfuehren. Damit jedes Objekt mit remove() zerstoert werden kann, ist hier eine "Default"-Routine definiert, die ein einfaches destruct(..) enthaelt, aber jederzeit ueberlagert werden kann. Bewegungsmeldungen ================== Alle Objekte, die an der Bewegung beteiligt sind sollten eine Moeglichkeit haben, die Bewegungsmeldungen zu beinflussen. Bislang werden allerdings nur das bewegte Objekt und der Ursprungs- raum zur Erstellung der Bewegungsmeldungen herangezogen. Der Zielraum bleibt unberuecksichtigt. Die Bewegungsmeldung beim Betreten eines Raumes haengt nur vom Usprungsraum und vom bewegten Objekt ab. Um maximale Flexibilitaet zu ereichen wird folgende Hierarchie benutzt: - Zuerst werden die expliziten Parameter beim Aufruf von move() abgefragt. (verlassen, ankommen) Sind sie ungleich Null so werden sie verwendet. - Jetzt wird im bewegten Objekt gefragt, ob es Bewegungsmeldungen gesetzt hat, die unabhaengig vom Raum immer verwendet werden sollen (Pflichtmeldungen) - Sind keine solchen gesetzt, wird der Raum abgefragt. Sind fuer den speziellen Ausgang Bewegungsmeldungen gesetzt, so werden diese benutzt, ansonsten Defaultmeldungen des Raums. - Liefert der Raum keine Bewegungsmeldungen, wird nochmals das bewegte Objekt befragt, ob es Meldungen gesetzt hat (also keine Pflichtmeldungen). - Hat auch das Objekt keine Meldung auf Lager, so wird eine Defaultmeldung von move() generiert. Zum Setzen und Abfragen der Bewegungsmeldungen werden nun im Objekt und im Raum zahlreiche Bewegungsmeldungen zur Verfuegung gestellt. Die meisten setzten eine 'Regel' zur Erstellung der Bewegungsmeldung: Eine Regel hat folgende Form: "... $Der() ...beliebiger Text... $dir() ... " Die Symbole $Der(), $der(), $Ein(), $ein() werden vom move() durch die entsprechenden Grammatikaufrufe ersetzt. $dir() bzw. $Dir() wird durch die Richtung der Bewegung ersetzt. Beispiel: $Der() ==> "Garthan" $dir() ==> "nach Osten" Die Regel "$Der() hopst $dir() davon." ergibt dann: "Garthan hopst nach Osten davon.\n" Folgende Funktionen gibt es zu den Bewegungsmeldungen in jedem bewegbaren Objekt: (Sie werden hier in /i/move definiert.) Zum Setzen: (im OBJEKT) ----------- void set_msg_out (string verlassen_regel); void set_msg_in (string ankommen_regel); void set_mmsg_out(string magisch_verlassen_regel); void set_mmsg_in (string magisch_ankommen_regel); Bei den letzten zwei wird $dir() bzw. $Dir() immer zu einem Leerstring expandiert, da bei magischen Bewegungen keine Richtung definiert ist. Die ankommen_regeln beziehen sich IMMER auf das Ankommen im ZIELraum, nicht im Ursprungsraum! set_msg(string verlassen_regel, string ankommen_regel, int pflichtmeldung); set_mmsg(string magisch_verlassen_regel, string magisch_ankommen_regel); Die letzten zwei sind Kombinationsfunktionen der obigen vier. Bei set_msg kann mitangegeben werden ob die Regel zur Pflichtregel wird, und auf jeden Fall den Raummeldungen vorgezogen wird. Zum Abfragen der Regeln: (im OBJEKT) ------------------------ string query_msg_in(); string query_msg_out(); string query_mmsg_in(); string query_mmsg_out(); Zum Abfragen der precompilierten Regeln (zum Abfragen der Closures): -------------------------------------------------------------------- (im OBJEKT) closure query_c_msg_in(); closure query_c_msg_out(); closure query_c_mmsg_in(); closure query_c_mmsg_out(); Zum Abfragen der expandierten Bewegungsmeldungen: (im OBJEKT) ------------------------------------------------- varargs string query_exp_msg_out(string dir); varargs string query_exp_msg_in(string dir); varargs string query_exp_mmsg_out(string dir); varargs string query_exp_mmsg_in(string dir); wobei man hier den Richtungsstring selbst uebergeben kann ("nach Osten") Und jetzt die Funktionen im RAUM: Zum Setzen der Defaultraummessage im RAUM: ------------------------------------------- void set_msg_out(string verlassen_regel); void set_msg_in(string ankommen_regel); set_msg(string verlassen_regel, string ankommen_regel); Die ankommen_regel bezieht sich IMMER auf das Ankommen im ZIELraum, nicht im Ursprungsraum! Zum Setzen einer speziellen Meldung fuer einen speziellen Ausgang im RAUM: -------------------------------------------------------------------------- void set_exit_msg(string ausgangs_kommando, string verlassen_regel, string ankommen_regel); ausgangs_kommando ist dann der Befehl mit dem man den Raum regulaer verlaesst ( "norden", ... ) Richtungsmeldungen ------------------ In der Regel erzeugt entweder der Raum oder das zu bewegende Objekt die Richtungsmeldungen ("nach Osten", "von unten", ...), die dann vom move() in den Regeln fuer $dir() und $Dir() eingesetzt werden. Fuer gewoehnliche Richtungsmeldungen nimmt einem der move() die Arbeit ab. (alle Himmelsrichtungen und oben/unten/links/rechts) Will man aber fuer einen bestimmten Ausgang eine bestimmte Richtungs- meldung setzten so verwendet man im RAUM: set_dir_msg(string ausgangs_kommando, string richtung_raus, string richtung_rein); Fuer ganz abgefahrene Situationen kann man auch noch die Praepositionen aendern, die bei Standardrichtungsmeldungen verwendet werden (normalerweise "nach" und "von"). Das geschieht im Raum fuer alle Raumausgaenge mit: void set_dir_prep(string praep_raus, string praep_rein) oder einzeln: void set_dir_prep_in(string praep_rein); void set_dir_prep_out(string praep_raus); und abzufragen mit: string query_dir_prep_in(); string query_dir_prep_out(); FOLLOWERS ========= Followes sind Objekte, die jeden move eines anderen mitbekommen, in dem sich bei diesem mit add_follower(object verfolger); als Verfolger anmelden. Bei jeder Bewegung des Verfolgten wird dann im Verfolger die Funktion notify_follow(...) aufgerufen. (siehe oben) Abmelden kann man sich der Verfolger wieder mit delete_follower(object verfolger); SET_NO_MOVE =========== Mit der Funktion set_no_move(1) koennen Objekte quasi installiert werden, dass heisst sie koennen sich danach nicht mehr bewegen. Mit set_no_move(0) koennen sie wieder bewegbar gemacht werden. Letzeres funktioniert nicht mit echten "install"ed Objekten, diese sollen ja NIE bewegt werden.