EmberMUD-0.9.40/
EmberMUD-0.9.40/clan/
EmberMUD-0.9.40/gods/
EmberMUD-0.9.40/log/
EmberMUD-0.9.40/player/
EmberMUD-0.9.40/src/MSVC/
EmberMUD-0.9.40/src/Sleep/
EmberMUD-0.9.40/src/StartMUD/
EmberMUD-0.9.40/src/Win32Common/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,        *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *                                                                         *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael          *
 *  Chastain, Michael Quan, and Mitchell Tse.                              *
 *                                                                         *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc       *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.                                               *
 *                                                                         *
 *  Much time and thought has gone into this software and you are          *
 *  benefitting.  We hope that you share your changes too.  What goes      *
 *  around, comes around.                                                  *
 ***************************************************************************/

/***************************************************************************
 *  The MOBprograms have been contributed by N'Atas-ha.  Any support for   *
 *  these routines should not be expected from Merc Industries.  However,  *
 *  under no circumstances should the blame for bugs, etc be placed on     *
 *  Merc Industries.  They are not guaranteed to work on all systems due   *
 *  to their frequent use of strxxx functions.  They are also not the most *
 *  efficient way to perform their tasks, but hopefully should be in the   *
 *  easiest possible way to install and begin using. Documentation for     *
 *  such installation can be found in INSTALL.  Enjoy...         N'Atas-Ha *
 ***************************************************************************/

/***************************************************************************
 * Heavy modifications were made to Mobprogs (now MudProgs) by Thanatos,   *
 * Zak and Zane                                                            *
 ***************************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "merc.h"
#include "interp.h"

/*
 * Local function prototypes
 */

char *	mprog_next_command		args( ( char* clist ) );
bool	mprog_seval				args( ( char* lhs, char* opr, char* rhs ) );
bool	mprog_veval				args( ( int lhs, char* opr, int rhs ) );
long	mprog_do_ifchck			args( ( char* ifchck, CHAR_DATA* mob,
				       CHAR_DATA* actor, OBJ_DATA* obj,
				       void* vo, CHAR_DATA* rndm, CHAR_DATA* evil ) );
char *	mprog_process_if		args( ( char* ifchck, char* com_list, 
				       CHAR_DATA* mob, CHAR_DATA* actor,
				       OBJ_DATA* obj, void* vo,
				       CHAR_DATA* rndm, CHAR_DATA *evil ) );
void	mprog_translate			args( ( char ch, char* t, CHAR_DATA* mob,
				       CHAR_DATA* actor, OBJ_DATA* obj,
				       void* vo, CHAR_DATA* rndm, CHAR_DATA *evil ) );
void	mprog_process_cmnd		args( ( char* cmnd, CHAR_DATA* mob, 
				       CHAR_DATA* actor, OBJ_DATA* obj,
				       void* vo, CHAR_DATA* rndm, CHAR_DATA *evil ) );
void	mprog_driver			args( ( char* com_list, CHAR_DATA* mob,
				       CHAR_DATA* actor, OBJ_DATA* obj,
				       void* vo ) );
void	set_supermob            args( ( void *source, int prog_type ) );
void    release_supermob		args( ( void ) );
void	room_act_add			args( ( ROOM_INDEX_DATA *room ) );

 /*
  * Structure needed to efficiently handle room and object act
  * triggers.
  */
struct  act_prog_data
{
    struct act_prog_data *next;
    void *vo;
};

CHAR_DATA *supermob;
struct act_prog_data *room_act_list;
struct act_prog_data *obj_act_list;

/***************************************************************************
 * Local function code and brief comments.
 */

/* if you dont have these functions, you damn well should... */

#ifdef DUNNO_STRSTR
char * strstr(s1,s2) const char *s1; const char *s2;
{
  char *cp;
  int i,j=strlen(s1)-strlen(s2),k=strlen(s2);
  if(j<0)
    return NULL;
  for(i=0; i<=j && strncmp(s1++,s2, k)!=0; i++);
  return (i>j) ? NULL : (s1-1);
}
#endif

/* 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 *mprog_next_command( char *clist )
{

  char *pointer = clist;

  if ( !pointer )
      return NULL;
      
  while ( *pointer != '\n' && *pointer != '\r' && *pointer != '\0' )
    pointer++;


  /* Strip \n\r and/or \r\n */
  if ( *pointer == '\n' )
    *pointer++ = '\0';
  else if ( *pointer == '\r' )
    *pointer++ = '\0';

  if ( *pointer == '\n' )
    *pointer++ = '\0';
  else if ( *pointer == '\r' )
    *pointer++ = '\0';

  return ( pointer );

}

/* These two functions do the basic evaluation of ifcheck operators.
 *  It is important to note that the string operations are not what
 *  you probably expect.  Equality is exact and division is substring.
 *  remember that lhs has been stripped of leading space, but can
 *  still have trailing spaces so be careful when editing since:
 *  "guard" and "guard " are not equal.
 */
bool mprog_seval( char *lhs, char *opr, char *rhs )
{

  if ( !str_cmp( opr, "==" ) )
    return ( bool )( !str_cmp( lhs, rhs ) );
  if ( !str_cmp( opr, "!=" ) )
    return ( bool )( str_cmp( lhs, rhs ) );
  if ( !str_cmp( opr, "/" ) )
    return ( bool )( !str_infix( rhs, lhs ) );
  if ( !str_cmp( opr, "!/" ) )
    return ( bool )( str_infix( rhs, lhs ) );

  bug ( "Improper MudProg operator\n\r", 0 );
  return 0;

}

bool mprog_veval( int lhs, char *opr, int rhs )
{

  if ( !str_cmp( opr, "==" ) )
    return ( lhs == rhs );
  if ( !str_cmp( opr, "!=" ) )
    return ( lhs != rhs );
  if ( !str_cmp( opr, ">" ) )
    return ( lhs > rhs );
  if ( !str_cmp( opr, "<" ) )
    return ( lhs < rhs );
  if ( !str_cmp( opr, "<=" ) )
    return ( lhs <= rhs );
  if ( !str_cmp( opr, ">=" ) )
    return ( lhs >= rhs );
  if ( !str_cmp( opr, "&" ) )
    return ( lhs & rhs );
  if ( !str_cmp( opr, "|" ) )
    return ( lhs | rhs );

  bug ( "Improper MudProg operator\n\r", 0 );
  return 0;

}

/* This function performs the evaluation of the if checks.  It is
 * here that you can add any ifchecks which you so desire. Hopefully
 * it is clear from what follows how one would go about adding your
 * own. The syntax for an if check is: ifchck ( arg ) [opr val]
 * where the parenthesis are required and the opr and val fields are
 * optional but if one is there then both must be. The spaces are all
 * optional. The evaluation of the opr expressions is farmed out
 * to reduce the redundancy of the mammoth if statement list.
 * If there are errors, then return -1 otherwise return boolean 1,0
 */
