wileymud-1.187b/
wileymud-1.187b/attic/
wileymud-1.187b/attic/bin/
wileymud-1.187b/attic/lib/
wileymud-1.187b/attic/lib/adm/
wileymud-1.187b/attic/lib/man/
wileymud-1.187b/attic/lib/new-wld/
wileymud-1.187b/attic/lib/new-wld/default/
wileymud-1.187b/attic/lib/old/
wileymud-1.187b/attic/lib/wld/
wileymud-1.187b/attic/public_html/
wileymud-1.187b/attic/public_html/gfx/
wileymud-1.187b/attic/src/bin/
wileymud-1.187b/attic/src/etc/
wileymud-1.187b/attic/src/libauth-4.0-p5/
wileymud-1.187b/attic/src/sedna/
wileymud-1.187b/backups/
wileymud-1.187b/bin/
wileymud-1.187b/docs/
wileymud-1.187b/etc/
wileymud-1.187b/lib/
wileymud-1.187b/lib/adm/
wileymud-1.187b/lib/boards/
wileymud-1.187b/lib/log/
wileymud-1.187b/lib/man/
wileymud-1.187b/lib/ply/
wileymud-1.187b/lib/ply/a/
wileymud-1.187b/lib/ply/b/
wileymud-1.187b/lib/ply/c/
wileymud-1.187b/lib/ply/d/
wileymud-1.187b/lib/ply/g/
wileymud-1.187b/lib/ply/k/
wileymud-1.187b/lib/ply/m/
wileymud-1.187b/lib/ply/s/
wileymud-1.187b/lib/ply/t/
wileymud-1.187b/public_html/gfx/
wileymud-1.187b/src/bin/
wileymud-1.187b/src/convert/attic/
wileymud-1.187b/src/convert/obj/
wileymud-1.187b/src/convert/perl/
wileymud-1.187b/src/convert/perl/MudConvert/
wileymud-1.187b/src/convert/perl/MudConvert/DUMP/
wileymud-1.187b/src/convert/perl/MudConvert/Report/
wileymud-1.187b/src/convert/perl/MudConvert/WileyMUD/
wileymud-1.187b/src/convert/perl/output/
wileymud-1.187b/src/convert/perl/output/DUMP/
wileymud-1.187b/src/convert/perl/output/Report/
wileymud-1.187b/src/convert/perl/output/WileyMUD/
wileymud-1.187b/src/etc/
wileymud-1.187b/src/etc/init.d/
wileymud-1.187b/src/etc/rc.d/
wileymud-1.187b/src/etc/rc.d/init.d/
wileymud-1.187b/src/lib/
wileymud-1.187b/src/lib/adm/
wileymud-1.187b/src/lib/boards/
wileymud-1.187b/src/lib/log/
wileymud-1.187b/src/lib/man/
wileymud-1.187b/src/lib/ply/
wileymud-1.187b/src/lib/ply/a/
wileymud-1.187b/src/lib/ply/b/
wileymud-1.187b/src/lib/ply/c/
wileymud-1.187b/src/lib/ply/d/
wileymud-1.187b/src/lib/ply/e/
wileymud-1.187b/src/lib/ply/f/
wileymud-1.187b/src/lib/ply/g/
wileymud-1.187b/src/lib/ply/h/
wileymud-1.187b/src/lib/ply/i/
wileymud-1.187b/src/lib/ply/j/
wileymud-1.187b/src/lib/ply/k/
wileymud-1.187b/src/lib/ply/l/
wileymud-1.187b/src/lib/ply/m/
wileymud-1.187b/src/lib/ply/n/
wileymud-1.187b/src/lib/ply/o/
wileymud-1.187b/src/lib/ply/p/
wileymud-1.187b/src/lib/ply/q/
wileymud-1.187b/src/lib/ply/r/
wileymud-1.187b/src/lib/ply/s/
wileymud-1.187b/src/lib/ply/t/
wileymud-1.187b/src/lib/ply/u/
wileymud-1.187b/src/lib/ply/v/
wileymud-1.187b/src/lib/ply/w/
wileymud-1.187b/src/lib/ply/x/
wileymud-1.187b/src/lib/ply/y/
wileymud-1.187b/src/lib/ply/z/
wileymud-1.187b/src/obj/
wileymud-1.187b/src/utils/
wileymud-1.187b/src/utils/mobmaker/
/* ************************************************************************
 *  file: limits.c , Limit and gain control module.        Part of DIKUMUD *
 *  Usage: Procedures controling gain and limit.                           *
 *  Copyright (C) 1990, 1991 - see 'license.doc' for complete information. *
 ************************************************************************* */

