lurf/area/
lurf/build/testing/
lurf/log/
lurf/player/
lurf/player/backup/
#include <glib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <merc.h>
#include <recycle.h>
#include <fight.h>

long    flag_convert    args( (char letter ) );
int		riddle_max;
int		riddle_number;
struct  riddle_type   riddle_table[MAX_RIDDLE];
int		social_count;
int		xsocial_count;
struct  social_type   social_table[MAX_SOCIALS];
struct  xsocial_type   xsocial_table[MAX_SOCIALS];
char *			help_greeting;
int     thread_count        = 0;
int		    world_affects = 0;	/* World Affect bits		*/
bool		    MOBtrigger = TRUE;    /* act() switch                 */

/*
 * Used Globals
 */
char *			string_space;
char *			top_string;
int			top_mprog_index;
char			str_empty	[1];
char *			string_hash		[MAX_KEY_HASH];
bool			fBootDb;
char			strArea[MAX_INPUT_LENGTH];
FILE *			fpArea;
time_t		    current_time;	/* Time of this pulse		*/
time_t			boot_time;
TIME_INFO_DATA		time_info;
WEATHER_DATA		weather_info[SECT_MAX]; 
FILE *		    fpReserve;		/* Reserved file handle		*/
bool		    god;		/* All new chars are gods!	*/
bool		    merc_down;		/* Shutdown			*/
bool		    wizlock;		/* Game is wizlocked		*/
bool            newlock;            /* Game is newlocked            */
char		    str_boot_time[MAX_INPUT_LENGTH];
char		    crypt_pwd[MAX_INPUT_LENGTH];
HELP_DATA *		help_first;
HELP_DATA *		help_last;
int			top_affect;
int			top_area;
int			top_rt;
int			top_ed;
int			top_exit;
int			top_help;
int			top_mob_index;
int			top_obj_index;
int			top_reset;
int			top_room;
int			top_shop;
int			top_vnum_mob;
int			top_vnum_room;
int			top_vnum_obj;

SHOP_DATA *		shop_first;
SHOP_DATA *		shop_last;
AREA_DATA *		area_first;
AREA_DATA *		area_last;
AREA_DATA *		current_area;
DUMMY_ARG *             dummy_free;
DUMMY_ARG *             dummy_list;

extern CHAR_DATA * 	        char_free;
GSList *				object_free;
GSList *	extra_descr_free;
NOTE_DATA *		note_free;
GSList *		obj_free;
extern PC_DATA *		pcdata_free;
MPROG_CODE *		mprog_list;

char			bug_buf		[2*MAX_INPUT_LENGTH];
CHAR_DATA *		char_list;
char			log_buf		[2*MAX_INPUT_LENGTH];
KILL_DATA		kill_table	[MAX_LEVEL];
GSList			*object_list;

MOB_INDEX_DATA *	mob_index_hash		[MAX_KEY_HASH];
OBJ_INDEX_DATA *	obj_index_hash		[MAX_KEY_HASH];
ROOM_INDEX_DATA *	room_index_hash		[MAX_KEY_HASH];

sh_int			gsn_agg_damage;
sh_int			gsn_backstab;
sh_int			gsn_tail;
sh_int			gsn_hunt;
sh_int			gsn_plague;
sh_int			gsn_hide;
sh_int			gsn_peek;
sh_int			gsn_pick_lock;
sh_int			gsn_sneak;
sh_int			gsn_steal;
sh_int			gsn_weaken;
sh_int			gsn_silent;

sh_int			gsn_disarm;
sh_int			gsn_fastdraw;
sh_int			gsn_berserk;
sh_int			gsn_punch;
sh_int			gsn_stomp;
sh_int			gsn_elbow;
sh_int			gsn_headbutt;
sh_int			gsn_sweep;
sh_int			gsn_knee;
sh_int			gsn_kick;
sh_int			gsn_hurl;
sh_int			gsn_rescue;
sh_int			gsn_track;
sh_int			gsn_polymorph;
sh_int			gsn_web;
sh_int			gsn_arm;
sh_int 			gsn_fear;
sh_int			gsn_blindness;
sh_int			gsn_charm_person;
sh_int			gsn_curse;
sh_int			gsn_invis;
sh_int			gsn_mass_invis;
sh_int			gsn_poison;
sh_int			gsn_sleep;

sh_int			gsn_darkness;
sh_int			gsn_paradox;
sh_int			gsn_bash;
sh_int          gsn_potency;

