/
dirt31/
dirt31/bin/
#include "kernel.h"
#include "condact.h"
#include "verbs.h"
#include "sflags.h"
#include "sendsys.h"
#include "locations.h"
#include "objects.h"
#include "parse.h"
#include "mobile.h"
#include "exec.h"
#include "move.h"
#include "commands.h"
#include "weather.h"
#include "wizard.h"
#include "change.h"
#include "clone.h"

#define NOISECHAR(c)	((c) == ' ' || (c) == '.' || (c) == ',' || (c) == '%')

static void parse_1(char *itemb,int *pl,int *ob,int *pre);
static char *markpos(void);

static char *preptable[] = { NULL, "at", "on", "with", "to", "in", "into",
			       "from", "out", TABLE_END};

static int xgamecom(char *str,Boolean savecom)
{
  int a;

  if (str == NULL || *str == 0) {
    return 0;
  } else if (EQ(str,"!")) {
    return gamecom(cur_player->prev_com,False);
  } else {
    if (savecom) (void)strcpy(cur_player->prev_com,str);

    /* Translate : and ; to "emote", and ' and " to "say".
     */
    a = -1;

    if (str[0] == '\"' || str[0] == '\'') {
      strcpy(strbuf,"say ");
      strcat(strbuf,str+1);
    } else if (str[0] == ':' || str[0] == ';') {
      strcpy(strbuf,"emote ");
      strcat(strbuf,str+1);
    } else {
      strcpy(strbuf,str);
    }

    stp = 0;

    if (brkword() == -1) {	/* if line contains nothing but  */
      erreval();		/* pn's or articles (a, an, the) */
      return -1;
    }
    if ((a = chkverb()) != -1) {
      doaction(a);
      return 0;
    }
    if (fextern(wordbuf) >= 0) {	/* handle external commands */
      stp = 0;
      return 0;
    }
    stp = 0;
    (void)brkword();
    if ((a = fpbn(wordbuf)) >= 0) { /* translate NAME to TELL NAME */
      stp = 0;
      a = VERB_TELL;
      doaction(a);
      return 0;
    }
    bprintf("Pardon?\n");
    return -1;
  }
}

int gamecom(char *str,Boolean savecom)
{
  int x;

  plast_cmd(real_mynum) = global_clock;
  x = xgamecom(str,savecom);
  exectable(status,0);
  special_events(mynum);
  return x;
}

char *getreinput(char *b)
{
  while (strbuf[stp] == ' ')
    stp++;
  return b != NULL ? strcpy(b, &strbuf[stp]) : &strbuf[stp];
}

int brkword(void)
{
  static int neword = 0;
  int worp;

  if (stp == 0)
    neword = 0;
  if (neword) {
    neword = 0;
    return 0;
  }
  for ( ; ; ) {
    while (NOISECHAR(strbuf[stp]))
      stp++;
    for (worp = 0; strbuf[stp] != 0 && !NOISECHAR(strbuf[stp]); )
      wordbuf[worp++] = strbuf[stp++];
    wordbuf[worp] = 0;
    lowercase(wordbuf);
    if (EQ(wordbuf, "the") || EQ(wordbuf, "a") || EQ(wordbuf, "an")
	|| EQ(wordbuf, "of") || EQ(wordbuf, "with"))
      continue;

    if (EQ(wordbuf, "it")) {
      if (cur_player->wd_it == NULL) {
	bprintf( "What exactly do you mean by \'it\'?\n");
	return -1;
      }
      strcpy(wordbuf, cur_player->wd_it);
    }

    if (EQ(wordbuf, "him")) {
/*      if (*cur_player->wd_him == '\0') {
	bprintf( "What exactly do you mean by \'him\'?\n");
	return -1;
      }
*/
      strcpy(wordbuf, cur_player->wd_him);
    }

    if (EQ(wordbuf, "her")) {
/*      if (*cur_player->wd_her == '\0') {
	bprintf( "What exactly do you mean by \'her\'?\n");
	return -1;
      }
*/
      strcpy(wordbuf, cur_player->wd_her);
    }

    if (EQ(wordbuf, "them")) {
/*      if (cur_player->wd_them == NULL) {
	bprintf( "What exactly do you mean by \'them\'?\n");
	return -1;
      }
*/
      strcpy(wordbuf, cur_player->wd_them);
    }

    if (EQ(wordbuf, "me")) {
      strcpy(wordbuf, pname(mynum));
    }

    break;
  }

  return (worp ? 0 : -1);
}