#include <stdio.h>
#include <assert.h>
#include "structs.h"
#include "limits.h"
#include "utils.h"
#include "spells.h"
#include "comm.h"
#include "race.h"

struct room_data *real_roomp(int);

extern struct char_data *character_list;
extern int DEBUG;
extern struct obj_data *object_list;
extern struct title_type titles[4][ABS_MAX_LVL];
extern struct room_data *world;
extern const char *RaceName[];
extern const int RacialMax[][4];

/* External procedures */

void update_pos( struct char_data *victim );                 /* in fight.c */
void damage(struct char_data *ch, struct char_data *victim,  /*    "       */
            int damage, int weapontype);
struct time_info_data age(struct char_data *ch);
void zero_rent(struct char_data *ch);

char *ClassTitles(struct char_data *ch)
{
  int i, count=0;
  char buf[256];
if(DEBUG) dlog("ClassTitles");  
    for(i=MAGE_LEVEL_IND; i<=DRUID_LEVEL_IND; i++) {
      if (GET_LEVEL(ch, i)) {
	count++;
	if (count > 1) {
	  sprintf(buf+strlen(buf),"/%s",GET_CLASS_TITLE(ch, i,GET_LEVEL(ch,i)));
	} else {
	  sprintf(buf, "%s", GET_CLASS_TITLE(ch, i, GET_LEVEL(ch, i)));
	}
      }
    }
  return(buf);
}


/* 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(DEBUG) dlog("graf");  
  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 three MAX functions define a characters Effective maximum */
/* Which is NOT the same as the ch->points.max_xxxx !!!          */
int mana_limit(struct char_data *ch)
{
  int max;
if(DEBUG) dlog("mana_limit");  
  max = 100;

  if (IS_NPC(ch)) return(max);

  if (HasClass(ch, CLASS_MAGIC_USER)) 
  {
    max += GET_LEVEL(ch, MAGE_LEVEL_IND) * 5;
  }
  else
  if (HasClass(ch, CLASS_CLERIC))
  {
    max += ((2*GET_LEVEL(ch, CLERIC_LEVEL_IND))/3) * 5;
  }
  else
  if (HasClass(ch, CLASS_DRUID)) 
  {
    max += (GET_LEVEL(ch, DRUID_LEVEL_IND)/2) * 5;
  }
  else
  if (HasClass(ch, CLASS_RANGER)) 
  {
    max += (GET_LEVEL(ch, RANGER_LEVEL_IND)/2) * 5;
  }
  else
  if (HasClass(ch, CLASS_WARRIOR)) 
  {
    max += (GET_LEVEL(ch, WARRIOR_LEVEL_IND)/4) * 5;
  }
  else
  if (HasClass(ch, CLASS_THIEF)) 
  {
    max += (GET_LEVEL(ch, THIEF_LEVEL_IND)/3) * 5;
  }
  else
  { 
    max = 100;
  }

  max += ch->points.max_mana;   /* bonus mana */
  
  return(max);
}

int hit_limit(struct char_data *ch)
{
  int max;
if(DEBUG) dlog("hit_limit");  
  if (IS_PC(ch))
    max = (ch->points.max_hit)+(graf(age(ch).year, 2,4,17,14,8,4,3));
  else 
    max = (ch->points.max_hit);
  
  /* Class/Level calculations */
  /* Skill/Spell calculations */
  
  return (max);
}

