deltamud/deltamud/
deltamud/deltamud/bin/
deltamud/deltamud/cnf/
deltamud/deltamud/lib/
deltamud/deltamud/lib/etc/
deltamud/deltamud/lib/misc/
deltamud/deltamud/lib/plrobjs/
deltamud/deltamud/lib/text/
deltamud/deltamud/lib/text/help/
deltamud/deltamud/lib/world/
deltamud/deltamud/lib/world/trg/
/* ************************************************************************
   *   File: limits.c                                      Part of CircleMUD *
   *  Usage: limits & gain funcs for HMV, exp, hunger/thirst, idle time      *
   *                                                                         *
   *  All rights reserved.  See license.doc for complete information.        *
   *                                                                         *
   *  Copyright (C) 1993, 94 by the Trustees of the Johns Hopkins University *
   *  CircleMUD is based on DikuMUD, Copyright (C) 1990, 1991.               *
   ************************************************************************ */

#include "conf.h"
#include "sysdep.h"

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

extern struct char_data *character_list;
extern struct obj_data *object_list;
extern struct index_data *obj_index;
extern struct room_data *world;
extern int max_exp_gain;
extern int max_exp_loss;
extern int exp_to_level();
extern int arena_flee_timeout;
extern long r_immort_start_room;
void do_oldbie (struct char_data *vict);
void die(struct char_data * ch, struct char_data * killer);
char *title_male (int class, int level);
char *title_female (int class, int level);

extern int has_boat(struct char_data *ch);

/* When age < 15 return the value p0 */
/* When age in 15..29 calculate the line between p1 & p2 */
/* When age in 30..44 calculate the line between p2 & p3 */
/* When age in 45..59 calculate the line between p3 & p4 */
/* When age in 60..79 calculate the line between p4 & p5 */
/* When age >= 80 return the value p6 */
int 
graf (int age, int p0, int p1, int p2, int p3, int p4, int p5, int p6)
{

  if (age < 15)
    return (p0);		/* < 15   */
  else if (age <= 29)
    return (int) (p1 + (((age - 15) * (p2 - p1)) / 15));	/* 15..29 */
  else if (age <= 44)
    return (int) (p2 + (((age - 30) * (p3 - p2)) / 15));	/* 30..44 */
  else if (age <= 59)
    return (int) (p3 + (((age - 45) * (p4 - p3)) / 15));	/* 45..59 */
  else if (age <= 79)
    return (int) (p4 + (((age - 60) * (p5 - p4)) / 20));	/* 60..79 */
  else
    return (p6);		/* >= 80 */
}


/*
 * The hit_limit, mana_limit, and move_limit functions are gone.  They
 * added an unnecessary level of complexity to the internal structure,
 * weren't particularly useful, and led to some annoying bugs.  From the
 * players' point of view, the only difference the removal of these
 * functions will make is that a character's age will now only affect
 * the HMV gain per tick, and _not_ the HMV maximums.
 */

/* manapoint gain pr. game hour */
int 
mana_gain (struct char_data *ch)
{
  int gain;
  int i;

  if (IS_NPC (ch))
    {
      /* Neat and fast */
      gain = GET_LEVEL (ch);
    }
  else
    {
      gain = graf (age (ch).year, 4, 8, 12, 16, 12, 10, 8);

            for (i=0; i< NUM_WEARS; i++) {
       if(GET_EQ(ch, i)) {
        if(GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_MP_REGEN) {
         gain += 10; /* this can be played around with to your liking */
        }
       }
      }

      /* Class calculations */

      /* Skill/Spell calculations */

      /* Position calculations    */
      switch (GET_POS (ch))
	{
	case POS_SLEEPING:
	  gain <<= 1;       /* mult by 2 */
	  break;
	case POS_MEDITATING:
	  gain <<= 3;       /* mult by 8 */
	  break;
	case POS_RESTING:
	  gain += (gain >> 1);	/* Divide by 2 */
	  break;
	case POS_SITTING:
	  gain += (gain >> 2);	/* Divide by 4 */
	  break;
	}

      if ((GET_CLASS (ch) == CLASS_MAGIC_USER) || (GET_CLASS (ch) == CLASS_CLERIC))
	gain <<= 1;
    }

  if (IS_AFFECTED (ch, AFF_POISON))
    gain >>= 2;

  if ((GET_COND (ch, FULL) == 0) || (GET_COND (ch, THIRST) == 0))
    gain >>= 2;

  if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_GOOD_REGEN))
    gain += (gain * 2);
  if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_BAD_REGEN)) gain=0;
  return (gain);
}