int chkverb()
{
  return chklist(wordbuf, verbtxt, verbnum);
}

int chklist(char *word, char *lista[], int listb[])
{
  int a, b, c;
  int d = -1;

  b = c = 0;
  for (a = 0; lista[a]; a++)
    if ((b = Match(word, lista[a])) > c) {
      c = b;
      d = listb[a];
    }
  return (c < 5 ? -1 : d);
}

int Match(char *x, char *y)
{
  if (strncasecmp(x, y, strlen(x)) == 0)
    return 10000;
  return 0;
}

void doaction(int vb)
{
  char xx[128];
  char  yy[20];

  if (do_tables(vb) == 2)
    return;
  if (vb > 1 && vb < 8) {
    if (cur_player->i_follow >= 0) {
      bprintf("You stopped following.\n");
      cur_player->i_follow = -1;
    }
    dodirn(vb);
    return;
  }
  if (cur_player->isforce) {

    switch (vb) {
    case VERB_QUIT:
    case VERB_BECOME:
    case VERB_BUG:
    case VERB_TYPO:
    case VERB_FORCE:
    case VERB_MAIL:
      bprintf("You can't be forced to do that.\n");
      return;
    }

  }
  switch (vb) {
  case VERB_GO:
    if (cur_player->i_follow >= 0) {
      bprintf("You stopped following %s.\n", pname(cur_player->i_follow));
      cur_player->i_follow = -1;
    }
    dogocom();
    break;
  case VERB_FLOWERS:
    flowercom();
    break;
  case VERB_DESCRIPTION:
    change_desc();
    break;
  case VERB_CLONE:
    clonecom(True);
    break;
  case VERB_DESTRUCT:
    destructcom(NULL);
    break;
  case VERB_LOAD:
    loadcom();
    break;
  case VERB_STORE:
    storecom();
    break;
  case VERB_DEBUG:
    debugcom();
    break;
  case VERB_TICKLE:
    ticklecom();
    break;
  case VERB_PET:
    petcom();
    break;
  case VERB_QUIT:
    quit_game();
    break;
  case VERB_SIT:
    sitcom();
    break;
  case VERB_STAND:
    standcom(mynum);
    break;
  case VERB_GET:
    getcom();
    break;
  case VERB_ASMORTAL:
    asmortalcom();
    break;
  case VERB_DROP:
    dropobj();
    break;
  case VERB_WHO:
    whocom();
    break;
  case VERB_MWHO:
    mwhocom();
    break;
  case VERB_RESET:
    resetcom(RES_TEST);
    break;
  case VERB_ZAP:
    zapcom();
    break;
  case VERB_EAT:
    eatcom();
    break;
  case VERB_SAVE:
    saveme();
    break;
  case VERB_SAVESET:
    saveset();
    break;
  case VERB_GLOBAL:
    globalcom();
    break;
  case VERB_STEAL:
    stealcom();
    break;
  case VERB_REVIEW:
    reviewcom();
    break;
  case VERB_LEVELS:
    levelscom();
    break;
  case VERB_COUPLES:
    bprintf("\001f%s\003", COUPLES);
    break;
  case VERB_WIZLIST:
    wizlistcom();
    break;
  case VERB_BULLETIN:
    bulletincom();
    break;
  case VERB_MAIL:
    mailcom();
    break;
  case VERB_PROMPT:
    promptcom();
    break;
#if 0
  case VERB_TIMEOUT: /* Not needed in dirt3 */
    timeoutcom();
    break;
#endif
  case VERB_INFO:
    infocom();
    break;
  case VERB_QUESTS:
    questcom();
    break;
  case VERB_TOURNAMENT:
    tournamentcom();
    break;
  case VERB_SYSLOG:
    syslogcom();
    break;
  case VERB_DELETE:
    deletecom();
    break;
  case VERB_OPENGAME:
    opengamecom();
    break;
  case VERB_HELP:
    helpcom();
    break;
  case VERB_STATS:
    showplayer();
    break;
  case VERB_EXAMINE:
    examcom();
    break;
  case VERB_EXORCISE:
    exorcom();
    break;
  case VERB_SUMMON:
    sumcom();
    break;
  case VERB_WIELD:
    wieldcom();
    break;
  case VERB_KILL:
    killcom();
    break;
  case VERB_POSE:
    posecom();
    break;
  case VERB_SET:
    setcom();
    break;
  case VERB_PRAY:
    praycom();
    break;
  case VERB_STORM:
    set_weather(stormy);
    break;
  case VERB_RAIN:
    set_weather(rainy);
    break;
  case VERB_SUN:
    set_weather(sunny);
    break;
  case VERB_SNOW:
    set_weather(snowing);
    break;
  case VERB_HAIL:
    set_weather(hailing);
    break;
  case VERB_TIPTOE:
    gotocom(True);
    break;
  case VERB_GOTO:
    gotocom(False);
    break;
  case VERB_WEAR:
    wearcom();
    break;
  case VERB_REMOVE:
    removecom();
    break;
  case VERB_PUT:
    putcom();
    break;
  case VERB_WAVE:
    wavecom();
    break;
  case VERB_BLIZZARD:
    set_weather(blizzard);
    break;
  case VERB_FORCE:
    forcecom();
    break;
  case VERB_LIGHT:
    lightcom();
    break;
  case VERB_EXTINGUISH:
    extinguishcom();
    break;
  case VERB_CRIPPLE:
    cripplecom();
    break;
  case VERB_CURE:
    curecom();
    break;
  case VERB_HEAL:
    healcom();
    break;
  case VERB_MUTE:
    dumbcom();
    break;
  case VERB_CHANGE:
    changecom();
    break;
  case VERB_MISSILE:
    spellcom(VERB_MISSILE);
    break;
  case VERB_SHOCK:
    spellcom(VERB_SHOCK);
    break;
  case VERB_FIREBALL:
    spellcom(VERB_FIREBALL);
    break;
  case VERB_FROST:
    spellcom(VERB_FROST);
    break;
  case VERB_BLOW:
    blowcom();
    break;
  case VERB_WIZ:
    wizcom();
    break;
  case VERB_NOWIZ:
    nowizcom();
    break;
  case VERB_GOD:
    godcom();
    break;
  case VERB_EXITS:
    exitcom();
    break;
  case VERB_OBJECTS:
    dircom();
    break;
  case VERB_PUSH:
    pushcom();
    break;
  case VERB_IN:
    incom(True);
    break;
  case VERB_AT:
    incom(False);
    break;
  case VERB_INVISIBLE:
    inviscom();
    break;
  case VERB_VISIBLE:
    viscom();
    break;
  case VERB_DEAFEN:
    deafcom();
    break;
  case VERB_RESURRECT:
    resurcom();
    break;
  case VERB_TITLE:
    change_title();
    break;
  case VERB_SETSTART:
    setstart();
    break;
  case VERB_LOCATIONS:
  case VERB_ZONES:
    zonescom();
    break;
  case VERB_USERS:
    usercom();
    break;
  case VERB_BECOME:
    becom(NULL);
    break;
  case VERB_SNOOP:
    snoopcom();
    break;
  case VERB_RAW:
    rawcom();
    break;
  case VERB_ROLL:
    rollcom();
    break;
  case VERB_CREDITS:
    bprintf("\001f%s\003", CREDITS);
    break;
  case VERB_BRIEF:
    bprintf("Brief mode ");
    if (ststflg(mynum, SFL_BRIEF)) {
      bprintf("off.\n");
      sclrflg(mynum, SFL_BRIEF);
    }
    else {
      bprintf("on.\n");
      ssetflg(mynum, SFL_BRIEF);
    }
    break;
  case VERB_JUMP:
    jumpcom();
    break;
  case VERB_WHERE:
    wherecom();
    break;
  case VERB_FLEE:
    fleecom();
    break;
  case VERB_BUG:
    bugcom();
    break;
  case VERB_TYPO:
    typocom();
    break;
  case VERB_ACTIONS:
    lisextern();
    break;
  case VERB_PN:
    pncom();
    break;
  case VERB_BLIND:
    blindcom();
    break;
  case VERB_MASK:
    maskcom();
    break;
  case VERB_PFLAGS:
    pflagscom();
    break;
  case VERB_MFLAGS:
    mflagscom();
    break;
  case VERB_FROB:
    frobcom(NULL);
    break;
  case VERB_SHUTDOWN:
    shutdowncom(False);
    break;
  case VERB_CRASH:
    shutdowncom(True);
    break;
  case VERB_EMOTE:
    emotecom();
    break;
  case VERB_EMOTETO:
    emotetocom();
    break;
  case VERB_EMPTY:
    emptycom();
    break;
  case VERB_TIME:
    timecom();
    break;
  case VERB_TREASURES:
    treasurecom();
    break;
  case VERB_WAR:
    warcom();
    break;
  case VERB_PEACE:
    peacecom();
    break;
  case VERB_QUIET:
    if (plev(mynum) < LVL_WIZARD) {
      erreval();
      break;
    }
    bprintf("Quiet mode ");
    if (ststflg(mynum, SFL_QUIET)) {
      bprintf("off.\n");
      sclrflg(mynum, SFL_QUIET);
    }
    else {
      bprintf("on.\n");
      ssetflg(mynum, SFL_QUIET);
    }
    break;
  case VERB_NOSHOUT:
    noshoutcom();
    break;
  case VERB_COLOR:
    if (ststflg(mynum, SFL_COLOR)) {
      bprintf("Back to black and white.\n");
      sclrflg(mynum, SFL_COLOR);
    }
    else {
      bprintf("Welcome to the wonderful world of \033[1;31mC\033[32mO\033[33mL\033[34mO\033[35mR\033[36m!\033[0m\n");
      ssetflg(mynum, SFL_COLOR);
    }
    break;
  case VERB_ALOOF:
    if (plev(mynum) < LVL_WIZARD) {
      erreval();
      break;
    }
    if (ststflg(mynum, SFL_ALOOF)) {
      bprintf("You feel less distant.\n");
      sclrflg(mynum, SFL_ALOOF);
    }
    else {
      bprintf("From now on you'll ignore some mortals' actions.\n");
      ssetflg(mynum, SFL_ALOOF);
    }
    break;
  case VERB_SHOW:
    showitem();
    break;
  case VERB_WIZLOCK:
    wizlock();
    break;
  case VERB_AWIZ:
    awizcom();
    break;
  case VERB_FOLLOW:
    followcom();
    break;
  case VERB_LOSE:
    losecom();
    break;
#if 0
  case VERB_CLS:
    cls();
    break;
#endif
  case VERB_ECHO:
    echocom();
    break;
  case VERB_ECHOALL:
    echoallcom();
    break;
  case VERB_ECHOTO:
    echotocom();
    break;
  case VERB_WISH:
    wishcom();
    break;
#if 0
  case VERB_TRACE:
    tracecom();
    break;
#endif
  case VERB_START:
    startcom();
    break;
  case VERB_STOP:
    stopcom();
    break;
  case VERB_MOBILES:
    mobilecom();
    break;
  case VERB_UNVEIL:
    unveilcom(NULL);
    break;
  case VERB_BANG:
    if (plev(mynum) < LVL_SORCERER)
      erreval();
    else
      broad("\001dA huge crash of thunder echoes through the land.\n\003");
    break;
  case VERB_TRANSLOCATE:
    sumcom();
    break;
  case VERB_ALIAS:
    aliascom();
    return;
  case VERB_LFLAGS:
    lflagscom();
    break;
  case VERB_PRIVS:
    pflagscom();
    break;
  case VERB_VERSION:
    bprintf(VERSION "\n");
    break;
  case VERB_MEDITATE:

#ifdef LOCMIN_ANCIENT
    if (ploc(mynum) == LOC_ANCIENT_ANC59) {
        if (oarmor(OBJ_ANCIENT_LBOOK) == 0) {
            bprintf("You meditate, but nothing seems to happen.\n");
        } else {
            bprintf("You are teleported!\n\n\n");
            trapch(LOC_ANCIENT_ANC35);
	}
        break;
    }
#endif
    bprintf("You meditate quietly in the corner.\n");
    break;

  default:
    mudlog( "No match for verb = %d", vb);
    bprintf("You can't do that now.\n");
    break;
  }
}