int move_limit(struct char_data *ch)
{
  int max;
if(DEBUG) dlog("move_limit");  
  if (!IS_NPC(ch))
    max = 70 + age(ch).year + GET_CON(ch) + GetTotLevel(ch);
  else
    max = ch->points.max_move;

  if (GET_RACE(ch) == RACE_GNOME)
    max -= 20;  
  if (GET_RACE(ch) == RACE_DWARF)
    max -= 17;
  if (GET_RACE(ch) == RACE_HALFLING)
    max -= 14;
  else if (GET_RACE(ch) == RACE_ELVEN)
    max += 10;

  return (max);
}

int mana_gain(struct char_data *ch)
{
  int gain;
if(DEBUG) dlog("mana_gain");  
  if(IS_NPC(ch)) {
    /* Neat and fast */
    gain = GetTotLevel(ch);
  }
  else 
  {
    gain = graf(age(ch).year, 2,4,6,8,10,12,16);
    
    if(GET_RACE(ch) == RACE_ELVEN)
      gain += 5;

    /* Class calculations */
    /* Skill/Spell calculations */
    /* Position calculations    */

    switch (GET_POS(ch)) {
    case POSITION_SLEEPING:
      gain += gain;
      break;
    case POSITION_RESTING:
      gain+= (gain>>1);  /* Divide by 2 */
      break;
    case POSITION_SITTING:
      gain += (gain>>2); /* Divide by 4 */
      break;
    }

    if (HasClass(ch, CLASS_MAGIC_USER) ||
        HasClass(ch, CLASS_CLERIC) ||
        HasClass(ch, CLASS_DRUID))
      gain += gain;
  }
  
  if (IS_AFFECTED(ch,AFF_POISON))
    gain >>= 2;
  
  if((GET_COND(ch,FULL)==0)||(GET_COND(ch,THIRST)==0))
    gain >>= 2;
 
  if(number(1,101) < ch->skills[SKILL_MEDITATION].learned)
    gain += 10;

  return (gain);
}


int hit_gain(struct char_data *ch)
{
  int gain;
 if(DEBUG) dlog("hit_gain"); 
  if(IS_NPC(ch)) 
  {
    gain = 8;
  }
  else
  {
    if (GET_POS(ch) == POSITION_FIGHTING) 
    {
      gain = 1;
    }
    else
    {
      gain = graf(age(ch).year, 2,5,10,18,6,4,2);
    }
    
    /* Class/Level calculations */
    
    /* Skill/Spell calculations */
    
    /* Position calculations    */
    

    switch (GET_POS(ch)) 
    {
    case POSITION_SLEEPING:
      gain += gain>>1;
      break;
    case POSITION_RESTING:
      gain+= gain>>2;
      break;
    case POSITION_SITTING:
      gain += gain>>3;
      break;
    }

    if(GET_POS(ch) == POSITION_SLEEPING)
      if(number(1,101) < ch->skills[SKILL_MEDITATION].learned)
	gain += 3;
  }
  
  if(GET_RACE(ch) == RACE_DWARF)
    gain += 5;

  if(GET_RACE(ch) == RACE_ELVEN)
    gain -= 1;

  if (GET_RACE(ch) == RACE_GNOME)
    gain += 1;
  
  if(IS_AFFECTED(ch,AFF_POISON))  
  {
    gain >>= 2;
    damage(ch,ch,15,SPELL_POISON);
  }
  
  if((GET_COND(ch,FULL)==0)||(GET_COND(ch,THIRST)==0))
    gain >>= 2;

  gain = MAX(gain,1);

  return (gain);
}

