Doku-Update: AddCmd-Beispiele neu strukturiert

Change-Id: Ib53e87285146fb1fe8da959f9915344068df77b0
diff --git a/doc/lfun/AddCmd_bsp b/doc/lfun/AddCmd_bsp
index ec8ff17..4f382c8 100644
--- a/doc/lfun/AddCmd_bsp
+++ b/doc/lfun/AddCmd_bsp
@@ -1,10 +1,6 @@
 
-AddCmd_bsp()
-************
-
-
 ADDCMD() - BEISPIELE
-====================
+********************
 
 
 FUNKTION
@@ -25,48 +21,61 @@
 BEISPIELE
 =========
 
-   // SIMPEL: ganz simpel, beinahe wie add_action
+
+Einfache Beispiele
+------------------
+
+1. 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
+     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
+2. SIMPEL .. weitere Beispiele
+
    AddCmd(({"kletter","klettere"}),"action_klettern" );
    AddCmd(({"renn","renne"}),#'action_rennen);
 
-   // REGELN: eine komplexere Regel
+3. 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
+4. 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 (!)
+5. 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
+6. FALSCH: sehr schlecht, kein Imperativ verwendet
+
    AddCmd("lese","eval_lesen");
 
-   // SIMPLE REGEL
+   ausserdem sollte man fuer Lese-Syntaxen AddReadDetail benutzen
+
+7. 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,
@@ -76,307 +85,314 @@
      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
+8. 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 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 :)
+Komplexbeispiel: Regeln mit Fehlermeldungen
+-------------------------------------------
 
-            if((j=member(tmp[(i+1)..],"in"))<0 &&
-                     (j=member(tmp[(i+1)..],"durch"))<0)
 
-                  write("Willst Du das Loch in etwas bohren?n");
+Variante 1a, OHNE REGELN
+~~~~~~~~~~~~~~~~~~~~~~~~
 
-               else if((i=member(tmp[(j+1)..],"boden"))<0 &&
-                     (i=member(tmp[(j+1)..],"erde"))<0)
+   Wenn man keine Regeln verwendet, muss man die Eingabe selbst
+   auswerten.
 
-                  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
-
+   AddCmd(({"bohr","bohre"}),#'action_bohren);
+   // ...
+   private 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
 
-         } // 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
+Variante 1b, OHNE REGELN, Alternative
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-      } // end fun
+   prinzipiell koennte die Methode action_bohren() auch so aussehen,
+   ist aber nicht ganz so flexibel:
 
-   ## Variante 1a, OHNE REGELN ##
-      // prinzipiell koennte die Methode action_bohren auch so //
-      aussehen, ist aber nicht ganz so flexibel: private int
-      action_bohren(string str) {
+   private int action_bohren(string str) {
+     string unused;
+     if(!str || (sprintf(str,"loch in erde%s", unused)!=1 &&
+                 sprintf(str,"loch durch erde%s", unused)!=1 &&
+                 sprintf(str,"loch in boden%s", unused)!=1 &&
+                 sprintf(str,"loch durch boden%s", unused)!=1))
+       notify_fail("Willst Du in irgendwas ein Loch bohren?\n");
+     else {
+       // ...
+       return 1;
+     }
+     return 0;
+   }
 
-         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))
+Variante 2, MIT REGEL
+~~~~~~~~~~~~~~~~~~~~~
 
-            notify_fail("Willst Du in irgendwas ein Loch bohren?n");
+   das gleiche in etwa mal als einfache Regel
 
-         else {
-            ... return 1;
+   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 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;
+   }
 
-         } return 0;
 
-      }
+Variante 3, MIT REGEL UND FEHLERMELDUNG
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-   ## Variante 2, MIT REGEL ##
-      // das gleiche in etwa mal als einfache Regel
-      AddCmd("bohr|bohre&loch&in|durch&erde|boden",#'action_bohren,
+   und nun mit Fehlermeldungen mit Ersetzungen, so dass wir mehr auf
+   die Eingaben des Spielers eingehen
 
-         "Was willst du (wohin) bohren?|" "Willst du das Loch in etwas
-         bohren?|" "Wohin willst du das Loch bohren?");
+   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 int action_bohren(string str, mixed *param) // ...
 
-      ... private 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 4, MIT REGEL, FEHLERMELDUNG UND RETURN 1
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-      }
+   In Variante 1 kam sinnvollerweise sehr frueh der Abbruch mit
+   "return 1;" und mit Ausgabe von write-Fehlermeldungen, das koennen
+   wir auch direkt und ohne eigene Methode.
 
