Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/mkobj.c

2,034pages on
this wiki
Add New Page
Talk0

Below is the full text to mkobj.c from the source code of SLASH'EM 0.0.7E7F2. To link to a particular line, write [[SLASH'EM 0.0.7E7F2/mkobj.c#line123]], for example.

The latest source code for vanilla NetHack is at Source code.


The NetHack General Public License applies to screenshots, source code and other content from NetHack.
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 *
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 *
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 *
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
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
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 *
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
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
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 *
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
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
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
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
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
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
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
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
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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 *
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
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
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
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 *
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
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
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
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
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
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 *
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
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*/

Ad blocker interference detected!


Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.