int move_gain(struct char_data *ch)
     /* move gain pr. game hour */
{
  int gain;
 if(DEBUG) dlog("move_gain"); 
  if(IS_NPC(ch)) 
    return(GetTotLevel(ch));	
  else
  {
    if(GET_POS(ch) != POSITION_FIGHTING)
      gain = 5 + GET_CON(ch);
    else
    {
      if(number(1,101) < ch->skills[SKILL_ENDURANCE].learned)
	gain = 2;
      else
        gain = 0;
    }

    /* Position calculations    */
    switch (GET_POS(ch)) {
    case POSITION_SLEEPING:
      gain += (gain>>1); /* Divide by 2 */
      break;
    case POSITION_RESTING:
      gain+= (gain>>2);  /* Divide by 4 */
      break;
    case POSITION_SITTING:
      gain += (gain>>3); /* Divide by 8 */
      break;
    }
  }
  
  if (GET_RACE(ch) == RACE_DWARF)
    gain += 4;
  if (GET_RACE(ch) == RACE_HALFLING)
    gain += 3;
  
  if(IS_AFFECTED(ch,AFF_POISON))
    gain >>= 2;
  
  if((GET_COND(ch,FULL)==0)||(GET_COND(ch,THIRST)==0))
    gain >>= 2;
 
  if(number(1,101) < ch->skills[SKILL_ENDURANCE].learned)
    gain += 5;

  return (gain);
}

/* Gain maximum in various points */
void advance_level(struct char_data *ch, int class)
{
  int add_hp, i;
  
  extern struct wis_app_type wis_app[];
  extern struct con_app_type con_app[];
  extern struct int_app_type int_app[];
if(DEBUG) dlog("advance_level");
  if(GET_LEVEL(ch,class) > 0 &&
     GET_EXP(ch) < titles[class][GET_LEVEL(ch, class)+1].exp) 
  {
    log("Bad advance_level");
    return;
  }

  GET_LEVEL(ch, class) += 1;

/* Constitution Bonus only for Fighter types */

  if ((class == RANGER_LEVEL_IND) || (class == WARRIOR_LEVEL_IND))  
     add_hp = con_app[GET_CON(ch)].hitp;
  else 
     add_hp = MIN(con_app[GET_CON(ch)].hitp,2);

  switch(class) 
  {
  case MAGE_LEVEL_IND : 
  {
    ch->specials.spells_to_learn += MAX(3,wis_app[GET_INT(ch)].bonus);
    if (GET_LEVEL(ch, MAGE_LEVEL_IND) < 30)
      add_hp += number(2,4);
    else
      add_hp += 1;
  } break;
    
  case DRUID_LEVEL_IND : 
  {
    if (GET_LEVEL(ch, DRUID_LEVEL_IND) < 20)
      add_hp += number(2,8);
    else
      add_hp += 3;
  } break;

  case CLERIC_LEVEL_IND : 
  {
    ch->specials.spells_to_learn += MAX(3,wis_app[GET_WIS(ch)].bonus);
    if (GET_LEVEL(ch, CLERIC_LEVEL_IND) < 30)
      add_hp += number(2,8);
    else
      add_hp += 3;
  } break;
    
  case THIEF_LEVEL_IND : 
  {
    ch->specials.spells_to_learn += MAX(3,wis_app[GET_DEX(ch)].bonus);
    if (GET_LEVEL(ch, THIEF_LEVEL_IND) < 30)
      add_hp += number(2,6);
    else
      add_hp += 2;
  } break;

  case RANGER_LEVEL_IND : 
  {
    ch->specials.spells_to_learn +=
     MAX(3,wis_app[(GET_DEX(ch)>=GET_STR(ch) ? GET_DEX(ch):GET_STR(ch))].bonus);
    if (GET_LEVEL(ch, RANGER_LEVEL_IND) < 30)
      add_hp += number(2,10);
    else
      add_hp += 4;
  } break;
    
  case WARRIOR_LEVEL_IND : 
  {
    ch->specials.spells_to_learn += MAX(3,wis_app[GET_STR(ch)].bonus);
    if (GET_LEVEL(ch, WARRIOR_LEVEL_IND) < 30)
      add_hp += number(2,10);
    else
      add_hp += 4;
  } break;
  }

  add_hp /= HowManyClasses(ch);

  add_hp++;

  if (GET_LEVEL(ch, class) <= 5)
     add_hp++;

  ch->points.max_hit += MAX(1, add_hp);
  
  if (GetMaxLevel(ch) >= LOW_IMMORTAL)
    for (i = 0; i < 3; i++)
      ch->specials.conditions[i] = -1;

  ch->points.max_move = GET_MAX_MOVE(ch);
}	

