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");
+}
+