int 
hit_gain (struct char_data *ch)
/* Hitpoint gain pr. game hour */
{
  int gain;
  int i;

  if (IS_NPC (ch))
    {
      gain = GET_LEVEL (ch);
      /* Neat and fast */
    }
  else
    {

      gain = graf (age (ch).year, 8, 12, 20, 32, 16, 10, 4);

            for (i=0; i< NUM_WEARS; i++) {
       if(GET_EQ(ch, i)) {
        if(GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_HP_REGEN) {  
         gain += 10; /* this can be played around with to your liking */
        }
       }
      }

      /* Class/Level calculations */

      /* Skill/Spell calculations */

      /* Position calculations    */

      switch (GET_POS (ch))
	{
	case POS_SLEEPING:
	  gain += (gain >> 1);	/* Divide by 2 */
	  break;
	case POS_MEDITATING:
	  gain += (gain >> 1);	/* Divide by 2 */
	  break;
	case POS_RESTING:
	  gain += (gain >> 2);	/* Divide by 4 */
	  break;
	case POS_SITTING:
	  gain += (gain >> 3);	/* Divide by 8 */
	  break;
	}

      if ((GET_CLASS (ch) == CLASS_MAGIC_USER) || (GET_CLASS (ch) == CLASS_CLERIC))
	gain >>= 1;
    }

  if (IS_AFFECTED (ch, AFF_POISON) || IS_AFFECTED (ch, AFF_PLAGUED))
    gain >>= 2;

  if ((GET_COND (ch, FULL) == 0) || (GET_COND (ch, THIRST) == 0))
    gain >>= 2;

  if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_GOOD_REGEN))
    gain += (gain * 2);
  if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_BAD_REGEN)) gain=0;
  return (gain);
}



int 
move_gain (struct char_data *ch)
/* move gain pr. game hour */
{
  int gain;
  int i;  

  if (IS_NPC (ch))
    {
      return (GET_LEVEL (ch));
      /* Neat and fast */
    }
  else
    {
      gain = graf (age (ch).year, 16, 20, 24, 20, 16, 12, 10);

            for (i=0; i< NUM_WEARS; i++) {
       if(GET_EQ(ch, i)) {
        if(GET_OBJ_TYPE(GET_EQ(ch, i)) == ITEM_MV_REGEN) {  
         gain += 10; /* this can be played around with to your liking */
        }
       }
      }

      /* Class/Level calculations */

      /* Skill/Spell calculations */


      /* Position calculations    */
      switch (GET_POS (ch))
	{
	case POS_SLEEPING:
	  gain += (gain >> 1);	/* Divide by 2 */
	  break;
	case POS_MEDITATING:
	  gain += (gain >> 1);	/* Divide by 2 */
	  break;
	case POS_RESTING:
	  gain += (gain >> 2);	/* Divide by 4 */
	  break;
	case POS_SITTING:
	  gain += (gain >> 3);	/* Divide by 8 */
	  break;
	}

      if (IS_AFFECTED (ch, AFF_POISON))
	gain >>= 2;

      if ((GET_COND (ch, FULL) == 0) || (GET_COND (ch, THIRST) == 0))
	gain >>= 2;

  if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_GOOD_REGEN))
    gain += (gain * 2);
      if (IS_SET(ROOM_FLAGS(ch->in_room), ROOM_BAD_REGEN)) gain=0;
      return gain;
    }
}



void 
set_title (struct char_data *ch, char *title)
{
  if (title == NULL)
    {
      if (GET_SEX (ch) == SEX_FEMALE)
	title = "the Woman";
      else
	title = "the Man";
    }

  if (strlen (title) > MAX_TITLE_LENGTH)
    title[MAX_TITLE_LENGTH] = '\0';

  if (GET_TITLE (ch) != NULL)
    free (GET_TITLE (ch));

  GET_TITLE (ch) = str_dup (title);
}