/*
 * Stick a little fuzz on a number.
 */
int number_fuzzy( int number )
{
	switch ( number_bits( 2 ) )
	{
		case 0:  number -= 1; break;
		case 3:  number += 1; break;
	}
	
	return UMAX( 1, number );
}
bool is_name ( char *str, char *namelist )
{
	char name[MAX_INPUT_LENGTH],part[MAX_INPUT_LENGTH];
	char *list, *string;
	
    /* fix crash on NULL namelist */
	if (namelist == NULL || namelist[0] == '\0')
		return FALSE;
	
    /* fixed to prevent is_name on "" returning TRUE */
	if (str[0] == '\0')
		return FALSE;
	
	string = str;
    /* we need ALL parts of string to match part of namelist */
	for ( ; ; )  /* start parsing string */
	{
		str = one_argument(str,part);
		
		if (part[0] == '\0' )
			return TRUE;
   /* check to see if this is part of namelist */
		list = namelist;
		for ( ; ; )  /* start parsing namelist */
		{
			list = one_argument(list,name);
			
			if (name[0] == '\0')  /* this name was not found */
			{
				return FALSE;
			}
			if (!str_prefix(string,name))
			{
				return TRUE; /* full pattern match */
			}
			if (!str_prefix(part,name))
			{
				break;
			}
		}
	}
	return FALSE;
}
/*
 * 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;
}



/*
 * 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 = '.';
			str_cpy( arg, pdot+1 );
			return number;
		}
	}
	
	str_cpy( arg, argument );
	return 1;
}

bool is_exact_name(char *str, char *namelist )
{
	char name[MAX_INPUT_LENGTH];
	
	if (namelist == NULL)
		return FALSE;
	
	for ( ; ; )
	{
		namelist = one_argument( namelist, name );
		if ( name[0] == '\0' )
			return FALSE;
		if ( !str_cmp( str, name ) )
			return TRUE;
	}
}

/*
 * Str_Dup:
 * This allocates memory for Everything not in the
 * lurkingfear String Hash..
 * we Need to know where it came from first...
 * 
 * we are using Glib string handling now..
 * that will probly make this obsolete.
char *str_dup( const char *str )
{
	return;	
}
 */

/*
 * Free_String: free up memory that was used
 * by str_dup and other memory functions
 * for strings. 
 * 
 * g_lib should already have handlers for this
 * so it should be almost obsolete..

void free_string( char *pstr )
{
	//g_free(pstr);
	return;
}
 */


/*
 * Generate a random number.
 */
int number_range( int from, int to )
{
	int power;
	int number;
	
	if ( ( to = to - from + 1 ) <= 1 )
		return from;
	
	for ( power = 2; power < to; power <<= 1 )
		;
	
	while ( ( number = number_mm( ) & (power - 1) ) >= to )
		;
	
	return from + number;
}



/*
 * Generate a percentile roll.
 */
int number_percent( void )
{
	int percent;
	
	while ( ( percent = number_mm( ) & (128-1) ) > 99 )
		;
	
	return 1 + percent;
}



/*
 * Generate a random door.
 */
int number_door( void )
{
	int door;
	
	while ( ( door = number_mm( ) & (8-1) ) > 5 )
		;
	
	return door;
}



int number_bits( int width )
{
	return number_mm( ) & ( ( 1 << width ) - 1 );
}



/*
 * I've gotten too many bad reports on OS-supplied random number generators.
 * This is the Mitchell-Moore algorithm from Knuth Volume II.
 * Best to leave the constants alone unless you've read Knuth.
 * -- Furey
 */
static	int	rgiState[2+55];

void init_mm( )
{
	int *piState;
	int iState;
	
	piState	= &rgiState[2];
	
	piState[-2]	= 55 - 55;
	piState[-1]	= 55 - 24;
	
	piState[0]	= ((int) current_time) & ((1 << 30) - 1);
	piState[1]	= 1;
	for ( iState = 2; iState < 55; iState++ )
	{
		piState[iState] = (piState[iState-1] + piState[iState-2])
			& ((1 << 30) - 1);
	}
	return;
}



int number_mm( void )
{
	int *piState;
	int iState1;
	int iState2;
	int iRand;
	
	piState		= &rgiState[2];
	iState1	 	= piState[-2];
	iState2	 	= piState[-1];
	iRand	 	= (piState[iState1] + piState[iState2])
		& ((1 << 30) - 1);
	piState[iState1]	= iRand;
	if ( ++iState1 == 55 )
		iState1 = 0;
	if ( ++iState2 == 55 )
		iState2 = 0;
	piState[-2]		= iState1;
	piState[-1]		= iState2;
	return iRand >> 6;
}



