/
Archipelago/
Archipelago/doc/
Archipelago/lib/misc/
Archipelago/lib/plrobjs/
Archipelago/lib/plrobjs/P-T/
Archipelago/lib/world/mob/
Archipelago/lib/world/obj/
Archipelago/lib/world/shp/
Archipelago/lib/world/wld/
Archipelago/lib/world/zon/
Archipelago/slave/
/* ************************************************************************
*  handler.c                                     Part of CircleMUD        *
*  Usage: internal funcs: moving and finding chars/objs                   *
*                                                                         *
*  All rights reserved.  See license.doc for complete information.        *
*                                                                         *
*  Copyright (C) 1993 by the Trustees of the Johns Hopkins University     *
*  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
************************************************************************ */
/* Archipelago changes by Alastair J. Neil Copyright (C) 1993, 94, 95, 96 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <assert.h>

#include "structs.h"
#include "utils.h"
#include "comm.h"
#include "db.h"
#include "handler.h"
#include "interpreter.h"
#include "spells.h"

/* external vars */
extern struct room_data *world;
extern struct obj_data *object_list;
extern struct char_data *character_list;
extern struct index_data *mob_index;
extern struct index_data *obj_index;
extern struct descriptor_data *descriptor_list;
extern char	*MENU;
extern char	*ANSI_MENU;
extern int    top_of_world;
/* external functions */
int     report_money_weight(int amount);
void    set_timer(struct obj_data *object);
void    clear_timer(struct obj_data *object);
void	free_char(struct char_data *ch);
void	stop_fighting(struct char_data *ch);
void	remove_follower(struct char_data *ch);
void	clearMemory(struct char_data *ch);
void    snarf_limited_from_char(struct obj_data *object);
int     can_see_hidden(struct char_data *sub, struct char_data *obj);
void    add_event(int plse, int event, int inf1, int inf2, int inf3
	       , int inf4, char *arg, void *subj, void *vict);
void    limited_from_char(int obj_no);
void    limited_to_char(int obj_no);
void    extract_event(struct char_data *ch);
void    extract_limited(int obj_no);
char    *report_cost(int gold);
void    unhitch(struct char_data *ch, struct obj_data *cart, struct char_data *vict, char quiet);
void    free_hitched(struct obj_data *obj);
void    extinguish_light(struct obj_data *obj);
int     illumination_level(int value, struct char_data *ch);
bool    can_see_obj(struct char_data *ch, struct obj_data *vict);
bool    can_see_char(struct char_data *ch, struct char_data *vict);
void    remove_weight_from_char(struct char_data *ch, int amount);
void    add_weight_to_char(struct char_data *ch, int amount);
void change_gold(struct char_data *ch, int amount);
		 
void change_gold(struct char_data *ch, int amount)
{
  remove_weight_from_char(ch, report_money_weight(GET_GOLD(ch)));
  GET_GOLD(ch) += amount;
  add_weight_to_char(ch, report_money_weight(GET_GOLD(ch)));
}
void add_weight_to_char(struct char_data *ch, int amount)
{
  IS_CARRYING_W(ch) += amount;
  if (ch->specials.carried_by)
    IS_CARRYING_W(ch->specials.carried_by) += amount;
  if (ch->specials.mount)
    IS_CARRYING_W(ch->specials.mount) += amount;      
  
}

void remove_weight_from_char(struct char_data *ch, int amount)
{
  IS_CARRYING_W(ch) -= amount;
  if (IS_CARRYING_W(ch) < 0)
    IS_CARRYING_W(ch) =0;
  if (ch->specials.carried_by) {
    IS_CARRYING_W(ch->specials.carried_by)-= amount;
    if (IS_CARRYING_W(ch->specials.carried_by) < 0)
      IS_CARRYING_W(ch->specials.carried_by) =0;
  }
  if (ch->specials.mount) {
    IS_CARRYING_W(ch->specials.mount) -= amount;
    if (IS_CARRYING_W(ch->specials.mount) < 0)
      IS_CARRYING_W(ch->specials.mount) =0;
  }
}

char	*fname(char *namelist)
{
   static char	holder[30];
   register char	*point;

   for (point = holder; isalpha(*namelist); namelist++, point++)
      *point = *namelist;

   *point = '\0';

   return(holder);
}


int	isname(char *str, char *namelist)
{
   register char	*curname, *curstr;

   curname = namelist;
   for (; ; ) {
      for (curstr = str; ; curstr++, curname++) {
	 if (!*curstr && !isalpha(*curname))
	    return(1);

	 if (!*curname)
	    return(0);

	 if (!*curstr || *curname == ' ')
	    break;

	 if (LOWER(*curstr) != LOWER(*curname))
	    break;
      }

      /* skip to next name */

      for (; isalpha(*curname); curname++)
	 ;
      if (!*curname)
	 return(0);
      curname++;			/* first char of new name */
   }
}



void	affect_modify(struct char_data *ch, byte loc, sbyte mod, long bitv, bool add)
{
   int	maxabil;

   if (add) {
      SET_BIT(ch->specials.affected_by, bitv);
   } else {
      REMOVE_BIT(ch->specials.affected_by, bitv);
      mod = -mod;
   }


   maxabil = (IS_NPC(ch) ? 30 : 30);

   switch (loc) {
   case APPLY_NONE: break;

   case APPLY_STR:
       if (GET_STR(ch) + mod > 30)
	   mod = 30 - GET_STR(ch);
       GET_STR(ch) += mod;
       break;
   case APPLY_DEX:
       if (GET_DEX(ch) + mod > 30)
	   mod = 30 - GET_DEX(ch);
       GET_DEX(ch) += mod;
       break;
   case APPLY_INT:
       if (GET_INT(ch) + mod > 30)
	   mod = 30 - GET_INT(ch);
       GET_INT(ch) += mod;
       break;
   case APPLY_WIS:
       if (GET_WIS(ch) + mod > 30)
	   mod = 30 - GET_WIS(ch);
       GET_WIS(ch) += mod;
       break;
   case APPLY_CON:
       if (GET_CON(ch) + mod > 30)
	   mod = 30 - GET_CON(ch);
       GET_CON(ch) += mod;
       break;
   case APPLY_CHR:
       if (GET_CHR(ch) + mod > 30)
	   mod = 30 - GET_CHR(ch);
       GET_CHR(ch) += mod;
       break;
   case APPLY_PER:
       if (GET_PER(ch) + mod > 30)
	   mod = 30 - GET_PER(ch);
       GET_PER(ch) += mod;
       break;
   case APPLY_GUI:
       if (GET_GUI(ch) + mod > 30)
	   mod = 30 - GET_GUI(ch);
       GET_GUI(ch) += mod;
       break;
   case APPLY_LUC:
       if (GET_LUC(ch) + mod > 30)
           mod = 30 - GET_LUC(ch);
       GET_LUC(ch) += mod;
       break;
   case APPLY_FOCUS:
       if (GET_FOC(ch) + mod > 30)
	   mod = 30 - GET_FOC(ch);
       GET_FOC(ch) += mod;
       break;
   case APPLY_DEVOTION:
       if (GET_DEV(ch) + mod > 30)
	   mod = 30 - GET_DEV(ch);
       GET_DEV(ch) += mod;
       break;       
       
   case APPLY_SEX:
      break;

   case APPLY_RACE:
      break;

   case APPLY_LEVEL:
      break;

   case APPLY_AGE:
      ch->player.time.birth -= (mod * SECS_PER_MUD_YEAR);
      break;

   case APPLY_CHAR_WEIGHT:
      GET_WEIGHT(ch) += mod;
      break;

   case APPLY_CHAR_HEIGHT:
      GET_HEIGHT(ch) += mod;
      break;

   case APPLY_MANA:
      break;

   case APPLY_POWER:
      break;       

   case APPLY_HIT:
      ch->points.max_hit += mod;
      break;

   case APPLY_MOVE:
      ch->points.max_move += mod;
      break;

   case APPLY_GOLD:
      break;

   case APPLY_EXP:
      break;

   case APPLY_BODY_AC:
      GET_BODY_AC(ch) += mod;
      break;

   case APPLY_LEGS_AC:
       GET_LEGS_AC(ch) += mod;
      break;

   case APPLY_ARMS_AC:
      GET_ARMS_AC(ch) += mod;
      break;

   case APPLY_HEAD_AC:
      GET_HEAD_AC(ch) += mod;
      break;

   case APPLY_ALL_STOPPING:
       GET_BODY_STOPPING(ch) += mod;
       GET_LEGS_STOPPING(ch) += mod;
       GET_ARMS_STOPPING(ch) += mod;
       GET_HEAD_STOPPING(ch) += mod;
      break;
   case APPLY_ALL_AC:
       GET_BODY_AC(ch) += mod;
       GET_LEGS_AC(ch) += mod;
       GET_ARMS_AC(ch) += mod;
       GET_HEAD_AC(ch) += mod;
       break;              

   case APPLY_BODY_STOPPING:
      GET_BODY_STOPPING(ch) += mod;
      break;

   case APPLY_LEGS_STOPPING:
      GET_LEGS_STOPPING(ch) += mod;
      break;

   case APPLY_ARMS_STOPPING:
      GET_ARMS_STOPPING(ch) += mod;
      break;
       
   case APPLY_HEAD_STOPPING:
      GET_HEAD_STOPPING(ch) += mod;
      break;

   case APPLY_HITROLL:
      GET_HITROLL(ch) += mod;
      break;

   case APPLY_DAMROLL2:
      GET_DAMROLL2(ch) += mod;
      break;
   case APPLY_HITROLL2:
      GET_HITROLL2(ch) += mod;
      break;

   case APPLY_DAMROLL:
      GET_DAMROLL(ch) += mod;
      break;
      
   case APPLY_ALL_SAVE:
      ch->specials2.apply_saving_throw[0] += mod;
      ch->specials2.apply_saving_throw[1] += mod;
      ch->specials2.apply_saving_throw[2] += mod;
      ch->specials2.apply_saving_throw[3] += mod;
      ch->specials2.apply_saving_throw[4] += mod;       
       break;              
   case APPLY_SAVING_PARA:
      ch->specials2.apply_saving_throw[0] += mod;
      break;

   case APPLY_SAVING_ROD:
      ch->specials2.apply_saving_throw[1] += mod;
      break;

   case APPLY_SAVING_PETRI:
      ch->specials2.apply_saving_throw[2] += mod;
      break;

   case APPLY_SAVING_BREATH:
      ch->specials2.apply_saving_throw[3] += mod;
      break;

   case APPLY_SAVING_SPELL:
      ch->specials2.apply_saving_throw[4] += mod;
      break;

   default:
      logg("SYSERR: Unknown apply adjust attempt (handler.c, affect_modify).");
      break;

   } /* switch */
}



