This snippet makes three major changes to standard SMAUG MUD-Progs.

1.    You become capable of using tokens as RVALS

2.    You gain the ability to expose actual attributes of tokens rather than just their names.

3.    You gain the ability to set and recall tokens $1 through $5 within the scope of any script.

 


 

Some simple examples to clarify:

 

Script:

>speech_prog test

say Hi $n, you're a $n.race.

'You might even be a $n.class.

 

Output:

You say 'test'

Puff says 'Hi Eos, you're a pixie.'

Puff says 'You might even be a druid.'

 


 

Script:

>speech_prog bleh

setvar 1 murp

say $1

 

OutPut:

You say 'bleh'

Puff says 'murp'

 


 

Script:

>speech_prog thirdtry

setvar 1 $n.race

if race($i) == $1

say Hey look we're the same race!

else

say Aw. You're a different species.

endif

 

OutPut:

mset puff race dragon

You say 'thirdtry'

Puff says 'Aw. You're a different species.'

mset puff race pixie

You say 'thirdtry'

Puff says 'Hey look we're the same race!'

 


 

 

In db.c after:

 

 void mprog_read_programs( FILE * fp, MOB_INDEX_DATA * pMobIndex );
 void oprog_read_programs( FILE * fp, OBJ_INDEX_DATA * pObjIndex );
 void rprog_read_programs( FILE * fp, ROOM_INDEX_DATA * pRoomIndex );
Add:

 void reset_variables( void );
 

 

After:

 /*
  * Globals.
  */
    load_weatherdata(  );
    init_area_weather(  );
Add:

    reset_variables();
 

 

 

 

In mud.h after:

 

 typedef struct lcnv_data LCNV_DATA;
 typedef struct lang_data LANG_DATA;
 typedef struct specfun_list SPEC_LIST;
Add:

 typedef struct variable_data VARIABLE_DATA; /* Mud Prog Variables - Eos */
 

 

 

 

Before:

 /*
  * Ban Types --- Shaddai
  */
 

Add:

 

 
/* Mud Prog Variables - Eos */
struct variable_data
{
    char *v1;
    char *v2;
    char *v3;
    char *v4;
    char *v5;
};
 

 

 

After:

 extern short gsn_halfling;
 

Add:

/*
      Mud Prog Variables - Eos
*/
extern      struct      variable_data     variable;
 

 

 

 

 

 

In mud_prog.c

 

After:

 

 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
 #include "mud.h"
 

Add

 #include <stdarg.h>
 

 VARIABLE_DATA variable;
 void reset_variables( void );
 char *parse_setvar( char *cmnd, CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void *vo, CHAR_DATA *rndm );
 void add_letter( char *string, char letter);
 char *rval_translate( char *rval, CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void *vo, CHAR_DATA *rndm );
 void stralloc_printf( char **pointer, char *fmt, ...);
 char *format( char *fmt, ...);
 

 

Then After:

 /*
  * Recursive function used by the carryingvnum ifcheck.
  * It loops thru all objects belonging to a char (in nested containers)
    {
       switch ( cvar[1] )
       {
 

 

Add:

 

 

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

 

 

 

After

       if( !chkchar && !chkobj )
          return BERR;
Add:

 

     rval = rval_translate(rval, mob, actor, obj, vo, rndm);
     if ( !str_cmp(chck, "var1") )
     {
             bug( "setvar %s", rval);
             if (is_number(rval))
              return mprog_veval(atoi(variable.v1), opr, atoi(rval), mob);
 
             if (!str_cmp(variable.v1, rval))
              return TRUE;
 
             return FALSE;
     }
     if ( !str_cmp(chck, "var2") )
     {
             if (is_number(rval))
              return mprog_veval(atoi(variable.v2), opr, atoi(rval), mob);
 
             if (!str_cmp(variable.v2, rval))
              return TRUE;
 
             return FALSE;
     }
     if ( !str_cmp(chck, "var3") )
     {
             if (is_number(rval))
              return mprog_veval(atoi(variable.v3), opr, atoi(rval), mob);
 
             if (!str_cmp(variable.v3, rval))
              return TRUE;
 
             return FALSE;
     }
     if ( !str_cmp(chck, "var4") )
     {
             if (is_number(rval))
              return mprog_veval(atoi(variable.v4), opr, atoi(rval), mob);
 
             if (!str_cmp(variable.v4, rval))
              return TRUE;
 
             return FALSE;
     }
     if ( !str_cmp(chck, "var5") )
     {
             if (is_number(rval))
              return mprog_veval(atoi(variable.v5), opr, atoi(rval), mob);
 
             if (!str_cmp(variable.v5, rval))
              return TRUE;
 
             return FALSE;
     }
 

 

 

 

 

Between:

    switch ( ch )
    {
And

       case 'i':
          if( mob && !char_died( mob ) )
          {
 

Add:

 

       case '1':
          strcpy( t, variable.v1 );
          break;
       case '2':
          strcpy( t, variable.v2 );
          break;
       case '3':
          strcpy( t, variable.v3 );
          break;
       case '4':
          strcpy( t, variable.v4 );
          break;
       case '5':
          strcpy( t, variable.v5 );
          break;
 

 

 

 

 

 

 

Above:

    iflevel = 0;
Add:

    reset_variables();
 

 

 

 

Replace:

   vnum = mob->pIndexData->vnum;
   point = buf;
   str = cmnd;

   /*
    * 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';

   interpret( mob, buf );
 

 

With:

 

   vnum = mob->pIndexData->vnum;
   point = buf;
   str = cmnd;

  str = parse_setvar( str, 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" ) )
  {
    short var;
    char *newtext;

    /* does not make it past this point, explore why */
    newtext = buf;
    newtext = one_argument( newtext, firstword );
    newtext = one_argument( newtext, firstword );
    var = atoi(firstword);
    str     = cmnd;
    switch(var)
    {
      default:
       bug( "Unknown setvar %s:%d", firstword, mob->pIndexData->vnum );
       return BERR;
      case 1:
       stralloc_printf( &variable.v1, "%s", newtext);
       break;
      case 2:
       stralloc_printf( &variable.v2, "%s", newtext);
       break;
      case 3:
       stralloc_printf( &variable.v3, "%s", newtext);
       break;
      case 4:
       stralloc_printf( &variable.v4, "%s", newtext);
       break;
      case 5:
       stralloc_printf( &variable.v5, "%s", newtext);
       break;
    }
  }

   interpret( mob, buf );
 

 

 

 

 

 

 