/*
 * Roll some dice.
 */
int dice( int number, int size )
{
	int idice;
	int sum;
	
	switch ( size )
	{
		case 0: return 0;
		case 1: return number;
	}
	
	for ( idice = 0, sum = 0; idice < number; idice++ )
		sum += number_range( 1, size );
	
	return sum;
}



/*
 * Simple linear interpolation.
 */
int interpolate( int level, int value_00, int value_32 )
{
	return value_00 + level * (value_32 - value_00) / 32;
}



/*
 * 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_quote( char *str )
{
	for ( ; *str != '\0'; str++ )
	{
		if ( *str == '\'' )
			*str = '-';
		if ( *str == '"' )
			*str = '-';
	}
	
	return;
}

void smash_CRLF( char *str )
{
	for ( ; *str != '\0'; str++ )
	{
		if ( *str == '\n'  )
		{
				*str = '\0';
		}
	}
	
	return;
}


/*
 * Compare strings, case insensitive.
 * Return TRUE if different
 *   (compatibility with historical functions).
 */
bool str_cmp( const char *astr, const char *bstr )
{
	if ( astr == NULL )
	{
		bug( "Str_cmp: null astr.", 0 );
		return TRUE;
	}
	
	if ( bstr == NULL )
	{
		bug( "Str_cmp: null bstr.", 0 );
		return TRUE;
	}
	
	for ( ; *astr || *bstr; astr++, bstr++ )
	{
		if ( LOWER(*astr) != LOWER(*bstr) )
			return TRUE;
	}
	
	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.
 */
char *capitalize( const char *str )
{
	static char strcap[MAX_STRING_LENGTH];
	int i;
	
	for ( i = 0; str[i] != '\0'; i++ )
		strcap[i] = LOWER(str[i]);
	strcap[i] = '\0';
	strcap[0] = UPPER(strcap[0]);
	return strcap;
}

/*
 * Read one word (into static buffer).
 */
char *fread_word( FILE *fp )
{
	static char word[MAX_INPUT_LENGTH];
	char *pword;
	char cEnd;
	
	do
	{
		cEnd = getc( fp );
	}
	while ( isspace( cEnd ) );
	
	if ( cEnd == '\'' || cEnd == '"' )
	{
		pword   = word;
	}
	else
	{
		word[0] = cEnd;
		pword   = word+1;
		cEnd    = ' ';
	}
	
	for ( ; pword < word + MAX_INPUT_LENGTH; pword++ )
	{
		*pword = getc( fp );
		if ( cEnd == ' ' ? isspace(*pword) : *pword == cEnd )
		{
			if ( cEnd == ' ' )
				ungetc( *pword, fp );
			*pword = '\0';
			return word;
		}
	}
	
	bug( "Fread_word: word too long.", 0 );
	if (Player_Load == TRUE)
	{
		Player_Error = TRUE;
		return g_strdup("");
	}
	else
		abort();
	return NULL;
}
/*
 * Read a letter from a file.
 */
char fread_letter( FILE *fp )
{
	char c;
	
	do
	{
		c = getc( fp );
	}
	while ( isspace(c) );
	
	return c;
}



/*
 * Read a number from a file.
 */
int fread_number( FILE *fp )
{
	int number;
	bool sign;
	char c;
	
	do
	{
		c = getc( fp );
	}
	while ( isspace(c) );
	
	number = 0;
	
	sign   = FALSE;
	if ( c == '+' )
	{
		c = getc( fp );
	}
	else if ( c == '-' )
	{
		sign = TRUE;
		c = getc( fp );
	}
	
	if ( !isdigit(c) )
	{
		bug( "Fread_number: bad format.", 0 );
        /* this is changed so damaged pfiles don't crash us - Spiral */
	/* exit( 1 ); */
		return 0;
	}
	
	while ( isdigit(c) )
	{
		number = number * 10 + c - '0';
		c      = getc( fp );
	}
	
	if ( sign )
		number = 0 - number;
	
	if ( c == '|' )
		number += fread_number( fp );
	else if ( c != ' ' )
		ungetc( c, fp );
	
	return number;
}

long fread_flag( FILE *fp)
{
	int number;
	char c;
	bool negative = FALSE;
	
	do
	{
		c = getc(fp);
	}
	while ( isspace(c));
	
	if (c == '-')
	{
		negative = TRUE;
		c = getc(fp);
	}
	
	number = 0;
	
	if (!isdigit(c))
	{
		while (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z'))
		{
			number += flag_convert(c);
			c = getc(fp);
		}
	}
	
	while (isdigit(c))
	{
		number = number * 10 + c - '0';
		c = getc(fp);
	}
	
	if (c == '|')
		number += fread_flag(fp);
	
	else if  ( c != ' ')
		ungetc(c,fp);
	
	if (negative)
		return -1 * number;
	
	return number;
}

long flag_convert(char letter )
{
	long bitsum = 0;
	char i;
	
	if ('A' <= letter && letter <= 'Z') 
	{
		bitsum = 1;
		for (i = letter; i > 'A'; i--)
			bitsum *= 2;
	}
	else if ('a' <= letter && letter <= 'z')
	{
		bitsum = 67108864; /* 2^26 */
		for (i = letter; i > 'a'; i --)
			bitsum *= 2;
	}
	
	return bitsum;
}
/*
 * See if a string is one of the names of an object.
 */

bool is_full_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_cmp( str, name ) )
			return TRUE;
	}
}
/*
 * Pick off one argument from a string and return the rest.
 * Understands quotes.
 */