void quit_game(void)
{
    char xx[128];

    if (cur_player->aliased) {
      unalias(real_mynum);
      return;
    }

    if (pfighting(mynum) >= 0) {
      bprintf("Not in the middle of a fight!\n");
      return;
    }

    if (cur_player->polymorphed >= 0) {
      bprintf("A mysterious force won't let you quit.\n");
      return;
    }

    bprintf("Ok");

    send_msg(ploc(mynum), 0, pvis(mynum), LVL_MAX, mynum, NOBODY,
	     "%s\n", build_setin(xx, cur_player->setqout,pname(mynum), NULL));

    send_msg(DEST_ALL, MODE_QUIET|MODE_COLOR, max(pvis(mynum),LVL_WIZARD),
	     LVL_MAX, mynum, NOBODY, "[Quitting Game: %s]\n", pname(mynum));
    crapup("\t\t\tGoodbye", CRAP_SAVE);
}

void erreval(void)
{
  bprintf("You can't do that now.\n");
}

Boolean parse_2(int vb)
{
  int savestp = stp;
  int ob, pl, pre;

  *item1 = *item2 = '\0';

  if (vb == -1) return;
  ob1 = pl1 = ob2 = pl2 = -1;
  prep = 0;
  txt1 = markpos();
  txt2 = NULL;
  parse_1(item1,&pl,&ob,&pre);
#if 0
  bprintf( "vb = %d, item1 = %s, pl = %d, ob = %d, pre = %d\n",
	  vb, item1, pl, ob, pre);
#endif
  if (pre == 0) {
    ob1 = ob;
    pl1 = pl;
    txt2 = markpos();
    parse_1(item2,&pl,&ob,&pre);
  }
  if (pre != 0) {
    prep = pre;
    parse_1(item2,&pl,&ob,&pre);
  }
  if (pre != 0) {
    bprintf("Huh?\n");
    return False;
  } else {
    pl2 = pl;
    ob2 = ob;
  }
  stp = savestp;
  return True;
}

