player/a/
player/b/
player/c/
player/d/
player/e/
player/f/
player/g/
player/i/
player/j/
player/k/
player/m/
player/n/
player/r/
player/s/
player/v/
player/w/
player/x/
player/z/
player_fst/e/
player_fst/f/
player_fst/h/
player_fst/i/
player_fst/j/
player_fst/n/
player_fst/o/
player_fst/p/
player_fst/player/a/
player_fst/player/b/
player_fst/player/c/
player_fst/player/d/
player_fst/player/e/
player_fst/player/f/
player_fst/player/g/
player_fst/player/j/
player_fst/player/k/
player_fst/player/m/
player_fst/player/n/
player_fst/player/r/
player_fst/player/s/
player_fst/player/v/
player_fst/player/w/
player_fst/player/x/
player_fst/player/z/
player_fst/u/
player_fst/v/
player_fst/w/
player_fst/x/
/*~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
 ~  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.                              ~
 ~                                                                         ~
 ~  Ack 2.2 improvements copyright (C) 1994 by Stephen Dooley              ~
 ~  ACK!MUD is modified Merc2.0/2.1/2.2 code (c)Stephen Zepp 1998 Ver: 4.3 ~
 ~                                                                         ~
 ~  In order to use any part of this  PA  Diku Mud, you must comply with   ~
 ~  both the original Diku license in 'license.doc' as well the Merc       ~
 ~  license in 'license.txt', and the Ack!Mud license in 'ack_license.txt'.~
 ~  In particular, you may not remove any of these copyright notices.      ~
 ~                                                                         ~
 ~           _______      _____                                            ~
 ~          /  __  /\    / ___ \       222222        PA_MUD by Amnon Kruvi ~
 ~         /______/ /   / /___\ \            2       PA_MUD is modified    ~
 ~        / _______/   / _______ \           2       Ack!Mud, v4.3         ~
 ~       /_/          /_/       \_\        2                               ~
 ~                                      2                                  ~
 ~                                     2222222                             ~
 ~                                                                         ~
 ~                                                                         ~
 ~   Years of work have been invested to create DIKU, Merc, Ack and PA.    ~
 ~   Please show your respect by following the licenses, and issuing       ~
 ~   credits where due.                                                    ~
 ~                                                                         ~
 ~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-*/

#if defined(macintosh)
#include <types.h>
#else
#include <sys/types.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
/* For forks etc. */
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>

#ifndef  DEC_ACK_H 
#include "ack.h"
#include "tables.h"
#endif

#ifndef DEC_STRFUNS_H
#include "strfuns.h"
#endif

void pre_parse( char * list, char * victimname, char * containername, char * things )
{
  char arg1[MSL];
  char container_name[MSL];
  char one_object[MSL];
  char holdbuf[MSL];
  char victim_name[MSL];
  char object_list[MSL];
  char * argument = list;
  container_name[0] = '\0';
  victim_name[0] = '\0';
  object_list[0] = '\0';
  for ( ; ; )
  {
    argument = one_argument( argument, arg1 );
    if ( arg1[0] == '\0' )
      break;
    if (  ( !str_cmp( "from", arg1 ) )
       || ( !str_cmp( "in", arg1 ) )  )
    {
      argument = one_argument( argument, container_name );
    }
    else if ( !str_cmp( "to", arg1 ) )
    {
      argument = one_argument( argument, victim_name );
    }
    else if ( object_list[0] != '\0' )
    {
      safe_strcat(MSL,victim_name,arg1);
    }
    else
    {
      if ( is_number( arg1 ) )
      {
        argument = one_argument( argument, one_object );
        sprintf( holdbuf, "%s %s ", arg1, one_object );
        safe_strcat( MSL, object_list, holdbuf );
      }
      else
      {
        sprintf( holdbuf, "1 %s ", arg1 );
        safe_strcat( MSL, object_list, holdbuf );
      }
    }
  }
//  strcpy( victimname , argument );
  strcpy( victimname , victim_name );
  strcpy( things,object_list);
  strcpy( containername , container_name);
  return;
}



/*
 * Return true if an argument is completely numeric.
 */
