/
mudd/docs/html/
mudd/world/
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "mud.h"
AFFECT_DATA *affect_free = NULL;
RESET_DATA *reset_free = NULL;
int total_fgt = 0;
void affect_modify (CHAR_DATA * ch, AFFECT_DATA * paf, bool fAdd, short flaggy);
extern char *ans_uppercase (const char *txt);

FGT *
new_fgt (void)
{
  FGT *f;
  int i;
  total_fgt++;
  f = mem_alloc (sizeof (*f));
  f->ears = 2;
  f->combat_delay_count = -1;
  for (i = 0; i < 4; i++)
    f->attackers[i] = 0;
  f->compliance = 25;
  f->master = NULL;
  f->leader = NULL;
  f->pulling = NULL;
  f->riding = NULL;
  f->mounted_by = NULL;
  f->hunting = NULL;
  f->attackers[0] = NULL;
  f->attackers[1] = NULL;
  f->attackers[2] = NULL;
  f->attackers[3] = NULL;
  f->fighting = NULL;
  
  return f;
}

void 
clear_fgt (CHAR_DATA * ch)
{
  if (ch->fgt)
    {
      if (ch->fgt->hunting)
	free_string (ch->fgt->hunting);
    }
  if (ch->fgt)
    {
      free (ch->fgt);
      total_fgt--;
    }
  ch->fgt = NULL;
  return;
}

void 
check_fgt (CHAR_DATA * ch)
{
  if (!ch->fgt)
    ch->fgt = new_fgt ();
  return;
}

void 
do_coins (CHAR_DATA * ch, char *argy)
{
  int coinage;
  DEFINE_COMMAND ("coins", do_coins, POSITION_DEAD, IMM_LEVEL, LOG_ALWAYS, "Creates the specified amount of coins.")

    if (!is_number (argy) || argy[0] == '\0')
    {
      return;
    }
  coinage = atoi (argy);
  if (coinage > 0 && coinage < 1000000)
    create_amount (coinage, ch, NULL, NULL);
  return;
}

void 
no_spam (CHAR_DATA * ch, char *argy)
{
  DEFINE_COMMAND ("nospam", no_spam, POSITION_DEAD, 0, LOG_NORMAL, "Toggles between levels of spam.")

    if (IS_PLAYER (ch))
    {
      ch->pcdata->no_spam = 1;
      send_to_char ("NoSpam mode ENABLED.\n\r", ch);
      send_to_char ("NOTE: You can toggle through the modes using the SPAM command.\n\r", ch);
    }
  return;
}

void 
add_to_aggro_list (CHAR_DATA * ch)
{
  CHAR_DATA *c;
  if (IS_SET (ch->special, IS_IN_AGGRO_LIST) || !IS_SET(ch->act, ACT_AGGRESSIVE | ACT_ANGRY) || ch->in_room->pcs == 0)
    return;
  for (c = aggro_check; c != NULL; c = c->gen_next)
    {
      if (c == ch)
	return;
    }
  ch->gen_next = aggro_check;
  aggro_check = ch;
  SET_BIT (ch->special, IS_IN_AGGRO_LIST);
  return;
}



void 
spam (CHAR_DATA * ch, char *argy)
{
  DEFINE_COMMAND ("spam", spam, POSITION_DEAD, 0, LOG_NORMAL, "Turns on nospam mode.")
    if (IS_MOB (ch))
    return;
  if (ch->pcdata->no_spam == 0)
    {
      send_to_char ("Moderate SPAM mode enabled.\n\r", ch);
      ch->pcdata->no_spam = 2;
      return;
    }
  else if (ch->pcdata->no_spam == 1)
    {
      send_to_char ("FULL SPAM mode enabled.\n\r", ch);
      ch->pcdata->no_spam = 0;
      return;
    }
  else
    send_to_char ("NO SPAM mode enabled.\n\r", ch);
  ch->pcdata->no_spam = 1;
  return;
}

int 
get_race_look (char *argy)
{
  int i;
  if (!str_cmp(argy, "enemy"))
    return 100;
  for (i = 0; i < RACE_COUNT; i++)
    {
      if (!str_prefix (argy, race_info[i].name))
	return i;
    }
  
  for (i = 0; i <NUM_ALIGN; i++)
    {
      if (!str_prefix(argy, align_info[i].name))
	return i+50;
    }
  return -1;
}

/*
   * Retrieve a character's age.
 */
int 
get_age (CHAR_DATA * ch)
{
  return 18 + (((ch->pcdata->played / 2) + (((int) (current_time - ch->pcdata->logon)) / 2)) / 7200) / 4;
}

/* These 5 functions return the character's current stats. */



int 
get_stat (CHAR_DATA *ch, int num)
{
  if (IS_MOB(ch)) return 32;
  return URANGE (3, (ch->pcdata->stat[num] + UMIN(2, ch->pcdata->stat_mod[num])), 32);
}


int 
get_curr_str (CHAR_DATA * ch)
{
  return get_stat (ch, STR);
}

int 
get_curr_int (CHAR_DATA * ch)
{
  return get_stat (ch, INT); 
}

int 
get_curr_dex (CHAR_DATA * ch)
{
   return get_stat (ch, DEX);
}

int 
get_curr_wis (CHAR_DATA * ch)
{
  return get_stat (ch, WIS);
}

int 
get_curr_con (CHAR_DATA * ch)
{
  return get_stat (ch, CON);
}

bool 
is_name (const char *str, char *namelist)
{
  char name[SML_LENGTH];
  if (!str_cmp (str, namelist))
    return TRUE;
  for (;;)
    {
      if (namelist == NULL)
	return FALSE;
      if (!str_cmp(str,namelist)) return TRUE;
      namelist = one_argy (namelist, name);
      if (name[0] == '\0')
	return FALSE;
      if (!str_cmp (str, name))
	return TRUE;
    }
  return FALSE;
}


bool 
is_approx_name (const char *str, char *namelist)
{
  char name[SML_LENGTH];
  if (!str_cmp (str, namelist))
    return TRUE;
  for (;;)
    {
      if (namelist == NULL)
	return FALSE;
      namelist = one_argy (namelist, name);
      if (name[0] == '\0')
	return FALSE;
      if (!str_cmp (str, name))
	return TRUE;
      if (strlen (str) > 1 && !str_prefix (str, name))
	return TRUE;
    }
  return FALSE;
}



void 
affect_modify (CHAR_DATA * ch, AFFECT_DATA * paf, bool fAdd, short flagg)
{
  int mod, i;
  mod = paf->modifier;
  if (fAdd)
    {
      for (i = 0; i < 4; i++)
	SET_BIT(ch->aff[i], paf->aff[i]);
    }
  else
    {
      for (i = 0; i < 4; i++)
	REMOVE_BIT(ch->aff[i], paf->aff[i]);
      mod = 0 - mod;
    }
  if(IS_PLAYER(ch))
    {
      switch (paf->location)
	{
	default:
	  bug ("Affect_modify: unknown location %d.", paf->location);
	  return;
	case APPLY_NONE:
	  break;
	case APPLY_STR:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[STR] += mod;
	  break;
	case APPLY_DEX:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[DEX] += mod;
	  break;
	case APPLY_INT:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[INT] += mod;
	  break;
	case APPLY_WIS:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[WIS] += mod;
	  break;
	case APPLY_CON:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[CON] += mod;
	  break;
	case APPLY_LCK:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[LCK] += mod;
	  break;
	case APPLY_WIL:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[WIL] += mod;
	  break;
	 case APPLY_CHA:
	  if (flagg != 1)
	    ch->pcdata->stat_mod[CHA] += mod;
	  break;
	case APPLY_RANDOM_STAT:
	  if (flagg != 1)
	    {
	      paf->location = number_range(1,NUM_STATS);
	      ch->pcdata->stat_mod[paf->location-1] += mod;
	    }
	  break; 
	case APPLY_MANA:
	  ch->pcdata->n_max_mana += mod;
	  break;
	case APPLY_HIT:
	  if (flagg != 1)
	    ch->max_hit += mod;
	  break;
	case APPLY_MOVE:
	  if (flagg != 1)
	    ch->max_move += mod;
	  break;
	case APPLY_AC:
	  ch->armor += mod;
	  break;
	case APPLY_HITROLL:
	  ch->hitroll += mod;
	  break;
	case APPLY_DAMROLL:
	  ch->damroll += mod;
	  break;
	case APPLY_SAVING_THROW:
	  ch->pcdata->saving_throw += mod;
	  break;
	case APPLY_KICK_DAMAGE:
	  ch->pcdata->plus_kick += mod;
	  break;
	case APPLY_SNEAK:
	  ch->pcdata->plus_sneak += mod;
	  break;
	case APPLY_WARMTH:
	  ch->pcdata->warmth += mod;
	  break;  
	case APPLY_HIDE:
	  ch->pcdata->plus_hide += mod;
	  break;
	}
    }
  if (IS_PLAYER (ch))
    {
      int i;
      for (i = 0; i < 4; i++)
	{
	  ch->aff[i] |= ch->pcdata->nat_aff[i];
	  ch->aff[i] |= race_info[ch->pcdata->race].aff[i];
	  ch->aff[i] |= align_info[ch->pcdata->alignment].aff[i];
	}
      
    }
  
  return;
}


void 
affect_to_char (CHAR_DATA * ch, AFFECT_DATA * paf)
{
  AFFECT_DATA *paf_new;
  long hurts = (paf->aff[HURT] &~(ch->aff[PROT]));

  /* In other words, hurts is all of the affect bits which are on the 
     affect, and which the character does not have a resistance to. 
     This seems to bea lot cleaner than the old stuff.
     If the character is resistant to all the affects and there were
     harmful affects, then the spell does not take affect. This is different
     than the old style where if you resist any part of the spell then
     you resist it all. This seems to make more sense. */


  if (IS_MOB(ch)) /* Guarding mobs cannot be blinded to stop twinks :) */
    {
      if(ch->pIndexData->guard != NULL &&
	 (IS_SET(paf->aff[HURT], BLIND)))
	return;
    }
  /* This says if the spell had bad affects and you resisted them 
     all, the spell does not take affect. It also requires the other
     affects to not take place...so if you make a powerful affect have
     a bad side affect (like TP and maybe poison or something) you can
     still get the TP even if you resist the poison. */

  if (paf->aff[HURT] && !hurts && !paf->aff[PROT] && !paf->aff[AFF] &&
      !paf->aff[DET])
    {
      send_to_char("You are immune! you resist the effect!\n\r", ch);
      return;
    }
  
  
  if (affect_free == NULL)
    paf_new = mem_alloc (sizeof (*paf_new));
  else
    {
      paf_new = affect_free;
      affect_free = affect_free->next;
    }
  *paf_new = *paf;

  /* You change paf_new->aff[HURT] to remove the resisted bits.
     People will not like this. */
  
  paf_new->aff[HURT] = hurts;
  paf_new->next = ch->affected;
  ch->affected = paf_new;
  affect_modify (ch, paf_new, TRUE, 0);
  return;
}