char *one_argument( char *argument, char *arg_first )
{
	char cEnd;
	
	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;
}

/*
 * Read and allocate space for a string from a file.
 * These strings are read-only and shared.
 * Strings are hashed:
 *   each string prepended with hash pointer to prev string,
 *   hash code is simply the string length.
 * This function takes 40% to 50% of boot-up time.
 */
char *fread_string( FILE *fp )
{
	GString *buffer;
	char *shared_string = NULL;
	char c;
	
    /*
     * Skip blanks.
     * Read first char.
     */
    buffer = g_string_new("");
    do
	{
		c = getc( fp );
	}
	
	while ( isspace(c) );
	
	if ( c  == '~' )
		return &str_empty[0];
	
	ungetc( c, fp );
		
	for ( ;; )
	{
	/*
	 * Back off the char type lookup,
	 *   it was too dirty for portability.
	 *   -- Furey
	 */
		c = getc( fp );
		switch ( c )
		{
			default:
				buffer = g_string_append_c(buffer, c);
				break;
				
			case EOF:
				bug( "Fread_string: EOF", 0 );
				if ( Player_Load == TRUE )
				{
					Player_Error = TRUE;
					return g_strdup("");
				}
				else
					exit( 1 );
				break;
				
			case '\n':
				buffer = g_string_append(buffer, "\n\r");
				break;
				
			case '\r':
				break;
				
			case '~':
				shared_string = g_string_chunk_insert_const(LurfStringChunk,buffer->str);
				g_string_free(buffer,TRUE);
				return shared_string;
				break;
		}
	}
}

/*
 * Non Shared String Version of Fread_string
 * for load players, finger and other temp info.
 */
GString *nonfread_string( GString *string, FILE *fp )
{
	GString *buffer;
	char c;
	
    /*
     * Skip blanks.
     * Read first char.
     */
    buffer = g_string_new("");
    do
	{
		c = getc( fp );
	}
	
	while ( isspace(c) );
	
	if ( c  == '~' )
	{
		string = g_string_assign(string,"");
		return string;
	}
	
	ungetc( c, fp );
		
	for ( ;; )
	{
	/*
	 * Back off the char type lookup,
	 *   it was too dirty for portability.
	 *   -- Furey
	 */
		c = getc( fp );
		switch ( c )
		{
			default:
				buffer = g_string_append_c(buffer, c);
				break;
				
			case EOF:
				bug( "Fread_string: EOF", 0 );
				if ( Player_Load == TRUE )
				{
					Player_Error = TRUE;
					string = g_string_assign(string,"");
					return string;
				}
				else
					exit( 1 );
				break;
				
			case '\n':
				buffer = g_string_append(buffer, "\n\r");
				break;
				
			case '\r':
				break;
				
			case '~':
				string = g_string_assign(string, buffer->str);
				g_string_free(buffer,TRUE);
				return string;
		}
	}
}

/*
 * Read to end of line (for comments).
 */
void fread_to_eol( FILE *fp )
{
	char c;
	
	do
	{
		c = getc( fp );
	}
	while ( c != '\n' && c != '\r' );
	
	do
	{
		c = getc( fp );
	}
	while ( c == '\n' || c == '\r' );
	
	ungetc( c, fp );
	return;
}