bool is_number( char *arg )
{
    if ( *arg == '\0' )
	return FALSE;

    if ( *arg == '+' || *arg == '-' )
	arg++;

    for ( ; *arg != '\0'; arg++ )
    {
	if ( !isdigit(*arg) )
	    return FALSE;
    }

    return TRUE;
}



bool is_name( const char *str, char *namelist )
{
    char name[MAX_INPUT_LENGTH];

    for ( ; ; )
    {
	namelist = one_argument( namelist, name );
	if ( name[0] == '\0' )
	    return FALSE;
	if ( !str_prefix( str, name ) )
	    return TRUE;
    }
}
void safe_strcat(int max_len,char * dest,char * source)
{
	int a;
	char c;
	char * orig_dest;
	char * orig_source;
	
	if (dest == NULL && source == NULL)
	 return;
	
	if (dest == NULL)
	{ 
	 fprintf(stderr,"safe_strcat: Null dest string for source : %s\n",source);
	 return;
	}
	
	if (source == NULL)
	{
	 fprintf(stderr,"safe_strcat: NULL source for dest : %s\n",dest);
	 return;
	}
	
	orig_dest=dest;
	orig_source=source;

	while (*dest !='\0')       /* Check to see if dest is already over limit. */
	 dest++;
	
	a=dest-orig_dest;
	if ( a > max_len )
	{
	 fprintf(stderr,"WARNING: dest string already too long:\nsource: %s\ndest: %s\n",source,orig_dest);
	 return;
	}
	
	if ( a == max_len )
	{
	  fprintf(stderr,"safe_strcat: string too long, source is : %s\n",orig_source);
	  return;
	}       
	 
	while ( (c = *(source++)) != 0 )
	{
	 *(dest++)=c;
	 a++;
	 if ( a == max_len )
	 {
	  *(--dest)='\0';
	  fprintf(stderr,"safe_strcat: string too long, source is : %s\n",orig_source);
	  return;
	 }
	}
	  
	*dest='\0';
	return;
}        
	
	
char * space_pad( const char * str, sh_int final_size )
{
  sh_int space_pad = my_strlen( str );
  static char padbuf[MSL];

  sprintf( padbuf, "%s", str );
  for ( ; space_pad != final_size ; space_pad++ )
    safe_strcat( MSL, padbuf, " " );
  return padbuf;
}


/*
 * Removes the tildes from a string.
 * Used for player-entered strings that go into disk files.
 */
void smash_tilde( char *str )
{
    for ( ; *str != '\0'; str++ )
    {
	if ( *str == '~' )
	    *str = '-';
    }

    return;
}

void smash_system( char *str )
{
    for ( ; *str != '\0'; str++ )
    {
	if ( *str == '%' )
	    *str = '*';
    }

    return;
}