void 
affect_remove (CHAR_DATA * ch, AFFECT_DATA * paf)
{
  if (ch->affected == NULL)
    {
      bug ("Affect_remove: no affect.", 0);
      return;
    }
  affect_modify (ch, paf, FALSE, 0);
  if (paf == ch->affected)
    {
      ch->affected = paf->next;
    }
  else
    {
      AFFECT_DATA *prev;
      for (prev = ch->affected; prev != NULL; prev = (!prev->next ? NULL : prev->next))
	{
	  if (prev->next == paf)
	    {
	      prev->next = paf->next;
	      break;
	    }
	}
      if (prev == NULL)
	{
	  bug ("Affect_remove: can't find paf.", 0);
	  return;
	}
    }
  paf->next = affect_free;
  affect_free = paf->next;
  return;
}

void 
strip_all_affects (CHAR_DATA * ch)
{
  AFFECT_DATA *paf;
  AFFECT_DATA *paf_next;
  int i;
  for (paf = ch->affected; paf != NULL; paf = paf_next)
    {
      paf_next = paf->next;
      affect_remove (ch, paf);
    }
  for (i = 0; i < 4; i++)
    ch->aff[i] = 0;
  if (IS_PLAYER (ch))
    {
      for (i = 0; i < 4; i++)
	{
	  ch->aff[i] |= ch->pcdata->nat_aff[i];
	  ch->aff[i] |= race_info[ch->pcdata->race].aff[i];
	  ch->aff[i] |= align_info[ch->pcdata->alignment].aff[i];
	}
      FIXIT (ch)
	}
  return;
}

void 
affect_strip_bits (CHAR_DATA * ch, int type, int bits)
{
  AFFECT_DATA *paf;
  AFFECT_DATA *paf_next;
  int i;

  /* Two types of affect removes...first is for removing all affects
     from a spell that removes bits. when type == -1 the bits
     are the spell->gsn instead of the bits..otherwise you send
     the type of affect: HURT PROT AFF DET and then remove the bits. */
  
  if (type == -1) 
    {
      SPELL_DATA *spl;
      if ((spl = skill_lookup(NULL, bits)) == NULL)
	return;
      for (paf = ch->affected; paf != NULL; paf = paf_next)
	{
	  if (!paf->next)
	    paf_next = NULL;
	  else
	    paf_next = paf->next;
	  for (i = 0; i < 4; i ++)
	    {
	      if (IS_SET(paf->aff[i], spl->aff[i]))
		{
		  affect_remove(ch, paf);
		  break;
		}
	    }
	}
    }
  else if (type >= 0 && type < 4)
    {
      for (paf = ch->affected; paf != NULL; paf = paf_next)
	{
	  if (!paf->next)
	    paf_next = NULL;
	  else
	    paf_next = paf->next;
	  if (IS_SET (paf->aff[type], bits))
	    affect_remove (ch, paf);
	}
    }
  if (IS_PLAYER (ch))
    {
      for (i = 0; i < 4; i++)
	{
	  ch->aff[i] |= ch->pcdata->nat_aff[i];
	  ch->aff[i] |= race_info[ch->pcdata->race].aff[i];
	  ch->aff[i] |= align_info[ch->pcdata->alignment].aff[i];
	}
      FIXIT(ch)
    }
  return;
}

void 
affect_strip (CHAR_DATA * ch, int sn)
{
  AFFECT_DATA *paf;
  AFFECT_DATA *paf_next;
  if (sn < 0)
    return;
  for (paf = ch->affected; paf != NULL; paf = paf_next)
    {
      if (!paf->next)
	paf_next = NULL;
      else
	paf_next = paf->next;
      if (paf->type == sn)
	affect_remove (ch, paf);
    }
  if (IS_PLAYER (ch))
    {
      int i;
      for (i = 0; i < 4; i++)
	{
	  ch->aff[i] |= ch->pcdata->nat_aff[i];
	  ch->aff[i] |= race_info[ch->pcdata->race].aff[i];
	  ch->aff[i] |= align_info[ch->pcdata->alignment].aff[i];
	}
      FIXIT(ch)
    }
  return;
}



void 
affect_join (CHAR_DATA * ch, AFFECT_DATA * paf)
{
  AFFECT_DATA *paf_old;
  bool found;
  if (paf->type < 0)
    return;
  if (IS_PLAYER (ch) && (IN_BATTLE (ch) || CHALLENGE (ch) == ARENA_FIGHTING))
    return;
  found = FALSE;
  for (paf_old = ch->affected; paf_old != NULL; paf_old = paf_old->next)
    {
      if (paf_old->type == paf->type && paf_old->location == paf->location)
	{
	  paf->duration += paf_old->duration;
	  paf->modifier += paf_old->modifier;
	  affect_remove (ch, paf_old);
	}
    }
  affect_to_char (ch, paf);
  return;
}

void 
remove_from_fighting_list (CHAR_DATA * ch)
{
  CHAR_DATA *c;
  if (IS_SET (ch->special, IS_IN_FIGHTING_LIST))
    REMOVE_BIT (ch->special, IS_IN_FIGHTING_LIST);

  if (ch == f_first)
    {
      f_first = ch->next_fighting;
      ch->next_fighting = NULL;
      return;
    }
  for (c = f_first; c != NULL; c = c->next_fighting)
    {
      if (c->next_fighting == ch)
	{
	  c->next_fighting = ch->next_fighting;
	  ch->next_fighting = NULL;
	  return;
	}
    }

  return;
}


void 
add_to_fighting_list (CHAR_DATA * ch)
{
  CHAR_DATA *c;
  CHAR_DATA *cn;
  if (IS_SET (ch->special, IS_IN_FIGHTING_LIST))
    return;
  for (c = f_first; c != NULL; c = cn)
    {
      cn = c->next_fighting;
      if (c == ch)
	{
	  fprintf (stderr, "Found %s already in fighting list without bit set!\n", NAME (c));
	  return;
	}
    }
  ch->next_fighting = f_first;
  f_first = ch;
  SET_BIT (ch->special, IS_IN_FIGHTING_LIST);
  return;
}

void 
remove_from_aggro_list (CHAR_DATA * ch)
{
  CHAR_DATA *c;
  if (IS_SET (ch->special, IS_IN_AGGRO_LIST))
    {
      REMOVE_BIT (ch->special, IS_IN_AGGRO_LIST);
    }
  if (ch == aggro_check)
    {
      aggro_check = ch->gen_next;
      ch->gen_next = NULL;
    }
  else
    for (c = aggro_check; c != NULL; c = c->gen_next)
      {
	if (ch == c->gen_next)
	  {
	    c->gen_next = ch->gen_next;
	    ch->gen_next = NULL;
	    return;
	  }
      }
  return;
}

void 
char_from_room (CHAR_DATA * ch)
{
  CHAR_DATA *pir;
  int kk = 0;
  if (!ch || ch->in_room == NULL)
    {
      return;
    }
  if (ch->fgt && ch->fgt->pulling)
    {
      send_to_char ("You stop pulling your load.\n\r", ch);
      ch->fgt->pulling = NULL;
    }

  if (IS_PLAYER(ch))
    {
      ch->in_room->light -= ch->pcdata->light;
      
      ch->in_room->area->nplayer--;
      ch->in_room->pcs--;
    }
  else
    {
      if (IS_SET(ch->pIndexData->act4, ACT4_COMMANDSCRIPT))
	ch->in_room->command_objs--;
      if (ch->in_room->command_objs < 0)
	ch->in_room->command_objs = 0;
    }
  if (ch == ch->in_room->people)
    {
      ch->in_room->people = ch->next_in_room;
    }
  else
    {
      CHAR_DATA *prev;
      for (prev = ch->in_room->people; prev; prev = prev->next_in_room)
	{
	  if (prev->next_in_room == ch)
	    {
	      prev->next_in_room = ch->next_in_room;
	      break;
	    }
	}
      if (prev == NULL)
	{
          bug( "Char_from_room: ch not found.", 0 );
	  ch->in_room = NULL;
	  ch->next_in_room = NULL;
	  return;
	}
    }
  if (IS_MOB (ch) && ch->in_room->pcs == 0)
    remove_from_aggro_list (ch);
  if (IS_PLAYER (ch))
    {
      for (pir = ch->in_room->people; pir != NULL; pir = pir->next_in_room)
	{
	  if (ch->in_room->pcs == 0)
	    {
	      remove_from_aggro_list (pir);
	    }
	  if (IS_MOB (pir) && IS_HURT (pir,CHARM) && MASTER (pir) == ch)
	    {
	      while (ch->pcdata->pet_temp[kk] != 0)
		kk++;
	      ch->pcdata->pet_temp[kk] = pir->pIndexData->vnum;
	      ch->pcdata->pet_hps[kk] = pir->hit;
	      ch->pcdata->pet_move[kk] = pir->move;
	    }
	}
    }
  if (FIGHTING(ch)) 
    {
      CHAR_DATA *vch;
      int i;
      
      for (i = 0; i < TOTAL_LIST; i++)
	{
	  for (vch=char_list[i]; vch!=NULL; vch=vch->next) 
	    {
	      if (FIGHTING(vch)==ch) 
		{
		  vch->fgt->fighting=NULL;
		  vch->position=POSITION_STANDING;
		}
	    }
	  ch->fgt->fighting=NULL;
	  ch->position=POSITION_STANDING;
	}
    }
  ch->in_room = NULL;
  ch->next_in_room = NULL;
  return;
}

void 
check_stats (CHAR_DATA * ch)
{
  int i;
  if (IS_MOB(ch)) 
    return;
  for (i = 0; i < NUM_STATS; i++)
    {
      if (ch->pcdata->stat[i] >  race_info[ch->pcdata->race].limits[i])
	ch->pcdata->stat[i] = race_info[ch->pcdata->race].limits[i];
    }
  return;
}


void 
remove_char_from_list (CHAR_DATA *ch)
{
  if (!ch || ch->list == TOTAL_LIST + 1)
    return;
  if (ch == char_list[ch->list])
    {
      char_list[ch->list] = ch->next;
      if (char_list[ch->list])
	char_list[ch->list]->prev = NULL;
    }
  else 
    {
      if (ch->prev && ch->next)
	{
	  ch->prev->next = ch->next;
	  ch->next->prev = ch->prev;
	}
      else if (ch->prev)
	{
	  ch->prev->next = ch->next;
	}
      else if (ch->next)
	{
	  fprintf (stderr, "Error removing mob from list with no prev!\n");
	}
    }
  ch->next = NULL;
  ch->prev = NULL;
  ch->list = TOTAL_LIST + 1;
  return;
}

void
add_char_to_list (CHAR_DATA *ch)
{
  if (!ch)
    return;
  
  if (ch->list != TOTAL_LIST + 1)
    {
      remove_char_from_list (ch);
    }
  
  ch->list = (IS_PLAYER (ch) ? PLAYER_LIST : 
	      (ch->in_room ?
	       (ch->in_room->area->nplayer > 0 ?
		(ch->pIndexData->vnum % MOB_LIST) : MOB_LIST) : TOTAL_LIST));
  ch->prev = NULL;
  if (char_list[ch->list])
    char_list[ch->list]->prev = ch;
  ch->next = char_list[ch->list];
  char_list[ch->list] = ch;
  return;
}