-   ## 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,
+   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 int action_bohren(string str, mixed *param) // ...
 
-         "Was willst du (wohin) @verben?|" "Willst du das Loch in
-         etwas @verben?|" "@WER3 was willst du das Loch @verben?");
 
-      ... private int action_bohren(string str, mixed >>*<<param) ...
+Variante 5, MIT REGEL, FEHLERMELDUNG, RETURN 1, OHNE FUN
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-   ## 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,
+   // 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.");
 
-         "Was willst du (wohin) @verben?|" "Willst du das Loch in
-         etwas @verben?^|" "@WER3 was willst du das Loch @verben?^");
 
-      ... private int action_bohren(string str, mixed >>*<<param) ...
+Komplexbeispiel: Spezialregeln @PRESENT und @ID
+-----------------------------------------------
 
-   ## 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.");
+Variante 1, OHNE REGELN
+~~~~~~~~~~~~~~~~~~~~~~~
 
-      --- Ende Komplexbeispiel Regeln mit Fehlermeldungen ---
+   Oft agieren Kommandos auf Objekten im Raum, diese muessen dabei per
+   present() identifiziert werden: Beispiel ist ein Geldautomat
+   (Hinweis: dieses Beispiel dient der Illustration, die
+   Funktionalitaet an sich sollte man besser mit einem Container mit
+   PreventInsert() erzeugen.)
 
-## 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 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 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;
-
+   AddCmd(({"stopf","stopfe"}),#'action_stopf);
+   // ...
+   private int action_stopf(string str) {
+     string was, unused;
+     if(str && (sprintf("%s in automat%s", was, unused)==2 ||
+                sprintf("%s in geldautomat%s", was, unused)==2 ||
+                sprintf("%s in bankomat%s", was, unused)==2) {
+       object o = present(was, 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;
+   }
 
-      --- 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.
+Variante 2, MIT REGEL
+~~~~~~~~~~~~~~~~~~~~~
 
-   ## 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|hin
-      auf|hinaus|heraus|raus",#'result_kriech,
+   einerseits koennen wir auf diese Weise das Finden von Objekten in
+   Inv und Env in die AddCmd()-Regel integrieren und uns andererseits
+   das Aufzaehlen aller IDs des Automaten ersparen.
 
-         "Wohin willst Du kriechen?");
+   Wie immer werden die gefundenen Matches als Parameterarray an die
+   angegebene Methode uebergeben. Das Array enthaelt die mit @PRESENT
+   und @ID gefundenen Treffer praktischerweise als Objekte.
 
-      AddCmd("kriech|krieche&nach&oben",#'result_kriech,
-         "Wohin willst Du kriechen??|Wohin willst Du kriechen?");
+   AddCmd("steck|stecke&@PRESENT&in&@ID",#'action_stopf,
+          "Was willst du wohin stopfen?|"
+          "Willst du @WEN2 in etwas stopfen?|"
+          "Wohinein willst du @WEN2 stopfen?");
+   // ...
+   private 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;
+   }
 
-      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
+Komplexbeispiel: gleiches Verb, mehrere Regeln
+----------------------------------------------
 
-      ## 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",
+   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.
 
-         #'result_kriech, "Wohin willst Du kriechen?");
 
-      ... static int result_kriech(string str, mixed >>*<<extra) {
+Problem 1: Mehrere Regeln weil mehrere Zwecke
+---------------------------------------------
 
-         if(member(extra,"aus")>=0 &&
-               !sizeof(({str}),"*.\<(hoehle|grube|falle)\>.*"))
 
-            notify_fail("Woraus willst Du kriechen?n");
+Variante 1 - GLEICHLAUTENDE FEHLERMELDUNG
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-         else if(member(extra,"nach")>=0 && strstr(str,"oben")<0)
-            notify_fail("In welche Richtung willst Du kriechen?n");
+   Fuer alles wird eine identische Fehlermeldung gesetzt, das ist
+   natuerlich nicht sehr flexibel oder schoen oder man versucht eine
+   bessere Regel zu schaffen, was hier durch die Moeglichkeit von zwei
+   oder drei Parameter unmoeglich ist
 
-         else if(this_player()->QueryAttribute(A_DEX)>10 ||
-               member(holding_root,this_player())) {
+   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?");
 
-            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");
+Variante 2 - EIGENE AUSWERTUNG
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-            return 1;
+   Statt der Verwendung mehrerer aehnlicher AddCmd() bietet sich die
+   eigene Weiterauswertung an, was durch die Uebergabe der
+   getriggerten Argumente erleichtert wird.
 
-         } else
-            write("Du bist zu ungeschickt, halt Dich irgendwo
-            fest.n"); return 1;
+   AddCmd("kriech|krieche&hoch|hinauf|hinaus|heraus|raus|aus|nach",
+          #'result_kriech,
+          "Wohin willst Du kriechen?");
+   // ...
+   private 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;
+   }
 
-         } return 0;
 
-      } // (ob sich der Aufwand fuer diese Beispielsyntax lohnt ist
-      fraglich)
+Problem 2: mehrere Regeln aufgrund von optionalen Parametern
+------------------------------------------------------------
 
