// $Id: parse.cc,v 1.19.2.5 2000/05/13 19:42:59 greear Exp $ // $Revision: 1.19.2.5 $ $Author: greear $ $Date: 2000/05/13 19:42:59 $ // //ScryMUD Server Code //Copyright (C) 1998 Ben Greear // //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU General Public License //as published by the Free Software Foundation; either version 2 //of the License, or (at your option) any later version. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //GNU General Public License for more details. // //You should have received a copy of the GNU General Public License //along with this program; if not, write to the Free Software //Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // To contact the Author, Ben Greear: greear@cyberhighway.net, (preferred) // greearb@agcs.com // /******************** parse.cc ***************/ /* this holds the calls to every function, if you wish to add another function, you better add it in the switch statement. If you wish to add help for this function, add it in the second switch towards the bottom of the file. */ #include "ar_skll.h" #include "cr_skll.h" #include "social2.h" #include "ez_skll.h" #include "dam_skll.h" #include "misc.h" #include "misc2.h" #include "commands.h" #include "command2.h" #include "command3.h" #include "command4.h" #include "command5.h" #include "spells.h" #include "skills.h" #include "olc.h" #include "olc2.h" #include "socials.h" #include <fstream.h> #include <stdio.h> #include "classes.h" #include "wep_skll.h" #include "parse.h" #include <PtrArray.h> #include "script.h" CmdCollection cmds_collection; int CmdSpecifier::_cnt = 0; String CmdSpecifier::toString() const { String retval(100); Sprintf(retval, "CmdSpecifier: word: -:%S:- help_key: -:%S:- len: %i CmdId: %i", &word, &hlp_key, len, (int)(id)); return retval; } CmdCollection::CmdCollection() { for (int i = 0; i<CMD_ARRAY_LEN; i++) { cmd_specifiers[i] = NULL; } }//constructor void CmdCollection::addCmdSpecifier(const CmdSpecifier* cs) { addCmdSpecifierNoCreate(new CmdSpecifier(*cs)); } void CmdCollection::addCmdSpecifierNoCreate(CmdSpecifier* cs) { int idx1 = calculateIndex(cs->getCmd().charAt(0)); // Append to the end of the list CmdSpecifier* walker = cmd_specifiers[idx1]; if (walker) { while (walker->getNext()) { walker = walker->getNext(); } // when here, walker->next is null walker->setNext(cs); cs->setNext(NULL); } else { cmd_specifiers[idx1] = cs; cs->setNext(NULL); } } // can return NULL const CmdSpecifier* CmdCollection::findSpecifierFor(const CmdSpecifier* cs, int cmd_only) { int idx = calculateIndex(cs->getCmd().charAt(0)); CmdSpecifier* ptr; if (mudlog.ofLevel(PARSE)) { mudlog << "CmdCollection::findSpecifierFor: cs: " << cs->toString() << "\n calculated index: " << idx << endl; } for (ptr = cmd_specifiers[idx]; ptr != NULL; ptr = ptr->getNext()) { if (cmd_only && (ptr->getId() == ci_HELP_ONLY)) { if (mudlog.ofLevel(PARSE)) { mudlog << "Comparing ptr: " << ptr->toString() << " was HELP_ONLY, and we are just doing commands!\n"; } continue; } if (cs->doesSatisfyMatch(*ptr)) { if (mudlog.ofLevel(PARSE)) { mudlog << "Comparing ptr: " << ptr->toString() << " to cs, was EQUAL." << endl; } return ptr; }//if else { if (mudlog.ofLevel(PARSE)) { mudlog << "Comparing ptr: " << ptr->toString() << " to cs, was NOT EQUAL." << endl; } } }//for return NULL; } /******************************************/ int critter::processInput(String& input, short do_sub, int script_driven, critter* c_script_owner, room* r_script_owner, int was_ordered) { String raw_strings[RAW_MAX]; String cooked_strs[COOKED_MAX]; int cooked_ints[COOKED_MAX]; String buf(100); int i, j, k, len1; short eos, term_by_period; for (i = 0; i<COOKED_MAX; i++) { cooked_ints[i] = 1; } if (mudlog.ofLevel(INF)) { mudlog << "INPUT: player: " << *(getName()) << " input: " << input << endl; if (pc) { mudlog << "PARSE: Was PC, host: " << pc->host << endl; } } /* any input causes you to un-meditate */ if (POS == POS_MED) { show("You break your meditative reverie.\n"); setPosn(POS_REST); } if (isMob()) { //not gonna parse for MOB's, but will for SMOBs btw mudlog.log(ERROR, "ERROR: MOB tried to process_input, parse.cc.\n"); return -1; }//if if (PAUSE > 100) { PAUSE = 100; } if ((PAUSE > 0) && !script_driven) { buf = input.Look_Command(TRUE); //look at the first one if (buf == "\'") { buf = "say"; } if (!((buf == "say") || (buf == "gossip") || (buf == "yell") || (buf == "tell") || (buf == ":") || (buf == "/") || (buf == "ask"))) { //show("DEBUG: You are in pause mode.\n", pc); if (!(pc && (getLinkCond() == CON_LINKDEAD))) return -1; }//if }//if if (input.Strlen() == 0) { return -1; //do nothing }//if else { if (pc && !script_driven) { if (isInPageBreak()) { releasePageBreak(); input = ""; return 0; }//if else { setDoPrompt(TRUE); } }//if else if (possessed_by && !script_driven) { if (possessed_by->isInPageBreak()) { possessed_by->releasePageBreak(); input = ""; return 0; }//if else { possessed_by->setDoPrompt(TRUE); } } }//else /* make sure it ends in newline */ j = input.Strlen(); if (input[j - 1] != '\n') { //log("WARNING: input doesn't end in a newline, process_input.\n"); input += "\n"; }//if /* Test for various Modes. */ if (pc) { //if its a pc pc->idle_ticks = 0; if ((MODE == MODE_QUIT_ME_PLEASE) || (MODE == MODE_LOGOFF_NEWBIE_PLEASE)) { return 0; }//if quitting if (MODE == MODE_OLC) { String first_cmd = input.Look_Command(TRUE); if (first_cmd == "\'") { first_cmd = "say"; } if (first_cmd == ":") { first_cmd = input.Get_Command(eos, term_by_period); first_cmd = input.Look_Command(); if ((strcasecmp(first_cmd, "say") == 0) || (strncasecmp(first_cmd, "gossip", 3) == 0) || (strncasecmp(first_cmd, "tell", 3) == 0)) { show("Escaping OLC for this one command.\n"); }//if else { show("You can only escape olc to: say, gossip, or tell.\n"); input = ""; return -1; } }//if else { do_olc(*this); //read it in and process it pc->input = NULL_STRING; //get rid of any junk still there if (MODE == MODE_OLC) { //still if (USING_CLIENT) { Sprintf(buf, "<Phase %i>", pc->imm_data->olc_counter); show(buf); } show(olc_prompts[pc->imm_data->olc_counter]); //show prompt }//if return 0; }//else }//if olc if (MODE == MODE_LOGGING_IN) { doLogin(); //log("Do login finished...\n"); if (MODE != MODE_NORMAL) { show(login_prompts[pc->index]); }//if return 0; }//if logging in // TODO: This can be interesting when coupled with scripting! if (MODE == MODE_CH_DESC) { return do_ch_desc(*this); }//if if (MODE == MODE_ADD_MOB_SCRIPT) { return do_add_mob_script(*this); } if (MODE == MODE_ADD_ROOM_SCRIPT) { return do_add_room_script(*this); } if (MODE == MODE_ADD_OBJECT_SCRIPT) { return do_add_obj_script(*this); } if (MODE == MODE_WRITING_POST) { return do_post(*this); }//if if (MODE == MODE_ADD_BUG_COMMENT) { return do_add_bug_comment(*this); }//if if (MODE == MODE_ADD_IDEA_COMMENT) { return do_add_idea_comment(*this); }//if /* copy entry to last_input */ if ((input.Look_Command() != "!") && do_sub && (input.Look_Command().Strlen())) { pc->last_input = input.Get_Rest(FALSE); //get till newline pc->last_input += "\n"; }//if }//if a pc raw_strings[0] = input.Get_Command(eos, term_by_period, TRUE); if (raw_strings[0].Strlen() == 0) { return -1; }//if if (pc) { if (raw_strings[0] == "!") { pc->input.Prepend(pc->last_input); return processInput(pc->input, do_sub, script_driven, c_script_owner, r_script_owner); }//if }//if a pc ///****************************************************************/// ///*************** non-standard-input-commands *******************/// ///****************************************************************/// len1 = raw_strings[0].Strlen(); if ((strncasecmp(raw_strings[0], "tell", max(3, len1)) == 0) || (strncasecmp(raw_strings[0], "ask", max(3, len1)) == 0)) { buf = input.Get_Command(eos, term_by_period); if (buf.Strlen() != 0) { if (isnum(buf)) { i = atoi(buf); buf = input.Get_Command(eos, term_by_period); if (buf.Strlen() != 0) { (cooked_strs[1]) = buf; buf = input.Get_Rest(); parse_communication(buf); return tell(i, &(cooked_strs[1]), buf, *this); }//if else { show(PARSE_ERR_MSG); return -1; }//else }//if is number else { (cooked_strs[1]) = buf; buf = input.Get_Rest(); parse_communication(buf); return tell(1, &(cooked_strs[1]), buf, *this); }//else }//if else { show("Tell who what?\n"); return -1; }//else return -1; }//if tell if (strncasecmp(raw_strings[0], "pecho", max(3, len1)) == 0) { buf = input.Get_Command(eos, term_by_period); if (buf.Strlen() != 0) { if (isnum(buf)) { i = atoi(buf); buf = input.Get_Command(eos, term_by_period); if (buf.Strlen() != 0) { (cooked_strs[1]) = buf; buf = input.Get_Rest(); buf.Append("\n"); parse_communication(buf); return com_pecho(i, &(cooked_strs[1]), &buf, *this); }//if else { show(PARSE_ERR_MSG); return -1; }//else }//if is number else { (cooked_strs[1]) = buf; buf = input.Get_Rest(); parse_communication(buf); buf.Append("\n"); return com_pecho(1, &(cooked_strs[1]), &buf, *this); }//else }//if else { show("Tell who what?\n"); return -1; }//else return -1; }//if pecho if (strncasecmp(raw_strings[0], "reply", max(1, len1)) == 0) { if (pc) { buf = input.Get_Rest(); parse_communication(buf); return tell(1, &(pc->rep_to), buf, *this); }// }//if if ((strcasecmp(raw_strings[0], "emote") == 0) || (strcasecmp(raw_strings[0], ":") == 0)) { buf = input.Get_Rest(); parse_communication(buf); return com_emote(&buf, *this); }//if if (strcasecmp(raw_strings[0], "pemote") == 0) { buf = input.Get_Rest(); parse_communication(buf); return com_pemote(&buf, *this); }//if if (strcasecmp(raw_strings[0], "gemote") == 0) { buf = input.Get_Rest(); parse_communication(buf); return com_gemote(&buf, *this); }//if if (strcasecmp(raw_strings[0], "gecho") == 0) { buf = input.Get_Rest(); parse_communication(buf); return com_gecho(&buf, *this); }//if if (strcasecmp(raw_strings[0], "recho") == 0) { buf = input.Get_Rest(); parse_communication(buf); return com_recho(&buf, *this); }//if if (strcasecmp(raw_strings[0], "zecho") == 0) { buf = input.Get_Rest(); parse_communication(buf); return com_zecho(&buf, *this); }//if /* yell */ if (strncasecmp(raw_strings[0], "yell", len1) == 0) { buf = input.Get_Rest(); parse_communication(buf); return yell(buf, *this); }//if yell if (strncasecmp(raw_strings[0], "shout", max(2, len1)) == 0) { buf = input.Get_Rest(); parse_communication(buf); return shout(buf, *this); }//if yell if ((strncasecmp(raw_strings[0], "gossip", max(3, len1)) == 0) || (raw_strings[0] == "/")) { buf = input.Get_Rest(); parse_communication(buf); return gossip(buf, *this); }//if gossip if ((strncasecmp(raw_strings[0], "gs", max(2, len1)) == 0) || (strncasecmp(raw_strings[0], "gt", max(2, len1)) == 0)) { buf = input.Get_Rest(); parse_communication(buf); return group_say(buf, *this); }//if gossip if ((strncasecmp(raw_strings[0], "wizchat", max(3, len1)) == 0) || (raw_strings[0] == "wc")) { buf = input.Get_Rest(); parse_communication(buf); return wizchat(buf, *this); }//if wizchat if (strncasecmp(raw_strings[0], "auction", max(3, len1)) == 0) { buf = input.Get_Rest(); parse_communication(buf); return auction(buf, *this); }//if auction if ((strncasecmp(raw_strings[0], "force", max(5, len1)) == 0) && len1<6) { buf = input.Get_Rest(); buf += "\n"; //better fer processing! parse_communication(buf); return force(&buf, *this); }//if force if (strncasecmp(raw_strings[0], "force_all", max(9, len1)) == 0) { buf = input.Get_Rest(); buf += "\n"; //better fer processing! parse_communication(buf); return force_all(&buf, *this); }//if force_all if (strncasecmp(raw_strings[0], "order", len1) == 0) { buf = input.Get_Rest(); buf += "\n"; //better fer processing! parse_communication(buf); return order(&buf, *this); }//if order if (strcasecmp(raw_strings[0], "self") == 0) { buf = input.Get_Rest(); buf += "\n"; //better fer processing! if (possessed_by) { return possessed_by->processInput(buf, do_sub, script_driven, c_script_owner, r_script_owner); } else { show("Eh??"); return -1; } }//if 'self' if ((strncasecmp(raw_strings[0], "say", max(3, len1)) == 0) || (raw_strings[0] == "\"") || (raw_strings[0] == "\'") || (strncasecmp(raw_strings[0], "talk", max(3, len1)) == 0)) { buf = input.Get_Rest(); parse_communication(buf); return say(buf, *this, *(getCurRoom())); }//if say if (strncasecmp(raw_strings[0], "title", max(3, len1)) == 0) { buf = input.Get_Rest(); parse_communication(buf); return title(&buf, *this); }//if title if (strncasecmp(raw_strings[0], "poofout", max(5, len1)) == 0) { buf = input.Get_Rest(); parse_communication(buf); return poofout(&buf, *this); }//if poofout if (strncasecmp(raw_strings[0], "poofin", max(5, len1)) == 0) { buf = input.Get_Rest(); parse_communication(buf); return poofin(&buf, *this); }//if title if (strncasecmp(raw_strings[0], "idea", max(4, len1)) == 0) { buf = input.Get_Rest(); return idea(buf, *this); }//if idea if ((strncasecmp(raw_strings[0], "bug", max(3, len1)) == 0) || (strncasecmp(raw_strings[0], "typo", max(4, len1)) == 0)) { buf = input.Get_Rest(); return bug(buf, *this); }//if bug mudlog.log(DBG, "Entering the while loop.\n"); int count = 1; while (!eos) { //if more than one command to get... raw_strings[count] = input.Get_Command(eos, term_by_period); if (term_by_period && (strcasecmp(raw_strings[count], "all") == 0)) { raw_strings[count] = "-1"; }//if count++; //max input is RAW_MAX words/numbers if ((count >= (RAW_MAX - 1)) && (!eos)) { show(PARSE_ERR_MSG); return -1; }//if }//while // log("Done w/while loop.\n"); mudlog.log(DBG, "\n"); /* now separate the numbers from the words... */ /* example of command: cast fireball 2.guard */ /* put 2.wand 3.bag */ if (mudlog.ofLevel(DBG)) { mudlog << "Here are all commands\n"; for (j = 0; j < RAW_MAX; j++) { mudlog << j << ": " << raw_strings[j] << " "; if (raw_strings[i].Strlen() == 0) break; }//for mudlog << endl << flush; } i = j = k = 0; for (buf = raw_strings[j]; buf.Strlen(); ) { if (j >= RAW_MAX) { mudlog << "ERROR: over-ran RAW_MAX while parsing." << endl; break; } if (isnum(buf)) { cooked_ints[k] = atoi(buf); k++; }//if else { //it was a string of some type cooked_strs[i] = buf; if (k == i) { cooked_ints[k] = 1; //implicit 1 k++; }//if i++; }//else j++; buf = raw_strings[j]; }//for if (mudlog.ofLevel(PARSE)) { mudlog << "OK, made it to beginning of definitions.\n" << "Here are cooked_strs\n"; for (i = 0; i< COOKED_MAX; i++) { mudlog << i << ": " << cooked_strs[i] << " "; }//for mudlog << endl; mudlog << "Here are cooked_ints\n"; for (i = 0; i< COOKED_MAX; i++) { mudlog << " " << i << ": " << cooked_ints[i] << " "; }//for mudlog << endl << flush; }//if /********************************************************/ /*********** HERE START DEFINITIONS OF COMMANDS ********/ /********************************************************/ return executeCommand(cooked_strs, cooked_ints, 1, c_script_owner, r_script_owner, do_sub, was_ordered); }// process input int critter::executeCommand(String* cooked_strs, int* cooked_ints, int sanity, critter* c_script_owner, room* r_script_owner, int do_sub, int was_ordered) { int is_dead = FALSE; int i, len1; // Recurse sanity check if (sanity > 5) { return -1; } if ((len1 = cooked_strs[0].Strlen()) == 0) { show(PARSE_ERR_MSG); return -1; }//if CmdSpecifier cur_cmd((cooked_strs[0]), len1); const CmdSpecifier* real_cmd = cmds_collection.findSpecifierFor(&cur_cmd, TRUE); if (real_cmd) { i = (int)(real_cmd->getId()); if (exe_cmd_array[i]) { return exe_cmd_array[i]-> execute(cooked_strs[0], cooked_strs[1], cooked_strs[2], cooked_strs[3], cooked_strs[4], cooked_ints[1], cooked_ints[2], cooked_ints[3], cooked_ints[4], cooked_ints[5], cooked_ints[6], is_dead, *this, c_script_owner, r_script_owner, cooked_strs, cooked_ints, do_sub, sanity + 1, was_ordered); }//if we have a command handler. else { show("You may need to be more specific, or maybe there is only\n"); show("help for that keyword.\n"); } }//if else { int retval = getCurRoom()->attemptExecuteUnknownScript(cooked_strs[0], cooked_ints[1], cooked_strs[1], *this); if (retval >= 0) { return retval; } else { if (mudlog.ofLevel(DBG)) { mudlog << "ERROR: Could not find real_cmd for cmd: " << cur_cmd.toString() << endl; } show(PARSE_ERR_MSG); return -1; } }//switch return -1; }//executeCommand String parse_hlp_command(const String& topic) { //mudlog << "parse_hlp_command: topic -:" << topic << ":-\n"; if (topic.Strlen() > 0) { CmdSpecifier cur_cmd(topic, topic.Strlen()); const CmdSpecifier* real_cmd = cmds_collection.findSpecifierFor(&cur_cmd, FALSE); if (real_cmd) { return real_cmd->getHelpKey(); } else if (mudlog.ofLevel(DBG)) { mudlog << "WARNING: (Help) Could not find real_cmd for cmd: " << cur_cmd.toString() << endl; } } return NULL_STRING; }//parse_hlp_command