void
char_to_room (CHAR_DATA * ch, ROOM_DATA * oneroom)
{
  bool neww;
  neww = FALSE;
  if (!oneroom) oneroom = get_room_index(2);
  if ((IS_SET(oneroom->room_flags,ROOM_INDOORS | ROOM_UNDERGROUND) ||
       (oneroom->sector_type >= SECT_CAVE)) &&
      IS_AFF(ch, FLYING) && (ch->height > INDOOR_FLY_HEIGHT)) 
    {
      
      send_to_char("You cannot fly while indoors.\n\r",ch);
      do_land(ch,"");
    }
  
  if (ch->in_room)
    {
      char_from_room (ch);
    }
  if (oneroom->area && IS_PLAYER (ch) && IS_OPEN (oneroom->area)  && (ch->pcdata->level > 100 && ch->pcdata->level < 105))
    {
      send_to_char ("You have no reasons to be in an open area...\n\r", ch);
      send_to_char ("If you are a god, you may check out characters using the snoop\n\r", ch);
      send_to_char ("command. Please stay in your zone or another closed area.\n\r", ch);
      
      if (LEVEL(ch)<100) oneroom = get_room_index (3); else
	oneroom = get_room_index (2);
    }
  else 
    {
      if (oneroom->area && !IS_OPEN (oneroom->area) && IS_PLAYER (ch) && ch->pcdata->level < 101)
	{
	  send_to_char ("You may not go to unopened areas. Sorry!\n\r", ch);
	  
	  oneroom = get_room_index (3);
	}
    }
  
  if (IS_PLAYER (ch) && !IS_SET (ch->act, PLR_HOLYWALK))
    {
      
      if (oneroom->vnum >= 100 && oneroom->vnum < (NUM_ALIGN-1+100)) 
	{
	  DESCRIPTION_DATA *ded;
	  char *cp;
	  char kw[500];
	  char argo[SML_LENGTH];
	  FIXIT(ch);
	  fix_char(ch);
          natural_mana (ch);
	  
	  for (ded = oneroom->extra_descr; ded != NULL; ded =
		 ded->next)
	    {
	      if (!ded->keyword || ded->keyword[0] == '\0')
		continue;
	      strcpy (kw, ded->keyword);
	      cp = one_argy (kw, argo);
	      if (is_number (argo) && is_number (cp))
		{
		  int racenum;
		  int roomvn;
		  ROOM_DATA *nr;
		  racenum = atoi (argo);
		  roomvn = atoi (cp);
		  if (racenum >= 0 && racenum <= RACE_COUNT &&
		      racenum == ch->pcdata->race && (nr = get_room_index (roomvn)) != NULL && (nr->vnum < 100 && nr->vnum > (100+NUM_ALIGN-1)))
		    {
		      char_to_room (ch, nr);
		      return;
		    }
		}
	    }
	}
    }
  
  if (IS_PLAYER (ch) && ch->in_room)
    {
      CHAR_DATA *d;
      
      for (d = ch->in_room->people; d != NULL; d = d->next_in_room)
	{
	  if (IS_MOB (d))
	    {
	      add_to_aggro_list (d);
	    }
	  if (d == ch)
	    {
	      ch->in_room = oneroom;
	      return;
	    }
	}
    }
  
  if (IS_PLAYER (ch) && oneroom)
    {
      CHAR_DATA *d;
      
      for (d = oneroom->people; d != NULL; d = d->next_in_room)
	{
	  if (IS_MOB (d))
	    add_to_aggro_list (d);
	  if (d == ch)
	    {
	      fprintf (stderr, "UGH!\n");
	      ch->in_room = oneroom;
	      return;
	    }
	}
    }
  if (oneroom == NULL)
    {
      bug ("Char_to_room: NULL.", 0);
      return;
    }
  
  ch->in_room = oneroom;
  
  if (IS_PLAYER (ch))
    {
      int kk;
      if (pet_flag)
	for (kk = 0; kk < 20; kk++)
	  ch->pcdata->pet_temp[kk] = 0;
      ch->in_room->area->nplayer++;
      ch->in_room->pcs++;
    }
  if (IS_MOB (ch) && ch->in_room->pcs > 0)
    add_to_aggro_list (ch);
  
  if (oneroom->people != ch)
    {
      ch->next_in_room = oneroom->people;
      oneroom->people = ch;
    }
  if (IS_PLAYER(ch))
    {
      if (oneroom->vnum >= BATTLEGROUND_START_VNUM && oneroom->vnum <= BATTLEGROUND_END_VNUM)
	{
	  ch->pcdata->battleground = BATTLE_FIGHTING;
	}
      else
	{
	  ch->pcdata->battleground = 0;
	  ch->pcdata->wasroom = oneroom->vnum;
	}
      oneroom->light +=ch->pcdata->light;
    }
  else
    {
      if (IS_SET(ch->pIndexData->act4, ACT4_COMMANDSCRIPT))
	ch->in_room->command_objs++;
      add_char_to_list (ch);
    }
  if (IS_PLAYER(ch) && IS_SET(ch->pcdata->act2, PLR_MAPPING))
    {
      small_map(ch);  
    }
  
  return;
}


SINGLE_OBJECT *
get_item_held (CHAR_DATA * ch, int itype)
{
  int i;
  int num_hands = UMIN(MAX_HOLD,(IS_MOB(ch) ? 1 : race_info[ch->pcdata->race].parts[3])*2);
  for (i = 0; i < num_hands; i++)
    {
      if (ch->hold[i] != NULL && 
	  ch->hold[i]->pIndexData->item_type == itype)
	return ch->hold[i];
    }
  return NULL;
}

SINGLE_OBJECT *
get_eq_char (CHAR_DATA * ch, int wear_loc, int wear_num)
{
  SINGLE_OBJECT *obj;
  for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
    {
      if (worn_flags[obj->wear_loc].flagname == wear_loc && 
	  (obj->wear_num == wear_num))
	return obj;
    }
  return NULL;
}

/*
   * Equip a char with an obj.
 */
void 
equip_char (CHAR_DATA * ch, SINGLE_OBJECT * obj, int wear_loc, int wear_num)
{
  AFFECT_DATA *paf;
  SINGLE_OBJECT *prev;
  int bitty;
  
  if (obj->pIndexData->item_type == ITEM_ARMOR)
    {
      if (obj->size < 1)
	SET_OBJ_SIZE (ch, obj);
      if (!OBJ_FITS (obj, ch))
	{
	  char tmpb[1000];
	  bool plural;
	  plural = (obj->pIndexData->short_descr[strlen (obj->pIndexData->short_descr) - 1] == 's');
	  if (OBJ_TOO_BIG (obj, ch))
	    {
	      sprintf (tmpb, "%s\x1B[37;0m %s too big and just fall%s off!\n\r",
		       capitalize (obj->pIndexData->short_descr),
		       (plural ? "are" : "is"),
		       (plural ? "" : "s"));
	      send_to_char (tmpb, ch);
	    }
	  else
	    {
	      sprintf (tmpb, "%s\x1B[37;0m %s too small for you to wear!\n\r",
		       capitalize (obj->pIndexData->short_descr),
		       (plural ? "are" : "is"));
	      send_to_char (tmpb, ch);
	    }
	  return;
	}
    }
  obj->wear_loc = wear_loc;
  obj->wear_num = wear_num;
  
  /* Remove the object from the carrying list. */
  
  if(obj == ch->carrying)
    {
      ch->carrying = obj->next_content;
      obj->next_content = NULL;
      prev = NULL;
    }
  else
    {
      for (prev = ch->carrying; prev != NULL; prev = prev->next_content)
	{
	  if (prev->next_content == obj)
	    {
	      prev->next_content = obj->next_content;
	      obj->next_content = NULL;
	      break;
	    }
	}
    }

  /* If ch was not carrying anything, or the first item is not worn
     or the first item is worn but a greater number...we put the new
     item first. */
  
  if (!ch->carrying || 
      (ch->carrying && 
       (ch->carrying->wear_loc == WEAR_NONE || 
	ch->carrying->wear_loc > wear_loc)))
    {
      obj->next_content = ch->carrying;
      ch->carrying = obj;
    }
  else 

    /* Otherwise the top item exists and is worn and its wearing number
       is <= that of the new obj. */
    
    {
      for (prev = ch->carrying; prev != NULL; prev = prev->next_content)
	{
	  
	  /* Now we look for an object that either has nothing following
	     or if it does have something following, then the object 
	     following is not worn or its wear_loc is >= that of
	     obj. */
	  
	  if (!prev->next_content ||
	      (prev->next_content &&
	       (prev->next_content->wear_loc == WEAR_NONE ||
		prev->next_content->wear_loc > wear_loc)))
	    {
	      obj->next_content = prev->next_content;
	      prev->next_content = obj;
	      break;
	    }
	}
    }

  
  if (worn_flags[wear_loc].flagname == ITEM_WIELD)
    {
      ch->hold[wear_num] = obj;
    }
  if (IS_PLAYER(ch))
    {
      if(obj->pIndexData->item_type == ITEM_ARMOR)
	{
	  I_ARMOR *r = (I_ARMOR *) obj->more;
	  if (r->max_condition == 0)
	    {
	      ch->pcdata->armor[0] += (r->protects_body);
	      ch->pcdata->armor[1] += (r->protects_head);
	      ch->pcdata->armor[2] += (r->protects_legs);
	      ch->pcdata->armor[3] += (r->protects_arms);
	    }
	  else
	    {
	      ch->pcdata->armor[2] += (r->protects_legs * r->condition_now) / (r->max_condition);
	      ch->pcdata->armor[0] += (r->protects_body * r->condition_now) / (r->max_condition);
	      ch->pcdata->armor[1] += (r->protects_head * r->condition_now) / (r->max_condition);
	      ch->pcdata->armor[3] += (r->protects_arms * r->condition_now) / (r->max_condition);
	    }
	  ch->pcdata->warmth += r->warmth;
	  if (ch->pcdata->warmth < 0) 
	    ch->pcdata->warmth = 0;
	}
      if (worn_flags[wear_loc].flagname == ITEM_WEAR_FEET)
	SET_BIT(ch->act, PLR_HAS_SHOES);
      if (worn_flags[wear_loc].flagname == ITEM_WEAR_SHIELD)
	SET_BIT(ch->act, PLR_HAS_SHIELD);
      if (obj->pIndexData->item_type == ITEM_VEHICLE && obj->wear_loc > WEAR_NONE)
	{
	  I_VEHICLE *veh = (I_VEHICLE *) obj->more;
	  if (veh->sector_use == SECT_SNOW)
	    SET_BIT(ch->act, PLR_HAS_SNOWSHOES);
	  if (veh->sector_use == SECT_UNDERWATER)
	    SET_BIT(ch->act, PLR_HAS_SCUBA);
	  if (veh->sector_use == SECT_MOUNTAIN) 
	    SET_BIT(ch->act, PLR_HAS_MTN_BOOTS);
	}    
      if (obj->pIndexData->item_type == ITEM_GEM && worn_flags[wear_loc].flagname == ITEM_WIELD )
	{
	  act ("As you hold $p in your hand, its energy drains.", ch, obj, NULL, TO_CHAR);
	  act ("...You slowly start to feel the gem get used to your hand and it begins", ch, obj, NULL, TO_CHAR);
	  act ("to power up for use. Use the examine command to check it's power.", ch, obj, NULL, TO_CHAR);
	 
	  ((I_GEM *) obj->more)->mana_now = 0;
	  ch->pcdata->n_mana = 0;
	}
      if (obj->pIndexData->item_type == ITEM_SHIELD)
	{
	  send_to_char("As the powershield floats about your head, all power drains from it...\n\r", ch);
	  ((I_SHIELD *)obj->more)->current_power = 0;
	}


      bitty = 0;
      if (!IS_AFF (ch, FLYING))
	bitty = 1;
      for (paf = obj->pIndexData->affected; paf != NULL; paf = ((!paf->next) ? NULL : paf->next))
	affect_modify (ch, paf, TRUE, 0);
      if (obj->affected != NULL)
	for (paf = obj->affected; paf != NULL; paf = ((!paf->next) ? NULL : paf->next)) 
	  affect_modify (ch, paf, TRUE, 0); 
      
      
      if (IS_AFF (ch, FLYING) && bitty == 1)
	REMOVE_BIT (ch->aff[AFF], FLYING);
      ++ch->pcdata->light;
      if (ch->move > ch->max_move)
	ch->move = ch->max_move;
    }
  return;
}