-   ## 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,
+   Manchmal will man optionale Parameter erlauben, die aber eine
+   Wirkung zeigen sollen. Hierbei ist die Reihenfolge der AddCmd()-
+   Anweisungen und ggf. deren Aufbau entscheidend.
 
-         "Was oder wen willst du @verben?|" "Wie willst du @WEN2
-         schlagen?");
+   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?");
 
-      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.
 
-      // 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:
 
-      // anders herum: AddCmd("schlag|schlage&@ID",#'action_schlag,
+   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?");
 
-         "Was oder wen willst du @verben?");
+   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&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 wie @verben?");
+   AddCmd("schlag|schlage&@ID&hart",#'action_schlag_hart);
 
-      // 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.
+   Das ist zwar auch nur fast perfekt, besser wird es aber nicht.
 
-      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 ---
-
-Letzte Aenderung: 22.12.2016, Bugfix
+Letzte Aenderung: 20.11.2019, Arathorn
diff --git a/doc/sphinx/lfun/AddCmd_bsp.rst b/doc/sphinx/lfun/AddCmd_bsp.rst
index d0665d3..f3b848e 100644
--- a/doc/sphinx/lfun/AddCmd_bsp.rst
+++ b/doc/sphinx/lfun/AddCmd_bsp.rst
@@ -1,18 +1,14 @@
-AddCmd_bsp()
-============
-
 ADDCMD() - BEISPIELE
---------------------
-::
+********************
 
 FUNKTION
---------
+========
 ::
 
     varargs void AddCmd(mixed cmd, mixed func, mixed flag);
 
 BEMERKUNGEN
------------
+===========
 ::
 
     Die hier aufgefuehrten Komplexbeispiele sind zum Verstaendnis gedacht,
@@ -21,267 +17,351 @@
     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) {
+Einfache Beispiele
+------------------
+
+1. SIMPEL: ganz simpel, beinahe wie add_action()
+
+.. code-block:: pike
+
+   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");
+       // 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
+       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
-    }
+     return 0;    // MISSERFOLG - Fehlermeldung oben gesetzt
+   }
 