/* This updates a character by subtracting everything he is affected by */
/* restoring original abilities, and then affecting all again           */
void	affect_total(struct char_data *ch)
{
   struct affected_type *af;
   int	i, j;

   for (i = 0; i < MAX_WEAR; i++) {
     if (ch->equipment[i])
       for (j = 0; j < MAX_OBJ_AFFECT; j++) {
	 if ((i == HOLD)  &&
	     (ch->equipment[i]->obj_flags.type_flag == ITEM_WEAPON)
	     && (ch->equipment[i]->affected[j].location == APPLY_DAMROLL))
	   affect_modify(ch, APPLY_DAMROLL2,
			 ch->equipment[i]->affected[j].modifier,
			 ch->equipment[i]->obj_flags2.bitvector_aff, FALSE);
	 else if ((i == HOLD)  &&
		  (ch->equipment[i]->obj_flags.type_flag == ITEM_WEAPON)
		  && (ch->equipment[i]->affected[j].location == APPLY_HITROLL))
	   affect_modify(ch, APPLY_HITROLL2,
			 ch->equipment[i]->affected[j].modifier,
			 ch->equipment[i]->obj_flags2.bitvector_aff, FALSE);
	 else
	   affect_modify(ch, ch->equipment[i]->affected[j].location,
			 ch->equipment[i]->affected[j].modifier,
			 ch->equipment[i]->obj_flags2.bitvector_aff, FALSE);
	 
	 
       }
   }
   
   for (af = ch->affected; af; af = af->next)
      affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE);

   ch->tmpabilities = ch->abilities;


   for (i = 0; i < MAX_WEAR; i++) {
     if (ch->equipment[i])
       for (j = 0; j < MAX_OBJ_AFFECT; j++) {
	 if ((i == HOLD)  &&
	     (ch->equipment[i]->obj_flags.type_flag == ITEM_WEAPON)
	     && (ch->equipment[i]->affected[j].location == APPLY_DAMROLL))
	   affect_modify(ch, APPLY_DAMROLL2,
			 ch->equipment[i]->affected[j].modifier,
			 ch->equipment[i]->obj_flags2.bitvector_aff, TRUE);
	 else if ((i == HOLD)  &&
		  (ch->equipment[i]->obj_flags.type_flag == ITEM_WEAPON)
		  && (ch->equipment[i]->affected[j].location == APPLY_HITROLL))
	   affect_modify(ch, APPLY_HITROLL2,
			 ch->equipment[i]->affected[j].modifier,
			 ch->equipment[i]->obj_flags2.bitvector_aff, TRUE);
	 else
	   affect_modify(ch, ch->equipment[i]->affected[j].location,
			 ch->equipment[i]->affected[j].modifier,
			 ch->equipment[i]->obj_flags2.bitvector_aff, TRUE);
       }
   }
   for (af = ch->affected; af; af = af->next)
      affect_modify(ch, af->location, af->modifier, af->bitvector, TRUE);

   /* Make certain values are between 0..25, not < 0 and not > 25! */

   i = (IS_NPC(ch) ? 30 : 30);

   GET_DEX(ch) = MAX(0, MIN(GET_DEX(ch), i));
   GET_INT(ch) = MAX(0, MIN(GET_INT(ch), i));
   GET_WIS(ch) = MAX(0, MIN(GET_WIS(ch), i));
   GET_CON(ch) = MAX(0, MIN(GET_CON(ch), i));
   GET_STR(ch) = MAX(0, GET_STR(ch));

   if (IS_NPC(ch)) 
      GET_STR(ch) = MIN(GET_STR(ch), i);
   if ((GET_RACE(ch) == RACE_HALF_ELF || GET_RACE(ch) == RACE_DWARF
       || GET_RACE(ch) == RACE_AMARYA || GET_RACE(ch) == RACE_ELVEN)
	&& !IS_AFFECTED(ch,AFF_INFRARED))
       SET_BIT(ch->specials.affected_by, AFF_INFRARED);
   if (GET_RACE(ch) == RACE_TROLL)
       SET_BIT(ch->specials.affected_by, AFF_HEALING);
   if (GET_RACE(ch) == RACE_PIXIE && !IS_AFFECTED(ch,AFF_FLY))
       SET_BIT(ch->specials.affected_by, AFF_FLY);
   if (GET_RACE(ch) == RACE_MERMAN && !IS_AFFECTED(ch,AFF_WATER_BREATH))
       SET_BIT(ch->specials.affected_by, AFF_WATER_BREATH);
   if (GET_RACE(ch) == RACE_MERMAN && !IS_AFFECTED(ch,AFF_FREE_ACTION))
       SET_BIT(ch->specials.affected_by, AFF_FREE_ACTION);   
   
}



/* Insert an affect_type in a char_data structure
   Automatically sets apropriate bits and apply's */
void	affect_to_char( struct char_data *ch, struct affected_type *af )
{
   struct affected_type *affected_alloc;

   CREATE(affected_alloc, struct affected_type, 1);

   *affected_alloc = *af;
   affected_alloc->next = ch->affected;
   ch->affected = affected_alloc;

   affect_modify(ch, af->location, af->modifier, af->bitvector, TRUE);
   affect_total(ch);
}



/* Remove an affected_type structure from a char (called when duration
   reaches zero). Pointer *af must never be NULL! Frees mem and calls 
   affect_location_apply                                                */
void	affect_remove( struct char_data *ch, struct affected_type *af )
{
   struct affected_type *hjp;

   assert(ch->affected);

   affect_modify(ch, af->location, af->modifier, af->bitvector, FALSE);

   /* remove structure *af from linked list */
   if (ch->affected == af) {
      /* remove head of list */
      ch->affected = af->next;
   } else {
      for (hjp = ch->affected; (hjp->next) && (hjp->next != af); hjp = hjp->next)
	 ;

      if (hjp->next != af) {
	 logg("SYSERR: FATAL : Could not locate affected_type in ch->affected. (handler.c, affect_remove)");
	 exit(1);
      }
      hjp->next = af->next; /* skip the af element */
   }

   free (af);

   affect_total(ch);
}



/* Call affect_remove with every spell of spelltype "skill" */
void	affect_from_char( struct char_data *ch, int skill)
{
   struct affected_type *hjp, *next;

   for (hjp = ch->affected; hjp; hjp = next){
     next = hjp->next;
     if (hjp->type == skill)
       affect_remove(ch, hjp);
   }
}

/* Return if a char is affected by a spell (SPELL_XXX), NULL indicates 
   not affected                                                        */
struct affected_type  *affected_by_spell( struct char_data *ch, int skill )
{
   struct affected_type *hjp;