char *smash_swear( char *str )
{
    int i;

    for ( i = 0; str[i] != '\0'; i++ )
    {
      if (  ( str[i]   == 'f' || str[i]   == 'F'  )
         && ( str[i+1] == 'u' || str[i+1] == 'U'  ) 
         && ( str[i+2] == 'c' || str[i+2] == 'C'  )
         && ( str[i+3] == 'k' || str[i+3] == 'K'  )  )
      {
        str[i] = '*';
        str[i +1] = '*';
        str[i +2] = '*';
        str[i +3] = '*';
        i += 3;
      }
      if (  ( str[i]   == 's' || str[i]   == 'S'  )
         && ( str[i+1] == 'h' || str[i+1] == 'H'  ) 
         && ( str[i+2] == 'i' || str[i+2] == 'I'  )
         && ( str[i+3] == 't' || str[i+3] == 'T'  )  )
      {
        str[i] = '*';
        str[i +1] = '*';
        str[i +2] = '*';
        str[i +3] = '*';
        i += 3;
      }
      if (  ( str[i]   == 'c' || str[i]   == 'C'  )
         && ( str[i+1] == 'u' || str[i+1] == 'U'  ) 
         && ( str[i+2] == 'n' || str[i+2] == 'N'  )
         && ( str[i+3] == 't' || str[i+3] == 'T'  )  )
      {
        str[i] = '*';
        str[i +1] = '*';
        str[i +2] = '*';
        str[i +3] = '*';
        i += 3;
      }
      if (  ( str[i]   == 'p' || str[i]   == 'P'  )
         && ( str[i+1] == 'e' || str[i+1] == 'E'  ) 
         && ( str[i+2] == 'n' || str[i+2] == 'N'  )
         && ( str[i+3] == 'i' || str[i+3] == 'I'  )
         && ( str[i+4] == 's' || str[i+4] == 'S'  )  )
      {
        str[i] = '*';
        str[i +1] = '*';
        str[i +2] = '*';
        str[i +3] = '*';
        str[i +4] = '*';
        i += 4;
      }
      if (  ( str[i]   == 'd' || str[i]   == 'D'  )
         && ( str[i+1] == 'i' || str[i+1] == 'I'  ) 
         && ( str[i+2] == 'c' || str[i+2] == 'C'  )
         && ( str[i+3] == 'k' || str[i+3] == 'K'  )  )
      {
        str[i] = '*';
        str[i +1] = '*';
        str[i +2] = '*';
        str[i +3] = '*';
        i += 3;
      }
      if (  ( str[i]   == 'c' || str[i]   == 'C'  )
         && ( str[i+1] == 'o' || str[i+1] == 'O'  ) 
         && ( str[i+2] == 'c' || str[i+2] == 'C'  )
         && ( str[i+3] == 'k' || str[i+3] == 'K'  )  )
      {
        str[i] = '*';
        str[i +1] = '*';
        str[i +2] = '*';
        str[i +3] = '*';
        i += 3;
      }
      if (  ( str[i]   == 'f' || str[i]   == 'F'  )
         && ( str[i+1] == 'a' || str[i+1] == 'A'  ) 
         && ( str[i+2] == 'g' || str[i+2] == 'G'  ) )
      {
        str[i] = '*';
        str[i +1] = '*';
        str[i +2] = '*';
        i += 2;
      }
      if (  ( str[i]   == 'b' || str[i]   == 'B'  )
         && ( str[i+1] == 'i' || str[i+1] == 'I'  )
         && ( str[i+2] == 't' || str[i+2] == 'T'  )
         && ( str[i+3] == 'c' || str[i+3] == 'C'  )
         && ( str[i+4] == 'h' || str[i+4] == 'H'  ) )
      {
        str[i] = '*';
        str[i+1] = '*';
        str[i+2] = '*';
        str[i+3] = '*';
        str[i+4] = '*';
        i +=4;
      }
    }
    return str;
}


/*
 * Compare strings, case insensitive.
 * Return TRUE if different
 *   (compatibility with historical functions).
 */
bool str_cmp( const char *astr, const char *bstr )
{
  int count = 0;
  bool notrunc = FALSE;
    if ( astr == NULL )
	return TRUE;

    if ( bstr == NULL )
	return TRUE;

    if ( *astr == '^' )
    {
      notrunc = TRUE;
      astr++;
    } 
    if ( *bstr == '^' )
    {
      notrunc = TRUE;
      bstr++;
    }
    if ( astr == NULL )
    {
	/* bug( "Str_cmp: null astr.", 0 );   */
	return TRUE;
    }

    if ( bstr == NULL )
    {
	return TRUE;
    }


    for ( ; *astr || *bstr; astr++, bstr++ )
    {
      if ( !notrunc )
        if ( *astr == '*' && count )
          return FALSE;

	if ( LOWER(*astr) != LOWER(*bstr) )
	    return TRUE;
      count++;
    }

    return FALSE;
}



/*
 * Compare strings, case insensitive, for prefix matching.
 * Return TRUE if astr not a prefix of bstr
 *   (compatibility with historical functions).
 */
bool str_prefix( const char *astr, const char *bstr )
{
    if ( astr == NULL )
    {
	bug( "Strn_cmp: null astr.", 0 );
	return TRUE;
    }

    if ( bstr == NULL )
    {
	bug( "Strn_cmp: null bstr.", 0 );
	return TRUE;
    }

    for ( ; *astr; astr++, bstr++ )
    {
	if ( LOWER(*astr) != LOWER(*bstr) )
	    return TRUE;
    }

    return FALSE;
}



/*
 * Compare strings, case insensitive, for match anywhere.
 * Returns TRUE is astr not part of bstr.
 *   (compatibility with historical functions).
 */