-    // SIMPEL .. weitere Beispiele
-    AddCmd(({"kletter","klettere"}),"action_klettern" );
-    AddCmd(({"renn","renne"}),#'action_rennen);
+2. SIMPEL .. weitere Beispiele
 
-    // REGELN: eine komplexere Regel
-    AddCmd("loesch|loesche|ersticke&feuer|brand|flammen&decke|wolldecke",
-           "action_loeschen",
-           "Was willst du loeschen?|Womit willst du loeschen?");
+.. code-block:: pike
 
-    // 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?");
+   AddCmd(({"kletter","klettere"}),"action_klettern" );
+   AddCmd(({"renn","renne"}),#'action_rennen);
 
-    // SCHLECHT: eine unscharfe Regel - sie sollten eine Ausnahme sein (!)
-    AddCmd("kletter","fun_klettern",1);
+3. REGELN: eine komplexere Regel
 
-    // FALSCH: sehr schlecht, kein Imperativ verwendet
-    // ausserdem sollte man fuer solche Syntaxen AddReadDetail benutzen
-    AddCmd("lese","eval_lesen");
+.. code-block:: pike
 
-    // 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;
-    }
+   AddCmd("loesch|loesche|ersticke&feuer|brand|flammen&decke|wolldecke",
+          "action_loeschen",
+          "Was willst du loeschen?|Womit willst du loeschen?");
 
-    // 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.");
+4. REGELN: mit Platzhaltern im Fehlerstring
 
-## Komplexbeispiel: Regeln mit Fehlermeldungen ##
- ## Variante 1, OHNE REGELN ##
-    // bei Nichtverwendung von Regeln muss man Parameter selbst auswerten
-    AddCmd(({"bohr","bohre"}),#'action_bohren);
-    ...
-    private 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 :)
+.. code-block:: pike
+
+   AddCmd("spring|springe|huepf|huepfe&von|vom&baum|ast|eiche",
+          #'action_huepfe,
+          "Willst du von etwas @verben?|Von wo willst du @verben?");
+
+5. SCHLECHT: eine unscharfe Regel - sie sollten eine Ausnahme sein (!)
+
+.. code-block:: pike
+
+   AddCmd("kletter","fun_klettern",1);
+
+6. FALSCH: sehr schlecht, kein Imperativ verwendet 
+
+.. code-block:: pike
+
+   AddCmd("lese","eval_lesen");
+
+   ausserdem sollte man fuer Lese-Syntaxen AddReadDetail benutzen
+
+7. SIMPLE REGEL
+
+.. code-block:: pike
+
+   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;
+   }
+
+8. 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
+
+.. code-block:: pike
+
+   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 1a, OHNE REGELN
+^^^^^^^^^^^^^^^^^^^^^^^^
+    
+  Wenn man keine Regeln verwendet, muss man die Eingabe selbst auswerten.
+
+.. code-block:: pike
+
+   AddCmd(({"bohr","bohre"}),#'action_bohren);
+   // ...
+   private 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)
+       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 {
+       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 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 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 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 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 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;  // "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 1b, OHNE REGELN, Alternative
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  prinzipiell koennte die Methode action_bohren() auch so
+  aussehen, ist aber nicht ganz so flexibel:
+
+.. code-block:: pike
+
+  private int action_bohren(string str) {
+    string unused;
+    if(!str || (sprintf(str,"loch in erde%s", unused)!=1 &&
+                sprintf(str,"loch durch erde%s", unused)!=1 &&
+                sprintf(str,"loch in boden%s", unused)!=1 &&
+                sprintf(str,"loch durch boden%s", unused)!=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
+
+.. code-block:: pike
+
+  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 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
+
+.. code-block:: pike
+
+   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 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 mit Ausgabe von write-Fehlermeldungen, das koennen
+  wir auch direkt und ohne eigene Methode.
+
+.. code-block:: pike
+
+  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 int action_bohren(string str, mixed *param) // ...
+
+Variante 5, MIT REGEL, FEHLERMELDUNG, RETURN 1, OHNE FUN
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: pike
+
+  // 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.");
+
+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 
+  (Hinweis: dieses Beispiel dient der Illustration, die Funktionalitaet an
+  sich sollte man besser mit einem Container mit PreventInsert() erzeugen.)
+
+.. code-block:: pike
+
+   AddCmd(({"stopf","stopfe"}),#'action_stopf);
+   // ...
+   private int action_stopf(string str) {
+     string was, unused;
+     if(str && (sprintf("%s in automat%s", was, unused)==2 ||
+                sprintf("%s in geldautomat%s", was, unused)==2 ||
+                sprintf("%s in bankomat%s", was, unused)==2) {
+       object o = present(was, 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 int action_stopf(string str, mixed *param) {
-     if(param[0]->QueryProp(...)) {
+Variante 2, MIT REGEL
+^^^^^^^^^^^^^^^^^^^^^
+
+  einerseits koennen wir auf diese Weise das Finden von Objekten in Inv 
+  und Env in die AddCmd()-Regel integrieren und uns andererseits das 
+  Aufzaehlen aller IDs des Automaten ersparen.
+
+  Wie immer werden die gefundenen Matches als Parameterarray an die
+  angegebene Methode uebergeben. Das Array enthaelt die mit @PRESENT und 
+  @ID gefundenen Treffer praktischerweise als Objekte.
+
+.. code-block:: pike
+
+  AddCmd("steck|stecke&@PRESENT&in&@ID",#'action_stopf,
+         "Was willst du wohin stopfen?|"
+         "Willst du @WEN2 in etwas stopfen?|"
+         "Wohinein willst du @WEN2 stopfen?");
+  // ...
+  private 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));
+        "Du stopfst "+param[0]->name(WEN,1)+" in den Automaten.",78));
       say(...);
-     } else {
+    } 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));
+        "Du versuchst "+param[0]->name(WEN,1)+" in den Automaten zu "
+        "stopfen, aber "+param[0]->QueryPronoun(WER)+" passt nicht "
+        "hinein.",78));
       say(...);
-     }
-     return 1;
     }