   for (hjp = ch->affected; hjp; hjp = hjp->next)
      if (hjp->type == skill)
	 return(hjp);

   return(FALSE);
}



void	affect_join( struct char_data *ch, struct affected_type *af,
bool avg_dur, bool avg_mod )
{
   struct affected_type *hjp;
   bool found = FALSE;

   for (hjp = ch->affected; !found && hjp; hjp = hjp->next) {
      if ( hjp->type == af->type ) {

	 af->duration += hjp->duration;
	 if (avg_dur)
	    af->duration /= 2;

	 af->modifier += hjp->modifier;
	 if (avg_mod)
	    af->modifier /= 2;

	 affect_remove(ch, hjp);
	 affect_to_char(ch, af);
	 found = TRUE;
      }
   }
   if (!found)
      affect_to_char(ch, af);
}


/* move a player out of a room */
void	char_from_room(struct char_data *ch)
{
   struct char_data *i;
   struct room_data *rm;

   if (ch->in_room >= 0 && ch->in_room <= top_of_world){
       rm = &world[ch->in_room];
       if (world[ch->in_room].obj){
	   GET_OBJ_WEIGHT(world[ch->in_room].obj) =
	        MAX(100,GET_OBJ_WEIGHT(world[ch->in_room].obj)
		     - GET_WEIGHT(ch));
	   GET_OBJ_WEIGHT(world[ch->in_room].obj) =
	       MAX(100,GET_OBJ_WEIGHT(world[ch->in_room].obj)
		   - IS_CARRYING_W(ch));		   
       }

       if (ch == world[ch->in_room].people)  /* head of list */
	   world[ch->in_room].people = ch->next_in_room;
       else /* locate the previous element */ {
	   for (i = world[ch->in_room].people; i->next_in_room &&
		i->next_in_room != ch; i = i->next_in_room)
	       ;
	   
	   i->next_in_room = ch->next_in_room;
       }
       ch->in_room = NOWHERE;
       ch->next_in_room = 0;
       rm->light = compute_room_light_value(rm);
   }

}


/* place a character in a room */
void	char_to_room(struct char_data *ch, int room, bool virtual)
{
   void	raw_kill(struct char_data *ch);

   if (virtual)
       room = real_room(room);

   ch->next_in_room = world[room].people;
   world[room].people = ch;

	   
   ch->in_room = room;
   if((world[ch->in_room].sector_type== SECT_UNDER_WATER) ||
      (world[ch->in_room].sector_type== SECT_WATER_SWIM) ||
      (world[ch->in_room].sector_type== SECT_WATER_NOSWIM))
       water_extinguish_lights(ch);

   if (world[ch->in_room].tele_delay > -1 &&
       (!IS_NPC(ch) || IS_AFFECTED(ch, AFF_CHARM))) {
       add_event(world[ch->in_room].tele_delay,
		 EVENT_TELEPORT,0,0,0,0,0,&world[ch->in_room],ch);
       if (ch->specials.mount)
	 add_event(world[ch->in_room].tele_delay,EVENT_TELEPORT
		   ,0,0,0,0,0,&world[ch->in_room],ch->specials.mount);
   }
   if (world[room].obj){
       GET_OBJ_WEIGHT(world[room].obj) += GET_WEIGHT(ch);
       GET_OBJ_WEIGHT(world[room].obj) += IS_CARRYING_W(ch);
       }
   world[room].light = compute_room_light_value(&world[room]);
}


/* give an object to a char   */
void	obj_to_char(struct obj_data *object, struct char_data *ch, int mode)
{
    struct obj_data *tmp;
    int virtual;
    
    object->next_content = ch->inventory;
    ch->inventory = object;
    object->carried_by = ch;
    object->in_room = NOWHERE;
    add_weight_to_char(ch,GET_OBJ_WEIGHT(object));
    IS_CARRYING_N(ch)++;
    clear_timer(object);
    if (mode == 0 && !IS_NPC(ch)){
	if (object->obj_flags.value[6] >0)
	    {
		virtual = (object->item_number >= 0) ? obj_index[object->item_number].virtual : 0;
		limited_to_char(virtual);
	    }
	if (object->contains)
	    for (tmp = object->contains;tmp;tmp = tmp->next_content)
		if (tmp->obj_flags.value[6] > 0)
		    {
			virtual = (tmp->item_number >= 0) ? obj_index[tmp->item_number].virtual : 0;
			limited_to_char(virtual);
		    }
	
    }
    /* set flag for crash-save system */
    SET_BIT(PLR_FLAGS(ch), PLR_CRASH);
}


/* take an object from a char */
void	obj_from_char(struct obj_data *object, int mode)
{
    struct obj_data *tmp;
    struct char_data *ch;

    ch = object->carried_by;
    
    if (object->carried_by->inventory == object)   /* head of list */
	object->carried_by->inventory = object->next_content;
    
    else {
	for (tmp = object->carried_by->inventory; 
	     tmp && (tmp->next_content != object); 
	     tmp = tmp->next_content)
	   ; /* locate previous */
	
       tmp->next_content = object->next_content;
    }
    if (GET_LEVEL(ch) < LEVEL_BUILDER)
	set_timer(object);
     /* set flag for crash-save system */
    SET_BIT(PLR_FLAGS(object->carried_by), PLR_CRASH);

    remove_weight_from_char(object->carried_by,GET_OBJ_WEIGHT(object));
    IS_CARRYING_N(object->carried_by)--;
    if (mode == 0 && !IS_NPC(ch))
	snarf_limited_from_char(object);
    object->carried_by = 0;
    object->next_content = 0;
}

void set_timer(struct obj_data *object)
{
    struct obj_data *tmp;
    
    if ( (GET_ITEM_TYPE(object) == ITEM_CONTAINER)
	 && (object->obj_flags.value[3]) )
	return;
    object->obj_flags.timer = 24;
    if (object->contains)
	for (tmp = object->contains;tmp;tmp = tmp->next_content)
	    set_timer(tmp);
}

void clear_timer(struct obj_data *object)
{
    struct obj_data *tmp;
    
    if ( (GET_ITEM_TYPE(object) == ITEM_CONTAINER)
	 && (object->obj_flags.value[3]) )
	return;
    object->obj_flags.timer = -1;
    if (object->contains)
	for (tmp = object->contains;tmp;tmp = tmp->next_content)
	    clear_timer(tmp);
}

void snarf_limited_from_char(struct obj_data *object)
{
    int virtual;
    struct obj_data *tmp;
    
    if (object->obj_flags.value[6] >0)
	{
	  virtual = (object->item_number >= 0) ? obj_index[object->item_number].virtual : 0;
	  limited_from_char(virtual);
	}
    if (object->contains)
      for (tmp = object->contains;tmp;tmp = tmp->next_content)
	if (tmp->obj_flags.value[6] > 0)
	  {
	    virtual = (tmp->item_number >= 0) ? obj_index[tmp->item_number].virtual : 0;
	    limited_from_char(virtual);
	  }
    
}

/* Return the effect of a piece of armor in position eq_pos */
int	apply_ac(struct char_data *ch, int eq_pos)
{
   int factor;

   assert(ch->equipment[eq_pos]);

   if (!(GET_ITEM_TYPE(ch->equipment[eq_pos]) == ITEM_ARMOR))
      return 0;

   switch (eq_pos) {

   case WEAR_BODY	: factor = 3; break;	/* 30% */
   case WEAR_HEAD	: factor = 2; break;	/* 20% */
   case WEAR_LEGS	: factor = 2; break;	/* 20% */
   default		: factor = 1; break;	/* all others 10% */
   }

   return (factor * ch->equipment[eq_pos]->obj_flags.value[0]);
}