bool str_infix( const char *astr, const char *bstr )
{
    int sstr1;
    int sstr2;
    int ichar;
    char c0;

    if ( ( c0 = LOWER(astr[0]) ) == '\0' )
	return FALSE;

    sstr1 = strlen(astr);
    sstr2 = strlen(bstr);

    for ( ichar = 0; ichar <= sstr2 - sstr1; ichar++ )
    {
	if ( c0 == LOWER(bstr[ichar]) && !str_prefix( astr, bstr + ichar ) )
	    return FALSE;
    }

    return TRUE;
}



/*
 * Compare strings, case insensitive, for suffix matching.
 * Return TRUE if astr not a suffix of bstr
 *   (compatibility with historical functions).
 */
bool str_suffix( const char *astr, const char *bstr )
{
    int sstr1;
    int sstr2;

    sstr1 = strlen(astr);
    sstr2 = strlen(bstr);
    if ( sstr1 <= sstr2 && !str_cmp( astr, bstr + sstr2 - sstr1 ) )
	return FALSE;
    else
	return TRUE;
}



/*
 * Returns an initial-capped string.
 */
#if 0
char *capitalize( const char *str )
{
    static char strcap[MAX_STRING_LENGTH];
    int i;

    for ( i = 0; str[i] != '\0'; i++ )
    {
      if (  ( str[i]   == '@'   )
         && ( str[i+1] == '@'   ) 
         && ( str[i+2] != '\0'  )  )
      {
        strcap[i] = str[i];
        strcap[i +1] = str[i+1];
        strcap[i +2] = str[i+2]; 
        i += 2;
      }
      else
        strcap[i] = LOWER(str[i]);
    }

    strcap[i] = '\0';
    for ( i = 0; strcap[i] != '\0' && !isalpha( strcap[i] ); i++ );
    if (  ( i > 0 )
       && ( strcap[i] != '\0' )  )
      i++;
    if ( strcap[i] != '\0' )
      strcap[i] = UPPER(strcap[i]);
    return strcap;
}
#endif
/* Capitalize function by KaVir: 3th December 1997.
 *
 * Pass in a pointer to the string to capitalize.  The function will return
 * a pointer to the corrected string, however for safety purposes the original
 * pointer will also be set to point to the new string.  Thus if you do:
 *    char *normal_string = "a piece of text";
 *    char *cap_string = capitalize( normal_string );
 * Then both cap_string and normal_string will contain the capitalized string.
 *
 * The precise rules of capitalization are as follows:
 *    1) The first non-colorcode alphabetic character will be uppercase.
 *    2) Any alphabetic character following two or more @'s will be unchanged.
 *    3) Any other alphabetic character will be set to lowercase.
 *    4) Any other non-alphabetic characters will be ignored.
 */
char *capitalize( const char *str )
{
    static char strcap[MAX_STRING_LENGTH]; /* Permanent store */
/*    char *oldstr = str;  */
    int i = 0;                  /* Position in strcap */
    int count = 0;              /* Number of previous '@'s encountered */
    bool first_letter = TRUE;   /* You will UPPER the first letter you find */
    bool ignore_next  = FALSE;  /* Ignore the case of the next letter you find */

    /* If this occurs, then you have a bug elsewhere */
    if ( ( strcap[i] = *str ) == '\0' )
        return NULL;

    do /* Begin looping through the string, checking each character */
    {
        /* Should be more efficient than all those 'if' statements ;) */
        switch ( strcap[i] )
        {
            default: /* Non-alphabetic letters and not '@' */
                ignore_next = FALSE;   /* Not a color code */
                count = 0;
                break;
            case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
            case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
            case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
            case 's': case 't': case 'u': case 'v': case 'w': case 'x':
            case 'y': case 'z': /* Any lowercase letter */
                if ( ignore_next )
                    ignore_next = FALSE;  /* We ignore the case of the this letter */
                else if ( first_letter )
                {
                    first_letter = FALSE; /* Reset the flag */
                    strcap[i] = UPPER(strcap[i]); /* We set this letter to uppercase */
                }
                count = 0;
                break;
            case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
            case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
            case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
            case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
            case 'Y': case 'Z': /* Any uppercase letter */
                /* Then its the first letter in the string */
                if ( ignore_next )
                    ignore_next = FALSE;  /* We ignore the case of the this letter */
                else if ( first_letter )
                    first_letter = FALSE; /* We ignore the case of the this letter */
                else
                    strcap[i] = LOWER(strcap[i]); /* Set this letter to lowercase */
                    count = 0;
                break;
            case '@':
                if ( ++count >= 2 ) /* If there are two or more '@@'s in a row */
                    ignore_next = TRUE; /* Set the flag to ignore the next letter */
                break;
        }
    } while ( ( strcap[++i] = *++str ) != '\0' ); /* loop until end of string */

    i = 0; /* str = oldstr;  Reset variables */
#if 0
    /* Copy strcap back into the old string */
    while ( ( *str++ = strcap[i++] ) != '\0' )
	;

    return ( oldstr ); /* Return pointer to start of old string */
#endif
  return ( strcap );
}



