Added public files

Roughly added all public files. Probably missed some, though.
diff --git a/std/player/command.c b/std/player/command.c
new file mode 100644
index 0000000..230445d
--- /dev/null
+++ b/std/player/command.c
@@ -0,0 +1,1074 @@
+// MorgenGrauen MUDlib
+//
+// player/commands.c -- alias, history and player command handling
+//
+// $Id: command.c 9576 2016-06-18 15:00:01Z Zesstra $
+#pragma strong_types
+#pragma save_types
+//#pragma range_check
+#pragma no_clone
+#pragma pedantic
+
+#define NEED_PROTOTYPES
+#include <player/command.h>
+#include <player/comm.h>
+#include <thing/properties.h>
+#include <living/moving.h>
+#include <player.h>
+#undef NEED_PROTOTYPES
+
+#include <properties.h>
+#include <language.h>
+#include <new_skills.h>
+#include <config.h>
+#include <defines.h>
+#include <wizlevels.h>
+#include <logging.h>
+#include <strings.h>
+
+#define CBLOG(x)    log_file(SHELLLOG("DISABLECOMMANDS"),x,200000)
+
+#define HIST_SIZE 40
+#define EPMASTER "/secure/explorationmaster"
+
+private mapping aliases;
+private string *commands;
+private int hist_size, show_processing, histmin;
+private string default_notify_fail;
+private nosave string *history, *unparsed_args, unmodified;
+private nosave int hist_now;
+private nosave object last_command_env;
+private nosave int cmds_per_time, last_chg, max_commands, *cmd_types;
+// Datenstruktur: ({Setzer, Ablaufzeit, String/Closure})
+private nosave mixed disablecommands;
+private nosave object* syntaxdb;
+
+nomask void __set_bb(int flag);
+
+static varargs int __auswerten(string str, string intern);
+varargs int SoulComm(string str, string _verb);
+varargs mixed More(string str, int fflag, string returnto);
+static int _starts_with(string str, string start);
+static void reallocate_histbuf();
+
+private void AddHistory(string str)
+{
+  if (!stringp(str) || str=="" || str[0]=='&' || str[0]=='^' ||
+      str=="hist")
+    return;
+  if (!hist_size) return;
+  if (!pointerp(history) || sizeof(history)!=hist_size)
+    reallocate_histbuf();
+  if (sizeof(str)>=histmin && history[(hist_size+hist_now-1)%hist_size]!=str)
+    history[(hist_now++)%hist_size]=str;
+}
+
+static void create()
+{
+  last_chg=0;
+  histmin=hist_now=0;
+  Set(P_LOCALCMDS,({}));
+  Set(P_LOCALCMDS,PROTECTED,F_MODE_AS);
+  Set("_syntaxdb", SECURED|SAVE, F_MODE_AS);
+
+  show_processing=1;
+  unparsed_args=({0,0,0});
+  hist_size=HIST_SIZE;
+}
+
+static int replacedisplay(string str)
+{
+  if (!str || str=="" || !sscanf(str,"%d",show_processing))
+    printf("Unzulaessige Eingabe!\n%s 0|1|2\n",query_verb());
+    printf("Ersetzungsanzeige auf Level %d.\nLevel 0: Nichts anzeigen\n"+
+     "Level 1: Nur History-Ersetzungen anzeigen\n"+
+     "Level 2: History- und Alias-Ersetzungen anzeigen\n",show_processing);
+  if (show_processing>2&&!IS_WIZARD(ME)) show_processing=2;
+  return 1;
+}
+
+static int histmin(string str)
+{
+  int len;
+
+  if (!str||!sscanf(str,"%d",len)||len<0)
+  {
+    write("Benutzung: histmin ZAHL\nLegt die Mindestlaenge fest, die eine \
+Befehlszeile haben muss, um in den\nHistory-Puffer zu gelangen. Derzeit \
+eingestellt auf "+(string)histmin+" Zeichen.\n");
+    return 1;
+  }
+  histmin=len;
+  write("Mindestlaenge auf "+(string)len+" eingestellt.\n");
+  return 1;
+}
+
+static void reallocate_histbuf()
+{
+  int i;
+
+  history=allocate(hist_size);
+  hist_now=0;
+  for (i=0;i<hist_size;i++)
+    if (!stringp(history[i]))
+      history[i]="\n\n";
+}
+
+static int histlen(string str)
+{
+  int d;
+  if (!str||!sscanf(str,"%d",d)||d<0||d>40)
+  {
+    write("Benutzung: histlen ZAHL\nZAHL muss zwischen 0 und 40 liegen.\n");
+    printf("Deine History-Buffer-Laenge liegt bei %d Befehlen.\n",hist_size);
+    return 1;
+  }
+  hist_size=d;
+  printf("Deine History-Buffer-Laenge liegt jetzt bei %d Befehlen.\n",
+   hist_size);
+  reallocate_histbuf();
+  return 1;
+}
+
+static void initialize()
+{
+  if (!pointerp(history)||sizeof(history)!=hist_size)
+    reallocate_histbuf();
+  add_action("__auswerten","",1);
+    max_commands = EPMASTER->QueryCommands();
+    cmd_types = EPMASTER->QueryCmdTypes() || ({});
+
+    if ( !mappingp(aliases) )
+        aliases = ([]);
+
+    if ( !pointerp(commands) )
+        commands = ({});
+
+    if (QueryProp("_syntaxdb"))
+        syntaxdb = ({find_object("/secure/syntaxdb")});
+/*    else if (QueryProp(P_TESTPLAYER))
+    {
+      SetProp("_syntaxdb", 1);
+      call_out(#'_notify, 2,
+          "\nDa Du als Testspieler markiert bist, wurde bei Dir "
+          "die Syntaxsammlung eingeschaltet. Du kannst dies "
+          "wieder ausschalten. (hilfe syntaxsammlung) "
+          "Es waere schoen, wenn Du es beim Testen von "
+          "Gebieten einschaltest.", 0);
+    }*/
+}
+
+static mixed _set_default_notify_fail(string s)
+{
+  if (stringp(s)&&s!="")
+  {
+    if (s[<1]!='\n') s+="\n";
+    return default_notify_fail=s;
+  }
+  else if (!s||s=="")
+    return (default_notify_fail=0);
+}
+
+static mixed _query_default_notify_fail()
+{
+  return default_notify_fail;
+}
+
+static int set_errormessage(string s)
+{
+  if (!(s=_unparsed_args()))
+  {
+    _set_default_notify_fail(0);
+    write("Standard-Fehlermeldung auf \"Wie bitte?\" gesetzt.\n");
+  } else
+  {
+    write(break_string(sprintf("Standard-Fehlermeldung auf %s gesetzt.\n",
+             s),78));
+    _set_default_notify_fail(s);
+  }
+  return 1;
+}
+
+void reconnect()
+{
+  if (!mappingp(aliases)) aliases=([]);
+
+    if ( !pointerp(commands) )
+        commands = ({});
+
+    max_commands = EPMASTER->QueryCommands();
+    cmd_types = EPMASTER->QueryCmdTypes() || ({});
+}
+
+static int show_hist()
+{
+  int i;
+  string comm;
+
+  tell_object( ME, "Die History-Liste enthaelt folgende Kommandos:\n" );
+
+  for( i = 0; i < hist_size; i++ )
+      if ((comm=history[(hist_now+i)% hist_size])!= "\n\n")
+          tell_object( ME, " &"+(hist_now+i-hist_size)+"/-"+ (hist_size-i-1)
+      +"\t= "+comm+"\n");
+  return 1;
+}
+
+static string present_alias(mixed *ali)
+{
+  int j,k;
+  string s,s2;
+
+  for (s="",j=sizeof(ali)-1;j>=0;j--)
+    if (intp(ali[j]))
+      if ((k=ali[j])<0)
+  s="$"+(k==-1?"":(string)-k)+"*"+s;
+      else
+  s="$"+(string)k+s;
+    else
+      {
+         s2=implode(explode(ali[j],"\\"),"\\\\");
+         s=implode(explode(s2,"$"),"\\$")+s;
+      }
+  return s;
+}
+
+#define ALIFORMAT ({" %s\t= %s", "alias %s %s"})[display_as_aliascommand]
+// Ich weiss, den Variablennamen im define zu haben ist unfein, aber das
+// macht es im Code dann angenehm uebersichtlich.  -HrT
+
+static int query_aliases(int display_as_aliascommand)
+{
+  int i;
+  string *a,*ali;
+
+  if(i=sizeof(ali=sort_array(m_indices(aliases),#'<))) //')))
+  {
+    for(a=({}),i--; i>=0; i--)
+        a+=({sprintf(ALIFORMAT, ali[i], present_alias( aliases[ali[i]] ) ) });
+    More("Du hast folgende Aliase definiert:\n"+implode(a,"\n"));
+  }
+  else
+    write("Du hast keine Aliase definiert.\n");
+  return 1;
+}
+
+static int
+_starts_with(string str, string start)
+{
+  return (sizeof(start)>sizeof(str) ? 0
+    : str[0..sizeof(start)-1]==start);
+}
+
+static int alias(string str)
+{
+  string command;
+  string *tmp,um,*hits;
+  int num, l, pos, cont;
+  int display_as_aliascommand;
+
+  if (unmodified&&unmodified!="")
+    um=implode(old_explode(unmodified," ")[1..]," ");
+  if (um=="") um=0;
+  if(!(str=um||_unparsed_args()) || str=="*") return query_aliases(0);
+
+    if (str=="-a" || strstr(str, "-a ")==0 )  {
+    str=str[2..];
+    if (str && str!="" && str[0]==' ') str=str[1..];
+    if (!str || str=="" || str=="*") return query_aliases(1);
+    display_as_aliascommand=1;
+  }
+
+  if ((pos=member(str,' '))<0) // 1 Arg only
+  {
+    if ((tmp=aliases[str]))
+      printf(ALIFORMAT+"\n",str,present_alias(tmp));
+    else
+      if (str[<1]=='*')
+      {
+        str=str[0..<2];
+        hits=filter(m_indices(aliases), #'_starts_with, str);
+        if (!sizeof(hits))
+        {
+          printf("Du hast kein Alias, das mit \"%s\" anfaengt.\n", str);
+          return 1;
+        }
+        hits=sort_array(hits, #'>);
+        for (l=sizeof(hits); l--;)
+          hits[l]=sprintf(ALIFORMAT, hits[l], present_alias(aliases[hits[l]]));
+        More("Folgende Aliase beginnen mit \""+str+"\":\n"+implode(hits,"\n"));
+      }
+    else
+      printf("Du hast kein Alias \"%s\" definiert.\n",str);
+    return 1;
+  }
+  if (!pos)
+  {
+    write("Fehler: Blanc am Alias-Anfang\n");
+    return 1;
+  }
+  if ((command=str[0..pos-1])=="unalias")
+  {
+    write
+      ("Es nicht moeglich, den Befehl unalias zu ueberladen (waer dumm :))\n");
+    return 1;
+  }
+  if ((command=str[0..pos-1])=="*")
+  {
+    write
+      ("Es nicht moeglich, den Befehl \"*\" zu ueberladen.\n");
+    return 1;
+  }
+
+  str=str[pos+1..],tmp=({});
+  while (l=sizeof(str)) {
+    pos=0,cont=1;
+    while (cont) {
+      if (pos<l) {
+        if(str[pos]=='\\') {
+          str=str[0..pos-1]+str[pos+1..];
+          l--;
+        } else {
+          if (str[pos]=='&' || str[pos]=='$') {
+            cont=0;
+            if (pos>0) {
+              tmp+=({str[0..pos-1]});
+            }
+            if (pos==l-1) {
+              printf("Fehler: %c am Zeilenende\n",str[pos]);
+              return 1;
+            }
+            if ((num=str[++pos])=='*') {
+              num=1;
+              pos--;
+            } else {
+              num-='0';
+            }
+            if (num<0 || num>9) {
+              printf("Fehler: Nach %c muss Ziffer oder * folgen\n",
+               str[pos-1]);
+              return 1;
+            }
+            if ((str=str[pos+1..])!=""&&str[0]=='*') {
+              str=str[1..];
+              num=-num;
+            }
+            tmp+=({num});
+          }
+        }
+        pos++;
+      } else {
+        cont=0;
+        if (str!="") tmp+=({str});
+        str="";
+      }
+    }
+  }
+  if ((!aliases[command]) && (sizeof(aliases)>2000))
+    printf("Du hast schon genuegend Aliase definiert!\n");
+  else
+  {
+    aliases[command]=tmp;
+    printf("Neues Alias: %s\t= %s\n",command,present_alias(tmp));
+  }
+  return 1;
+}
+
+static int unalias(string str) {
+  int i;
+  string *als,um;
+
+  if (unmodified&&unmodified!="")
+    um=implode(old_explode(unmodified," ")[1..]," ");
+  if (um=="") um=0;
+  if ( !(str=um || _unparsed_args())) return 0;
+  if (str == "*.*" || str == "*") {
+    write(break_string(
+      "Versuchs mal mit 'unalias .*', wenn Du wirklich alle Alias entfernen "
+      "willst.",78));
+    return 1;
+  }
+  if (!member(aliases,str)) {
+    als=regexp(m_indices(aliases),("^"+str+"$"));
+    if (!(i=sizeof(als))) {
+      write("So ein Alias hast Du nicht definiert.\n");
+      return 1;
+    }
+    for (--i;i>=0;i--)
+      m_delete(aliases,als[i]);
+    write(break_string(("Du entfernst folgende Aliase: "+
+      implode(als," ")+".\n"),75));
+    return 1;
+  }
+  m_delete(aliases,str);
+  write("Du entfernst das Alias \""+str+"\".\n");
+  return 1;
+}
+
+varargs string _unparsed_args(int level)
+{
+  return unparsed_args[level];
+}
+
+#define ARTIKEL ({"das","der","die","des","dem","den","ein","eine","einer",\
+                  "eines"})
+
+#define TRENNER ({"in","aus","ueber","auf","unter","mit","durch","fuer",\
+                  "von","vom","im","aufs","ein","weg","zurueck"})
+
+static string _single_spaces(string str)
+{
+  return regreplace(str, "  *", " ", 1);
+}
+
+static mixed _return_args(string str)
+{
+  string *t,*t2,verb,s2;
+  int i,l,j,l2;
+
+  t=explode(trim(str,TRIM_BOTH)," ");
+  verb=t[0];
+  t = t[1..];
+  if (!sizeof(t))
+  {
+    unparsed_args[0]=unparsed_args[1]=unparsed_args[2]=0;
+    return str=verb;
+  }
+  else
+    str = unparsed_args[0] = implode(t, " ");
+
+  str=unparsed_args[1]=lower_case(_single_spaces(str));
+  t=regexplode(str,"\\<im\\>|\\<ins\\>");
+  for (i=1;i<sizeof(t);i+=2) t[i]="in";
+  t=regexplode(implode(t,""),"[\\,\\!\\:][\\,\\!\\:]*");
+  l=sizeof(t);
+  for(i=1;i<l;i+=2) t[i]="";
+  t=old_explode(implode(t,"")," ")-({""});
+  for (i=sizeof(t)-2;i>=0;i--)
+  {
+    if (member(ARTIKEL,t[i])>=0)
+      t=t[0..i-1]+t[i+1..];
+  }
+  unparsed_args[2]=implode(t," ");
+  t=regexplode((str=implode(t," ")),"[0-9][0-9]*\\.");
+  if ((l=sizeof(t))>2)
+  {
+    i=1;
+    while (i<l-1)
+    {
+      t[i]=" "+t[i][0..<2]+" ";
+      if ((l2=sizeof(t2=old_explode(t[i+1]," ")))<2)
+  t[i+1]+=t[i];
+      else
+      {
+  for (j=1;j<l2;j++)
+  {
+    if (member(TRENNER,t2[j])>=0)
+    {
+      t2[j-1]+=t[i];
+      l2=0;
+    }
+  }
+  if (!l2)
+    t[i+1]=implode(t2," ");
+  else
+    t[i+1]+=t[i];
+      }
+      t[i]="";
+      i+=2;
+    }
+    str=_single_spaces(verb+" "+implode(t," "));
+    if (str[<1]==' ') str=str[0..<2];
+  } else str=verb+(str==""?"":" "+str);
+  if (show_processing>2)
+    printf("-> {%s}\n",str);
+  return str;
+}
+
+static void decay_average()
+{
+  if (absolute_hb_count()-last_chg>14)
+  {
+    last_chg=absolute_hb_count()-last_chg;
+    if (last_chg>3000)
+      last_chg=absolute_hb_count(),cmds_per_time=0;
+    else
+    {
+      while (last_chg>14)
+  cmds_per_time=cmds_per_time*9/10, last_chg-=15;
+      last_chg=absolute_hb_count()-last_chg;
+    }
+  }
+}
+
+private void DelayPreparedSpells() {
+  mixed ps;
+
+  if (pointerp(ps=QueryProp(P_PREPARED_SPELL))
+      && sizeof(ps)>=1 && intp(ps[0])) {
+    ps[0]++;
+    SetProp(P_PREPARED_SPELL,ps);
+    write("Die Ausfuehrung Deines vorbereiteten Spruches wird verzoegert.\n");
+  } else if (ps) {
+    SetProp(P_PREPARED_SPELL,0);
+  }
+}
+
+static mixed bb;
+#ifndef BBMASTER
+#define BBMASTER "/secure/bbmaster"
+#endif
+
+/** Interpretiert Aliase und History-Kommandos
+  Eigentlich muesste hier noch die Umwandlung der Sonderzeichen
+  verschiedener Zeichensaetze mit convert_charset gemacht werden,
+  aber noch gibt es keine Moeglichkeit, den vom Spieler genutzten
+  Zeichensatz zu identifizieren.
+  \param[in] str string - Kommando des Spielers
+  \return interpretiertes Alias bzw. korrektes Kommando aus der History
+*/
+private string parsecommand(string str)
+{
+  if (str[0]=='\\')
+  {
+    // Kommando soll nicht interpretiert werden
+    return str[1..];
+  }
+  else if (str[0]=='&')
+  {
+    // Kommando aus der History
+    string cmd = str[1..];
+    int cmd_size = sizeof(cmd);
+    int cmd_found = 0;
+    if (cmd_size)
+    {
+      // Test ob &<text> etwas findet
+      for (int i=0;i<hist_size-1 && !cmd_found;i++)
+      {
+        int idx = (hist_size-i+hist_now-1)%hist_size;
+        if (history[idx][0..cmd_size-1]==cmd)
+        {
+          str = history[idx];
+          cmd_found = 1;
+        }
+        if (cmd_found)
+        {
+          if (show_processing)
+            printf("[%s]\n",str);
+        }
+      }
+    }
+    if (!cmd_found)
+    {
+      // Test, ob &<nr> klappt
+      int nummer;
+      if (str=="&&")
+        str = "&-0";
+      if (sscanf(str,"&%d",nummer))
+      {
+        if (nummer<0 || (!nummer && str[1]=='-'))
+        {
+          if (nummer<-(hist_size-1))
+            nummer=-1;
+          else
+            nummer=(hist_now+nummer-1+hist_size)%hist_size;
+        }
+        else
+        {
+          if (nummer>hist_now || hist_now-nummer>hist_size)
+            nummer=-1;
+          else
+            nummer=nummer%hist_size;
+        }
+        if (nummer<0 
+            || ( (cmd=history[nummer]) =="\n\n") )
+          notify_fail("Der Befehl ist nicht in der History!\n");
+        else
+        {
+          str = cmd;
+          if (show_processing)
+            printf("[%s]\n",str);
+        }
+      }
+    }
+  }
+  switch (str)
+  {
+    case "n": return "norden";
+    case "s": return "sueden";
+    case "w": return "westen";
+    case "o": return "osten";
+    case "nw": return "nordwesten";
+    case "sw": return "suedwesten";
+    case "so": return "suedosten";
+    case "no": return "nordosten";
+    case "ob": return "oben";
+    case "u": return "unten";
+  }
+  // Test auf Alias
+  string output = "";
+  string* input = explode(str," ");
+  int input_size = sizeof(input);
+  mixed alias = aliases[input[0]];
+  if (!alias)
+    return str;
+  foreach (mixed a:alias)
+  {
+    if (!intp(a))
+      output += a;
+    else
+    {
+      if (a >= 0)
+      {
+        if (input_size > a)
+          output += input[a];
+      }
+      else
+      {
+        a = -a;
+        if (input_size > a)
+          output += implode(input[a..]," ");
+      }
+    }
+  }
+  output = _single_spaces(output);
+  str = trim(output,TRIM_RIGHT);
+  if (show_processing>1)
+    printf("[%s]\n",str);
+  return str;
+}
+
+/** Behandelt alle Sonderfaelle der Eingabe des Spielers
+  Alle Befehle des Spielers, die nicht durch Objekte behandelt
+  werden sollen, werden hier erkannt und ausgefuehrt.
+  Dazu gehoert auch die Interpretation von Aliases und History-
+  befehlen.
+  \param[in] str string: Kommando des Spielers
+  \return auszufuehrendes Kommando
+    oder 0 fuer ein nicht interpretierbares Kommando
+    oder 1 fuer ein bereits durchgefuehrtes Kommando
+*/
+mixed modify_command(string str)
+{
+
+  if (extern_call() && previous_object() &&
+      (previous_object()!=this_object() || process_call()) )
+  {
+    return 0;
+  }
+
+  // Leerzeichen an den Enden abschneiden.
+  str = trim(str, TRIM_BOTH);
+
+  if (bb)
+    BBMASTER->BBWrite(trim(str,TRIM_RIGHT,"\n"), 0);
+
+  decay_average();
+  cmds_per_time+=10000;
+
+  unparsed_args[0]=unparsed_args[1]=unparsed_args[2]=unmodified=""; 
+
+  if (!sizeof(str)) return "";
+
+  // Kommando wird geparst
+  unmodified=parsecommand(str);
+
+  // Environment schonmal merken.
+  last_command_env=environment();
+
+  if (unmodified == "")
+      return "";
+  // Kommando in History merken, auch wenn es im Kommandoblock abgebrochen
+  // wird.
+  AddHistory(unmodified);
+
+  // pruefen, ob Kommandoblock gesetzt ist.
+  // (Fuer Magier mit mschau ein wird das ignoriert.)
+  // BTW: Es wird absichtlich nicht das Ergebnis der Closure zurueckgegeben,
+  // sonst wuerde man beliebigen Objekten nicht nur das Abbrechen, sondern
+  // auch das Aendern von Kommandos ermoeglichen.
+  if (disablecommands && !IS_LEARNING(ME) )
+  {
+    if (disablecommands[B_TIME] >= time()
+      && objectp(disablecommands[B_OBJECT]))
+    {
+      // disablecommands valid
+      // hart-kodierte Ausnameliste pruefen
+      if ( member(({"mrufe","mschau","bug","idee","typo","detail"}),
+            explode(str," ")[0]) == -1)
+      {
+        if (closurep(disablecommands[B_VALUE]))
+        {
+          if (funcall(disablecommands[B_VALUE],_return_args(unmodified)))
+          {
+            // Non-zero Closure-Ergebnis, Abbruch. Die gerufene Funktion ist
+            // fuer eine geeignete Meldung an den Spieler verantwortlich.
+            return 1;
+          }
+        }
+        // wenn Text, dann auch pruefen, ob das Kommandoverb in den Ausnahmen
+        // steht. (query_verb() geht leider hier noch nicht.)
+        else if (stringp(disablecommands[B_VALUE])
+                 && member(disablecommands[B_EXCEPTIONS],
+                           explode(str," ")[0]) == -1)
+        {
+          // meldung ausgeben...
+          tell_object(PL, disablecommands[B_VALUE]);
+          // und Ende...
+          return 1;
+        }
+      }
+    }
+    else disablecommands=0;
+  }
+
+  // Verfolger direkt ins Env reinholen.
+  if (remove_call_out("TakeFollowers")>=0)
+    catch(TakeFollowers();publish);
+
+  DelayPreparedSpells();
+
+  // Historyeintrag korrigieren
+  if (unmodified[0]=='^')
+  {
+    string *oldnew,pre,post;
+    if (sizeof(oldnew=explode(unmodified,"^"))>2)
+    {
+      int hist_idx = (hist_now-1)%hist_size;
+      sscanf(history[hist_idx],"%s"+oldnew[1]+"%s", pre, post);
+      unmodified = pre+oldnew[2]+post;
+      if (show_processing)
+        write("["+unmodified+"]\n");
+      // korrigiertes Kommando natuerlich auch in die History.
+      AddHistory(unmodified);
+    }
+  }
+
+  if( bb )
+    BBMASTER->BBWrite(" -> " + unmodified, 1);
+
+  if (show_processing>1)
+    printf("[%s]\n",unmodified);
+
+  mixed ret = _return_args(unmodified);
+
+  // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
+  // dorthin melden.
+  if (syntaxdb)
+  {
+    if (!objectp(syntaxdb[0]))
+      syntaxdb[0] = find_object("/secure/syntaxdb");
+    if (syntaxdb[0])
+      catch(syntaxdb[0]->start_cmd(unmodified);nolog);
+  }
+  return ret;
+}
+
+static int do_list(string str)
+{
+  string *cmdlist;
+  int i;
+
+  if (!QueryProp(P_WANTS_TO_LEARN))
+    return 0;
+  cmdlist=old_explode(_unparsed_args()||"",";")-({ "" });
+  for (i=0;i<sizeof(cmdlist);i++)
+  {
+    cmdlist[i]=implode(old_explode(cmdlist[i]," ")-({}), " ");
+    if (show_processing)
+      write("["+cmdlist[i]+"]\n");
+    command(cmdlist[i]);
+  }
+  return 1;
+}
+
+//falls die aliasliste kaputt ist ...
+
+int unalias_all()
+{
+  if (IS_ELDER(this_interactive())) aliases=([]);
+  return 1;
+}
+
+object _query_last_command_env()
+{
+  return last_command_env;
+}
+
+int _query_show_alias_processing()
+{
+  return show_processing;
+}
+
+int _query_histmin()
+{
+  return histmin;
+}
+
+varargs void AddAction(mixed fun, mixed cmd, int flag, int lvl)
+{
+  int i;
+  mixed *cmds;
+
+  log_file( "ARCH/ADD_ACTION", sprintf(
+	"%s:\n  TO: %O TP: %O PO: %O\n   fun: %O cmd: %O flag: %O lvl: %O",
+        dtime(time()), this_object(), this_player(), previous_object(),
+	fun, cmd, flag, lvl));
+
+  if (!(cmds=Query(P_LOCALCMDS))) cmds=({});
+
+  if (!pointerp(cmd)) cmd=({cmd});
+
+  for (i = sizeof(cmd)-1; i>=0; i--)
+    cmds += ({({ cmd[i] , fun, flag, lvl})});
+
+  Set(P_LOCALCMDS, cmds);
+}
+
+static int auswerten(mixed cmd, string str)
+{
+  if (closurep(cmd))
+    return funcall(cmd,str);
+  if (stringp(cmd))
+    return call_other(this_object(),cmd,str);
+  return 0;
+}
+
+static varargs int __auswerten(string str, string intern)
+{
+  string verb;
+  mixed *cmd, cmds;
+  int i,ret,lvl,l,vl;
+
+  if (!intern)
+    verb=query_verb();
+  else
+    verb=intern;
+  lvl=query_wiz_level(ME);
+  vl=sizeof(verb);
+  cmds=QueryProp(P_LOCALCMDS);
+
+  for(i=sizeof(cmds)-1;i>=0;i--)
+  {
+    cmd=cmds[i],l=sizeof(cmd[0]);
+    if (cmd[0]==verb[0..l-1] && cmd[3]<=lvl && (cmd[2]||vl==l) &&
+  (ret=auswerten(cmd[1],str)))
+      return ret;
+  }
+  // An dieser Stelle gibt es hier und vermutlich nirgendwo anders etwas, was
+  // dieses Kommando als gueltig betrachtet. Wir informieren ggf. die
+  // Syntax-DB. (Achtung: wenn jemand ne add_action() im Spielerobjekt
+  // einbaut, die vor dieser eingetragen wird, ist die Annahme ggf. falsch.)
+  // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
+  // dorthin melden.
+  if (syntaxdb)
+  {
+    if (!objectp(syntaxdb[0]))
+      syntaxdb[0] = find_object("/secure/syntaxdb");
+    if (syntaxdb[0])
+      catch(syntaxdb[0]->cmd_unsuccessful();nolog);
+  }
+
+  return 0;
+}
+
+public void syntax_log_ep(int type)
+{
+  // wenn Spieler eingewilligt hat und die SyntaxDB geladen ist, Befehl
+  // dorthin melden.
+  if (syntaxdb && syntaxdb[0])
+  {
+      catch(syntaxdb[0]->LogEP(type);nolog);
+  }
+}
+
+static mixed _query_localcmds()
+{
+  mixed *l;
+
+  l=Query(P_LOCALCMDS);
+  if (!pointerp(l))
+    l=({});
+  return ({
+    ({"ali","alias",0,0}),
+    ({"alias","alias",0,0}),
+    ({"unali","unalias",1,0}),
+    ({"histmin","histmin",0,0}),
+    ({"histlen","histlen",0,0}),
+    ({"hist","show_hist",0,0}),
+    ({"history","show_hist",0,0}),
+    ({"do","do_list",0,LEARNER_LVL}),
+    ({"ersetzungsanzeige","replacedisplay",0,0}),
+    ({"syntaxsammlung","collect_cmds",0,0}),
+    ({"fehlermeldung","set_errormessage",0,SEER_LVL}),
+  })+l;
+}
+
+static int collect_cmds(string cmd)
+{
+  if (!stringp(cmd))
+  {
+    _notify("Mit diesem Befehl kannst Du mithelfen, Syntaxen im MG zu "
+            "verbessern. Wenn Du einverstanden bist, speichern wir "
+            "anonym (d.h. ohne Deinen Charnamen), welche Deiner Befehle "
+            "erfolgreich und nicht erfolgreich waren. Uebliche "
+            "Kommunikationsbefehle werden dabei nicht gespeichert.",
+            0);
+    _notify("Mit 'syntaxsammlung ja' kannst Du die Speicherung einschalten, "
+            "mit 'syntaxsammlung nein' kannst Du sie ausschalten.",0);
+    _notify("Deine Befehle werden zur Zeit"
+            + (QueryProp("_syntaxdb") ? " " : " NICHT ")
+            + "gespeichert.", 0);
+  }
+  else if (cmd == "ja")
+  {
+    SetProp("_syntaxdb", 1);
+    _notify("Ab jetzt werden Deine Befehle gespeichert. Vielen Dank!", 0);
+  }
+  else
+  {
+    SetProp("_syntaxdb", 0);
+    _notify("Ab jetzt werden Deine Befehle NICHT gespeichert.", 0);
+  }
+  return 1;
+}
+
+int _query_command_average()
+{
+  decay_average();
+  return cmds_per_time;
+}
+
+nomask void __set_bb(int flag)  {
+  if( previous_object()!=find_object(BBMASTER) || process_call() )
+    return;
+  bb=flag;
+}
+
+
+nomask public void countCmds( int type, string key )
+{
+    string tmp;
+
+    if ( this_player() != this_interactive()
+         || this_interactive() != this_object()
+         || member( cmd_types, type ) < 0 )
+        return;
+
+    tmp = sprintf( "%d\n%s", type, key );
+
+    commands -= ({ tmp });
+    commands += ({ tmp });
+    commands = commands[0..max_commands-1];
+}
+
+
+nomask public string *getCmds()
+{
+    string *tmp;
+
+    if ( previous_object() != find_object(BBMASTER) )
+        return ({});
+
+    tmp = commands;
+    commands = ({});
+
+    return tmp;
+}
+
+/*
+ * Force the monster to do a command. The force_us() function isn't
+ * always good, because it checks the level of the caller, and this function
+ * can be called by a room.
+ */
+int command_me(string cmd)
+{
+  if (IS_LEARNER(ME))
+  {
+    if (!this_interactive() || !previous_object())
+      return 0;
+    if( geteuid(ME)!=geteuid(this_interactive())
+        || geteuid(ME)!=geteuid(previous_object()) )
+    {
+      if( query_wiz_level(ME)<query_wiz_level(previous_object()))
+        tell_object(ME,previous_object()->name()+" zwingt Dich zu: "
+                    + cmd + ".\n");
+      else
+      {
+        tell_object(ME,previous_object()->name()
+                    + " versucht, Dich zu " + cmd + " zu zwingen.\n" );
+        return 0;
+      }
+    }
+  }
+  return command(cmd);
+}
+
+
+static mixed _query_p_lib_disablecommands() {
+    // abgelaufen oder Objekt zerstoert? Weg damit.
+    if (pointerp(disablecommands)
+        && (disablecommands[B_TIME] < time()
+          || !objectp(disablecommands[B_OBJECT])) )
+        return(disablecommands = 0);
+
+    // sonst Kopie zurueck (copy(0) geht)
+    return(copy(disablecommands));
+}
+
+static mixed _set_p_lib_disablecommands(mixed data) {
+
+  // setzendes Objekt ermitteln, da diese Funktion nur per SetProp() gerufen
+  // werden sollte (!), ist das PO(1);
+  object origin = previous_object(1);
+  // wenn nicht existent, direkt abbruch
+  if (!objectp(origin))
+    return _query_p_lib_disablecommands();
+
+  // Prop loeschen? Explizit loeschen darf jeder, allerdings nicht direkt
+  // ungeprueft ueberschreiben.
+  if (!data) {
+      return (disablecommands = 0 );
+  }
+  // mal direkt buggen bei falschen Datentyp, damits auffaellt.
+  if (!pointerp(data) || sizeof(data) < 2 || !intp(data[0])
+      || (!stringp(data[1]) && !closurep(data[1]))
+      || (sizeof(data) >= 3 && !pointerp(data[2])) )
+      raise_error(sprintf(
+            "Wrong data type for P_DISABLE_COMMANDS. Expected Array with "
+            "2 or 3 elements (int, string|closure, [string*]), got %.25O\n",
+            data));
+
+  // Wenn abgelaufen oder gleiches Objekt wie letztes Mal: eintragen.
+  if (!disablecommands || (disablecommands[B_TIME] < time()
+        || !objectp(disablecommands[B_OBJECT]) 
+        || disablecommands[B_OBJECT] == origin) ) {
+      // Loggen nur, wenn eine Closure eingetragen wird. Reduziert den
+      // Logscroll und Strings haben deutlich weniger Missbrauchspotential.
+      if (closurep(data[1])) {
+        CBLOG(sprintf("[%s] CB gesetzt von %O, gueltig bis %s, Daten: %O\n",
+        strftime("%Y%m%d-%H:%M:%S"),origin,
+        strftime("%Y%m%d-%H:%M:%S",data[0]),
+        (stringp(data[1]) ? regreplace(data[1],"\n","\\n",0)
+                          : data[1])));
+      }
+      if (sizeof(data)+1 <= B_EXCEPTIONS)
+        disablecommands = ({ origin, data[0], data[1], ({}) });
+      else
+        disablecommands = ({ origin, data[0], data[1], data[2] });
+      return(copy(disablecommands));
+  }
+
+  return(_query_p_lib_disablecommands());
+}
+
+static mixed _set__syntaxdb(mixed v)
+{
+  Set("_syntaxdb", v, F_VALUE);
+  if (v)
+      syntaxdb = ({find_object("/secure/syntaxdb")});
+  else
+      syntaxdb = 0;
+  return QueryProp("_syntaxdb");
+}
+