void 
check_autowiz (struct char_data *ch)
{
#ifndef CIRCLE_UNIX
  return;
#else
  char buf[100];
  extern int use_autowiz;
  extern int min_wizlist_lev;

  if (use_autowiz && GET_LEVEL (ch) >= LVL_HERO)
    {
      sprintf (buf, "nice ../bin/autowiz %d %s %d %s %d &", min_wizlist_lev,
	       WIZLIST_FILE, LVL_HERO, IMMLIST_FILE, (int) getpid ());
      mudlog ("Initiating autowiz.", PFT, LVL_IMMORT, FALSE);
      system (buf);
    }
#endif /* CIRCLE_UNIX */
}



void 
gain_exp (struct char_data *ch, int gain)
{
  int is_altered = FALSE;
//  int i;
//  struct obj_data *obj;
  int num_levels = 0;
  char buf[128];

  if (IS_NPC(ch))
    return;

  if ((!IS_NPC (ch) && ((GET_LEVEL (ch) < 1 || GET_LEVEL (ch) >= LVL_HERO))) ||
PRF2_FLAGGED(ch, PRF2_INTANGIBLE))
    return;

  if (IS_NPC (ch))
    {
      GET_EXP (ch) += gain;
      return;
    }

  if (IS_ARENACOMBATANT(ch)){
    return;
  }

  if (gain > 0)
    {
      gain = MIN (max_exp_gain, gain);	/* put a cap on the max gain per kill */
      GET_EXP (ch) += gain;
      while (GET_LEVEL (ch) < LVL_HERO &&
             GET_EXP (ch) >= exp_to_level (GET_LEVEL(ch)))
	{
	  GET_LEVEL (ch) += 1;
	  num_levels++;
	  advance_level (ch);
	  is_altered = TRUE;
	}

      if (is_altered)
	{

	  if (num_levels == 1)
	    send_to_char ("You rise a level!\r\n", ch);
	  else
	    {
	      sprintf (buf, "You rise %d levels!\r\n", num_levels);
	      send_to_char (buf, ch);
	    }
	  check_autowiz (ch);
	  sprintf (buf, "&m[&YINFO&m]&n %s has advanced to level %d!\r\n", GET_NAME (ch), GET_LEVEL (ch));
	  send_to_all (buf);

//	  if (GET_LEVEL (ch) == LVL_GETSTUFF)
//	    {
//	      do_oldbie (ch);
//	      send_to_char ("&YThe gods have rewarded you for getting to level 3!&n\r\nTwo gold bricks fall from the sky into your hands.&n\r\n", ch);
//	    }

         if (GET_LEVEL (ch) == 10)
          send_to_char("Congratulations on achieving level 10! Be warned, that you are no longer\r\nconsidered a newbie and can now be attacked by other players. You will\r\nnow lose experience when fleeing from combat.\r\n", ch);

	  if (GET_LEVEL (ch) == LVL_HERO)
	    {
	      sprintf (buf, "&m[&YINFO&m]&n %s has become a &YHERO&n!\r\n", 
		       GET_NAME (ch));
	      send_to_all (buf);
              set_title(ch, "the Hero");
	      send_to_char ("You shall forever be known as a hero throughout the land of Deltania!\r\nYou have reached level 100, for more information please type 'help hero'.\r\n", ch);
	      
              /* a hero sees all that is seen and unseen */
              SET_BIT (PRF_FLAGS (ch), PRF_HOLYLIGHT);

             
	      save_char (ch, NOWHERE);	     
	    }
	}
    }
  else if (gain < 0)
    {
      gain = MAX (-max_exp_loss, gain);		/* Cap max exp lost per death */
      GET_EXP (ch) += gain;
      if (GET_EXP (ch) < 0)
	GET_EXP (ch) = 0;
    }
}


void 
gain_exp_regardless (struct char_data *ch, int gain)
{
  int is_altered = FALSE;
  int num_levels = 0;

  if (IS_NPC(ch))
    return;

  GET_EXP (ch) += gain;
  if (GET_EXP (ch) < 0)
    GET_EXP (ch) = 0;

  if (!IS_NPC (ch))
    {
      while (GET_LEVEL (ch) < LVL_IMPL &&
          GET_EXP (ch) >= exp_to_level (GET_LEVEL(ch)))
	{
	  GET_LEVEL (ch) += 1;
	  num_levels++;
	  advance_level (ch);
	  is_altered = TRUE;
	}

      if (is_altered)
	{
	  if (num_levels == 1)
	    send_to_char ("You rise a level!\r\n", ch);
	  else
	    {
	      sprintf (buf, "You rise %d levels!\r\n", num_levels);
	      send_to_char (buf, ch);
	    }
	  check_autowiz (ch);
	  sprintf (buf, "&m[&YINFO&m]&n %s has advanced to level %d!\r\n", GET_NAME (ch), GET_LEVEL (ch));
	  send_to_all (buf);
	  if (GET_LEVEL (ch) == LVL_GETSTUFF)
	    {
	      do_oldbie (ch);
	      send_to_char ("&YThe gods have rewarded you for getting to level 3!&n\r\nTwo gold bricks fall from the sky into your hands.&n\r\n", ch);
	    }
	}
    }
}


