rst gefixt, Files erzeugt

Update autoerzeugter Manapges

Change-Id: I68afa0ee3d81fefa13ebd61df096a31812f2a4d1
diff --git a/doc/efun-mg.index b/doc/efun-mg.index
new file mode 100644
index 0000000..b963327
--- /dev/null
+++ b/doc/efun-mg.index
@@ -0,0 +1,53 @@
+
+MG-Manpages fuer efuns
+**********************
+
+Fuer einige efuns haben wir Ergaenzungen, Bemerkungen oder Beispiele
+zu den Manpages aus dem Driver erstellt. Diese sind im Folgenden zu
+finden.
+
+Verzeichnis der dokumentierten sefuns im Morgengrauen:
+
+* add_action(E)
+
+* all_inventory
+
+* call_out
+
+* count_bits
+
+* environment
+
+* file_size
+
+* filter
+
+* filter_objects
+
+* find_call_out
+
+* get_eval_cost
+
+* lambda
+
+* limited
+
+* map_objects
+
+* raise_error
+
+* BEISPIELE
+
+* replace_program
+
+* save_object
+
+* say
+
+* set_next_reset
+
+* sort_array
+
+* tell_room
+
+* walk_mapping
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);
diff --git a/doc/index b/doc/index
index 17ea1f3..ffb46ab 100644
--- a/doc/index
+++ b/doc/index
@@ -12,6 +12,8 @@
 
 * Allgemeine Informationen fuer Magier
 
+* MG-Manpages fuer efuns
+
 
 Indices and tables
 ******************
diff --git a/doc/lfun-liste b/doc/lfun-liste
index 98653a7..5aa5b31 100644
--- a/doc/lfun-liste
+++ b/doc/lfun-liste
@@ -850,6 +850,8 @@
 
 * query_real_name()
 
+* query_userlist()
+
 * query_weight_contents()
 
 * reduce_hit_points()
diff --git a/doc/lfun/Defend_bsp b/doc/lfun/Defend_bsp
index 5ef0350..e3e4261 100644
--- a/doc/lfun/Defend_bsp
+++ b/doc/lfun/Defend_bsp
@@ -10,146 +10,159 @@
 FUNKTION
 ========
 
-   varargs int Defend(int dam, mixed dam_type, mixed spell, object enemy)
+   varargs int Defend(int dam, mixed dam_type, mixed spell, object
+   enemy)
 
 
 BEMERKUNGEN
 ===========
 
-   Die hier aufgefuehrten Komplexbeispiele sind zum Verstaendnis gedacht.
+   Die hier aufgefuehrten Komplexbeispiele sind zum Verstaendnis
+   gedacht.
 
 
 BEISPIELE
 =========
 
-   1) Ein ordinaerer Biss ins Bein.
-      this_player()->Defend(random(500),
-                            ({DT_PIERCE, DT_RIP}),
-                            0,
-                            this_object());
+   1. Ein ordinaerer Biss ins Bein.
 
-   2) Ein Biss ins Bein, mit der Hose als 200%ige Ruestung und Rest mit 100%.
-      this_player()->Defend(random(500),
-                            ({DT_PIERCE, DT_RIP}),
-                            ([SP_PHYSICAL_ATTACK: 1,
-                              SP_REDUCE_ARMOUR:   ([AT_TROUSERS: 200])
-                            ]),
-                            this_object());
+         this_player()->Defend(random(500),
+                               ({DT_PIERCE, DT_RIP}),
+                               0,
+                               this_object());
 
-   3) Der Biss, wenn ein Tier in die Hose gekrochen ist und dieser ohne
-      Treffermeldung und physischen Ruestungsschutz durchgeht.
-      this_player()->Defend(random(500),
-                            ({DT_PIERCE, DT_RIP}),
-                            ([SP_PHYSICAL_ATTACK: 0, SP_SHOW_DAMAGE:0]),
-                            this_object());
+   2. Ein Biss ins Bein, mit der Hose als 200%ige Ruestung und Rest
+      mit 100%.
 
