1/*	SCCS Id: @(#)mkobj.c	3.4	2002/10/07	*/
2/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3/* NetHack may be freely redistributed.  See license for details. */
4
5#include "hack.h"
6#include "prop.h"
7
8STATIC_DCL void FDECL(mkbox_cnts,(struct obj *));
9STATIC_DCL void FDECL(obj_timer_checks,(struct obj *, XCHAR_P, XCHAR_P, int));
10#ifdef OVL1
11STATIC_DCL void FDECL(container_weight, (struct obj *));
12STATIC_DCL struct obj *FDECL(save_mtraits, (struct obj *, struct monst *));
13#ifdef WIZARD
14STATIC_DCL const char *FDECL(where_name, (int));
15STATIC_DCL void FDECL(check_contained, (struct obj *,const char *));
16#endif
17#endif /* OVL1 */
18
19extern struct obj *thrownobj;		/* defined in dothrow.c */
20
21/*#define DEBUG_EFFECTS*/	/* show some messages for debugging */
22
23struct icp {
24    int  iprob;		/* probability of an item type */
25    char iclass;	/* item class */
26};
27
28#ifdef OVL1
29
30const struct icp mkobjprobs[] = {
31{10, WEAPON_CLASS},
32{10, ARMOR_CLASS},
33{20, FOOD_CLASS},
34{ 8, TOOL_CLASS},
35{ 8, GEM_CLASS},
36{16, POTION_CLASS},
37{16, SCROLL_CLASS},
38{ 4, SPBOOK_CLASS},
39{ 4, WAND_CLASS},
40{ 3, RING_CLASS},
41{ 1, AMULET_CLASS}
42};
43
44const struct icp boxiprobs[] = {
45{18, GEM_CLASS},
46{15, FOOD_CLASS},
47{18, POTION_CLASS},
48{18, SCROLL_CLASS},
49{12, SPBOOK_CLASS},
50{ 7, COIN_CLASS},
51{ 6, WAND_CLASS},
52{ 5, RING_CLASS},
53{ 1, AMULET_CLASS}
54};
55
56#ifdef REINCARNATION
57const struct icp rogueprobs[] = {
58{12, WEAPON_CLASS},
59{12, ARMOR_CLASS},
60{22, FOOD_CLASS},
61{22, POTION_CLASS},
62{22, SCROLL_CLASS},
63{ 5, WAND_CLASS},
64{ 5, RING_CLASS}
65};
66#endif
67
68const struct icp hellprobs[] = {
69{20, WEAPON_CLASS},
70{20, ARMOR_CLASS},
71{16, FOOD_CLASS},
72{12, TOOL_CLASS},
73{10, GEM_CLASS},
74{ 1, POTION_CLASS},
75{ 1, SCROLL_CLASS},
76{ 8, WAND_CLASS},
77{ 8, RING_CLASS},
78{ 4, AMULET_CLASS}
79};
80
81struct obj *
82mkobj_at(let, x, y, artif)
83char let;
84int x, y;
85boolean artif;
86{
87	struct obj *otmp;
88
89	otmp = mkobj(let, artif);
90	place_object(otmp, x, y);
91	return(otmp);
92}
93
94struct obj *
95mksobj_at(otyp, x, y, init, artif)
96int otyp, x, y;
97boolean init, artif;
98{
99	struct obj *otmp;
100
101	otmp = mksobj(otyp, init, artif);
102	place_object(otmp, x, y);
103	return(otmp);
104}
105
106struct obj *
107mkobj(oclass, artif)
108char oclass;
109boolean artif;
110{
111	int tprob, i, prob = rnd(1000);
112
113	if(oclass == RANDOM_CLASS) {
114		const struct icp *iprobs =
115#ifdef REINCARNATION
116				    (Is_rogue_level(&u.uz)) ?
117				    (const struct icp *)rogueprobs :
118#endif
119				    Inhell ? (const struct icp *)hellprobs :
120				    (const struct icp *)mkobjprobs;
121
122		for(tprob = rnd(100);
123		    (tprob -= iprobs->iprob) > 0;
124		    iprobs++);
125		oclass = iprobs->iclass;
126	}
127
128	i = bases[(int)oclass];
129	while((prob -= objects[i].oc_prob) > 0) i++;
130
131	if(objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
132		panic("probtype error, oclass=%d i=%d", (int) oclass, i);
133
134	return(mksobj(i, TRUE, artif));
135}
136
137STATIC_OVL void
138mkbox_cnts(box)
139struct obj *box;
140{
141	register int n;
142	register struct obj *otmp;
143
144	box->cobj = (struct obj *) 0;
145
146	switch (box->otyp) {
147	case ICE_BOX:		n = 20; break;
148	case CHEST:		n = 5; break;
149	case LARGE_BOX:		n = 3; break;
150	case SACK:
151	case OILSKIN_SACK:
152				/* initial inventory: sack starts out empty */
153				if (moves <= 1 && !in_mklev) { n = 0; break; }
154				/*else FALLTHRU*/
155	case BAG_OF_HOLDING:	n = 1; break;
156	default:		n = 0; break;
157	}
158
159	for (n = rn2(n+1); n > 0; n--) {
160	    if (box->otyp == ICE_BOX) {
161		if (!(otmp = mksobj(CORPSE, TRUE, TRUE))) continue;
162		/* Note: setting age to 0 is correct.  Age has a different
163		 * from usual meaning for objects stored in ice boxes. -KAA
164		 */
165		otmp->age = 0L;
166		if (otmp->timed) {
167		    (void) stop_timer(ROT_CORPSE, (genericptr_t)otmp);
168		    (void) stop_timer(REVIVE_MON, (genericptr_t)otmp);
169		}
170	    } else {
171		register int tprob;
172		const struct icp *iprobs = boxiprobs;
173
174		for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
175		    ;
176		if (!(otmp = mkobj(iprobs->iclass, TRUE))) continue;
177
178		/* handle a couple of special cases */
179		if (otmp->oclass == COIN_CLASS) {
180		    /* 2.5 x level's usual amount; weight adjusted below */
181		    otmp->quan = (long)(rnd(level_difficulty()+2) * rnd(75));
182		    otmp->owt = weight(otmp);
183		} else while (otmp->otyp == ROCK) {
184		    otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE);
185		    if (otmp->quan > 2L) otmp->quan = 1L;
186		    otmp->owt = weight(otmp);
187		}
188		if (box->otyp == BAG_OF_HOLDING) {
189		    if (Is_mbag(otmp)) {
190			otmp->otyp = SACK;
191			otmp->spe = 0;
192			otmp->owt = weight(otmp);
193		    } else while (otmp->otyp == WAN_CANCELLATION)
194			    otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
195		}
196	    }
197	    (void) add_to_container(box, otmp);
198	}
199}
200
201int
202rndmonnum()	/* select a random, common monster type */
203{
204	register struct permonst *ptr;
205	register int	i;
206
207	/* Plan A: get a level-appropriate common monster */
208	ptr = rndmonst();
209	if (ptr) return(monsndx(ptr));
210
211	/* Plan B: get any common monster */
212	do {
213	    i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
214	    ptr = &mons[i];
215	} while((ptr->geno & G_NOGEN) || (!Inhell && (ptr->geno & G_HELL)));
216
217	return(i);
218}
219
220/*
221 * Split obj so that it gets size gets reduced by num. The quantity num is
222 * put in the object structure delivered by this call.  The returned object
223 * has its wornmask cleared and is positioned just following the original
224 * in the nobj chain (and nexthere chain when on the floor).
225 */
226struct obj *
227splitobj(obj, num)
228struct obj *obj;
229long num;
230{
231	struct obj *otmp;
232
233	if (obj->cobj || num <= 0L || obj->quan <= num)
234	    panic("splitobj");	/* can't split containers */
235	otmp = newobj(obj->oxlth + obj->onamelth);
236	*otmp = *obj;		/* copies whole structure */
237	otmp->o_id = flags.ident++;
238	if (!otmp->o_id) otmp->o_id = flags.ident++;	/* ident overflowed */
239	otmp->timed = 0;	/* not timed, yet */
240	otmp->lamplit = 0;	/* ditto */
241	otmp->owornmask = 0L;	/* new object isn't worn */
242	obj->quan -= num;
243	obj->owt = weight(obj);
244	otmp->quan = num;
245	otmp->owt = weight(otmp);	/* -= obj->owt ? */
246	obj->nobj = otmp;
247	/* Only set nexthere when on the floor, nexthere is also used */
248	/* as a back pointer to the container object when contained. */
249	if (obj->where == OBJ_FLOOR)
250	    obj->nexthere = otmp;
251	if (obj->oxlth)
252	    (void)memcpy((genericptr_t)otmp->oextra, (genericptr_t)obj->oextra,
253			obj->oxlth);
254	if (obj->onamelth)
255	    (void)strncpy(ONAME(otmp), ONAME(obj), (int)obj->onamelth);
256	if (obj->unpaid) splitbill(obj,otmp);
257	if (obj->timed) obj_split_timers(obj, otmp);
258	if (obj_sheds_light(obj)) obj_split_light_source(obj, otmp);
259	return otmp;
260}
261
262/*
263 * Insert otmp right after obj in whatever chain(s) it is on.  Then extract
264 * obj from the chain(s).  This function does a literal swap.  It is up to
265 * the caller to provide a valid context for the swap.  When done, obj will
266 * still exist, but not on any chain.
267 *
268 * Note:  Don't use use obj_extract_self() -- we are doing an in-place swap,
269 * not actually moving something.
270 */
271void
272replace_object(obj, otmp)
273struct obj *obj;
274struct obj *otmp;
275{
276    otmp->where = obj->where;
277    switch (obj->where) {
278    case OBJ_FREE:
279	/* do nothing */
280	break;
281    case OBJ_INVENT:
282	otmp->nobj = obj->nobj;
283	obj->nobj = otmp;
284	extract_nobj(obj, &invent);
285	break;
286    case OBJ_CONTAINED:
287	otmp->nobj = obj->nobj;
288	otmp->ocontainer = obj->ocontainer;
289	obj->nobj = otmp;
290	extract_nobj(obj, &obj->ocontainer->cobj);
291	break;
292    case OBJ_MINVENT:
293	otmp->nobj = obj->nobj;
294	otmp->ocarry =  obj->ocarry;
295	obj->nobj = otmp;
296	extract_nobj(obj, &obj->ocarry->minvent);
297	break;
298    case OBJ_FLOOR:
299	otmp->nobj = obj->nobj;
300	otmp->nexthere = obj->nexthere;
301	otmp->ox = obj->ox;
302	otmp->oy = obj->oy;
303	obj->nobj = otmp;
304	obj->nexthere = otmp;
305	extract_nobj(obj, &fobj);
306	extract_nexthere(obj, &level.objects[obj->ox][obj->oy]);
307	break;
308    default:
309	panic("replace_object: obj position");
310	break;
311    }
312}
313
314/*
315 * Create a dummy duplicate to put on shop bill.  The duplicate exists
316 * only in the billobjs chain.  This function is used when a shop object
317 * is being altered, and a copy of the original is needed for billing
318 * purposes.  For example, when eating, where an interruption will yield
319 * an object which is different from what it started out as; the "I x"
320 * command needs to display the original object.
321 *
322 * The caller is responsible for checking otmp->unpaid and
323 * costly_spot(u.ux, u.uy).  This function will make otmp no charge.
324 *
325 * Note that check_unpaid_usage() should be used instead for partial
326 * usage of an object.
327 */
328void
329bill_dummy_object(otmp)
330register struct obj *otmp;
331{
332	register struct obj *dummy;
333
334	if (otmp->unpaid)
335	    subfrombill(otmp, shop_keeper(*u.ushops));
336	dummy = newobj(otmp->oxlth + otmp->onamelth);
337	*dummy = *otmp;
338	dummy->where = OBJ_FREE;
339	dummy->o_id = flags.ident++;
340	if (!dummy->o_id) dummy->o_id = flags.ident++;	/* ident overflowed */
341	dummy->timed = 0;
342	if (otmp->oxlth)
343	    (void)memcpy((genericptr_t)dummy->oextra,
344			(genericptr_t)otmp->oextra, otmp->oxlth);
345	if (otmp->onamelth)
346	    (void)strncpy(ONAME(dummy), ONAME(otmp), (int)otmp->onamelth);
347	if (Is_candle(dummy)) dummy->lamplit = 0;
348	addtobill(dummy, FALSE, TRUE, TRUE);
349	otmp->no_charge = 1;
350	otmp->unpaid = 0;
351	return;
352}
353
354#endif /* OVL1 */
355#ifdef OVLB
356
357static const char dknowns[] = {
358		WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS,
359		GEM_CLASS, SPBOOK_CLASS, WEAPON_CLASS, TOOL_CLASS, 0
360};
361
362struct obj *
363mksobj(otyp, init, artif)
364int otyp;
365boolean init;
366boolean artif;
367{
368	int mndx, tryct;
369	struct obj *otmp;
370	char let = objects[otyp].oc_class;
371
372	otmp = newobj(0);
373	*otmp = zeroobj;
374	otmp->age = monstermoves;
375	otmp->o_id = flags.ident++;
376	if (!otmp->o_id) otmp->o_id = flags.ident++;	/* ident overflowed */
377	otmp->quan = 1L;
378	otmp->oclass = let;
379	otmp->otyp = otyp;
380	otmp->where = OBJ_FREE;
381	otmp->dknown = index(dknowns, let) ? 0 : 1;
382	if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) ||
383			otmp->otyp == SHIELD_OF_REFLECTION)
384		otmp->dknown = 0;
385	if (!objects[otmp->otyp].oc_uses_known)
386		otmp->known = 1;
387#ifdef INVISIBLE_OBJECTS
388	otmp->oinvis = !rn2(1250);
389#endif
390	if (init) switch (let) {
391	case WEAPON_CLASS:
392		otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L;
393		if(!rn2(11)) {
394			otmp->spe = rne(3);
395			otmp->blessed = rn2(2);
396		} else if(!rn2(10)) {
397			curse(otmp);
398			otmp->spe = -rne(3);
399		} else	blessorcurse(otmp, 10);
400		if (is_poisonable(otmp) && !rn2(100))
401			otmp->opoisoned = 1;
402
403		if (artif && !rn2(20))
404		    otmp = mk_artifact(otmp, (aligntyp)A_NONE);
405		break;
406	case FOOD_CLASS:
407	    otmp->oeaten = 0;
408	    switch(otmp->otyp) {
409	    case CORPSE:
410		/* possibly overridden by mkcorpstat() */
411		tryct = 50;
412		do otmp->corpsenm = undead_to_corpse(rndmonnum());
413		while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE) && (--tryct > 0));
414		if (tryct == 0) {
415		/* perhaps rndmonnum() only wants to make G_NOCORPSE monsters on
416		   this level; let's create an adventurer's corpse instead, then */
417			otmp->corpsenm = PM_HUMAN;
418		}
419		/* timer set below */
420		break;
421	    case EGG:
422		otmp->corpsenm = NON_PM;	/* generic egg */
423		if (!rn2(3)) for (tryct = 200; tryct > 0; --tryct) {
424		    mndx = can_be_hatched(rndmonnum());
425		    if (mndx != NON_PM && !dead_species(mndx, TRUE)) {
426			otmp->corpsenm = mndx;		/* typed egg */
427			attach_egg_hatch_timeout(otmp);
428			break;
429		    }
430		}
431		break;
432	    case TIN:
433		otmp->corpsenm = NON_PM;	/* empty (so far) */
434		if (!rn2(6))
435		    otmp->spe = 1;		/* spinach */
436		else for (tryct = 200; tryct > 0; --tryct) {
437		    mndx = undead_to_corpse(rndmonnum());
438		    if (mons[mndx].cnutrit &&
439			    !(mvitals[mndx].mvflags & G_NOCORPSE)) {
440			otmp->corpsenm = mndx;
441			break;
442		    }
443		}
444		blessorcurse(otmp, 10);
445		break;
446	    case SLIME_MOLD:
447		otmp->spe = current_fruit;
448		break;
449	    case KELP_FROND:
450		otmp->quan = (long) rnd(2);
451		break;
452	    }
453	    if (otmp->otyp == CORPSE || otmp->otyp == MEAT_RING ||
454		otmp->otyp == KELP_FROND) break;
455	    /* fall into next case */
456
457	case GEM_CLASS:
458		if (otmp->otyp == LOADSTONE) curse(otmp);
459		else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6);
460		else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L;
461		else otmp->quan = 1L;
462		break;
463	case TOOL_CLASS:
464	    switch(otmp->otyp) {
465		case TALLOW_CANDLE:
466		case WAX_CANDLE:	otmp->spe = 1;
467					otmp->age = 20L * /* 400 or 200 */
468					      (long)objects[otmp->otyp].oc_cost;
469					otmp->lamplit = 0;
470					otmp->quan = 1L +
471					      (long)(rn2(2) ? rn2(7) : 0);
472					blessorcurse(otmp, 5);
473					break;
474		case BRASS_LANTERN:
475		case OIL_LAMP:		otmp->spe = 1;
476					otmp->age = (long) rn1(500,1000);
477					otmp->lamplit = 0;
478					blessorcurse(otmp, 5);
479					break;
480		case MAGIC_LAMP:	otmp->spe = 1;
481					otmp->lamplit = 0;
482					blessorcurse(otmp, 2);
483					break;
484		case CHEST:
485		case LARGE_BOX:		otmp->olocked = !!(rn2(5));
486					otmp->otrapped = !(rn2(10));
487		case ICE_BOX:
488		case SACK:
489		case OILSKIN_SACK:
490		case BAG_OF_HOLDING:	mkbox_cnts(otmp);
491					break;
492#ifdef TOURIST
493		case EXPENSIVE_CAMERA:
494#endif
495		case TINNING_KIT:
496		case MAGIC_MARKER:	otmp->spe = rn1(70,30);
497					break;
498		case CAN_OF_GREASE:	otmp->spe = rnd(25);
499					blessorcurse(otmp, 10);
500					break;
501		case CRYSTAL_BALL:	otmp->spe = rnd(5);
502					blessorcurse(otmp, 2);
503					break;
504		case HORN_OF_PLENTY:
505		case BAG_OF_TRICKS:	otmp->spe = rnd(20);
506					break;
507		case FIGURINE:	{	int tryct2 = 0;
508					do
509					    otmp->corpsenm = rndmonnum();
510					while(is_human(&mons[otmp->corpsenm])
511						&& tryct2++ < 30);
512					blessorcurse(otmp, 4);
513					break;
514				}
515		case BELL_OF_OPENING:   otmp->spe = 3;
516					break;
517		case MAGIC_FLUTE:
518		case MAGIC_HARP:
519		case FROST_HORN:
520		case FIRE_HORN:
521		case DRUM_OF_EARTHQUAKE:
522					otmp->spe = rn1(5,4);
523					break;
524	    }
525	    break;
526	case AMULET_CLASS:
527		if (otmp->otyp == AMULET_OF_YENDOR) flags.made_amulet = TRUE;
528		if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION ||
529		   otmp->otyp == AMULET_OF_CHANGE ||
530		   otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
531			curse(otmp);
532		} else	blessorcurse(otmp, 10);
533	case VENOM_CLASS:
534	case CHAIN_CLASS:
535	case BALL_CLASS:
536		break;
537	case POTION_CLASS:
538		if (otmp->otyp == POT_OIL)
539		    otmp->age = MAX_OIL_IN_FLASK;	/* amount of oil */
540		/* fall through */
541	case SCROLL_CLASS:
542#ifdef MAIL
543		if (otmp->otyp != SCR_MAIL)
544#endif
545			blessorcurse(otmp, 4);
546		break;
547	case SPBOOK_CLASS:
548		blessorcurse(otmp, 17);
549		break;
550	case ARMOR_CLASS:
551		if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS ||
552		   otmp->otyp == LEVITATION_BOOTS ||
553		   otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT ||
554		   otmp->otyp == GAUNTLETS_OF_FUMBLING ||
555		   !rn2(11))) {
556			curse(otmp);
557			otmp->spe = -rne(3);
558		} else if(!rn2(10)) {
559			otmp->blessed = rn2(2);
560			otmp->spe = rne(3);
561		} else	blessorcurse(otmp, 10);
562		if (artif && !rn2(40))
563		    otmp = mk_artifact(otmp, (aligntyp)A_NONE);
564		/* simulate lacquered armor for samurai */
565		if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL &&
566		    (moves <= 1 || In_quest(&u.uz))) {
567#ifdef UNIXPC
568			/* optimizer bitfield bug */
569			otmp->oerodeproof = 1;
570			otmp->rknown = 1;
571#else
572			otmp->oerodeproof = otmp->rknown = 1;
573#endif
574		}
575		break;
576	case WAND_CLASS:
577		if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else
578		otmp->spe = rn1(5,
579			(objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
580		blessorcurse(otmp, 17);
581		otmp->recharged = 0; /* used to control recharging */
582		break;
583	case RING_CLASS:
584		if(objects[otmp->otyp].oc_charged) {
585		    blessorcurse(otmp, 3);
586		    if(rn2(10)) {
587			if(rn2(10) && bcsign(otmp))
588			    otmp->spe = bcsign(otmp) * rne(3);
589			else otmp->spe = rn2(2) ? rne(3) : -rne(3);
590		    }
591		    /* make useless +0 rings much less common */
592		    if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3);
593		    /* negative rings are usually cursed */
594		    if (otmp->spe < 0 && rn2(5)) curse(otmp);
595		} else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION ||
596			  otmp->otyp == RIN_POLYMORPH ||
597			  otmp->otyp == RIN_AGGRAVATE_MONSTER ||
598			  otmp->otyp == RIN_HUNGER || !rn2(9))) {
599			curse(otmp);
600		}
601		break;
602	case ROCK_CLASS:
603		switch (otmp->otyp) {
604		    case STATUE:
605			/* possibly overridden by mkcorpstat() */
606			otmp->corpsenm = rndmonnum();
607			if (!verysmall(&mons[otmp->corpsenm]) &&
608				rn2(level_difficulty()/2 + 10) > 10)
609			    (void) add_to_container(otmp,
610						    mkobj(SPBOOK_CLASS,FALSE));
611		}
612		break;
613	case COIN_CLASS:
614		break;	/* do nothing */
615	default:
616		impossible("impossible mkobj %d, sym '%c'.", otmp->otyp,
617						objects[otmp->otyp].oc_class);
618		return (struct obj *)0;
619	}
620
621	/* Some things must get done (timers) even if init = 0 */
622	switch (otmp->otyp) {
623	    case CORPSE:
624		start_corpse_timeout(otmp);
625		break;
626	}
627
628	/* unique objects may have an associated artifact entry */
629	if (objects[otyp].oc_unique && !otmp->oartifact)
630	    otmp = mk_artifact(otmp, (aligntyp)A_NONE);
631	otmp->owt = weight(otmp);
632	return(otmp);
633}
634
635/*
636 * Start a corpse decay or revive timer.
637 * This takes the age of the corpse into consideration as of 3.4.0.
638 */
639void
640start_corpse_timeout(body)
641	struct obj *body;
642{
643	long when; 		/* rot away when this old */
644	long corpse_age;	/* age of corpse          */
645	int rot_adjust;
646	short action;
647
648#define TAINT_AGE (50L)		/* age when corpses go bad */
649#define TROLL_REVIVE_CHANCE 37	/* 1/37 chance for 50 turns ~ 75% chance */
650#define ROT_AGE (250L)		/* age when corpses rot away */
651
652	/* lizards and lichen don't rot or revive */
653	if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN) return;
654
655	action = ROT_CORPSE;		/* default action: rot away */
656	rot_adjust = in_mklev ? 25 : 10;	/* give some variation */
657	corpse_age = monstermoves - body->age;
658	if (corpse_age > ROT_AGE)
659		when = rot_adjust;
660	else
661		when = ROT_AGE - corpse_age;
662	when += (long)(rnz(rot_adjust) - rot_adjust);
663
664	if (is_rider(&mons[body->corpsenm])) {
665		/*
666		 * Riders always revive.  They have a 1/3 chance per turn
667		 * of reviving after 12 turns.  Always revive by 500.
668		 */
669		action = REVIVE_MON;
670		for (when = 12L; when < 500L; when++)
671		    if (!rn2(3)) break;
672
673	} else if (mons[body->corpsenm].mlet == S_TROLL && !body->norevive) {
674		long age;
675		for (age = 2; age <= TAINT_AGE; age++)
676		    if (!rn2(TROLL_REVIVE_CHANCE)) {	/* troll revives */
677			action = REVIVE_MON;
678			when = age;
679			break;
680		    }
681	}
682
683	if (body->norevive) body->norevive = 0;
684	(void) start_timer(when, TIMER_OBJECT, action, (genericptr_t)body);
685}
686
687void
688bless(otmp)
689register struct obj *otmp;
690{
691#ifdef GOLDOBJ
692	if (otmp->oclass == COIN_CLASS) return;
693#endif
694	otmp->cursed = 0;
695	otmp->blessed = 1;
696	if (carried(otmp) && confers_luck(otmp))
697	    set_moreluck();
698	else if (otmp->otyp == BAG_OF_HOLDING)
699	    otmp->owt = weight(otmp);
700	else if (otmp->otyp == FIGURINE && otmp->timed)
701		(void) stop_timer(FIG_TRANSFORM, (genericptr_t) otmp);
702	return;
703}
704
705void
706unbless(otmp)
707register struct obj *otmp;
708{
709	otmp->blessed = 0;
710	if (carried(otmp) && confers_luck(otmp))
711	    set_moreluck();
712	else if (otmp->otyp == BAG_OF_HOLDING)
713	    otmp->owt = weight(otmp);
714}
715
716void
717curse(otmp)
718register struct obj *otmp;
719{
720#ifdef GOLDOBJ
721	if (otmp->oclass == COIN_CLASS) return;
722#endif
723	otmp->blessed = 0;
724	otmp->cursed = 1;
725	/* welded two-handed weapon interferes with some armor removal */
726	if (otmp == uwep && bimanual(uwep)) reset_remarm();
727	/* rules at top of wield.c state that twoweapon cannot be done
728	   with cursed alternate weapon */
729	if (otmp == uswapwep && u.twoweap)
730	    drop_uswapwep();
731	/* some cursed items need immediate updating */
732	if (carried(otmp) && confers_luck(otmp))
733	    set_moreluck();
734	else if (otmp->otyp == BAG_OF_HOLDING)
735	    otmp->owt = weight(otmp);
736	else if (otmp->otyp == FIGURINE) {
737		if (otmp->corpsenm != NON_PM
738		    && !dead_species(otmp->corpsenm,TRUE)
739		    && (carried(otmp) || mcarried(otmp)))
740			attach_fig_transform_timeout(otmp);
741	}
742	return;
743}
744
745void
746uncurse(otmp)
747register struct obj *otmp;
748{
749	otmp->cursed = 0;
750	if (carried(otmp) && confers_luck(otmp))
751	    set_moreluck();
752	else if (otmp->otyp == BAG_OF_HOLDING)
753	    otmp->owt = weight(otmp);
754	else if (otmp->otyp == FIGURINE && otmp->timed)
755	    (void) stop_timer(FIG_TRANSFORM, (genericptr_t) otmp);
756	return;
757}
758
759#endif /* OVLB */
760#ifdef OVL1
761
762void
763blessorcurse(otmp, chance)
764register struct obj *otmp;
765register int chance;
766{
767	if(otmp->blessed || otmp->cursed) return;
768
769	if(!rn2(chance)) {
770	    if(!rn2(2)) {
771		curse(otmp);
772	    } else {
773		bless(otmp);
774	    }
775	}
776	return;
777}
778
779#endif /* OVL1 */
780#ifdef OVLB
781
782int
783bcsign(otmp)
784register struct obj *otmp;
785{
786	return(!!otmp->blessed - !!otmp->cursed);
787}
788
789#endif /* OVLB */
790#ifdef OVL0
791
792/*
793 *  Calculate the weight of the given object.  This will recursively follow
794 *  and calculate the weight of any containers.
795 *
796 *  Note:  It is possible to end up with an incorrect weight if some part
797 *	   of the code messes with a contained object and doesn't update the
798 *	   container's weight.
799 */
800int
801weight(obj)
802register struct obj *obj;
803{
804	int wt = objects[obj->otyp].oc_weight;
805
806	if (obj->otyp == LARGE_BOX && obj->spe == 1) /* Schroedinger's Cat */
807		wt += mons[PM_HOUSECAT].cwt;
808	if (Is_container(obj) || obj->otyp == STATUE) {
809		struct obj *contents;
810		register int cwt = 0;
811
812		if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
813		    wt = (int)obj->quan *
814			 ((int)mons[obj->corpsenm].cwt * 3 / 2);
815
816		for(contents=obj->cobj; contents; contents=contents->nobj)
817			cwt += weight(contents);
818		/*
819		 *  The weight of bags of holding is calculated as the weight
820		 *  of the bag plus the weight of the bag's contents modified
821		 *  as follows:
822		 *
823		 *	Bag status	Weight of contents
824		 *	----------	------------------
825		 *	cursed			2x
826		 *	blessed			x/4 + 1
827		 *	otherwise		x/2 + 1
828		 *
829		 *  The macro DELTA_CWT in pickup.c also implements these
830		 *  weight equations.
831		 *
832		 *  Note:  The above checks are performed in the given order.
833		 *	   this means that if an object is both blessed and
834		 *	   cursed (not supposed to happen), it will be treated
835		 *	   as cursed.
836		 */
837		if (obj->otyp == BAG_OF_HOLDING)
838		    cwt = obj->cursed ? (cwt * 2) :
839					(1 + (cwt / (obj->blessed ? 4 : 2)));
840
841		return wt + cwt;
842	}
843	if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
844		long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
845
846		wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int)long_wt;
847		if (obj->oeaten) wt = eaten_stat(wt, obj);
848		return wt;
849	} else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
850		return eaten_stat((int)obj->quan * wt, obj);
851	} else if (obj->oclass == COIN_CLASS)
852		return (int)((obj->quan + 50L) / 100L);
853	else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0)
854		return((int)(obj->owt));	/* kludge for "very" heavy iron ball */
855	return(wt ? wt*(int)obj->quan : ((int)obj->quan + 1)>>1);
856}
857
858static int treefruits[] = {APPLE,ORANGE,PEAR,BANANA,EUCALYPTUS_LEAF};
859
860struct obj *
861rnd_treefruit_at(x,y)
862int x, y;
863{
864	return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
865}
866#endif /* OVL0 */
867#ifdef OVLB
868
869struct obj *
870mkgold(amount, x, y)
871long amount;
872int x, y;
873{
874    register struct obj *gold = g_at(x,y);
875
876    if (amount <= 0L)
877	amount = (long)(1 + rnd(level_difficulty()+2) * rnd(30));
878    if (gold) {
879	gold->quan += amount;
880    } else {
881	gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
882	gold->quan = amount;
883    }
884    gold->owt = weight(gold);
885    return (gold);
886}
887
888#endif /* OVLB */
889#ifdef OVL1
890
891/* return TRUE if the corpse has special timing */
892#define special_corpse(num)  (((num) == PM_LIZARD)		\
893				|| ((num) == PM_LICHEN)		\
894				|| (is_rider(&mons[num]))	\
895				|| (mons[num].mlet == S_TROLL))
896
897/*
898 * OEXTRA note: Passing mtmp causes mtraits to be saved
899 * even if ptr passed as well, but ptr is always used for
900 * the corpse type (corpsenm). That allows the corpse type
901 * to be different from the original monster,
902 *	i.e.  vampire -> human corpse
903 * yet still allow restoration of the original monster upon
904 * resurrection.
905 */
906struct obj *
907mkcorpstat(objtype, mtmp, ptr, x, y, init)
908int objtype;	/* CORPSE or STATUE */
909struct monst *mtmp;
910struct permonst *ptr;
911int x, y;
912boolean init;
913{
914	register struct obj *otmp;
915
916	if (objtype != CORPSE && objtype != STATUE)
917	    impossible("making corpstat type %d", objtype);
918	if (x == 0 && y == 0) {		/* special case - random placement */
919		otmp = mksobj(objtype, init, FALSE);
920		if (otmp) rloco(otmp);
921	} else
922		otmp = mksobj_at(objtype, x, y, init, FALSE);
923	if (otmp) {
924	    if (mtmp) {
925		struct obj *otmp2;
926
927		if (!ptr) ptr = mtmp->data;
928		/* save_mtraits frees original data pointed to by otmp */
929		otmp2 = save_mtraits(otmp, mtmp);
930		if (otmp2) otmp = otmp2;
931	    }
932	    /* use the corpse or statue produced by mksobj() as-is
933	       unless `ptr' is non-null */
934	    if (ptr) {
935		int old_corpsenm = otmp->corpsenm;
936
937		otmp->corpsenm = monsndx(ptr);
938		otmp->owt = weight(otmp);
939		if (otmp->otyp == CORPSE &&
940			(special_corpse(old_corpsenm) ||
941				special_corpse(otmp->corpsenm))) {
942		    obj_stop_timers(otmp);
943		    start_corpse_timeout(otmp);
944		}
945	    }
946	}
947	return(otmp);
948}
949
950/*
951 * Attach a monster id to an object, to provide
952 * a lasting association between the two.
953 */
954struct obj *
955obj_attach_mid(obj, mid)
956struct obj *obj;
957unsigned mid;
958{
959    struct obj *otmp;
960    int lth, namelth;
961
962    if (!mid || !obj) return (struct obj *)0;
963    lth = sizeof(mid);
964    namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0;
965    if (namelth)
966	otmp = realloc_obj(obj, lth, (genericptr_t) &mid, namelth, ONAME(obj));
967    else {
968	otmp = obj;
969	otmp->oxlth = sizeof(mid);
970	(void) memcpy((genericptr_t)otmp->oextra, (genericptr_t)&mid,
971								sizeof(mid));
972    }
973    if (otmp && otmp->oxlth) otmp->oattached = OATTACHED_M_ID;	/* mark it */
974    return otmp;
975}
976
977static struct obj *
978save_mtraits(obj, mtmp)
979struct obj *obj;
980struct monst *mtmp;
981{
982	struct obj *otmp;
983	int lth, namelth;
984
985	lth = sizeof(struct monst) + mtmp->mxlth + mtmp->mnamelth;
986	namelth = obj->onamelth ? strlen(ONAME(obj)) + 1 : 0;
987	otmp = realloc_obj(obj, lth, (genericptr_t) mtmp, namelth, ONAME(obj));
988	if (otmp && otmp->oxlth) {
989		struct monst *mtmp2 = (struct monst *)otmp->oextra;
990		if (mtmp->data) mtmp2->mnum = monsndx(mtmp->data);
991		/* invalidate pointers */
992		/* m_id is needed to know if this is a revived quest leader */
993		/* but m_id must be cleared when loading bones */
994		mtmp2->nmon     = (struct monst *)0;
995		mtmp2->data     = (struct permonst *)0;
996		mtmp2->minvent  = (struct obj *)0;
997		otmp->oattached = OATTACHED_MONST;	/* mark it */
998	}
999	return otmp;
1000}
1001
1002/* returns a pointer to a new monst structure based on
1003 * the one contained within the obj.
1004 */
1005struct monst *
1006get_mtraits(obj, copyof)
1007struct obj *obj;
1008boolean copyof;
1009{
1010	struct monst *mtmp = (struct monst *)0;
1011	struct monst *mnew = (struct monst *)0;
1012
1013	if (obj->oxlth && obj->oattached == OATTACHED_MONST)
1014		mtmp = (struct monst *)obj->oextra;
1015	if (mtmp) {
1016	    if (copyof) {
1017		int lth = mtmp->mxlth + mtmp->mnamelth;
1018		mnew = newmonst(lth);
1019		lth += sizeof(struct monst);
1020		(void) memcpy((genericptr_t)mnew,
1021				(genericptr_t)mtmp, lth);
1022	    } else {
1023	      /* Never insert this returned pointer into mon chains! */
1024	    	mnew = mtmp;
1025	    }
1026	}
1027	return mnew;
1028}
1029
1030#endif /* OVL1 */
1031#ifdef OVLB
1032
1033/* make an object named after someone listed in the scoreboard file */
1034struct obj *
1035mk_tt_object(objtype, x, y)
1036int objtype; /* CORPSE or STATUE */
1037register int x, y;
1038{
1039	register struct obj *otmp, *otmp2;
1040	boolean initialize_it;
1041
1042	/* player statues never contain books */
1043	initialize_it = (objtype != STATUE);
1044	if ((otmp = mksobj_at(objtype, x, y, initialize_it, FALSE)) != 0) {
1045	    /* tt_oname will return null if the scoreboard is empty */
1046	    if ((otmp2 = tt_oname(otmp)) != 0) otmp = otmp2;
1047	}
1048	return(otmp);
1049}
1050
1051/* make a new corpse or statue, uninitialized if a statue (i.e. no books) */
1052struct obj *
1053mk_named_object(objtype, ptr, x, y, nm)
1054int objtype;	/* CORPSE or STATUE */
1055struct permonst *ptr;
1056int x, y;
1057const char *nm;
1058{
1059	struct obj *otmp;
1060
1061	otmp = mkcorpstat(objtype, (struct monst *)0, ptr,
1062				x, y, (boolean)(objtype != STATUE));
1063	if (nm)
1064		otmp = oname(otmp, nm);
1065	return(otmp);
1066}
1067
1068boolean
1069is_flammable(otmp)
1070register struct obj *otmp;
1071{
1072	int otyp = otmp->otyp;
1073	int omat = objects[otyp].oc_material;
1074
1075	if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
1076		return FALSE;
1077
1078	return((boolean)((omat <= WOOD && omat != LIQUID) || omat == PLASTIC));
1079}
1080
1081boolean
1082is_rottable(otmp)
1083register struct obj *otmp;
1084{
1085	int otyp = otmp->otyp;
1086
1087	return((boolean)(objects[otyp].oc_material <= WOOD &&
1088			objects[otyp].oc_material != LIQUID));
1089}
1090
1091#endif /* OVLB */
1092#ifdef OVL1
1093
1094/*
1095 * These routines maintain the single-linked lists headed in level.objects[][]
1096 * and threaded through the nexthere fields in the object-instance structure.
1097 */
1098
1099/* put the object at the given location */
1100void
1101place_object(otmp, x, y)
1102register struct obj *otmp;
1103int x, y;
1104{
1105    register struct obj *otmp2 = level.objects[x][y];
1106
1107    if (otmp->where != OBJ_FREE)
1108	panic("place_object: obj not free");
1109
1110    obj_no_longer_held(otmp);
1111    if (otmp->otyp == BOULDER) block_point(x,y);	/* vision */
1112
1113    /* obj goes under boulders */
1114    if (otmp2 && (otmp2->otyp == BOULDER)) {
1115	otmp->nexthere = otmp2->nexthere;
1116	otmp2->nexthere = otmp;
1117    } else {
1118	otmp->nexthere = otmp2;
1119	level.objects[x][y] = otmp;
1120    }
1121
1122    /* set the new object's location */
1123    otmp->ox = x;
1124    otmp->oy = y;
1125
1126    otmp->where = OBJ_FLOOR;
1127
1128    /* add to floor chain */
1129    otmp->nobj = fobj;
1130    fobj = otmp;
1131    if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
1132}
1133
1134#define ON_ICE(a) ((a)->recharged)
1135#define ROT_ICE_ADJUSTMENT 2	/* rotting on ice takes 2 times as long */
1136
1137/* If ice was affecting any objects correct that now
1138 * Also used for starting ice effects too. [zap.c]
1139 */
1140void
1141obj_ice_effects(x, y, do_buried)
1142int x, y;
1143boolean do_buried;
1144{
1145	struct obj *otmp;
1146
1147	for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) {
1148		if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
1149	}
1150	if (do_buried) {
1151	    for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
1152 		if (otmp->ox == x && otmp->oy == y) {
1153			if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
1154		}
1155	    }
1156	}
1157}
1158
1159/*
1160 * Returns an obj->age for a corpse object on ice, that would be the
1161 * actual obj->age if the corpse had just been lifted from the ice.
1162 * This is useful when just using obj->age in a check or calculation because
1163 * rot timers pertaining to the object don't have to be stopped and
1164 * restarted etc.
1165 */
1166long
1167peek_at_iced_corpse_age(otmp)
1168struct obj *otmp;
1169{
1170    long age, retval = otmp->age;
1171
1172    if (otmp->otyp == CORPSE && ON_ICE(otmp)) {
1173	/* Adjust the age; must be same as obj_timer_checks() for off ice*/
1174	age = monstermoves - otmp->age;
1175	retval = otmp->age + (age / ROT_ICE_ADJUSTMENT);
1176#ifdef NETHACK_DEBUG_EFFECTS
1177	pline_The("%s age has ice modifications:otmp->age = %ld, returning %ld.",
1178		s_suffix(doname(otmp)),otmp->age, retval);
1179	pline("Effective age of corpse: %ld.",
1180		monstermoves - retval);
1181#endif
1182    }
1183    return retval;
1184}
1185
1186STATIC_OVL void
1187obj_timer_checks(otmp, x, y, force)
1188struct obj *otmp;
1189xchar x, y;
1190int force;	/* 0 = no force so do checks, <0 = force off, >0 force on */
1191{
1192    long tleft = 0L;
1193    short action = ROT_CORPSE;
1194    boolean restart_timer = FALSE;
1195    boolean on_floor = (otmp->where == OBJ_FLOOR);
1196    boolean buried = (otmp->where == OBJ_BURIED);
1197
1198    /* Check for corpses just placed on or in ice */
1199    if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x,y)) {
1200	tleft = stop_timer(action, (genericptr_t)otmp);
1201	if (tleft == 0L) {
1202		action = REVIVE_MON;
1203		tleft = stop_timer(action, (genericptr_t)otmp);
1204	}
1205	if (tleft != 0L) {
1206	    long age;
1207
1208	    tleft = tleft - monstermoves;
1209	    /* mark the corpse as being on ice */
1210	    ON_ICE(otmp) = 1;
1211#ifdef NETHACK_DEBUG_EFFECTS
1212	    pline("%s is now on ice at %d,%d.", The(xname(otmp)),x,y);
1213#endif
1214	    /* Adjust the time remaining */
1215	    tleft *= ROT_ICE_ADJUSTMENT;
1216	    restart_timer = TRUE;
1217	    /* Adjust the age; must be same as in obj_ice_age() */
1218	    age = monstermoves - otmp->age;
1219	    otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
1220	}
1221    }
1222    /* Check for corpses coming off ice */
1223    else if ((force < 0) ||
1224	     (otmp->otyp == CORPSE && ON_ICE(otmp) &&
1225	     ((on_floor && !is_ice(x,y)) || !on_floor))) {
1226	tleft = stop_timer(action, (genericptr_t)otmp);
1227	if (tleft == 0L) {
1228		action = REVIVE_MON;
1229		tleft = stop_timer(action, (genericptr_t)otmp);
1230	}
1231	if (tleft != 0L) {
1232		long age;
1233
1234		tleft = tleft - monstermoves;
1235		ON_ICE(otmp) = 0;
1236#ifdef NETHACK_DEBUG_EFFECTS
1237	    	pline("%s is no longer on ice at %d,%d.", The(xname(otmp)),x,y);
1238#endif
1239		/* Adjust the remaining time */
1240		tleft /= ROT_ICE_ADJUSTMENT;
1241		restart_timer = TRUE;
1242		/* Adjust the age */
1243		age = monstermoves - otmp->age;
1244		otmp->age = otmp->age + (age / ROT_ICE_ADJUSTMENT);
1245	}
1246    }
1247    /* now re-start the timer with the appropriate modifications */
1248    if (restart_timer)
1249	(void) start_timer(tleft, TIMER_OBJECT, action, (genericptr_t)otmp);
1250}
1251
1252#undef ON_ICE
1253#undef ROT_ICE_ADJUSTMENT
1254
1255void
1256remove_object(otmp)
1257register struct obj *otmp;
1258{
1259    xchar x = otmp->ox;
1260    xchar y = otmp->oy;
1261
1262    if (otmp->where != OBJ_FLOOR)
1263	panic("remove_object: obj not on floor");
1264    if (otmp->otyp == BOULDER) unblock_point(x,y); /* vision */
1265    extract_nexthere(otmp, &level.objects[x][y]);
1266    extract_nobj(otmp, &fobj);
1267    if (otmp->timed) obj_timer_checks(otmp,x,y,0);
1268}
1269
1270/* throw away all of a monster's inventory */
1271void
1272discard_minvent(mtmp)
1273struct monst *mtmp;
1274{
1275    struct obj *otmp;
1276
1277    while ((otmp = mtmp->minvent) != 0) {
1278	obj_extract_self(otmp);
1279	obfree(otmp, (struct obj *)0);	/* dealloc_obj() isn't sufficient */
1280    }
1281}
1282
1283/*
1284 * Free obj from whatever list it is on in preperation of deleting it or
1285 * moving it elsewhere.  This will perform all high-level consequences
1286 * involved with removing the item.  E.g. if the object is in the hero's
1287 * inventory and confers heat resistance, the hero will lose it.
1288 *
1289 * Object positions:
1290 *	OBJ_FREE	not on any list
1291 *	OBJ_FLOOR	fobj, level.locations[][] chains (use remove_object)
1292 *	OBJ_CONTAINED	cobj chain of container object
1293 *	OBJ_INVENT	hero's invent chain (use freeinv)
1294 *	OBJ_MINVENT	monster's invent chain
1295 *	OBJ_MIGRATING	migrating chain
1296 *	OBJ_BURIED	level.buriedobjs chain
1297 *	OBJ_ONBILL	on billobjs chain
1298 */
1299void
1300obj_extract_self(obj)
1301    struct obj *obj;
1302{
1303    switch (obj->where) {
1304	case OBJ_FREE:
1305	    break;
1306	case OBJ_FLOOR:
1307	    remove_object(obj);
1308	    break;
1309	case OBJ_CONTAINED:
1310	    extract_nobj(obj, &obj->ocontainer->cobj);
1311	    container_weight(obj->ocontainer);
1312	    break;
1313	case OBJ_INVENT:
1314	    freeinv(obj);
1315	    break;
1316	case OBJ_MINVENT:
1317	    extract_nobj(obj, &obj->ocarry->minvent);
1318	    break;
1319	case OBJ_MIGRATING:
1320	    extract_nobj(obj, &migrating_objs);
1321	    break;
1322	case OBJ_BURIED:
1323	    extract_nobj(obj, &level.buriedobjlist);
1324	    break;
1325	case OBJ_ONBILL:
1326	    extract_nobj(obj, &billobjs);
1327	    break;
1328	default:
1329	    panic("obj_extract_self");
1330	    break;
1331    }
1332}
1333
1334
1335/* Extract the given object from the chain, following nobj chain. */
1336void
1337extract_nobj(obj, head_ptr)
1338    struct obj *obj, **head_ptr;
1339{
1340    struct obj *curr, *prev;
1341
1342    curr = *head_ptr;
1343    for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) {
1344	if (curr == obj) {
1345	    if (prev)
1346		prev->nobj = curr->nobj;
1347	    else
1348		*head_ptr = curr->nobj;
1349	    break;
1350	}
1351    }
1352    if (!curr) panic("extract_nobj: object lost");
1353    obj->where = OBJ_FREE;
1354}
1355
1356
1357/*
1358 * Extract the given object from the chain, following nexthere chain.
1359 *
1360 * This does not set obj->where, this function is expected to be called
1361 * in tandem with extract_nobj, which does set it.
1362 */
1363void
1364extract_nexthere(obj, head_ptr)
1365    struct obj *obj, **head_ptr;
1366{
1367    struct obj *curr, *prev;
1368
1369    curr = *head_ptr;
1370    for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) {
1371	if (curr == obj) {
1372	    if (prev)
1373		prev->nexthere = curr->nexthere;
1374	    else
1375		*head_ptr = curr->nexthere;
1376	    break;
1377	}
1378    }
1379    if (!curr) panic("extract_nexthere: object lost");
1380}
1381
1382
1383/*
1384 * Add obj to mon's inventory.  If obj is able to merge with something already
1385 * in the inventory, then the passed obj is deleted and 1 is returned.
1386 * Otherwise 0 is returned.
1387 */
1388int
1389add_to_minv(mon, obj)
1390    struct monst *mon;
1391    struct obj *obj;
1392{
1393    struct obj *otmp;
1394
1395    if (obj->where != OBJ_FREE)
1396	panic("add_to_minv: obj not free");
1397
1398    /* merge if possible */
1399    for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
1400	if (merged(&otmp, &obj))
1401	    return 1;	/* obj merged and then free'd */
1402    /* else insert; don't bother forcing it to end of chain */
1403    obj->where = OBJ_MINVENT;
1404    obj->ocarry = mon;
1405    obj->nobj = mon->minvent;
1406    mon->minvent = obj;
1407    return 0;	/* obj on mon's inventory chain */
1408}
1409
1410/*
1411 * Add obj to container, make sure obj is "free".  Returns (merged) obj.
1412 * The input obj may be deleted in the process.
1413 */
1414struct obj *
1415add_to_container(container, obj)
1416    struct obj *container, *obj;
1417{
1418    struct obj *otmp;
1419
1420    if (obj->where != OBJ_FREE)
1421	panic("add_to_container: obj not free");
1422    if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT)
1423	obj_no_longer_held(obj);
1424
1425    /* merge if possible */
1426    for (otmp = container->cobj; otmp; otmp = otmp->nobj)
1427	if (merged(&otmp, &obj)) return (otmp);
1428
1429    obj->where = OBJ_CONTAINED;
1430    obj->ocontainer = container;
1431    obj->nobj = container->cobj;
1432    container->cobj = obj;
1433    return (obj);
1434}
1435
1436void
1437add_to_migration(obj)
1438    struct obj *obj;
1439{
1440    if (obj->where != OBJ_FREE)
1441	panic("add_to_migration: obj not free");
1442
1443    obj->where = OBJ_MIGRATING;
1444    obj->nobj = migrating_objs;
1445    migrating_objs = obj;
1446}
1447
1448void
1449add_to_buried(obj)
1450    struct obj *obj;
1451{
1452    if (obj->where != OBJ_FREE)
1453	panic("add_to_buried: obj not free");
1454
1455    obj->where = OBJ_BURIED;
1456    obj->nobj = level.buriedobjlist;
1457    level.buriedobjlist = obj;
1458}
1459
1460/* Recalculate the weight of this container and all of _its_ containers. */
1461STATIC_OVL void
1462container_weight(container)
1463    struct obj *container;
1464{
1465    container->owt = weight(container);
1466    if (container->where == OBJ_CONTAINED)
1467	container_weight(container->ocontainer);
1468/*
1469    else if (container->where == OBJ_INVENT)
1470	recalculate load delay here ???
1471*/
1472}
1473
1474/*
1475 * Deallocate the object.  _All_ objects should be run through here for
1476 * them to be deallocated.
1477 */
1478void
1479dealloc_obj(obj)
1480    struct obj *obj;
1481{
1482    if (obj->where != OBJ_FREE)
1483	panic("dealloc_obj: obj not free");
1484
1485    /* free up any timers attached to the object */
1486    if (obj->timed)
1487	obj_stop_timers(obj);
1488
1489    /*
1490     * Free up any light sources attached to the object.
1491     *
1492     * We may want to just call del_light_source() without any
1493     * checks (requires a code change there).  Otherwise this
1494     * list must track all objects that can have a light source
1495     * attached to it (and also requires lamplit to be set).
1496     */
1497    if (obj_sheds_light(obj))
1498	del_light_source(LS_OBJECT, (genericptr_t) obj);
1499
1500    if (obj == thrownobj) thrownobj = (struct obj*)0;
1501
1502    free((genericptr_t) obj);
1503}
1504
1505#ifdef WIZARD
1506/* Check all object lists for consistency. */
1507void
1508obj_sanity_check()
1509{
1510    int x, y;
1511    struct obj *obj;
1512    struct monst *mon;
1513    const char *mesg;
1514    char obj_address[20], mon_address[20];  /* room for formatted pointers */
1515
1516    mesg = "fobj sanity";
1517    for (obj = fobj; obj; obj = obj->nobj) {
1518	if (obj->where != OBJ_FLOOR) {
1519	    pline("%s obj %s %s@(%d,%d): %s\n", mesg,
1520		fmt_ptr((genericptr_t)obj, obj_address),
1521		where_name(obj->where),
1522		obj->ox, obj->oy, doname(obj));
1523	}
1524	check_contained(obj, mesg);
1525    }
1526
1527    mesg = "location sanity";
1528    for (x = 0; x < COLNO; x++)
1529	for (y = 0; y < ROWNO; y++)
1530	    for (obj = level.objects[x][y]; obj; obj = obj->nexthere)
1531		if (obj->where != OBJ_FLOOR) {
1532		    pline("%s obj %s %s@(%d,%d): %s\n", mesg,
1533			fmt_ptr((genericptr_t)obj, obj_address),
1534			where_name(obj->where),
1535			obj->ox, obj->oy, doname(obj));
1536		}
1537
1538    mesg = "invent sanity";
1539    for (obj = invent; obj; obj = obj->nobj) {
1540	if (obj->where != OBJ_INVENT) {
1541	    pline("%s obj %s %s: %s\n", mesg,
1542		fmt_ptr((genericptr_t)obj, obj_address),
1543		where_name(obj->where), doname(obj));
1544	}
1545	check_contained(obj, mesg);
1546    }
1547
1548    mesg = "migrating sanity";
1549    for (obj = migrating_objs; obj; obj = obj->nobj) {
1550	if (obj->where != OBJ_MIGRATING) {
1551	    pline("%s obj %s %s: %s\n", mesg,
1552		fmt_ptr((genericptr_t)obj, obj_address),
1553		where_name(obj->where), doname(obj));
1554	}
1555	check_contained(obj, mesg);
1556    }
1557
1558    mesg = "buried sanity";
1559    for (obj = level.buriedobjlist; obj; obj = obj->nobj) {
1560	if (obj->where != OBJ_BURIED) {
1561	    pline("%s obj %s %s: %s\n", mesg,
1562		fmt_ptr((genericptr_t)obj, obj_address),
1563		where_name(obj->where), doname(obj));
1564	}
1565	check_contained(obj, mesg);
1566    }
1567
1568    mesg = "bill sanity";
1569    for (obj = billobjs; obj; obj = obj->nobj) {
1570	if (obj->where != OBJ_ONBILL) {
1571	    pline("%s obj %s %s: %s\n", mesg,
1572		fmt_ptr((genericptr_t)obj, obj_address),
1573		where_name(obj->where), doname(obj));
1574	}
1575	/* shouldn't be a full container on the bill */
1576	if (obj->cobj) {
1577	    pline("%s obj %s contains %s! %s\n", mesg,
1578		fmt_ptr((genericptr_t)obj, obj_address),
1579		something, doname(obj));
1580	}
1581    }
1582
1583    mesg = "minvent sanity";
1584    for (mon = fmon; mon; mon = mon->nmon)
1585	for (obj = mon->minvent; obj; obj = obj->nobj) {
1586	    if (obj->where != OBJ_MINVENT) {
1587		pline("%s obj %s %s: %s\n", mesg,
1588			fmt_ptr((genericptr_t)obj, obj_address),
1589			where_name(obj->where), doname(obj));
1590	    }
1591	    if (obj->ocarry != mon) {
1592		pline("%s obj %s (%s) not held by mon %s (%s)\n", mesg,
1593			fmt_ptr((genericptr_t)obj, obj_address),
1594			doname(obj),
1595			fmt_ptr((genericptr_t)mon, mon_address),
1596			mon_nam(mon));
1597	    }
1598	    check_contained(obj, mesg);
1599	}
1600}
1601
1602/* This must stay consistent with the defines in obj.h. */
1603static const char *obj_state_names[NOBJ_STATES] = {
1604	"free",		"floor",	"contained",	"invent",
1605	"minvent",	"migrating",	"buried",	"onbill"
1606};
1607
1608STATIC_OVL const char *
1609where_name(where)
1610    int where;
1611{
1612    return (where<0 || where>=NOBJ_STATES) ? "unknown" : obj_state_names[where];
1613}
1614
1615/* obj sanity check: check objs contained by container */
1616STATIC_OVL void
1617check_contained(container, mesg)
1618    struct obj *container;
1619    const char *mesg;
1620{
1621    struct obj *obj;
1622    char obj1_address[20], obj2_address[20];
1623
1624    for (obj = container->cobj; obj; obj = obj->nobj) {
1625	if (obj->where != OBJ_CONTAINED)
1626	    pline("contained %s obj %s: %s\n", mesg,
1627		fmt_ptr((genericptr_t)obj, obj1_address),
1628		where_name(obj->where));
1629	else if (obj->ocontainer != container)
1630	    pline("%s obj %s not in container %s\n", mesg,
1631		fmt_ptr((genericptr_t)obj, obj1_address),
1632		fmt_ptr((genericptr_t)container, obj2_address));
1633    }
1634}
1635#endif /* WIZARD */
1636
1637#endif /* OVL1 */
1638
1639/*mkobj.c*/
1640