void 
gain_condition (struct char_data *ch, int condition, int value)
{
  bool intoxicated;

  if (GET_COND (ch, condition) == -100)	/* No change */
    return;

  intoxicated = (GET_COND (ch, DRUNK) > 4);

  GET_COND (ch, condition) += value;

  if ((condition == DRUNK))
  GET_COND (ch, condition) = MAX (0, GET_COND (ch, condition));
  else
  GET_COND (ch, condition) = MAX (-72, GET_COND (ch, condition));

  GET_COND (ch, condition) = MIN (24, GET_COND (ch, condition));

  if (GET_COND (ch, condition) || PLR_FLAGGED (ch, PLR_WRITING))
    return;

  switch (condition)
    {
    case FULL:
      send_to_char ("You are hungry.\r\n", ch);
      return;
    case THIRST:
      send_to_char ("You are thirsty.\r\n", ch);
      return;
    case DRUNK:
      if (intoxicated)
	send_to_char ("You are now sober.\r\n", ch);
      return;
    default:
      break;
    }

}


void 
check_idling (struct char_data *ch)
{
  extern int free_rent;
  void Crash_rentsave (struct char_data *ch, int cost);
  void command_interpreter (struct char_data *ch, char *argument);

  if (PRF2_FLAGGED(ch, PRF2_LOCKOUT))
    ch->char_specials.timer = 0;

  if (++(ch->char_specials.timer) > 5  && PRF2_FLAGGED(ch, PRF2_MBUILDING)) {
    send_to_char("Build mode, my friend, was not made for you to idle in.\r\n", ch);
    command_interpreter(ch, "build off");
    return;
  }

  if (ch->char_specials.timer > 8) {
    if (GET_WAS_IN (ch) == NOWHERE && ch->in_room != NOWHERE)
      {
	GET_WAS_IN (ch) = ch->in_room;
	if (FIGHTING (ch))
	  {
	    stop_fighting (FIGHTING (ch));
	    stop_fighting (ch);
	  }
	act ("$n disappears into the void.", TRUE, ch, 0, 0, TO_ROOM);
	send_to_char ("You have been idle, and are pulled into a void.\r\n", ch);
	save_char (ch, NOWHERE);
	Crash_crashsave (ch);
	char_from_room (ch);
	char_to_room (ch, 1);
      }
    else if (ch->char_specials.timer > 48)
      {
	if (ch->in_room != NOWHERE)
	  char_from_room (ch);
	char_to_room (ch, 3);
	if (ch->desc)
	  close_socket (ch->desc);
	ch->desc = NULL;
	if (free_rent || (GET_LEVEL(ch) >= LVL_IMMORT))
	  Crash_rentsave (ch, 0);
	else
	  Crash_idlesave (ch);
	sprintf (buf, "%s force-rented and extracted (idle).", GET_NAME (ch));
	mudlog (buf, PFT, LVL_GOD, TRUE);
	extract_char (ch);
      }
  }
}


