OSDN Git Service

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