#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "merc.h"
#include "olc.h"
#include "obj_trig.h"
extern int top_vnum_room;
extern long int level_cost (int level);

int getbit args((char *explored, int index));
	

void do_submit (CHAR_DATA * ch, char *argument)
{
  send_to_char ("Please enter the mob's vnum:\n\r", ch);
  ch->desc->editor = SUBMIT_MOB_VNUM;
}

void do_mail (CHAR_DATA * ch, char *argument)
{
  char *mailto, tcbuf[MAX_STRING_LENGTH];
  if (argument[0] == '\0' || IS_NPC (ch))
    {
      send_to_char ("Send mail to who?\n\r", ch);
      return;
    }
  if ((mailto = get_player_email (argument)) == NULL)
    {
      send_to_char ("Sorry, no such player exists on Exodus.\n\r", ch);
      return;
    }
  sprintf (tcbuf, "From: exodus@mischief.com\nReply-To: %s\nTo: %s\n",
	   ch->pcdata->email_addr, mailto);
  ch->desc->submit_info = str_dup (tcbuf);
  send_to_char ("Subject:\n\r", ch);
  ch->desc->editor = MAIL_GET_SUBJECT;
}

int get_dir (char *arg)
{
  int door = MAX_DIR;
  if (!str_cmp (arg, "n") || !str_cmp (arg, "north"))
    door = DIR_NORTH;

  else if (!str_cmp (arg, "e") || !str_cmp (arg, "east"))
    door = DIR_EAST;

  else if (!str_cmp (arg, "s") || !str_cmp (arg, "south"))
    door = DIR_SOUTH;

  else if (!str_cmp (arg, "w") || !str_cmp (arg, "west"))
    door = DIR_WEST;

  else if (!str_cmp (arg, "u") || !str_cmp (arg, "up"))
    door = DIR_UP;

  else if (!str_cmp (arg, "d") || !str_cmp (arg, "down"))
    door = DIR_DOWN;
  return door;
}


/*
 * This little command helps a user debug the scripts online.  It can give
 * information about a single trigger, or general info on the mob's current
 * state of execution.
 */
void do_script (CHAR_DATA * ch, char *argument)
{
  char buf[MAX_STRING_LENGTH];
  char arg[MAX_INPUT_LENGTH];
  char arg2[MAX_INPUT_LENGTH];
  CHAR_DATA *victim;
  TRIGGER_DATA *trig;
  VARIABLE_DATA *var;
  argument = one_argument (argument, arg);
  one_argument (argument, arg2);
  if (arg[0] == '\0')
    {
      send_to_char ("Script whom (which trigger)?\n\r", ch);
      return;
    }
  if ((victim = get_char_world (ch, arg)) == NULL)
    {
      send_to_char ("They aren't here.\n\r", ch);
      return;
    }
  if (IS_NPC (victim))
    {
      sprintf (buf, "Name: '%s'\n\rArea: [%3d] '%s'\n\r", NAME (victim),
	       victim->pIndexData->area->vnum,
	       victim->pIndexData->area->name);
      send_to_char (buf, ch);
      sprintf (buf, "Vnum: %d  Sex: %s  Room: %d\n\r",
	       victim->pIndexData->vnum,
	       victim->sex == SEX_MALE ? "male" : victim->sex ==
	       SEX_FEMALE ? "female" : "neutral",
	       victim->in_room == NULL ? 0 : victim->in_room->vnum);
      send_to_char (buf, ch);
    }
  if (arg2[0] != '\0')
    {
      for (trig = victim->triggers; trig != NULL; trig = trig->next)
	{
	  if (!str_prefix (trig->name, arg2))
	    break;
	}
      if (trig == NULL)
	send_to_char ("No such trigger.\n\r", ch);

      else
	{
	  SCRIPT_DATA *scr;
	  char buf[MAX_STRING_LENGTH];
	  for (scr = trig->script; scr != NULL; scr = scr->next)
	    {
	      if (scr == trig->current)
		sprintf (buf, "##\n\r%s   <--\n\r", scr->command);

	      else
		sprintf (buf, "##\n\r%s\n\r", scr->command);
	      send_to_char (buf, ch);
	    }
	}
    }
  else
    {
      for (trig = victim->triggers; (trig != NULL); trig = trig->next)
	{
	  char buf[MAX_STRING_LENGTH];
	  if (trig != NULL)
	    {
	      sprintf (buf,
		       "Trigger '%s' (key '%s')\n\r'%s' w/tra/typ: %d %d %d  %s %s\n\r",
		       trig->name, trig->keywords,
		       trig->current !=
		       NULL ? trig->current->command : "not running",
		       trig->waiting, trig->tracer, trig->trigger_type,
		       IS_SET (trig->bits,
			       SCRIPT_ADVANCE) ? "" : "stopped",
		       IS_SET (trig->bits, SCRIPT_HALT) ? "halted" : "");
	      send_to_char (buf, ch);
	    }
	}
      if (victim->variables != NULL)
	send_to_char ("Variables:\n\r", ch);
      for (var = victim->variables; (var != NULL); var = var->next)
	{
	  char buf[MAX_STRING_LENGTH];
	  if (var != NULL)
	    {
	      sprintf (buf, "'%s' = '%s'\n\r", var->name, var->value);
	      send_to_char (buf, ch);
	    }
	}
      if (IS_NPC (victim))
	{
	  sprintf (buf,
		   "Current spec tracer set to %d, loads with file '%s'\n\r",
		   victim->spec_tracer, victim->pIndexData->script_fn);
	  send_to_char (buf, ch);
	}
    }
  send_to_char ("\n\r", ch);
  return;
}


/*
 * This is a quick and dirty utility for adding a few fields to a trigger
 * quickly.  When a script is triggered, information is sent into variables
 * using this procedure.  The arg, from, to are preceded by the command
 * string, thus:
 * act_trigger( bill, "Argyle", "Red", NULL, NULL );
 * would put the following variables on the mob bill:
 * %Argyle-arg%      = Red
 */
void
act_trigger (CHAR_DATA * mob,
	     char *command, char *argument, char *from, char *to)
{
  char buf[MAX_STRING_LENGTH];
  if (!HAS_SCRIPT (mob) || command == NULL)
    return;
  if (from != NULL)
    {
      sprintf (buf, "%%%s-from%%", command);
      assign_variable (buf, from, mob);
    }
  if (to != NULL)
    {
      sprintf (buf, "%%%s-to%%", command);
      assign_variable (buf, to, mob);
    }
  if (argument != NULL)
    {
      sprintf (buf, "%%%s-arg%%", command);
      assign_variable (buf, argument, mob);
    }
  return;
}


/*
 * This searches a list of variables for a variable with a certain name,
 * returning NULL if the variable happens to not currently exist.
 */
VARIABLE_DATA *get_variable (char *var_name, CHAR_DATA * mob)
{
  VARIABLE_DATA *var;
  for (var = mob->variables; var != NULL; var = var->next)
    {
      if (!str_cmp (var_name, var->name))
	{
	  return var;
	}
    }
  return NULL;
}


/*
 * Unlike the above, this takes a variable name and returns a value string
 * no matter if the variable exists or not.  This is for func evaluations
 * and if-thens mostly.
 */
char *varval (char *var_name, CHAR_DATA * mob)
{
  VARIABLE_DATA *var;
  var = get_variable (var_name, mob);
  if (var == NULL)
    return str_dup ("");
  return var->value;
}


/*
 * Assigns or creates a variable with a value.   Translates interior variables.
 */