+    return 1;
+  }
 
-   --- Ende Komplexbeispiel Spezialregeln @PRESENT und @ID  ---
+Komplexbeispiel: gleiches Verb, mehrere Regeln
+----------------------------------------------
 
-## 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.
+  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?");
+Problem 1: Mehrere Regeln weil mehrere Zwecke
+---------------------------------------------
 
-    // oder man versucht eine bessere Regel zu schaffen, was hier durch
-    // die Moeglichkeit von zwei oder drei Parameter unmoeglich ist
+Variante 1 - GLEICHLAUTENDE FEHLERMELDUNG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+  
+  Fuer alles wird eine identische Fehlermeldung gesetzt, das ist
+  natuerlich nicht sehr flexibel oder schoen
+  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:
+.. code-block:: pike
+
+  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?");
+
+
+Variante 2 - EIGENE AUSWERTUNG
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    
+  Statt der Verwendung mehrerer aehnlicher AddCmd() bietet sich die eigene 
+  Weiterauswertung an, was durch die Uebergabe der getriggerten Argumente
+  erleichtert wird.
+
+.. code-block:: pike
+
     AddCmd("kriech|krieche&hoch|hinauf|hinaus|heraus|raus|aus|nach",
            #'result_kriech,
            "Wohin willst Du kriechen?");
-    ...
-    static int result_kriech(string str, mixed *extra) {
+    // ...
+    private int result_kriech(string str, mixed *extra) {
       if(member(extra,"aus")>=0 &&
          !sizeof(({str}),"*.\\<(hoehle|grube|falle)\\>.*"))
-       notify_fail("Woraus willst Du kriechen?\n");
+        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");
+        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");
@@ -295,42 +375,49 @@
       }
       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?");
+Problem 2: mehrere Regeln aufgrund von optionalen Parametern
+------------------------------------------------------------
 
-    // Da juengere AddCmd aelteren vorgehen, wird die komplexere Regel samt
-    // ihrer Fehlermeldung nie ausgewertet, da ein "schlag ball hart" auch
-    // die zweite Regel triggert.
+  Manchmal will man optionale Parameter erlauben, die aber eine
+  Wirkung zeigen sollen. Hierbei ist die Reihenfolge der AddCmd()-
+  Anweisungen und ggf. deren Aufbau entscheidend.
 
-    // 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?");
+.. code-block:: pike
 
-    // 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&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?");
 
-    AddCmd("schlag|schlage&@ID",#'action_schlag,
-           "Was oder wen willst du wie @verben?");
-    AddCmd("schlag|schlage&@ID&hart",#'action_schlag_hart);
+  Da juengere AddCmd aelteren vorgehen, wird die komplexere Regel samt
+  ihrer Fehlermeldung nie ausgewertet, da ein "schlag ball hart" auch
+  die zweite Regel triggert.
 
-    // Fast perfekt. Besser wird es nicht.
+  Anders herum:
 
+.. code-block:: pike
 
-    --- Ende Komplexbeispiel mehrere Regeln ---
+  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?");
 
-Letzte Aenderung: 22.12.2016, Bugfix
+  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.
+
+.. code-block:: pike
+
+  AddCmd("schlag|schlage&@ID",#'action_schlag,
+         "Was oder wen willst du wie @verben?");
+  AddCmd("schlag|schlage&@ID&hart",#'action_schlag_hart);
+
+  Das ist zwar auch nur fast perfekt, besser wird es aber nicht.
+
+Letzte Aenderung: 20.11.2019, Arathorn