int 
hand_empty (CHAR_DATA * ch)
{
  int i;
  
  int arm_pairs = (IS_MOB(ch) ? 1 : race_info[ch->pcdata->race].parts[3]);
  for (i = 0; i < arm_pairs*2; i++)
    {
      if (ch->hold[i] == NULL)
	return i;
    }
  return WEAR_NONE;
}

bool 
unequip_char (CHAR_DATA * ch, SINGLE_OBJECT * obj)
{
  AFFECT_DATA *paf;
  int amt;
  SINGLE_OBJECT *objs;
  if (worn_flags[obj->wear_loc].flagname != ITEM_WEAR_BELT && obj->wear_loc != WEAR_NONE)
    {
      for (paf = obj->pIndexData->affected; paf != NULL; paf = ((!paf->next) ? NULL : paf->next))
	affect_modify (ch, paf, FALSE, 0);
      for (paf = obj->affected; paf != NULL; paf = ((!paf->next) ? NULL : paf->next))
	affect_modify (ch, paf, FALSE, 0);
    }
  if (worn_flags[obj->wear_loc].flagname == ITEM_WIELD)
    ch->hold[obj->wear_num] = NULL;
  
  if (IS_PLAYER(ch))
    {
      if (worn_flags[obj->wear_loc].flagname == ITEM_WEAR_FEET)
	REMOVE_BIT(ch->act, PLR_HAS_SHOES);
      if (worn_flags[obj->wear_loc].flagname == ITEM_WEAR_SHIELD)
	REMOVE_BIT(ch->act, PLR_HAS_SHIELD);
      if (obj->pIndexData->item_type == ITEM_VEHICLE)
	{
	  I_VEHICLE *veh = (I_VEHICLE *) obj->more;
	  if (veh->sector_use == SECT_SNOW)
	    REMOVE_BIT(ch->act, PLR_HAS_SNOWSHOES);
	  if (veh->sector_use == SECT_UNDERWATER)
	    REMOVE_BIT(ch->act, PLR_HAS_SCUBA);
	  if (veh->sector_use == SECT_MOUNTAIN) 
	    REMOVE_BIT(ch->act, PLR_HAS_MTN_BOOTS);
	  
	}
      if (obj->pIndexData->item_type == ITEM_GEM) 
	{
	  if (((I_GEM *) obj->more)->mana_now < 0) 
	    {
	      amt=UMIN((0-((I_GEM *) obj->more)->mana_now),ch->pcdata->n_mana);
	      ((I_GEM *) obj->more)->mana_now+=amt;
	      ch->pcdata->n_mana-=amt;
	    }
	}
      if (obj->pIndexData->item_type == ITEM_LIGHT && IS_LIT (obj))
	{
	  if (ch->in_room != NULL)
	    {
	      ch->in_room->light--;
	      if (IS_PLAYER(ch))
	       ch->pcdata->light--;
	      
	    }
	}
      if(obj->pIndexData->item_type == ITEM_ARMOR)
	{
	  I_ARMOR *r = (I_ARMOR *) obj->more;
	  if (r->max_condition == 0)
	    {
	      ch->pcdata->armor[0] -= (r->protects_body);
	      ch->pcdata->armor[1] -= (r->protects_head);
	      ch->pcdata->armor[2] -= (r->protects_legs);
	      ch->pcdata->armor[3] -= (r->protects_arms);
	    }
	  else
	    {
	      ch->pcdata->armor[2] -= (r->protects_legs * r->condition_now) / (r->max_condition);
	      ch->pcdata->armor[0] -= (r->protects_body * r->condition_now) / (r->max_condition);
	      ch->pcdata->armor[1] -= (r->protects_head * r->condition_now) / (r->max_condition);
	      ch->pcdata->armor[3] -= (r->protects_arms * r->condition_now) / (r->max_condition);
	    }
	  ch->pcdata->warmth -= r->warmth;
	  if (ch->pcdata->warmth < 0) 
	    ch->pcdata->warmth = 0;
	}
     }
  
   /* If the object we unequip is the first, remove it and make the 
      obj_list start at 2nd object. */

  if(obj == ch->carrying)
    {
      ch->carrying = obj->next_content;
      obj->next_content = NULL;
    }
  if (ch->carrying == NULL)
    {
      ch->carrying = obj;
      obj->next_content = NULL;
    }
  else
    {
      for (objs = ch->carrying; objs != NULL; objs = objs->next_content)
	{
	  
	  /* Pop obj from the linked list... */
	  
	  if (objs->next_content == obj)
	    {
	      objs->next_content = obj->next_content;
	      obj->next_content = NULL;  
	    }
	}
      
      for(objs = ch->carrying; objs != NULL; objs = objs->next_content)
	{
	  if (objs->wear_loc > WEAR_NONE)
	    {
	      if (objs->pIndexData->item_type == ITEM_ARMOR)
		{
		  if (worn_flags[objs->wear_loc].flagname == ITEM_WEAR_FEET)
		    SET_BIT(ch->act, PLR_HAS_SHOES);
		  if (worn_flags[objs->wear_loc].flagname == ITEM_WEAR_SHIELD)
		    SET_BIT(ch->act, PLR_HAS_SHIELD);
		}
	      else if (obj->pIndexData->item_type == ITEM_VEHICLE)
		{
		  I_VEHICLE *veh = (I_VEHICLE *) obj->more;
		  if (veh->sector_use == SECT_SNOW)
		    SET_BIT(ch->act, PLR_HAS_SNOWSHOES);
		  if (veh->sector_use == SECT_UNDERWATER)
		    SET_BIT(ch->act, PLR_HAS_SCUBA);
		  if (veh->sector_use == SECT_MOUNTAIN) 
		    SET_BIT(ch->act, PLR_HAS_MTN_BOOTS);
		}
	    }
	  
	  /* If we are at the end of the linked list, slap obj back in. */
      
	  if (objs->next_content == NULL)
	    {
	      objs->next_content = obj;       
	      obj->next_content = NULL;
	      break;
	    }
	}
    }
  obj->wear_loc = WEAR_NONE;
  obj->wear_num = WEAR_NONE;
  return TRUE;
}


int 
count_obj_list (OBJ_PROTOTYPE * pObjIndex, SINGLE_OBJECT * list)
{
  SINGLE_OBJECT *obj;
  int nMatch;
  nMatch = 0;
  for (obj = list; obj != NULL; obj = obj->next_content)
    {
      if (obj->next_content && obj == obj->next_content)
	{
	  fprintf (stderr, "Endless object pointers called in count_obj_list\n");
	  exit (15);
	}
      if (obj->pIndexData == pObjIndex)
	nMatch++;
    }
  return nMatch;
}

void 
extract_char (CHAR_DATA * ch, bool fPull)
{
  CHAR_DATA *wch;
  SINGLE_OBJECT *obj;
  SINGLE_OBJECT *obj_next;
  ROOM_DATA *ir;
  DESCRIPTOR_DATA *d;
  int i;
  if (IS_MOB(ch))
    clear_tracks (ch);
  if (fPull)
    die_follower (ch);
  ir = ch->in_room;
  if (ch->in_room)
    stop_fighting (ch, TRUE);
  if (ch->in_room)
    char_from_room (ch);
  if (IS_PLAYER(ch))
    {
      if(ch->pcdata->guarding != NULL)
	{
	  for(i = 0; i < 4; i++)
	    {
	      if(IS_PLAYER(ch->pcdata->guarding))
		if (ch->pcdata->guarding->pcdata->guarded_by[i] == ch)
		  ch->pcdata->guarding->pcdata->guarded_by[i] = NULL;
	    }
	  ch->pcdata->guarding = NULL;
	}
      for (i = 0; i < 4; i++)
	{
	  if(ch->pcdata->guarded_by[i] != NULL)
	    {
	      if (IS_PLAYER(ch->pcdata->guarded_by[i]))
		ch->pcdata->guarded_by[i]->pcdata->guarding = NULL;
	      ch->pcdata->guarded_by[i] = NULL;
	    }
	}
    }  
  else
    {
      remove_from_aggro_list(ch);
    }
  if (RIDING (ch) != NULL)
    {
      check_fgt (ch->fgt->riding);
      ch->fgt->riding->fgt->mounted_by = NULL;
      ch->fgt->riding = NULL;
    }
  if (MOUNTED_BY (ch) != NULL)
    {
      check_fgt (ch->fgt->mounted_by);
      ch->fgt->mounted_by->fgt->riding = NULL;
      ch->fgt->mounted_by = NULL;
    }
  if (IS_MOB (ch) && ch->society)
    {
      SOCIETY_DATA *soc;
      int jj, rank;
      if ((soc = society_lookup (NULL, ch->society)) != NULL)
	{
	  for (jj = 0; jj < NUM_CASTES; jj++)
	    {
	      if (soc->caste[jj] && 
		  ((rank = (ch->pIndexData->vnum - soc->caste[jj]->mob_start_vnum)) >= 0) &&
		  rank < soc->caste[jj]->num_ranks)
		{
		  soc->caste[jj]->curr_pop[rank]--;
		  if (soc->caste[jj]->curr_pop[rank] < 0)
		    soc->caste[jj]->curr_pop[rank] = 0;
		  break;
		}
	    }
	}
      ch->society = 0;
    }
  if (IS_PLAYER (ch) && ch->desc != NULL && ch->desc->original != NULL)
    do_return (ch, "");
  if (fPull)
    {
      SCRIPT_INFO *si;
      SCRIPT_INFO *si_next;
      for (si = info_list; si != NULL; si = si_next)
	{
	  si_next = si->next;
	  if (si->current == ch || si->mob == ch)
	    {
	      end_script (si);
	    }
	}
      for (i = 0; i < TOTAL_LIST; i++)
	{
	  for (wch = char_list[i]; wch != NULL; wch = wch->next)
	    {
	      if (wch->fgt)
		{
		  if (MASTER (wch) == ch)
		    wch->fgt->master = NULL;
		  if (LEADER (wch) == ch)
		    wch->fgt->leader = NULL;
		  if (RIDING (wch) == ch)
		    wch->fgt->riding = NULL;
		  if (MOUNTED_BY (wch) == ch)
		    wch->fgt->mounted_by = NULL;
		}
	      if (wch->pcdata && wch->pcdata->reply == ch)
		wch->pcdata->reply = NULL;
	    }
	}
      remove_char_from_list (ch);
      if (IS_PLAYER (ch))
	{
	  for (d = descriptor_list; d != NULL; d = d->next)
	    {
	      if (d->character && d->connected == CON_PEDITOR &&
		  ch == (CHAR_DATA *) d->pEdit)
		{
		  ch->in_room = ir;
		  return;
		}
	    }
	}
      if (ch == debugger)
	debugger = NULL;
      for (obj = ch->carrying; obj != NULL; obj = obj_next)
	{
	  obj_next = obj->next_content;
	  free_it (obj);
	}
    }
  if (IS_PLAYER (ch) && !fPull)
    {
      
      ch->pcdata->condition[COND_FULL] = 55;
      ch->pcdata->condition[COND_THIRST] = 55;
      ch->pcdata->condition[COND_DRUNK] = 0;
    }
  if (!fPull)
    {
      strip_all_affects (ch);
      char_to_room(ch, get_room_index(ch->pcdata->alignment+100));
      WAIT_STATE(ch, 5*PULSE_VIOLENCE);
      return;
    }
  if (IS_MOB (ch))
    {
      --ch->pIndexData->count;
    }
  if (IS_PLAYER (ch) && ch->desc)
    ch->desc->character = NULL;
  free_it (ch);
  return;
}