void assign_variable (char *var_name, char *value, CHAR_DATA * mob)
{
  VARIABLE_DATA *var;
  if ((var = get_variable (var_name, mob)) != NULL)
    {
      free_string (var->value);
      var->value = translate_variables (value, mob);
    }
  else
    {
      if (variable_free == NULL)
	{
	  var = alloc_perm (sizeof (*var));
	}
      else
	{
	  var = variable_free;
	  variable_free = variable_free->next;
	}
      var->next = mob->variables;
      mob->variables = var;
      var->name = str_dup (var_name);
      var->value = translate_variables (value, mob);
    }
  return;
}


/*
 * Translates all variables in a string, note the usage of replace_string()..
 * which is as good as any.
 */
char *translate_variables (char *argument, CHAR_DATA * mob)
{
  VARIABLE_DATA *var;
  char *newstr = str_dup (argument);
  for (var = mob->variables; var != NULL; var = var->next)
    {
      if (strcmp (newstr, var->name) == 0)
	return newstr;
      while (strstr (newstr, var->name))
	newstr = replace_string (newstr, var->name, var->value);
    }
  return newstr;
}

char *replace_string (char *orig, char *old, char *new)
{
  char xbuf[MAX_STRING_LENGTH];
  int i;
  if (orig == NULL || old == NULL)
    return FALSE;
  xbuf[0] = '\0';
  strcpy (xbuf, orig);
  if (strstr (orig, old) != NULL)
    {
      i = strlen (orig) - strlen (strstr (orig, old));
      xbuf[i] = '\0';
      strcat (xbuf, new);
      strcat (xbuf, &orig[i + strlen (old)]);
      if (orig != NULL)
	free_string (orig);
    }
  return (str_dup (xbuf));
}


/*
 * Used to get sequential lines of a multi line string (separated by "\n\r")
 * Thus its like one_argument(), but a trifle different. It is destructive
 * to the multi line string argument, and thus clist must not be shared.
 */
char *next_command (char *argument, char *arg_first)
{
  while (*argument != '\0')
    {
      if (*argument == '\n')
	{
	  argument++;
	  break;
	}
      *arg_first = *argument;
      arg_first++;
      argument++;
    }
  *arg_first = '\0';
  return argument;
}


/*
 * Evaluates multiple line command parses and does them all in one pulse.
 * Kinda kludgy, but useful.
 */
void multi_interpret (CHAR_DATA * mob, char *com_list)
{
  char buf[MAX_STRING_LENGTH];
  while (com_list[0] != '\0')
    {
      com_list = next_command (com_list, buf);
      interpret (mob, buf);
    }
  return;
}


/*
 * Takes a plain and simple 1 + 2 + 4 * 2 and does a infix left to right
 * evaluation, returning the final numeric.
 */
int expression (char *ex, CHAR_DATA * ch)
{
  char buf[MAX_STRING_LENGTH];
  char op[MAX_STRING_LENGTH];
  int num;
  int val;
  if (ex == NULL)
    return 0;
  ex = first_arg (ex, buf, FALSE);
  if (buf[0] == '%')
    strcpy (buf, varval (buf, ch));
  num = atoi (buf);
  while (ex[0] != '\0')
    {
      ex = first_arg (ex, op, TRUE);
      ex = first_arg (ex, buf, TRUE);
      if (buf[0] == '%')
	strcpy (buf, varval (buf, ch));
      val = atoi (buf);
      switch (op[0])
	{
	case '+':
	  num = num + val;
	  break;
	case '-':
	  num = num - val;
	  break;
	case '/':
	  if (val == 0)
	    num = 0;

	  else
	    num = num / val;
	  break;
	case '*':
	  num = num * val;
	  break;
	case '&':
	  num = num & val;
	  break;
	case '|':
	  num = num | val;
	  break;
	case '^':
	  num = num ^ val;
	  break;
	default:
	  break;
	}
    }
  return num;
}


/*
 * This procedure is the 'let' routine. It assigns variables on a mobile,
 * allowing the translation of expressions with variables in them.
 */
void eval_assign (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char var[MAX_STRING_LENGTH];
  char op[MAX_STRING_LENGTH];
  char val[MAX_STRING_LENGTH];
  char num[MAX_STRING_LENGTH];
  char nval[MAX_STRING_LENGTH];
  argument = one_argument (argument, var);
  argument = first_arg (argument, op, TRUE);
  one_argument (argument, val);
  strcpy (val, argument);
  if (!str_cmp (op, "=="))
    assign_variable (var, val, ch);

  else if (!str_cmp (op, "="))
    {
      sprintf (num, "%d", expression (val, ch));
      assign_variable (var, num, ch);
    }
  else if (!str_cmp (op, "+="))
    {
      int iVal;
      int iOld;
      iVal = atoi (val);
      iOld =
	get_variable (var,
		      ch) == NULL ? 0 : atoi (get_variable (var, ch)->value);
      sprintf (val, "%d", iVal + iOld);
      assign_variable (var, val, ch);
    }
  else if (!str_cmp (op, "-="))
    {
      int iVal;
      int iOld;
      iVal = atoi (val);
      iOld =
	get_variable (var,
		      ch) == NULL ? 0 : atoi (get_variable (var, ch)->value);
      sprintf (val, "%d", iOld - iVal);
      assign_variable (var, val, ch);
    }
  else if (!str_cmp (op, "|="))
    {
      int iVal;
      int iOld;
      iVal = atoi (val);
      iOld =
	get_variable (var,
		      ch) == NULL ? 0 : atoi (get_variable (var, ch)->value);
      sprintf (val, "%d", iVal | iOld);
      assign_variable (var, val, ch);
    }
  else if (!str_cmp (op, "&="))
    {
      int iVal;
      int iOld;
      iVal = atoi (val);
      iOld =
	get_variable (var,
		      ch) == NULL ? 0 : atoi (get_variable (var, ch)->value);
      sprintf (val, "%d", iVal & iOld);
      assign_variable (var, val, ch);
    }
  else if (!str_cmp (op, "^="))
    {
      int iVal;
      int iOld;
      iVal = atoi (val);
      iOld =
	get_variable (var,
		      ch) == NULL ? 0 : atoi (get_variable (var, ch)->value);
      sprintf (val, "%d", iVal ^ iOld);
      assign_variable (var, val, ch);
    }
  else if (!str_cmp (op, "++"))
    {
      sprintf (nval, "%d", atoi (get_variable (var, ch)->value) + 1);
      assign_variable (var, nval, ch);
    }
  else if (!str_cmp (op, "--"))
    {
      sprintf (nval, "%d", atoi (get_variable (var, ch)->value) - 1);
      assign_variable (var, nval, ch);
    }
  return;
}


/*
 * the 'int' command -> does an interpret at the script level
 */
void eval_interp (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char *cmd;
  int truss;
  cmd = translate_variables (argument, ch);
  truss = ch->trust;
  ch->trust = 100;
  SET_BIT (ch->comm, COMM_TRUE_TRUST);
  interpret (ch, cmd);
  REMOVE_BIT (ch->comm, COMM_TRUE_TRUST);
  ch->trust = truss;
  free_string (cmd);
  return;
}


/*
 * This procedure does a few different 'halt' functions:
 *
 * 1)   triggers  -> will halt the single trigger until mob dies
 * 2)   all       -> halts the whole mob
 * 3)   statement -> aborts a single 'Sc' statement from continuing
 * 4)   once      -> abort it this time
 */
