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