/*
 * We need a replacement for strlen() which will take the color
 * codes into account when reporting a string's length.
 * -- Stephen
 */
 
int my_strlen( const char *text )
{
   char c;
   int i;
   int status;		
   int length;
   int strlen_size;
   
   status = 0;
   length = 0;
   strlen_size = strlen( text );
   
   for ( i = 0; i < strlen_size; i++ )
   {
      
      c = text[i];
      length++;
      
      switch( status )
      {
         case 0:
         case 1:
            if ( c == '@' )
               status++;
            else
               status = 0;
            break;
         case 2:
            if ( c == '@' )
              length -= 2;
            else
              length -= 3; /* Subtract for '@@x' */
            status = 0;
            break;
      }
   }
   return( length );
}

int nocol_strlen( const char *text )
{
   char c;
   int i;
   int status;		
   int length;
   int strlen_size;
   
   status = 0;
   length = 0;
   strlen_size = strlen( text );
   
   for ( i = 0; i < strlen_size; i++ )
   {
      
      c = text[i];
      length++;
      
      switch( status )
      {
         case 0:
         case 1:
            if ( c == '@' )
               status++;
            else
               status = 0;
            break;
         case 2:   
            length -= 3; /* Subtract for '@@x' */
            status=0;
            break;
      }
   }
   return( length );
}

int ccode_len( const char *text, sh_int desired )
{
   char c;
   int i;
   int status;		
   int length;
   int strlen_size;
   
   status = 0;
   length = 0;
   strlen_size = strlen( text );
   
   for ( i = 0; i < strlen_size; i++ )
   {
      
      c = text[i];
      
      switch( status )
      {
         case 0:
         case 1:
            if ( c == '@' )
               status++;
            else
               status = 0;
            break;
         case 2:
            if ( c != '@' )
              length += 3; /* Subtract for '@@x' */
            status=0;
            break;
      }
   }
   return( length + desired );
}
/* END NOTE */

/* A Function to "center" text, and return a string with
 * the required amount of white space either side of the
 * original text.  --Stephen
 */
 
char *center_text( char *text, int width )
{
  /* This could do with a LOT of improvement sometime! */
  /* Improvements done.. -- Altrag */
  static char foo[MAX_STRING_LENGTH];
  int len, diff;
   
  /* Don't bother with strings too long.. */
  if ( (len = my_strlen(text)) >= width )
    return text;

  diff = strlen(text)-len;

  /* Add the spaces and terminate string */
  memset(foo, ' ', width+diff);
  foo[width+diff] = '\0';
   
  /* Copy old string over */
  memcpy(&foo[(width-len)/2], text, len+diff);
  
  return foo;
}