bool eval_halt (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg[MAX_STRING_LENGTH];
  one_argument (argument, arg);
  if (!str_cmp (arg, "once"))
    {
      trigger->current = NULL;
      return FALSE;
    }
  else if (!str_cmp (arg, "trigger"))
    {
      trigger->current = NULL;
      SET_BIT (trigger->bits, SCRIPT_HALT);
      return FALSE;
    }
  else if (!str_cmp (arg, "all"))
    {
      TRIGGER_DATA *Trig;
      SET_BIT (ch->act, ACT_HALT);
      for (Trig = ch->triggers; Trig != NULL; Trig = Trig->next)
	Trig->current = NULL;
      return FALSE;
    }
  else if (!str_cmp (arg, "statement"))
    return FALSE;
  return TRUE;
}


/*
 *  This procedure sets the pulse-wait state on mobs ( num = 2*arg1 )
 */
void eval_wait (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg[MAX_STRING_LENGTH];
  int waittime;
  one_argument (argument, arg);
  if (arg[0] == '\0')
    return;
  if (is_number (arg))
    {
      trigger->waiting = atoi (arg);
      return;
    }
  else if (!str_cmp (arg, "time"))
    {
      argument = one_argument (argument, arg);
      if (!is_number (arg))
	return;
      waittime = atoi (arg);
      if (waittime != time_info.hour)
	trigger->tracer--;
    }
  return;
}


/*
 *  This goto evaluates things one of two ways:
 *  1)  Will go to a specific script entry (counting 0 as first)
 *  2)  Go to a label ( define labels as the first part of a script ': label')
 */
void eval_goto (TRIGGER_DATA * trigger, char *argument)
{
  char arg[MAX_STRING_LENGTH];
  SCRIPT_DATA *scr = trigger->script;
  one_argument (argument, arg);
  if (is_number (arg))
    {
      int count = 0;
      int jump_loc;
      jump_loc = atoi (arg);
      while (count < jump_loc && scr != NULL)
	{
	  count++;
	  scr = scr->next;
	}
      trigger->current = scr;
    }
  else
    {
      char arg2[MAX_STRING_LENGTH];
      char *cmd;
      while (scr != NULL)
	{
	  cmd = one_argument (scr->command, arg2);
	  if (!str_cmp (arg2, ":"))
	    {
	      cmd = one_argument (cmd, arg2);
	      if (!str_cmp (arg2, arg))
		break;
	    }
	  scr = scr->next;
	}
      if (scr == NULL)
	scr = trigger->script;
      trigger->current = scr;
    }
  return;
}


/*
 * Assigns a single value on a mobile:
 * usage:
 * mfunc <mobile/variable of mobile's name>  <value/variable w/ value> <what>
 */
void eval_msign (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  CHAR_DATA *victim;
  int val;
  argument = one_argument (argument, arg1);	/* mob to assign */
  argument = one_argument_nl (argument, arg2);	/* value to assign */
  argument = one_argument (argument, arg3);	/* deliminator */
  if (arg1[0] == '%')
    strcpy (arg1, varval (arg1, ch));
  if (arg2[0] == '%')
    strcpy (arg2, varval (arg2, ch));
  victim = !str_cmp (arg1, "self") ? ch : get_char_world (ch, arg1);
  val = atoi (arg2);
  if (victim == NULL)
    {
      eval_halt (ch, trigger, "once");
      return;
    }
  else if (!str_cmp (arg3, "position"))
    victim->position = val;

  else if (!str_cmp (arg3, "mood"))
    victim->mood = val;

  else if (!str_cmp (arg3, "gold"))
    victim->gold = val;

  else if (!str_cmp (arg3, "silver"))
    victim->silver = val;

  else if (!str_cmp (arg3, "spectracer"))
    victim->spec_tracer = val;

  else if (!str_cmp (arg3, "exp"))
    victim->exp = val;

  else if (!str_cmp (arg3, "act"))
    victim->act = val;

  else if (!str_cmp (arg3, "affected_by"))
    victim->affected_by = val;

  else if (!str_cmp (arg3, "practice"))
    // victim->practice = val;
    val = val;

  else if (!str_cmp (arg3, "sex"))
    victim->sex = val;

  else if (!str_cmp (arg3, "race"))
    victim->race = val;

  else if (!str_cmp (arg3, "level"))
    victim->level = val;

  else if (!str_cmp (arg3, "align"))
    victim->alignment = val;

  else if (!str_cmp (arg3, "hit"))
    victim->hit = val;

  else if (!str_cmp (arg3, "maxhit"))
    victim->max_hit = val;

  else if (!str_cmp (arg3, "mana"))
    victim->mana = val;

  else if (!str_cmp (arg3, "maxmana"))
    victim->max_mana = val;

  else if (!str_cmp (arg3, "move"))
    victim->move = val;

  else if (!str_cmp (arg3, "short"))
    {
      char buf[MAX_STRING_LENGTH];
      sprintf (buf, "%s\n\r", arg2);
      free_string (victim->short_descr);
      victim->short_descr = str_dup (buf);
    }
  else if (!str_cmp (arg3, "long"))
    {
      char buf[MAX_STRING_LENGTH];
      sprintf (buf, "%s\n\r", arg2);
      free_string (victim->long_descr);
      victim->long_descr = str_dup (buf);
    }
  else if (!str_cmp (arg3, "maxmove"))
    victim->max_move = val;

  else if (!str_cmp (arg3, "str") && !IS_NPC (ch))
    victim->perm_stat[STAT_STR] = val;

  else if (!str_cmp (arg3, "int") && !IS_NPC (ch))
    victim->perm_stat[STAT_INT] = val;

  else if (!str_cmp (arg3, "wis") && !IS_NPC (ch))
    victim->perm_stat[STAT_WIS] = val;

  else if (!str_cmp (arg3, "dex") && !IS_NPC (ch))
    victim->perm_stat[STAT_DEX] = val;

  else if (!str_cmp (arg3, "con") && !IS_NPC (ch))
    victim->perm_stat[STAT_CON] = val;

  else if (!str_cmp (arg3, "cha") && !IS_NPC (ch))
    victim->perm_stat[STAT_CHA] = val;
  return;
}

void eval_osign (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  OBJ_DATA *obj;
  int val;
  argument = one_argument (argument, arg1);
  argument = one_argument_nl (argument, arg2);
  argument = one_argument (argument, arg3);
  if (arg1[0] == '%')
    strcpy (arg1, varval (arg1, ch));
  if (arg2[0] == '%')
    strcpy (arg2, varval (arg2, ch));
  obj = get_obj_world (ch, arg1);
  val = atoi (arg2);
  if (obj == NULL)
    {
      eval_halt (ch, trigger, "once");
      return;
    }
  else if (!str_cmp (arg3, "cost"))
    obj->cost = val;

  else if (!str_cmp (arg3, "wear_flags"))
    obj->wear_flags = val;

  else if (!str_cmp (arg3, "wear_loc"))
    obj->wear_loc = val;

  else if (!str_cmp (arg3, "weight"))
    obj->weight = val;

  else if (!str_cmp (arg3, "item_type"))
    obj->item_type = val;

  else if (!str_cmp (arg3, "level"))
    obj->level = val;

  else if (!str_cmp (arg3, "condition"))
    obj->condition = val;

  else if (!str_cmp (arg3, "short"))
    {
      free_string (obj->short_descr);
      obj->short_descr = str_dup (arg2);
    }
  else if (!str_cmp (arg3, "long"))
    {
      free_string (obj->description);
      obj->description = str_dup (arg2);
    }
  else if (!str_cmp (arg3, "material"))
    {
      free_string (obj->material);
      obj->material = str_dup (arg2);
    }
  else if (!str_cmp (arg3, "name"))
    {
      free_string (obj->name);
      obj->name = str_dup (arg2);
    }
  else if (!str_cmp (arg3, "timer"))
    obj->timer = val;

//IBLIS NOTE NOTE NOTE - This command only set the xtra flags in [0]
//CHANGE OR ADD if need to set other array elements
  else if (!str_cmp (arg3, "extra_flags"))
    obj->extra_flags[0] = val;

  else if (is_number (arg3))
    obj->value[URANGE (0, atoi (arg3), 4)] = val;
  return;
}