CHAR_DATA *
get_char_room (CHAR_DATA * ch, char *argy)
{
  static char arg[500];
  CHAR_DATA *rch;
  int RCLOOK;
  int number;
/*char buf[50]; */
  int count;
  RCLOOK = 0;
  if (ch == NULL || !ch->in_room) return NULL;
  arg[0] = '\0';
  number = number_argy (argy, arg);
  count = 0;
  if (!ch->in_room)
    return NULL;
  if (!str_cmp (arg, "self"))
    return ch;
  if (!str_cmp (arg, "me"))
    return ch;
  RCLOOK = get_race_look(arg);
  /*Mobs FIRST */
  for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
    {
      if (!rch->in_room)
	continue;
      if (IS_PLAYER (rch))
	continue;
      if (!can_see (ch, rch) || (!is_approx_name (arg, RNAME (rch)) &&
				 str_prefix (arg, RNAME (rch))))
	continue;
      if (++count == number)
	return rch;
    }
 
  if (RCLOOK != -1)
    {
      for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
	{
	  if (!rch->in_room)
	    continue;
	  if (LEVEL(rch) == MAX_LEVEL)
	      continue;
	  if (!can_see (ch, rch) || IS_MOB (rch) || IS_MOB (ch))
	    continue;
	  if (LEVEL(rch) == MAX_LEVEL)
	      continue;
	  if (rch == ch)
	    continue;
          if (!DIFF_ALIGN(ch, rch))
	    continue;
	  if (RCLOOK < 100)
	    {
	      if (RCLOOK >= 50)
		{
		  if (ALIGN(rch) != (RCLOOK - 50))
		    continue;
		}
	      else
		{
		  if (rch->pcdata->race != RCLOOK)
		    continue;
		}
	    }
	  if (++count == number)
	    return rch;
	}
    }
  {
    for (rch = ch->in_room->people; rch != NULL; rch = rch->next_in_room)
      {
	if (!rch->in_room)
	  continue;
	if (!can_see (ch, rch) || (!is_name (arg, RNAME (rch)) &&
				   str_prefix (arg, RNAME (rch))))
	  continue;
	if (IS_MOB (rch) && !IS_SET (ch->act, PLR_HOLYLIGHT) &&
	    IS_SET (rch->pIndexData->act3, ACT3_MIMIC))
	  continue;
        if (arg[0] == '\0' && IS_PLAYER(rch))
          continue;
	if (++count == number)
	  return rch;
      }
  }
  return NULL;
}

CHAR_DATA * 
get_char_room_near (CHAR_DATA *ch, ROOM_DATA *in_room, int range, char * argy)
{
  if (!ch || !in_room)
    return NULL;
  return get_char_room_near2 (ch, in_room, range,argy, 9999);
}

CHAR_DATA *
get_char_room_near2 (CHAR_DATA * ch, ROOM_DATA *in_room, int range, char *argy, int direction)
{
  static char arg[500];
  char argg[SML_LENGTH];
  CHAR_DATA *rch = NULL;
  int RCLOOK = 0;
  int number;
  int count;
  int door;
   ROOM_DATA *troom;
   EXIT_DATA *pexit;
   bool people = FALSE;
   if(in_room == NULL)
     return NULL;
  if (ch == NULL) return NULL;
  if (range < 0) return NULL;
  else range--;
  arg[0] = '\0';
  strcpy(argg, argy);
  number = number_argy (argy, arg);
  count = 0;
  if (!str_cmp (arg, "self"))
    {
      return ch;
    }
  if (!str_cmp (arg, "me"))
    {
      return ch;
    }
  RCLOOK = get_race_look(arg);
  /*Mobs FIRST */
  if (!in_room)
    {
      return NULL;
    }
  for (rch = in_room->people; rch != NULL; rch = rch->next_in_room)
    {
      people = TRUE;
      if (IS_PLAYER (rch))
	continue;
      if (!can_see (ch, rch) || (!is_approx_name (arg, RNAME (rch)) &&
				 str_prefix (arg, RNAME (rch))))
	continue;
      if (++count == number)
	{
	  return rch;
	}
    }

  if (RCLOOK != -1)
    {
      for (rch = in_room->people; rch != NULL; rch = rch->next_in_room)
	{
	  
	  if (!can_see (ch, rch) || IS_MOB (rch))
	    continue;
	  if (LEVEL(rch) == MAX_LEVEL)
	      continue;
	  if (rch == ch)
	    continue;
          if (!DIFF_ALIGN(ch, rch))
	    continue;
	  if (RCLOOK < 100)
	    {
	      if (RCLOOK >= 50)
		{
		  if (ALIGN(rch) != (RCLOOK - 50))
		    continue;
		}
	      else
		{
		  if (rch->pcdata->race != RCLOOK)
		    continue;
		}
	    }
	  if (++count == number)
	    {
	      return rch;
	    }
	}
    }
  
  for (rch = in_room->people; rch != NULL; rch = rch->next_in_room)
    {
      if (!can_see (ch, rch) || (!is_name (arg, RNAME (rch)) &&
				 str_prefix (arg, RNAME (rch))))
	continue;
        if (arg[0] == '\0' && IS_PLAYER(rch))
          continue;
      if (++count == number)
	{
	  return rch;
	}
    }
  if (direction == 9999)
    {
      for (door = 0; ((door < MAX_DIR)); door++)
	{
	  
	  if ((pexit = in_room->exit[door]) != NULL && (troom = in_room->exit[door]->to_room) != NULL && (!pexit->d_info || !IS_SET(pexit->d_info->exit_info, EX_CLOSED)))
	    {
	      if ((rch = get_char_room_near2 (ch, troom, range, argg, door)) != NULL)
		return rch;
	    }
	  else
	    rch = NULL;
	}
    }
  if (direction >= 0 && direction < MAX_DIR)
    {
      if (!people && (pexit = in_room->exit[direction]) != NULL && (troom = in_room->exit[direction]->to_room) != NULL && (!pexit->d_info || !IS_SET(pexit->d_info->exit_info, EX_CLOSED)))
	{
	 if (( rch = get_char_room_near2 (ch, troom, range, argg, direction)) != NULL)
	   return rch;
	}
      else rch = NULL;
    }
  return NULL;
}




/* Find a player in the world */
CHAR_DATA *
get_player_world (CHAR_DATA * ch, char *argy, bool need_see)
{
  char arg[SML_LENGTH];
  CHAR_DATA *wch;
  DESCRIPTOR_DATA *dd;
  int number;
  int count;
  if (!ch || !ch->in_room)
    return NULL;
  if ((wch = get_char_room (ch, argy)) != NULL)
    return wch;
  number = number_argy (argy, arg);
  count = 0;
  for (dd = descriptor_list; dd != NULL; dd = dd->next)
    {
      if (dd->character == NULL)
	continue;
      if (dd->connected > 0)
	continue;
      wch = dd->character;
      if (!wch->in_room)
	continue;
      if ((need_see && !can_see (ch, wch)) || !is_approx_name (arg, RNAME (wch)) ||
	  (ch->in_room && wch->in_room && wch->in_room->area != ch->in_room->area))
	continue;
      if (++count == number)
	return wch;
    }
  number = number_argy (argy, arg);
  count = 0;
  for (dd = descriptor_list; dd != NULL; dd = dd->next)
    {
      if (dd->character == NULL)
	continue;
      if (dd->connected > 0)
	continue;
      wch = dd->character;
      if (!wch->in_room) continue;
      if ((need_see && !can_see (ch, wch)) || !is_name (arg, RNAME (wch)))
	continue;
      if (++count == number)
	return wch;
    }
  return NULL;
}

ONLINE * /* JRAJRA - stuff to check the online list for people */
check_online (ONLINE *victim, char* argy)
{
  bool found = FALSE;
  ONLINE *online;
  ONLINE *onlinenx;
  int ll = 0;
  for (online = been_online; onlinenx != NULL && !found ; online = onlinenx)
    {
      onlinenx = online->next;
      ll++;
      if (!str_cmp(online->name,argy))
	{
	  return online;
	}
      if (ll > 1000)
       break;
    }
  return NULL;
}


CHAR_DATA *
get_char_world (CHAR_DATA * ch, char *argy)
{
  char arg[SML_LENGTH];
  CHAR_DATA *wch;
  int number, i, count;
  if (!ch->in_room)
    return NULL;
  if ((wch = get_char_room (ch, argy)) != NULL)
    return wch;
  if ((wch = get_player_world (ch, argy, TRUE)) != NULL)
    return wch;
  number = number_argy (argy, arg);
  count = 0;

  number = number_argy (argy, arg);
  count = 0;
  for (i = 0; i < TOTAL_LIST; i++)
    {
      for (wch = char_list[i]; wch != NULL; wch = wch->next)
	{
	  if (!wch->in_room)
	    continue;
	  if (wch->desc && wch->desc > 0)
	    continue;
	  if (!can_see (ch, wch) || !is_name (arg, RNAME (wch)))
	    continue;
	  if (++count == number)
	    return wch;
	}
    }
  return NULL;
}