char * str_mod( char * mod_string,  char *argument )
{
 

    char       arg1 [ MAX_INPUT_LENGTH  ];
    char       buf  [ MAX_STRING_LENGTH ];
    char      *buf2;
    char      *buf3 = NULL;
    char      *word;
    char        temp[MSL];
    int        i = 0;
    bool        multiple = FALSE;

    if ( !str_cmp( argument, "" ) )
    {
      sprintf( bug_buf, "Unknown reason for return, argument is -%s-", argument );
      monitor_chan( NULL, bug_buf, MONITOR_DEBUG );
      return mod_string;
      
    }


    if ( argument[0] == '+' || argument[0] == '-' )
    {
      buf[0] = '\0';
      smash_tilde( argument );
      if ( argument[0] == '+' )
      {
        argument++;
      
        if ( mod_string )
          safe_strcat( MSL, buf, mod_string );
        while ( isspace( *argument ) )
          argument++;
        if ( !str_infix( argument, mod_string ) )
        {
          return mod_string;
        }
        safe_strcat( MSL, buf, argument );
        safe_strcat( MSL, buf, " " );
      }
      if ( argument[0] == '-' )
      {
        argument++;
        if ( argument[0] == '\'' )
          multiple = TRUE;
 	one_argument( argument, arg1 );

        if ( multiple )
        {
          sprintf( temp, "\'%s\'", arg1 );
          sprintf( arg1, "%s", temp );
        }

        if ( arg1 )
	{
          buf2 = str_dup( mod_string );
	  buf3 = buf2;
	  if ( (word = strstr( buf2, arg1 ) ) == NULL )  
	  {
            free_string( buf2 );
            return mod_string;
          }
          else
          {
            while ( buf2 != word )
              buf[i++] = *(buf2++);
            while (  ( !isspace ( *(buf2++) ) )
                  || (  ( multiple )
                     && (  ( buf2[0] != '\'' ) 
                        && ( buf2[0] != '\0' ) ) )  );
              buf[i] = '\0';
            safe_strcat ( MSL, buf, buf2 );
          }
	}

      }

      free_string( buf3 );
      word = buf2 = buf3 = NULL;
      free_string( mod_string );
      mod_string = str_dup( buf );
    }
    return mod_string;
}
void rand_arg( char *argument, char *output )
{
  char  temp[MSL];
  sh_int        counter = 0;
  argument = one_argument( argument, temp );
  while ( temp[0] )
  {
    if (number_range(0, counter)==0)
      strcpy (output, temp); 
    counter++;
    argument = one_argument( argument, temp );
  }
}


/*
 * Given a string like 14.foo, return 14 and 'foo'
 */
int number_argument( char *argument, char *arg )
{
    char *pdot;
    int number;
    
    for ( pdot = argument; *pdot != '\0'; pdot++ )
    {
	if ( *pdot == '.' )
	{
	    *pdot = '\0';
	    number = atoi( argument );
	    *pdot = '.';
	    strcpy( arg, pdot+1 );
	    return number;
	}
    }

    strcpy( arg, argument );
    return 1;
}



/*
 * Pick off one argument from a string and return the rest.
 * Understands quotes.
 */
char *one_argument( char *argument, char *arg_first )
{
    char cEnd;
//    char buf[MSL];
    
    if ( argument == NULL )
      return NULL;
    while ( isspace(*argument) )
	argument++;

    cEnd = ' ';
    if ( *argument == '\'' || *argument == '"' )
	cEnd = *argument++;

    while ( *argument != '\0' )
    {
      if ( *argument == cEnd )
      {
        argument++;
        break;
      }
      *arg_first = LOWER(*argument);
      arg_first++;
      argument++;
    }
    *arg_first = '\0';

    while ( isspace(*argument) )
      argument++;

    return argument;
}

/*
 * Pick off one argument from a string and return the rest.
 * Understands quotes.
 */
char *one_word( char *argument, char *arg_first )
{
    char cEnd;
    if ( argument == NULL )
      return NULL;
    while ( isspace(*argument) )
	argument++;

    cEnd = ' ';
    if ( *argument == '\'' || *argument == '"' )
	cEnd = *argument++;

    while ( *argument != '\0' )
    {
      if ( *argument == cEnd )
      {
        argument++;
        break;
      }
      *arg_first = (*argument);
      arg_first++;
      argument++;
    }
    *arg_first = '\0';

    while ( isspace(*argument) )
      argument++;

    return argument;
}


char *two_args( char *argument, char *arg_first, char *arg_second )
{
  char *temp_arg = argument;
  
  temp_arg = one_argument( temp_arg, arg_first );
  temp_arg = one_argument( temp_arg, arg_second );
  return temp_arg;
}
  