void eval_wsign (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  int val;
  argument = one_argument (argument, arg2);
  argument = one_argument (argument, arg3);
  if (arg2[0] == '%')
    strcpy (arg2, varval (arg2, ch));
  val = atoi (arg2);
  if (!str_cmp (arg3, "hour"))
    time_info.hour = val;

  else if (!str_cmp (arg3, "day"))
    time_info.day = val;

  else if (!str_cmp (arg3, "month"))
    time_info.month = val;

  else if (!str_cmp (arg3, "year"))
    time_info.year = val;

  else if (!str_cmp (arg3, "sunlight"))
    weather_info.sunlight = val;

  else if (!str_cmp (arg3, "mmhg"))
    weather_info.mmhg = val;

  else if (!str_cmp (arg3, "weather"))
    weather_info.sky = val;
  return;
}


/*
 * Grabs world stuff/random numbers.
 * Usage:
 * wfunc %variable-to-go-in% <what> [<min random> <max random>]
 */
void eval_wfunc (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  argument = one_argument (argument, arg1);
  argument = one_argument (argument, arg3);
  if (!str_cmp (arg3, "hour"))
    sprintf (buf, "%d", time_info.hour);

  else if (!str_cmp (arg3, "day"))
    sprintf (buf, "%d", time_info.day);

  else if (!str_cmp (arg3, "month"))
    sprintf (buf, "%d", time_info.month);

  else if (!str_cmp (arg3, "year"))
    sprintf (buf, "%d", time_info.year);

  else if (!str_cmp (arg3, "sunlight"))
    sprintf (buf, "%d", weather_info.sunlight);

  else if (!str_cmp (arg3, "mmhg"))
    sprintf (buf, "%d", weather_info.mmhg);

  else if (!str_cmp (arg3, "weather"))
    sprintf (buf, "%d", weather_info.sky);

  else if (!str_cmp (arg3, "topmob"))
    sprintf (buf, "%d", top_vnum_mob);

  else if (!str_cmp (arg3, "topobj"))
    sprintf (buf, "%d", top_vnum_obj);

  else if (!str_cmp (arg3, "toproom"))
    sprintf (buf, "%d", top_vnum_room);

  else if (!str_cmp (arg3, "random"))
    {
      char arg4[MAX_STRING_LENGTH];
      char arg5[MAX_STRING_LENGTH];
      argument = one_argument (argument, arg4);
      if (arg4[0] == '%')
	strcpy (arg4, varval (arg4, ch));
      argument = one_argument (argument, arg5);
      if (arg5[0] == '%')
	strcpy (arg5, varval (arg5, ch));
      sprintf (buf, "%d", number_range (atoi (arg4), atoi (arg5)));
    }
  else
    {
      short door;
      door = get_dir (arg3);
      if (door >= 0 && door < MAX_DIR)
	{
	  sprintf (buf, "%d", ch->in_room->exit[door] != NULL
		   && ch->in_room->exit[door]->u1.to_room !=
		   NULL ? ch->in_room->exit[door]->u1.to_room->
		   vnum : ROOM_VNUM_TEMPLATE);
	}
      else
	strcpy (buf, "0");
    }
  assign_variable (arg1, buf, ch);
  return;
}

void eval_mfunc (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  CHAR_DATA *victim;
  argument = one_argument (argument, arg1);	/* mob name */
  argument = one_argument (argument, arg2);	/* variable to put val in */
  argument = one_argument (argument, arg3);	/* deliminator */
  if (arg1[0] == '%')
    strcpy (arg1, varval (arg1, ch));
  victim = !str_cmp (arg1, "self") ? ch : get_char_world (ch, arg1);
  if (victim == NULL)
    sprintf (buf, "NOONE");

  else if (!str_cmp (arg3, "position"))
    sprintf (buf, "%d", victim->position);

  else if (!str_cmp (arg3, "gold"))
    sprintf (buf, "%ld", victim->gold);

  else if (!str_cmp (arg3, "silver"))
    sprintf (buf, "%ld", victim->silver);

  else if (!str_cmp (arg3, "name"))
    {
      sprintf (buf, "%s",
	       victim->name !=
	       NULL ? victim->name : victim->pIndexData->player_name);
      one_argument (buf, arg1);
      sprintf (buf, "%s", fcapitalize (arg1));
    }
  else if (!str_cmp (arg3, "room"))
    sprintf (buf, "%d", victim->in_room->vnum);

  else if (!str_cmp (arg3, "mood"))
    sprintf (buf, "%d", victim->mood);

  else if (!str_cmp (arg3, "short"))
    sprintf (buf, "%s", victim->short_descr);

  else if (!str_cmp (arg3, "long"))
    sprintf (buf, "%s", victim->long_descr);

  else if (!str_cmp (arg3, "spectracer"))
    sprintf (buf, "%d", victim->spec_tracer);

  else if (!str_cmp (arg3, "exp"))
    sprintf (buf, "%ld", victim->exp);

  else if (!str_cmp (arg3, "expneeded"))
    sprintf (buf, "%ld", IS_NPC (victim) ? -1 : level_cost (ch->level));

  else if (!str_cmp (arg3, "act"))
    sprintf (buf, "%ld", victim->act);

  else if (!str_cmp (arg3, "affected_by"))
    sprintf (buf, "%ld", victim->affected_by);

  else if (!str_cmp (arg3, "practice"))
    sprintf (buf, "0");

  else if (!str_cmp (arg3, "hitroll"))
    sprintf (buf, "%d", get_hitroll (victim));

  else if (!str_cmp (arg3, "damroll"))
    sprintf (buf, "%d", get_damroll (victim));

  else if (!str_cmp (arg3, "age"))
    sprintf (buf, "%d", get_age (victim));

  else if (!str_cmp (arg3, "sex"))
    sprintf (buf, "%d", victim->sex);

  else if (!str_cmp (arg3, "race"))
    sprintf (buf, "%d", victim->race);

  else if (!str_cmp (arg3, "class"))
    sprintf (buf, "%d", victim->class);

  else if (!str_cmp (arg3, "2class"))
    sprintf (buf, "%d", victim->class2);

  else if (!str_cmp (arg3, "3class"))
    sprintf (buf, "%d", victim->class3);

  else if (!str_cmp (arg3, "level"))
    sprintf (buf, "%d", victim->level);

  else if (!str_cmp (arg3, "align"))
    sprintf (buf, "%d", victim->alignment);

  else if (!str_cmp (arg3, "hit"))
    sprintf (buf, "%d", victim->hit);

  else if (!str_cmp (arg3, "maxhit"))
    sprintf (buf, "%d", victim->max_hit);

  else if (!str_cmp (arg3, "mana"))
    sprintf (buf, "%d", victim->mana);

  else if (!str_cmp (arg3, "maxmana"))
    sprintf (buf, "%d", victim->max_mana);

  else if (!str_cmp (arg3, "move"))
    sprintf (buf, "%d", victim->move);

  else if (!str_cmp (arg3, "maxmove"))
    sprintf (buf, "%d", victim->max_move);

  else if (!str_cmp (arg3, "str"))
    sprintf (buf, "%d", get_curr_stat (victim, STAT_STR));

  else if (!str_cmp (arg3, "int"))
    sprintf (buf, "%d", get_curr_stat (victim, STAT_INT));

  else if (!str_cmp (arg3, "dex"))
    sprintf (buf, "%d", get_curr_stat (victim, STAT_DEX));

  else if (!str_cmp (arg3, "wis"))
    sprintf (buf, "%d", get_curr_stat (victim, STAT_WIS));

  else if (!str_cmp (arg3, "con"))
    sprintf (buf, "%d", get_curr_stat (victim, STAT_CON));

  else if (!str_cmp (arg3, "cha"))
    sprintf (buf, "%d", get_curr_stat (victim, STAT_CHA));
  else if (!str_prefix ("qbit",arg3))
  {
    char qbuf[10];
    int i=0;
    if (arg3[4] != '\0')
      qbuf[i++] = arg3[4];
    if (arg3[5] != '\0')
      qbuf[i++] = arg3[5];
    if (arg3[6] != '\0')
      qbuf[i++] = arg3[6];
    qbuf[i] = '\0';
    i = atoi(qbuf);
    if (i < 0 || i > MAX_QUEST_BITS || IS_NPC(victim))
      i = -1;
    else i = (getbit(victim->pcdata->qbits,i));
    sprintf (buf, "%d",i);
  }
    

  else
    return;
  assign_variable (arg2, buf, ch);
  return;
}