void	equip_char(struct char_data *ch, struct obj_data *obj, int pos)
{
   int	j,damg;

   assert(pos >= 0 && pos < MAX_WEAR);

   if (ch->equipment[pos]) {
      sprintf(buf, "SYSERR: Char is already equipped: %s, %s", GET_NAME(ch),
	      obj->short_description);
      logg(buf);
      return;
   }

   if (obj->carried_by) {
      logg("SYSERR: EQUIP: Obj is carried_by when equip.");
      return;
   }

   if (obj->in_room != NOWHERE) {
      logg("SYSERR: EQUIP: Obj is in_room when equip.");
      return;
   }

   if ((IS_OBJ_STAT(obj, ITEM_ANTI_EVIL) && IS_EVIL(ch)) || 
       (IS_OBJ_STAT(obj, ITEM_ANTI_GOOD) && IS_GOOD(ch)) || 
       (IS_OBJ_STAT(obj, ITEM_ANTI_NEUTRAL) && IS_NEUTRAL(ch))) {
      if (ch->in_room != NOWHERE) {

	 act("You are zapped by $p and instantly drop it.", FALSE, ch, obj, 0, TO_CHAR);
	 act("$n is zapped by $p and instantly drops it.", FALSE, ch, obj, 0, TO_ROOM);
	 obj_to_room(obj, ch->in_room, FALSE);
	 return;
      } else {

	 act("You are zapped by $p and instantly drop it.", FALSE, ch, obj, 0, TO_CHAR);
	 act("$n is zapped by $p and instantly drops it.", FALSE, ch, obj, 0, TO_ROOM);
	 obj_to_char(obj, ch,1); /* what happens if you drop something in NOWHERE? */
      }
   }
   ch->equipment[pos] = obj;
   damg = obj->obj_flags.value[4];
   if (GET_ITEM_TYPE(obj) == ITEM_ARMOR)
       switch(pos) {
       case WEAR_BODY:
	   GET_BODY_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_BODY_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_BACK:
	   GET_BODY_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_BODY_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_LEGS:
	 GET_LEGS_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	 GET_LEGS_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	 break;
       case WEAR_ARMS:
	 GET_ARMS_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	 GET_ARMS_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	 break;
       case WEAR_WRIST_R:
	 GET_ARMS_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	 GET_ARMS_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	 break;	   
       case WEAR_FINGER_R:
	 GET_ARMS_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	 GET_ARMS_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	 break;	   
       case WEAR_HEAD:
	 GET_HEAD_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	 GET_HEAD_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	 break;
       case WEAR_NECK_1:
	 GET_HEAD_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	 GET_HEAD_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	 break;
       case WEAR_EYES:
	   GET_HEAD_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_EARS_R:
	   GET_HEAD_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;	   
       case WEAR_MOUTH:
	   GET_HEAD_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;	   
       case WEAR_HANDS:
	   GET_ARMS_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_ARMS_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_FEET:
 	   GET_LEGS_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_LEGS_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       default:
	   GET_BODY_AC(ch) -= (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_BODY_STOPPING(ch) += (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       }
   obj->worn_by = ch;
   
   for (j = 0; j < MAX_OBJ_AFFECT; j++) {
     if (pos == HOLD &&
	 (obj->obj_flags.type_flag == ITEM_WEAPON) &&
	 (obj->affected[j].location == APPLY_DAMROLL))
       affect_modify(ch, APPLY_DAMROLL2,
		     obj->affected[j].modifier,
		     obj->obj_flags2.bitvector_aff, TRUE);
     else if (pos == HOLD &&
	      (obj->obj_flags.type_flag == ITEM_WEAPON) &&
	      (obj->affected[j].location == APPLY_HITROLL))
       affect_modify(ch, APPLY_HITROLL2,
		     obj->affected[j].modifier,
		     obj->obj_flags2.bitvector_aff, TRUE);
     else
       affect_modify(ch, obj->affected[j].location,
		     obj->affected[j].modifier,
		     obj->obj_flags2.bitvector_aff, TRUE);
   }
   if (obj->obj_flags.type_flag == ITEM_LIGHT
       && !IS_OBJ_STAT(obj, ITEM_GLOW))
     SET_BIT(obj->obj_flags.extra_flags, ITEM_GLOW);
   ch->light = compute_char_light_value(ch);
   if (ch->in_room >=0 && ch->in_room <= top_of_world)
     world[ch->in_room].light = compute_room_light_value(&world[ch->in_room]);
   affect_total(ch);
}



struct obj_data *unequip_char(struct char_data *ch, int pos)
{
   int	j,damg;
   struct obj_data *obj;

   assert(pos >= 0 && pos < MAX_WEAR);
   assert(ch->equipment[pos]);
   
   obj = ch->equipment[pos];
   damg = obj->obj_flags.value[4];
   if (GET_ITEM_TYPE(obj) == ITEM_ARMOR)
       switch(pos) {
       case WEAR_BODY:
	   GET_BODY_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_BODY_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_BACK:
	   GET_BODY_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_BODY_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_LEGS:
	   GET_LEGS_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_LEGS_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_ARMS:
	   GET_ARMS_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_ARMS_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_WRIST_R:
	   GET_ARMS_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_ARMS_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_FINGER_R:
	   GET_ARMS_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_ARMS_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_HEAD:
	   GET_HEAD_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_NECK_1:
	   GET_HEAD_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_EYES:
	   GET_HEAD_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_EARS_R:
	   GET_HEAD_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_MOUTH:
	   GET_HEAD_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_HEAD_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;	   
       case WEAR_HANDS:
	   GET_ARMS_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_ARMS_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       case WEAR_FEET:
	   GET_LEGS_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_LEGS_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       default:
	   GET_BODY_AC(ch) += (ch->equipment[pos]->obj_flags.value[0])*(10-damg)/10;
	   GET_BODY_STOPPING(ch) -= (ch->equipment[pos]->obj_flags.value[1])*(10-damg)/10;
	   break;
       }

   ch->equipment[pos] = 0;
   obj->worn_by = 0;

   for (j = 0; j < MAX_OBJ_AFFECT; j++) {
     if (pos == HOLD &&
	 (obj->obj_flags.type_flag == ITEM_WEAPON) &&
	 (obj->affected[j].location == APPLY_DAMROLL))
       affect_modify(ch, APPLY_DAMROLL2,
		     obj->affected[j].modifier,
		     obj->obj_flags2.bitvector_aff, FALSE);
     else if (pos == HOLD &&
	      (obj->obj_flags.type_flag == ITEM_WEAPON) &&
	      (obj->affected[j].location == APPLY_HITROLL))
       affect_modify(ch, APPLY_HITROLL2,
		     obj->affected[j].modifier,
		     obj->obj_flags2.bitvector_aff, FALSE);
     else
       affect_modify(ch, obj->affected[j].location,
		     obj->affected[j].modifier,
		     obj->obj_flags2.bitvector_aff, FALSE);
   }
   if (obj->obj_flags.type_flag == ITEM_LIGHT
       && IS_OBJ_STAT(obj, ITEM_GLOW))
     REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_GLOW);
   ch->light = compute_char_light_value(ch);
   if (ch->in_room >=0 && ch->in_room <= top_of_world)
     world[ch->in_room].light = compute_room_light_value(&world[ch->in_room]);
   affect_total(ch);

   return(obj);
}
int compute_room_light_value(struct room_data *room)
{
    struct char_data *tmp;
    struct obj_data *tmp_o;
    int light = 5, door;
    
    if (IS_SET(room->room_flags, DARK))
	light = -15;
    else if (room->sector_type != SECT_INSIDE
	     && !IS_SET(room->room_flags, INDOORS)) {
      switch(weather_info.sunlight) {
      case SUN_SET:
      case SUN_RISE:
	light = 2;
	break;
      case SUN_DARK:
	light = -5;
	break;
      default:
	light = 15;
	break;
      }
      switch(weather_info.moonlight) {
      case MOON_RISE:
      case MOON_SET:
	light += 2;
	break;
      case MOON_LIGHT:
	light += 4;
	break;
      default:
	break;
      }
      switch (weather_info.sky) {
      case SKY_CLOUDY:
	light -= 2;
	break;
      case SKY_RAINING:
	light -= 3;
	break;
      case SKY_LIGHTNING:
	light -= 4;
	break;
      default:
	break;
      }
    }
    if (room->sector_type == SECT_CITY)
      light += 7;
    if (room->sector_type == SECT_FIRE)
      light += 12;    
    if (room->sector_type == SECT_FOREST)
      light -= 4;
    if (room->sector_type == SECT_UNDER_WATER)
      light -= 10;
    
    for (door=0;door<=5;door++) {
      if (room->dir_option[door] &&
	  (room->dir_option[door]->to_room != NOWHERE) &&
	  !IS_SET(room->dir_option[door]->exit_info, EX_CLOSED) &&
	  !IS_SET(room->dir_option[door]->exit_info, EX_DARK) &&
	  (world[real_room(room->dir_option[door]->to_room)].light > 2)
	  && (light < 10) &&
	  ((room->sector_type == SECT_INSIDE ||
	    IS_SET(room->room_flags,INDOORS)) ||
	   (weather_info.sunlight == SUN_DARK)))
	light += world[real_room(room->dir_option[door]->to_room)].light/2;
    }
    for (tmp = room->people;tmp;tmp = tmp->next_in_room)
      {
	if (light < 10)
	  light += tmp->light;
	else if ((tmp->light > 3) || (tmp->light < 0))
	  light += tmp->light;
      }
    for (tmp_o = room->contents; tmp_o; tmp_o = tmp_o->next_content)
      if (IS_OBJ_STAT(tmp_o, ITEM_GLOW)) {
	if (light < 10)
	  light += MIN(7,tmp_o->obj_flags2.light/3);
	else if ((tmp_o->obj_flags2.light/3 > 3) ||
		 (tmp_o->obj_flags2.light/3 < 0))
	  light += MIN(7,tmp_o->obj_flags2.light/3);
      }
    return(light);
}
bool can_see_char(struct char_data *ch, struct char_data *vict)
{
  int vict_light;
  int invis_lev=0, lev=0;
  struct affected_type *af;
  
  for (af = ch->affected; af; af = af->next){
    if (af->type == SPELL_DETECT_INVISIBLE)
      lev = af->level;
  }
  
  if (IS_AFFECTED(ch, AFF_DETECT_INVISIBLE) && (lev == 0))
    lev = GET_LEVEL(ch);

  lev += GET_PER(ch);
  
  if (hates(ch, vict))
    lev += GET_PER(ch)/2;
  
  for (af = vict->affected; af; af = af->next){
    if ((af->type == SPELL_INVIS1) ||
	(af->type == SPELL_INVIS2) ||
	(af->type == SPELL_INVIS3))
      if (af->level > invis_lev)
	invis_lev = af->level;
  }
  if (IS_AFFECTED(vict, AFF_INVISIBLE) && (invis_lev == 0))
    invis_lev = GET_LEVEL(vict);
  
  if (IS_AFFECTED(vict, AFF_HIDE) && (invis_lev == 0))
    invis_lev = GET_LEVEL(vict);
  
  if ((invis_lev > 0) && (lev < invis_lev))
    return(FALSE);

  vict_light = compute_char_light_value(vict);
  switch(illumination_level(world[vict->in_room].light, ch)) {
  case -1:
    if ((vict_light > 3) && !number(0,7) && (GET_SIZE(vict) <= 4))
      return(TRUE);
    else if ((vict_light > 3) && !number(0,12) && (GET_SIZE(vict) > 4))
      return(TRUE);
    break;
  case 0:
    if ((vict_light > 3) && number(0,3) && (GET_SIZE(vict) <= 4))
      return(TRUE);
    else if ((vict_light > 3) && !number(0,3) && (GET_SIZE(vict) > 4))
      return(TRUE);
    break;
  case 1:    
    if ((vict_light >= 0) && (GET_SIZE(vict) <= 5))
      return(TRUE);
    if ((vict_light >= 0) && GET_PER(ch) > 15 && number(0,2)
	&& (GET_SIZE(vict) > 4))
      return(TRUE);
    break;
  case 2:
    if (vict_light < 20)
      return(TRUE);
    break;
  case 3:
    if (vict_light < 15)
      return(TRUE);
    break;
  case 4:
    if (vict_light < 10)
      return(TRUE);
    break;
  case 5:
    if (vict_light < 0)
      return(TRUE);
    break;
  }
  return(FALSE);
}
bool can_see_obj(struct char_data *ch, struct obj_data *vict)
{
  int vict_light=0;
  if (IS_OBJ_STAT(vict, ITEM_GLOW))
      vict_light = MIN(7,vict->obj_flags2.light/3);
  switch(illumination_level(world[vict->in_room].light, ch)) {
  case -1:
    if ((vict_light > 3) && !number(0,7) && (GET_OBJ_SIZE(vict) <= 4))
      return(TRUE);
    else if ((vict_light > 3) && !number(0,12) && (GET_OBJ_SIZE(vict) > 4))
      return(TRUE);
    break;
  case 0:
    if ((vict_light > 3) && !number(0,3) && (GET_OBJ_SIZE(vict) <= 4))
      return(TRUE);
    else if ((vict_light > 3) && !number(0,7) && (GET_OBJ_SIZE(vict) > 4))
      return(TRUE);
    break;
  case 1:    
    if ((vict_light >= 0) && (GET_OBJ_SIZE(vict) <= 4))
      return(TRUE);
    if ((vict_light >= 0) && !number(0,1) && (GET_OBJ_SIZE(vict) > 4))
      return(TRUE);
    break;
  case 2:
    if ((vict_light >= -2)  && (vict_light < 10) && (GET_OBJ_SIZE(vict) < 6))
      return(TRUE);
    if ((vict_light >= -2) && !number(0,1) && (vict_light < 10)
	&& (GET_OBJ_SIZE(vict) > 5))
      return(TRUE);
    break;
  case 3:
    if (vict_light < 15)
      return(TRUE);
    break;
  case 4:
    if (vict_light < 10)
      return(TRUE);
    break;
  case 5:
    if (vict_light < 0)
      return(TRUE);
    break;
  }
  return(FALSE);
}

int illumination_level(int value, struct char_data *ch)
{
  if (GET_RACE(ch) == RACE_DWARF)
    value += 3;
  if (GET_RACE(ch) == RACE_ELVEN)
    value += 2;
  if (GET_RACE(ch) == RACE_TROLL)
    value += 2;
  if (GET_RACE(ch) == RACE_HALF_ELF)
    value += 1;
  if (GET_RACE(ch) == RACE_AMARYA)
    value += 2;
  if (GET_RACE(ch) == RACE_MERMAN)
    value += 3;  
  if (IS_AFFECTED(ch, AFF_INFRARED))
    value += 7;

  if (value < -10)
    return(-1);
  else if (value < 0)
    return(0);
  else if (value < 10)
    return(1);
  else if (value < 20)
    return(2);
  else if (value < 30)
    return(3);
  else if (value < 40)
    return(4);
  else
    return(5);
}

int    compute_char_light_value(struct char_data *ch)
{
    int j,light=0;

    if (IS_AFFECTED(ch, AFF_SANCTUARY))
	light += 3;
    for (j=0; j< MAX_WEAR; j++)
      if (ch->equipment[j]
	  && IS_OBJ_STAT(ch->equipment[j], ITEM_GLOW)) {
	if (light < 10)
	  light += MIN(7,ch->equipment[j]->obj_flags2.light/2);
	else if ((ch->equipment[j]->obj_flags2.light/3 > 3) ||
		 (ch->equipment[j]->obj_flags2.light/3 < 0))
	  light += MIN(7,ch->equipment[j]->obj_flags2.light/2);
      }
    return(light);
}

int	get_number(char **name)
{

   int	i;
   char	*ppos;
   char	number[MAX_INPUT_LENGTH] = "";

   if ((ppos = strchr(*name, '.'))) {
      *ppos++ = '\0';
      strcpy(number, *name);
      strcpy(*name, ppos);
      
      for (i = 0; *(number + i); i++)
	 if (!isdigit(*(number + i)))
	    return(0);

      return(atoi(number));
   }

   return(1);
}


/* Search a given list for an object, and return a pointer to that object */
struct obj_data *get_obj_in_list(char *name, struct obj_data *list)
{
   struct obj_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);

   for (i = list, j = 1; i && (j <= number); i = i->next_content)
      if (isname(tmp, i->name)) {
	 if (j == number)
	    return(i);
	 j++;
      }

   return(0);
}