/* Lose in various points */
/*
** Damn tricky for multi-class...
*/

void drop_level(struct char_data *ch, int class)
{
  int add_hp, lin_class;
  
  extern struct wis_app_type wis_app[];
  extern struct con_app_type con_app[];
  
if(DEBUG) dlog("drop_level");  
  if (GetMaxLevel(ch) >= LOW_IMMORTAL)
    return;
  if (GetMaxLevel(ch) == 1)
    return;
  
  add_hp = con_app[GET_CON(ch)].hitp;
  
  switch(class) {
    
  case CLASS_MAGIC_USER : {
    lin_class = MAGE_LEVEL_IND;
    if (GET_LEVEL(ch, MAGE_LEVEL_IND) < 30)
      add_hp += number(2, 4);
    else
      add_hp += 1;
  } break;
    
  case CLASS_DRUID : {
    lin_class = DRUID_LEVEL_IND;
    if (GET_LEVEL(ch, DRUID_LEVEL_IND) < 30)
      add_hp += number(2, 8);
    else
      add_hp += 3;
  } break;

  case CLASS_CLERIC : {
    lin_class = CLERIC_LEVEL_IND;
    if (GET_LEVEL(ch, CLERIC_LEVEL_IND) < 30)
      add_hp += number(2, 8);
    else
      add_hp += 3;
  } break;
    
  case CLASS_THIEF : {
    lin_class = THIEF_LEVEL_IND;
    if (GET_LEVEL(ch, THIEF_LEVEL_IND) < 30)
      add_hp += number(2,6);
    else
      add_hp += 2;
  } break;
    
  case CLASS_WARRIOR : {
    lin_class = WARRIOR_LEVEL_IND;
    if (GET_LEVEL(ch, WARRIOR_LEVEL_IND) < 30)
      add_hp += number(2,10);
    else
      add_hp += 4;
  } break;

  case CLASS_RANGER : {
    lin_class = RANGER_LEVEL_IND;
    if (GET_LEVEL(ch, RANGER_LEVEL_IND) < 30)
      add_hp += number(2,10);
    else
      add_hp += 4;
  } break;
  }

  add_hp /= HowManyClasses(ch);

  GET_LEVEL(ch, class) -= 1;
  
  if (GET_LEVEL(ch, class) < 1) 
    GET_LEVEL(ch, class) = 1;

  ch->points.max_hit -= MAX(1,add_hp);
  if (ch->points.max_hit < 1)
    ch->points.max_hit = 1;
  
  ch->specials.spells_to_learn -= MAX(3,wis_app[GET_WIS(ch)].bonus);
  
  ch->points.exp = 
    MIN(titles[lin_class][GET_LEVEL(ch, lin_class)].exp, GET_EXP(ch));
}	

void set_title(struct char_data *ch)
{
  char buf[256];
  
  if(DEBUG) dlog("set_title");
  sprintf(buf,"the %s %s",RaceName[ch->race], ClassTitles(ch));
  if (GET_TITLE(ch))
  {
    free(GET_TITLE(ch));
    CREATE(GET_TITLE(ch),char,strlen(buf)+1);    
  } else {
    CREATE(GET_TITLE(ch),char,strlen(buf)+1);
  }
  strcpy(GET_TITLE(ch), buf);
}