/*
 ** str_cpy
 *
 *  FILENAME: C:\lurf\lurfcode\db.c
 *
 *  PARAMETERS:	str, dest
 *
 *  DESCRIPTION: This replaces the str_cpy we widely use, so that
 *				 we can tell if the src is smaller then dest.
 *
 *  RETURNS:
 *
 */

 void str_cpy(char *dest, char *src)
 {
	
	strcpy(dest,src);
	return;
 }


/*
 * Local functions.
 */
void	update_damcap		args( ( CHAR_DATA *ch, CHAR_DATA *victim ) );


/*
 * True if room is dark.
 */
bool room_is_dark( ROOM_INDEX_DATA *pRoomIndex )
{
	if ( pRoomIndex->light > 0 )
		return FALSE;
	
	if ( IS_SET(pRoomIndex->room_flags, ROOM_DARK) )
		return TRUE;
	
	if ( pRoomIndex->sector_type == SECT_INSIDE
		||   pRoomIndex->sector_type == SECT_CITY )
		return FALSE;
	
	if ( weather_info[SECT_CITY].sunlight == SUN_SET
		||   weather_info[SECT_CITY].sunlight == SUN_DARK )
		return TRUE;
	
	return FALSE;
}



/*
 * True if room is private.
 */
bool room_is_private( ROOM_INDEX_DATA *pRoomIndex )
{
	CHAR_DATA *rch;
	int count;
	
	count = 0;
	for ( rch = pRoomIndex->people; rch != NULL; rch = rch->next_in_room )
		count++;
	
	if ( IS_SET(pRoomIndex->room_flags, ROOM_PRIVATE)  && count >= 2 )
		return TRUE;
	
	if ( IS_SET(pRoomIndex->room_flags, ROOM_SOLITARY) && count >= 1 )
		return TRUE;
	
	return FALSE;
}

/*
 * Return ascii name of an affect bit vector.
 */
char *affect_bit_name( int vector )
{
	static char buf[512];
	
	buf[0] = '\0';
	if ( vector & AFF_BLIND         ) strcat( buf, " blind"         );
	if ( vector & AFF_INVISIBLE     ) strcat( buf, " invisible"     );
	if ( vector & AFF_SANCTUARY     ) strcat( buf, " sanctuary"     );
	if ( vector & AFF_FAERIE_FIRE   ) strcat( buf, " faerie_fire"   );
	if ( vector & AFF_CURSE         ) strcat( buf, " curse"         );
	if ( vector & AFF_FLAMING       ) strcat( buf, " flaming"       );
	if ( vector & AFF_POISON        ) strcat( buf, " poison"        );
	if ( vector & AFF_PROTECT       ) strcat( buf, " protect"       );
	if ( vector & AFF_SLEEP         ) strcat( buf, " sleep"         );
	if ( vector & AFF_SNEAK         ) strcat( buf, " sneak"         );
	if ( vector & AFF_HIDE          ) strcat( buf, " hide"          );
	if ( vector & AFF_CHARM         ) strcat( buf, " charm"         );
	if ( vector & AFF_FLYING        ) strcat( buf, " flying"        );
	if ( vector & AFF_PASS_DOOR     ) strcat( buf, " pass_door"     );
	if ( vector & AFF_POLYMORPH     ) strcat( buf, " polymorph"     );
	if ( vector & AFF_WEBBED        ) strcat( buf, " web"           );
	if ( vector & AFF_CONTRACEPTION ) strcat( buf, " contraception" );
	if ( vector & AFF_DARKNESS      ) strcat( buf, " darkness" );
	if ( vector & AFF_PLAGUE        ) strcat( buf, " plague" );
	if ( vector & AFF_FEAR          ) strcat( buf, " fear" );
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}



