Fandom

Wikihack

Source:SLASH'EM 0.0.7E7F2/mkobj.c

2,034pages on
this wiki
Add New Page
Talk0

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.

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*/

Also on Fandom

Random Wiki