/* Search a given list for an object number, and return a ptr to that obj */
struct obj_data *get_obj_in_list_num(int num, struct obj_data *list)
{
   struct obj_data *i;

   for (i = list; i; i = i->next_content)
      if (i->item_number == num)
	 return(i);

   return(0);
}





/*search the entire world for an object, and return a pointer  */
struct obj_data *get_obj(char *name)
{
   struct obj_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);

   for (i = object_list, j = 1; i && (j <= number); i = i->next)
      if (isname(tmp, i->name)) {
	 if (j == number)
	    return(i);
	 j++;
      }

   return(0);
}





/*search the entire world for an object number, and return a pointer  */
struct obj_data *get_obj_num(int nr)
{
   struct obj_data *i;

   for (i = object_list; i; i = i->next)
      if (i->item_number == nr)
	 return(i);

   return(0);
}





/* search a room for a char, and return a pointer if found..  */
struct char_data *get_char_room(char *name, int room)
{
   struct char_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);
   
   for (i = world[room].people, j = 1; i && (j <= number); i = i->next_in_room)
      if (isname(tmp, i->player.name)) {
	 if (j == number)
	    return(i);
	 j++;
      }

   return(0);
}





/* search all over the world for a char, and return a pointer if found */
struct char_data *get_char(char *name)
{
   struct char_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);

   for (i = character_list, j = 1; i && (j <= number); i = i->next)
      if (isname(tmp, i->player.name)) {
	 if (j == number)
	    return(i);
	 j++;
      }

   return(0);
}



/* search all over the world for a char num, and return a pointer if found */
struct char_data *get_char_num(int nr)
{
   struct char_data *i;

