/* ************************************************************************
* 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);
}