char *strip_out(const char *orig, const char *strip)
{
  static char buf[MAX_STRING_LENGTH];
  char *i, *b = buf;
  int slen;

  if (!orig || !strip)
  {
/*    log_f("strip_out called with NULL param");  */
    return "!!OUT!!";
  }
  slen = strlen(strip);
  for (i = strstr(orig, strip); i; i = strstr(orig, strip))
  {
    strncpy(b, orig, (i-orig));
    b += i-orig;
    orig = i+slen;
  }
  strcpy(b, orig);
  return buf;
}


/* this code donated by Altrag */
char *strip_color(const char *orig, const char *strip)
{
  static char buf[MAX_STRING_LENGTH];
  char *i, *b = buf;
  int slen;

  if (!orig || !strip)
  {
/*    log_f("strip_out called with NULL param");  */
    return "!!OUT!!";
  }
  slen = strlen(strip)+1;
  for (i = strstr(orig, strip); i; i = strstr(orig, strip))
  {
    strncpy(b, orig, (i-orig));
    b += i-orig;
    orig = i+slen;
  }
  strcpy(b, orig);
  return buf;
}

bool list_in_list( char * first_list, char * second_list )
{
    char check_word[MAX_INPUT_LENGTH];
    char against_word[MSL];
    char *      checklist;
    char *      againstlist;

      checklist =  first_list ;
      againstlist = second_list;

    for ( ; ; )
    {
      checklist = one_argument( checklist, check_word );
      againstlist = second_list;
      if ( check_word[0] == '\0' )
      {
	 return FALSE;
      }
      for ( ; ; )
      {
        againstlist = one_argument( againstlist, against_word );
        if ( against_word[0] == '\0' )
          break; 
	if ( !str_cmp( check_word, against_word ) )
        {
	  return TRUE;
        }
 
      }
    }
}


/*
 * Return ascii name of an item type.
 */
char *item_type_name( OBJ_DATA *obj )
{
    char log[MAX_STRING_LENGTH];
    
    switch ( obj->item_type )
    {
    case ITEM_LIGHT:            return "light";
    case ITEM_AMMO:             return "ammo";
    case ITEM_BOMB:             return "bomb";
    case ITEM_BLUEPRINT:        return "blueprint";
    case ITEM_SUIT:		return "suit";
    case ITEM_MEDPACK:          return "medpack";
    case ITEM_WEAPON:           return "weapon";
    case ITEM_DRONE:            return "drone";
    case ITEM_ARMOR:            return "armor";
    case ITEM_POTION:           return "potion";
    case ITEM_TELEPORTER:       return "teleporter";
    case ITEM_BOARD:            return "bulletin board";
    case ITEM_INSTALLATION:	return "installation";
    case ITEM_TOKEN:            return "token";
    case ITEM_FLAG:         	return "flag";
    case ITEM_DART_BOARD:	return "dart board";
    case ITEM_CONTAINER:	return "container";
    case ITEM_WEAPON_UP:	return "weapon upgrade";
    case ITEM_PIECE:		return "piece";
    case ITEM_COMPUTER:		return "computer";
    case ITEM_LOCATOR:		return "item locator";
    case ITEM_SKILL_UP:		return "skill upgrade";
    case ITEM_DISK:		return "disk";
    case ITEM_TRASH:		return "trash";
    case ITEM_ASTEROID:		return "asteroid";
    case ITEM_VEHICLE_UP:	return "vehicle addon";
    case ITEM_TOOLKIT:		return "toolkit";
    case ITEM_SCAFFOLD:		return "scaffold";
    case ITEM_ORE:		return "ore";
    case ITEM_BIOTUNNEL:	return "Bio Tunnel";
    case ITEM_BATTERY:		return "battery";
    }

    sprintf( log, "Item_type_name: Object: %d.  Unknown Type: %d",
       obj->pIndexData->vnum, obj->item_type );
    monitor_chan( NULL, log, MONITOR_OBJ ); 
    bug( log, 0 );    
    return "(unknown)";
}