   for (i = character_list; i; i = i->next)
      if (i->nr == nr)
	 return(i);

   return(0);
}




/* put an object in a room */
void	obj_to_room(struct obj_data *object, int room, bool virtual)
{
    if (virtual)
	room = real_room(room);
    if (world[room].obj)
	GET_OBJ_WEIGHT(world[room].obj) += GET_OBJ_WEIGHT(object);
    object->next_content = world[room].contents;
    world[room].contents = object;
    object->in_room = room;
    object->carried_by = 0;
    if (((world[object->in_room].sector_type== SECT_UNDER_WATER) ||
	 (world[object->in_room].sector_type== SECT_WATER_SWIM) ||
	 (world[object->in_room].sector_type== SECT_WATER_NOSWIM))  && (
	(object->obj_flags.type_flag == ITEM_LIGHT)
	&& IS_OBJ_STAT(object, ITEM_GLOW)))
	under_water_extinguish_light(object);
    if (room >= 0 && room <= top_of_world)
	world[room].light = compute_room_light_value(&world[room]);
}


/* Take an object from a room */
void	obj_from_room(struct obj_data *object)
{
   struct obj_data *i;
   struct room_data *rm;

   /* remove object from room */
   
   rm = &world[object->in_room];
   if (object == world[object->in_room].contents)  /* head of list */
      world[object->in_room].contents = object->next_content;
   else /* locate previous element in list */	 {
      for (i = world[object->in_room].contents; i && 
          (i->next_content != object); i = i->next_content)
	 ;

      i->next_content = object->next_content;
   }

   object->in_room = NOWHERE;
   object->next_content = 0;
   
   rm->light = compute_room_light_value(rm);
}


/* put an object in an object (quaint)  */
void	obj_to_obj(struct obj_data *obj, struct obj_data *obj_to)
{
   struct obj_data *tmp_obj;
   int to_room=0;
   if (GET_ITEM_TYPE(obj_to) == ITEM_CONTAINER)
     to_room = real_room(obj_to->obj_flags.value[3]);
   
   if (to_room > 0 && to_room < top_of_world ){
       if (obj->in_room != NOWHERE){
	   obj_from_room(obj);
	   obj_to_room(obj,to_room, FALSE);
       }
       else
	   obj_to_room(obj,to_room, FALSE);
       GET_OBJ_WEIGHT(obj_to) += GET_OBJ_WEIGHT(obj);
   }
   else{
       obj->next_content = obj_to->contains;
       obj_to->contains = obj;
       obj->in_obj = obj_to;
   
       for (tmp_obj = obj->in_obj; tmp_obj->in_obj; tmp_obj = tmp_obj->in_obj)
	   GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj);
       
       /* top level object.  Subtract weight from inventory if necessary. */
       GET_OBJ_WEIGHT(tmp_obj) += GET_OBJ_WEIGHT(obj);
       if (tmp_obj->carried_by)
	   add_weight_to_char(tmp_obj->carried_by,GET_OBJ_WEIGHT(obj));
   }
}


/* remove an object from an object */
void	obj_from_obj(struct obj_data *obj)
{
   struct obj_data *tmp, *obj_from;
   

   if (obj->in_obj) {
      obj_from = obj->in_obj;
      if (obj == obj_from->contains)   /* head of list */
	 obj_from->contains = obj->next_content;
      else {
	 for (tmp = obj_from->contains; 
	     tmp && (tmp->next_content != obj); 
	     tmp = tmp->next_content)
	    ; /* locate previous */

	 if (!tmp) {
	     perror("SYSERR: Fatal error in object structures.");
	     abort();
	 }

	 tmp->next_content = obj->next_content;
      }


      /* Subtract weight from containers container */
      for (tmp = obj->in_obj; tmp->in_obj; tmp = tmp->in_obj)
	  GET_OBJ_WEIGHT(tmp) -= GET_OBJ_WEIGHT(obj);
      
      /* Subtract weight from char that carries the object */
      GET_OBJ_WEIGHT(tmp) -= GET_OBJ_WEIGHT(obj);
      if (tmp->carried_by)
	remove_weight_from_char(tmp->carried_by,GET_OBJ_WEIGHT(obj));

      obj->in_obj = 0;
      obj->next_content = 0;
   }
   else {
      perror("SYSERR: Trying to object from object when in no object.");
      abort();
   }
}


/* Set all carried_by to point to new owner */
void	object_list_new_owner(struct obj_data *list, struct char_data *ch)
{
   if (list) {
      object_list_new_owner(list->contains, ch);
      object_list_new_owner(list->next_content, ch);
      list->carried_by = ch;
   }
}


/* Extract an object from the world */
void	extract_obj(struct obj_data *obj, int mode)
{
  struct obj_data *temp1, *temp2;
  
  if (!obj)
    return;
   
  if (obj->in_room != NOWHERE)
    obj_from_room(obj);
  else if (obj->carried_by)
    obj_from_char(obj,mode);
  else if (obj->in_obj) {
    temp1 = obj->in_obj;
    GET_OBJ_WEIGHT(temp1) -= GET_OBJ_WEIGHT(obj);
    if (temp1->contains == obj)   /* head of list */
      temp1->contains = obj->next_content;
    else
      {
	for ( temp2 = temp1->contains ; 
	      temp2 && (temp2->next_content != obj); 
	      temp2 = temp2->next_content )
	  ;
	
	if (temp2) {
	  temp2->next_content = 
	    obj->next_content;
	}
      }
  }
  
  for ( ; obj->contains; extract_obj(obj->contains,mode))
    ;
  /* leaves nothing ! */
  
  if (object_list == obj )       /* head of list */
    object_list = obj->next;
  else
    {
      for (temp1 = object_list; 
	   temp1 && (temp1->next != obj); 
	   temp1 = temp1->next)
	;
      
      if (temp1)
	temp1->next = obj->next;
    }
  if (obj->pulled_by)
    free_hitched(obj);
  if (HASROOM(obj))
    if (world[real_room(obj->obj_flags.value[3])].obj == obj)
      world[real_room(obj->obj_flags.value[3])].obj = 0;
  if (obj->obj_flags.value[6] > 0)
    extract_limited(obj_index[obj->item_number].virtual);
  if (obj->reset && obj->reset->num > 0)
    obj->reset->num--;
  if (obj->item_number >= 0)
    (obj_index[obj->item_number].number)--;
  free_obj(obj);
  obj=0;
}

void free_hitched(struct obj_data *obj)
{
  struct follow_type *k,*j;
  k = obj->pulled_by;
  while (k)
    {
      k->follower->specials.cart = 0;
      j = k->next;
      free(k);
      k = j;
    }
  obj->pulled_by = 0;
  return;

}
void water_extinguish_lights(struct char_data *ch)
{
    int j;
    struct obj_data *obj;

    for (j =0;j<=MAX_WEAR;j++)
	if (ch->equipment[j]
	    && ch->equipment[j]->obj_flags.type_flag == ITEM_LIGHT)
	    under_water_extinguish_light(ch->equipment[j]);
    for (obj=ch->inventory;obj; obj= obj->next_content)
	if (obj->obj_flags.type_flag != ITEM_LIGHT)
    	    under_water_extinguish_light(obj);
}
void under_water_extinguish_light(struct obj_data *obj)
{
    if (obj->obj_flags.type_flag != ITEM_LIGHT)
	return;
    if( obj->obj_flags2.light <= 0)
	return;
    obj->obj_flags2.light = 0;
    if (IS_OBJ_STAT(obj, ITEM_GLOW)){
	if (obj->worn_by){
	    act("$n's $o is extinguished.",FALSE,obj->worn_by,obj,0,TO_ROOM);
	    act("Your $o is extinguished.",FALSE,obj->worn_by,obj,0,TO_CHAR);

	}
	else if (obj->carried_by)
	    act("Your $o is extinguished.",FALSE,obj->carried_by,obj,0,TO_CHAR);
	else if (obj->in_room != NOWHERE)
	    act("$p is extinguished.",FALSE,0,obj,0,TO_ROOM);
	REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_GLOW);
    }
    extinguish_light(obj);    
}