void eval_chobj (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  CHAR_DATA *victim;
  int ovnum;
  OBJ_DATA *obj;
  argument = one_argument (argument, arg1);	/* mob name */
  argument = one_argument (argument, arg2);	/* variable to put val in */
  argument = one_argument (argument, arg3);	/* deliminator */
  if (arg1[0] == '%')
    strcpy (arg1, varval (arg1, ch));
  victim = !str_cmp (arg1, "self") ? ch : get_char_world (ch, arg1);
  strcpy (buf, "0");
  if (victim == NULL)
    {
      assign_variable (arg2, buf, ch);
      return;
    }
  ovnum = atoi (arg3);
  for (obj = victim->carrying; obj; obj = obj->next_content)
    if (obj->pIndexData->vnum == ovnum)
      {
	strcpy (buf, "1");
	break;
      }
  assign_variable (arg2, buf, ch);
  return;
}

void eval_getch (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  CHAR_DATA *fch;
  int cnt = 0, rnd;
  strcpy (buf, "0");
  argument = one_argument (argument, arg1);	/* variable to put val in */
  for (fch = ch->in_room->people; fch; fch = fch->next_in_room)
    if (can_see (ch, fch) && ch != fch)
      cnt++;
  rnd = number_range (1, cnt) - 1;
  cnt = 0;
  for (fch = ch->in_room->people; fch; fch = fch->next_in_room)
    {
      if (!can_see (ch, fch) || ch == fch)
	continue;
      if (cnt == rnd)
	{
	  strcpy (buf, NAME (fch));
	  break;
	}
      cnt++;
    }
  assign_variable (arg1, buf, ch);
  return;
}

void eval_getpc (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  CHAR_DATA *fch;
  int cnt = 0, rnd;
  argument = one_argument (argument, arg1);	/* variable to put val in */
  strcpy (buf, "0");
  for (fch = ch->in_room->people; fch; fch = fch->next_in_room)
    if (!IS_NPC (fch) && can_see (ch, fch))
      cnt++;
  rnd = number_range (1, cnt) - 1;
  cnt = 0;
  for (fch = ch->in_room->people; fch; fch = fch->next_in_room)
    {
      if (IS_NPC (fch) || !can_see (ch, fch))
	continue;
      if (cnt == rnd)
	{
	  strcpy (buf, NAME (fch));
	  break;
	}
      cnt++;
    }
  assign_variable (arg1, buf, ch);
  return;
}

void eval_ofunc (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  OBJ_DATA *obj;
  argument = one_argument (argument, arg1);	/* object name */
  argument = one_argument (argument, arg2);	/* variable to put val in */
  argument = one_argument (argument, arg3);	/* deliminator */
  if (arg1[0] == '%')
    strcpy (arg1, varval (arg1, ch));
  obj = get_obj_world (ch, arg1);
  if (obj == NULL)
    sprintf (buf, "NOTHING");

  else if (!str_cmp (arg3, "cost"))
    sprintf (buf, "%d", obj->cost);

  else if (!str_cmp (arg3, "vnum"))
    sprintf (buf, "%d", obj->pIndexData->vnum);

  else if (!str_cmp (arg3, "short"))
    sprintf (buf, "%s", obj->short_descr);

  else if (!str_cmp (arg3, "long"))
    sprintf (buf, "%s", obj->description);

  else if (!str_cmp (arg3, "material"))
    sprintf (buf, "%s", obj->material);

  else if (!str_cmp (arg3, "name"))
    {
      sprintf (buf, "%s", STR (obj, name));
      one_argument (buf, arg1);
      sprintf (buf, "%s", arg1);
    }
  else if (!str_cmp (arg3, "room"))
    sprintf (buf, "%d", obj->in_room != NULL ? obj->in_room->vnum : 0);

  else if (!str_cmp (arg3, "inobj"))
    sprintf (buf, "%s",
	     obj->in_obj != NULL ? STR (obj->in_obj, name) : "none");

  else if (!str_cmp (arg3, "carried_by"))
    sprintf (buf, "%s",
	     obj->carried_by != NULL ? obj->carried_by->name !=
	     NULL ? obj->carried_by->name : obj->carried_by->
	     pIndexData->player_name : "none");

  else if (!str_cmp (arg3, "wear_flags"))
    sprintf (buf, "%ld", obj->wear_flags);

  else if (!str_cmp (arg3, "wear_loc"))
    sprintf (buf, "%ld", obj->wear_loc);

  else if (!str_cmp (arg3, "weight"))
    sprintf (buf, "%d", obj->weight);

  else if (!str_cmp (arg3, "item_type"))
    sprintf (buf, "%d", obj->item_type);

  else if (!str_cmp (arg3, "level"))
    sprintf (buf, "%d", obj->level);

  else if (!str_cmp (arg3, "timer"))
    sprintf (buf, "%d", obj->timer);

  else if (!str_cmp (arg3, "condition"))
    sprintf (buf, "%d", obj->condition);

  else if (!str_cmp (arg3, "extra_flags"))
    sprintf (buf, "%ld", obj->extra_flags[0]);

  else if (is_number (arg3))
    sprintf (buf, "%d", obj->value[URANGE (0, atoi (arg3), 4)]);

  else
    return;
  assign_variable (arg2, buf, ch);
  return;
}