-   4) Spell-Parameter
-      // Beispiel fuer einen Spell, der nur vom Helm normal und von einem
-      // Amulett mit 115% aufgehalten wird, alle anderen (angebenenen)
-      // Ruestungen haben 0% Schutzwirkung.
-      // Mit Ausgabe eigener Meldungen: beginnend mit -1, da der verursachte
-      // Schadenswert minimal 0 wird (fuers Ersetzen: Feind: @WEx2,
-      // Spieler: WEx1); maximal wird er (Empfindlichkeiten jetzt mal aussen
-      // vor) 49 (499/10 = 49), nicht 499!!!
-      this_player()->Defend(
-        random(500),
-        ({DT_PIERCE, DT_AIR}),
-        ([SP_PHYSICAL_ATTACK: 1, // wegen DT_PIERCE
-          SP_REDUCE_ARMOUR:   ([AT_ARMOUR:   0,
-                                AT_HELMET: 100,
-                                AT_RING:     0,
-                                AT_GLOVE:    0,
-                                AT_CLOAK:    0,
-                                AT_BOOT:     0,
-                                AT_TROUSERS: 0,
-                                AT_SHIELD:   0,
-                                AT_AMULET: 115,
-                                AT_MISC:     0,
-                                AT_BELT:     0,
-                                AT_QUIVER:   0])
-          SP_SHOW_DAMAGE:
-                ({({-1,"@WER2 schrammt Dich mit einem durchbohrenden Blick.",
-                       "Du schrammst @WEN1 mit einem durchbohrenden Blick.",
-                       "@WER2 schrammt @WEN1 mit einem durchbohrenden Blick."
-                  }),
-                  ({5,"Der durchbohrende Blick von @WEM2 trifft Dich.",
-                      "Dein durchbohrender Blick trifft @WEN1.",
-                      "Der durchbohrende Blick von @WEM2 trifft @WEN1."
-                  }),
-                  ({20,"@WESSEN2 stechender Blick durchbohrt Dich.",
-                       "Dein stechender Blick durchbohrt @WEN1.",
-                       "@WESSEN2 stechender Blick durchbohrt @WEN1."
-                })})
-        ]),
-        this_object());
+         this_player()->Defend(random(500),
+                               ({DT_PIERCE, DT_RIP}),
+                               ([SP_PHYSICAL_ATTACK: 1,
+                                 SP_REDUCE_ARMOUR:   ([AT_TROUSERS: 200])
+                               ]),
+                               this_object());
 
