Automatisch erzeugte Manpages.
Damit nicht jeder sphinx auf dem Rechner haben muss,
behalten wir bis auf weiteres die aus den .rst
erzeugten Manpoages auch im Repo.
Change-Id: Id556c0d11cf5f79659d8350952ce1c014d81ea44
diff --git a/doc/sphinx/man/lfun/AddCmd_bsp b/doc/sphinx/man/lfun/AddCmd_bsp
new file mode 100644
index 0000000..ec8ff17
--- /dev/null
+++ b/doc/sphinx/man/lfun/AddCmd_bsp
@@ -0,0 +1,382 @@
+
+AddCmd_bsp()
+************
+
+
+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 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 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;
+
+ } 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;
+
+ }
+
+ --- 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|hin
+ auf|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 ---
+
+Letzte Aenderung: 22.12.2016, Bugfix