void	update_object( struct obj_data *obj, int use)
{
    if ((obj->obj_flags2.light > 0)
	&& IS_OBJ_STAT(obj, ITEM_GLOW)
	&& !IS_OBJ_STAT(obj, ITEM_MAGIC)){
	obj->obj_flags2.light--;
	if ((obj->obj_flags2.light == 0) && obj->worn_by){
	    REMOVE_BIT(obj->obj_flags.extra_flags, ITEM_GLOW);
	    act("$n's $o stops glowing.",FALSE,obj->worn_by,obj,0,TO_ROOM);
	    act("Your $o stops glowing.",FALSE,obj->worn_by,obj,0,TO_CHAR);
	    if (obj->obj_flags.type_flag == ITEM_LIGHT)
		extinguish_light(obj);
	}
	else if ((obj->obj_flags2.light <= 4) && (obj->obj_flags2.light > 0)
		 && obj->worn_by)
    	    act("Your $o is growing dim.",FALSE,obj->worn_by,obj,0,TO_CHAR);
    }
    if (obj->obj_flags.timer > 0)
      obj->obj_flags.timer -= use;
   if (obj->contains)
      update_object(obj->contains, use);
   if (obj->next_content)
      update_object(obj->next_content, use);
}
void extinguish_light(struct obj_data *obj){
    sprintf(buf,"%s spent",obj->name);
    CREATE(obj->name, char,strlen(buf)+1);
    strcpy(obj->name, buf);
    sprintf(buf,"%s (spent)",obj->short_description);
    CREATE(obj->short_description,char, strlen(buf)+1);
    strcpy(obj->short_description, buf);
    sprintf(buf,"%s (spent)",obj->description);
    CREATE(obj->description,char, strlen(buf)+1);
    strcpy(obj->description, buf);
    obj->obj_flags.type_flag = ITEM_TRASH;
}

void	update_char_objects( struct char_data *ch )
{
   int	i;

   for (i = 0; i < MAX_WEAR; i++)
       if (ch->equipment[i])
	   update_object(ch->equipment[i], 2);
   ch->light = compute_char_light_value(ch);
    
   if (ch->inventory)
       update_object(ch->inventory, 1);
}



/* Extract a ch completely from the world, and leave his stuff behind */
void	extract_char(struct char_data *ch, bool delrent)
{
    struct obj_data *i;
    struct char_data *k, *next_char;
    struct descriptor_data *t_desc;
    int	l, was_in;
    
    extern struct char_data *combat_list;
    
    ACMD(do_save);
    ACMD(do_return);
    
    void	die_follower(struct char_data *ch);

    if (!IS_NPC(ch) && !ch->desc) {
	for (t_desc = descriptor_list; t_desc; t_desc = t_desc->next)
	    if (t_desc->original == ch)
	    do_return(t_desc->character, "", 0, 0);
    }
    
/*   if (ch->in_room == NOWHERE) {
     logg("SYSERR: NOWHERE extracting char. (handler.c, extract_char)");
      exit(1);
      }
      */
    if (ch->followers || ch->master)
      die_follower(ch);
    if (ch->specials.mount) {
      act("$n falls from $N's back.",FALSE,ch,0,ch->specials.mount,TO_NOTVICT);
      act("$n falls from your back.",FALSE,ch,0,ch->specials.mount,TO_VICT);
      unmount(ch);
    }
    if (ch->specials.carrying) 
      do_drop_mob(ch);
    if (ch->specials.carried_by) 
      do_drop_mob(ch->specials.carried_by);    
    if (ch->specials.rider) {
      act("$n collapses under $N.",FALSE,ch,0,ch->specials.rider,TO_NOTVICT);
      act("$n collapses under you.",FALSE,ch,0,ch->specials.rider,TO_VICT);   
      unmount(ch->specials.rider);
    }
    
    if (IS_PULLING(ch))
	unhitch(0,IS_PULLING(ch),ch,1);
    if (ch->desc) {
	/* Forget snooping */
	if (ch->desc->snoop.snooping)
	    ch->desc->snoop.snooping->desc->snoop.snoop_by = 0;
	
	if (ch->desc->snoop.snoop_by) {
	    send_to_char("Your victim is no longer among us.\r\n",
			 ch->desc->snoop.snoop_by);
	    ch->desc->snoop.snoop_by->desc->snoop.snooping = 0;
	}

	ch->desc->snoop.snooping = ch->desc->snoop.snoop_by = 0;
    }
      
    if (ch->inventory) {
	if (world[ch->in_room].contents)  {
	    for (i = world[ch->in_room].contents; i->next_content; 
						  i = i->next_content)
		;
       
	    i->next_content = ch->inventory;
	} else
	    world[ch->in_room].contents = ch->inventory;
	
	for (i = ch->inventory; i; i = i->next_content) {
	    i->carried_by = 0;
	    if(!IS_NPC(ch))
		snarf_limited_from_char(i);
	    i->in_room = ch->in_room;
	}
    }



   if (ch->specials.fighting)
      stop_fighting(ch);

   for (k = combat_list; k ; k = next_char) {
      next_char = k->next_fighting;
      if (k->specials.fighting == ch)
	 stop_fighting(k);
   }

   /* Must remove from room before removing the equipment! */
   was_in = ch->in_room;
   char_from_room(ch);

   /* clear equipment_list */
   for (l = 0; l < MAX_WEAR; l++)
       if (ch->equipment[l]){
	   if (!IS_NPC(ch))
	       snarf_limited_from_char(ch->equipment[l]);
	   obj_to_room(unequip_char(ch, l), was_in, FALSE);}


   /* pull the char from the list */

   if (ch == character_list)
      character_list = ch->next;
   else {
      for (k = character_list; (k) && (k->next != ch); k = k->next)
	 ;
      if (k)
	 k->next = ch->next;
      else {
	 logg("SYSERR: Trying to remove ?? from character_list. (handler.c, extract_char)");
	 abort();
      }
   }
    /* remove any events */  
   extract_event(ch);

   if (ch->desc) {
      if (ch->desc->original) {
	 do_return(ch, "", 0, 0);
      }
      save_char(ch, NOWHERE);
   }
    if (delrent && !IS_NPC(ch))
	Crash_delete_crashfile(ch);

    if (IS_NPC(ch)) {
      if (ch->reset && ch->reset->num > 0)
	ch->reset->num--;
      if (ch->nr > -1) /* if mobile */
	mob_index[ch->nr].number--;
      clearMemory(ch);   /* Only NPC's can have memory */
      free_char(ch);
      return;
   }
    
    if (ch->desc) {
      ch->desc->connected = CON_SLCT;
      if (ch->desc->color)
	  SEND_TO_Q(ANSI_MENU,ch->desc);
      else
	  SEND_TO_Q(MENU, ch->desc);
   }
}



/* ***********************************************************************
   Here follows high-level versions of some earlier routines, ie functions
   which incorporate the actual player-data.
   *********************************************************************** */


struct char_data *get_char_room_vis(struct char_data *ch, char *name)
{
   struct char_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);
   
   if (!strcmp("me",name) || !strcmp("self",name) || !strcmp("I",name))
       return(ch);

   for (i = world[ch->in_room].people, j = 1; i && (j <= number); i = i->next_in_room)
      if (isname(tmp, i->player.name))
	 if (CAN_SEE(ch, i) && (!IS_AFFECTED(i,AFF_HIDE)
				|| can_see_hidden(ch,i)) )
	     {
	    if (j == number)
	       return(i);
	    j++;
	 }

   return(0);
}


struct char_data *get_player_vis(struct char_data *ch, char *name)
{
   struct char_data *i;

   if (!strcmp("me",name) || !strcmp("self",name) || !strcmp("I",name))
       return(ch);
       
   for (i = character_list; i; i = i->next)
      if (!IS_NPC(i) && !str_cmp(i->player.name, name) && CAN_SEE(ch, i))
	 return i;

   return 0;
}


struct char_data *get_char_vis(struct char_data *ch, char *name)
{
   struct char_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   /* check location */
   if ((i = get_char_room_vis(ch, name)))
      return(i);

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);

   for (i = character_list, j = 1; i && (j <= number); i = i->next)
      if (isname(tmp, i->player.name))
	 if (CAN_SEE(ch, i))	 {
	    if (j == number)
	       return(i);
	    j++;
	 }

   return(0);
}






struct obj_data *get_obj_in_list_vis(struct char_data *ch, char *name, 
struct obj_data *list)
{
   struct obj_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);

   for (i = list, j = 1; i && (j <= number); i = i->next_content)
      if (isname(tmp, i->name))
	 if (CAN_SEE_OBJ(ch, i)) {
	    if (j == number)
	       return(i);
	    j++;
	 }
   return(0);
}





/*search the entire world for an object, and return a pointer  */
struct obj_data *get_obj_vis(struct char_data *ch, char *name)
{
   struct obj_data *i;
   int	j, number;
   char	tmpname[MAX_INPUT_LENGTH];
   char	*tmp;

   /* scan items carried */
   if ((i = get_obj_in_list_vis(ch, name, ch->inventory)))
      return(i);

   /* scan room */
   if ((i = get_obj_in_list_vis(ch, name, world[ch->in_room].contents)))
      return(i);

   strcpy(tmpname, name);
   tmp = tmpname;
   if (!(number = get_number(&tmp)))
      return(0);