CHAR_DATA *
get_char_world_2 (CHAR_DATA * ch, char *argy)
{
  char arg[SML_LENGTH];
  CHAR_DATA *wch;
  int number, i, count;
  if (!ch->in_room)
    return NULL;
  if ((wch = get_char_room (ch, argy)) != NULL)
    return wch;
  if ((wch = get_player_world (ch, argy, FALSE)) != NULL)
    return wch;
  number = number_argy (argy, arg);
  count = 0;
  for (i = 0; i < TOTAL_LIST; i++)
    {
      for (wch = char_list[i]; wch != NULL; wch = wch->next)
	{
	  if (!wch->in_room)
	    continue;
	  if (!is_name (arg, RNAME (wch)) &&
	      str_cmp (arg, NAME (wch)))
	    continue;
	  if (++count == number)
	    return wch;
	}
    }
  return NULL;
}

SINGLE_OBJECT *
get_obj_type (OBJ_PROTOTYPE * pObjIndex)
{
  SINGLE_OBJECT *obj;
  int i;
  for (i = 0; i < 2; i++)
    {
      for (obj = object_list[i]; obj != NULL; obj = obj->next)
	{
	  if (obj->pIndexData == pObjIndex)
	    return obj;
	}
    }
  return NULL;
}


SINGLE_OBJECT *
get_obj_list (CHAR_DATA * ch, char *argy, SINGLE_OBJECT * list)
{
  char arg[SML_LENGTH];
  SINGLE_OBJECT *obj;
  int number;
  int count;
  number = number_argy (argy, arg);
  count = 0;
  for (obj = list; obj != NULL; obj = obj->next_content)
    {
      if (can_see_obj (ch, obj) && is_name (arg, obj->pIndexData->name))
	{
	  if (++count == number)
	    return obj;
	}
    }
  return NULL;
}


SINGLE_OBJECT *
get_obj_carry (CHAR_DATA * ch, char *argy)
{
  char arg[SML_LENGTH];
  SINGLE_OBJECT *obj;
  int number;
  int count;
  number = number_argy (argy, arg);
  count = 0;
  for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
    {
      if ((obj->wear_loc == WEAR_NONE)
	  && (obj->pIndexData->item_type == ITEM_FOOD || obj->pIndexData->item_type == ITEM_PILL || can_see_obj (ch, obj))
	  && is_name (arg, obj->pIndexData->name))
	{
	  if (++count == number)
	    return obj;
	}
    }
  for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
    {
      if ((obj->wear_loc == WEAR_NONE)
	  && (obj->pIndexData->item_type == ITEM_FOOD || obj->pIndexData->item_type == ITEM_PILL || can_see_obj (ch, obj))
	  && is_approx_name (arg, obj->pIndexData->name))
	{
	  if (++count == number)
	    return obj;
	}
    }
  return NULL;
}



SINGLE_OBJECT *
get_obj_wear (CHAR_DATA * ch, char *argy)
{
  char arg[SML_LENGTH];
  SINGLE_OBJECT *obj;
  int number;
  int count;
  number = number_argy (argy, arg);
  count = 0;
  for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
    {
      if (obj->wear_loc != WEAR_NONE
	  && can_see_obj (ch, obj)
	  && is_name (arg, obj->pIndexData->name))
	{
	  if (++count == number)
	    return obj;
	}
    }
  for (obj = ch->carrying; obj != NULL; obj = obj->next_content)
    {
      if (obj->wear_loc != WEAR_NONE
	  && can_see_obj (ch, obj)
	  && is_approx_name (arg, obj->pIndexData->name))
	{
	  if (++count == number)
	    return obj;
	}
    }
  return NULL;
}


SINGLE_OBJECT *
get_obj_inv (CHAR_DATA * ch, char *argy)
{
  SINGLE_OBJECT *obj;
  if ((obj = get_obj_carry (ch, argy)) != NULL)
    return obj;
  if ((obj = get_obj_wear (ch, argy)) != NULL)
    return obj;
  return NULL;
}


SINGLE_OBJECT *
get_obj_here (CHAR_DATA * ch, char *argy, int lookfirst)
{
  SINGLE_OBJECT *obj;
  if (lookfirst == SEARCH_ROOM_FIRST)
    {
      obj = get_obj_list (ch, argy, ch->in_room->contents);
      if (obj != NULL)
	return obj;
      if ((obj = get_obj_inv (ch, argy)) != NULL)
	return obj;
      return NULL;
    }
  else if (lookfirst == SEARCH_INV_FIRST)
    {
      if ((obj = get_obj_inv (ch, argy)) != NULL)
	return obj;
      obj = get_obj_list (ch, argy, ch->in_room->contents);
      if (obj != NULL)
	return obj;
      return NULL;
    }
  else
    return NULL;
}


SINGLE_OBJECT *
get_obj_world (CHAR_DATA * ch, char *argy)
{
  char arg[SML_LENGTH];
  SINGLE_OBJECT *obj;
  int number, i;
  int count;
  if ((obj = get_obj_here (ch, argy, SEARCH_ROOM_FIRST)) != NULL)
    return obj;
  number = number_argy (argy, arg);
  count = 0;
  for (i = 1; i >= 0; i--)
    {
      for (obj = object_list[i]; obj != NULL; obj = obj->next)
	{
	  if (can_see_obj (ch, obj) && is_name (arg, obj->pIndexData->name))
	    {
	      if (++count == number)
		return obj;
	    }
	}
    }
  return NULL;
}


void 
create_amount (int amount, CHAR_DATA * pMob, ROOM_DATA * pRoom,
	       SINGLE_OBJECT * pObj)
{
  I_CONTAINER *c = NULL;
  if (pObj && pObj->pIndexData->item_type != ITEM_CONTAINER &&
      pObj->pIndexData->item_type != ITEM_CORPSE_NPC && pObj->pIndexData->item_type != ITEM_CORPSE_PC)
    return;
  if (pObj)
    c = (I_CONTAINER *) pObj->more;
  if (amount <= 0)
    {
      bug ("Create_amount: zero or negative money %d.", amount);
      return;
    }
  if (amount == 1)
    {
      
      if (pMob)
	pMob->coins[COPPER]++;
      if (pObj)
	c->money++;
      if (pRoom)
	{
	  pRoom->coins[COPPER]++;
	}
    }
  else
    {
      if (pMob)
	{
	  int i;
	  for (i = MAX_COINS -1; i >= 0; i--)
	    {
	      if (amount >= coin_mult[i])
		{
		  pMob->coins[i] += amount/coin_mult[i];
		  amount %= coin_mult[i];
		}
	    }
	}
      else if (pRoom)
	{
	  int i;
	  for (i = MAX_COINS -1; i >= 0; i--)
	    {
	      if (amount >= coin_mult[i])
		{
		  pRoom->coins[i] += amount/coin_mult[i];
		  amount %= coin_mult[i];
		}
	    }
	}
      else if (pObj)
	c->money += amount;
    }
  return;
}

int 
tally_coins (CHAR_DATA * ch)
{
  int total = 0;
  int i;
  for (i = 0; i < MAX_COINS; i++)
    {
      if(ch->coins[i] < 0)
	ch->coins[i] = 0;
      total += coin_mult[i] * ch->coins[i];
    }
  return total;
}


char *
name_amount (int amount)
{
  static char buf[STD_LENGTH];
  char buf2[500];
  int amt_left = amount;
  int coin_types = 0;
  int coins_used = 0;
  int i;
  buf[0] = '\0';
  buf2[0] = '\0';
  if (amount == 0)
    {
      sprintf(buf, "nothing");
      return buf;
    }
  
  /* First figure out what kinds of coins we need to use...
     start with biggest and subtract off those kinds of coins first. */
  
  for (i = MAX_COINS-1; i >= 0; i--)
    {
      if (amt_left >= coin_mult[i])
	{
	  amt_left = amt_left % coin_mult[i];
	  
	  coin_types++;
	}
    }
  amt_left = amount;
  if (coin_types == 1)
    {
      for (i = MAX_COINS-1; i >=0; i--)
	if (amt_left >= coin_mult[i])
	  break;
      sprintf(buf2, "%d %s", amt_left/ coin_mult[i], coin_name[i]);
      sprintf(buf, buf2);
    }
  else
    {
      buf[0] = '\0';
      for (i = MAX_COINS -1; i >= 0; i--)
	{
	  if (amt_left >= coin_mult[i])
	    {
	      coins_used++;
	      if (coins_used < coin_types)
		{ 
		  sprintf(buf2, " %d %s,", amt_left/ coin_mult[i], coin_color[i]);
		  strcat(buf, buf2);
		}
	      else
		{
		  sprintf(buf2, " and %d %s", amt_left/coin_mult[i], coin_color[i]);
		  strcat(buf, buf2);
		}
	      amt_left = amt_left % coin_mult[i];
	    }
	}
    }
  if (buf[0] == '\0')
    sprintf (buf, "nothing");
  return buf;
}


/* Ch is totally rewritten to handle any number of different coin types...
   even with different ratios between coin types ! */


char *
sub_coins (int amount, CHAR_DATA * ch)
{
  static char ret_val[500];
  int money = 0;
  int i;
  
  if (tally_coins (ch) < amount)
    {
      sprintf (ret_val, "nothing");
      bug ("Sub_coins: ch doesn't have enough money (%d)", amount);
      return ret_val;
    }
  

  if (tally_coins (ch) == amount)
    {
      for (i = 0; i < MAX_COINS; i++)
	ch->coins[i] = 0;
      sprintf (ret_val, "nothing");
      return ret_val;
    }
  
  /* First do a cascading making of change to make sure we can always
     make change for the above amounts. We basically check to make
     sure that at each level we have enough coins to fully split
     the next level up. This does assume that the coin denominations
     are ALL divisible by each other in order. So be careful if you
     change that fact :) */

  for (i = MAX_COINS-1; i > 0; i--)
    {
      if (ch->coins[i-1] < coin_mult[i]/coin_mult[i-1] && ch->coins[i] > 0)
	{

	  /* THE FOLLOWING LINE REQUIRES!!!! THAT THE AMOUNTS IN 
	     coin_mult ARE ALL DIVISIBLE!!!! LOOK AT IT...IF THESE
	     ARE NOT DIVISIBLE, YOU WILL BE MAKING PLAYERS LOSE MONEY
	     AND THEY WILL COME AND BITCH AT YOU!!!! */

	  ch->coins[i-1] += coin_mult[i]/coin_mult[i-1];
	  ch->coins[i]--;
	}
    }
  
  money = 0;

  /* The idea of making this sort of change is.. money starts at 0,
     then we start from the BIGGEST coins the person has. We then
     see if we have collected too little money, we start subtracting 
     coins until we have at least enough money. */

  /* Then if the money was too great we collected, we go down a level
     in coins and start to give some of the change back. Then that
     should take us to below the amount possibly, so we go and keep
     going back and forth until we reach the lowest denomination coins
     and there should be enough of those because we changed a
     bigger value for one of them. */



  for (i = MAX_COINS-1; i >= 0; i--)
    {
      if (money < amount)
	{
	  if (ch->coins[i] > 0)
	    {
	      while(ch->coins[i] > 0 && money < amount)
		{
		  ch->coins[i]--;
		  money += coin_mult[i];
		}
	    }
	}
      else if (money > amount)
	{
	  while(money > amount)
	    {
	      ch->coins[i]++;
	      money -= coin_mult[i];
	    }
	}
      else
	break;
    }

  money = amount;
  sprintf (ret_val, "%s", name_amount (money));
  return ret_val;
}