/*
 * 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_GLOW         ) strcat( buf, " glow"         );
	if ( extra_flags & ITEM_HUM          ) strcat( buf, " hum"          );
	if ( extra_flags & ITEM_INVIS        ) strcat( buf, " invis"        );
	if ( extra_flags & ITEM_MAGIC        ) strcat( buf, " magic"        );
	if ( extra_flags & ITEM_NODROP       ) strcat( buf, " nodrop"       );
	if ( extra_flags & ITEM_ANTI_GOOD    ) strcat( buf, " anti-good"    );
	if ( extra_flags & ITEM_ANTI_EVIL    ) strcat( buf, " anti-evil"    );
	if ( extra_flags & ITEM_ANTI_NEUTRAL ) strcat( buf, " anti-neutral" );
	if ( extra_flags & ITEM_BLESS        ) strcat( buf, " bless"        );
	if ( extra_flags & ITEM_NOREMOVE     ) strcat( buf, " noremove"     );
	if ( extra_flags & ITEM_INVENTORY    ) strcat( buf, " inventory"    );
	if ( extra_flags & ITEM_LOYAL        ) strcat( buf, " loyal"        );
	if ( extra_flags & ITEM_THROWN       ) strcat( buf, " thrown"       );
	if ( extra_flags & ITEM_KEEP         ) strcat( buf, " keep"         );
	if ( extra_flags & ITEM_VANISH       ) strcat( buf, " vanish"       );
	if ( extra_flags & ITEM_FILET        ) strcat( buf, " filet"        );
	if ( extra_flags & ITEM_SHADOWPLANE  ) strcat( buf, " shadowplane"        );
	if ( extra_flags & ITEM_FROZEN       ) strcat( buf, " frozen"        );
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}

char *attack_bit_name( int flag )
{
	
	static char buf[512];
	
	buf[0] = '\0';
	
	if (flag & ATTACK_VAMP) strcat(buf, " vamp");
	if (flag & ATTACK_WWF) strcat(buf, " wwf");
	if (flag & ATTACK_MAGE) strcat(buf, " mage");
	if (flag & ATTACK_CAMARILLA) strcat(buf, " cam");
	if (flag & ATTACK_SABBAT) strcat(buf, " sabbat");
	if (flag & ATTACK_FOLLOWERS) strcat(buf, " followers");
	if (flag & ATTACK_WYRM) strcat(buf, " wyrm");
	if (flag & ATTACK_PACK) strcat(buf, " pack");
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}

char *comm_bit_name( int flag )
{
	
	static char buf[512];
	
	buf[0] = '\0';
	
	if (flag & COMM_SHOW_FIGHT) strcat(buf, " shfgt");
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}

char *act_bit_name( int act_flags )
{
	static char buf[512];
	
	buf[0] = '\0';
	
	if (IS_SET(act_flags,ACT_IS_NPC))
	{ 
		strcat(buf," npc");
		if (act_flags & ACT_SENTINEL 	) strcat(buf, " sentinel");
		if (act_flags & ACT_SCAVENGER	) strcat(buf, " scavenger");
		if (act_flags & ACT_AGGRESSIVE	) strcat(buf, " aggressive");
		if (act_flags & ACT_STAY_AREA	) strcat(buf, " stay_area");
		if (act_flags & ACT_WIMPY	) strcat(buf, " wimpy");
		if (act_flags & ACT_PET	) strcat(buf, " pet");
		if (act_flags & ACT_TRAIN	) strcat(buf, " train");
		if (act_flags & ACT_PRACTICE	) strcat(buf, " practice");
		if (act_flags & ACT_MOUNT	) strcat(buf, " mount");	     
		if (act_flags & ACT_NOPARTS	) strcat(buf, " noparts");     
		if (act_flags & ACT_NOEXP	) strcat(buf, " noexp");     
		if (act_flags & ACT_HOLYLIGHT	) strcat(buf, " holylight");    
		if (act_flags & ACT_PLAYER_KILLER) strcat(buf," plrkill");    
		if (act_flags & ACT_HUNTER	) strcat(buf, " hunter");     
		if (act_flags & ACT_ANIMAL	) strcat(buf, " animal");     
		if (act_flags & ACT_HUMAN 	) strcat(buf, " human");     
		if (act_flags & ACT_GUARD 	) strcat(buf, " guard");     
		if (act_flags & ACT_ELITE 	) strcat(buf, " elite");     
		if (act_flags & ACT_TAPPING	) strcat(buf, " tapping");     
		
	}
	else
	{
		strcat(buf," player");
		if (act_flags & PLR_FREEZE	) strcat(buf, " frozen");
		if (act_flags & PLR_AUTOEXIT	) strcat(buf, " autoexit");
		if (act_flags & PLR_HOLYLIGHT	) strcat(buf, " holylight");
		if (act_flags & PLR_WIZINVIS	) strcat(buf, " wizinvis");
		if (act_flags & PLR_AUTOLOOT	) strcat(buf, " autoloot");
		if (act_flags & PLR_BLANK	) strcat(buf, " blank");
		if (act_flags & PLR_COMBINE	) strcat(buf, " combine");
		if (act_flags & PLR_PROMPT	) strcat(buf, " prompt");
		if (act_flags & PLR_TELNET_GA	) strcat(buf, " telnetga");
		if (act_flags & PLR_ANSI	) strcat(buf, " ansi");
		if (act_flags & PLR_SILENCE	) strcat(buf, " silence");
		if (act_flags & PLR_NO_EMOTE	) strcat(buf, " no_emote");
		if (act_flags & PLR_INCOG	) strcat(buf, " incog");
		if (act_flags & PLR_NO_TELL	) strcat(buf, " notell");
		if (act_flags & PLR_LOG	) strcat(buf, " log");
		if (act_flags & PLR_DENY	) strcat(buf, " deny");
		if (act_flags & PLR_GODLESS	) strcat(buf, " godless");
		if (act_flags & PLR_WATCHER	) strcat(buf, " watcher");
		if (act_flags & PLR_PERMIT	) strcat(buf, " permit");
		if (act_flags & PLR_AUTODAMAGE	) strcat(buf, " autodamage");
		if (act_flags & PLR_MARBLEFLESH	) strcat(buf, " marbleflesh");
		if (act_flags & PLR_TAG		) strcat(buf, " tag");
	}
	
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}


char *added_bit_name( int vector)
{
	static char buf[512];
	
	buf[0] = '\0';
	if ( vector & ADDED_ENLARGE     ) strcat( buf, " enlarge"         );
	if ( vector & ADDED_SHRINK      ) strcat( buf, " shrink"     );
	if ( vector & ADDED_FLAMES_PURE ) strcat( buf, " flamespure"    );
	if ( vector & ADDED_POLY_MIST   ) strcat( buf, " polymist"     );
	if ( vector & ADDED_POLY_GENERAL ) strcat( buf, " polygen"     );
	if ( vector & ADDED_CLOAK       ) strcat( buf, " cloak"     );
	if ( vector & ADDED_NIGHTFALL   ) strcat( buf, " nightfall"     );
	if ( vector & ADDED_HAUNT   ) strcat( buf, " haunt"     );
	if ( vector & ADDED_CONFUSE   ) strcat( buf, " confuse"     );
	if ( vector & ADDED_INSANE   ) strcat( buf, " insane"     );
	if ( vector & ADDED_CALM     ) strcat( buf, " calm"     );
	if ( vector & ADDED_ANGER   ) strcat( buf, " anger"     );
	if ( vector & ADDED_COURAGE   ) strcat( buf, " courage"     );
	if ( vector & ADDED_BRISTLES   ) strcat( buf, " bristles"     );
	if ( vector & ADDED_FLAMES   ) strcat( buf, " flames"     );
	if ( vector & ADDED_ANIMAL_MASTER   ) strcat( buf, " animalmaster"     );
	if ( vector & ADDED_ILLUSION   ) strcat( buf, " illusion"     );
	if ( vector & ADDED_LOYAL   ) strcat( buf, " loyal"     );
	if ( vector & ADDED_HAND_FLAME   ) strcat( buf, " handlflame"     );
	if ( vector & ADDED_FRENZY   ) strcat( buf, " frenzy"     );
	if ( vector & ADDED_DIABLERIE   ) strcat( buf, " diablerie"     );
	if ( vector & ADDED_HARDCORE   ) strcat( buf, " hardcore"     );
	
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}

char *fight_bit_name( int vector)
{
	static char buf[512];
	
	buf[0] = '\0';
	if ( vector & FIGHT_VIPER ) strcat( buf, " viper"	);
	if ( vector & FIGHT_CRANE ) strcat( buf, " crane"	);
	if ( vector & FIGHT_MONGOOSE ) strcat( buf, " moongoose");
	if ( vector & FIGHT_BULL ) strcat( buf, " bull"		);
	if ( vector & FIGHT_CRAB ) strcat( buf, " crab"		);
	if ( vector & FIGHT_MANTIS ) strcat( buf, " mantis"	);
	if ( vector & FIGHT_TIGER ) strcat( buf, " tiger"	);
	if ( vector & FIGHT_DRAGON ) strcat( buf, " dragon"	);
	if ( vector & FIGHT_MONKEY ) strcat( buf, " monkey"	);
	if ( vector & FIGHT_SWALLOW ) strcat( buf, " swallow"	);
	if ( vector & FIGHT_RANDOM ) strcat( buf, " random"	);
	if ( vector & FIGHT_MASTER ) strcat( buf, " master"	);
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}



char *spaffect_bit_name( int vector)
{
	static char buf[512];
	
	buf[0] = '\0';
	if ( vector & AFSPHERE_ENTROPY_SHIELD     ) strcat( buf, " entropy_shield"	);
	if ( vector & AFSPHERE_MIND_SHIELD  	  ) strcat( buf, " mind_shield"         );
	if ( vector & AFSPHERE_FORCES_SHIELD 	  ) strcat( buf, " forces_shield"       );
	if ( vector & AFSPHERE_PRIME_SHIELD       ) strcat( buf, " prime_shield"        );
	if ( vector & AFSPHERE_LIFE_SHIELD        ) strcat( buf, " life_shield"         );
	if ( vector & AFSPHERE_SPIRIT_SHIELD      ) strcat( buf, " spirit_shield"       );
	if ( vector & AFSPHERE_SHIELD             ) strcat( buf, " shield"     );
	if ( vector & AFSPHERE_MANA_SHIELD        ) strcat( buf, " mana_shield"     );
	if ( vector & AFSPHERE_SLOW_TIME          ) strcat( buf, " slow_time"     );
	if ( vector & AFSPHERE_SPEED_TIME         ) strcat( buf, " speed_time"     );
	if ( vector & AFSPHERE_TAINTED            ) strcat( buf, " tainted"     );
	if ( vector & AFSPHERE_REGEN	          ) strcat( buf, " regen"     );
	if ( vector & AFSPHERE_SQUARE_CIRCLE      ) strcat( buf, " squarecircle"     );
	
	return ( buf[0] != '\0' ) ? buf+1 : (char *)"none";
}

bool hates_players( CHAR_DATA *ch, CHAR_DATA *victim )
{
	/*  simple check to see if the mobile(ELITE) 
         *  reconises the player as a wwf or vampire
	 *  we give a shit about mages and thie magiks
         */
	
	if (ch->plane != victim->plane)
		return FALSE;
	if (!IS_NPC(ch))
		return FALSE; 
	if (IS_NPC(victim))
		return FALSE;
	if ( ch->fighting != NULL )
		return FALSE;
	if (is_tempsafe(victim))
		return FALSE;
	if (!can_see(ch,victim))
		return FALSE;
	if (IS_SET(ch->act, ACT_GUARD) && victim->blood_count > 0 )
		return TRUE;
	if ( !IS_SET(ch->act,ACT_ELITE))
		return FALSE;
	if (IS_VAMPAFF(victim,VAM_FANGS))
		return TRUE;
	if (IS_VAMPAFF(victim,VAM_CLAWS))
		return TRUE;
	if (victim->pcdata->stats[UNI_RAGE] > 100 )
		return TRUE;
	return FALSE;
}