void eval_sfunc (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{

/*    char  arg[MAX_STRING_LENGTH];    */
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  char buf[MAX_STRING_LENGTH];
  char *st;
  int count;
  argument = one_argument (argument, arg1);	/* string */
  argument = one_argument (argument, arg2);	/* variable to put it in */
  argument = one_argument (argument, arg3);	/* arg deliminator */
  if (arg1[0] == '%')
    sprintf (arg1, "%s", varval (arg1, ch));
  if (!str_cmp (arg3, "money"))
    {
      sprintf (buf, "%d", atoi (arg1));
    }
  else if (is_number (arg3))
    {
      st = one_argument (arg1, buf);
      for (count = atoi (arg3); count > 0; count--)
	{
	  st = one_argument (st, buf);
	}
    }
  assign_variable (arg2, buf, ch);
  return;
}

bool boolchk (char *v1, char *v2, char *s)
{
  if (!str_cmp (s, "in"))
    return (str_infix (v1, v2));
  if (!str_cmp (s, "pre"))
    return (str_prefix (v1, v2));
  if (!str_cmp (s, "cmp"))
    return (!str_cmp (v1, v2));
  if (!str_cmp (s, "substr"))
    return (strstr (v2, v1) != NULL);
  if (!str_cmp (s, "num"))
    return (is_number (v1));
  if (!str_cmp (s, ">"))
    return (atoi (v1) > atoi (v2));
  if (!str_cmp (s, "<"))
    return (atoi (v1) < atoi (v2));
  if (!str_cmp (s, ">="))
    return (atoi (v1) >= atoi (v2));
  if (!str_cmp (s, "<="))
    return (atoi (v1) <= atoi (v2));
  if (!str_cmp (s, "=="))
    return (atoi (v1) == atoi (v2));
  if (!str_cmp (s, "!="))
    return (atoi (v1) != atoi (v2));
  if (!str_cmp (s, "&"))
    return (atoi (v1) & atoi (v2));
  if (!str_cmp (s, "|"))
    return (atoi (v1) | atoi (v2));
  if (!str_cmp (s, "isset"))
    return (IS_SET (atoi (v1), atoi (v2)));
  if (s[0] == '\0')
    return (atoi (v1));
  return FALSE;
}


#define C_AND     1
#define C_OR      2
#define C_NOT     4
bool eval_if (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char buf[MAX_STRING_LENGTH];
  char *arg;
  char v1[MAX_STRING_LENGTH];
  char v2[MAX_STRING_LENGTH];
  char s[MAX_STRING_LENGTH];
  bool ifstatement = TRUE;
  bool prev = TRUE;
  int andornot=0;
  while (argument[0] != '\0')
    {
      argument = first_arg (argument, buf, TRUE);
      arg = buf;
      
      while (arg[0] != '\0')
	{			/* do a single ( ) */
		
	  //andornot = 0;
	  arg = one_argument (arg, v1);
	  
	  
	  if (!str_cmp (v1, "not") || !str_cmp (v1, "!"))
	    {
	      arg = one_argument (arg, v1);
	      SET_BIT (andornot, C_NOT);
	      prev = ifstatement;
	      continue;
	    }
	  else if (!str_cmp (v1, "or") || !str_cmp (v1, "||"))
	    {
	      arg = one_argument (arg, v1);
	      SET_BIT (andornot, C_OR);
	      prev = ifstatement;
	       continue;
	    }
	  else if (!str_cmp (v1, "and") || !str_cmp (v1, "&&"))
	    {
	      arg = one_argument (arg, v1);
	      SET_BIT (andornot, C_AND);
	      prev = ifstatement;
	       continue;
	    }
	  else
	    {
	      arg = one_argument (arg, s);
	      arg = one_argument (arg, v2);
	      if (v1[0] == '%')
		strcpy (v1, varval (v1, ch));
	      if (v2[0] == '%')
		strcpy (v2, varval (v2, ch));
	      if (s[0] == '%')
		strcpy (s, varval (s, ch));
	      ifstatement = boolchk (v1, v2, s);
	    }
	  if (IS_SET (andornot, C_NOT))
	  {
	    ifstatement = !ifstatement;
	    andornot = 0;
	  }
	  if (IS_SET (andornot, C_AND))
	  {
	    ifstatement = ifstatement && prev;
	    andornot = 0;
	  }
	  if (IS_SET (andornot, C_OR))
	    {
	      ifstatement = ifstatement || prev;
	      andornot = 0;
	    }
	}
    }
  return ifstatement;
}


/*
bool 
eval_while(CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{ 
  char buf[MAX_STRING_LENGTH];
  char *arg;
  char v1[MAX_STRING_LENGTH];
  char v2[MAX_STRING_LENGTH];
  char s[MAX_STRING_LENGTH];
  bool ifstatement = TRUE;
  bool prev = TRUE;
  int andornot;

  while (argument[0] != '\0')
    {
      argument = first_arg(argument, buf, TRUE);
      arg = buf;

      while (arg[0] != '\0')	
	{
	  andornot = 0;
	  arg = one_argument(arg, v1);

	  if (!str_cmp(v1, "not") || !str_cmp(v1, "!"))
	    {
	      arg = one_argument(arg, v1);
	      SET_BIT(andornot, C_NOT);
	      prev = ifstatement;
	    }
	  else if (!str_cmp(v1, "or") || !str_cmp(v1, "||"))
	    {
	      arg = one_argument(arg, v1);
	      SET_BIT(andornot, C_OR);
	      prev = ifstatement;
	    }
	  else if (!str_cmp(v1, "and") || !str_cmp(v1, "&&"))
	    {
	      arg = one_argument(arg, v1);
	      SET_BIT(andornot, C_AND);
	      prev = ifstatement;
	    }
	  else
	    {
	      arg = one_argument(arg, s);
	      arg = one_argument(arg, v2);

	      if (v1[0] == '%')
		strcpy(v1, varval(v1, ch));
	      if (v2[0] == '%')
		strcpy(v2, varval(v2, ch));
	      if (s[0] == '%')
		strcpy(s, varval(s, ch));

	      ifstatement = boolchk(v1, v2, s);
	    }

	  if (IS_SET(andornot, C_NOT))
	    ifstatement = !ifstatement;
	  if (IS_SET(andornot, C_AND))
	    ifstatement = ifstatement && prev;
	  if (IS_SET(andornot, C_OR))
	    ifstatement = ifstatement || prev;

	}
    }

  if (!ifstatement)
    SET_BIT(trigger->bits, SCRIPT_ADVANCE);
  else
    REMOVE_BIT(trigger->bits, SCRIPT_ADVANCE);

  return ifstatement;
}
*/
#undef C_NOT
#undef C_AND
#undef C_OR
void eval_walkto (CHAR_DATA * ch, char *argument)
{
  char buf[MAX_STRING_LENGTH];
  one_argument (argument, buf);
  if (ch->in_room->vnum == atoi (buf))
    return;
  ch->walkto = atoi (buf);
}

void eval_mob (CHAR_DATA * ch, TRIGGER_DATA * trigger, char *argument)
{
  char arg1[MAX_STRING_LENGTH];
  char arg2[MAX_STRING_LENGTH];
  char arg3[MAX_STRING_LENGTH];
  char tcbuf[15];
  CHAR_DATA *victim;
  argument = one_argument (argument, arg1);	/* string */
  if (arg1[0] == '%')
    strcpy (arg1, varval (arg1, ch));
  argument = one_argument (argument, arg2);	/* string */
  if (arg2[0] == '%')
    strcpy (arg2, varval (arg2, ch));
  argument = one_argument (argument, arg3);	/* string */
  if (arg3[0] == '%')
    strcpy (arg3, varval (arg3, ch));
  victim = get_char_world (ch, arg2);
  if (!str_cmp (arg1, "push"))
    {
      char parg[MAX_STRING_LENGTH];
      sprintf (parg, "%s %s", arg2, arg3);
      push_char (ch, parg, TRUE);
    }
  else if (!str_cmp (arg1, "lock"))
    {
      int door;
      door = get_dir (arg2);
      if (ch->in_room->exit[door] == NULL
	  || !IS_SET (ch->in_room->exit[door]->exit_info, EX_ISDOOR))
	{
	  eval_halt (ch, trigger, "once");
	  return;
	}
      SET_BIT (ch->in_room->exit[door]->exit_info, EX_LOCKED);
      if (ch->in_room->exit[door]->u1.to_room != NULL
	  && ch->in_room->exit[door]->u1.to_room->exit[rev_dir[door]] !=
	  NULL && IS_SET (ch->in_room->exit[door]->u1.to_room->
			  exit[rev_dir[door]]->exit_info, EX_ISDOOR))
	SET_BIT (ch->in_room->exit[door]->u1.to_room->
		 exit[rev_dir[door]]->exit_info, EX_LOCKED);
    }
  else if (!str_cmp (arg1, "unlock"))
    {
      int door;
      door = get_dir (arg2);
      if (ch->in_room->exit[door] == NULL
	  || !IS_SET (ch->in_room->exit[door]->exit_info, EX_ISDOOR))
	{
	  eval_halt (ch, trigger, "once");
	  return;
	}
      REMOVE_BIT (ch->in_room->exit[door]->exit_info, EX_LOCKED);
      if (ch->in_room->exit[door]->u1.to_room != NULL
	  && ch->in_room->exit[door]->u1.to_room->exit[rev_dir[door]] !=
	  NULL && IS_SET (ch->in_room->exit[door]->u1.to_room->
			  exit[rev_dir[door]]->exit_info, EX_ISDOOR))
	REMOVE_BIT (ch->in_room->exit[door]->u1.to_room->
		    exit[rev_dir[door]]->exit_info, EX_LOCKED);
    }
  else if (!str_cmp (arg1, "open"))
    {
      int door;
      door = get_dir (arg2);
      if (ch->in_room->exit[door] == NULL
	  || !IS_SET (ch->in_room->exit[door]->exit_info, EX_ISDOOR))
	{
	  eval_halt (ch, trigger, "once");
	  return;
	}
      REMOVE_BIT (ch->in_room->exit[door]->exit_info, EX_CLOSED);
      if (ch->in_room->exit[door]->u1.to_room != NULL
	  && ch->in_room->exit[door]->u1.to_room->exit[rev_dir[door]] !=
	  NULL && IS_SET (ch->in_room->exit[door]->u1.to_room->
			  exit[rev_dir[door]]->exit_info, EX_ISDOOR))
	REMOVE_BIT (ch->in_room->exit[door]->u1.to_room->
		    exit[rev_dir[door]]->exit_info, EX_CLOSED);
    }
  else if (!str_cmp (arg1, "close"))
    {
      int door;
      door = get_dir (arg2);
      if (ch->in_room->exit[door] == NULL
	  || !IS_SET (ch->in_room->exit[door]->exit_info, EX_ISDOOR))
	{
	  eval_halt (ch, trigger, "once");
	  return;
	}
      SET_BIT (ch->in_room->exit[door]->exit_info, EX_CLOSED);
      if (ch->in_room->exit[door]->u1.to_room != NULL
	  && ch->in_room->exit[door]->u1.to_room->exit[rev_dir[door]] !=
	  NULL && IS_SET (ch->in_room->exit[door]->u1.to_room->
			  exit[rev_dir[door]]->exit_info, EX_ISDOOR))
	SET_BIT (ch->in_room->exit[door]->u1.to_room->
		 exit[rev_dir[door]]->exit_info, EX_CLOSED);
    }
  else if (!str_cmp (arg1, "trans"))
    {
      ROOM_INDEX_DATA *pRoom;
      if (victim == NULL || (pRoom = get_room_index (atoi (arg3))) == NULL)
	{
	  eval_halt (ch, trigger, "once");
	  return;
	}
      char_from_room (victim);
      char_to_room (victim, pRoom);
      trip_triggers(victim, OBJ_TRIG_ENTER_ROOM, NULL, NULL, OT_SPEC_NONE);
      trap_check(victim,"room",victim->in_room,NULL);
      sprintf(tcbuf,"%d",victim->in_room->vnum);
      trip_triggers_arg(victim, OBJ_TRIG_CHAR_TO_ROOM, NULL, NULL, OT_SPEC_NONE,tcbuf);
      check_aggression(victim);
    }
  else if (!str_cmp (arg1, "cash"))
    {
      int cost;
      cost = atoi (arg3);
      if (victim == NULL)
	{
	  eval_halt (ch, trigger, "once");
	  return;
	}

      /*       if ( cost > 0 ) create_amount( cost, victim, NULL, NULL ); */
    }
  return;
}

void eval_signal (CHAR_DATA * ch, char *buf)
{
  CHAR_DATA *ach;
  char mob_str[MAX_STRING_LENGTH];
  char signal_name[MAX_STRING_LENGTH];
  int mob_vnum;
  buf = one_argument (buf, mob_str);
  one_argument (buf, signal_name);
  if (signal_name[0] == '%')
    strcpy (signal_name, varval (signal_name, ch));
  mob_vnum = atoi (mob_str);
  for (ach = char_list; ach; ach = ach->next)
    {
      if (!IS_NPC (ach))
	continue;
      if (mob_vnum == ach->pIndexData->vnum)
	{
	  if (HAS_SCRIPT (ach))
	    {
	      TRIGGER_DATA *pTrig;
	      for (pTrig = ach->triggers; pTrig != NULL; pTrig = pTrig->next)
		{
		  if (pTrig->trigger_type ==
		      TRIG_SIGNAL && pTrig->current ==
		      NULL && !IS_SET (ach->act, ACT_HALT))
		    {
		      act_trigger (ach, pTrig->name, signal_name,
				   NAME (ch), NULL);
		      pTrig->bits = SCRIPT_ADVANCE;
		      pTrig->current = pTrig->script;
		    }
		}
	    }
	}
    }
}
void script_interpret (CHAR_DATA * ch, TRIGGER_DATA * trigger)
{
  char buf[MAX_STRING_LENGTH];
  char buf2[MAX_STRING_LENGTH];
  char *cmd;
  if (trigger->current == NULL || trigger->current->command == NULL)
    return;
  trigger->tracer++;
  
  cmd = one_argument (trigger->current->command, buf2);
  while (cmd[0] != '\0')
    {
      cmd = next_command (cmd, buf);
      if (!str_cmp (buf2, "let"))
	eval_assign (ch, trigger, buf);

      else if (!str_cmp (buf2, "signal"))
	eval_signal (ch, buf);

      else if (!str_cmp (buf2, "walkto"))
	eval_walkto (ch, buf);

      else if (!str_cmp (buf2, "mob"))
	eval_mob (ch, trigger, buf);

      else if (!str_cmp (buf2, "ofunc"))
	eval_ofunc (ch, trigger, buf);

      else if (!str_cmp (buf2, "osign"))
	eval_osign (ch, trigger, buf);

      else if (!str_cmp (buf2, "mfunc"))
	eval_mfunc (ch, trigger, buf);

      else if (!str_cmp (buf2, "chobj"))
	eval_chobj (ch, trigger, buf);

      else if (!str_cmp (buf2, "getch"))
	eval_getch (ch, trigger, buf);

      else if (!str_cmp (buf2, "getpc"))
	eval_getpc (ch, trigger, buf);

      else if (!str_cmp (buf2, "msign"))
	eval_msign (ch, trigger, buf);

      else if (!str_cmp (buf2, "wfunc"))
	eval_wfunc (ch, trigger, buf);

      else if (!str_cmp (buf2, "wsign"))
	eval_wsign (ch, trigger, buf);

      else if (!str_cmp (buf2, "sfunc"))
	eval_sfunc (ch, trigger, buf);

      else if (!str_cmp (buf2, "jump"))
	eval_goto (trigger, buf);

      else if (!str_cmp (buf2, "wait"))
	eval_wait (ch, trigger, buf);

      else if (!str_cmp (buf2, "if"))
	{
	  if (!eval_if (ch, trigger, buf))
	    return;
	}
      else if (!str_cmp (buf2, "cmd"))
	{
	  eval_interp (ch, trigger, buf);
	}
      else if (!str_cmp (buf2, "halt"))
	{
	  if (!eval_halt (ch, trigger, buf))
	    return;
	}
      else
	{
	  strcat (buf2, " ");
	  strcat (buf2, buf);
	  eval_interp (ch, trigger, buf2);
	}
      cmd = one_argument (cmd, buf2);
    }
  return;
}


/*
 * Called from the mobile_update() procedure in update.c
 * This should be called every mobile pulse or so.
 */
void script_update (CHAR_DATA * ch, int timetype)
{
  TRIGGER_DATA *trig;
  if (!IS_NPC (ch))
    return;
  for (trig = ch->triggers; trig != NULL; trig = trig->next)
    {
      if (IS_SET (ch->act, ACT_HALT) || IS_SET (trig->bits, SCRIPT_HALT))
	{
	  trig->current = NULL;
	  continue;
	}
      if (trig->waiting > 0)
	{
	  trig->waiting--;
	  continue;
	}
      if (trig->trigger_type == timetype && trig->current == NULL)
	{
	  trig->current = trig->script;
	  trig->bits = SCRIPT_ADVANCE;
	}
      if (trig->current == NULL || !IS_SET (trig->bits, SCRIPT_ADVANCE))
	{
	  continue;
	}
      script_interpret (ch, trig);
      if (trig->current != NULL)
	trig->current = trig->current->next;

      else
	trig->tracer = 0;
    }
  return;
}


/*
 * BFS return values.
 */
#define BFS_ERROR           -1
#define BFS_ALREADY_THERE   -2
#define BFS_NO_PATH         -3
struct bfs_queue_struct
{
  ROOM_INDEX_DATA *room;
  sh_int dir;
  sh_int depth;
  struct bfs_queue_struct *next;
};
struct room_list_struct
{
  ROOM_INDEX_DATA *room;
  struct room_list_struct *next;
};
static struct bfs_queue_struct *queue_head = NULL, *queue_tail = NULL;
static struct room_list_struct *list_head = NULL, *list_tail = NULL;

/* Utility macros */
#define MARK( room )          ( SET_BIT( ( room )->room_flags, BFS_MARK))
#define UNMARK( room )        ( REMOVE_BIT( ( room )->room_flags, BFS_MARK))
#define IS_MARKED( room )     ( IS_SET( ( room )->room_flags, BFS_MARK))
#define TOROOM( room, y )     ( ( room )->exit[ ( y ) ]->u1.to_room )
#define IS_CLOSED( room, y )  ( IS_SET( ( room )->exit[( y )]->exit_info, \
    EX_CLOSED))