   /* ok.. no luck yet. scan the entire obj list   */
   for (i = object_list, j = 1; i && (j <= number); i = i->next)
      if (isname(tmp, i->name))
	 if (CAN_SEE_OBJ(ch, i)) {
	    if (j == number)
	       return(i);
	    j++;
	 }
   return(0);
}



struct obj_data *get_object_in_equip_vis(struct char_data *ch,
char *arg, struct obj_data *equipment[], int *j)
{

   for ((*j) = 0; (*j) < MAX_WEAR ; (*j)++)
      if (equipment[(*j)])
	 if (CAN_SEE_OBJ(ch, equipment[(*j)]))
	    if (isname(arg, equipment[(*j)]->name))
	       return(equipment[(*j)]);

   return (0);
}


struct obj_data *create_money(int amount)
{
   char	buf[200];

   struct obj_data *obj;
   struct extra_descr_data *new_descr=0;

   if (amount <= 0) {
      logg("SYSERR: Try to create negative or 0 money.");
      exit(1);
   }
   amount = MIN(amount, 499999);
   CREATE(obj, struct obj_data, 1);
   CREATE(new_descr, struct extra_descr_data, 1);
   new_descr->keyword =0;
   new_descr->description =0;
   new_descr->next =0;   
   clear_object(obj);
   if (amount <= 10) {
     obj->name = str_dup("penny coin coins copper coppers");
      obj->short_description = str_dup("a copper penny");
      obj->description = str_dup("One miserable copper penny is lying here.");
      new_descr->keyword = str_dup("penny copper");
      new_descr->description = str_dup("It's just one miserable little copper penny.");
   } else {
      obj->name = str_dup("coins coppers");
      if (amount < 100) {
	 obj->short_description = str_dup("a small pile of copper coins");
	 obj->description = str_dup("A small pile of copper coins is lying here.");
      }
      else if (amount == 100){
	  obj->name = str_dup("coin coins groat silver groats");
	  obj->short_description = str_dup("a silver groat");
	  obj->description = str_dup("A silver groat is lying here.");
      }else if (amount <1000 && (amount%100)) {
	 obj->short_description = str_dup("a pile of silver and copper coins");
	 obj->description = str_dup("A pile of silver and copper coins is lying here.");
      }else if (amount <1000 && !(amount%100)) {
	 obj->short_description = str_dup("a pile of silver coins");
	 obj->description = str_dup("A pile of silver coins is lying here.");
      }else if (amount == 1000){
	  obj->name = str_dup("coin coins gold crown crowns");
	  obj->short_description = str_dup("a gold coin");
	  obj->description = str_dup("A gold coin is lying here.");	 
      }else if (amount <10000 && (amount%1000) && !((amount%1000)%100) ) {
	 obj->short_description = str_dup("a pile of gold and silver coins");
	 obj->description = str_dup("A pile of gold and silver coins is lying here.");
      }else if (amount <10000 && !((amount/100)%10) && (amount%1000)) {
	 obj->short_description = str_dup("a pile of gold and copper coins");
	 obj->description = str_dup("A pile of gold and copper coins is lying here.");
      }else if (amount <10000 && (amount%1000) && (amount%100)) {
	 obj->short_description = str_dup("a pile of gold, silver and copper coins");
	 obj->description = str_dup("A pile of gold, silver and copper coins is lying here.");
	 
      }else if (amount <10000 && !(amount%1000) && !(amount%100)) {
	 obj->short_description = str_dup("a pile of gold coins");
	 obj->description = str_dup("A pile of gold coins is lying here.");
      } else if (amount <= 25000) {
	 obj->short_description = str_dup("a small pile of gold coins");
	 obj->description = str_dup("A small pile of gold coins is lying here.");
      } else if (amount <= 500000) {
	 obj->short_description = str_dup("a pile of gold coins");
	 obj->description = str_dup("A pile of gold coins is lying here.");
      } else {
	 obj->short_description = str_dup("a fortune in gold coins");
	 obj->description = str_dup("A fortune in gold coins is lying here.");
      }

      new_descr->keyword = str_dup("coins pile coin money gold copper silver");
      if (amount < 10) {
	 sprintf(buf, "There are %s.", report_cost(amount));
	 new_descr->description = str_dup(buf);
      } else if (amount < 100) {
	 sprintf(buf, "There are about %s.", report_cost(10 * (amount / 10)));
	 new_descr->description = str_dup(buf);
      } else if (amount < 1000) {
	 sprintf(buf, "It looks to be about %s.", report_cost(100 * (amount / 100)));
	 new_descr->description = str_dup(buf);
      } else if (amount < 100000) {
	 sprintf(buf, "You guess there are, maybe, %s.",
	     report_cost(1000 * ((amount / 1000) + number(0, (amount / 1000)))));
	 new_descr->description = str_dup(buf);
      } else
	 new_descr->description = str_dup("There are a LOT of coins.");
   }

   new_descr->next = 0;
   obj->ex_description = new_descr;

   obj->obj_flags.type_flag = ITEM_MONEY;
   obj->obj_flags.wear_flags = ITEM_TAKE;
   obj->obj_flags.value[0] = amount;
   obj->obj_flags.cost = amount;
   obj->obj_flags.weight = report_money_weight(amount);
   obj->obj_flags.timer = -1;
   obj->item_number = -1;

   obj->next = object_list;
   object_list = obj;

   return(obj);
}


/* Generic Find, designed to find any object/character                    */
/* Calling :                                                              */
/*  *arg     is the sting containing the string to be searched for.       */
/*           This string doesn't have to be a single word, the routine    */
/*           extracts the next word itself.                               */
/*  bitv..   All those bits that you want to "search through".            */
/*           Bit found will be result of the function                     */
/*  *ch      This is the person that is trying to "find"                  */
/*  **tar_ch Will be NULL if no character was found, otherwise points     */
/* **tar_obj Will be NULL if no object was found, otherwise points        */
/*                                                                        */
/* The routine returns a pointer to the next word in *arg (just like the  */
/* one_argument routine).                                                 */

int	generic_find(char *arg, int bitvector, struct char_data *ch,
struct char_data **tar_ch, struct obj_data **tar_obj)
{
   static char	*ignore[] = {
      "the",
      "in",
      "on",
      "at",
      "\n"       };

   int	i;
   char	name[256];
   bool found;

   found = FALSE;


   /* Eliminate spaces and "ignore" words */
   while (*arg && !found) {

      for (; *arg == ' '; arg++)
	 ;

      for (i = 0; (name[i] = *(arg + i)) && (name[i] != ' '); i++)
	 ;
      name[i] = 0;
      arg += i;
      if (search_block(name, ignore, TRUE) > -1)
	 found = TRUE;

   }

   if (!name[0])
      return(0);

   *tar_ch  = 0;
   *tar_obj = 0;

   if (IS_SET(bitvector, FIND_CHAR_ROOM))      /* Find person in room */
     if ((*tar_ch = get_char_room_vis(ch, name))) 
       return(FIND_CHAR_ROOM);

   if (IS_SET(bitvector, FIND_CHAR_WORLD)) 
      if ((*tar_ch = get_char_vis(ch, name)))
	 return(FIND_CHAR_WORLD);

   if (IS_SET(bitvector, FIND_OBJ_EQUIP)) 
     if(( *tar_obj = get_object_in_equip_vis(ch, name, ch->equipment, &i)))
	 return(FIND_OBJ_EQUIP);

   if (IS_SET(bitvector, FIND_OBJ_INV)) 
     if ((*tar_obj = get_obj_in_list_vis(ch, name, ch->inventory))) 
       return(FIND_OBJ_INV);

   if (IS_SET(bitvector, FIND_OBJ_ROOM)) {
      if ((*tar_obj = get_obj_in_list_vis(ch, name, world[ch->in_room].contents))) 
	  return(FIND_OBJ_ROOM);
      else if (world[ch->in_room].obj)
	  if ((*tar_obj =
	       get_obj_in_list_vis(ch, name,
				   world[world[ch->in_room].obj->in_room]
				   .contents))) 
	      return(FIND_OBJ_ROOM);
   }

   if (IS_SET(bitvector, FIND_OBJ_WORLD)) {
       if ((*tar_obj = get_obj_vis(ch, name))) {
	   return(FIND_OBJ_WORLD);
       }
   }

   return(0);
}


/* a function to scan for "all" or "all.x" */
int	find_all_dots(char *arg)
{
   if (!strcmp(arg, "all"))
      return FIND_ALL;
   else if (!strncmp(arg, "all.", 4)) {
      strcpy(arg, arg+4);
      return FIND_ALLDOT;
   } else
      return FIND_INDIV;
}