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