int 
get_obj_number (SINGLE_OBJECT * obj)
{
  int number;
  if (obj->pIndexData->item_type == ITEM_CONTAINER)
    number = 0;
  else
    number = 1;
  for (obj = obj->contains; obj != NULL; obj = obj->next_content)
    {
      number += get_obj_number (obj);
    }
  return number;
}


int 
get_obj_weight (SINGLE_OBJECT * obj)
{
  int weight;
  weight = obj->pIndexData->weight;
  for (obj = obj->contains; obj != NULL; obj = obj->next_content)
    {
      weight += get_obj_weight (obj);
    }
  return weight;
}


int 
room_is_dark (ROOM_DATA * oneroom)
{
  if (oneroom == NULL || oneroom->light > 0)
    return FALSE;
  if (oneroom->sector_type >= SECT_CAVE || (oneroom->room_flags & (ROOM_UNDERGROUND | ROOM_DARK)))
    return TRUE;
  if (IS_SET (oneroom->room_flags, ROOM_INDOORS) || oneroom->sector_type == SECT_INSIDE)
    return FALSE;
  if (oneroom->sector_type >= SECT_WOODS && oneroom->sector_type <= SECT_CANYON && weather_info.sky > SKY_RAINING)
    return TRUE;
  if (weather_info.sunlight > SUN_DARK)
    return FALSE;
  return TRUE;
}


bool 
can_see (CHAR_DATA * ch, CHAR_DATA * victim)
{
  if (!ch || !victim) 
    return FALSE;
  if (ch == victim)
    return TRUE;
  if (IS_PLAYER (victim)
      && victim->pcdata->wizinvis > LEVEL (ch)
      && LEVEL (ch) < LEVEL (victim))
    return FALSE;
  if (IS_PLAYER (ch) && IS_SET (ch->act, PLR_HOLYLIGHT))
    return TRUE;
  if (IS_HURT (ch, BLIND))
    return FALSE;
  if ((victim->aff[AFF] % COLD) & ~ (victim->aff[DET] % COLD))
    return FALSE;
  if (weather_info.sky == SKY_FOGGY
      && number_range(1,4) != 0 && !IS_DET(ch, FOGGY))
    return FALSE;
  if (room_is_dark (ch->in_room) && (!IS_DET(ch, DARK) || (IS_AFF(victim, COLD) && !IS_DET(ch, COLD))))
    return FALSE;
  return TRUE;
}

bool 
can_see_nextdoor (CHAR_DATA * ch, CHAR_DATA * victim)
{
  if (!ch || !victim)
    return FALSE;
  if (ch == victim)
    return TRUE;
  if (IS_PLAYER (victim)
      && victim->pcdata->wizinvis > ch->pcdata->level)
    return FALSE;
  if (IS_PLAYER (ch) && IS_SET (ch->act, PLR_HOLYLIGHT))
    return TRUE;
  if (IS_HURT (ch, BLIND))
    return FALSE;
  if ((victim->aff[AFF] % COLD) & ~ (victim->aff[DET] % COLD))
    return FALSE;
  if (weather_info.sky == SKY_FOGGY
      && number_bits (2) != 0 && !IS_DET(ch, FOGGY))
    return FALSE;
  if (room_is_dark (victim->in_room) && (!IS_DET(ch, DARK) || (IS_AFF(victim, COLD) && !IS_DET(ch, COLD))))
    return FALSE;
  return TRUE;
}

bool 
can_see_obj (CHAR_DATA * ch, SINGLE_OBJECT * obj)
{
  if (IS_PLAYER (ch) && IS_SET (ch->act, PLR_HOLYLIGHT))
    return TRUE;
  if (IS_HURT (ch, BLIND))
    return FALSE;
  if (IS_SET (obj->pIndexData->extra_flags, ITEM_UNSEEN)
      && (IS_SET (obj->pIndexData->wear_flags, ITEM_TAKE)))
    return FALSE;
  if (obj->pIndexData->item_type == ITEM_LIGHT && IS_LIT (obj))
    return TRUE;
  if (obj->carried_by == ch)
    return TRUE;
  if (room_is_dark (ch->in_room) && !IS_DET (ch,DARK ))
    return FALSE;
  if (IS_SET (obj->pIndexData->extra_flags, ITEM_INVIS)
      && !IS_DET (ch, INVIS))
    return FALSE;
  return TRUE;
}

/*
   * True if char can drop obj.
 */
bool 
can_drop_obj (CHAR_DATA * ch, SINGLE_OBJECT * obj)
{
  if (!obj)
    return TRUE;
  if (!IS_SET (obj->pIndexData->extra_flags, ITEM_NODROP))
    return TRUE;
  if (IS_PLAYER (ch) && ch->pcdata->level >= LEVEL_IMMORTAL)
    return TRUE;

  return FALSE;
}

/* 
   * Return ascii name of a mob type.
 */
char *
mob_type_name (int mob_num)
{
  static char retv[30];
  if (mob_num >= 0 && mob_num < MAX_MOB_TYPE)
    strcpy(retv, mob_info[mob_num].name);
  else
    strcpy(retv, "unknown");
  return retv;
}

/*
   * Return ascii attack of a mob type.
 */
char *
mob_type_attack (int mob_type)
{
  static char retv[30];
  if (mob_type >= 0 && mob_type < MAX_MOB_TYPE)
    strcpy(retv, mob_info[mob_type].attackname);
  else
    strcpy(retv, "punch");
  return retv;
}

/*
   * Return ascii name of an item type.
 */
char *
item_type_name (int itemtype)
{
  static char retv[30];
  if(itemtype < 1 || itemtype > ITEM_MAX)
    itemtype = ITEM_MAX;
  strcpy (retv, item_types[itemtype-1].name);
  return retv;
}

int 
mob_name_type (char *name)
{
  int i;
  for (i = 0; i < MAX_MOB_TYPE; i++)
    {
      if (!str_cmp(name, mob_info[i].name))
	return i;
    }
  return -1;
}

int 
item_name_type (char *name)
{
  int i;
  for (i = 0; i < ITEM_MAX; i ++)
    {
      if (!str_cmp(name, item_types[i].name))
	return item_types[i].number;
    }
  return 0;
}

/*
   * Return ascii name of an affect location.
 */
char *
affect_loc_name (int location)
{
  static char retv[30];
  if (location >= 0 && location < MAX_APPLY)
    strcpy(retv, apply_loc_names[location]);
  else
    strcpy(retv, "unknown");
  return retv;
}

int 
affect_name_loc (char *name)
{
  int i;
  if (!str_cmp(name, "none"))
    return APPLY_NONE;
  for (i = 1; i < MAX_APPLY; i++)
    if (!str_cmp(name, apply_loc_names[i]))
      return i;
  return -99;
}

/*
   * Return ascii name of an affect bit vector.
 */
char *
affect_bit_name (int vector0, int vector1, int vector2, int vector3)
{
  static char buf[STD_LENGTH];
  int i, k;
  int vector[4];
  bool found;
  buf[0] = '\0';
  vector[0] = vector0;
  vector[1] = vector1;
  vector[2] = vector2;
  vector[3] = vector3;
  for (k = 0; k < 2; k++)
    {
      found = FALSE;
      for (i = 0; affect_flags1[i].flagname > 0; i++)
	{
	  if (vector[k] & affect_flags1[i].flagname)
	    {
	      if (!found) 
		strcat(buf, (k == 0 ? " Hurt:" : " Prot:"));
	      found = TRUE;
	      strcat (buf, affect_flags1[i].how_it_appears);
	    }
	}
    }
  for (k = 2; k < 4; k++)
    {
      found = FALSE;
      for (i = 0; affect_flags2[i].flagname > 0; i++)
	{
	  if (vector[k] & affect_flags2[i].flagname)
	    {
	      if (!found)
		strcat(buf, (k == 2 ? " Aff:" : " Det:"));
	      found = TRUE;
	      strcat (buf, affect_flags2[i].how_it_appears);
	    }
	}
    }
  strcat(buf, "\x1b[0;37m");
  return buf;
}






/*
   * Return bit vector
 */
int 
affect_name_bit (int type, char *buf)
{
  int i;
 
  if (type < 2)
    {
      for (i = 0; affect_flags1[i].flagname > 0; i++)
	if (!str_cmp (buf, affect_flags1[i].what_you_type))
	  return affect_flags1[i].flagname;
    }
  else
    {
      for (i = 0; affect_flags2[i].flagname > 0; i++)
	if (!str_cmp (buf, affect_flags2[i].what_you_type))
	  return affect_flags2[i].flagname;
    }
  return 0;
}


char *
augment_bit_name (int vector)
{
  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; augment_flagss[i].flagname > 0; i++)
    if (vector & augment_flagss[i].flagname)
      strcat (buf, augment_flagss[i].how_it_appears);
  return (buf[0] != '\0') ? buf + 1 : " ";
}


char *
tactics_bit_name (int vector)
{
  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; tactics_flags[i].flagname > 0; i++)
    if (vector & tactics_flags[i].flagname)
      strcat (buf, tactics_flags[i].how_it_appears);
  return (buf[0] != '\0') ? buf + 1 : " ";
}






/*
   * Return bit vector
 */
int 
augment_name_bit (char *buf)
{
  int i;
  if (!str_cmp(buf,"flaglist"))
    {
      for (i = 0; augment_flagss[i].flagname > 0; i++) 
	{
	  sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
		  augment_flagss[i].what_you_type);
	}
    }
  for (i = 0; augment_flagss[i].flagname > 0; i++)
    if (!str_cmp (buf, augment_flagss[i].what_you_type))
      return augment_flagss[i].flagname;
  return 0;
}


int 
tactics_name_bit (char *buf)
{
  int i;
  if (!str_cmp(buf,"flaglist"))
    {
      for (i = 0; tactics_flags[i].flagname > 0; i++) 
	{
	  sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
		  tactics_flags[i].what_you_type);
	}
    }
  for (i = 0; tactics_flags[i].flagname > 0; i++)
    if (!str_cmp (buf, tactics_flags[i].what_you_type))
      return tactics_flags[i].flagname;
  return 0;
}



/*
   * Return ascii name of extra flags vector.
 */
char *
extra_bit_name (int extra_flags)
{
  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; extra_flagss[i].flagname > 0; i++)
    if (extra_flags & extra_flagss[i].flagname)
      strcat (buf, extra_flagss[i].how_it_appears);
  return (buf[0] != '\0') ? buf + 1 : "none";
}

int 
extra_name_bit (char *buf)
{
  int i;
  if (!str_cmp(buf,"flaglist")) {
	for (i = 0; extra_flagss[i].flagname > 0; i++) {
		sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
			extra_flagss[i].what_you_type);
		}
	}
  for (i = 0; extra_flagss[i].flagname > 0; i++)
    if (!str_cmp (buf, extra_flagss[i].what_you_type))
      return extra_flagss[i].flagname;
  return 0;
}