bool is_same_plane(CHAR_DATA *ch, CHAR_DATA *victim)
{
	if (ch->plane != victim->plane)
		return FALSE;
	else
		return TRUE;
}

void strip_player( CHAR_DATA *ch )
{
	OBJ_DATA *obj,*obj_next;
	
	for ( obj = ch->carrying; obj != NULL; obj = obj_next )
	{
		obj_next = obj->next_content;
		if ( obj->wear_loc != WEAR_NONE ) 
		{
			obj_from_char(obj); 
			obj_to_char(obj,ch);
		}
	}
		
}


 /* returns a flag for wiznet */
long wiznet_lookup (const char *name)
{
    int flag;

    for (flag = 0; wiznet_table[flag].name != NULL; flag++)
    {
	if (LOWER(name[0]) == LOWER(wiznet_table[flag].name[0])
	&& !str_prefix(name,wiznet_table[flag].name))
	    return flag;
    }

    return -1;
}

int check_follower_count (CHAR_DATA *ch)
{
    int fCount = 0;
    CHAR_DATA *wch;

    for (wch = char_list; wch != NULL; wch = wch->next)
    {
        if (!strcmp(wch->lord->str,ch->name->str))
            fCount++;
    }

    return fCount;
}

/*
 * This function is here to aid in debugging.
 * If the last expression in a function is another function call,
 *   gcc likes to generate a JMP instead of a CALL.
 * This is called "tail chaining."
 * It hoses the debugger call stack for that call.
 * So I make this the last call in certain critical functions,
 *   where I really need the call stack to be right for debugging!
 *
 * If you don't understand this, then LEAVE IT ALONE.
 * Don't remove any calls to tail_chain anywhere.
 *
 * -- Furey
 */
void tail_chain( void )
{
	return;
}