/* #define VALID_EDGE( room , y )                                             \
                              ( ( room )->exit[ ( y ) ] &&                 \
                              ( TOROOM( ( room ), ( y ) ) != NULL ) &&     \
                              ( !IS_CLOSED( (room), ( y ) ) ) &&           \
                              ( !IS_MARKED( TOROOM( ( room ), ( y ) ) ) ) )
			      */
inline int valid_edge (ROOM_INDEX_DATA * room, int dir, CHAR_DATA * ch)
{
  if (room->exit[dir] == NULL)
    return (0);
  if (room->exit[dir]->u1.to_room == NULL)
    return (0);
  if (IS_MARKED (TOROOM (room, dir)))
    return (0);
  if (IS_CLOSED (room, dir) && ch->huntto == 0)
    return (0);
  switch (TOROOM (room, dir)->sector_type)
    {
    case SECT_WATER_SWIM:
    case SECT_WATER_NOSWIM:
    case SECT_AIR:
      if (!is_affected (ch, skill_lookup ("fly")))
	return (0);
    }
  if (IS_SET (TOROOM (room, dir)->room_flags, ROOM_IMP_ONLY)
      || IS_SET (TOROOM (room, dir)->room_flags, ROOM_GODS_ONLY) ||
      /*        IS_SET(TOROOM(room, dir)->room_flags, ROOM_HEROES_ONLY) || */
      IS_SET (TOROOM (room, dir)->room_flags, ROOM_NEWBIES_ONLY))
    return (0);
  return (1);
}