Finally at the bottom of the file add in all of this:

 

char *rval_translate( char *rval, CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void *vo, CHAR_DATA *rndm )
{
   CHAR_DATA *ch=NULL;
   OBJ_DATA *obj2=NULL;

   if (rval[0] != '$')
    return rval;

   switch(rval[1])
   {
          case 'i':     ch = mob;               break;
          case 'n':     ch = actor;             break;
          case 't':     ch = (CHAR_DATA *)vo;         break;
          case 'r':     ch = rndm;              break;
          case 'o':     obj2 = obj;             break;
          case 'p':     obj2 = (OBJ_DATA *)vo;        break;
          case '1':    
                return variable.v1;
          case '2':    
                return variable.v2;
          case '3':    
                return variable.v3;
          case '4':    
                return variable.v4;
          case '5':    
                return variable.v5;
          default:
            break;
   }
   if (ch)
     return IS_NPC(ch) ? ch->short_descr : ch->name;
   if (obj2)
     return obj2->short_descr;
   return "Tell a Staff Member you got this result and how";

}

void reset_variables()
{
   stralloc_printf( &variable.v1, "%s", "Unset");
   stralloc_printf( &variable.v2, "%s", "Unset");
   stralloc_printf( &variable.v3, "%s", "Unset");
   stralloc_printf( &variable.v4, "%s", "Unset");
   stralloc_printf( &variable.v5, "%s", "Unset");
   return;
}

char *parse_setvar( char *cmnd, CHAR_DATA *mob, CHAR_DATA *actor, OBJ_DATA *obj, void *vo, CHAR_DATA *rndm )
{
  static char results[MAX_STRING_LENGTH*2];
  int x;
  CHAR_DATA *chkchar = NULL;
  OBJ_DATA *chkobj = 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;

            if (!chkchar)      // Used $n where they should've $r'd

              chkchar = rndm;

            break;

  case 't':

            chkchar = (CHAR_DATA *)vo;

            if (!chkchar) // Used $t where $t was impossible.

              chkchar = actor;  // can use actor or rndm as you prefer

            break;

  case 'r':

            chkchar = rndm;

            if (!chkchar)

              chkchar = actor;  // Used $r where they should've $n'd

            break;

  case 'o':
           chkobj = obj;
           break;
  case 'p':
           chkobj = (OBJ_DATA *)vo;
           break;
       }
    }
    if (chkchar || chkobj)  // 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[MAX_INPUT_LENGTH];;
         word[0] = '\0';
         x++;
         while ( isalpha(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, "level"))
             {
                 strcat( results, format( "%d", chkchar->level) );
             }

             // add your own char checks at this point
         }
         if (chkobj != NULL)  // Then do objects.
         {
             if (!str_cmp( word, "level"))
             {
                 strcat( results, format( "%d", chkobj->level) );
             }
             // add your own obj checks at this point
         }
         if (cmnd[x] == '\0')
          return results;
         else
          add_letter( results, cmnd[x]);
      }
    }
  }
  return results;
}


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

  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;
}