/* Update PCs, NPCs, and objects */
void 
point_update (void)
{
  void update_char_objects (struct char_data *ch);	/* handler.c */
  void extract_obj (struct obj_data *obj);	/* handler.c */
  void do_extract_char (struct char_data *ch, int type);	/* handler.c */
  struct descriptor_data *d;
  struct char_data *i, *next_char;
  struct obj_data *j, *next_thing, *jj, *next_thing2;
  char mybuf[1024];
  int enter_player_game (struct descriptor_data *d);

  /* characters */
  for (i = character_list; i; i = next_char)
    {
      next_char=i->next;
      if (!IS_NPC(i) && IS_SET(PRF2_FLAGS(i), PRF2_INTANGIBLE) && GET_LEVEL(i) < LVL_IMMORT) {
        if (PRF2_FLAGGED(i, PRF2_MBUILDING)) check_idling (i);
        else if (i->player_specials->saved.death_timer > 0) {
          i->player_specials->saved.death_timer--;
          if (!i->player_specials->saved.death_timer) {
            send_to_char("Death makes a cryptic gesture and you find yourself englufed in light!\r\n", i);
            act("Death makes a cryptic gesture and $n dissapears in a bright light!\r\n", FALSE, i, NULL, NULL, TO_ROOM);
            REMOVE_BIT(PRF2_FLAGS(i), PRF2_INTANGIBLE);
            d=i->desc;
            do_extract_char(i, 2);
            enter_player_game(d);
            look_at_room(d->character, 1);
            act("A white mist appears and $n steps out.\r\n", FALSE, i, NULL, NULL, TO_ROOM);
          }
        }
        continue;
      }
      gain_condition (i, FULL, -1);
      gain_condition (i, DRUNK, -1);
      gain_condition (i, THIRST, -1);

      if (GET_POS (i) >= POS_STUNNED)
	{
	  GET_HIT (i) = MIN (GET_HIT (i) + hit_gain (i), GET_MAX_HIT (i));
	  GET_MANA (i) = MIN (GET_MANA (i) + mana_gain (i), GET_MAX_MANA (i));
	  GET_MOVE (i) = MIN (GET_MOVE (i) + move_gain (i), GET_MAX_MOVE (i));

	  /* This is the flee-protection code for arena */
	  /* A person who flee's from combat must wait for the flee_timer */
	  /* to expire before recalling, or else it's considered as       */
	  /* concedeing a lost match. -Thargor- */
	  if (IS_ARENACOMBATANT(i)){
	    if (GET_ARENAFLEETIMER(i) >= (1 + arena_flee_timeout)){
	      send_to_char("Flee-Recall timer expired. You may now"
			   "recall without conceding the match.\r\n", i);
	      GET_ARENAFLEETIMER(i) = 0;
	    }else if (GET_ARENAFLEETIMER(i) >= 1){
	      GET_ARENAFLEETIMER(i) += 1;
	      sprintf(mybuf, "Flee-Recall timer in tic #%d. "
		      "%d tic(s) to go.\r\n", 
		      (GET_ARENAFLEETIMER(i)-1), 
		      (arena_flee_timeout+1)-GET_ARENAFLEETIMER(i));
	      send_to_char(mybuf, i);
	    }
	  }

	  if (IS_AFFECTED (i, AFF_POISON))
	    damage (i, i, 2, SPELL_POISON);
	  if (GET_POS (i) <= POS_STUNNED)
	    update_pos (i);
	  if (IS_AFFECTED (i, AFF_PLAGUED))
	    send_to_char("&RYou feel the effects of a deadly plague ravage through your body.&n", i);
	}
      else if (GET_POS (i) == POS_INCAP)
	damage (i, i, 1, TYPE_SUFFERING);
      else if (GET_POS (i) == POS_MORTALLYW)
	damage (i, i, 2, TYPE_SUFFERING);
      if (!IS_NPC (i))
	{
	  update_char_objects (i);

	  if (GET_LEVEL (i) < LVL_IMMORT)
	    check_idling (i);

      if (GET_LEVEL(i) < LVL_IMMORT)
	if (SECT(i->in_room) == SECT_WATER_NOSWIM && !has_boat(i)) {
	  act("$n thrashes about in the water straining to stay afloat.", FALSE,
		i, 0, 0, TO_ROOM);
	  send_to_char("You are drowning!\r\n", i);
	  damage (i, i, GET_MAX_HIT(i) / 5, TYPE_DROWNING); /* TYPE_DROWNING ? */
	}
      if (GET_LEVEL(i) < LVL_IMMORT) {

      if ((GET_COND(i, THIRST) < 0) && (GET_COND(i, THIRST) > -12))
      send_to_char("You are extremely thirsty.\r\n", i);
      else
      if ((GET_COND(i, THIRST) <= -12) && (GET_COND(i, THIRST) >= -20))
      send_to_char("You are suffering from dehydration and must get something to drink.\r\n", i); 
     else
    if ((GET_COND(i, THIRST) < -20) && (GET_COND(i, THIRST) > -24)) {
    send_to_char("You are now dying of thirst! You must get something to drink quickly.\r\n", i);
     damage (i, i, GET_MAX_HIT(i) / 4, TYPE_STARVING);
     update_pos(i);
  }
  else
  if ((GET_COND(i, THIRST) <= -24) && (GET_COND(i, THIRST) > -100)) {
  send_to_char("&RYou have died of extreme thirst!&n\r\n", i);
  die(i, NULL);
  }

      if ((GET_COND(i, FULL) < 0) && (GET_COND(i, FULL) >= -23))
      send_to_char("You are very hungry.\r\n", i);
      if ((GET_COND(i, FULL) < -23) && (GET_COND(i, FULL) > -36))       
      send_to_char("You are extremely hungry.\r\n", i);                                            
      else
      if ((GET_COND(i, FULL) <= -36) && (GET_COND(i, FULL) >= -48))  
      send_to_char("You are suffering from starvation and must get something to eat.\r\n", i);
     else
    if ((GET_COND(i, FULL) < -48) && (GET_COND(i, FULL) > -60)) {
    send_to_char("You are now dying of hunger! You must get something to eat soon.\r\n", i);
     damage (i, i, GET_MAX_HIT(i) / 8, TYPE_STARVING);
     update_pos(i);
  }
  else
  if ((GET_COND(i, FULL) <= -60) && (GET_COND(i, FULL) > -100)) {
  send_to_char("&RYou have died of extreme hunger!&n\r\n", i);
  die(i, NULL);
  }
 }

	}
    }

  /* objects */
  for (j = object_list; j; j = next_thing)
    {
      next_thing = j->next;	/* Next in object list */

    /* If this object is in water. */
    if (j->in_room != NOWHERE && (SECT(j->in_room) == SECT_WATER_NOSWIM ||
		SECT(j->in_room) == SECT_WATER_SWIM)) {
      /* Give everything a random chance of sinking, some may never. */
       if (GET_OBJ_TYPE(j) != ITEM_BOAT && number(0, GET_OBJ_WEIGHT(j)) > 0) {
	act("$p sinks into the murky depths.", FALSE, 0, j, 0, TO_ROOM);
	extract_obj(j);
	continue;
      } else
	act("$p floats unsteadily in the area.", FALSE, 0, j, 0, TO_ROOM);
    }
    /* Portals */
    if (GET_OBJ_TYPE(j) == ITEM_PORTAL && !j->carried_by && !j->in_obj) {
      // Ignore portals in people's inv or in other objects.
      if (GET_OBJ_TIMER(j)>0)
        GET_OBJ_TIMER(j)--;
      if (GET_OBJ_TIMER(j)==0) {
	act ("$p dissapears in a puff of smoke!", FALSE, 0, j, 0, TO_ROOM);
        extract_obj(j);
        continue;
      }
    }    

	/* If this is a corpse */
      if ((GET_OBJ_TYPE (j) == ITEM_CONTAINER) && GET_OBJ_VAL (j, 3))
	{
	  /* timer count down */
	  if (GET_OBJ_TIMER (j) > 0)
	    GET_OBJ_TIMER (j)--;

	  if (!GET_OBJ_TIMER (j))
	    {

	      if (j->carried_by)
		act ("$p decays in your hands.", FALSE, j->carried_by, j, 0, TO_CHAR);
	      else if ((j->in_room != NOWHERE) && (world[j->in_room].people))
		{
		  act ("A quivering horde of maggots consumes $p.",
		       TRUE, world[j->in_room].people, j, 0, TO_ROOM);
		  act ("A quivering horde of maggots consumes $p.",
		       TRUE, world[j->in_room].people, j, 0, TO_CHAR);
		}

	      for (jj = j->contains; jj; jj = next_thing2)
		{
		  next_thing2 = jj->next_content;	/* Next in inventory */
		  obj_from_obj (jj);

		  if (j->in_obj)
		    obj_to_obj (jj, j->in_obj);
		  else if (j->carried_by)
		    obj_to_room (jj, j->carried_by->in_room);
		  else if (j->in_room != NOWHERE)
		    obj_to_room (jj, j->in_room);
		  else
		    assert (FALSE);
       }
        extract_obj(j);
      }
     }
    /* If the timer is set, count it down and at 0, try the trigger */
    /* note to .rej hand-patchers: make this last in your point-update() */
    else if (GET_OBJ_TIMER(j)>0) {
      GET_OBJ_TIMER(j)--;
      if (!GET_OBJ_TIMER(j))
        timer_otrigger(j);
    }
   }
 }