/* /lib/command.c * from the Dead Souls Object Library * handles commands of living objects * created by Descartes of Borg 950323 * Version: @(#) command.c 1.2@(#) * Last modified: 96/12/07 */ #include <lib.h> #include <daemons.h> #include "include/command.h" #define OLD_STYLE_PLURALS 1 int Paused = 0; private static int Forced = 0; private static int StillTrying = 0; private static int ParseRecurse = 0; private static string CommandFail; private static string *SearchPath; private static int last_cmd_time = 0; private static int cmd_count = 1; private string *CommandHist = ({}); private string *localcmds = ({}); private string *next_command = ({}); private static string *QueuedCommands = ({}); private int MaxCommandHistSize = 20; static string current_command = ""; int direct_force_liv_str() { return 1; } int direct_force_liv_to_str() { return 1; } /* *************** /lib/command.c driver applies *************** */ static void create() { SearchPath = ({ DIR_PLAYER_CMDS, DIR_SECURE_PLAYER_CMDS, DIR_CLAN_CMDS, DIR_COMMON_CMDS, DIR_SECURE_COMMON_CMDS }); } static string process_input(string cmd) { current_command = cmd; return cmd; } /* *************** /lib/command.c command lfuns *************** */ static int cmdAll(string args) { object old_agent; mixed err; string verb, file; if(Paused) { return 0; } if(!archp(this_player()) && MAX_COMMANDS_PER_SECOND){ if(last_cmd_time == time()) cmd_count++; else { last_cmd_time = time(); cmd_count = 1; } if(cmd_count > MAX_COMMANDS_PER_SECOND) { write("You have exceeded the "+MAX_COMMANDS_PER_SECOND+" commands per second limit."); return 1; } } if(sizeof(CommandHist) >= MaxCommandHistSize) CommandHist -= ({ CommandHist[0] }); if(!args) CommandHist += ({ query_verb() }); else CommandHist += ({ query_verb()+" "+args }); old_agent = this_agent(this_object()); verb = query_verb(); if(this_player()->GetSleeping() > 0) { if(verb != "wake") { this_player()->eventPrint("You are asleep."); return 1; } } if(BARE_EXITS){ localcmds = ({}); filter(this_player()->GetCommands(), (: localcmds += ({ $1[0] }) :)); if(member_array(verb,CMD_D->GetCommands()) == -1 && member_array(verb,keys(VERBS_D->GetVerbs())) == -1 && member_array(verb,localcmds) == -1 && environment(this_player())->GetExits()){ if(member_array(verb,environment(this_player())->GetExits()) != -1) verb = "go "+verb; if(member_array(verb,environment(this_player())->GetEnters()) != -1) verb = "enter "+verb; } } if(COMMAND_MATCHING && sizeof(match_command(verb))) verb = match_command(verb); if(OLD_STYLE_PLURALS && args){ int numba, i; string tmp_ret; string *line = explode(args," "); for(i = 1; i < sizeof(line); i++){ string element = line[i]; if(sscanf(element,"%d.%s",numba,tmp_ret) == 2){ if(present(numba+ordinal(numba)+" "+tmp_ret,environment(this_player()))){ args = replace_string(args,element,numba+ordinal(numba)+" "+tmp_ret); continue; } } //start single-number check if(numba = atoi(element)){ object o1; string e1, e2; e1 = numba+ordinal(numba); e2 = line[i-1]; o1 = present(e2+" "+numba,this_player()); if(!o1) o1 = present(e2+" "+numba,environment(this_player())); if(o1){ tmp_ret = e1+" "+e2; args = replace_string(args,e2+" "+numba,tmp_ret); } }//end single number check } } if(query_custom_command(verb) && query_custom_command(verb) != "" && !creatorp(this_player()) ){ this_player()->eventPrint("How clever of you. Or lucky. In any case, this command is unavailable to you."); return 1; } if( !(file = (query_custom_command(verb) )) || query_custom_command(verb) == "") { if( !(file = (string)CMD_D->GetCommand(verb, GetSearchPath())) ) { string cmd; int dbg; if( args ) cmd = verb + " " + args; else cmd = verb; if( (int)this_object()->GetProperty("parse debug") ) dbg = 1; else if( (int)this_object()->GetProperty("debug") ) dbg = 1; else dbg = 0; if( (err = parse_sentence(cmd, dbg)) == 1 ) { this_agent(old_agent || 1); return 1; } if( err ) { if( err == -1 ) { if( !(err = (string)VERBS_D->GetErrorMessage(verb)) && !(err = (string)SOUL_D->GetErrorMessage(verb)) ) { err = "Such a command exists, but no default " "syntax is known."; } } if( intp(err) ) /* MudOS bug */ err = "What?"; SetCommandFail(err); } message("error", GetCommandFail(), this_object()); this_agent(old_agent || 1); return 1; } } if( (err = (mixed)call_other(file, "cmd", args)) != 1 ) { string cmd; if( err ) SetCommandFail(err); if( !args || args == "" ) cmd = verb; else cmd = verb + " " + args; if( (err = parse_sentence(cmd)) == 1 ) { this_agent(old_agent || 1); return 1; } if( !err ) err = GetCommandFail(); message("error", err, this_object()); this_agent(old_agent || 1); return 1; } this_agent(old_agent || 1); return 1; } int cmdDebugAll(string args) { object old_agent; mixed err; string verb, file; old_agent = this_agent(this_object()); verb = query_verb(); if( !(file = (string)CMD_D->GetCommand(verb, GetSearchPath())) ) { string cmd; if( args ) cmd = verb + " " + args; else cmd = verb; if( (err = parse_sentence(cmd, 3)) == 1 ) { this_agent(old_agent || 1); return 1; } if( err ) SetCommandFail(err); message("error", GetCommandFail(), this_object()); this_agent(old_agent || 1); return 1; } if( (err = (mixed)call_other(file, "cmd", args)) != 1 ) { string cmd; if( err ) SetCommandFail(err); if( !args || args == "" ) cmd = verb; else cmd = verb + " " + args; if( (err = parse_sentence(cmd, 3)) == 1 ) { this_agent(old_agent || 1); return 1; } if( !err ) err = GetCommandFail(); message("error", err, this_object()); this_agent(old_agent || 1); return 1; } this_agent(old_agent || 1); return 1; } /* *************** /lib/command.c lfuns *************** */ int Setup() { enable_commands(); add_action( (: cmdAll :), "", 1); } int eventForce(string cmd) { string err; int res; if(!cmd) return 0; cmd = process_input(cmd); Forced = 1; err = catch(res = command(cmd)); Forced = 0; if(err) error(err); return res; } int eventForceQueuedCommand(string cmd){ tell_object(this_object(),"%^RED%^Executing queued command: %^RESET%^"+cmd); eventForce(cmd); } int eventExecuteQueuedCommands(){ int i = 0; foreach(string tmp in QueuedCommands){ i++; call_out("eventForceQueuedCommand", i, tmp); QueuedCommands -= ({ tmp }); } } int eventQueueCommand(string line){ if(!line || !sizeof(line) || !stringp(line)) return 0; if(!this_player()) return 0; if(interactive(this_object())){ if(this_player() && this_player() != this_object()) return 0; } if(line != "") QueuedCommands += ({ line }); //if(sizeof(QueuedCommands)) eventExecuteQueuedCommands(); return 1; } int DoneTrying(){ return StillTrying = 0; } int eventRetryCommand(string lastcmd){ string virb, wrd, prep, rest,ret; string *tmp_arr = ({}); string *prep_arr = MASTER_D->parse_command_prepos_list(); next_command = ({}); prep_arr -= ({"here","room","exit","enter"}); if(previous_object() != master()) return 0; StillTrying++; //debug("StillTrying: "+StillTrying,"white"); filter(explode(lastcmd," "), (: next_command += ({ trim($1) }) :) ); //debug("next_command: "+identify(next_command)); if(sizeof(next_command) == 2){ ret = next_command[0]+" a "+next_command[1]; //debug("ret: "+ret,"red"); } else if(sizeof(next_command) == 3){ if(member_array(next_command[1],prep_arr) != -1) ret = next_command[0]+" "+next_command[1]+" a "+next_command[2]; else ret = next_command[0]+" a "+next_command[1]+" "+next_command[2]; //debug("ret: "+ret,"green"); } else if(sizeof(next_command) == 4 && StillTrying < MAX_COMMANDS_PER_SECOND){ ret = next_command[0]+" a "+next_command[1]+" "+next_command[2]+" "+next_command[3]; //debug("ret: "+ret,"magenta"); } //debug("ret: "+ret,"cyan"); if(StillTrying > 3){ int i; tmp_arr = ({}); tmp_arr = explode(ret," "); ret = ""; for(i = 0; i < sizeof(tmp_arr);i++){ //debug("ret: "+ret,"yellow"); //debug("tmp_arr["+i+"]: "+tmp_arr[i],"yellow"); ret += " "+tmp_arr[i]; if(member_array(tmp_arr[i],prep_arr) != -1 && tmp_arr[i+1] != "a") ret += " a"; } ret = trim(ret); //debug("ret: "+ret,"white"); } if(StillTrying > 3 && tmp_arr[1] != "a"){ ret = tmp_arr[0]+" a "+implode(tmp_arr[1..]," "); //debug("still tryin is greater than 3"); //debug("tmp_arr: "+identify(tmp_arr)); } //debug("ret: "+ret,"yellow"); if(COMMAND_MATCHING){ string vb; next_command = ({}); tmp_arr = explode(ret," "); vb = match_command(tmp_arr[0]); if(sizeof(vb)) next_command = ({ vb }); else next_command = ({ tmp_arr[0] }); foreach(string element in tmp_arr[1..]){ next_command += ({ element }); } ret = implode(next_command," "); } if(StillTrying > 6) { write("Your command is ambiguous. Please be more specific. Which thing do you mean?"); StillTrying = 0; return 1; } //debug("ret: "+ret,"cyan"); if(ret) { mixed err; //debug("trying to parse: "+ret,0,"cyan"); if(err = parse_sentence(ret)){ //debug("err: "+err,0,"red"); if(stringp(err) && sizeof(trim(err))){ write(err); return 1; } } } return 1; } /* ********** /lib/command.c data manipulation functions ********** */ string *AddSearchPath(mixed val) { if(stringp(val)) { if(!strsrch(val,"/secure/cmds/admins") || !strsrch(val,"/cmds/admins")){ if(!(int)master()->valid_apply(({ "SECURE", "ASSIST", "LIB_CONNECT" })) ){ tell_creators("Security violation in progress: "+identify(previous_object(-1)) + ", "+get_stack()); error("Illegal attempt to modify path data: "+identify(previous_object(-1)) + ", "+get_stack()); } } val = ({ val }); } else if(!pointerp(val)) error("Bad argument 1 to AddSearchPath()\n"); return (SearchPath = distinct_array(SearchPath + val)); } string *RemoveSearchPath(mixed val) { if(stringp(val)) val = ({ val }); else if(!pointerp(val)) error("Bad argument 1 to RemoveSearchPath()\n"); return (SearchPath -= val); } string *GetSearchPath() { return SearchPath; } int GetForced() { return Forced; } int GetClient() { return 0; } static string *GetCommandHist(){ return CommandHist; } string GetLastCommand(){ if(!GetForced() && (this_player() == this_object() || previous_object() == master())){ return CommandHist[sizeof(CommandHist)-1]; } else return ""; } string GetCurrentCommand(){ if(!this_player()) return ""; if(this_player() != this_object()) return ""; return current_command; } int GetMaxCommandHistSize(){ return MaxCommandHistSize; } int SetMaxCommandHistSize(int i){ if(!i || i < 2) i = 2; return MaxCommandHistSize = i; } int SetPlayerPaused(int i){ if( !this_player() || !archp(this_player()) ){ error("Illegal attempt to pause a player: "+get_stack()+" "+identify(previous_object(-1))); log_file("adm/pause",timestamp()+" Illegal attempt to access SetPlayerPaused on "+identify(this_object())+" by "+identify(previous_object(-1))+"\n"); } Paused = i; return Paused; } int GetPlayerPaused(){ return Paused; } string SetCommandFail(string str) { if( !str || str == "" ){ if(!creatorp(this_player())) CommandFail = "Try \"help commands\" for a list of some commands."; if(creatorp(this_player())) CommandFail = "Try \"help creator commands\" for a list of some creator commands."; return CommandFail; } else return (CommandFail = str); } string GetCommandFail() { return CommandFail; }