rst gefixt, Files erzeugt
Update autoerzeugter Manapges
Change-Id: I68afa0ee3d81fefa13ebd61df096a31812f2a4d1
diff --git a/doc/efun-mg/add_action b/doc/efun-mg/add_action
new file mode 100644
index 0000000..73555fe
--- /dev/null
+++ b/doc/efun-mg/add_action
@@ -0,0 +1,57 @@
+
+add_action(E)
+*************
+
+
+BEMERKUNGEN
+===========
+
+ 1. Das Verhalten dieser efun wird durch AddCmd aus
+ /std/thing/commands.c komfortabler widergespiegelt. Darauf
+ sollte man zurueckgreifen.
+
+ 2. add_action() sollte immer innerhalb von init() benutzt werden
+
+ 3. das definierende Objekt muss im inventory des Spielers oder
+ environment() des kommandogebenden Lebewesens sein
+
+ 4. im init() spaeter eingetragene Kommandos oder spaeter
+ hinzukommende Objekte werden bei der Kommandoauswertung VOR den
+ alten beruecksichtigt. (Daher bewegt sich das Xtool der Magier
+ regelmaessing neu in das Inventory, um immer "erstes" Objekt zu
+ sein.)
+
+
+BEISPIELE
+=========
+
+ 1. ein Kommando in einem Schirm
+
+ void init() {
+ ::init();
+ add_action("action_oeffne", "oeffne");
+ }
+
+ int action_oeffne(string str) {
+ if(stringp(str) && id(str)) // Argument da und bin ich gemeint?
+ {
+ write("Du oeffnest den Schirm.\n");
+ say(break_string(this_player()->Name(WER)+" oeffnet einen Schirm.",
+ 78));
+ return 1;
+ }
+ notify_fail("Was willst Du oeffnen?\n");
+ return 0;
+ }
+
+ 2. Kommandoblockierer: frueher beliebt um Spieler
+ lahmzulegen, da es _alle_ Kommandos triggert. Heute jedoch
+ dafuer eher P_DISABLE_COMMANDS verwenden. *Achtung*: siehe
+ Implikation von (4) oben.
+
+ add_action("action_nothing", "",1 );
+ ...
+ int action_nothing(string str) {
+ write("Dir sind die Haende gebunden.\n");
+ return 1;
+ }
diff --git a/doc/efun-mg/all_inventory b/doc/efun-mg/all_inventory
new file mode 100644
index 0000000..49f8dfa
--- /dev/null
+++ b/doc/efun-mg/all_inventory
@@ -0,0 +1,11 @@
+
+all_inventory
+*************
+
+
+BEMERKUNGEN
+===========
+
+Gerade bei sehr vollen Objekten ist first_inventory() und
+next_inventory() eine gute Alternative, die die Erzeugung langer
+Arrays vermeidet.
diff --git a/doc/efun-mg/call_out b/doc/efun-mg/call_out
new file mode 100644
index 0000000..5266f65
--- /dev/null
+++ b/doc/efun-mg/call_out
@@ -0,0 +1,12 @@
+
+call_out
+********
+
+
+WARNUNG
+=======
+
+ Bitte nie call_out(..., 0) in rekursiven Callouts nutzen und in
+ anderen Anwendungen sehr vorsichtig damit sein. So ein Callout
+ wuerde direkt nach nach dem aktuellen Callout ausgefuehrt und man
+ erhaelt wirklich eine Verzoegerung von 0.
diff --git a/doc/efun-mg/count_bits b/doc/efun-mg/count_bits
new file mode 100644
index 0000000..3d163ab
--- /dev/null
+++ b/doc/efun-mg/count_bits
@@ -0,0 +1,10 @@
+
+count_bits
+**********
+
+
+BEMERKUNGEN
+===========
+
+ Arbeitet eigentlich nur sinnvoll auf Bitstrings, nicht auf
+ allgemeinen Strings! :)
diff --git a/doc/efun-mg/environment b/doc/efun-mg/environment
new file mode 100644
index 0000000..be6b524
--- /dev/null
+++ b/doc/efun-mg/environment
@@ -0,0 +1,61 @@
+
+environment
+***********
+
+
+BEMERKUNGEN
+===========
+
+ Blueprints, wie zum Beispiel Raeume haben oft kein environment().
+ Man sollte daher ueberpruefen, ob ein environment() existiert, wenn
+ man darin oder darauf eine Funktion aufrufen will.
+
+
+BEISPIELE
+=========
+
+ // In der Variable "raum" steht der Raum, in dem sich der Spieler
+ // derzeit aufhaelt - das kann auch 0 sein!
+
+ raum = environment(this_player());
+
+ // Dieses Objekt hat noch kein environment, da es eben erst geclont
+ // wurde. Ergo steht in env eine 0.
+ obj = clone_object("/std/thing");
+ env = environment(obj);
+
+ // alle Methoden die auf Environment arbeiten, sollten das vorher
+ // pruefen - insbesondere tell_room()
+ if(this_player() && environment(this_player()) &&
+ objectp(o=present("schild",environment(this_player()))) {
+
+ write("Du klebst Deine Plakette auf "+o->name(WEN)+".\n");
+ tell_room(environment(this_player()), break_string(
+ this_player()->Name(WER)+" pappt einen Aufkleber auf "
+ +o->name(WEN)+".",78), ({this_player()}));
+ }
+
+ // wenn Dinge sehr offensichtlich in Leuten kaputtgehen wird es
+ // komplexer (man kann das natuerlich noch weiter schachteln oder
+ // ueber all_environment() versuchen zu loesen
+ if(environment()) {
+ object ee;
+ ee=environment(environment());
+ if(living(environment()))
+ {
+ tell_object(environment(),Name(WER)+" zerfaellt.\n");
+ if(ee)
+ tell_room(ee, environment()->Name(WESSEN)
+ +" "+name(RAW)+" zerfaellt.\n", ({environment()}));
+ }
+ else if(ee && living(ee))
+ {
+ if(environment()->QueryProp(P_TRANSPARENT))
+ tell_object(ee, Name(WER)+" zerfaellt in Deine"
+ + (environment()->QueryProp(P_PLURAL) ? "n" :
+ (environment()->QueryProp(P_GENDER)==FEMALE?"r":"m"))
+ + environment()->name(RAW)+".\n");
+ }
+ else
+ tell_room(environment(),Name(WER)+" zerfaellt.\n");
+ }
diff --git a/doc/efun-mg/file_size b/doc/efun-mg/file_size
new file mode 100644
index 0000000..754b7fd
--- /dev/null
+++ b/doc/efun-mg/file_size
@@ -0,0 +1,20 @@
+
+file_size
+*********
+
+
+BEISPIELE
+=========
+
+ Ein Spieler soll seinen Plan abfragen koennen:
+
+ #include <sys/files.h>
+ if(file_size("/p/service/loco/plans/"+
+ getuid(this_player())+".plan") <= FSIZE_NOFILE)
+ {
+ write("Du hast keinen eigenen Plan festgelegt.\n");
+ return 1;
+ }
+
+ this_player()->More(read_file("/p/service/loco/plans/"+
+ getuid(this_player())+".plan");
diff --git a/doc/efun-mg/filter b/doc/efun-mg/filter
new file mode 100644
index 0000000..c7227be
--- /dev/null
+++ b/doc/efun-mg/filter
@@ -0,0 +1,92 @@
+
+filter
+******
+
+
+BEMERKUNGEN
+===========
+
+ 1. Achtung, die Elemente in 'arr' werden nicht tief kopiert,
+ sind sie also selbst Arrays oder Mappings, so fuehrt eine
+ spaetere Aenderung im Rueckgabe-Arrays zur Aenderung im
+ Ursprungsarray:
+
+ int *i, *j;
+ i=({({1,2,3}),({4,5,6})});
+ j=filter(i, #'sizeof); // filtert leere Arrays heraus
+ j[0][0]=8;
+
+ fuehrt zu: i==j==({({8,2,3}),({4,5,6})});
+
+ 2. Das Kopieren in das Rueckgabemapping erfolgt fuer jedes
+ Element nach Ausfuehrung der Filtermethode. Aenderungen der
+ Werte im Array in dieser Methode (globale Variable/Uebergabe als
+ Referenz an filter) schlagen sich also im Rueckgabearray nieder.
+
+ 3. Fuer Arrays wirkt filter() wie filter_array(), fuer Mappings
+ stellt filter() eine Verallgemeinerung von filter_indices() dar.
+
+
+BEISPIELE
+=========
+
+ ### Filtere alle Lebewesen in einem Raum in ein Array ###
+ filter(all_inventory(this_object()),#'living);
+
+ ### Filtere alle tauben Spieler im Raum in ein Array ###
+ static int filter_isdeaf(object who) {
+ return (interactive(who) && who->QueryProp(P_DEAF));
+ }
+
+ filter(all_inventory(this_object()), #'filter_isdeaf);
+
+
+ ### Filtern von Idlern (>=1 Sekunde idle) ###
+ // Folgend identische Resultate, aber andere Ansaetze:
+
+ #1: nutzt die Efun query_idle() als Lfun-Closure (ideal hier)
+ idle_usr = filter(users(), #'query_idle );
+
+ #2: mit Filtermethode
+ int check_if_idle(object user) {
+ return query_idle(user);
+ }
+
+ #2a: filtert mittels der Lfun im selben Objekt die Idler in das
+ Rueckgabearray
+ idle_usr = filter(users(), "check_if_idle");
+ idle_usr = filter(users(), "check_if_idle", this_object());
+
+ #2b: ruft die Lfun check_if_idle() als Lfun-Closure (Funktions-
+ pointer)
+ idle_usr = filter(users(), #'check_if_idle );
+
+ #3: Nutzt eine Inline-Closure
+ idle_usr = filter(users(), function int (object user) {
+ return query_idle(user);
+ } );
+
+ ### Filtern von Idlern (>=20 Sekunden idle) mit Extraparameter ###
+ // Folgend identische Resultate, aber andere Ansaetze:
+
+ #1: die Efun koennen wir nicht mehr direkt nutzen, weil sie
+ diesen Parameter nicht unterstuetzt
+ // idle_usr = filter(users(), #'query_idle );
+
+ #2: mit separater Filtermethode ... mit neuem Parameter
+ int check_if_idle(object user, int length) {
+ return query_idle(user)>length;
+ }
+
+ #2a: filtert mittels der Lfun im selben Objekt die Idler in das
+ Rueckgabearray ... mit drittem Parameter!
+ idle_usr = filter(users(), "check_if_idle", this_object(), 20);
+
+ #2b: ruft die Lfun check_if_idle() als Lfun-Closure (Funktions-
+ pointer)
+ idle_usr = filter(users(), #'check_if_idle, 20);
+
+ #3: Nutzt eine Inline-Closure
+ idle_usr = filter(users(), function int (object user, int length) {
+ return (query_idle(user) > length);
+ }, 20);
diff --git a/doc/efun-mg/filter_objects b/doc/efun-mg/filter_objects
new file mode 100644
index 0000000..c13d46e
--- /dev/null
+++ b/doc/efun-mg/filter_objects
@@ -0,0 +1,27 @@
+
+filter_objects
+**************
+
+
+BEMERKUNGEN
+===========
+
+ Werden Pfade angegeben, so wird versucht ein Objekt zu laden, falls
+ dieses nicht existiert.
+
+
+BEISPIELE
+=========
+
+ // gibt alle tauben Personen wieder
+ deaf=filter_objects(users(), "QueryProp", P_DEAF);
+
+ // gibt alle blinden Personen wieder
+ blind=filter_objects(users(), "QueryProp", P_BLIND);
+
+ // filtert alle Objekte auf eine bestimmte ID (-> present)
+ idmatch=filter_objects(arr, "id", "irgendwasID");
+
+ // gibt alle Autoloader wieder
+ al=filter_objects(all_inventory(this_player()),
+ "QueryProp", P_AUTOLOADOBJ);
diff --git a/doc/efun-mg/find_call_out b/doc/efun-mg/find_call_out
new file mode 100644
index 0000000..610095d
--- /dev/null
+++ b/doc/efun-mg/find_call_out
@@ -0,0 +1,33 @@
+
+find_call_out
+*************
+
+
+BEISPIELE
+=========
+
+ // Findet sich kein call_out auf die Funktion 'func', so kann er
+ // gestartet werden. (Wichtig falls der call_out nicht mehrfach
+ // aufgerufen werden soll).
+
+ if(find_call_out("func")==-1)
+ call_out("func",5);
+
+
+BEMERKUNGEN
+===========
+
+ Die Suche nach call_out()s auf Closures funktioniert nur, wenn der
+ genaue Wert der Closure gesucht wird.
+
+ // Das funktioniert:
+ closure cl = symbol_function("main", obj);
+ call_out(cl, 2);
+ find_call_out(cl);
+
+ // Das funktioniert nicht:
+ call_out(symbol_function("main", obj), 2);
+ find_call_out(symbol_function("main", obj));
+
+ Ein Codebeispiel, um alle call_out()s auf eine Funktion zu
+ entfernen, findet sich in der Manpage zu remove_call_out().
diff --git a/doc/efun-mg/get_eval_cost b/doc/efun-mg/get_eval_cost
new file mode 100644
index 0000000..2f65c28
--- /dev/null
+++ b/doc/efun-mg/get_eval_cost
@@ -0,0 +1,42 @@
+
+get_eval_cost
+*************
+
+
+BEMERKUNGEN
+===========
+
+ Der Maximalwert betraegt zur Zeit 1.500.000 Ticks (Stand: 2020).
+
+ Sollten die Ticks waehrend der Ausfuehrung irgendwo auf 0 fallen,,
+ wird ein Fehler der Art "too long eval" erzeugt.
+
+ Diese Funktion dient dazu, solche Fehler zu verhindern oder genauer
+ zu lokalisieren an welchen Stellen im Code wieviel Ticks verbraucht
+ werden.
+
+
+BEISPIELE
+=========
+
+ // Ticks zaehlen
+ void foo()
+ {
+ int prev, used, i;
+
+ prev=get_eval_cost(); // Merken, was bis hierhin verbraucht wurde
+ for (i=0;i<=1000;i++) // Dann kommt der zu testende Code, zB eine
+ { // Schleife
+ ...
+ }
+ used=prev-get_eval_cost(); // Berechnung der Differenz
+ printf("Die Schleife verbrauchte %d Ticks.\n", used);
+ }
+
+ // Ticks im Auge behalten bei der Ausfuehrung
+ foreach(...)
+ {
+ ... // komplexer code
+ if (get_eval_cost() < 100000)
+ break;
+ }
diff --git a/doc/efun-mg/lambda b/doc/efun-mg/lambda
new file mode 100644
index 0000000..22a8630
--- /dev/null
+++ b/doc/efun-mg/lambda
@@ -0,0 +1,26 @@
+
+lambda
+******
+
+
+BEMERKUNGEN
+===========
+
+ Von der Verwendung wird aus Lesbarkeits- und Wartungsgruenden
+ dringend abgeraten.
+
+
+BEISPIEL
+========
+
+ Das Beispiel dient nur der Illustration, nicht zur Nachahmung.
+ Bitte verwendet lfun- oder inline-Closures.
+
+ // Lambdas werden gern eingesetzt, um komplexere Filter zu schreiben
+ // Allerdings kann jede Lambda dabei auch durch eine Inline-Closure
+ // oder eine LFun-Closure ersetzt werden.
+ filter(users(),
+ lambda(({'x}),
+ ({#'==,
+ ({#'call_other,'x,"QueryProp",P_SECOND}),"gloinson"
+ })));
diff --git a/doc/efun-mg/limited b/doc/efun-mg/limited
new file mode 100644
index 0000000..9465d71
--- /dev/null
+++ b/doc/efun-mg/limited
@@ -0,0 +1,14 @@
+
+limited
+*******
+
+
+BEMERKUNGEN
+===========
+
+ Diese Funktion kann bei uns mudlibweit genutzt werden. Allerdings
+ wird nur die _Reduktion_ von LIMIT_EVAL zugelassen, alle anderen
+ Limits duerfen _nicht_ veraendert werden. Hierbei ist zu beachten,
+ dass das Limit fuer LIMIT_EVAL um min. 1000 Ticks unter den noch
+ verfuegbaren Ticks liegen muss (get_eval_cost()). Fuer LIMIT_COST
+ sind nur 0 und -100 zugelassen.
diff --git a/doc/efun-mg/map_objects b/doc/efun-mg/map_objects
new file mode 100644
index 0000000..e9e0f48
--- /dev/null
+++ b/doc/efun-mg/map_objects
@@ -0,0 +1,29 @@
+
+map_objects
+***********
+
+
+BEMERKUNGEN
+===========
+
+ Werden Pfade angegeben, so wird versucht ein Objekt zu laden, falls
+ dieses nicht existiert.
+
+
+BEISPIELE
+=========
+
+ // ersetze alle Objekte durch ihre Namen
+ arr=map_objects(inputarr, "name");
+
+ // ersetze alle Objekte durch ihre Namen im Genitiv
+ arr=map_objects(inputarr, "name", WESSEN);
+
+ // AeQUIVALENZCODE (nicht empfohlen, nur zum Verstaendnis!):
+ int i;
+ object *ret; mixed *input;
+
+ i=sizeof(input);
+ ret=allocate(i);
+ while(i--)
+ ret[i]=input[i]->fun([extra1, extra2, ...]);
diff --git a/doc/efun-mg/raise_error b/doc/efun-mg/raise_error
new file mode 100644
index 0000000..562cc84
--- /dev/null
+++ b/doc/efun-mg/raise_error
@@ -0,0 +1,12 @@
+
+raise_error
+***********
+
+
+BEMERKUNGEN
+===========
+
+ Der String sollte umgebrochen oder wenigstens mit einem n
+ terminiert werden, da die Ausgabe direkt an den interaktiven Magier
+ erfolgen kann bzw. auf dem Debug-Kanal das letzte Zeichen entfernt
+ wird.
diff --git a/doc/efun-mg/random b/doc/efun-mg/random
new file mode 100644
index 0000000..a6077dd
--- /dev/null
+++ b/doc/efun-mg/random
@@ -0,0 +1,26 @@
+
+BEISPIELE
+*********
+
+ // Einfache Abfrage z.B. aus der HitFunc einer Waffe:
+ if(random(101) >= 70)
+ return random(11);
+ else
+ return 0;
+
+ // Spieler soll in einen zufaellig ausgewaehlten Raum gemovt
+ // werden:
+ string *dest = ({ "raum1","raum2","raum3","raum4","raum5" });
+ this_player()->move(dest[random(sizeof(dest))],M_GO);
+
+ // Es soll eine zufaellige Meldung ausgegeben werden:
+ tell_object(this_player(),
+ ({ "Es knackt.\n", "Dir ist kalt.\n", "Du schwitzt.\n",
+ "Du bekommst Angst.\n", "Hinter Dir knackt es im Gebuesch.\n",
+ "Ein kuehler Wind kommt auf.\n" })[random(6)]);
+ // Hinweis: ist es nicht sehr effizient, dafuer staendig ein Array neu zu
+ // erzeugen.
+
+ Wie man sieht, gibt es fuer random() viele schoene Einsatz-
+ moeglichkeiten. Wobei letzteres Beispiel ueber AddRoomMessage (fuer
+ Raeume) viel einfacher umzusetzen ist.
diff --git a/doc/efun-mg/replace_program b/doc/efun-mg/replace_program
new file mode 100644
index 0000000..f715e67
--- /dev/null
+++ b/doc/efun-mg/replace_program
@@ -0,0 +1,12 @@
+
+replace_program
+***************
+
+
+BEMERKUNGEN
+===========
+
+ Raeume benutzen replace_program automatisch. Es selten sinnvoll
+ oder notwendig, replace_program selbst einzusetzen! Wenn ihr es
+ einsetzt, ist vermutlich eine Konsultaton mit einem Erzmagier (fuer
+ Driver oder Mudlib) sinnvoll.
diff --git a/doc/efun-mg/save_object b/doc/efun-mg/save_object
new file mode 100644
index 0000000..1674836
--- /dev/null
+++ b/doc/efun-mg/save_object
@@ -0,0 +1,15 @@
+
+save_object
+***********
+
+
+BEMERKUNGEN
+===========
+
+ Bitte beachten, dass diese efun im MG durch eine Sefun
+ ueberschrieben wird und deren Manpage auch lesen!
+
+ Damit ein Objekt in Verzeichnisse der Region/des Magiers schreiben
+ kann, muss es entsprechende Rechte, also eine gueltige EUID
+ besitzen. Viele Objekte setzen diese im create() automatisch.
+ Ansonsten ist an passender Stelle ein Aufruf von seteuid() noetig.
diff --git a/doc/efun-mg/say b/doc/efun-mg/say
new file mode 100644
index 0000000..8a50af4
--- /dev/null
+++ b/doc/efun-mg/say
@@ -0,0 +1,18 @@
+
+say
+***
+
+
+BEMERKUNGEN
+===========
+
+ * da say() in der Vergangenheit wg. des Automatismus der
+ Zielbestimmung oft an die falschen Spieler ausgegeben hat, wird
+ von der Verwendung abgeraten.
+
+ * Bitte ReceiveMsg() benutzen, sofern sinnvoll
+
+ * fuer laengere Meldungen sollte break_string() verwendet werden
+
+ * say(<str>) ist verhaltensgleich zu tell_room(environment(),
+ <str>, ({this_player()||this_object()}))
diff --git a/doc/efun-mg/set_next_reset b/doc/efun-mg/set_next_reset
new file mode 100644
index 0000000..129be10
--- /dev/null
+++ b/doc/efun-mg/set_next_reset
@@ -0,0 +1,29 @@
+
+set_next_reset
+**************
+
+
+BEISPIELE
+=========
+
+ // ein Objekt mit verkuerzter reset()-Zeit
+ void create() {
+ ...
+ set_next_reset(15*60); // ~ 15 Minuten
+ ...
+ }
+
+ void reset() {
+ set_next_reset(900); // die muss im reset() immer wieder
+ ::reset(); // neu gesetzt werden
+ }
+
+ // ein Objekt, dessen Blueprint keinen reset() bekommen soll
+ void create() {
+ if(!clonep(this_object())) {
+ set_next_reset(-1);
+ return;
+ }
+ ::create();
+ ...
+ }
diff --git a/doc/efun-mg/sort_array b/doc/efun-mg/sort_array
new file mode 100644
index 0000000..0a5ddd8
--- /dev/null
+++ b/doc/efun-mg/sort_array
@@ -0,0 +1,53 @@
+
+sort_array
+**********
+
+
+BEMERKUNGEN
+===========
+
+ Achtung, die Elemente in 'arr' werden nicht tief kopiert, sind sie
+ also selbst Arrays oder Mappings, so fuehrt eine Aenderung im
+ Rueckgabe- Array zur Aenderung im Ursprungsarray.
+
+
+BEISPIELE
+=========
+
+ 1. Sortieren von Zahlen in aufsteigender Reihenfolge
+
+ int *arr = ({ 3, 8, 1, 3 })
+
+ // Folgend identische Resultate, aber andere Ansaetze:
+ #1: nutzt die 'Efun' > als Lfun-Closure (ideal hier):
+ sort_array(arr, #'>);
+
+ #2: mit Sortierfunktion im selben Objekt:
+ int is_greater (int a, int b) {
+ return a > b;
+ }
+
+ #2a: sortiert mittels der Lfun im selben Objekt die Elemente in das
+ Rueckgabearray
+ sort_array(arr, "is_greater", this_object())
+ sort_array(arr, "is_greater")
+
+ #2b: nutzt die Lfun is_greater() als Lfun-Closure (Funktionspointer)
+ sort_array(arr, #'is_greater)
+
+ #3: Nutzt eine Inline-Closure
+ sort_array(arr, function int (int a, int b) {
+ return a > b; } );
+
+ Resultat in allen Faellen: ({1,3,3,8})
+
+ 2. Sortieren von geschachtelten Arrays
+
+ arr = ({ ({ "foo", 3 }), ({ "quux", 1 }), ... })
+
+ // Vorgehen identisch, allerdings muss die Sortierfunktion
+ // angepasst werden:
+
+ int is_greater (<string|int> *a, <string|int> *b) {
+ return a[1] > b[1];
+ }
diff --git a/doc/efun-mg/tell_room b/doc/efun-mg/tell_room
new file mode 100644
index 0000000..aebb16f
--- /dev/null
+++ b/doc/efun-mg/tell_room
@@ -0,0 +1,49 @@
+
+tell_room
+*********
+
+
+BEMERKUNGEN
+===========
+
+ Wird in einem catch_msg() der Wert von <msg> veraendert, erhalten
+ alle nachfolgenden Objekte das veraenderte <msg> (Referenz!)
+
+
+BEISPIELE
+=========
+
+ // Dies ist ein einfaches Beispiel fuer eine Meldung an alle An-
+ // wesenden im Raum.
+
+ tell_room(this_object(),"Ein leichter Wind kommt auf.\n");
+
+ // Diese Meldung wird im Raum /d/ebene/ark/raum.c ausgegeben, dieser
+ // Raum muss nicht derjenige sein, in dem das tell_room() ausgefuehrt
+ // wird.
+
+ tell_room("/d/ebene/ark/raum","Ein leichter Wind kommt auf.\n");
+
+
+ // Diese Meldung wird an alle Anwesenden im Raum AUSSER this_player()
+ // (der diese Meldung ausgeloest hat) ausgegeben. Der muss eine ge-
+ // sonderte Meldung ueber sein Stolpern per write() oder
+ // tell_object() bekommen.
+ tell_room(this_object(),
+ break_string(this_player()->Name()+" stolpert.", 78),
+ ({ this_player() }));
+ tell_object(this_player(), "Du stolperst.\n");
+
+ // Ein Beispiel mit zwei Objekten, das zeigt, wie das Zusammenspiel
+ // von catch_tell() und tell_room() ablaueft. Objekt1 ist ein
+ // Lebewesen mit Namen "Dummymonster", Objekt2 verteilt die Meldung:
+
+ Objekt1 (ein Lebewesen, steht im Env von this_player()):
+ void catch_tell(string str) {
+ write("Empfangen: "+str+"\n");
+ }
+
+ Objekt2:
+ void fun() {
+ tell_room(environment(this_player()), "Hallo Welt!\n");
+ }
diff --git a/doc/efun-mg/walk_mapping b/doc/efun-mg/walk_mapping
new file mode 100644
index 0000000..87f5106
--- /dev/null
+++ b/doc/efun-mg/walk_mapping
@@ -0,0 +1,31 @@
+
+walk_mapping
+************
+
+
+BEISPIELE
+=========
+
+ In einem Mapping (Keys: Spielerobjekte) soll auf alle Werte etwas
+ drauf addiert werden:
+
+ // Liste mit Spielern durchgehen ...
+ mapping x=([ [/human:liafar]: 20,
+ [/dwarf:mesirii]: 50,
+ [/elf:zarniya]: 40,
+ [/feline:turbo]: 30]);
+
+ // ... und Werte aendern:
+ void add_val(object key, int val, int add) {
+ if(key->InFight())
+ val+=add;
+ else
+ val-=add;
+ }
+
+ // verschiedene Aufrufarten, identisches Resultat:
+ walk_mapping(x, "add_val", 0, 10);
+ walk_mapping(x, "add_val", this_object(), 10
+ walk_mapping(x, "add_val", "/players/jof/addierobjektmitmethode", 10);
+
+ walk_mapping(x, #'add_val, 10);