static void parse_1(char *itemb,int *pl,int *ob,int *pre)
{
  int o, p;

  *pl = *ob = -1;
  *pre = 0;
  if (brkword() != -1) {
    strcpy(itemb,wordbuf);
    if ((p = findprep(itemb)) != -1) {
      *pre = p;
    } else {
      /* It's not a preposition. */
      if ((p = *pl = fpbn(itemb)) != -1) {
	if (psex(p)) {
	  cur_player->wd_them = strcpy(cur_player->wd_her,pname(p));
	} else {
	  cur_player->wd_them = strcpy(cur_player->wd_him,pname(p));
	}
      }

      if ((o = *ob = fobnc(itemb)) != -1 || (o = *ob = fobna(itemb)) != -1) {
	cur_player->wd_it = oname(o);
      }
    }
  }
}

static char *markpos(void)
{
  register int c;

  while ((c = strbuf[stp]) == ',' || isspace(c)) ++stp;
  return strbuf + stp;
}

int findprep(char *t)
{
  return xlookup(t,preptable);
}

int prmmod(int p)
{
  switch (p) {
  case FL_PL1:   return pl1;
  case FL_PL2:   return pl2;
  case FL_OB1:   return ob1;
  case FL_OB2:   return ob2;
  case FL_CURCH: return ploc(mynum);
  case FL_PREP:  return prep;
  case FL_LEV:   return plev(mynum);
  case FL_STR:   return pstr(mynum);
  case FL_SEX:   return psex(mynum);
  case FL_SCORE: return pscore(mynum);
  case FL_MYNUM: return mynum;
  }
#if 0
  if (p >= 10000) return globaldata[p - 10000];
#endif

  if (IS_PL(p)) return p - PL_CODE + max_players;
  return p;
}