void list_enqueue (ROOM_INDEX_DATA * room)
{
  static struct room_list_struct *curr;
  curr = alloc_mem (sizeof (struct room_list_struct));
  curr->room = room;
  curr->next = NULL;
  if (list_tail != NULL)
    {
      list_tail->next = curr;
      list_tail = curr;
    }
  else
    list_head = list_tail = curr;
  return;
}

void bfs_enqueue (ROOM_INDEX_DATA * room, sh_int dir, sh_int depth)
{
  struct bfs_queue_struct *curr;
  curr = alloc_mem (sizeof (struct bfs_queue_struct));
  curr->room = room;
  curr->dir = dir;
  curr->depth = depth + 1;
  curr->next = NULL;
  if (queue_tail != NULL)
    {
      queue_tail->next = curr;
      queue_tail = curr;
    }
  else
    queue_head = queue_tail = curr;
  list_enqueue (room);
  return;
}

void bfs_dequeue (void)
{
  struct bfs_queue_struct *curr;
  curr = queue_head;
  if ((queue_head = queue_head->next) == NULL)
    queue_tail = NULL;
  free_mem (curr, sizeof (struct bfs_queue_struct));
  return;
}

void list_dequeue (void)
{
  struct room_list_struct *curr;
  curr = list_head;
  if ((list_head = list_head->next) == NULL)
    list_tail = NULL;
  UNMARK (curr->room);
  free_mem (curr, sizeof (struct room_list_struct));
  return;
}

void bfs_clear_queue (void)
{
  while (queue_head != NULL)
    bfs_dequeue ();
  return;
}

void list_clear_queue (void)
{
  while (list_head != NULL)
    list_dequeue ();
}


/* find_first_step: given a source room and a target room, find the first
   step on the shortest path from the source to the target.

   Intended usage: in mobile_activity, give a mob a dir to go if they're
   tracking another mob or a PC.  Or, a 'track' skill for PCs.
*/
int
find_first_step (ROOM_INDEX_DATA * src, ROOM_INDEX_DATA * target,
		 CHAR_DATA * ch)
{
  int curr_dir;
  if (src == NULL || target == NULL)
    {
      bug ("Illegal value passed to find_first_step", 0);
      return BFS_ERROR;
    }
  if (src == target)
    return BFS_ALREADY_THERE;
  queue_head = queue_tail = NULL;
  list_head = list_tail = NULL;
  MARK (src);
  list_enqueue (src);
  for (curr_dir = 0; curr_dir < 6; curr_dir++)
    if (valid_edge (src, curr_dir, ch))
      {
	MARK (TOROOM (src, curr_dir));
	bfs_enqueue (TOROOM (src, curr_dir), curr_dir, 0);
      }

  /* now, do the classic BFS. */
  while (queue_head)
    {
      if (queue_head->depth >= 1000)
	{
	  bfs_clear_queue ();
	  list_clear_queue ();
	  return BFS_NO_PATH;
	}
      if (queue_head->room == target)
	{
	  curr_dir = queue_head->dir;
	  bfs_clear_queue ();
	  list_clear_queue ();
	  return curr_dir;
	}
      else
	{
	  for (curr_dir = 0; curr_dir < MAX_DIR; curr_dir++)
	    {
	      if (valid_edge (queue_head->room, curr_dir, ch))
		{
		  MARK (TOROOM (queue_head->room, curr_dir));
		  bfs_enqueue (TOROOM (queue_head->room, curr_dir),
			       queue_head->dir, queue_head->depth);
		}
	    }
	  bfs_dequeue ();
	}
    }
  list_clear_queue ();
  return BFS_NO_PATH;
}