Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/doc/lfun/AddCmd_bsp b/doc/lfun/AddCmd_bsp
new file mode 100644
index 0000000..edb8d98
--- /dev/null
+++ b/doc/lfun/AddCmd_bsp
@@ -0,0 +1,320 @@
+ADDCMD() - BEISPIELE
+FUNKTION
+    varargs void AddCmd(mixed cmd, mixed func, mixed flag);
+
+BEMERKUNGEN
+    Die hier aufgefuehrten Komplexbeispiele sind zum Verstaendnis gedacht,
+    daher fuehren sie oft Alternativen auf. Die letzte Variante ist dann
+    jeweils diejenige, welche am leichtesten das Problem loesen koennte.
+    Falls die einem zu komplex ist, hilft vielleicht die vorletzte.
+
+BEISPIELE
+    // SIMPEL: ganz simpel, beinahe wie add_action
+    AddCmd("befiehl","action_befehlen");
+    ...
+    int action_befehlen(string str) {
+     if(!str || !strlen(str))
+      // Fehlermeldung, falls gar keine Funktion 1 dafuer zurueckgibt
+      notify_fail("Was willst du befehlen?!\n");
+     else {
+      write("Du befiehlst \""+str+"\", und alle folgen!\n");
+      say(TP->Name(WER)+" befiehlt \""+str+"\", und du folgst!\n");
+      return 1;		// ERFOLG - Abbruch der Kommandoauswertung
+     }
+     return 0;		// MISSERFOLG - Fehlermeldung oben gesetzt
+    }
+
+    // SIMPEL .. weitere Beispiele
+    AddCmd(({"kletter","klettere"}),"action_klettern" );
+    AddCmd(({"renn","renne"}),#'action_rennen);
+
+    // REGELN: eine komplexere Regel
+    AddCmd("loesch|loesche|ersticke&feuer|brand|flammen&decke|wolldecke",
+           "action_loeschen",
+           "Was willst du loeschen?|Womit willst du loeschen?");
+
+    // REGELN: mit Platzhaltern im Fehlerstring
+    AddCmd("spring|springe|huepf|huepfe&von|vom&baum|ast|eiche",
+           #'action_huepfe,
+           "Willst du von etwas @verben?|Von wo willst du @verben?");
+
+    // SCHLECHT: eine unscharfe Regel - sie sollten eine Ausnahme sein (!)
+    AddCmd("kletter","fun_klettern",1);
+
+    // FALSCH: sehr schlecht, kein Imperativ verwendet
+    // ausserdem sollte man fuer solche Syntaxen AddReadDetail benutzen
+    AddCmd("lese","eval_lesen");
+
+    // SIMPLE REGEL
+    static int action_jump(string str);        // Prototype (wegen closure)
+    ...
+    AddCmd("spring|springe|huepf|huepfe&von&baum|ast",#'action_jump,
+           "Willst Du von etwas @verben?|Wovon willst Du @verben?");
+    ...
+    static int action_jump(string str) {
+      write(break_string("Du springst vom Baum und kommst hart auf!",78));
+      this_player()->move((XXXROOM+"boden"), M_GO, 0,
+                          "springt unelegant vom Baum","faellt vom Baum");
+      this_player()->Defend(random(100),({DT_BLUDGEON}),([SP_RECURSIVE:1]),
+                            this_object());
+      return 1;
+    }
+
+    // SIMPLE REGEL OHNE METHODE
+    // mit Regeln kann man auch Aktivitaeten im Raum erlauben, ohne eine
+    // Funktion aufrufen zu muessen: die letzte Regel ist fuer Spieler
+    // unmoeglich zu erfuellen, die dazugehoerige Fehlermeldung wird mit
+    // dem ^ (write-Flag) versehen und entsprechend an den Spieler
+    // (und den Raum (hinter dem ^)) ausgegeben
+    AddCmd("spring|springe&herunter|runter&\n\bimpossible",0,
+           "Wohin oder wovon willst Du springen?|"
+           "Du springst vom Baum und kommst hart auf.^"
+           "@WER1 springt vom Baum und kommt hart auf.");
+
+## Komplexbeispiel: Regeln mit Fehlermeldungen ##
+ ## Variante 1, OHNE REGELN ##
+    // bei Nichtverwendung von Regeln muss man Parameter selbst auswerten
+    AddCmd(({"bohr","bohre"}),#'action_bohren);
+    ...
+    private static int action_bohren(string str) {
+      string *tmp;
+      notify_fail("Wo willst (etwas) Du bohren?\n");
+      if(!str) return 0;       // Tja, keine Argumente ...
+      tmp=explode(str," ");    // nach " " in Argument-Array aufspalten
+      if((i=member(tmp,"loch"))>=0) { // aha, ab jetzt uebernehmen wir :)
+       if((j=member(tmp[(i+1)..],"in"))<0 &&
+          (j=member(tmp[(i+1)..],"durch"))<0)
+         write("Willst Du das Loch in etwas bohren?\n");
+        else if((i=member(tmp[(j+1)..],"boden"))<0 &&
+                (i=member(tmp[(j+1)..],"erde"))<0)
+         write("In/Durch was willst du das Loch bohren?\n");
+        else {
+         write("Du bohrst ein Loch in den Boden.\n");
+         say(this_player()->Name(WER)+" bohrt ein Loch in den Boden.\n");
+        }
+        return 1;      // "bohre loch" war so eindeutig, dass nur diese
+                       // Methode gemeint sein konnte, also brechen wir die
+                       // weitere Auswertung auf jeden Fall ab (und geben
+                       // eine write-Fehlermeldung)
+      } // end if(..."loch")
+      return 0;        // "bohre" allein muss nicht diese Methode meinen,
+                       // also nur obige notify_fail()-Meldung, falls
+                       // sich nach dieser Methode gar keine sonst
+                       // angesprochen fuehlt
+    } // end fun
+
+ ## Variante 1a, OHNE REGELN ##
+    // prinzipiell koennte die Methode action_bohren auch so
+    // aussehen, ist aber nicht ganz so flexibel:
+    private static int action_bohren(string str) {
+     string tmp;
+     if(!str || (sprintf(str,"loch in erde%s",tmp)!=1 &&
+                 sprintf(str,"loch durch erde%s",tmp)!=1 &&
+                 sprintf(str,"loch in boden%s",tmp)!=1 &&
+                 sprintf(str,"loch durch boden%s",tmp)!=1))
+      notify_fail("Willst Du in irgendwas ein Loch bohren?\n");
+     else {
+      ...
+      return 1;
+     }
+     return 0;
+    }
+
+ ## Variante 2, MIT REGEL ##
+    // das gleiche in etwa mal als einfache Regel
+    AddCmd("bohr|bohre&loch&in|durch&erde|boden",#'action_bohren,
+           "Was willst du (wohin) bohren?|"
+           "Willst du das Loch in etwas bohren?|"
+           "Wohin willst du das Loch bohren?");
+    ...
+    private static int action_bohren(string str, mixed *param) {
+     write("Du bohrst ein Loch in den Boden.\n");
+     say(this_player()->Name(WER)+" bohrt ein Loch in den Boden.\n");
+     ...
+     return 1;
+    }
+
+ ## Variante 3, MIT REGEL UND FEHLERMELDUNG ##
+    // und nun mit Fehlermeldungen mit Ersetzungen, so dass wir mehr
+    // auf die Eingaben des Spielers eingehen
+    AddCmd("bohr|bohre&loch&in|durch&erde|boden",#'action_bohren,
+           "Was willst du (wohin) @verben?|"
+           "Willst du das Loch in etwas @verben?|"
+           "@WER3 was willst du das Loch @verben?");
+    ...
+    private static int action_bohren(string str, mixed *param) ...
+
+ ## Variante 4, MIT REGEL, FEHLERMELDUNG UND RETURN 1 ##
+    // in Variante 1 kam sinnvollerweise sehr frueh der Abbruch mit
+    // "return 1;" und die Ausgabe von write-Fehlermeldungen,
+    // das koennen wir auch
+    AddCmd("bohr|bohre&loch&in|durch&erde|boden",#'action_bohren,
+           "Was willst du (wohin) @verben?|"
+           "Willst du das Loch in etwas @verben?^|"
+           "@WER3 was willst du das Loch @verben?^");
+    ...
+    private static int action_bohren(string str, mixed *param) ...
+
+ ## Variante 5, MIT REGEL, FEHLERMELDUNG, RETURN 1, OHNE FUN ##
+    // und falls in action_bohren() nichts ausser Ausgaben passiert, koennen
+    // wir uns die auch ganz sparen indem wir eine nichterfuellbare Regel
+    // samt Fehlermeldung bauen
+    AddCmd("bohr|bohre&loch&in|durch&erde|boden&\nimpossible",0,
+           "Was willst du (wohin) @verben?|"
+           "Willst du das Loch in etwas @verben?^|"
+           "@WER3 was willst du das Loch @verben?^|"
+           "Du @verbst ein Loch @WER3 den Boden.^@WER1 @verbt "
+           "ein Loch @WER3 den Boden.");
+
+   --- Ende Komplexbeispiel Regeln mit Fehlermeldungen ---
+
+## Komplexbeispiel: Spezialregeln @PRESENT und @ID ##
+ ## Variante 1, OHNE REGELN ##
+    // oft agieren Kommandos auf Objekten im Raum, diese muessen dabei per
+    // present() identifiziert werden:
+    // Beispiel ist ein Geldautomat (den man besser mit einem Container
+    // mit PreventInsert() basteln sollte)
+    AddCmd(({"stopf","stopfe"}),#'action_stopf);
+    ...
+    private static int action_stopf(string str) {
+     string tmp,tmp2;
+     object o;
+
+     if(str && (sprintf("%s in automat%s",tmp,tmp2)==2 ||
+                sprintf("%s in geldautomat%s",tmp,tmp2)==2 ||
+                sprintf("%s in bankomat%s",tmp,tmp2)==2) {
+      o=present(tmp,this_player());
+      if(o) {
+       if(o->QueryProp(...)) {
+        write(break_string(
+         "Du stopfst "+o->name(WEN,1)+" in den Automaten.",78));
+        say(...);
+       } else {
+        write(break_string(
+         "Du versuchst "+o->name(WEN,1)+" in den Automaten zu stopfen, "
+         "aber "+o->QueryPronoun(WER)+" passt nicht hinein.",78));
+        say(...);
+       }
+      } else {
+       write("Was willst du in den Automaten stopfen?\n");
+       say(....);
+      }
+      return 1;
+     }
+     notify_fail("Was willst du wohin stecken?\n");
+     return 0;
+    }
+
+ ## Variante 2, MIT REGEL ##
+    // einerseits koennen wir das Finden von Objekten in Inv und Env
+    // integrieren und uns andererseits das Aufzaehlen aller IDs des
+    // Automaten ersparen
+    AddCmd("steck|stecke&@PRESENT&in&@ID",#'action_stopf,
+           "Was willst du wohin stopfen?|"
+           "Willst du @WEN2 in etwas stopfen?|"
+           "Wohinein willst du @WEN2 stopfen?");
+    ...
+    // dabei werden wie immer die gefunden Matches als Parameterarray
+    // uebergeben ... und die @PRESENT und @ID als Objekte!
+    private static int action_stopf(string str, mixed *param) {
+     if(param[0]->QueryProp(...)) {
+      write(break_string(
+       "Du stopfst "+param[0]->name(WEN,1)+" in den Automaten.",78));
+      say(...);
+     } else {
+      write(break_string(
+       "Du versuchst "+param[0]->name(WEN,1)+" in den Automaten zu "
+       "stopfen, aber "+param[0]->QueryPronoun(WER)+" passt nicht "
+       "hinein.",78));
+      say(...);
+     }
+     return 1;
+    }
+
+   --- Ende Komplexbeispiel Spezialregeln @PRESENT und @ID  ---
+
+## Komplexbeispiel: gleiches Verb, mehrere Regeln ##
+ // Das Problem mehrerer Regeln fuer ein Kommandoverb besteht darin, dass
+ // letztlich nur eine der Fehlermeldungen zum Tragen kommt - welche
+ // genau ist etwas vage.
+ // Dabei kann man sich auf eines verlassen: juengere AddCmd werden
+ // zuerst ausgewertet. Wenn sich das aendert, tretet euren EM.
+
+ ## Problem 1: Mehrere Regeln weil mehrere Zwecke ##
+    ## Variante 1 - GLEICHLAUTENDE FEHLERMELDUNG
+    // fuer alles wird eine identische Fehlermeldung gesetzt, das ist
+    // natuerlich nicht sehr flexibel oder schoen
+    AddCmd("kriech|krieche&hoch|hinauf|hinaus|heraus|raus",#'result_kriech,
+           "Wohin willst Du kriechen?");
+    AddCmd("kriech|krieche&nach&oben",#'result_kriech,
+           "Wohin willst Du kriechen??|Wohin willst Du kriechen?");
+    AddCmd("kriech|krieche&aus&loch|grube|falle",#'result_kriech);
+           "Wohin willst Du kriechen?|Wohin willst Du kriechen?");
+
+    // oder man versucht eine bessere Regel zu schaffen, was hier durch
+    // die Moeglichkeit von zwei oder drei Parameter unmoeglich ist
+
+    ## Variante 2 - EIGENE AUSWERTUNG
+    // es bietet sich also eigene Weiterauswertung an, was durch die
+    // Uebergabe der getriggerten Verben erleichtert wird:
+    AddCmd("kriech|krieche&hoch|hinauf|hinaus|heraus|raus|aus|nach",
+           #'result_kriech,
+           "Wohin willst Du kriechen?");
+    ...
+    static int result_kriech(string str, mixed *extra) {
+      if(member(extra,"aus")>=0 &&
+         !sizeof(({str}),"*.\\<(hoehle|grube|falle)\\>.*"))
+       notify_fail("Woraus willst Du kriechen?\n");
+      else if(member(extra,"nach")>=0 && strstr(str,"oben")<0)
+       notify_fail("In welche Richtung willst Du kriechen?\n");
+      else if(this_player()->QueryAttribute(A_DEX)>10 ||
+              member(holding_root,this_player())) {
+        write("Du kriechst mit Muehe heraus.\n");
+        this_player()->move((XXXROOM+"draussen"), M_GO, 0,
+                            "kriecht mit Muehe aus der Grube",
+                            "kriecht aus einer Grube");
+        return 1;
+      } else
+        write("Du bist zu ungeschickt, halt Dich irgendwo fest.\n");
+        return 1;
+      }
+      return 0;
+    }
+    // (ob sich der Aufwand fuer diese Beispielsyntax lohnt ist fraglich)
+
+ ## Problem 2: mehrere Regeln, weil optionale Parameter ##
+    // Manchmal will man optionale Parameter erlauben, die aber eine
+    // Wirkung zeigen sollen:
+    AddCmd("schlag|schlage&@ID&hart",#'action_schlag_hart,
+           "Was oder wen willst du @verben?|"
+           "Wie willst du @WEN2 schlagen?");
+    AddCmd("schlag|schlage&@ID",#'action_schlag,
+           "Was oder wen willst du @verben?");
+
+    // Da juengere AddCmd aelteren vorgehen, wird die komplexere Regel samt
+    // ihrer Fehlermeldung nie ausgewertet, da ein "schlag ball hart" auch
+    // die zweite Regel triggert.
+
+    // anders herum:
+    AddCmd("schlag|schlage&@ID",#'action_schlag,
+           "Was oder wen willst du @verben?");
+    AddCmd("schlag|schlage&@ID&hart",#'action_schlag_hart,
+           "Was oder wen willst du @verben?|"
+           "Wie willst du @WEN2 schlagen?");
+
+    // Jetzt wird die komplexere Regel zuerst ueberprueft und triggert
+    // auch die richtige Funktion.
+    // Leider kommt die Fehlermeldung nie zum Tragen, denn was durch Regel 2
+    // durchfaellt, triggert entweder Regel 1 oder faellt auch durch Regel 1
+    // durch und ueberschreibt dabei die Meldung.
+
+    AddCmd("schlag|schlage&@ID",#'action_schlag,
+           "Was oder wen willst du wie @verben?");
+    AddCmd("schlag|schlage&@ID&hart",#'action_schlag_hart);
+
+    // Fast perfekt. Besser wird es nicht.
+
+
+    --- Ende Komplexbeispiel mehrere Regeln ---
+
+10 Juni 2004 Gloinson