/*
   * Return ascii name of room flags vector.
 */
char *
room_bit_name (int room_flags)
{
  static char buf[512];
  int i;
  buf[0] = '\0';

  for (i = 0; room_flagss[i].flagname > 0; i++)
    {
      if (room_flags & room_flagss[i].flagname)
	{
          strcat (buf, room_flagss[i].how_it_appears);
	}
    }
  return (buf[0] != 0 ? buf + 1 :  " ");
}

int 
room_name_bit (char *buf)
{
  int i;
  if (!str_cmp(buf,"flaglist")) {
	for (i = 0; room_flagss[i].flagname > 0; i++) {
		sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
			room_flagss[i].what_you_type);
		}
	}
  for (i = 0; room_flagss[i].flagname > 0; i++)
    if (!str_cmp (buf, room_flagss[i].what_you_type))
      return room_flagss[i].flagname;
  return 0;
}

int 
society_name_bit (char *buf)
{
  int i;
  if (!str_cmp(buf,"flaglist")) {
	for (i = 0; society_flagss[i].flagname > 0; i++) {
		sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
			society_flagss[i].what_you_type);
		}
	}
  for (i = 0; society_flagss[i].flagname > 0; i++)
    if (!str_cmp (buf, society_flagss[i].what_you_type))
      return society_flagss[i].flagname;
  return 0;
}

int 
caste_name_bit (char *buf)
{
  int i;
  if (!str_cmp(buf,"flaglist")) {
	for (i = 0; caste_flagss[i].flagname > 0; i++) {
		sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
			caste_flagss[i].what_you_type);
		}
	}
  for (i = 0; caste_flagss[i].flagname > 0; i++)
    if (!str_cmp (buf, caste_flagss[i].what_you_type))
      return caste_flagss[i].flagname;
  return 0;
}


int 
exit_name_bit (char *buf)
{
  int i;
  for (i = 0; exit_flagss[i].flagname > 0; i++)
    if (!str_cmp (buf, exit_flagss[i].what_you_type))
      return exit_flagss[i].flagname;
  return 0;
}



char *
room_bit_name2 (int room_flags)
{
  static char buf[512];
  int i;
  buf[0] = '\0';

  for (i = 0; room_flags2[i].flagname > 0; i++)
    {
    if (room_flags & room_flags2[i].flagname)
      {
      strcat (buf, room_flags2[i].how_it_appears);
      }
    }
  return (buf[0] != 0 ? buf + 1 : " ");
}

int 
room_name_bit2 (char *buf)
{
  int i;
  if (!str_cmp(buf,"flaglist")) {
	for (i = 0; room_flags2[i].flagname > 0; i++) {
		sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
			room_flags2[i].what_you_type);
		}
	}
  for (i = 0; room_flags2[i].flagname > 0; i++)
    if (!str_cmp (buf, room_flags2[i].what_you_type))
      return room_flags2[i].flagname;
  return 0;
}

char *
race_bit_name (int rc)
{
  static char buf[512];
  char t[30];
  int i;
  buf[0] = '\0';

  for (i = 0; i < RACE_COUNT; i++)
    if (rc & (1 << i))
      {
	sprintf (t, " k%s", race_info[i].name);
	strcat (buf, t);
      }

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

char *
act_bit_name (int act)
{
  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; act_1[i].flagname > 0; i++)
    if (act & act_1[i].flagname)
      strcat (buf, act_1[i].how_it_appears);
  return (buf[0] != '\0') ? buf + 1 : " ";
}



char *
act3_bit_name (int act)
{

  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; act_3[i].flagname > 0; i++)
    if (act & act_3[i].flagname)
      strcat (buf, act_3[i].how_it_appears);
  return (buf[0] != '\0') ? buf + 1 : " ";
}


char *exit_bit_name (int bits)
{

  static char buf[500];
  int i;
  buf[0] = '\0';
  for (i = 0; exit_flagss[i].flagname > 0; i++)
    if (bits & exit_flagss[i].flagname)
      strcat(buf, exit_flagss[i].how_it_appears);
  return ((buf[0] != '\0') ? buf + 1: " ");
}



char *
act4_bit_name (int act)
{


  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; act_4[i].flagname > 0; i++)
    if (act & act_4[i].flagname)
      strcat (buf, act_4[i].how_it_appears);
  return ((buf[0] != '\0') ? buf + 1 : " ");
}

char *
society_bit_name (int act)
{


  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; society_flagss[i].flagname > 0; i++)
    if (act & society_flagss[i].flagname)
      strcat (buf, society_flagss[i].how_it_appears);
  return ((buf[0] != '\0') ? buf + 1 : " ");
}

char *
caste_bit_name (int act)
{


  static char buf[512];
  int i;
  buf[0] = '\0';
  for (i = 0; caste_flagss[i].flagname > 0; i++)
    if (act & caste_flagss[i].flagname)
      strcat (buf, caste_flagss[i].how_it_appears);
  return ((buf[0] != '\0') ? buf + 1 : " ");
}


char *
plr_bit_name (int act)
{
  static char buf[512];
  buf[0] = '\0';
  if (act & PLR_HOLYLIGHT)
    strcat (buf, " holylight");
  if (act & PLR_HOLYPEACE)
    strcat (buf, " holypeace");
  if (act & PLR_LOG)
    strcat (buf, " log");
  if (act & PLR_DENY)
    strcat (buf, " deny");
  if (act & PLR_FREEZE)
    strcat (buf, " freeze");
  if (act & WIZ_NOTIFY)
    strcat (buf, " notify");
  return (buf[0] != '\0') ? buf + 1 : "none";
}

int 
race_name_bit (char *buf)
{
  int i;
  buf++;
  for (i = 0; i < RACE_COUNT; i++)
    if (!str_cmp (buf, race_info[i].name))
      return (1 << i);

 
  if (!str_cmp (buf, "all"))
    return 0xFFFFFFFF;
  if (!str_cmp (buf, "none"))
    return 0;
  return 0;
}

int 
act_name_bit (char *buf)
{
  
  int i;
  if (!str_cmp(buf,"flaglist")) 
    {
      for (i = 0; act_1[i].flagname > 0; i++) 
	{
	  sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
		  act_1[i].what_you_type);
	}
    }
  for (i = 0; act_1[i].flagname > 0; i++)
    if (!str_cmp (buf, act_1[i].what_you_type))
      return act_1[i].flagname;
  
  
  if (!str_cmp(buf,"flaglist")) 
    {
      for (i = 0; act_3[i].flagname > 0; i++) 
	{
	  sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
		  act_3[i].what_you_type);
	}
    }
  for (i = 0; act_3[i].flagname > 0; i++)
    if (!str_cmp (buf, act_3[i].what_you_type))
      return act_3[i].flagname;
  
  if (!str_cmp(buf,"flaglist")) 
    {
      for (i = 0; act_4[i].flagname > 0; i++) 
	{
	  sprintf(hugebuf_o+strlen(hugebuf_o),"%-10s: ",
		  act_4[i].what_you_type);
	}
    }
  for (i = 0; act_4[i].flagname > 0; i++)
    if (!str_cmp (buf, act_4[i].what_you_type))
      return act_4[i].flagname;
  
  return 0;
}


/*
   * Returns the name of a wear bit.
 */
char *
wear_bit_name (int wear)
{
  int i;
  static char buf[512];
  buf[0] = '\0';
  for (i = 0; worn_flags[i].flagname != 0; i++)
    {
      if (wear & worn_flags[i].flagname)
	{
	  strcat(buf, " ");  
	  strcat(buf, worn_flags[i].what_you_type);
	}
    }
  return (buf[0] != '\0') ? buf + 1 : "none";
}

/*
   * Returns the bit, given a certain name.
 */
int 
wear_name_bit (char *buf)
{
 int i;
 for (i = 0; worn_flags[i].flagname > 0; i++)
   {
     if (!str_cmp(buf, worn_flags[i].what_you_type))
       return worn_flags[i].flagname;
   }
 return 0;
}

char *
area_bit_name (int areaflags)
{
  int i;
  static char buf[512];
  buf[0] = '\0';
  for (i = 0; area_flagss[i].flagname != 0; i++)
    {
      if (areaflags & area_flagss[i].flagname)
	{
	  strcat(buf, " ");  
	  strcat(buf, area_flagss[i].what_you_type);
	}
    }
  return (buf[0] != '\0') ? buf + 1 : "none";
}


int 
area_name_bit (char *buf)
{
 int i;
 for (i = 0; area_flagss[i].flagname > 0; i++)
   {
     if (!str_cmp(buf, area_flagss[i].what_you_type))
       return area_flagss[i].flagname;
   }
 return 0;
}

/*
   * Return ascii name of wear location.
 */
char *
wear_loc_name (int wearloc)
{
  static char retv[35];
  int i;
  for (i = 1; worn_flags[i].flagname > 0; i++)
    if (IS_SET(worn_flags[i].flagname, wearloc))
      {
	strcpy(retv, worn_flags[i].what_you_type);
	return retv;
	break;
      }
  strcpy(retv, "unknown");
  return retv;
}
  
int 
wear_name_loc (char *buf)
{
  int i;
  if (is_number (buf))
    {
      return atoi (buf);
    }
  for (i = 0; worn_flags[i].flagname > 0; i++)
    {
      if(!str_cmp(buf, worn_flags[i].what_you_type))
	return worn_flags[i].flagname;
    }
  return WEAR_NONE;
}

/*
   * Sees if last char is 's' and returns 'is' or 'are' pending.
 */
char *
is_are (char *text)
{
  while (*text != '\0')
    {
      text++;
    }
  text--;
  if (*text == 's' || *text == 'S')
    return "are";
  else
    return "is";
}


/*
   * Get an extra description from a list.
 */
char *
get_extra_descr (const char *name, DESCRIPTION_DATA * ed)
{
  for (; ed != NULL; ed = ed->next)
    {
      if (is_name (name, ed->keyword))
	return ed->description;
    }
  return NULL;
}

bool 
use_tool (SINGLE_OBJECT * obj, int bit)
{
  I_TOOL *t;
  if (obj == NULL
      || obj->pIndexData->item_type != ITEM_TOOL)
    return FALSE;
  t = (I_TOOL *) obj->more;
  if (!IS_SET (t->tool_type, bit))
    return FALSE;
  if (t->uses <= 0)
    return FALSE;
  t->uses--;
  return TRUE;
}

int 
PERCENTAGE (int amount, int max)
{
  if (max > 0) 
    return ((100 * amount)/max);
  return 100;
}

bool 
find_str (char *str1, char *str2)
{
  bool found;
  int length;
  char *str;
  length = strlen (str2);
  str = str2;
  found = 0;
  while (*str1 != '\0' && *str2 != '\0')
    {
      if (*str2 == *str1)
	{
	  found++;
	  str2++;
	}
      else
	{
	  found = 0;
	  str2 = str;
	}
      str1++;
    }
  if (found != length)
    found = 0;
  return found;
}