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 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 
201 int
rndmonnum()202 rndmonnum()	/* 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  */
226 struct obj *
splitobj(obj,num)227 splitobj(obj, num)
228 struct obj *obj;
229 long 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  */
271 void
replace_object(obj,otmp)272 replace_object(obj, otmp)
273 struct obj *obj;
274 struct 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  */
328 void
bill_dummy_object(otmp)329 bill_dummy_object(otmp)
330 register 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 
357 static const char dknowns[] = {
358 		WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS,
359 		GEM_CLASS, SPBOOK_CLASS, WEAPON_CLASS, TOOL_CLASS, 0
360 };
361 
362 struct obj *
mksobj(otyp,init,artif)363 mksobj(otyp, init, artif)
364 int otyp;
365 boolean init;
366 boolean 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  */
639 void
start_corpse_timeout(body)640 start_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 
687 void
bless(otmp)688 bless(otmp)
689 register 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 
705 void
unbless(otmp)706 unbless(otmp)
707 register 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 
716 void
curse(otmp)717 curse(otmp)
718 register 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 
745 void
uncurse(otmp)746 uncurse(otmp)
747 register 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 
762 void
blessorcurse(otmp,chance)763 blessorcurse(otmp, chance)
764 register struct obj *otmp;
765 register 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 
782 int
bcsign(otmp)783 bcsign(otmp)
784 register 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  */
800 int
weight(obj)801 weight(obj)
802 register 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 
858 static int treefruits[] = {APPLE,ORANGE,PEAR,BANANA,EUCALYPTUS_LEAF};
859 
860 struct obj *
rnd_treefruit_at(x,y)861 rnd_treefruit_at(x,y)
862 int x, y;
863 {
864 	return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
865 }
866 #endif /* OVL0 */
867 #ifdef OVLB
868 
869 struct obj *
mkgold(amount,x,y)870 mkgold(amount, x, y)
871 long amount;
872 int 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  */
906 struct obj *
mkcorpstat(objtype,mtmp,ptr,x,y,init)907 mkcorpstat(objtype, mtmp, ptr, x, y, init)
908 int objtype;	/* CORPSE or STATUE */
909 struct monst *mtmp;
910 struct permonst *ptr;
911 int x, y;
912 boolean 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  */
954 struct obj *
obj_attach_mid(obj,mid)955 obj_attach_mid(obj, mid)
956 struct obj *obj;
957 unsigned 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 
977 static struct obj *
save_mtraits(obj,mtmp)978 save_mtraits(obj, mtmp)
979 struct obj *obj;
980 struct 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  */
1005 struct monst *
get_mtraits(obj,copyof)1006 get_mtraits(obj, copyof)
1007 struct obj *obj;
1008 boolean 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 */
1034 struct obj *
mk_tt_object(objtype,x,y)1035 mk_tt_object(objtype, x, y)
1036 int objtype; /* CORPSE or STATUE */
1037 register 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) */
1052 struct obj *
mk_named_object(objtype,ptr,x,y,nm)1053 mk_named_object(objtype, ptr, x, y, nm)
1054 int objtype;	/* CORPSE or STATUE */
1055 struct permonst *ptr;
1056 int x, y;
1057 const 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 
1068 boolean
is_flammable(otmp)1069 is_flammable(otmp)
1070 register 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 
1081 boolean
is_rottable(otmp)1082 is_rottable(otmp)
1083 register 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 */
1100 void
place_object(otmp,x,y)1101 place_object(otmp, x, y)
1102 register struct obj *otmp;
1103 int 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  */
1140 void
obj_ice_effects(x,y,do_buried)1141 obj_ice_effects(x, y, do_buried)
1142 int x, y;
1143 boolean 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  */
1166 long
peek_at_iced_corpse_age(otmp)1167 peek_at_iced_corpse_age(otmp)
1168 struct 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 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 
1186 STATIC_OVL void
obj_timer_checks(otmp,x,y,force)1187 obj_timer_checks(otmp, x, y, force)
1188 struct obj *otmp;
1189 xchar x, y;
1190 int 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 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 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 
1255 void
remove_object(otmp)1256 remove_object(otmp)
1257 register 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 */
1271 void
discard_minvent(mtmp)1272 discard_minvent(mtmp)
1273 struct 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  */
1299 void
obj_extract_self(obj)1300 obj_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. */
1336 void
extract_nobj(obj,head_ptr)1337 extract_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  */
1363 void
extract_nexthere(obj,head_ptr)1364 extract_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  */
1388 int
add_to_minv(mon,obj)1389 add_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  */
1414 struct obj *
add_to_container(container,obj)1415 add_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 
1436 void
add_to_migration(obj)1437 add_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 
1448 void
add_to_buried(obj)1449 add_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. */
1461 STATIC_OVL void
container_weight(container)1462 container_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  */
1478 void
dealloc_obj(obj)1479 dealloc_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. */
1507 void
obj_sanity_check()1508 obj_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. */
1603 static const char *obj_state_names[NOBJ_STATES] = {
1604 	"free",		"floor",	"contained",	"invent",
1605 	"minvent",	"migrating",	"buried",	"onbill"
1606 };
1607 
1608 STATIC_OVL const char *
where_name(where)1609 where_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 */
1616 STATIC_OVL void
check_contained(container,mesg)1617 check_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