char *item_type_desc( int type )
{
    switch ( type )
    {
    case ITEM_LIGHT:            return "(unknown)";
    case ITEM_AMMO:             return "Ammo can be LOADed into weapons, so they can fire after they run out.";
    case ITEM_BOMB:             return "Bombs are dangerous tools of destruction - Just SET them, ARM them, and RUN AWAY!";
    case ITEM_BLUEPRINT:        return "Blueprints are used to upgrade buildings. They can only upgrade buildings by 1 level at a time.";
    case ITEM_SUIT:		return "Suits are used with the ACTIVATE command, suits can have special functions such as teleportation.";
    case ITEM_MEDPACK:          return "Medpacks are used with the HEAL command, they can cure your wounds when you use them.";
    case ITEM_WEAPON:           return "Weapons are the basic attack items - Wield/wear one, then FIRE or SHOOT at your enemies.";
    case ITEM_DRONE:            return "Just drop them, and they'll do their job. Repair drones, for example, fix damaged buildings.";
    case ITEM_ARMOR:            return "Armor can protect you from hits - Each armor type protects against a different damage type.";
    case ITEM_POTION:		return "Generates a special effect to anyone who drinks it.";
    case ITEM_TELEPORTER:       return "A Teleporter is used to take you back to one of your controlled buildings, in a certain radius.";
    case ITEM_BOARD:            return "Boards are found in players' HQs and Government Centers (alliance boards). You can READ and WRITE messages on them!";
    case ITEM_INSTALLATION:	return "You can INSTALL these into buildings, each giving a different effect.";
    case ITEM_TOKEN:            return "Tokens give players quest points when they are picked up.";
    case ITEM_FLAG:         	return "Flags you get for destroying a player's base. You can save them at the lodge as trophies!";
    case ITEM_DART_BOARD:	return "You can play Darts in a hunting lodge, and this is what you play with.";
    case ITEM_CONTAINER:	return "Containers are what you put elements in before you can mix them.";
    case ITEM_WEAPON_UP:	return "Weapon Upgrades can be WINSTALLed into weapons to give them special effects.";
    case ITEM_PIECE:		return "Piece items can be combined together to create new items.";
    case ITEM_COMPUTER:		return "Computers can be used to upload viruses to enemy buildings and track players down.";
    case ITEM_LOCATOR:		return "An item locator will scan the surroundings for items, letting you know whether you're close to an enemy base.";
    case ITEM_SKILL_UP:		return "Skill Upgrades are used to instantly increase your skill at a certain action.";
    case ITEM_DISK:		return "A disk containing software such as password crackers or viruses.";
    case ITEM_TRASH:		return "Useless junk.";
    case ITEM_ASTEROID:		return "Asteroids can be mined for metals in space, and might hold some hidden items within.";
    case ITEM_VEHICLE_UP:	return "Vehicle addons add special features to vehicles (increased range, scanner, etc).";
    case ITEM_TOOLKIT:		return "Toolkits are used by engineers to upgrade vehicles.";
    case ITEM_SCAFFOLD:		return "Creates the layout for a new building.";
    case ITEM_ORE:		return "Research these to produce new items!";
    case ITEM_BIOTUNNEL:	return "Transport all the items in the room to a receiving tunnel.";
    }

    return "(unknown)";
}


/*
 * Return ascii name of extra flags vector.
 */
char *extra_bit_name( int extra_flags )
{
    static char buf[512];

    buf[0] = '\0';
    if ( extra_flags & ITEM_INVIS        ) safe_strcat( MAX_STRING_LENGTH,  buf, " invis"             );
    if ( extra_flags & ITEM_NODROP       ) safe_strcat( MAX_STRING_LENGTH,  buf, " nodrop"            );
    if ( extra_flags & ITEM_NOREMOVE     ) safe_strcat( MAX_STRING_LENGTH,  buf, " noremove"          );
    if ( extra_flags & ITEM_NOSAVE	     ) safe_strcat( MAX_STRING_LENGTH,  buf, " nosave"            );
    if ( extra_flags & ITEM_RARE         ) safe_strcat( MAX_STRING_LENGTH,  buf, " rare"              );
    if ( extra_flags & ITEM_UNIQUE	     ) safe_strcat( MAX_STRING_LENGTH,  buf, " unique"            );

    return ( buf[0] != '\0' ) ? buf+1 : "none";
}