-      // Etwas geschickter geht das Ganze, wenn wir einfach aus der Mudlib
-      // alle existierenden Ruestungen in ein Mapping packen und diese
-      // nullen (damit sind wir auch gegen neue Ruestungstypen sicher):
-      mapping amap = map_indices(VALID_ARMOUR_CLASS,#'!);
-      amap[AT_HELMET]=100;
-      amap[AT_AMULET]=115;
+   3. Der Biss, wenn ein Tier in die Hose gekrochen ist und dieser
+      ohne Treffermeldung und physischen Ruestungsschutz durchgeht.
 
-      this_player()->Defend(random(500),
-                            ({DT_PIERCE, DT_AIR}),
-                            ([SP_PHYSICAL_ATTACK: 1,
-                              SP_REDUCE_ARMOUR: amap,
-                              SP_SHOW_DAMAGE: ({ ... (siehe oben)
+         this_player()->Defend(random(500),
+                               ({DT_PIERCE, DT_RIP}),
+                               ([SP_PHYSICAL_ATTACK: 0, SP_SHOW_DAMAGE:0]),
+                               this_object());
 
-   5) Der Biss von weiter oben mit Meldung.
-      // Eine Meldung, die nur ausgegeben wird, wenn der Biss auch mindestens
-      // einen LP abzieht.
-      this_player()->Defend(random(500),
-                            ({DT_PIERCE, DT_RIP}),
-                            ([SP_PHYSICAL_ATTACK: 1,
-                              SP_REDUCE_ARMOUR:   ([AT_TROUSERS: 200]),
-                              SP_SHOW_DAMAGE: ({
-                                ({1,"@WER2 beisst Dich ins Bein!",
-                                    "Du beisst @WEN1 ins Bein!",
-                                    "@WER2 beisst @WEN1 ins Bein!"
-                                 })           })
-                            ]),
-                            this_object());
+   4. Spell-Parameter Beispiel fuer einen Spell, der nur vom Helm
+      normal und von einem Amulett mit 115% aufgehalten wird, alle
+      anderen (angebenenen) Ruestungen haben 0% Schutzwirkung. Mit
+      Ausgabe eigener Meldungen: beginnend mit -1, da der verursachte
+      Schadenswert minimal 0 wird (fuers Ersetzen: Feind: @WEx2,
+      Spieler: WEx1); maximal wird er (Empfindlichkeiten jetzt mal
+      aussen vor) 49 (499/10 = 49), nicht 499!!!
 
-   6) DefendFunc() und Defend() in einem Objekt
-      6a)
-      // eine Luftangriffe reflektierende Ruestung:
-      int DefendFunc(string *dtyp, mixed spell, object enemy) {
-        if(member(dtyp, DT_AIR)>=0 && !spell[SP_RECURSIVE])
-          enemy->Defend(random(200),
-                        ({DT_AIR}),
-                        ([SP_RECURSIVE: 1,
-                          SP_SHOW_DAMAGE:
-                          ({"Ein Luftwirbel erfasst auch Dich.",
-                            "Deine Ruestung wirbelt @WEN1 herum.",
-                            "@WESSEN2 Ruestung wirbelt @WEN1 herum."
-                           })
-                        ]),
-                        QueryProp(P_WORN));
+         this_player()->Defend(
+          random(500),
+          ({DT_PIERCE, DT_AIR}),
+          ([SP_PHYSICAL_ATTACK: 1, // wegen DT_PIERCE
+            SP_REDUCE_ARMOUR:   ([AT_ARMOUR:   0,
+                                  AT_HELMET: 100,
+                                  AT_RING:     0,
+                                  AT_GLOVE:    0,
+                                  AT_CLOAK:    0,
+                                  AT_BOOT:     0,
+                                  AT_TROUSERS: 0,
+                                  AT_SHIELD:   0,
+                                  AT_AMULET: 115,
+                                  AT_MISC:     0,
+                                  AT_BELT:     0,
+                                  AT_QUIVER:   0])
+            SP_SHOW_DAMAGE:
+                  ({({-1,"@WER2 schrammt Dich mit einem durchbohrenden Blick.",
+                         "Du schrammst @WEN1 mit einem durchbohrenden Blick.",
+                         "@WER2 schrammt @WEN1 mit einem durchbohrenden Blick."
+                    }),
+                    ({5,"Der durchbohrende Blick von @WEM2 trifft Dich.",
+                        "Dein durchbohrender Blick trifft @WEN1.",
+                        "Der durchbohrende Blick von @WEM2 trifft @WEN1."
+                    }),
+                    ({20,"@WESSEN2 stechender Blick durchbohrt Dich.",
+                         "Dein stechender Blick durchbohrt @WEN1.",
+                         "@WESSEN2 stechender Blick durchbohrt @WEN1."
+                  })})
+          ]),
+          this_object());
 
-        return 0; // -> In diesem Fall gibts keinen Ruestungsbonus!
-      }
+      Etwas geschickter geht das Ganze, wenn wir einfach aus der
+      Mudlib alle existierenden Ruestungen in ein Mapping packen und
+      diese nullen (damit sind wir auch gegen neue Ruestungstypen
+      sicher):
 
-      6b)
-      // Eine NUR REINE Luftangriffe reflektierende Ruestung:
-      int DefendFunc(string *dtyp, mixed spell, object enemy) {
-        if(!sizeof(dtyp-({DT_AIR})) && !spell[SP_RECURSIVE])
-          ...
+         mapping amap = map_indices(VALID_ARMOUR_CLASS,#'!);
+         amap[AT_HELMET]=100;
+         amap[AT_AMULET]=115;
+
+         this_player()->Defend(random(500),
+                               ({DT_PIERCE, DT_AIR}),
+                               ([SP_PHYSICAL_ATTACK: 1,
+                                 SP_REDUCE_ARMOUR: amap,
+                                 SP_SHOW_DAMAGE: ({ ... (siehe oben)
+
+   5. Der Biss von weiter oben mit Meldung. Eine Meldung, die nur
+      ausgegeben wird, wenn der Biss auch mindestens einen LP abzieht.
+
+         this_player()->Defend(random(500),
+                               ({DT_PIERCE, DT_RIP}),
+                               ([SP_PHYSICAL_ATTACK: 1,
+                                 SP_REDUCE_ARMOUR:   ([AT_TROUSERS: 200]),
+                                 SP_SHOW_DAMAGE: ({
+                                   ({1,"@WER2 beisst Dich ins Bein!",
+                                       "Du beisst @WEN1 ins Bein!",
+                                       "@WER2 beisst @WEN1 ins Bein!"
+                                    })           })
+                               ]),
+                               this_object());
+
+   6. DefendFunc() und Defend() in einem Objekt
+
+      1. eine Luftangriffe reflektierende Ruestung:
+
+            int DefendFunc(string *dtyp, mixed spell, object enemy) {
+               if(member(dtyp, DT_AIR)>=0 && !spell[SP_RECURSIVE])
+                 enemy->Defend(random(200),
+                               ({DT_AIR}),
+                               ([SP_RECURSIVE: 1,
+                                 SP_SHOW_DAMAGE:
+                                 ({"Ein Luftwirbel erfasst auch Dich.",
+                                   "Deine Ruestung wirbelt @WEN1 herum.",
+                                   "@WESSEN2 Ruestung wirbelt @WEN1 herum."
+                                  })
+                               ]),
+                               QueryProp(P_WORN));
+
+               return 0; // -> In diesem Fall gibts keinen Ruestungsbonus!
+            }
+
+      2. Eine NUR REINE Luftangriffe reflektierende Ruestung:
+
+            int DefendFunc(string *dtyp, mixed spell, object enemy) {
+              if(!sizeof(dtyp-({DT_AIR})) && !spell[SP_RECURSIVE])
+              ...
 
 
 SIEHE AUCH
 ==========
 
-   Angriff:   Attack(L), P_NO_ATTACK, InsertEnemy(L)
-   Schaden:   P_ENABLE_IN_ATTACK_OUT, P_LAST_MOVE, do_damage(L),
-              reduce_hit_points(L), reduce_spell_points(L)
-   Schutz:    P_DEFENDERS, InformDefend(L), DefendOther(L),
-              P_ARMOURS, P_AC, P_DEFEND_FUNC, QueryDefend(L),
-              P_BODY, A_DEX, Defend(L)
-   Daten:     P_LAST_COMBAT_TIME, P_LAST_XP, P_LAST_DAMAGE,
-              P_LAST_DAMTYPES, P_LAST_DAMTIME
-   Resistenz: P_RESISTANCE_STRENGTHS, CheckResistance(L)
-   Sonstiges: CheckSensitiveAttack(L), UseSkill(L),
-              InternalModifyDefend(L)
+   * Angriff: Attack(), do_damage(), InsertEnemy(), P_NO_ATTACK
 
-25. Mai 2011 Gabylon
+   * Schaden: reduce_hit_points(), reduce_spell_points(),
+     P_ENABLE_IN_ATTACK_OUT, P_LAST_MOVE
+
+   * Schutz: InformDefend(), DefendOther(), QueryDefend(), Defend(),
+     P_DEFENDERS, P_ARMOURS, P_AC, P_DEFEND_FUNC, P_BODY
+
+   * Resistenz: CheckResistance(), P_RESISTANCE_STRENGTHS
+
+   * Daten: P_LAST_COMBAT_TIME, P_LAST_XP, P_LAST_DAMAGE,
+     P_LAST_DAMTYPES, P_LAST_DAMTIME
+
+   * Sonstiges CheckSensitiveAttack(), UseSkill(),
+     InternalModifyDefend()
+
+23.01.2020 Zesstra
diff --git a/doc/lfun/query_userlist b/doc/lfun/query_userlist
new file mode 100644
index 0000000..1dceab0
--- /dev/null
+++ b/doc/lfun/query_userlist
@@ -0,0 +1,73 @@
+
+query_userlist()
+****************
+
+
+FUNKTION
+========
+
+   public mixed query_userlist(string user, int prop)
+
+
+DEFINIERT IN
+============
+
+   /secure/master/userinfo.c
+
+
+ARGUMENTE
+=========
+
+   user
+      UID des abzufragenden Users
+
+   prop
+      Datum aus der Userliste, welches abgefragt werden soll
+
+
+BESCHREIBUNG
+============
+
+   Aus der Userliste des MG wird eine der folgenden Informationen
+   ueber den Spieler <user> abgefragt:
+
+   USER_LEVEL (int)
+      Magierlevel (1 fuer Seher)
+
+   USER_DOMAIN (string*)
+      Liste der Regionen, in der der Magier RM ist
+
+   USER_OBJECT (string)
+      Shell des Spielers
+
+   USER_CREATION_DATE (int)
+      Zeit des ersten Logins
+
+   USER_GUILD (string*)
+      Gilden, fuer welche die Spielerin Gildenmagierin ist
+
+   USER_EKTIPS (string)
+      Fuer welche EKs hat der Spieler einen Tip erhalten? Rueckgabe
+      als Bitstring, in welchem die entsprechenden Bits gesetzt sind.
+
+   USER_FPTIPS (string)
+      Fuer welche FPs hat der Spieler einen Tip erhalten? Rueckgabe
+      als Bitstring, in welchem die entsprechenden Bits gesetzt sind.
+
+   USER_UIDS_TO_TAKE_CARE (string*)
+      UIDs, fuer welche die Magierin zustaendig ist. Hierbei sind nur
+      explizit eingetragene in diesem Array, nicht welche, fuer sie
+      implizit kraft ihres Amtes zustaendig ist (z.B. als GM oder RM).
+
+   Die o.a. Konstanten sind in <userinfo.h> definiert.
+
+   Wenn der Spieler nicht existiert, wird 0 zurueckgegeben. Ein nicht
+   unterstuetztes <prop> loest einen Laufzeitfehler aus.
+
+
+SIEHE AUCH
+==========
+
+   *find_userinfo*
+
+Last modified: 21.01.2020, Zesstra
diff --git a/doc/props-liste b/doc/props-liste
index 84ae12c..fe9f231 100644
--- a/doc/props-liste
+++ b/doc/props-liste
@@ -798,6 +798,8 @@
 
 * P_TEAM_WIMPY_ROW
 
+* P_TELNET_CHARSET
+
 * P_TELNET_KEEPALIVE_DELAY
 
 * P_TELNET_RTTIME
diff --git a/doc/props/P_TELNET_CHARSET b/doc/props/P_TELNET_CHARSET
new file mode 100644
index 0000000..880b454
--- /dev/null
+++ b/doc/props/P_TELNET_CHARSET
@@ -0,0 +1,47 @@
+
+P_TELNET_CHARSET
+****************
+
+
+NAME
+====
+
+   P_TELNET_CHARSET
+   "p_lib_telnet_charset"
+
+
+DEFINIERT IN
+============
+
+   /secure/telnetneg.h
+
+
+BESCHREIBUNG
+============
+
+   In dieser Properties steht der Zeichensatz, den der Spieler manuell
+   konfiguriert hat. Das Spielerobjekt wird so konfiguriert, dass der
+   Driver - falls notwendig - alle Eingaben des Spielers von diesem
+   Zeichensatz nach UTF-8 und alle Ausgaben an den Spieler von UTF-8
+   in diesen Zeichensatz konvertiert.
+
+   Hierbei wird der manuell konfigurierte Zeichensatz allerdings nur
+   dann benutzt, wenn der Client des Spielers nicht mittels der
+   Telnet-Option CHARSET etwas anderes aushandelt!
+
+   Wird in dieser Property keine Einstellung vorgenommen und fuehrt
+   der Client keine Aushandlung durch, ist der Default im Morgengrauen
+   "ASCII//TRANSLIT".
+
+
+SIEHE AUCH
+==========
+
+   P_TTY_COLS, P_TTY_ROWS, P_TTY_SHOW, P_TTY, P_TTY_TYPE,
+   P_TELNET_RTTIME
+
+
+LETZTE AeNDERUNG
+================
+
+   16.01.2020, Zesstra
diff --git a/doc/sefun/getuuid b/doc/sefun/getuuid
index 63ea31e..840044c 100644
--- a/doc/sefun/getuuid
+++ b/doc/sefun/getuuid
@@ -6,15 +6,15 @@
 SYNOPSIS
 ========
 
-   string getuuid(object ob)
+   string getuuid(object|string ob)
 
 
 DESCRIPTION
 ===========
 
-   Liefert eine eindeutige (get unique uid) UID fuer einen Spieler.
-   Wird zusammengesetzt aus der UID des Spielers und seinem
-   Erstlogin-Datum.
+   Liefert eine eindeutige (get unique uid) UUID fuer einen Spieler.
+   Wird zusammengesetzt aus der UID des Spielers und seinem Erstlogin-
+   Datum.
 
    Nach einer Selbstloeschung und neuem Login erhaelt der Spieler eine
    neue UUID, bei einer Restaurierung behaelt er seine alte UUID.
@@ -22,8 +22,11 @@
    Wenn die Funktion ohne Parameter aufgerufen wird, wird per Default
    this_object() genommen.
 
+   Wird in <ob> ein string uebergeben, wird erwartet, dass es eine
+   Spieler-UID ist.
+
 
 SEE ALSO
 ========
 
-   getuid(E)
+   *../efun/getuid*
diff --git a/doc/sphinx/efun-mg/add_action.rst b/doc/sphinx/efun-mg/add_action.rst
index cac361a..cee9842 100644
--- a/doc/sphinx/efun-mg/add_action.rst
+++ b/doc/sphinx/efun-mg/add_action.rst
@@ -12,7 +12,7 @@
   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.)
+     Inventory, um immer "erstes" Objekt zu sein.)
 
 BEISPIELE
 ---------
diff --git a/doc/sphinx/efun-mg/filter.rst b/doc/sphinx/efun-mg/filter.rst
index 92244d8..9ff5285 100644
--- a/doc/sphinx/efun-mg/filter.rst
+++ b/doc/sphinx/efun-mg/filter.rst
@@ -91,5 +91,3 @@
                      return (query_idle(user) > length); 
                      }, 20);
 
-----------------------------------------------------------------------------
-23.09.2019, Zesstra
diff --git a/doc/sphinx/index.rst b/doc/sphinx/index.rst
index 9c9cf61..f0e4930 100644
--- a/doc/sphinx/index.rst
+++ b/doc/sphinx/index.rst
@@ -16,6 +16,7 @@
    props.index
    lfun.index
    wiz.index
+   efun-mg.index
 
 
 Indices and tables