void gain_exp(struct char_data *ch, int gain)
{
  int i;
  bool is_altered = FALSE;
  char buf[256];
  
/*  save_char(ch,NOWHERE); */
  
  if(DEBUG) dlog("gain_exp");
  if (!IS_IMMORTAL(ch)) 
  {
    if (gain > 0) 
    {
      gain = MIN(10000, gain);

      if(IS_PC(ch))
      {
	gain /= HowManyClasses(ch); 
      }
      else
	gain /= 2;

      if (GetMaxLevel(ch) == 1) gain *= 2;

      if(IS_PC(ch) || (IS_SET(ch->specials.act, ACT_POLYSELF))) 
      {
	for (i = MAGE_LEVEL_IND; i <= DRUID_LEVEL_IND; i++) 
        {
	  if (GET_LEVEL(ch, i)) 
          {
   	    if (GET_EXP(ch) >= titles[i][GET_LEVEL(ch,i)+2].exp) 
            {
	      send_to_char(
        "You will not gain anymore exp until you practice at a guild.\n\r", ch);
	      GET_EXP(ch) = titles[i][GET_LEVEL(ch,i)+2].exp - 1;
	      return;	      
	    } else
            if (GET_EXP(ch) >= titles[i][GET_LEVEL(ch,i)+1].exp) 
            {
	      /* do nothing..this is cool */
	    } else
            if (GET_EXP(ch)+gain >= titles[i][GET_LEVEL(ch,i)+1].exp) 
            {
	      sprintf(buf,"You have gained enough to be a(n) %s\n\r",
                      GET_CLASS_TITLE(ch,i,GET_LEVEL(ch,i)+1));
	      send_to_char(buf,ch);
	      send_to_char(
        "You will not gain anymore exp until you practice at a guild.\n\r",ch);
	      if (GET_EXP(ch)+gain >= titles[i][GET_LEVEL(ch,i)+2].exp) 
              {
		GET_EXP(ch) = titles[i][GET_LEVEL(ch,i)+2].exp - 1;
		return;
	      }
	    }
	  }
	}
      }

      GET_EXP(ch)+=gain;
      if (IS_PC(ch) || IS_SET(ch->specials.act, ACT_POLYSELF)) 
      {
         for (i=MAGE_LEVEL_IND; i<= DRUID_LEVEL_IND; i++) 
         {
           if (GET_LEVEL(ch,i)) 
           {
             if (GET_EXP(ch) > titles[i][GET_LEVEL(ch,i)+2].exp) 
             {
               GET_EXP(ch) = titles[i][GET_LEVEL(ch,i)+2].exp - 1;
             }
          }
        }
      }
    }

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


void gain_exp_regardless(struct char_data *ch, int gain, int class)
{
  int i;
  bool is_altered = FALSE;
if(DEBUG) dlog("gain_exp_regardless");  
  save_char(ch,NOWHERE);
  if (!IS_NPC(ch)) 
  {
    if (gain > 0) 
    {
      GET_EXP(ch) += gain;

      for(i=0;(i<ABS_MAX_LVL) &&(titles[class][i].exp <= GET_EXP(ch)); i++) 
      {
	if (i > GET_LEVEL(ch,class)) 
	{
	  send_to_char("You raise a level\n\r", ch);
/*	  GET_LEVEL(ch,class) = i; */
	  advance_level(ch,class);
	  is_altered = TRUE;
	}
      }
    }

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

    if (GET_EXP(ch) < 0)
      GET_EXP(ch) = 0;
  }
  if (is_altered)
    set_title(ch);
}

void gain_condition(struct char_data *ch,int condition,int value)
{
  bool intoxicated;
  if(DEBUG) dlog("gain_condition");  
  if(GET_COND(ch, condition)==-1) /* No change */
    return;
  
  intoxicated=(GET_COND(ch, DRUNK) > 0);
  
  GET_COND(ch, condition)  += value;
  
  GET_COND(ch,condition) = MAX(0,GET_COND(ch,condition));
  GET_COND(ch,condition) = MIN(24,GET_COND(ch,condition));
  
  if(GET_COND(ch,condition))
    return;
  
  switch(condition){
  case FULL :
    {
      send_to_char("You are hungry.\n\r",ch);
      return;
    }
  case THIRST :
    {
      send_to_char("You are thirsty.\n\r",ch);
      return;
    }
  case DRUNK :
    {
      if(intoxicated)
	send_to_char("You are now sober.\n\r",ch);
      return;
    }
    default : break;
  }
}

void check_idling(struct char_data *ch)
{
  char buf[1024];

  void do_save(struct char_data *ch, char *argument, int cmd);
  ++(ch->specials.timer);

  if (ch->specials.timer > 5 && ch->specials.timer < 10) 
  {
       do_save(ch, "", 0);
       return;
  }

  if(ch->specials.timer >= 10 && ch->specials.timer < 30) 
  {
    sprintf(buf,"LOG:%s in the void:Timer %d.",GET_NAME(ch),ch->specials.timer);
    log(buf);

    if(ch->in_room != NOWHERE) 
    {
      ch->specials.was_in_room = ch->in_room;
      if(ch->specials.fighting)     	
      {
	stop_fighting(ch->specials.fighting);
	stop_fighting(ch);
      }
      act("$n disappears into the void.", TRUE, ch, 0, 0, TO_ROOM);
      char_from_room(ch);
      char_to_room(ch, 0);
    }
    return;
  }

  if(ch->specials.timer >= 30)  
  {
    struct obj_cost cost;
    char buf[256];

    sprintf(buf,"Auto-Saving %s",GET_NAME(ch));
    log(buf);

    if (ch->in_room != NOWHERE)
    {
      ch->specials.was_in_room = ch->in_room;
      char_from_room(ch);
      char_to_room(ch, 0);
    }

    GET_HOME(ch) = 3008;

    if(recep_offer(ch, NULL, &cost)) 
    {
      cost.total_cost = 0;
      save_obj(ch, &cost,TRUE);
    }
    extract_char(ch);

    if(ch->desc) 
      close_socket(ch->desc);

    ch->desc = 0;

    sprintf(buf,"Done Auto-Saving %s",GET_NAME(ch));
    log(buf);
  }
}

/* Update both PC's & NPC's and objects*/

void point_update( int pulse )
{	
  void update_char_objects( struct char_data *ch ); /* handler.c */
  void extract_obj(struct obj_data *obj); /* handler.c */
  struct char_data *i, *next_dude;
  struct obj_data *j, *next_thing, *jj, *next_thing2;
  int count=0;
  
  if(DEBUG) dlog("point_update");

  /* characters */
  for (i = character_list; i; i = next_dude) 
  {
    next_dude = i->next;
    if (GET_POS(i) >= POSITION_STUNNED) 
    {
      if(!affected_by_spell(i,SPELL_AID))
      {
         GET_HIT(i)  = MIN(GET_HIT(i)  + hit_gain(i),  hit_limit(i));
      }
      else
      {
	if(GET_HIT(i)<hit_limit(i))
	{
          GET_HIT(i)  = MIN(GET_HIT(i)  + hit_gain(i),  hit_limit(i));
	}
      }

      GET_MANA(i) = MIN(GET_MANA(i) + mana_gain(i), mana_limit(i));
      GET_MOVE(i) = MIN(GET_MOVE(i) + move_gain(i), move_limit(i));
      if (GET_POS(i) == POSITION_STUNNED) 
         update_pos( i );
    }
    else 
    if(GET_POS(i) == POSITION_INCAP)
    {
      /* damage(i, i, 0, TYPE_SUFFERING); */
      GET_HIT(i) += 1;
      update_pos(i);
    }
    else
    if(IS_PC(i) && (GET_POS(i) == POSITION_MORTALLYW))
      damage(i, i, 1, TYPE_SUFFERING);

    if (!IS_NPC(i))
    {
      update_char_objects(i);
      if (GetMaxLevel(i) < 58)
	check_idling(i);
    }
    gain_condition(i,FULL,-2);
    gain_condition(i,DRUNK,-2);
    gain_condition(i,THIRST,-1);
  } /* for */
  
  /* objects */
  for(j = object_list; j ; j = next_thing)
  {
    next_thing = j->next;
    count++;

    if((GET_ITEM_TYPE(j) == ITEM_FOOD) && (!(pulse % 2)) && IS_OBJ_STAT(j,ITEM_PARISH))
    {
      if(j->obj_flags.value[0] > 0) j->obj_flags.value[0]--;

      switch(j->obj_flags.value[0])
      {
	case 3:
	{
          if(j->carried_by)
	    act("$p begins to look a little brown.",FALSE,j->carried_by,j,0,TO_CHAR);
	  else
	  if(j->in_room!=NOWHERE && (real_roomp(j->in_room)->people))
	  {
	   act("$p begins to look a little brown.",TRUE,real_roomp(j->in_room)->people,j,0,TO_CHAR);
	   act("$p begins to look a little brown.",TRUE,real_roomp(j->in_room)->people,j,0,TO_ROOM);
          }
        } break;
	case 2:
	{
          if(j->carried_by)
	    act("$p begins to smell funny.",FALSE,j->carried_by,j,0,TO_CHAR);
	  else
	  if(j->in_room!=NOWHERE && (real_roomp(j->in_room)->people))
	  {
	   act("$p begins to smell funny.",TRUE,real_roomp(j->in_room)->people,j,0,TO_CHAR);
	   act("$p begins to smell funny.",TRUE,real_roomp(j->in_room)->people,j,0,TO_ROOM);
          }
        } break;
	case 1:
	{
          if(j->carried_by)
	    act("$p begins to smell spoiled.",FALSE,j->carried_by,j,0,TO_CHAR);
	  else
	  if(j->in_room!=NOWHERE && (real_roomp(j->in_room)->people))
	  {
	   act("$p begins to smell spoiled.",TRUE,real_roomp(j->in_room)->people,j,0,TO_CHAR);
	   act("$p begins to smell spoiled.",TRUE,real_roomp(j->in_room)->people,j,0,TO_ROOM);
          }
        } break;
	case 0:
        {
	  if(j->carried_by)
	    act("$p dissolves into dust...",FALSE,j->carried_by,j,0,TO_CHAR);
          else
	  if((j->in_room != NOWHERE) && (real_roomp(j->in_room)->people)) 
          {
	    act("$p dissolves into dust...",TRUE,real_roomp(j->in_room)->people,j,0,TO_ROOM);
	    act("$p dissolves into dust...",TRUE,real_roomp(j->in_room)->people,j,0,TO_CHAR);
          }
	  extract_obj(j);
        }
      }
    }

    if ((GET_ITEM_TYPE(j) == ITEM_CONTAINER) && (j->obj_flags.value[3]))
    {
      /* timer count down */

      if (j->obj_flags.timer > 0) j->obj_flags.timer--;
      if (!j->obj_flags.timer) 
      {
	if (j->carried_by)
	  act("$p biodegrades in your hands.",FALSE, j->carried_by, j, 0, TO_CHAR);
	else
	if ((j->in_room != NOWHERE) && (real_roomp(j->in_room)->people))
	{
	 act("$p dissolves into a fertile soil.",TRUE,real_roomp(j->in_room)->people,j,0,TO_ROOM);
	 act("$p dissolves into a fertile soil.",TRUE,real_roomp(j->in_room)->people,j,0,TO_CHAR);
	}	
	ObjFromCorpse(j);
      }
    }
  }
}


int ObjFromCorpse( struct obj_data *c)
{
  struct obj_data *jj, *next_thing;
if(DEBUG) dlog("ObjFromCorpse");

        for(jj = c->contains; jj; jj = next_thing) {
	  next_thing = jj->next_content; /* Next in inventory */
	  if (jj->in_obj) {
	     obj_from_obj(jj);
	     if (c->in_obj)
	       obj_to_obj(jj,c->in_obj);
	     else if (c->carried_by)
	       obj_to_room(jj,c->carried_by->in_room);
	     else if (c->in_room != NOWHERE)
	       obj_to_room(jj,c->in_room);
	     else
	       assert(FALSE);
	   } else {
	     /*
	     **  hmm..  it isn't in the object it says it is in.
	     **  deal with the memory lossage
	     */
	     c->contains = 0;
	     extract_obj(c);
             log("Memory lost in ObjFromCorpse.");
	     return(TRUE);
	   }
	}
       	extract_obj(c);
}