Added public files
Roughly added all public files. Probably missed some, though.
diff --git a/doc/beispiele/AddCmd/Einfuehrung.AddCmd.txt b/doc/beispiele/AddCmd/Einfuehrung.AddCmd.txt
new file mode 100644
index 0000000..eadf6f9
--- /dev/null
+++ b/doc/beispiele/AddCmd/Einfuehrung.AddCmd.txt
@@ -0,0 +1,174 @@
+Hallo MitmagierInnen *g*,
+
+Ok, dann gehts mal ein bischen zur Sache:
+
+/std/thing/commands.c wurde so erweitert, dass man auch komplexe Syntax
+direkt im AddCmd vorparsen kann.
+
+Dazu ein kurzes Beispiel:
+-------------------------
+
+In einem Objekt (ein Busch) findet sich folgende Syntaxdefinition.
+
+ AddCmd("pfluecke|ernte&fruechte|beeren&@ID","cmd_pfluecken",
+ "Was willst Du denn @verben?|Wo willst Du denn die Beeren @verben?");
+
+Der erste Parameter definiert die Syntax. Das Zeichen & trennt verschiedene
+zu parsende Items:
+
+1. pfluecke|ernte
+2. fruechte|beeren
+3. @ID
+
+Unter 1. finden sich die Verben - das sind die gleichen, die man in der
+alten Version auch belegen konnte. Die Regel reagiert also auf "pfluecke"
+oder auf "ernte".
+
+Alle weiteren Regeln muessen erfuellt werden, damit der zweite Parameter
+(die Funktion) aufgerufen wird. @ID steht dabei fuer die ID des Objektes,
+in dem das AddCmd steht. Hier also der Busch.
+
+Dazu einige Beispiele:
+
+a) > pfluecke beeren
+ -> erfuellt 1 und 2. Aber nicht 3. => Fehlermeldung.
+
+b) > ernte von busch
+ -> erfuellt 1 und 3, jedoch 2 nicht. => Fehlermeldung.
+
+c) > pfluecke fruechte von busch
+ -> erfuellt 1, 2 und 3 -> busch->cmd_pfluecken() wird aufgerufen. Das "von"
+ ist Fuellwerk. Davon kann beliebig viel im String sein. Sie werden
+ ignoriert.
+ Es sind also auch unsinnige Syntaxe richtig, solange der String die
+ Items erufellt.
+
+Im Fall c) wird das Verhalten des Busches durch die Funktion "cmd_pfluecken"
+definiert, wie auch in der alten Version von AddCmd.
+
+Was passiert aber in den Faellen a) und b)? Dafuer ist der dritte
+Parameter da:
+ "Was willst Du denn @VERBen?|Wo willst Du denn die Beeren @VERBen?");
+
+Hier sind zwei Fehlermeldungen, durch | getrennt, definiert:
+
+x) Was willst Du denn @VERBen?
+y) Wo willst Du denn die Beeren @VERBen?
+
+Erst wird geprueft, ob 2. erfuellt ist. Falls nicht, gibt es Fehlermeldung x)
+Dann wird auf 3. geprueft. Ist das nicht erfuellt (aber 2. schon) gibt es
+Fehlermeldung y).
+
+Im Fall a sind 1 und 2 erfuellt. Demnach wird y) ausgegeben. @VERB wird
+dabei durch das benutzte Verb ersetzt (das abschliessende en, bzw e wird
+abgeschnitten):
+ Wo willst Du denn die Beeren pfluecken?
+
+Im Fall b ist 1 erufellt, 2 aber schon nicht. Daher gibt es Fehlermeldung
+x). Auf 3. wird nicht mehr geprueft.
+ Was willst Du denn ernten?
+
+Wie schon erwaehnt erfuellt c) alle Bedingungen und es gibt keine Ausgabe -
+Statt dessen kann man das Pfluecken in der Funktion abhandeln.
+
+In den Faellen 1 und 2 wird die Fehlermeldung ueber notify_fail()
+abgehandelt. Ergo wird hier anderen Befehlen von anderen Objekten noch
+eine Chance gegeben. Gleiches gilt fuer die Funktion cmd_pfluecken(), wenn
+deren Rueckgabewert 0 ist. Auch hier gibt es die Analogie zum alten AddCmd.
+
+Gibt cmd_pfluecken() einen Wert ungleich 0 zurueck, wird die Suche nach
+der richtigen Syntax danach abgebrochen, so dass auch kein anderes Objekt
+mehr gefragt wird (wie gehabt).
+
+Das ist auch fuer Forscherpunkte wichtig. FP werden generell nur bei einem
+Rueckgabewert ungleich 0 vergeben.
+
+Eine kleine Erweiterung der Beispielsyntax:
+-------------------------------------------
+
+ AddCmd("pfluecke|ernte&fruechte|beeren&@ID@\impossible",0,
+ "Was willst Du denn @VERBen?|Wo willst Du denn die Beeren @VERBen?|"
+ "Du pflueckst ein paar Beeren und isst sie auf.^@WER isst ein paar
+ Beeren.");
+
+Eine neue Regel:
+
+4. \impossible
+
+Und eine neue Fehlermeldung:
+z) Du pflueckst ein paar Beeren und isst sie auf.^@WER isst ein paar Beeren.
+
+Zur Regel:
+
+Die Regel ist nicht erfuellbar, da Spieler das \i nicht erzeugen
+koennen. Zwangslaeufig gibt es auch keine Funktion, die aufgerufen werden
+koennte.
+
+Dafuer gibt es eine Fehlermeldung, die ein neues Element enthaelt. Das
+^. Wird diese Meldung ausgegeben ist das genau wie ein return 1 in der
+Funktion. Die Syntax wird als richtig anerkannt. (Es kann hierfuer also
+auch FP geben).
+
+Der Text vor dem ^ geht an den Spieler, alles dahinter geht an die Spieler
+im Raum. Steht hinter dem ^ nichts, gibt es keine Raummeldung.
+
+Auf diese Weise kann man leicht ein Raumkommando erstellen, dass nur
+Textausgaben macht, aber keine Funktionalitaet enthaelt. Es ist keine
+eigenstaendige Funktion mit irgendwelchem eigenen Parsing mehr noetig.
+
+Das @WER wird durch this_player()->Name() ersetzt, so dass man auch einen
+Persoenlichen bezug in den Meldungen herstellen kann.
+
+Abwaertskompatibel
+------------------
+
+Die Erweiterungen von AddCmd erlauben ein einfacheres Erstellen von
+Standard-Kommandos, ohne dass man sich mit dem Parsen in Funktionen
+beschaeftigen muss.
+
+Die Aenderung ist vollstaendig abwaertskompatibel. Wer sich also sagt,
+das das alles viel zu kompliziert sei, kann weiterhin:
+
+ AddCmd(({"pfluecke","ernte"}),"cmd_pfluecken");
+
+benutzen. Das Verhalten ist haargenau das selbe wie bisher. Dementsprechend
+ist auch kaum Aufwand beim Einpflegen dieser Aenderung notwendig.
+
+Zur Beachtung
+-------------
+
+Ueberall, wo direkt auf P_COMMANDS zugegriffen wird, kann es prinzipiell
+zu Problemen kommen, da sich die Struktur des Mappings und der Zugriff
+darauf geaendert hat.
+
+Im Folgeartikel findet sich eine Liste mit allen Objekten, die das machen. In
+den oeffentlichen Verzeichnissen werde ich mich mit den Magiern in Verbindung
+setzen oder selbst kontrollieren, ob Aenderungen notwendig sind.
+
+Objekte in den Players-Verzeichnissen werde ich nur in Ausnahmefaellen
+anpassen. Zur Erinnerung: Angeschlossenes gehoert nicht nach /players/.
+
+Der Code ist auf Kompatibilitaet mit dem alten System ausgelegt, dennoch
+gibt es ein paar Aenderungen. Zum Beispiel ist P_COMMANDS keine echte
+Property mehr sondern eine lokale Variable. Demzufolge wird P_COMMANDS
+bei "xprop" nicht mehr angezeigt. Die Schnittstelle wird durch _set_
+und _query_funktionen realisiert. Die Mappings werden _immer_ als Kopien
+rausgegeben, so dass man damit nicht versehentlich Unsinn machen kann.
+
+Schlusswort
+-----------
+
+Dieser Artikel stellt nur eine Einleitung in die Aenderung und deren
+Moeglichkeiten dar und ist keinesfalls vollstaendig. Wer mehr darueber wissen
+will, ist eingeladen, sich die Manpage zu "AddCmd" und zu den Beispielen
+"AddCmd_bsp" anzuschauen.
+
+Die Seiten sind aus dem Regenbogen "geliehen" und werden in den kommenden
+Tagen noch auf die Beduerfnisse des Morgengrauen angepasst.
+
+Mein Dank geht an Gloinson, der die Idee hatte, die Anpassungen vorzunehmen
+und Migration des Codes ins MorgenGrauen uebernommen hat.
+
+Falls nun noch Fragen sind, nur zu! :)
+
+V*,
diff --git a/doc/beispiele/AddCmd/busch.c b/doc/beispiele/AddCmd/busch.c
new file mode 100644
index 0000000..da3c5b3
--- /dev/null
+++ b/doc/beispiele/AddCmd/busch.c
@@ -0,0 +1,58 @@
+inherit "/std/thing";
+#include <properties.h>
+#include <moving.h>
+#include <language.h>
+
+#pragma strict_types,save_types,rtt_checks
+
+protected void create()
+{
+ ::create();
+
+ SetProp(P_GENDER, NEUTER);
+ SetProp(P_NAME, "Gebuesch");
+ SetProp(P_SHORT,"Ein Gebuesch");
+ SetProp(P_LONG,"Du stehst vor einem gaanz normalen Gebuesch. Es traegt "
+ "Fruechte. Und eventuell\nkann man darin etwas finden.\n");
+ SetProp(P_NOGET,"Es ist festgewachsen, eventuell kann man es ausgraben?\n");
+
+ SetProp(P_WEIGHT,5000);
+ SetProp(P_SIZE,100);
+
+ AddId(({"busch","gebuesch"}));
+
+ AddDetail(({"fruechte","frucht"}),
+ "Es scheinen Beeren zu sein. Vielleicht kannst Du sie pfluecken?\n");
+ AddDetail("beeren",
+ "Pflueck sie doch, vielleicht bringt das ja was.\n");
+
+ // Nur wenn die Syntax erfuellt ist, wird cmd_pfluecken() aufgerufen.
+ // "pfluecke beeren von busch" etc.
+ AddCmd("pfluecke|ernte&fruechte|beeren&@ID","cmd_pfluecken",
+ "Was willst Du denn @verben?|Wo willst Du denn die Beeren @verben?");
+
+ // suchen gibt nur eine Meldung aus. Dafuer braucht man kuenftig keine
+ // Funktionen mehr.
+ AddCmd("such|suche|durchsuch|durchsuche&@ID&\nimpossible",0,
+ "Wo willst Du @VERBen?|Du durchsuchst das Gebuesch, findest aber nichts.^"
+ "@WER1 durchsucht ein Gebuesch, findet aber nichts.");
+
+ // Graben geht eh nicht. Daher nur Fehlermeldungen.
+ // Das ^ sagt, dass hier ein return1 zurueckgegeben wird. Es gibt aber keine
+ // Raummeldung.
+ AddCmd("grab|grabe&@ID&aus@\nimpossible",0,
+ "Was willst Du graben?|Du willst das Gebuesch ausgraben?|"
+ "Die Wurzeln scheinen tief zu rechen. Das wird nichts.^");
+}
+
+int cmd_pfluecken(string arg, mixed *param)
+{
+ object obj;
+ obj=clone_object(__DIR__"obst");
+ write("Verwundert pflueckst Du "+(obj->name())+" vom Busch. Komisch.\n");
+
+ // Das hier ist ein Beispiel fuer AddCmd, daher mach ich mir nich
+ // die Muehe das richtig zu machen. Is eh nur fuer Magier!
+ obj->move(this_player(),M_GET|M_NOCHECK);
+ return 1;
+}
diff --git a/doc/beispiele/AddCmd/obst.c b/doc/beispiele/AddCmd/obst.c
new file mode 100644
index 0000000..8efb471
--- /dev/null
+++ b/doc/beispiele/AddCmd/obst.c
@@ -0,0 +1,232 @@
+/* Hinweis zu diesem Beispielobjekt: Lebensmittel lassen sich besser von
+ * /std/food ableiten, das bringt viele Funktionalitaeten mit, die man sonst
+ * muehsam selber basteln muss.
+ */
+
+inherit "/std/thing";
+
+#include <moving.h>
+#include <properties.h>
+#include <wizlevels.h>
+
+#define SAETTIGUNG 2
+#define HEILUNG 20
+#define EAT_DELAY 1200 // 20 Minuten
+
+#define BS78(x) break_string(x,78)
+
+protected void create()
+{
+ ::create();
+
+ // Gemeinsamer Teil des create
+ AddId("obst");
+ SetProp( P_VALUE, 60+random(10) );
+
+ // AddCmd( ({"iss","esse"}), "act_essen");
+ // new style AddCmd
+ AddCmd( "iss|esse&@ID","act_essen","Was willst Du denn essen?");
+
+ // Nach ca. 10 Minuten resetet das Obst, im Reset wird es destructet,
+ // so spare ich call_outs
+ set_next_reset(600);
+
+ // Name, ID, Gender, Desc und Gewicht sind Abhaengig von der Obstart
+ switch (random(11)){
+ default:
+ SetProp( P_GENDER, MALE );
+ SetProp( P_NAME, "Apfel" );
+ AddId( "apfel" );
+ SetProp( P_SHORT, "Ein Apfel" );
+ SetProp( P_LONG, BS78(
+ "Ein saftiger Apfel. Dir laeuft das Wasser im Munde zusammen."
+ ));
+ SetProp( P_WEIGHT, 80 );
+ break;
+ case 1:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Birne" );
+ AddId( "birne" );
+ SetProp( P_SHORT, "Eine Birne" );
+ SetProp( P_LONG, BS78(
+ "Eine koestliche, reife Birne. Die ist sicher lecker."
+ ));
+ SetProp( P_WEIGHT, 90 );
+ break;
+ case 2:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Banane" );
+ AddId( "banane" );
+ SetProp( P_SHORT, "Eine Banane" );
+ SetProp( P_LONG, BS78(
+ "Die Banane sieht wirklich lecker aus, am besten gleich essen."
+ ));
+ SetProp( P_WEIGHT, 110 );
+ break;
+ case 3:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Kiwi" );
+ AddId( "kiwi" );
+ SetProp( P_SHORT, "Eine Kiwi" );
+ SetProp( P_LONG, BS78(
+ "Klein und gruen, aber mit leckeren Innenleben. Yam yam."
+ ));
+ SetProp( P_WEIGHT, 50 );
+ break;
+ case 4:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Erdbeere" );
+ AddId( "erdbeere" );
+ SetProp( P_SHORT, "Eine Erdbeere" );
+ SetProp( P_LONG, BS78(
+ "Eine ueberdurchschnittlich grosse Erdbeere. Sie "
+ "ist sicher suess und saftig."
+ ));
+ SetProp( P_WEIGHT, 20 );
+ break;
+ case 5:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Kirsche" );
+ AddId( "kirsche" );
+ SetProp( P_SHORT, "Eine Kirsche" );
+ SetProp( P_LONG, BS78(
+ "Zwar nur klein ist diese Kirsche, aber so dunkel wie sie "
+ "aussieht, ist sie sicher total suess und lecker."
+ ));
+ SetProp( P_WEIGHT, 15 );
+ break;
+ case 6:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Orange" );
+ AddId( "orange" );
+ SetProp( P_SHORT, "Eine Orange" );
+ SetProp( P_LONG, BS78(
+ "Eine grosse, gelbe Orange. Eine von diesen suessen, die sich so "
+ "leicht schaelen lassen und keine Zicken machen, so wie Saftorangen."
+ ));
+ SetProp( P_WEIGHT, 90 );
+ break;
+ case 7:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Mandarine" );
+ AddId( "mandarine" );
+ SetProp( P_SHORT, "Eine Mandarine" );
+ SetProp( P_LONG, BS78(
+ "Suess und saftig und gesund. So muss das Essen im Paradies "
+ "gewesen sein."
+ ));
+ SetProp( P_WEIGHT, 60 );
+ break;
+ case 8:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Zitrone" );
+ AddId( "zitrone" );
+ SetProp( P_SHORT, "Eine Zitrone" );
+ SetProp( P_LONG, BS78(
+ "Sauer, sauer und nochmals sauer. Aber ultralecker. Na, sabberst Du "
+ "schon auf die Tastatur?"
+ ));
+ SetProp( P_WEIGHT, 60 );
+ break;
+ case 9:
+ SetProp( P_GENDER, MALE );
+ SetProp( P_NAME, "Granatapfel" );
+ AddId( "granatapfel" );
+ SetProp( P_SHORT, "Ein Granatapfel" );
+ SetProp( P_LONG, BS78(
+ "Er ist zwar etwas schwieriger, den zu essen, aber der Aufwand "
+ "lohnt sich."
+ ));
+ SetProp( P_WEIGHT, 90 );
+ break;
+ case 10:
+ SetProp( P_GENDER, FEMALE );
+ SetProp( P_NAME, "Pflaume" );
+ AddId( "pflaume" );
+ SetProp( P_SHORT, "Eine Pflaume" );
+ SetProp( P_LONG, BS78(
+ "Eine grosse, blaue Pflaume. Lass sie Dir doch schmecken."
+ ));
+ SetProp( P_WEIGHT, 20 );
+ break;
+ }
+}
+
+void reset()
+{
+ object env = environment(this_object());
+
+ if (env) {
+ if (query_once_interactive(env)){
+ // Mein Env is ein User
+ tell_object(env, BS78(
+ capitalize(this_object()->name(WER))+" verschwindet mit einem "+
+ "\"PLOPP\" aus deinem Inventar. Da scheint Magie im Spiel zu sein."
+ ));
+ } else if (sizeof(all_inventory(env)&users())){
+ // In meinem Environment sind User (Es ist ein Raum)
+ tell_room(env, BS78(
+ capitalize(this_object()->name(WER))+" verschwindet mit einem "+
+ "\"PLOPP\". Da scheint Magie im Spiel zu sein."
+ ));
+ }
+ }
+
+ // Objekt zerstoeren
+ remove(1);
+}
+
+static int act_essen(string args)
+{
+ // Nur ein Demo-Objekt
+ if (!IS_LEARNING(this_player()))
+ {
+ write("Schwups, nun ist @@name@@ verschwunden. War wohl eine Illusion.");
+ remove(1);
+ }
+
+ // Der Syntaxtest ist unnoetig, der ist schon im new style
+ // AddCmd() eingebaut.
+
+ // Wenn das Objekt ein Environment hat (hoff ich doch)
+ // und das Environment nicht this_player() ist,
+ // hat der Spieler das Obst nich im Inv - das geht doch nicht ...
+ if (environment(this_object()) && (environment(this_object()) != this_player()) )
+ {
+ write(BS78(
+ "Du solltest "+ this_object()->name(WER,1) + " erstmal nehmen."
+ ));
+ return 1;
+ }
+
+ // DEBUG ("Satt?");
+ if (this_player()->eat_food(SAETTIGUNG))
+ {
+ // DEBUG("Noe!");
+ if (this_player()->check_and_update_timed_key(EAT_DELAY,"vanion_zach_obst")==-1)
+ {
+ write(BS78(
+ "Du isst genuesslich "+this_object()->name(WEN,0)+
+ ". Du fuehlst Dich gestaerkt."
+ ));
+ say(BS78(
+ this_player()->name()+" isst mit vollem Genuss "+this_object()->name(WEN,0)+". "
+ "Dir laeuft das Wasser im Munde zusammen."
+ ));
+ // Heilen und aufessen :)
+ this_player()->heal_self(HEILUNG);
+ }
+ else { // if (check_and_update_timed_key())
+ // Wenn es noch zu frueh ist, wieder welches zu essen
+ // Keine Heilung, aber Saettigung
+ write(BS78(
+ "Du solltest "+this_object()->name(WEN,1)+" lieber jemandem geben, "
+ "den Du magst, statt alles selbst zu futtern, findest Du nicht? "
+ "Deine Gier hat Dir jetzt nur einen vollen Bauch und ein schlechtes "
+ "Gewissen bescheert."
+ ));
+ } // end if (check_and_update_timed_key())
+ if (!remove()) destruct(this_object());
+ } // end of eat_food
+ return 1;
+}