The effects of this snippet:

You gain the ability to set 5 variables from within mudprogs for objects, characters,
mobiles, and rooms. Though the rooms aspect of which has not been entirely developed.
In parse_setvar and in the setvar part of mprog_do_command a new letter case 'g' in the 
switch function was added, for parsing and setting of the room variables.

syntax: setvar $n/$t/$i/$o/$p/$g # <variable string/int>
The ability to parse/compare variables with rval such as:
if name($n) == $i

The ability to create/use pointers anywhere in a prog.
Example:
say hi $n, I see you're a $n.race $n.class.
say Wow you're even level $n.level!

etc.


in mud.h the typical

typedef struct variable_data		VARIABLE_DATA;

struct	variable_data
{
    char *	v1;
    char *	v2;
    char *	v3;
    char *	v4;
    char *	v5;
};

inside struct room_index_data, struct obj_data, and struct char_data add
   VARIABLE_DATA * variable;

inside 

int mprog_do_ifcheck( char *ifcheck, CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void *vo, CHAR_DATA *rndm )


After:
    if ( cvar[0] == '$' )
    {
	switch(cvar[1])
	{

Add in:
	    case '1':	chkchar = actor;		break;
	    case '2':	chkchar = actor;		break;
	    case '3':	chkchar = actor;		break;
	    case '4':	chkchar = actor;		break;
	    case '5':	chkchar = actor;		break;

in mprog_do_command after:

  if ( !str_cmp( firstword, "break" ) )
    return BERR;

add in:

  cmnd = parse_setvar( cmnd, mob, actor, obj, vo, rndm );

  /* This chunk of code taken from mprog_process_cmnd. */
  while ( *str != '\0' )
  {
    if ( *str != '$' )
    {
      *point++ = *str++;
      continue;
    }
    str++;
    mprog_translate( *str, tmp, mob, actor, obj, vo, rndm );
    i = tmp;
    ++str;
    while ( ( *point = *i ) != '\0' )
      ++point, ++i;
  }
  *point = '\0';

/* This is where to add in the check for "setvar" */
  if ( !str_cmp( firstword, "setvar" ) )
  {
    CHAR_DATA *chkchar = NULL;
    OBJ_DATA *chkobj = NULL;
    ROOM_INDEX_DATA *chkroom = NULL;
    sh_int var, type = -1;
    char arg[MAX_STRING_LENGTH], arg2[MAX_STRING_LENGTH];

    /* does not make it past this point, explore why */
    /* does now - Richard */
    cmnd = one_argument( cmnd, arg );
    cmnd = one_argument( cmnd, arg );
    cmnd = one_argument( cmnd, arg2 );
    var = atoi(arg2);

    if ( arg[0] == '$' )
    {
        switch(arg[1])
        {
            case 'i':   chkchar = mob;      type = 1;            break;
            case 'n':   chkchar = actor;    type = 1;
                        if ( !chkchar )
                        {
                            if ( obj && obj->carried_by )
                                chkchar = obj->carried_by;
                        }
                                                        break;
            case 't':
            case 'a':   chkchar = (CHAR_DATA *)vo;      type = 1; break;
            case 'r':   chkchar = rndm;                 type = 1; break;
            case 'o':   chkobj = obj;                   type = 2; break;
            case 'p':   chkobj = (OBJ_DATA *)vo;        type = 2; break;
            case 'g':   chkroom = obj ? (obj->carried_by ? obj->carried_by->in_room : NULL) : mob ? mob->in_room :
                                        (actor ? actor->in_room : NULL); break;
            default:
                progbug(format("Bad argument '%c' to '%s'", arg[0], chck), mob);
                return BERR;
        }

        if ( !chkchar && !chkobj && !chkroom )
            return BERR;

        if ( chkroom )
            type = 0;
        if ( chkchar )
            type = 1;
        if ( chkobj )
            type = 2;

        switch(type)
        {
           case 0:
              switch(var)
              {
                 default:
                    progbug( format( "Unknown setvar %s", cmnd ), mob );
                    return BERR;
                 case 1:
                    stralloc_printf( &chkroom->variable->v1, "%s", cmnd);
                    break;
                 case 2:
                    stralloc_printf( &chkroom->variable->v2, "%s", cmnd);
                    break;
                 case 3:
                    stralloc_printf( &chkroom->variable->v3, "%s", cmnd);
                    break;
                 case 4:
                    stralloc_printf( &chkroom->variable->v4, "%s", cmnd);
                    break;
                 case 5:
                    stralloc_printf( &chkroom->variable->v5, "%s", cmnd);
                    break;
             }
             break;
           case 1:
              switch(var)
              {
                 default:
                    progbug( format( "Unknown setvar %s", buf ), mob );
                    return BERR;
                 case 1:
                    stralloc_printf( &chkchar->variable->v1, "%s", cmnd);
                    break;
                 case 2:
                    stralloc_printf( &chkchar->variable->v2, "%s", cmnd);
                    break;
                 case 3:
                    stralloc_printf( &chkchar->variable->v3, "%s", cmnd);
                    break;
                 case 4:
                    stralloc_printf( &chkchar->variable->v4, "%s", cmnd);
                    break;
                 case 5:
                    stralloc_printf( &chkchar->variable->v5, "%s", cmnd);
                    break;

             }
             break;
           case 2:
              switch(var)
              {
                 default:
                    progbug( format( "Unknown setvar %s", buf ), mob );
                    return BERR;
                 case 1:
                    stralloc_printf( &chkobj->variable->v1, "%s", cmnd);
                    break;
                 case 2:
                    stralloc_printf( &chkobj->variable->v2, "%s", cmnd);
                    break;
                 case 3:
                    stralloc_printf( &chkobj->variable->v3, "%s", cmnd);
                    break;
                 case 4:
                    stralloc_printf( &chkobj->variable->v4, "%s", cmnd);
                    break;
                 case 5:
                    stralloc_printf( &chkobj->variable->v5, "%s", cmnd);
                    break;
             }
             break;
        }
    }
    return COMMANDOK;
  }


Add the following function and add a declaration in mud.h for the prototype to be called
from other files.
void reset_variables( void *vo, int type )
{
   ROOM_INDEX_DATA *room = (ROOM_INDEX_DATA *)vo;
   CHAR_DATA *ch = (CHAR_DATA *)vo;
   OBJ_DATA *obj = (OBJ_DATA *)vo;
   switch (type)
   {
        case 0:
            stralloc_printf( &room->variable->v1, "%s", "Unset");
            stralloc_printf( &room->variable->v2, "%s", "Unset");
            stralloc_printf( &room->variable->v3, "%s", "Unset");
            stralloc_printf( &room->variable->v4, "%s", "Unset");
            stralloc_printf( &room->variable->v5, "%s", "Unset");
            break;
        case 1:
            stralloc_printf( &ch->variable->v1, "%s", "Unset");
            stralloc_printf( &ch->variable->v2, "%s", "Unset");
            stralloc_printf( &ch->variable->v3, "%s", "Unset");
            stralloc_printf( &ch->variable->v4, "%s", "Unset");
            stralloc_printf( &ch->variable->v5, "%s", "Unset");
            break;
        case 2:
            stralloc_printf( &obj->variable->v1, "%s", "Unset");
            stralloc_printf( &obj->variable->v2, "%s", "Unset");
            stralloc_printf( &obj->variable->v3, "%s", "Unset");
            stralloc_printf( &obj->variable->v4, "%s", "Unset");
            stralloc_printf( &obj->variable->v5, "%s", "Unset");
            break;
   }
   return;
}

In db.c inside function void load_rooms() after:
        pRoomIndex->last_exit           = NULL;
add:
        CREATE( pRoomIndex->variable, VARIABLE_DATA, 1 );
        reset_variables( pRoomIndex, 0 );

inside function void clear_char() after:
    xCLEAR_BITS(ch->affected_by);
add:
    CREATE( ch->variable, VARIABLE_DATA, 1 );
    reset_variables( ch, 1 );

inside function ROOM_INDEX_DATA *make_room() after:
        pRoomIndex->last_exit           = NULL;
add:
        CREATE( pRoomIndex->variable, VARIABLE_DATA, 1 );
        reset_variables( pRoomIndex, 0 );

inside function OBJ_DATA *create_object() after:
    obj->value[5]       = pObjIndex->value[5];
add:
    CREATE( obj->variable, VARIABLE_DATA, 1 );
    reset_variables( obj, 2 );

In save.c inside function void fread_obj() after:
                    if ( fNest )
                      rgObjNest[iNest] = obj;
add:
                    CREATE( obj->variable, VARIABLE_DATA, 1 );
                    reset_variables( obj, 2 );

If you don't have stralloc_printf, you can get a copy from my site,
its fairly simple, just a mix of STRALLOC and STRFREE combined into
one with some va_printf joy added in to make it possible to add in formatting.

Add this in to mud_prog.c

char *parse_setvar( char *cmnd, CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void *vo, CHAR_DATA *rndm )
{
  static char results[MSL*2];
  int x;
  CHAR_DATA *chkchar = NULL;
  OBJ_DATA *chkobj = NULL;
  ROOM_INDEX_DATA *chkroom = NULL;

  results[0] = '\0';
  for ( x=0; cmnd[x] != '\0'; x++)
  {
    chkchar = NULL;
    chkobj = NULL;
    if (cmnd[x] == '\0')
      return results;
    if (cmnd[x] != '$')
      add_letter( results, cmnd[x]);
    else
    {
       switch(cmnd[x+1])
       {
          default:
           add_letter( results, cmnd[x]);  // Because the next letter is not a $ it will just take care of itself
           break;
          case 'i':
           chkchar = mob;
           break;
          case 'n':
           chkchar = actor;
           break;
          case 't':
          case 'a':
           chkchar = (CHAR_DATA *)vo;
           break;
          case 'r':
           chkchar = rndm;
           break;
          case 'o':
           chkobj = obj;
           break;
          case 'p':
           chkobj = (OBJ_DATA *)vo;
           break;
          case 'g':
           chkroom = obj ? (obj->carried_by ? obj->carried_by->in_room : NULL) : mob ? mob->in_room :
                              (actor ? actor->in_room : NULL);
           break;
       }
    }
    if (chkchar || chkobj || chkroom)  // Ok, so one of them is valid, lets find out what the info we're looking at is.
    {
      x+=2; // skip over the identifier and go straight into whats next...
      if (cmnd[x] != '.' || cmnd[x] == '\0') //  not a period, so this isnt a pointer, just a variable.
      {
       add_letter( results, cmnd[x-2]); // Put this piece back
       add_letter( results, cmnd[x-1]); // Put this piece back
       add_letter( results, cmnd[x]); // Put this piece back
       if ( cmnd[x] == '\0')
         return results;
       continue; // and keep going.
      }
      else  // Ok, they used the right syntax, lets fight out what our 'word' is.
      {
         char word[MIL];;
         word[0] = '\0';
         x++;
         while ( (isalpha(cmnd[x])||isdigit(cmnd[x])) && cmnd[x] != '\0')  // Lets find the next single word.
         {
            add_letter( word, cmnd[x]);
            x++;
         }
           // If we get here, we assume we now have the word.
         if (chkchar != NULL)  // Begin looking for possible character matches.
         {
             if (!str_cmp( word, "name"))
             {
                 if (IS_NPC(chkchar))
                   strcat( results, format( "%s", chkchar->short_descr) );
                 else
                   strcat( results, format( "%s", chkchar->name ));
             }
             if (!str_cmp( word, "sex"))
             {
                 if (chkchar->sex == 2)
                   strcat( results, format( "%s", "female" ));
                 else
                   strcat( results, format( "%s", "male" ));
             }
             if (!str_cmp( word, "class"))
             {
                 strcat( results, format( "%s", npc_class[chkchar->class] ));
             }
             if (!str_cmp( word, "race"))
             {
                 strcat( results, get_race(chkchar) );
             }
             if (!str_cmp( word, "eyecolor"))
             {
                 strcat( results, get_eyes(chkchar) );
             }
             if (!str_cmp( word, "haircolor"))
             {
                 strcat( results, get_haircolor(chkchar) );
             }
             if (!str_cmp( word, "skin"))
             {
                 strcat( results, get_complexion(chkchar) );
             }
             if (!str_cmp( word, "level"))
             {
                 strcat( results, itoa( chkchar->level ) );
             }
             if (!str_cmp( word, "var1"))
             {
                strcat( results, format( "%s", chkchar->variable->v1 ) );
             }
             if (!str_cmp( word, "var2"))
             {
                strcat( results, format( "%s", chkchar->variable->v2 ) );
             }
             if (!str_cmp( word, "var3"))
             {
                strcat( results, format( "%s", chkchar->variable->v3 ) );
             }
             if (!str_cmp( word, "var4"))
             {
                strcat( results, format( "%s", chkchar->variable->v4 ) );
             }
             if (!str_cmp( word, "var5"))
             {
                strcat( results, format( "%s", chkchar->variable->v5 ) );
             }
             // add your own char checks at this point
         }
         if (chkobj != NULL)  // Then do objects.
         {
             if (!str_cmp( word, "level"))
             {
                 strcat( results, itoa( chkobj->level) );
             }
             if (!str_cmp( word, "var1"))
             {
                strcat( results, format( "%s", chkobj->variable->v1 ) );
             }
             if (!str_cmp( word, "var2"))
             {
                strcat( results, format( "%s", chkobj->variable->v2 ) );
             }
             }
             if (!str_cmp( word, "var3"))
             {
                strcat( results, format( "%s", chkobj->variable->v3 ) );
             }
             if (!str_cmp( word, "var4"))
             {
                strcat( results, format( "%s", chkobj->variable->v4 ) );
             }
             if (!str_cmp( word, "var5"))
             {
                strcat( results, format( "%s", chkobj->variable->v5 ) );
             }
             // add your own obj checks at this point
         }
         if (chkroom != NULL)
         {
             if (!str_cmp( word, "var1"))
             {
                strcat( results, format( "%s", chkroom->variable->v1 ) );
             }
             if (!str_cmp( word, "var2"))
             {
                strcat( results, format( "%s", chkroom->variable->v2 ) );
             }
             if (!str_cmp( word, "var3"))
             {
                strcat( results, format( "%s", chkroom->variable->v3 ) );
             }
             if (!str_cmp( word, "var4"))
             {
                strcat( results, format( "%s", chkroom->variable->v4 ) );
             }
             if (!str_cmp( word, "var5"))
             {
                strcat( results, format( "%s", chkroom->variable->v5 ) );
             }
             // add your own room checks at this point
         }
         if (cmnd[x] == '\0')
          return results;
         else
          add_letter( results, cmnd[x]);
      }
    }
  }
  return results;
}

Supportive functions you may not have and may need:

void add_letter( char *string, char letter)
{
  char buf[MIL];

  sprintf(buf, "%c", letter);
  strcat(string, buf);
  return;
}

void stralloc_printf( char **pointer, char *fmt, ...)
{
    char buf[MAX_STRING_LENGTH*2];	/* better safe than sorry */
    va_list args;

    va_start(args, fmt);
    vsprintf(buf, fmt, args);
    va_end(args);
	
    if (*pointer)
     STRFREE(*pointer);
    *pointer = STRALLOC( buf);
    return;
}

char *format( char *fmt, ...)  
{  
  static char newstring[MAX_INPUT_LENGTH];  
  char buf[MAX_STRING_LENGTH*2];        /* better safe than sorry */  
  va_list args;  
   
  newstring[0] = '\0';  
   
  if (fmt[0] == '\0')  
   return " ";  
   
  va_start(args, fmt);  
  vsprintf(buf, fmt, args);  
  va_end(args);  
   
  if (buf[0] == '\0')  
   return " ";  
  strcpy( newstring, buf);  
  return newstring;  
} 

char *itoa(int foo)
{
  static char bar[256];

  sprintf(bar,"%d",foo);
  return(bar);

}

::UPDATES::
 9/6/2006
 --------------
 in mud_prog.c goto function mprog_do_ifcheck(), this will allow you to use the variables
 for an ifcheck

after:
doneargs:
    q = p;
    while ( isoperator(*p) ) ++p;
    strncpy(opr, q, p-q);
    opr[p-q] = '\0';
    while ( isspace(*p) ) *p++ = '\0';
add:
    rval = parse_setvar( p, mob, actor, obj, vo, rndm );

::NEW::
This will add the ability to parse functions that can return strings or return
numbers. The example given is a random integer function:
eg.
 if str($n) < $f.rand(20,40)
and
 setvar $i 1 $f.rand(20,40)

mud_prog.c:
 inside parse_setvar():
after:
  ROOM_INDEX_DATA *chkroom = NULL;
add:
  bool function = FALSE;

after:
          case 'o':
           chkobj = obj;
           break;
          case 'p':
           chkobj = (OBJ_DATA *)vo;
           break;
add:
          case 'f': // function identifier
           function=TRUE;
           break;

change:
    if (chkchar || chkobj || chkroom)
to:
    if (chkchar || chkobj || chkroom || function) 

change:
         while ( (isalpha(cmnd[x])||isdigit(cmnd[x])) && cmnd[x] != '\0')
to:
         while ( (isalpha(cmnd[x]) || isdigit(cmnd[x]) || (function && (cmnd[x] == '(' || cmnd[x] == ')' || cmnd[x] == ',')) ) &&
cmnd[x] != '\0')

before:
         if (cmnd[x] == '\0')
          return results;
         else
          add_letter( results, cmnd[x]);
add:
         if ( function )
         {
             if ( !str_prefix( "rand", word ) )
             {
                char arg[MIL], arg2[MIL];
                arg[0] = '\0';
                arg2[0] = '\0';
                int y;

                if ( word[4] != '(' )
                {
                    progbug( format( "Function RAND missing opening parenthesis(%c)", word[4] ), mob );
                    return results;
                }

                for ( y = 5; y < strlen(word); y++ )
                {
                    if ( word[y] == ',' )
                        break;

                    if ( word[y] == '\0' || word[y] == ')' )
                    {
                        progbug( "Illegal use of RAND function", mob );
                        return results;
                    }
                    add_letter( arg, word[y] );
                }

                for ( y++; y < strlen(word); y++ )
                {
                    if ( word[y] == ')' )
                        break;

                    if ( word[y] == '\0' )
                    {
                        progbug( "Illegal use of RAND function", mob );
                        return results;
                    }
                    add_letter( arg2, word[y] );
                }

                if ( !is_number(arg) || !is_number(arg2) )
                {
                    progbug( format( "Non-number used for RAND function - %s : %s", arg, arg2 ), mob );
                    return results;
                }
                else
                {
                    strcat( results, format( "%d", number_range(atoi(arg),atoi(arg2)) ) );
                }
             }

	     // add your own functions inside here
             function = FALSE;
         }