long mprog_do_ifchck( char *ifchck, CHAR_DATA *mob, CHAR_DATA *actor,
		     OBJ_DATA *obj, void *vo, CHAR_DATA *rndm, CHAR_DATA *evil)
{

  char buf[ MAX_INPUT_LENGTH ];
  char arg[ MAX_INPUT_LENGTH ];
  char opr[ MAX_INPUT_LENGTH ];
  char val[ MAX_INPUT_LENGTH ];
  CHAR_DATA *pMob;
  CHAR_DATA *vict = (CHAR_DATA *) vo;
  OBJ_DATA *v_obj = (OBJ_DATA  *) vo;
  char     *bufpt = buf;
  char     *argpt = arg;
  char     *oprpt = opr;
  char     *valpt = val;
  char     *point = ifchck;
  int       lhsvl;
  int       rhsvl;

  if ( *point == '\0' ) 
    {
      bug ( "Mob: %d null ifchck", mob->pIndexData->vnum ); 
      return -1;
    }   
  /* skip leading spaces */
  while ( *point == ' ' )
    point++;

  /* get whatever comes before the left paren.. ignore spaces */
  while ( *point != '(' ) 
    if ( *point == '\0' ) 
      {
	bug ( "Mob: %d ifchck syntax error", mob->pIndexData->vnum ); 
	return -1;
      }   
    else
      if ( *point == ' ' )
	point++;
      else 
	*bufpt++ = *point++; 

  *bufpt = '\0';
  point++;

  /* get whatever is in between the parens.. ignore spaces */
  while ( *point != ')' )
    if ( *point == '\0' ) 
      {
	bug ( "Mob: %d ifchck syntax error", mob->pIndexData->vnum ); 
	return -1;
      }   
    else
      if ( *point == ' ' )
	point++;
      else 
	*argpt++ = *point++; 

  *argpt = '\0';
  point++;

  /* check to see if there is an operator */
  while ( *point == ' ' )
    point++;
  if ( *point == '\0' ) 
    {
      *opr = '\0';
      *val = '\0';
    }   
  else /* there should be an operator and value, so get them */
    {
      while ( ( *point != ' ' ) && ( !isalnum( *point ) ) ) 
	if ( *point == '\0' ) 
	  {
	    bug ( "Mob: %d ifchck operator without value",
		 mob->pIndexData->vnum ); 
	    return -1;
	  }   
	else
	  *oprpt++ = *point++; 

      *oprpt = '\0';
 
      /* finished with operator, skip spaces and then get the value */
      while ( *point == ' ' )
	point++;
      for( ; ; )
	{
	  if ( ( *point != ' ' ) && ( *point == '\0' ) )
	    break;
	  else
	    *valpt++ = *point++; 
	}

      *valpt = '\0';
    }
  bufpt = buf;
  argpt = arg;
  oprpt = opr;
  valpt = val;

  /* Ok... now buf contains the ifchck, arg contains the inside of the
   *  parentheses, opr contains an operator if one is present, and val
   *  has the value if an operator was present.
   *  So.. basically use if statements and run over all known ifchecks
   *  Once inside, use the argument and expand the lhs. Then if need be
   *  send the lhs,opr,rhs off to be evaluated.
   */

  if ( !str_cmp( buf, "memory" ) )
     {  /* if memory() returns TRUE if anything is in memory      */
	/* if memory() == $* returns TRUE if memory ==,!=,/,!/ $* */
	if ( mob->memory == NULL ) return FALSE;
	else if (get_char_world(mob,mob->memory->name) == NULL) return FALSE;
	if (opr[0]=='\0') return TRUE;
	if (val[0]=='$') switch (val[1])
	  {
	   case 'i': return FALSE; /* can't remember myself */
	   case 'n': if (actor)
	       return mprog_seval(actor->name,opr,mob->memory->name);
	       else return -1;
	   case 't': if (vict)
	       return mprog_seval(vict->name,opr,mob->memory->name);
	       else return -1;
	   case 'r': if (rndm)
	       return mprog_seval(rndm->name,opr,mob->memory->name);
	       else return -1;
	   case 'x': if (evil)
	       return mprog_seval(evil->name,opr,mob->memory->name);
	       else return -1;
	   default : bug("Mob: %d bad val for 'if memory'",mob->pIndexData->vnum);
	             return -1;
	  }
	return mprog_seval(val,opr,mob->memory->name);
     }

   if ( !str_cmp( buf, "rand" ) )
    {
      return ( number_percent() <= atoi(arg) );
    }

   if ( !str_cmp(buf, "getrand" ) )
   {
		lhsvl = number_range(1, atoi(arg));
		if (*opr == '\0')
		{
			return lhsvl;
		}
		else
		{
			if ( strstr(val, "(") )
			{
				rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
			}
			else
			{
				rhsvl = atoi( val );
			}
			return mprog_veval( lhsvl, opr, rhsvl );
		}
   }

   if ( !str_cmp(buf, "fightinroom" ) )
   {
	   for (pMob = mob->in_room->people; pMob && !pMob->fighting; pMob = pMob->next_in_room)
			;

	   if ( pMob )
		   lhsvl = 1;
	   else
		   lhsvl = 0;

		if (*opr == '\0')
		{
			return lhsvl;
		}
		else
		{
			if ( strstr(val, "(") )
			{
				rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
			}
			else
			{
				rhsvl = atoi( val );
			}
			return mprog_veval( lhsvl, opr, rhsvl );
		}
   }

  if ( !str_cmp(buf, "hour" ) )
  {
		lhsvl = time_info.hour;
		if (*opr == '\0')
		{
			return lhsvl;
		}
		else
		{
			if ( strstr(val, "(") )
			{
				rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
			}
			else
			{
				rhsvl = atoi( val );
			}
			return mprog_veval( lhsvl, opr, rhsvl );
		}
  }

  if ( !str_cmp( buf, "ispc" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return 0;
	case 'n': if ( actor )
 	             return ( !IS_NPC( actor ) );
	          else return -1;
	case 't': if ( vict )
                     return ( !IS_NPC( vict ) );
	          else return -1;
	case 'r': if ( rndm )
                     return ( !IS_NPC( rndm ) );
	          else return -1;
	case 'x': if ( evil )
                     return ( !IS_NPC( evil ) );
	          else return -1;
	default:
	  bug ( "Mob: %d bad argument to 'ispc'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "isnpc" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return 1;
	case 'n': if ( actor )
	             return IS_NPC( actor );
	          else return -1;
	case 't': if ( vict )
                     return IS_NPC( vict );
	          else return -1;
	case 'r': if ( rndm )
	             return IS_NPC( rndm );
	          else return -1;
	case 'x': if ( evil )
	             return IS_NPC( evil );
	          else return -1;
	default:
	  bug ("Mob: %d bad argument to 'isnpc'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "isgood" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return IS_GOOD( mob );
	case 'n': if ( actor )
	             return IS_GOOD( actor );
	          else return -1;
	case 't': if ( vict )
	             return IS_GOOD( vict );
	          else return -1;
	case 'r': if ( rndm )
	             return IS_GOOD( rndm );
	          else return -1;
	case 'x': if ( evil )
	             return IS_GOOD( evil );
	          else return -1;
	default:
	  bug ( "Mob: %d bad argument to 'isgood'", mob->pIndexData->vnum );
	  return -1;
	}
    }

  if ( !str_cmp( buf, "isfight" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return ( mob->fighting ) ? 1 : 0;
	case 'n': if ( actor )
	             return ( actor->fighting ) ? 1 : 0;
	          else return -1;
	case 't': if ( vict )
	             return ( vict->fighting ) ? 1 : 0;
	          else return -1;
	case 'r': if ( rndm )
	             return ( rndm->fighting ) ? 1 : 0;
	          else return -1;
	case 'x': if ( evil )
	             return ( evil->fighting ) ? 1 : 0;
	          else return -1;
	default:
	  bug ( "Mob: %d bad argument to 'isfight'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "isimmort" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return ( get_trust( mob ) > LEVEL_IMMORTAL );
	case 'n': if ( actor )
	             return ( get_trust( actor ) > LEVEL_IMMORTAL );
  	          else return -1;
	case 't': if ( vict )
	             return ( get_trust( vict ) > LEVEL_IMMORTAL );
                  else return -1;
	case 'r': if ( rndm )
	             return ( get_trust( rndm ) > LEVEL_IMMORTAL );
                  else return -1;
	case 'x': if ( evil )
	             return ( get_trust( evil ) > LEVEL_IMMORTAL );
                  else return -1;
	default:
	  bug ( "Mob: %d bad argument to 'isimmort'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "ischarmed" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return IS_SET( mob->affected_by , AFF_CHARM );
	case 'n': if ( actor )
	             return IS_AFFECTED( actor, AFF_CHARM );
	          else return -1;
	case 't': if ( vict )
	             return IS_AFFECTED( vict, AFF_CHARM );
	          else return -1;
	case 'r': if ( rndm )
	             return IS_AFFECTED( rndm, AFF_CHARM );
	          else return -1;
	case 'x': if ( evil )
	             return IS_AFFECTED( evil, AFF_CHARM );
	          else return -1;
	default:
	  bug ( "Mob: %d bad argument to 'ischarmed'",
	       mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "isfollow" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return ( mob->master != NULL
			  && mob->master->in_room == mob->in_room );
	case 'n': if ( actor )
	             return ( actor->master != NULL
			     && actor->master->in_room == actor->in_room );
	          else return -1;
	case 't': if ( vict )
	             return ( vict->master != NULL
			     && vict->master->in_room == vict->in_room );
	          else return -1;
	case 'r': if ( rndm )
	             return ( rndm->master != NULL
			     && rndm->master->in_room == rndm->in_room );
	          else return -1;
	case 'x': if ( evil )
	             return ( evil->master != NULL
			     && evil->master->in_room == evil->in_room );
	          else return -1;
	default:
	  bug ( "Mob: %d bad argument to 'isfollow'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "isaffected" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return ( mob->affected_by & atoi( arg ) );
	case 'n': if ( actor )
	             return ( actor->affected_by & atoi( arg ) );
	          else return -1;
	case 't': if ( vict )
	             return ( vict->affected_by & atoi( arg ) );
	          else return -1;
	case 'r': if ( rndm )
	             return ( rndm->affected_by & atoi( arg ) );
	          else return -1;
	case 'x': if ( evil )
	             return ( evil->affected_by & atoi( arg ) );
	          else return -1;
	default:
	  bug ( "Mob: %d bad argument to 'isaffected'",
	       mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "hitprcnt" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->hit / mob->max_hit;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
				      rhsvl = atoi( val );
				  }
  		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = actor->hit / actor->max_hit;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
			  else
				  return -1;
	case 't': if ( vict )
	          {
				  lhsvl = vict->hit / vict->max_hit;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
	              return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = rndm->hit / rndm->max_hit;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = evil->hit / evil->max_hit;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'hitprcnt'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "inroom" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->in_room->vnum;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
				      rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = actor->in_room->vnum;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
		      else
			      return -1;
	case 't': if ( vict )
	          {
				  lhsvl = vict->in_room->vnum;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = rndm->in_room->vnum;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = evil->in_room->vnum;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'inroom'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "crimethief" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = IS_SET(mob->act, PLR_THIEF);
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
				      rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = IS_SET(actor->act, PLR_THIEF);
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
		      else
			      return -1;
	case 't': if ( vict )
	          {
				  lhsvl = IS_SET(vict->act, PLR_THIEF);
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = IS_SET(rndm->act, PLR_THIEF);
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = IS_SET(evil->act, PLR_THIEF);
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'inroom'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "alignment" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->alignment;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
				      rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = actor->alignment;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
		      else
			      return -1;
	case 't': if ( vict )
	          {
				  lhsvl = vict->alignment;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = rndm->alignment;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = evil->alignment;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'alignment'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "sex" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->sex;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = actor->sex;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 't': if ( vict )
	          {
				  lhsvl = vict->sex;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = rndm->sex;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = evil->sex;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'sex'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "position" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->position;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = actor->position;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 't': if ( vict )
	          {
				  lhsvl = vict->position;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = rndm->position;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = evil->position;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'position'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "level" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = get_trust( mob );
			  if ( *opr == '\0' )
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
				  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = get_trust( actor );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else 
				  return -1;
	case 't': if ( vict )
	          {
			      lhsvl = get_trust( vict );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
		          return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = get_trust( rndm );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
			  else
		          return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = get_trust( evil );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
			  else
		          return -1;
	default:
	  bug ( "Mob: %d bad argument to 'level'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "immune" ) )
    {
	  if ( !obj )
		  return FALSE;
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = check_immune( mob, attack_table[obj->value[3]].damage );
			  if ( *opr == '\0' )
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
				  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = check_immune( actor, attack_table[obj->value[3]].damage );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else 
				  return -1;
	case 'r': if ( rndm )
	          {
			      lhsvl = check_immune( rndm, attack_table[obj->value[3]].damage );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
		          return -1;
	case 'x': if ( evil )
	          {
			      lhsvl = check_immune( evil, attack_table[obj->value[3]].damage );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
		          return -1;
	case 't': if ( vict )
	          {
			      lhsvl = check_immune( vict, attack_table[obj->value[3]].damage );
				  if ( *opr == '\0' )
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
					  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
		          return -1;
	default:
	  bug ( "Mob: %d bad argument to 'immune'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "class" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->Class;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = actor->Class;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else 
				  return -1;
	case 't': if ( vict )
	          {
				  lhsvl = vict->Class;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = rndm->Class;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = evil->Class;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'class'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "goldamt" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->gold;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
				  lhsvl = actor->gold;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 't': if ( vict )
	          {
				  lhsvl = vict->gold;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'r': if ( rndm )
	          {
				  lhsvl = rndm->gold;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'x': if ( evil )
	          {
				  lhsvl = evil->gold;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'goldamt'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "objtype" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'o': if ( obj )
	          {
				  lhsvl = obj->item_type;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
		          return -1;
	case 'p': if ( v_obj )
	          {
				  lhsvl = v_obj->item_type;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'objtype'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "objval0" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'o': if ( obj )
	          {
				  lhsvl = obj->value[0];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'p': if ( v_obj )
	          {
				  lhsvl = v_obj->value[0];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else 
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'objval0'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "objval1" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'o': if ( obj )
	          {
				  lhsvl = obj->value[1];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'p': if ( v_obj )
	          {
				  lhsvl = v_obj->value[1];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'objval1'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "objval2" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'o': if ( obj )
	          {
				  lhsvl = obj->value[2];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'p': if ( v_obj )
	          {
				  lhsvl = v_obj->value[2];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'objval2'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "objval3" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'o': if ( obj )
	          {
				  lhsvl = obj->value[3];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'p': if ( v_obj ) 
	          {
				  lhsvl = v_obj->value[3];
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'objval3'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "number" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': lhsvl = mob->gold;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
	case 'n': if ( actor )
	          {
		    if IS_NPC( actor )
		    {
		      lhsvl = actor->pIndexData->vnum;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
		    }
		  }
	          else
		    return -1;
	case 't': if ( vict )
	          {
		    if IS_NPC( actor )
		    {
		      lhsvl = vict->pIndexData->vnum;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
		    }
		  }
                  else
		    return -1;
	case 'r': if ( rndm )
	          {
		    if IS_NPC( actor )
		    {
		      lhsvl = rndm->pIndexData->vnum;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
		    }
		  }
	         else return -1;
	case 'x': if ( evil )
	          {
		    if IS_NPC( actor )
		    {
		      lhsvl = evil->pIndexData->vnum;
			  if (*opr == '\0')
			  {
				  return lhsvl;
			  }
			  else
			  {
				  if ( strstr(val, "(") )
				  {
					  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
				  }
				  else
				  {
					  rhsvl = atoi( val );
				  }
		     	  return mprog_veval( lhsvl, opr, rhsvl );
			  }
		    }
		  }
	         else return -1;
	case 'o': if ( obj )
	          {
				  lhsvl = obj->pIndexData->vnum;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	case 'p': if ( v_obj )
	          {
				  lhsvl = v_obj->pIndexData->vnum;
				  if (*opr == '\0')
				  {
					  return lhsvl;
				  }
				  else
				  {
					  if ( strstr(val, "(") )
					  {
						  rhsvl = mprog_do_ifchck(val, mob, actor, obj, vo, rndm, evil);
					  }
					  else
					  {
						  rhsvl = atoi( val );
					  }
		     		  return mprog_veval( lhsvl, opr, rhsvl );
				  }
			  }
	          else
				  return -1;
	default:
	  bug ( "Mob: %d bad argument to 'number'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  if ( !str_cmp( buf, "name" ) )
    {
      switch ( arg[1] )  /* arg should be "$*" so just get the letter */
	{
	case 'i': return mprog_seval( mob->name, opr, val );
	case 'n': if ( actor )
	            return mprog_seval( actor->name, opr, val );
	          else
		    return -1;
	case 't': if ( vict )
	            return mprog_seval( vict->name, opr, val );
	          else
		    return -1;
	case 'r': if ( rndm )
	            return mprog_seval( rndm->name, opr, val );
	          else
		    return -1;
	case 'x': if ( evil )
	            return mprog_seval( evil->name, opr, val );
	          else
		    return -1;
	case 'o': if ( obj )
	            return mprog_seval( obj->name, opr, val );
	          else
		    return -1;
	case 'p': if ( v_obj )
	            return mprog_seval( v_obj->name, opr, val );
	          else
		    return -1;
	default:
	  bug ( "Mob: %d bad argument to 'name'", mob->pIndexData->vnum ); 
	  return -1;
	}
    }

  /* Ok... all the ifchcks are done, so if we didnt find ours then something
   * odd happened.  So report the bug and abort the MudProg (return error)
   */
  bug ( "Mob: %d unknown ifchck = %s", mob->pIndexData->vnum, buf ); 
  return -1;

}
/* Quite a long and arduous function, this guy handles the control
 * flow part of MudProgs.  Basicially once the driver sees an
 * 'if' attention shifts to here.  While many syntax errors are
 * caught, some will still get through due to the handling of break
 * and errors in the same fashion.  The desire to break out of the
 * recursion without catastrophe in the event of a mis-parse was
 * believed to be high. Thus, if an error is found, it is bugged and
 * the parser acts as though a break were issued and just bails out
 * at that point. I havent tested all the possibilites, so I'm speaking
 * in theory, but it is 'guaranteed' to work on syntactically correct
 * MudProgs, so if the mud crashes here, check the mob carefully!
 */
char *mprog_process_if( char *ifchck, char *com_list, CHAR_DATA *mob,
		       CHAR_DATA *actor, OBJ_DATA *obj, void *vo,
		       CHAR_DATA *rndm, CHAR_DATA *evil )
{

 char null[ 1 ];
 char buf[ MAX_INPUT_LENGTH ];
 char *morebuf = '\0';
 char    *cmnd = '\0';
 bool loopdone = FALSE;
 bool     flag = FALSE;
 long  legal;

 *null = '\0';
  
 /* check for trueness of the ifcheck */
 if ( ( legal = mprog_do_ifchck( ifchck, mob, actor, obj, vo, rndm, evil ) ) )
   if ( legal == 1 )
     flag = TRUE;
   else
     return '\0';

 while( loopdone == FALSE ) /*scan over any existing or statements */
 {
     cmnd     = com_list;
     com_list = mprog_next_command( com_list );
     while ( *cmnd == ' ' )
       cmnd++;
     if ( *cmnd == '\0' )
     {
	 bug ( "Mob: %d no commands after IF/OR/AND", mob->pIndexData->vnum ); 
	 return '\0';
     }
     morebuf = one_argument( cmnd, buf );
     if ( !str_cmp( buf, "or" ) )
     {
	 if ( ( legal = mprog_do_ifchck( morebuf,mob,actor,obj,vo,rndm, evil ) ) )
	   if ( legal == 1 )
	     flag = TRUE;
	   else
	     return '\0';
     }
     else if ( !str_cmp( buf, "and" ) )
     {
	 if ( ( legal = mprog_do_ifchck( morebuf,mob,actor,obj,vo,rndm, evil ) ) )
	   if ( legal == 1 )
	     flag = flag && TRUE;
	   else
	     return '\0';
     }
	 else
       loopdone = TRUE;
 }
 
 if ( flag )
   for ( ; ; ) /*ifcheck was true, do commands but ignore else to endif*/ 
   {
       if ( !str_cmp( buf, "if" ) )
       { 
	   com_list = mprog_process_if(morebuf,com_list,mob,actor,obj,vo,rndm,evil);
	   while ( *cmnd==' ' )
	     cmnd++;
	   if ( *com_list == '\0' )
	     return '\0';
	   cmnd     = com_list;
	   com_list = mprog_next_command( com_list );
	   morebuf  = one_argument( cmnd,buf );
	   continue;
       }
       if ( !str_cmp( buf, "break" ) )
	 return '\0';
       if ( !str_cmp( buf, "endif" ) )
	 return com_list; 
       if ( !str_cmp( buf, "else" ) ) 
       {
	   while ( str_cmp( buf, "endif" ) ) 
	   {
	       cmnd     = com_list;
	       com_list = mprog_next_command( com_list );
	       while ( *cmnd == ' ' )
		 cmnd++;
	       if ( *cmnd == '\0' )
	       {
		   bug ( "Mob: %d missing endif after else",
			mob->pIndexData->vnum );
		   return '\0';
	       }
	       morebuf = one_argument( cmnd,buf );
	   }
	   return com_list; 
       }
       mprog_process_cmnd( cmnd, mob, actor, obj, vo, rndm, evil );
       cmnd     = com_list;
       com_list = mprog_next_command( com_list );
       while ( *cmnd == ' ' )
	 cmnd++;
       if ( *cmnd == '\0' )
       {
           bug ( "Mob: %d missing else or endif", mob->pIndexData->vnum ); 
           return '\0';
       }
       morebuf = one_argument( cmnd, buf );
   }
 else /*false ifcheck, find else and do existing commands or quit at endif*/
   {
     while ( ( str_cmp( buf, "else" ) ) && ( str_cmp( buf, "endif" ) ) )
       {
	 cmnd     = com_list;
	 com_list = mprog_next_command( com_list );
	 while ( *cmnd == ' ' )
	   cmnd++;
	 if ( *cmnd == '\0' )
	   {
	     bug ( "Mob: %d missing an else or endif",
		  mob->pIndexData->vnum ); 
	     return '\0';
	   }
	 morebuf = one_argument( cmnd, buf );
       }

     /* found either an else or an endif.. act accordingly */
     if ( !str_cmp( buf, "endif" ) )
       return com_list;
     cmnd     = com_list;
     com_list = mprog_next_command( com_list );
     while ( *cmnd == ' ' )
       cmnd++;
     if ( *cmnd == '\0' )
       { 
	 bug ( "Mob: %d missing endif", mob->pIndexData->vnum ); 
	 return '\0';
       }
     morebuf = one_argument( cmnd, buf );
     
     for ( ; ; ) /*process the post-else commands until an endif is found.*/
       {
	 if ( !str_cmp( buf, "if" ) )
	   { 
	     com_list = mprog_process_if( morebuf, com_list, mob, actor,
					 obj, vo, rndm, evil );
	     while ( *cmnd == ' ' )
	       cmnd++;
	     if ( *com_list == '\0' )
	       return '\0';
	     cmnd     = com_list;
	     com_list = mprog_next_command( com_list );
	     morebuf  = one_argument( cmnd,buf );
	     continue;
	   }
	 if ( !str_cmp( buf, "else" ) ) 
	   {
	     bug ( "Mob: %d found else in an else section",
		  mob->pIndexData->vnum ); 
	     return '\0';
	   }
	 if ( !str_cmp( buf, "break" ) )
	   return '\0';
	 if ( !str_cmp( buf, "endif" ) )
	   return com_list; 
	 mprog_process_cmnd( cmnd, mob, actor, obj, vo, rndm, evil );
	 cmnd     = com_list;
	 com_list = mprog_next_command( com_list );
	 while ( *cmnd == ' ' )
	   cmnd++;
	 if ( *cmnd == '\0' )
	   {
	     bug ( "Mob:%d missing endif in else section",
		  mob->pIndexData->vnum ); 
	     return '\0';
	   }
	 morebuf = one_argument( cmnd, buf );
       }
   }
}

/* This routine handles the variables for command expansion.
 * If you want to add any go right ahead, it should be fairly
 * clear how it is done and they are quite easy to do, so you
 * can be as creative as you want. The only catch is to check
 * that your variables exist before you use them. At the moment,
 * using $t when the secondary target refers to an object 
 * i.e. >prog_act drops~<nl>if ispc($t)<nl>sigh<nl>endif<nl>~<nl>
 * probably makes the mud crash (vice versa as well) The cure
 * would be to change act() so that vo becomes vict & v_obj.
 * but this would require a lot of small changes all over the code.
 */
void mprog_translate( char ch, char *t, CHAR_DATA *mob, CHAR_DATA *actor,
                    OBJ_DATA *obj, void *vo, CHAR_DATA *rndm, CHAR_DATA *evil )
{
 static char *he_she        [] = { "it",  "he",  "she" };
 static char *him_her       [] = { "it",  "him", "her" };
 static char *his_her       [] = { "its", "his", "her" };
 CHAR_DATA   *vict             = (CHAR_DATA *) vo;
 OBJ_DATA    *v_obj            = (OBJ_DATA  *) vo;

 *t = '\0';
 switch ( ch ) {
 /*
  * Mob that has the mob prog
  */
     case 'i':
         one_argument( mob->name, t );
      break;

     case 'I':
         strcpy( t, mob->short_descr );
      break;
/*
 * char that triggered the mob prog
 */
     case 'n':
         if ( actor )
         { 
	   if ( can_see( mob,actor ) )
	     one_argument( actor->name, t );
           if ( !IS_NPC( actor ) )
   	     *t = UPPER( *t );
   	 }
   	 else
   	 {
   	     bug( "Mprog_Translate: case 'n', NULL actor" );
   	     strcpy( t, "someone" );
   	 }
      break;

     case 'N':
         if ( actor ) 
            if ( can_see( mob, actor ) )
	       if ( IS_NPC( actor ) )
		 strcpy( t, actor->short_descr );
	       else
	       {
		   strcpy( t, actor->name );
		   strcat( t, " " );
		   strcat( t, actor->pcdata->title );
	       }
	    else
	      strcpy( t, "someone" );
	 break;
     /* 
      * used for victim 
      */
     case 't':
         if ( vict )
         {
	   if ( can_see( mob, vict ) )
	     one_argument( vict->name, t );
           if ( !IS_NPC( vict ) )
	      *t = UPPER( *t );
	 }
	 else
	 {
	     strcpy( t, "someone" );
	 }
	 break;

     case 'T':
         if ( vict ) 
            if ( can_see( mob, vict ) )
	       if ( IS_NPC( vict ) )
		 strcpy( t, vict->short_descr );
	       else
	       {
		 strcpy( t, vict->name );
		 strcat( t, " " );
		 strcat( t, vict->pcdata->title );
	       }
	    else
	      strcpy( t, "someone" );
	 break;
     
     case 'r':
         if ( rndm )
         {
	   if ( can_see( mob, rndm ) )
	     one_argument( rndm->name, t );
           if ( !IS_NPC( rndm ) )
	     *t = UPPER( *t );
	 }
	 else
	   strcpy( t, "someone" );
      break;

     case 'R':
         if ( rndm ) 
            if ( can_see( mob, rndm ) )
	       if ( IS_NPC( rndm ) )
		 strcpy(t,rndm->short_descr);
	       else
	       {
		 strcpy( t, rndm->name );
		 strcat( t, " " );
		 strcat( t, rndm->pcdata->title );
	       }
	    else
	      strcpy( t, "someone" );
	 break;

     case 'x':
         if ( evil )
         {
	   if ( can_see( mob, evil ) )
	     one_argument( evil->name, t );
           if ( !IS_NPC( evil ) )
	     *t = UPPER( *t );
	 }
	 else
	   strcpy( t, "someone" );
      break;

     case 'X':
         if ( evil ) 
            if ( can_see( mob, evil ) )
	       if ( IS_NPC( evil ) )
		 strcpy(t,evil->short_descr);
	       else
	       {
		 strcpy( t, evil->name );
		 strcat( t, " " );
		 strcat( t, evil->pcdata->title );
	       }
	    else
	      strcpy( t, "someone" );
	 break;

     case 'e':
         if ( actor )
	   can_see( mob, actor ) ? strcpy( t, he_she[ actor->sex ] )
	                         : strcpy( t, "someone" );
	 break;
  
     case 'm':
         if ( actor )
	   can_see( mob, actor ) ? strcpy( t, him_her[ actor->sex ] )
                                 : strcpy( t, "someone" );
	 break;
  
     case 's':
         if ( actor )
	   can_see( mob, actor ) ? strcpy( t, his_her[ actor->sex ] )
	                         : strcpy( t, "someone's" );
	 break;
     
     case 'E':
         if ( vict )
	   can_see( mob, vict ) ? strcpy( t, he_she[ vict->sex ] )
                                : strcpy( t, "someone" );
	 break;

     case 'M':
         if ( vict )
	   can_see( mob, vict ) ? strcpy( t, him_her[ vict->sex ] )
                                : strcpy( t, "someone" );
	 break;
  
     case 'S':
         if ( vict )
	   can_see( mob, vict ) ? strcpy( t, his_her[ vict->sex ] )
                                : strcpy( t, "someone's" ); 
	 break;

     case 'j':
	 strcpy( t, he_she[ mob->sex ] );
	 break;
  
     case 'k':
	 strcpy( t, him_her[ mob->sex ] );
	 break;
  
     case 'l':
	 strcpy( t, his_her[ mob->sex ] );
	 break;

     case 'J':
         if ( rndm )
	   can_see( mob, rndm ) ? strcpy( t, he_she[ rndm->sex ] )
	                        : strcpy( t, "someone" );
	 break;
  
     case 'K':
         if ( rndm )
	   can_see( mob, rndm ) ? strcpy( t, him_her[ rndm->sex ] )
                                : strcpy( t, "someone" );
	 break;
  
     case 'L':
         if ( rndm )
	   can_see( mob, rndm ) ? strcpy( t, his_her[ rndm->sex ] )
	                        : strcpy( t, "someone's" );
	 break;

     case 'o':
         if ( obj )
	   can_see_obj( mob, obj ) ? one_argument( obj->name, t )
                                   : strcpy( t, "something" );
	 break;

     case 'O':
         if ( obj )
	   can_see_obj( mob, obj ) ? strcpy( t, obj->short_descr )
                                   : strcpy( t, "something" );
	 break;

     case 'p':
         if ( v_obj )
	   can_see_obj( mob, v_obj ) ? one_argument( v_obj->name, t )
                                     : strcpy( t, "something" );
	 break;

     case 'P':
         if ( v_obj )
	   can_see_obj( mob, v_obj ) ? strcpy( t, v_obj->short_descr )
                                     : strcpy( t, "something" );
      break;

     case 'a':
         if ( obj ) 
          switch ( *( obj->name ) )
	  {
	    case 'a': case 'e': case 'i':
            case 'o': case 'u': strcpy( t, "an" );
	      break;
            default: strcpy( t, "a" );
          }
	 break;

     case 'A':
         if ( v_obj ) 
          switch ( *( v_obj->name ) )
	  {
            case 'a': case 'e': case 'i':
	    case 'o': case 'u': strcpy( t, "an" );
	      break;
            default: strcpy( t, "a" );
          }
	 break;

     case '$':
         strcpy( t, "$" );
	 break;

     default:
         bug( "Mob: %d bad $var", mob->pIndexData->vnum );
	 break;
       }

 return;

}

/* This procedure simply copies the cmnd to a buffer while expanding
 * any variables by calling the translate procedure.  The observant
 * code scrutinizer will notice that this is taken from act()
 */
void mprog_process_cmnd( char *cmnd, CHAR_DATA *mob, CHAR_DATA *actor,
			OBJ_DATA *obj, void *vo, CHAR_DATA *rndm, CHAR_DATA *evil )
{
  char buf[ MAX_INPUT_LENGTH ];
  char tmp[ MAX_INPUT_LENGTH ];
  char *str;
  char *i;
  char *point;

  point   = buf;
  str     = cmnd;

  while ( *str != '\0' )
  {
    if ( *str != '$' )
    {
	    if ( *str == '\r' )
			str++;
		else
			*point++ = *str++;

        continue;
    }
    str++;
    mprog_translate( *str, tmp, mob, actor, obj, vo, rndm, evil );
    i = tmp;
    ++str;
    while ( ( *point = *i ) != '\0' )
      ++point, ++i;
  }
  *point = '\0';
  interpret( mob, buf );

  return;

}

/* The main focus of the MudProgs.  This routine is called 
 *  whenever a trigger is successful.  It is responsible for parsing
 *  the command list and figuring out what to do. However, like all
 *  complex procedures, everything is farmed out to the other guys.
 */
void mprog_driver ( char *com_list, CHAR_DATA *mob, CHAR_DATA *actor,
		   OBJ_DATA *obj, void *vo)
{

 char tmpcmndlst[ MAX_STRING_LENGTH ];
 char buf       [ MAX_INPUT_LENGTH ];
 char *morebuf;
 char *command_list;
 char *cmnd;
 CHAR_DATA *rndm  = NULL;
 CHAR_DATA *vch   = NULL;
 CHAR_DATA *evil  = NULL;
 int        count = 0;
 int		max_evil = 999999;

 if ( !mob )
 {
     bug( "MPDriver:  NULL mob!" );
     return;
 }
      
 if IS_AFFECTED( mob, AFF_CHARM )
   return;

 /* get a random visable mortal player who is in the room with the mob */
 for ( vch = mob->in_room->people; vch; vch = vch->next_in_room )
   if ( !IS_NPC( vch )
       &&  can_see( mob, vch ) )
     {
       if ( number_range( 0, count ) == 0 )
	 rndm = vch;
       count++;
     }
  
 /* get the most evil visable mortal player who is in the room with the mob and is fighting */
 for ( vch = mob->in_room->people; vch; vch = vch->next_in_room )
   if ( !IS_NPC( vch )
       &&  can_see( mob, vch ) )
     {
	   if ( vch->fighting && vch->alignment < max_evil )
	   {
		   max_evil = vch->alignment;
		   evil = vch;
	   }
     }
  
 strcpy( tmpcmndlst, com_list );
 command_list = tmpcmndlst;
 cmnd         = command_list;
 command_list = mprog_next_command( command_list );
 while ( cmnd && *cmnd )
 {
     morebuf = one_argument( cmnd, buf );
     if ( !str_cmp( buf, "if" ) )
       command_list = mprog_process_if( morebuf, command_list, mob,
				       actor, obj, vo, rndm, evil );
     else
       mprog_process_cmnd( cmnd, mob, actor, obj, vo, rndm, evil );
       
     cmnd         = command_list;
     command_list = mprog_next_command( command_list );
 }

 return;

}

/***************************************************************************
 * Global function code and brief comments.
 */

/* The next two routines are the basic trigger types. Either trigger
 *  on a certain percent, or trigger on a keyword or word phrase.
 *  To see how this works, look at the various trigger routines..
 */
void mprog_wordlist_check( char *arg, void *source, CHAR_DATA *actor,
			  OBJ_DATA *obj, void *vo, int trigger_type, int prog_type )
{
  CHAR_DATA       *pMob = NULL;
  OBJ_DATA	      *pObj = NULL;
  ROOM_INDEX_DATA *pRoom = NULL;
  char			  temp1[ MAX_STRING_LENGTH ];
  char			  temp2[ MAX_INPUT_LENGTH ];
  char			  word[ MAX_INPUT_LENGTH ];
  MPROG_DATA	  *mprg;
  MPROG_LIST	  *pProgList = NULL;
  char			  *list;
  char			  *start;
  char			  *dupl;
  char			  *end;
  unsigned int    i;

  switch(prog_type)
  {
  case MOB_PROG:
	  pMob = (CHAR_DATA *) source;
	  pProgList = pMob->pIndexData->mudprogs;
	  break;
  case OBJ_PROG:
	  pObj = (OBJ_DATA *) source;
	  pMob = supermob;
	  pProgList = pObj->pIndexData->mudprogs;
	  break;
  case ROOM_PROG:
	  pRoom = (ROOM_INDEX_DATA *) source;
	  pMob = supermob;
	  pProgList = pRoom->mudprogs;
	  break;
  default:
	  break;
  }

  for ( ; pProgList; pProgList = pProgList->next )
    if ( pProgList->mudprog->trigger_type & trigger_type )
    {
		mprg = pProgList->mudprog;

		strcpy( temp1, mprg->arglist );
		list = temp1;

		for ( i = 0; i < strlen( list ); i++ )
			list[i] = LOWER( list[i] );

		strcpy( temp2, arg );
		dupl = remove_color(temp2);

		for ( i = 0; i < strlen( dupl ); i++ )
			dupl[i] = LOWER( dupl[i] );

		if ( ( list[0] == 'p' ) && ( list[1] == ' ' ) )
		{
			list += 2;
			while ( ( start = strstr( dupl, list ) ) )
				if ( (start == dupl || *(start-1) == ' ' )
				  && ( *(end = start + strlen( list ) ) == ' '
				  || *end == '\n'
				  || *end == '\r'
				  || *end == '\0' ) )
				{
					if ( pMob == supermob )
						set_supermob( source, prog_type );

					mprog_driver( mprg->comlist, pMob, actor, obj, vo );

					if ( pMob == supermob )
						release_supermob();

					break;
				}
				else
					dupl = start+1;
		}
		else
		{
			list = one_argument( list, word );
			for( ; word[0] != '\0'; list = one_argument( list, word ) )
				while ( ( start = strstr( dupl, word ) ) )
					if ( ( start == dupl || *(start-1) == ' ' )
					  && ( *(end = start + strlen( word ) ) == ' '
					  || *end == '\n'
				      || *end == '\r'
					  || *end == '\0' ) )
					{
						if ( pMob == supermob )
							set_supermob( source, prog_type );

						mprog_driver( mprg->comlist, pMob, actor, obj, vo );

						if ( pMob == supermob )
							release_supermob();

						break;
					}
				else
					dupl = start+1;
		}
  }

  return;
}

bool mprog_percent_check( CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj,
			 void *vo, int trigger_type, int prog_type)
{
	MPROG_LIST *pProgList;
	bool executed = FALSE;

	switch(prog_type)
	{
	case MOB_PROG:
		for ( pProgList = mob->pIndexData->mudprogs; pProgList; 
		  pProgList = pProgList->next )
			if ( ( pProgList->mudprog->trigger_type & trigger_type ) 
			  && ( number_percent( ) < atoi( pProgList->mudprog->arglist ) ) )
			{
				executed = TRUE;
				mprog_driver( pProgList->mudprog->comlist, mob, actor, obj, vo );
				if ( trigger_type != GREET_PROG && trigger_type != ALL_GREET_PROG )
					break;
			}
		break;
	case OBJ_PROG:
		for ( pProgList = obj->pIndexData->mudprogs; pProgList; 
		  pProgList = pProgList->next )
			if ( ( pProgList->mudprog->trigger_type & trigger_type )
			  && ( number_percent( ) <= atoi( pProgList->mudprog->arglist ) ) )
			{
				executed = TRUE;
				mprog_driver( pProgList->mudprog->comlist, mob, actor, obj, vo );
				if ( trigger_type != GREET_PROG )
					break;
			}
		break;
	case ROOM_PROG:
		for ( pProgList = mob->in_room->mudprogs; pProgList;
		  pProgList = pProgList->next )
			if ( ( pProgList->mudprog->trigger_type & trigger_type )
			  && ( number_percent( ) <= atoi( pProgList->mudprog->arglist ) ) )
			{
				executed = TRUE;
				mprog_driver( pProgList->mudprog->comlist, mob, actor, obj, vo );
				if(trigger_type != ENTER_PROG)
					break;
			}
		break;
	default:
		executed = FALSE;
		break;
	}

	return executed;
}

/* The triggers.. These are really basic, and since most appear only
 * once in the code (hmm. i think they all do) it would be more efficient
 * to substitute the code in and make the mprog_xxx_check routines global.
 * However, they are all here in one nice place at the moment to make it
 * easier to see what they look like. If you do substitute them back in,
 * make sure you remember to modify the variable names to the ones in the
 * trigger calls.
 */
void mprog_act_trigger( char *buf, CHAR_DATA *mob, CHAR_DATA *ch,
		       OBJ_DATA *obj, void *vo)
{
  MPROG_ACT_LIST * tmp_act;
  MPROG_LIST *pProgList;
  bool found = FALSE;
  
  if ( IS_NPC( mob )
       && IS_SET( mob->pIndexData->progtypes, ACT_PROG ) )
  {
        if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
           return;
        
        for ( pProgList = mob->pIndexData->mudprogs; pProgList; pProgList = pProgList->next )
            if ( pProgList->mudprog->trigger_type & ACT_PROG )
            {
                found = TRUE;
                break;
            }

        if ( !found )
           return;
           
        tmp_act = alloc_mem( sizeof( MPROG_ACT_LIST ) );
        if ( mob->mpactnum > 0 )
	  tmp_act->next = mob->mpact;
        else
	  tmp_act->next = NULL;

        mob->mpact      = tmp_act;
        mob->mpact->buf = str_dup( buf );
        mob->mpact->ch  = ch; 
        mob->mpact->obj = obj; 
        mob->mpact->vo  = vo; 
        mob->mpactnum++;
  }
  return;
}

void mprog_bribe_trigger( CHAR_DATA *mob, CHAR_DATA *ch, int amount )
{
  char        buf[ MAX_STRING_LENGTH ];
  MPROG_LIST *pList;
  OBJ_DATA   *obj;

  if ( IS_NPC( mob )
      && ( mob->pIndexData->progtypes & BRIBE_PROG ) )
  {
      if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
         return;
      obj = create_object( get_obj_index( OBJ_VNUM_MONEY_SOME ), 0 );
      sprintf( buf, obj->short_descr, amount );
      free_string( obj->short_descr );
      obj->short_descr = str_dup( buf );
      obj->value[0]    = amount;
      obj_to_char( obj, mob );
      mob->gold -= amount;

      for ( pList = mob->pIndexData->mudprogs; pList; pList = pList->next )
		if ( ( pList->mudprog->trigger_type & BRIBE_PROG )
	      && ( amount >= atoi( pList->mudprog->arglist ) ) )
		{
			mprog_driver( pList->mudprog->comlist, mob, ch, obj, NULL );
			break;
		}
  }
  
  return;
}

void mprog_death_trigger( CHAR_DATA *mob )
{

   if ( IS_NPC( mob )
     && ( mob->pIndexData->progtypes & DEATH_PROG ) )
   {
        mob->position = POS_RESTING;
        mprog_percent_check( mob, NULL, NULL, NULL, DEATH_PROG, MOB_PROG );
        mob->position = POS_DEAD;
   }
   else
   {
	death_cry( mob );
   }
 return;

}

void mprog_entry_trigger( CHAR_DATA *mob )
{

 if ( IS_NPC( mob )
     && ( mob->pIndexData->progtypes & ENTRY_PROG ) )
   mprog_percent_check( mob, NULL, NULL, NULL, ENTRY_PROG, MOB_PROG );

 return;

}

void mprog_fight_trigger( CHAR_DATA *mob, CHAR_DATA *ch )
{

     if ( IS_NPC( mob )
     && ( mob->pIndexData->progtypes & FIGHT_PROG ) )
     {
         if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
            return;
         mprog_percent_check( mob, ch, NULL, NULL, FIGHT_PROG, MOB_PROG );
     }

 return;

}

void mprog_fightroom_trigger( CHAR_DATA *mob )
{
	CHAR_DATA *victim;

	if ( !mob || !mob->in_room )
		return;

    if ( IS_NPC( mob )
      && ( mob->pIndexData->progtypes & FIGHTROOM_PROG ) )
    {
		for ( victim = mob->in_room->people; victim; victim = victim->next_in_room )
		{
			if ( victim != mob && victim->fighting == mob
			  && mprog_percent_check( mob, victim, NULL, NULL, FIGHTROOM_PROG, MOB_PROG ) )
				break;
		}
    }

 return;

}

void mprog_give_trigger( CHAR_DATA *mob, CHAR_DATA *ch, OBJ_DATA *obj )
{
 char        buf[MAX_INPUT_LENGTH];
 MPROG_LIST *pList;

 if ( IS_NPC( mob )
     && ( mob->pIndexData->progtypes & GIVE_PROG ) )
 {
     if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
            return;
            
   for ( pList = mob->pIndexData->mudprogs; pList; pList = pList->next )
   {
         one_argument( pList->mudprog->arglist, buf );
         if ( ( pList->mudprog->trigger_type & GIVE_PROG )
	     && ( ( !str_cmp( obj->name, pList->mudprog->arglist ) )
	       || ( !str_cmp( "all", buf ) ) ) )
		 {
			 mprog_driver( pList->mudprog->comlist, mob, ch, obj, NULL );
			 break;
		 }
   }
 }
 
 return;
}

void mprog_greet_trigger( CHAR_DATA *ch )
{
 CHAR_DATA *vmob;

 if ( IS_NPC( ch ) )
     return;
       
 for ( vmob = ch->in_room->people; vmob; vmob = vmob->next_in_room )
   if ( IS_NPC( vmob )
       && ch != vmob
       && can_see( vmob, ch )
       && ( !vmob->fighting )
       && IS_AWAKE( vmob )
       && ( vmob->pIndexData->progtypes & GREET_PROG) )
     mprog_percent_check( vmob, ch, NULL, NULL, GREET_PROG, MOB_PROG );
   else if ( IS_NPC( vmob )
	 && ( !vmob->fighting )
	 && IS_AWAKE( vmob )
	 && ( vmob->pIndexData->progtypes & ALL_GREET_PROG ) )
       mprog_percent_check(vmob,ch,NULL,NULL,ALL_GREET_PROG, MOB_PROG );

 return;
}

void mprog_hitprcnt_trigger( CHAR_DATA *mob, CHAR_DATA *ch)
{
 MPROG_LIST *pList;

 if ( IS_NPC( mob )
     && ( mob->pIndexData->progtypes & HITPRCNT_PROG ) )
 {
   if ( IS_NPC( ch ) && ch->pIndexData == mob->pIndexData )
       return;
       
   for ( pList = mob->pIndexData->mudprogs; pList; pList = pList->next )
     if ( ( pList->mudprog->trigger_type & HITPRCNT_PROG )
	 && ( ( 100*mob->hit / mob->max_hit ) < atoi( pList->mudprog->arglist ) ) )
       {
	 mprog_driver( pList->mudprog->comlist, mob, ch, NULL, NULL );
	 break;
       }
 }
 
 return;
}

void mprog_random_trigger( CHAR_DATA *mob )
{
  if ( mob->pIndexData->progtypes & RAND_PROG)
    mprog_percent_check(mob,NULL,NULL,NULL,RAND_PROG, MOB_PROG);

  return;
}

void mprog_speech_trigger( char *txt, CHAR_DATA *actor )
{

  CHAR_DATA *vmob;

  for ( vmob = actor->in_room->people; vmob; vmob = vmob->next_in_room )
    if ( IS_NPC( vmob ) && ( vmob->pIndexData->progtypes & SPEECH_PROG ) )
    {
        if ( IS_NPC( actor ) && ( vmob->pIndexData == actor->pIndexData ) )
            continue;

        mprog_wordlist_check( txt, vmob, actor, NULL, NULL, SPEECH_PROG, MOB_PROG );
    }

  return;
}

/* Written by Zak, Jan 13/1998
 * Goes in interpret() before regular command parsing.
 * This function checks all mobs in room with the character for a command
 * trigger matching what the character typed.
 * The function returns TRUE if the character's command should be run
 * through the regular interpreter too. */
bool mprog_command_trigger (char *txt, CHAR_DATA *ch)
{
   char *argument;
   char arg [MAX_INPUT_LENGTH];/* I'm assuming that the cmd_table won't
				 * ever have a command longer than
				 * MAX_INPUT_LENGTH                     */
   CHAR_DATA  *vmob;
   OBJ_DATA   *obj;
   ROOM_INDEX_DATA  *room;
   MPROG_LIST *pList;
   int cmd;
   bool can_do = TRUE;

   argument = strdup(txt);

   /* First check for the command typed being a prefix of anything in 
    * the regular command table, and expand it to the full command. */
  
   argument = one_argument( argument, arg );
   for (cmd=0; cmd_table[cmd].name[0] != '\0'; cmd++)
     {
	if (arg[0] == cmd_table[cmd].name[0] &&
	    !str_prefix( arg, cmd_table[cmd].name ) )
	  {
	     strncpy(arg,cmd_table[cmd].name,sizeof(arg));
	     break;
	  }
     }
   
   /* Find mobs that are in_room that have a COMMAND_PROG */
   
   for ( vmob = ch->in_room->people; vmob; vmob = vmob->next_in_room )
     if ( IS_NPC( vmob ) && ( vmob->pIndexData->progtypes & COMMAND_PROG ) )
     {
	for ( pList = vmob->pIndexData->mudprogs; pList; pList = pList->next )
	  {
	     if ( ( pList->mudprog->trigger_type & COMMAND_PROG ) &&
		  (!str_cmp(pList->mudprog->arglist,arg)) )
	       {
		  mprog_driver( pList->mudprog->comlist, vmob, ch, NULL, NULL );
		  can_do = FALSE;
	       }
	  }
     }

   /* Obj and Room command_prog support by Kyle Boyd */

   /* objs in inventory and worn... */
   for ( obj = ch->carrying; obj; obj = obj->next_content )
     if ( obj->pIndexData->progtypes & COMMAND_PROG )
     {
	for ( pList = obj->pIndexData->mudprogs; pList; pList = pList->next )
	  {
	     if ( (pList->mudprog->trigger_type & COMMAND_PROG) &&
		 (!str_cmp(pList->mudprog->arglist,arg)) )
	       {
		  set_supermob( obj, OBJ_PROG );
		  mprog_driver( pList->mudprog->comlist, supermob, ch, obj, NULL );
		  release_supermob();
		  can_do = FALSE;
	       }
	  }
     }

   /* objs in room... */

   for ( obj = ch->in_room->contents; obj; obj = obj->next_content )
     if ( obj->pIndexData->progtypes & COMMAND_PROG )
     {
	for ( pList = vmob->pIndexData->mudprogs; pList; pList = pList->next)
	  {
	     if ( (pList->mudprog->trigger_type & COMMAND_PROG) &&
		 (!str_cmp(pList->mudprog->arglist,arg)) )
	       {
		  set_supermob( obj, OBJ_PROG );
		  mprog_driver( pList->mudprog->comlist, supermob, ch, obj, NULL );
		  release_supermob();
		  can_do = FALSE;
	       }
	  }
     }

   /* And finally, room progs */

   room = ch->in_room;
   if ( room->progtypes & COMMAND_PROG )
     {
	for ( pList = room->mudprogs; pList; pList = pList->next)
	  {
	     if ( (pList->mudprog->trigger_type & COMMAND_PROG) &&
		 (!str_cmp(pList->mudprog->arglist,arg)) )
	       {
		  set_supermob( room, ROOM_PROG );
		  mprog_driver( pList->mudprog->comlist, supermob, ch, NULL, NULL );
		  release_supermob();
		  can_do = FALSE;
	       }
	  }
     }
   return can_do;
}

/*****************************************************************
 *   ROOM PROG SUPPORT STARTS HERE:                              *
 *          most of this code was taken from the SMAUG code base *
 *          with modifications made to fit our mud...            *
 *****************************************************************/

 void init_supermob( )
{
   supermob = create_mobile( get_mob_index(MOB_VNUM_SUPERMOB) );
   char_to_room( supermob, get_room_index(ROOM_VNUM_SUPERMOB) );

   return;
}

void set_supermob( void *source, int prog_type )
{
  OBJ_DATA  *pObj = NULL;
  ROOM_INDEX_DATA *pRoom = NULL;
  OBJ_DATA *in_obj = NULL;
  char buf[200];

  if ( !supermob )
  {
    supermob = create_mobile(get_mob_index( MOB_VNUM_SUPERMOB ));
	char_to_room( supermob, get_room_index(ROOM_VNUM_SUPERMOB) );
  }

  if(!source)
     return;

  switch(prog_type)
  {
  case OBJ_PROG:
	  pObj = (OBJ_DATA *) source;

	  for ( in_obj = pObj; in_obj->in_obj; in_obj = in_obj->in_obj )
		;

	  if ( in_obj->carried_by )
		  pRoom = in_obj->carried_by->in_room;
	  else
		  pRoom = pObj->in_room;

	  if( !pRoom )
		 return;

	  if (supermob->short_descr)
		 free_string(supermob->short_descr);

	  supermob->short_descr = str_dup(pObj->short_descr);

	  /* Added by Jenny to allow bug messages to show the vnum
		 of the object, and not just supermob's vnum */
	  sprintf( buf, "Object #%d", pObj->pIndexData->vnum );
	  free_string( supermob->description );
	  supermob->description = str_dup( buf );
	  break;
  case ROOM_PROG:
	  pRoom = (ROOM_INDEX_DATA *) source;

      if ( supermob->short_descr )
    	  free_string(supermob->short_descr);
      supermob->short_descr = str_dup(pRoom->name);

      if ( supermob->name )
    	  free_string(supermob->name);
      supermob->name        = str_dup(pRoom->name);

      /* Added by Jenny to allow bug messages to show the vnum
         of the room, and not just supermob's vnum */
      sprintf( buf, "Room #%d", pRoom->vnum );
	  if ( supermob->description )
		free_string( supermob->description );
      supermob->description = str_dup( buf );
	  break;
  }

  char_from_room (supermob );
  char_to_room( supermob, pRoom); 
  
  return;
}

void release_supermob( )
{
  char_from_room( supermob );
  if ( supermob->name )
     free_string( supermob->name );
  supermob->name = str_dup("SuperMob");
  char_to_room( supermob, get_room_index( ROOM_VNUM_SUPERMOB ) );
}

/*
 * Triggers follow
 */

void rprog_act_trigger( char *buf, ROOM_INDEX_DATA *room, CHAR_DATA *ch,
			OBJ_DATA *obj, void *vo )
{
   if ( room->progtypes & ACT_PROG ) 
   {
      MPROG_ACT_LIST *tmp_act;
      
      /* supermob can't trigger it's own mprog */
      if ( IS_NPC(ch) && ch->pIndexData == supermob->pIndexData )
         return;
         
      tmp_act = alloc_mem( sizeof( MPROG_ACT_LIST ) );
      if ( room->mpactnum > 0 )
        tmp_act->next = room->mpact;
      else
        tmp_act->next = NULL;
      
      room->mpact = tmp_act;
      room->mpact->buf = str_dup(buf);
      room->mpact->ch = ch;
      room->mpact->obj = obj;
      room->mpact->vo = vo;
      room->mpactnum++;
      room_act_add(room);
   }
   return;
}
/*
 *
 */
void rprog_leave_trigger( CHAR_DATA *ch )
{
  if( ch->in_room && ch->in_room->progtypes & LEAVE_PROG ) 
  {
    set_supermob( ch->in_room, ROOM_PROG );
    mprog_percent_check( supermob, ch, NULL, NULL, LEAVE_PROG, ROOM_PROG );
    release_supermob();
  }
  return;
}

void rprog_enter_trigger( CHAR_DATA *ch )
{
  if( ch->in_room && ch->in_room->progtypes & ENTER_PROG ) 
  {
    set_supermob( ch->in_room, ROOM_PROG );
    mprog_percent_check( supermob, ch, NULL, NULL, ENTRY_PROG, ROOM_PROG );
    release_supermob();
  }
  return;
}

void rprog_sleep_trigger( CHAR_DATA *ch )
{
  if( ch->in_room && ch->in_room->progtypes & SLEEP_PROG ) 
  {
    set_supermob( ch->in_room, ROOM_PROG );
    mprog_percent_check( supermob, ch, NULL, NULL, SLEEP_PROG, ROOM_PROG );
    release_supermob();
  }
  return;
}

void rprog_rest_trigger( CHAR_DATA *ch )
{
  if( ch->in_room && ch->in_room->progtypes & REST_PROG ) 
  {
    set_supermob( ch->in_room, ROOM_PROG );
    mprog_percent_check( supermob, ch, NULL, NULL, REST_PROG, ROOM_PROG );
    release_supermob();
  }
  return;
}

void rprog_rfight_trigger( CHAR_DATA *ch )
{
  if( ch->in_room && ch->in_room->progtypes & RFIGHT_PROG ) 
  {
    set_supermob( ch->in_room, ROOM_PROG );
    mprog_percent_check( supermob, ch, NULL, NULL, RFIGHT_PROG, ROOM_PROG );
    release_supermob();
  }
  return;
}

void rprog_death_trigger( CHAR_DATA *ch )
{
  if( ch->in_room && ch->in_room->progtypes & RDEATH_PROG ) 
  {
    set_supermob( ch->in_room, ROOM_PROG );
    mprog_percent_check( supermob, ch, NULL, NULL, RDEATH_PROG, ROOM_PROG );
    release_supermob();
  }
  return;
}

void rprog_speech_trigger( char *txt, CHAR_DATA *ch )
{
  /* prevent circular triggers by not allowing mob to trigger itself */
  if ( IS_NPC(ch) && ch->pIndexData == supermob->pIndexData )
     return;
     
  if( ch->in_room && ch->in_room->progtypes & SPEECH_PROG ) 
  {
    /* supermob is set and released in mprog_wordlist_check */
    mprog_wordlist_check( txt, ch->in_room, ch, NULL, NULL, SPEECH_PROG, ROOM_PROG );
  }
 return;
}

void rprog_random_trigger( CHAR_DATA *ch )
{

  if ( ch->in_room && ch->in_room->progtypes & RAND_PROG)
  {
    set_supermob( ch->in_room, ROOM_PROG );
    mprog_percent_check(supermob,ch,NULL,NULL,RAND_PROG, ROOM_PROG);
    release_supermob();
  }
  return;
}

/* Written by Jenny, Nov 29/95 */
void progbug( char *str, CHAR_DATA *mob )
{

  /* Check if we're dealing with supermob, which means the bug occurred
     in a room or obj prog. */
  if ( mob->pIndexData->vnum == MOB_VNUM_SUPERMOB )
  {
    /* It's supermob.  In set_supermob the description
       was set to indicate the object or room, so we just need to show
       the description in the bug message. */
    bug( "%s, %s.", str, 
             !mob->description ? "(unknown)" : mob->description );
  }
  else
  {
    bug( "%s, Mob #%d.", str, mob->pIndexData->vnum );
  }
  return;
}


/* Room act prog updates.  Use a separate list cuz we dont really wanna go
   thru 5-10000 rooms every pulse.. can we say lag? -- Alty */

void room_act_add( ROOM_INDEX_DATA *room )
{
    struct act_prog_data *runner;
  
    for ( runner = room_act_list; runner; runner = runner->next )
	if ( runner->vo == room )
	   return;

    runner = alloc_mem( sizeof(*runner) );
    runner->vo = room;
    runner->next = room_act_list;
    room_act_list = runner;
}


void room_act_update( void )
{
  struct act_prog_data *runner;
  MPROG_ACT_LIST *mpact;
  
  while ( (runner = room_act_list) )
  {
    ROOM_INDEX_DATA *room = runner->vo;
    
    while ( (mpact = room->mpact) )
    {
      if ( mpact->ch->in_room == room )
        mprog_wordlist_check(mpact->buf, room, mpact->ch, mpact->obj,
                             mpact->vo, ACT_PROG, ROOM_PROG);
      room->mpact = mpact->next;
      free_string( mpact->buf );
      free_mem( mpact, sizeof(*mpact) );
    }
    room->mpact = NULL;
    room->mpactnum = 0;
    room_act_list = runner->next;
    free_mem( runner, sizeof(*runner) );
  }
  return;
}

/*****************************************************************
 *   OBJECT PROG SUPPORT STARTS HERE:				             *
 *          most of this code was taken from the SMAUG code base *
 *          with modifications made to fit our mud...            *
 *****************************************************************/

/*
 * Triggers follow
 */
void oprog_greet_trigger( CHAR_DATA *ch )
{
  OBJ_DATA *vobj;

  for ( vobj=ch->in_room->contents; vobj; vobj = vobj->next_content )
    if  ( vobj->pIndexData->progtypes & GREET_PROG ) 
    {
     set_supermob( vobj, OBJ_PROG );  /* not very efficient to do here */
     mprog_percent_check( supermob, ch, vobj, NULL, GREET_PROG, OBJ_PROG );
     release_supermob();
    }

  return;
}

void oprog_speech_trigger( char *txt, CHAR_DATA *ch )
{
   OBJ_DATA *vobj;

  /* supermob is set and released in mprog_wordlist_check */
  for ( vobj=ch->in_room->contents; vobj; vobj = vobj->next_content )
    if  ( vobj->pIndexData->progtypes & SPEECH_PROG ) 
    {
      mprog_wordlist_check( txt, vobj, ch, vobj, NULL, SPEECH_PROG, OBJ_PROG );
    }

 return;
}

/*
 * Called at top of obj_update
 * make sure to put an if(!obj) continue
 * after it
 */
void oprog_random_trigger( OBJ_DATA *obj )
{

  if ( obj->pIndexData->progtypes & RAND_PROG)
  {
     set_supermob( obj, OBJ_PROG );
     mprog_percent_check(supermob,NULL,obj,NULL,RAND_PROG, OBJ_PROG);
     release_supermob();
  }
  return;
}

/*
 * in wear_obj, between each successful equip_char 
 * the subsequent return
 */
void oprog_wear_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & WEAR_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, WEAR_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}

bool oprog_use_trigger( CHAR_DATA *ch, OBJ_DATA *obj, CHAR_DATA *vict,
                        OBJ_DATA *targ, void *vo )
{
   bool executed = FALSE;

   if ( obj->pIndexData->progtypes & USE_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      if ( obj->item_type == ITEM_STAFF )
      {
        if ( vict )
          executed = mprog_percent_check( supermob, ch, obj, vict, USE_PROG, OBJ_PROG );
        else
          executed = mprog_percent_check( supermob, ch, obj, targ, USE_PROG, OBJ_PROG );
      }
      else
      {
        executed = mprog_percent_check( supermob, ch, obj, NULL, USE_PROG, OBJ_PROG );
      }
      release_supermob();
   }
   return executed;
}

/*
 * call in remove_obj, right after unequip_char   
 * do a if(!ch) return right after, and return TRUE (?)
 * if !ch
 */
void oprog_remove_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & REMOVE_PROG ) 
   {
     set_supermob( obj, OBJ_PROG );
     mprog_percent_check( supermob, ch, obj, NULL, REMOVE_PROG, OBJ_PROG );
     release_supermob();
   }
   return;
}


/*
 * call in do_sac, right before extract_obj
 */
void oprog_sac_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & SAC_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, SAC_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}

/*
 * call in do_get, right before check_for_trap
 * do a if(!ch) return right after
 */
void oprog_get_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & GET_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, GET_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}

/*
 * called in damage_obj in act_obj.c
 */
void oprog_damage_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & DAMAGE_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, DAMAGE_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}

/*
 * called in do_repair in shops.c
 */
void oprog_repair_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{

   if ( obj->pIndexData->progtypes & REPAIR_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, REPAIR_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}

/*
 * call twice in do_drop, right after the act( AT_ACTION,...)
 * do a if(!ch) return right after
 */
void oprog_drop_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & DROP_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, DROP_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}

/*
 * call towards end of do_examine, right before check_for_trap
 */
void oprog_examine_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & EXA_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, EXA_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}


/*
 * call in fight.c, group_gain, after (?) the obj_to_room
 */
void oprog_zap_trigger( CHAR_DATA *ch, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & ZAP_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, NULL, ZAP_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}

void obj_act_add( OBJ_DATA *obj );
void oprog_act_trigger( char *buf, OBJ_DATA *mobj, CHAR_DATA *ch,
			OBJ_DATA *obj, void *vo )
{
   if ( IS_NPC(ch) && ch->pIndexData == supermob->pIndexData )
      return;   /* prevent supermob from triggering itself */
      
   if ( mobj->pIndexData->progtypes & ACT_PROG ) 
   {
      MPROG_ACT_LIST *tmp_act;
      
      tmp_act = alloc_mem( sizeof(MPROG_ACT_LIST) );
      if ( mobj->mpactnum > 0 )
        tmp_act->next = mobj->mpact;
      else
        tmp_act->next = NULL;
      
      mobj->mpact = tmp_act;
      mobj->mpact->buf = str_dup(buf);
      mobj->mpact->ch = ch;
      mobj->mpact->obj = obj;
      mobj->mpact->vo = vo;
      mobj->mpactnum++;
      obj_act_add(mobj);
   }
   return;
}

void obj_act_add( OBJ_DATA *obj )
{
  struct act_prog_data *runner;

  for ( runner = obj_act_list; runner; runner = runner->next )
    if ( runner->vo == obj )
      return;

  runner = alloc_mem( sizeof(*runner) );
  runner->vo = obj;
  runner->next = obj_act_list;
  obj_act_list = runner;
}

void obj_act_update( void )
{
  struct act_prog_data *runner;
  MPROG_ACT_LIST *mpact;

  while ( (runner = obj_act_list) != NULL )
  {
    OBJ_DATA *obj = runner->vo;
    
    while ( (mpact = obj->mpact) != NULL )
    {
      mprog_wordlist_check(mpact->buf, obj, mpact->ch, mpact->obj,
                           mpact->vo, ACT_PROG, OBJ_PROG);
      obj->mpact = mpact->next;
      free_string(mpact->buf);
      free_mem(mpact, sizeof(*mpact) );
    }
    obj->mpact = NULL;
    obj->mpactnum = 0;
    obj_act_list = runner->next;
    free_mem(runner, sizeof(*runner));
  }
  return;
}

/*
 * call in fight.c, one_hit and second_one_hit at the end.
 */
void oprog_hit_trigger( CHAR_DATA *ch, CHAR_DATA *victim, OBJ_DATA *obj )
{
   if ( obj->pIndexData->progtypes & HIT_PROG ) 
   {
      set_supermob( obj, OBJ_PROG );
      mprog_percent_check( supermob, ch, obj, victim, HIT_PROG, OBJ_PROG );
      release_supermob();
   }
   return;
}