1 /* NetHack 3.6	mkobj.c	$NHDT-Date: 1571531889 2019/10/20 00:38:09 $  $NHDT-Branch: NetHack-3.6 $:$NHDT-Revision: 1.157 $ */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /*-Copyright (c) Derek S. Ray, 2015. */
4 /* NetHack may be freely redistributed.  See license for details. */
5 
6 #include "hack.h"
7 
8 STATIC_DCL void FDECL(mkbox_cnts, (struct obj *));
9 STATIC_DCL unsigned FDECL(nextoid, (struct obj *, struct obj *));
10 STATIC_DCL void FDECL(maybe_adjust_light, (struct obj *, int));
11 STATIC_DCL void FDECL(obj_timer_checks, (struct obj *,
12                                          XCHAR_P, XCHAR_P, int));
13 STATIC_DCL void FDECL(container_weight, (struct obj *));
14 STATIC_DCL struct obj *FDECL(save_mtraits, (struct obj *, struct monst *));
15 STATIC_DCL void FDECL(objlist_sanity, (struct obj *, int, const char *));
16 STATIC_DCL void FDECL(mon_obj_sanity, (struct monst *, const char *));
17 STATIC_DCL const char *FDECL(where_name, (struct obj *));
18 STATIC_DCL void FDECL(insane_object, (struct obj *, const char *,
19                                       const char *, struct monst *));
20 STATIC_DCL void FDECL(check_contained, (struct obj *, const char *));
21 STATIC_DCL void FDECL(check_glob, (struct obj *, const char *));
22 STATIC_DCL void FDECL(sanity_check_worn, (struct obj *));
23 
24 struct icp {
25     int iprob;   /* probability of an item type */
26     char iclass; /* item class */
27 };
28 
29 static const struct icp mkobjprobs[] = { { 10, WEAPON_CLASS },
30                                          { 10, ARMOR_CLASS },
31                                          { 20, FOOD_CLASS },
32                                          { 8, TOOL_CLASS },
33                                          { 8, GEM_CLASS },
34                                          { 16, POTION_CLASS },
35                                          { 16, SCROLL_CLASS },
36                                          { 4, SPBOOK_CLASS },
37                                          { 4, WAND_CLASS },
38                                          { 3, RING_CLASS },
39                                          { 1, AMULET_CLASS } };
40 
41 static const struct icp boxiprobs[] = { { 18, GEM_CLASS },
42                                         { 15, FOOD_CLASS },
43                                         { 18, POTION_CLASS },
44                                         { 18, SCROLL_CLASS },
45                                         { 12, SPBOOK_CLASS },
46                                         { 7, COIN_CLASS },
47                                         { 6, WAND_CLASS },
48                                         { 5, RING_CLASS },
49                                         { 1, AMULET_CLASS } };
50 
51 static const struct icp rogueprobs[] = { { 12, WEAPON_CLASS },
52                                          { 12, ARMOR_CLASS },
53                                          { 22, FOOD_CLASS },
54                                          { 22, POTION_CLASS },
55                                          { 22, SCROLL_CLASS },
56                                          { 5, WAND_CLASS },
57                                          { 5, RING_CLASS } };
58 
59 static const struct icp hellprobs[] = { { 20, WEAPON_CLASS },
60                                         { 20, ARMOR_CLASS },
61                                         { 16, FOOD_CLASS },
62                                         { 12, TOOL_CLASS },
63                                         { 10, GEM_CLASS },
64                                         { 1, POTION_CLASS },
65                                         { 1, SCROLL_CLASS },
66                                         { 8, WAND_CLASS },
67                                         { 8, RING_CLASS },
68                                         { 4, AMULET_CLASS } };
69 
70 struct oextra *
newoextra()71 newoextra()
72 {
73     struct oextra *oextra;
74 
75     oextra = (struct oextra *) alloc(sizeof (struct oextra));
76     oextra->oname = 0;
77     oextra->omonst = 0;
78     oextra->omid = 0;
79     oextra->olong = 0;
80     oextra->omailcmd = 0;
81     return oextra;
82 }
83 
84 void
dealloc_oextra(o)85 dealloc_oextra(o)
86 struct obj *o;
87 {
88     struct oextra *x = o->oextra;
89 
90     if (x) {
91         if (x->oname)
92             free((genericptr_t) x->oname);
93         if (x->omonst)
94             free_omonst(o);     /* 'o' rather than 'x' */
95         if (x->omid)
96             free((genericptr_t) x->omid);
97         if (x->olong)
98             free((genericptr_t) x->olong);
99         if (x->omailcmd)
100             free((genericptr_t) x->omailcmd);
101 
102         free((genericptr_t) x);
103         o->oextra = (struct oextra *) 0;
104     }
105 }
106 
107 void
newomonst(otmp)108 newomonst(otmp)
109 struct obj *otmp;
110 {
111     if (!otmp->oextra)
112         otmp->oextra = newoextra();
113 
114     if (!OMONST(otmp)) {
115         struct monst *m = newmonst();
116 
117         *m = zeromonst;
118         OMONST(otmp) = m;
119     }
120 }
121 
122 void
free_omonst(otmp)123 free_omonst(otmp)
124 struct obj *otmp;
125 {
126     if (otmp->oextra) {
127         struct monst *m = OMONST(otmp);
128 
129         if (m) {
130             if (m->mextra)
131                 dealloc_mextra(m);
132             free((genericptr_t) m);
133             OMONST(otmp) = (struct monst *) 0;
134         }
135     }
136 }
137 
138 void
newomid(otmp)139 newomid(otmp)
140 struct obj *otmp;
141 {
142     if (!otmp->oextra)
143         otmp->oextra = newoextra();
144     if (!OMID(otmp)) {
145         OMID(otmp) = (unsigned *) alloc(sizeof (unsigned));
146         (void) memset((genericptr_t) OMID(otmp), 0, sizeof (unsigned));
147     }
148 }
149 
150 void
free_omid(otmp)151 free_omid(otmp)
152 struct obj *otmp;
153 {
154     if (otmp->oextra && OMID(otmp)) {
155         free((genericptr_t) OMID(otmp));
156         OMID(otmp) = (unsigned *) 0;
157     }
158 }
159 
160 void
newolong(otmp)161 newolong(otmp)
162 struct obj *otmp;
163 {
164     if (!otmp->oextra)
165         otmp->oextra = newoextra();
166     if (!OLONG(otmp)) {
167         OLONG(otmp) = (long *) alloc(sizeof (long));
168         (void) memset((genericptr_t) OLONG(otmp), 0, sizeof (long));
169     }
170 }
171 
172 void
free_olong(otmp)173 free_olong(otmp)
174 struct obj *otmp;
175 {
176     if (otmp->oextra && OLONG(otmp)) {
177         free((genericptr_t) OLONG(otmp));
178         OLONG(otmp) = (long *) 0;
179     }
180 }
181 
182 void
new_omailcmd(otmp,response_cmd)183 new_omailcmd(otmp, response_cmd)
184 struct obj *otmp;
185 const char *response_cmd;
186 {
187     if (!otmp->oextra)
188         otmp->oextra = newoextra();
189     if (OMAILCMD(otmp))
190         free_omailcmd(otmp);
191     OMAILCMD(otmp) = dupstr(response_cmd);
192 }
193 
194 void
free_omailcmd(otmp)195 free_omailcmd(otmp)
196 struct obj *otmp;
197 {
198     if (otmp->oextra && OMAILCMD(otmp)) {
199         free((genericptr_t) OMAILCMD(otmp));
200         OMAILCMD(otmp) = (char *) 0;
201     }
202 }
203 
204 struct obj *
mkobj_at(let,x,y,artif)205 mkobj_at(let, x, y, artif)
206 char let;
207 int x, y;
208 boolean artif;
209 {
210     struct obj *otmp;
211 
212     otmp = mkobj(let, artif);
213     place_object(otmp, x, y);
214     return otmp;
215 }
216 
217 struct obj *
mksobj_at(otyp,x,y,init,artif)218 mksobj_at(otyp, x, y, init, artif)
219 int otyp, x, y;
220 boolean init, artif;
221 {
222     struct obj *otmp;
223 
224     otmp = mksobj(otyp, init, artif);
225     place_object(otmp, x, y);
226     return otmp;
227 }
228 
229 struct obj *
mksobj_migr_to_species(otyp,mflags2,init,artif)230 mksobj_migr_to_species(otyp, mflags2, init, artif)
231 int otyp;
232 unsigned mflags2;
233 boolean init, artif;
234 {
235     struct obj *otmp;
236 
237     otmp = mksobj(otyp, init, artif);
238     add_to_migration(otmp);
239     otmp->owornmask = (long) MIGR_TO_SPECIES;
240     otmp->corpsenm = mflags2;
241     return otmp;
242 }
243 
244 /* mkobj(): select a type of item from a class, use mksobj() to create it;
245    result is always non-Null */
246 struct obj *
mkobj(oclass,artif)247 mkobj(oclass, artif)
248 char oclass;
249 boolean artif;
250 {
251     int tprob, i, prob = rnd(1000);
252 
253     if (oclass == RANDOM_CLASS) {
254         const struct icp *iprobs = Is_rogue_level(&u.uz)
255                                    ? (const struct icp *) rogueprobs
256                                    : Inhell ? (const struct icp *) hellprobs
257                                             : (const struct icp *) mkobjprobs;
258 
259         for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
260             ;
261         oclass = iprobs->iclass;
262     }
263 
264     i = bases[(int) oclass];
265     while ((prob -= objects[i].oc_prob) > 0)
266         i++;
267 
268     if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
269         panic("probtype error, oclass=%d i=%d", (int) oclass, i);
270 
271     return mksobj(i, TRUE, artif);
272 }
273 
274 STATIC_OVL void
mkbox_cnts(box)275 mkbox_cnts(box)
276 struct obj *box;
277 {
278     register int n;
279     register struct obj *otmp;
280 
281     box->cobj = (struct obj *) 0;
282 
283     switch (box->otyp) {
284     case ICE_BOX:
285         n = 20;
286         break;
287     case CHEST:
288         n = box->olocked ? 7 : 5;
289         break;
290     case LARGE_BOX:
291         n = box->olocked ? 5 : 3;
292         break;
293     case SACK:
294     case OILSKIN_SACK:
295         /* initial inventory: sack starts out empty */
296         if (moves <= 1 && !in_mklev) {
297             n = 0;
298             break;
299         }
300         /*FALLTHRU*/
301     case BAG_OF_HOLDING:
302         n = 1;
303         break;
304     default:
305         n = 0;
306         break;
307     }
308 
309     for (n = rn2(n + 1); n > 0; n--) {
310         if (box->otyp == ICE_BOX) {
311             otmp = mksobj(CORPSE, TRUE, TRUE);
312             /* Note: setting age to 0 is correct.  Age has a different
313              * from usual meaning for objects stored in ice boxes. -KAA
314              */
315             otmp->age = 0L;
316             if (otmp->timed) {
317                 (void) stop_timer(ROT_CORPSE, obj_to_any(otmp));
318                 (void) stop_timer(REVIVE_MON, obj_to_any(otmp));
319             }
320         } else {
321             register int tprob;
322             const struct icp *iprobs = boxiprobs;
323 
324             for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
325                 ;
326             if (!(otmp = mkobj(iprobs->iclass, TRUE)))
327                 continue;
328 
329             /* handle a couple of special cases */
330             if (otmp->oclass == COIN_CLASS) {
331                 /* 2.5 x level's usual amount; weight adjusted below */
332                 otmp->quan = (long) (rnd(level_difficulty() + 2) * rnd(75));
333                 otmp->owt = weight(otmp);
334             } else
335                 while (otmp->otyp == ROCK) {
336                     otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE);
337                     if (otmp->quan > 2L)
338                         otmp->quan = 1L;
339                     otmp->owt = weight(otmp);
340                 }
341             if (box->otyp == BAG_OF_HOLDING) {
342                 if (Is_mbag(otmp)) {
343                     otmp->otyp = SACK;
344                     otmp->spe = 0;
345                     otmp->owt = weight(otmp);
346                 } else
347                     while (otmp->otyp == WAN_CANCELLATION)
348                         otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
349             }
350         }
351         (void) add_to_container(box, otmp);
352     }
353 }
354 
355 /* select a random, common monster type */
356 int
rndmonnum()357 rndmonnum()
358 {
359     register struct permonst *ptr;
360     register int i;
361     unsigned short excludeflags;
362 
363     /* Plan A: get a level-appropriate common monster */
364     ptr = rndmonst();
365     if (ptr)
366         return monsndx(ptr);
367 
368     /* Plan B: get any common monster */
369     excludeflags = G_UNIQ | G_NOGEN | (Inhell ? G_NOHELL : G_HELL);
370     do {
371         i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
372         ptr = &mons[i];
373     } while ((ptr->geno & excludeflags) != 0);
374 
375     return i;
376 }
377 
378 void
copy_oextra(obj2,obj1)379 copy_oextra(obj2, obj1)
380 struct obj *obj2, *obj1;
381 {
382     if (!obj2 || !obj1 || !obj1->oextra)
383         return;
384 
385     if (!obj2->oextra)
386         obj2->oextra = newoextra();
387     if (has_oname(obj1))
388         oname(obj2, ONAME(obj1));
389     if (has_omonst(obj1)) {
390         if (!OMONST(obj2))
391             newomonst(obj2);
392         (void) memcpy((genericptr_t) OMONST(obj2),
393                       (genericptr_t) OMONST(obj1), sizeof (struct monst));
394         OMONST(obj2)->mextra = (struct mextra *) 0;
395         OMONST(obj2)->nmon = (struct monst *) 0;
396 #if 0
397         OMONST(obj2)->m_id = context.ident++;
398         if (OMONST(obj2)->m_id) /* ident overflowed */
399             OMONST(obj2)->m_id = context.ident++;
400 #endif
401         if (OMONST(obj1)->mextra)
402             copy_mextra(OMONST(obj2), OMONST(obj1));
403     }
404     if (has_omid(obj1)) {
405         if (!OMID(obj2))
406             newomid(obj2);
407         (void) memcpy((genericptr_t) OMID(obj2), (genericptr_t) OMID(obj1),
408                       sizeof (unsigned));
409     }
410     if (has_olong(obj1)) {
411         if (!OLONG(obj2))
412             newolong(obj2);
413         (void) memcpy((genericptr_t) OLONG(obj2), (genericptr_t) OLONG(obj1),
414                       sizeof (long));
415     }
416     if (has_omailcmd(obj1)) {
417         new_omailcmd(obj2, OMAILCMD(obj1));
418     }
419 }
420 
421 /*
422  * Split obj so that it gets size gets reduced by num. The quantity num is
423  * put in the object structure delivered by this call.  The returned object
424  * has its wornmask cleared and is positioned just following the original
425  * in the nobj chain (and nexthere chain when on the floor).
426  */
427 struct obj *
splitobj(obj,num)428 splitobj(obj, num)
429 struct obj *obj;
430 long num;
431 {
432     struct obj *otmp;
433 
434     if (obj->cobj || num <= 0L || obj->quan <= num)
435         panic("splitobj"); /* can't split containers */
436     otmp = newobj();
437     *otmp = *obj; /* copies whole structure */
438     otmp->oextra = (struct oextra *) 0;
439     otmp->o_id = nextoid(obj, otmp);
440     otmp->timed = 0;                  /* not timed, yet */
441     otmp->lamplit = 0;                /* ditto */
442     otmp->owornmask = 0L;             /* new object isn't worn */
443     obj->quan -= num;
444     obj->owt = weight(obj);
445     otmp->quan = num;
446     otmp->owt = weight(otmp); /* -= obj->owt ? */
447 
448     context.objsplit.parent_oid = obj->o_id;
449     context.objsplit.child_oid = otmp->o_id;
450     obj->nobj = otmp;
451     /* Only set nexthere when on the floor, nexthere is also used */
452     /* as a back pointer to the container object when contained. */
453     if (obj->where == OBJ_FLOOR)
454         obj->nexthere = otmp;
455     copy_oextra(otmp, obj);
456     if (has_omid(otmp))
457         free_omid(otmp); /* only one association with m_id*/
458     if (obj->unpaid)
459         splitbill(obj, otmp);
460     if (obj->timed)
461         obj_split_timers(obj, otmp);
462     if (obj_sheds_light(obj))
463         obj_split_light_source(obj, otmp);
464     return otmp;
465 }
466 
467 /* when splitting a stack that has o_id-based shop prices, pick an
468    o_id value for the new stack that will maintain the same price */
469 STATIC_OVL unsigned
nextoid(oldobj,newobj)470 nextoid(oldobj, newobj)
471 struct obj *oldobj, *newobj;
472 {
473     int olddif, newdif, trylimit = 256; /* limit of 4 suffices at present */
474     unsigned oid = context.ident - 1; /* loop increment will reverse -1 */
475 
476     olddif = oid_price_adjustment(oldobj, oldobj->o_id);
477     do {
478         ++oid;
479         if (!oid) /* avoid using 0 (in case value wrapped) */
480             ++oid;
481         newdif = oid_price_adjustment(newobj, oid);
482     } while (newdif != olddif && --trylimit >= 0);
483     context.ident = oid + 1; /* ready for next new object */
484     return oid;
485 }
486 
487 /* try to find the stack obj was split from, then merge them back together;
488    returns the combined object if unsplit is successful, null otherwise */
489 struct obj *
unsplitobj(obj)490 unsplitobj(obj)
491 struct obj *obj;
492 {
493     unsigned target_oid = 0;
494     struct obj *oparent = 0, *ochild = 0, *list = 0;
495 
496     /*
497      * We don't operate on floor objects (we're following o->nobj rather
498      * than o->nexthere), on free objects (don't know which list to use when
499      * looking for obj's parent or child), on bill objects (too complicated,
500      * not needed), or on buried or migrating objects (not needed).
501      * [This could be improved, but at present additional generality isn't
502      * necessary.]
503      */
504     switch (obj->where) {
505     case OBJ_FREE:
506     case OBJ_FLOOR:
507     case OBJ_ONBILL:
508     case OBJ_MIGRATING:
509     case OBJ_BURIED:
510     default:
511         return (struct obj *) 0;
512     case OBJ_INVENT:
513         list = invent;
514         break;
515     case OBJ_MINVENT:
516         list = obj->ocarry->minvent;
517         break;
518     case OBJ_CONTAINED:
519         list = obj->ocontainer->cobj;
520         break;
521     }
522 
523     /* first try the expected case; obj is split from another stack */
524     if (obj->o_id == context.objsplit.child_oid) {
525         /* parent probably precedes child and will require list traversal */
526         ochild = obj;
527         target_oid = context.objsplit.parent_oid;
528         if (obj->nobj && obj->nobj->o_id == target_oid)
529             oparent = obj->nobj;
530     } else if (obj->o_id == context.objsplit.parent_oid) {
531         /* alternate scenario: another stack was split from obj;
532            child probably follows parent and will be found here */
533         oparent = obj;
534         target_oid = context.objsplit.child_oid;
535         if (obj->nobj && obj->nobj->o_id == target_oid)
536             ochild = obj->nobj;
537     }
538     /* if we have only half the split, scan obj's list to find other half */
539     if (ochild && !oparent) {
540         /* expected case */
541         for (obj = list; obj; obj = obj->nobj)
542             if (obj->o_id == target_oid) {
543                 oparent = obj;
544                 break;
545             }
546     } else if (oparent && !ochild) {
547         /* alternate scenario */
548         for (obj = list; obj; obj = obj->nobj)
549             if (obj->o_id == target_oid) {
550                 ochild = obj;
551                 break;
552             }
553     }
554     /* if we have both parent and child, try to merge them;
555        if successful, return the combined stack, otherwise return null */
556     return (oparent && ochild && merged(&oparent, &ochild)) ? oparent : 0;
557 }
558 
559 /* reset splitobj()/unsplitobj() context */
560 void
clear_splitobjs()561 clear_splitobjs()
562 {
563     context.objsplit.parent_oid = context.objsplit.child_oid = 0;
564 }
565 
566 /*
567  * Insert otmp right after obj in whatever chain(s) it is on.  Then extract
568  * obj from the chain(s).  This function does a literal swap.  It is up to
569  * the caller to provide a valid context for the swap.  When done, obj will
570  * still exist, but not on any chain.
571  *
572  * Note:  Don't use use obj_extract_self() -- we are doing an in-place swap,
573  * not actually moving something.
574  */
575 void
replace_object(obj,otmp)576 replace_object(obj, otmp)
577 struct obj *obj;
578 struct obj *otmp;
579 {
580     otmp->where = obj->where;
581     switch (obj->where) {
582     case OBJ_FREE:
583         /* do nothing */
584         break;
585     case OBJ_INVENT:
586         otmp->nobj = obj->nobj;
587         obj->nobj = otmp;
588         extract_nobj(obj, &invent);
589         break;
590     case OBJ_CONTAINED:
591         otmp->nobj = obj->nobj;
592         otmp->ocontainer = obj->ocontainer;
593         obj->nobj = otmp;
594         extract_nobj(obj, &obj->ocontainer->cobj);
595         break;
596     case OBJ_MINVENT:
597         otmp->nobj = obj->nobj;
598         otmp->ocarry = obj->ocarry;
599         obj->nobj = otmp;
600         extract_nobj(obj, &obj->ocarry->minvent);
601         break;
602     case OBJ_FLOOR:
603         otmp->nobj = obj->nobj;
604         otmp->nexthere = obj->nexthere;
605         otmp->ox = obj->ox;
606         otmp->oy = obj->oy;
607         obj->nobj = otmp;
608         obj->nexthere = otmp;
609         extract_nobj(obj, &fobj);
610         extract_nexthere(obj, &level.objects[obj->ox][obj->oy]);
611         break;
612     default:
613         panic("replace_object: obj position");
614         break;
615     }
616 }
617 
618 /* is 'obj' inside a container whose contents aren't known?
619    if so, return the outermost container meeting that criterium */
620 struct obj *
unknwn_contnr_contents(obj)621 unknwn_contnr_contents(obj)
622 struct obj *obj;
623 {
624     struct obj *result = 0, *parent;
625 
626     while (obj->where == OBJ_CONTAINED) {
627         parent = obj->ocontainer;
628         if (!parent->cknown)
629             result = parent;
630         obj = parent;
631     }
632     return result;
633 }
634 
635 /*
636  * Create a dummy duplicate to put on shop bill.  The duplicate exists
637  * only in the billobjs chain.  This function is used when a shop object
638  * is being altered, and a copy of the original is needed for billing
639  * purposes.  For example, when eating, where an interruption will yield
640  * an object which is different from what it started out as; the "I x"
641  * command needs to display the original object.
642  *
643  * The caller is responsible for checking otmp->unpaid and
644  * costly_spot(u.ux, u.uy).  This function will make otmp no charge.
645  *
646  * Note that check_unpaid_usage() should be used instead for partial
647  * usage of an object.
648  */
649 void
bill_dummy_object(otmp)650 bill_dummy_object(otmp)
651 register struct obj *otmp;
652 {
653     register struct obj *dummy;
654     long cost = 0L;
655 
656     if (otmp->unpaid) {
657         cost = unpaid_cost(otmp, FALSE);
658         subfrombill(otmp, shop_keeper(*u.ushops));
659     }
660     dummy = newobj();
661     *dummy = *otmp;
662     dummy->oextra = (struct oextra *) 0;
663     dummy->where = OBJ_FREE;
664     dummy->o_id = context.ident++;
665     if (!dummy->o_id)
666         dummy->o_id = context.ident++; /* ident overflowed */
667     dummy->timed = 0;
668     copy_oextra(dummy, otmp);
669     if (has_omid(dummy))
670         free_omid(dummy); /* only one association with m_id*/
671     if (Is_candle(dummy))
672         dummy->lamplit = 0;
673     dummy->owornmask = 0L; /* dummy object is not worn */
674     addtobill(dummy, FALSE, TRUE, TRUE);
675     if (cost)
676         alter_cost(dummy, -cost);
677     /* no_charge is only valid for some locations */
678     otmp->no_charge =
679         (otmp->where == OBJ_FLOOR || otmp->where == OBJ_CONTAINED) ? 1 : 0;
680     otmp->unpaid = 0;
681     return;
682 }
683 
684 /* alteration types; must match COST_xxx macros in hack.h */
685 static const char *const alteration_verbs[] = {
686     "cancel", "drain", "uncharge", "unbless", "uncurse", "disenchant",
687     "degrade", "dilute", "erase", "burn", "neutralize", "destroy", "splatter",
688     "bite", "open", "break the lock on", "rust", "rot", "tarnish"
689 };
690 
691 /* possibly bill for an object which the player has just modified */
692 void
costly_alteration(obj,alter_type)693 costly_alteration(obj, alter_type)
694 struct obj *obj;
695 int alter_type;
696 {
697     xchar ox, oy;
698     char objroom;
699     boolean learn_bknown;
700     const char *those, *them;
701     struct monst *shkp = 0;
702 
703     if (alter_type < 0 || alter_type >= SIZE(alteration_verbs)) {
704         impossible("invalid alteration type (%d)", alter_type);
705         alter_type = 0;
706     }
707 
708     ox = oy = 0;    /* lint suppression */
709     objroom = '\0'; /* ditto */
710     if (carried(obj) || obj->where == OBJ_FREE) {
711         /* OBJ_FREE catches obj_no_longer_held()'s transformation
712            of crysknife back into worm tooth; the object has been
713            removed from inventory but not necessarily placed at
714            its new location yet--the unpaid flag will still be set
715            if this item is owned by a shop */
716         if (!obj->unpaid)
717             return;
718     } else {
719         /* this get_obj_location shouldn't fail, but if it does,
720            use hero's location */
721         if (!get_obj_location(obj, &ox, &oy, CONTAINED_TOO))
722             ox = u.ux, oy = u.uy;
723         if (!costly_spot(ox, oy))
724             return;
725         objroom = *in_rooms(ox, oy, SHOPBASE);
726         /* if no shop cares about it, we're done */
727         if (!billable(&shkp, obj, objroom, FALSE))
728             return;
729     }
730 
731     if (obj->quan == 1L)
732         those = "that", them = "it";
733     else
734         those = "those", them = "them";
735 
736     /* when shopkeeper describes the object as being uncursed or unblessed
737        hero will know that it is now uncursed; will also make the feedback
738        from `I x' after bill_dummy_object() be more specific for this item */
739     learn_bknown = (alter_type == COST_UNCURS || alter_type == COST_UNBLSS);
740 
741     switch (obj->where) {
742     case OBJ_FREE: /* obj_no_longer_held() */
743     case OBJ_INVENT:
744         if (learn_bknown)
745             set_bknown(obj, 1);
746         verbalize("You %s %s %s, you pay for %s!",
747                   alteration_verbs[alter_type], those, simpleonames(obj),
748                   them);
749         bill_dummy_object(obj);
750         break;
751     case OBJ_FLOOR:
752         if (learn_bknown)
753             obj->bknown = 1; /* ok to bypass set_bknown() here */
754         if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
755             verbalize("You %s %s, you pay for %s!",
756                       alteration_verbs[alter_type], those, them);
757             bill_dummy_object(obj);
758         } else {
759             (void) stolen_value(obj, ox, oy, FALSE, FALSE);
760         }
761         break;
762     }
763 }
764 
765 static const char dknowns[] = { WAND_CLASS,   RING_CLASS, POTION_CLASS,
766                                 SCROLL_CLASS, GEM_CLASS,  SPBOOK_CLASS,
767                                 WEAPON_CLASS, TOOL_CLASS, 0 };
768 
769 /* mksobj(): create a specific type of object; result it always non-Null */
770 struct obj *
mksobj(otyp,init,artif)771 mksobj(otyp, init, artif)
772 int otyp;
773 boolean init;
774 boolean artif;
775 {
776     int mndx, tryct;
777     struct obj *otmp;
778     char let = objects[otyp].oc_class;
779 
780     otmp = newobj();
781     *otmp = zeroobj;
782     otmp->age = monstermoves;
783     otmp->o_id = context.ident++;
784     if (!otmp->o_id)
785         otmp->o_id = context.ident++; /* ident overflowed */
786     otmp->quan = 1L;
787     otmp->oclass = let;
788     otmp->otyp = otyp;
789     otmp->where = OBJ_FREE;
790     otmp->dknown = index(dknowns, let) ? 0 : 1;
791     if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD)
792         || otmp->otyp == SHIELD_OF_REFLECTION
793         || objects[otmp->otyp].oc_merge)
794         otmp->dknown = 0;
795     if (!objects[otmp->otyp].oc_uses_known)
796         otmp->known = 1;
797     otmp->lknown = 0;
798     otmp->cknown = 0;
799     otmp->corpsenm = NON_PM;
800 
801     if (init) {
802         switch (let) {
803         case WEAPON_CLASS:
804             otmp->quan = is_multigen(otmp) ? (long) rn1(6, 6) : 1L;
805             if (!rn2(11)) {
806                 otmp->spe = rne(3);
807                 otmp->blessed = rn2(2);
808             } else if (!rn2(10)) {
809                 curse(otmp);
810                 otmp->spe = -rne(3);
811             } else
812                 blessorcurse(otmp, 10);
813             if (is_poisonable(otmp) && !rn2(100))
814                 otmp->opoisoned = 1;
815 
816             if (artif && !rn2(20))
817                 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
818             break;
819         case FOOD_CLASS:
820             otmp->oeaten = 0;
821             switch (otmp->otyp) {
822             case CORPSE:
823                 /* possibly overridden by mkcorpstat() */
824                 tryct = 50;
825                 do
826                     otmp->corpsenm = undead_to_corpse(rndmonnum());
827                 while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE)
828                        && (--tryct > 0));
829                 if (tryct == 0) {
830                     /* perhaps rndmonnum() only wants to make G_NOCORPSE
831                        monsters on this level; create an adventurer's
832                        corpse instead, then */
833                     otmp->corpsenm = PM_HUMAN;
834                 }
835                 /* timer set below */
836                 break;
837             case EGG:
838                 otmp->corpsenm = NON_PM; /* generic egg */
839                 if (!rn2(3))
840                     for (tryct = 200; tryct > 0; --tryct) {
841                         mndx = can_be_hatched(rndmonnum());
842                         if (mndx != NON_PM && !dead_species(mndx, TRUE)) {
843                             otmp->corpsenm = mndx; /* typed egg */
844                             break;
845                         }
846                     }
847                 /* timer set below */
848                 break;
849             case TIN:
850                 otmp->corpsenm = NON_PM; /* empty (so far) */
851                 if (!rn2(6))
852                     set_tin_variety(otmp, SPINACH_TIN);
853                 else
854                     for (tryct = 200; tryct > 0; --tryct) {
855                         mndx = undead_to_corpse(rndmonnum());
856                         if (mons[mndx].cnutrit
857                             && !(mvitals[mndx].mvflags & G_NOCORPSE)) {
858                             otmp->corpsenm = mndx;
859                             set_tin_variety(otmp, RANDOM_TIN);
860                             break;
861                         }
862                     }
863                 blessorcurse(otmp, 10);
864                 break;
865             case SLIME_MOLD:
866                 otmp->spe = context.current_fruit;
867                 flags.made_fruit = TRUE;
868                 break;
869             case KELP_FROND:
870                 otmp->quan = (long) rnd(2);
871                 break;
872             }
873             if (Is_pudding(otmp)) {
874                 otmp->quan = 1L; /* for emphasis; glob quantity is always 1 */
875                 otmp->globby = 1;
876                 otmp->known = otmp->dknown = 1;
877                 otmp->corpsenm = PM_GRAY_OOZE
878                                  + (otmp->otyp - GLOB_OF_GRAY_OOZE);
879             } else {
880                 if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
881                     && otmp->otyp != KELP_FROND && !rn2(6)) {
882                     otmp->quan = 2L;
883                 }
884             }
885             break;
886         case GEM_CLASS:
887             otmp->corpsenm = 0; /* LOADSTONE hack */
888             if (otmp->otyp == LOADSTONE)
889                 curse(otmp);
890             else if (otmp->otyp == ROCK)
891                 otmp->quan = (long) rn1(6, 6);
892             else if (otmp->otyp != LUCKSTONE && !rn2(6))
893                 otmp->quan = 2L;
894             else
895                 otmp->quan = 1L;
896             break;
897         case TOOL_CLASS:
898             switch (otmp->otyp) {
899             case TALLOW_CANDLE:
900             case WAX_CANDLE:
901                 otmp->spe = 1;
902                 otmp->age = 20L * /* 400 or 200 */
903                             (long) objects[otmp->otyp].oc_cost;
904                 otmp->lamplit = 0;
905                 otmp->quan = 1L + (long) (rn2(2) ? rn2(7) : 0);
906                 blessorcurse(otmp, 5);
907                 break;
908             case BRASS_LANTERN:
909             case OIL_LAMP:
910                 otmp->spe = 1;
911                 otmp->age = (long) rn1(500, 1000);
912                 otmp->lamplit = 0;
913                 blessorcurse(otmp, 5);
914                 break;
915             case MAGIC_LAMP:
916                 otmp->spe = 1;
917                 otmp->lamplit = 0;
918                 blessorcurse(otmp, 2);
919                 break;
920             case CHEST:
921             case LARGE_BOX:
922                 otmp->olocked = !!(rn2(5));
923                 otmp->otrapped = !(rn2(10));
924                 /*FALLTHRU*/
925             case ICE_BOX:
926             case SACK:
927             case OILSKIN_SACK:
928             case BAG_OF_HOLDING:
929                 mkbox_cnts(otmp);
930                 break;
931             case EXPENSIVE_CAMERA:
932             case TINNING_KIT:
933             case MAGIC_MARKER:
934                 otmp->spe = rn1(70, 30);
935                 break;
936             case CAN_OF_GREASE:
937                 otmp->spe = rnd(25);
938                 blessorcurse(otmp, 10);
939                 break;
940             case CRYSTAL_BALL:
941                 otmp->spe = rnd(5);
942                 blessorcurse(otmp, 2);
943                 break;
944             case HORN_OF_PLENTY:
945             case BAG_OF_TRICKS:
946                 otmp->spe = rnd(20);
947                 break;
948             case FIGURINE:
949                 tryct = 0;
950                 do
951                     otmp->corpsenm = rndmonnum();
952                 while (is_human(&mons[otmp->corpsenm]) && tryct++ < 30);
953                 blessorcurse(otmp, 4);
954                 break;
955             case BELL_OF_OPENING:
956                 otmp->spe = 3;
957                 break;
958             case MAGIC_FLUTE:
959             case MAGIC_HARP:
960             case FROST_HORN:
961             case FIRE_HORN:
962             case DRUM_OF_EARTHQUAKE:
963                 otmp->spe = rn1(5, 4);
964                 break;
965             }
966             break;
967         case AMULET_CLASS:
968             if (otmp->otyp == AMULET_OF_YENDOR)
969                 context.made_amulet = TRUE;
970             if (rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION
971                             || otmp->otyp == AMULET_OF_CHANGE
972                             || otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
973                 curse(otmp);
974             } else
975                 blessorcurse(otmp, 10);
976             break;
977         case VENOM_CLASS:
978         case CHAIN_CLASS:
979         case BALL_CLASS:
980             break;
981         case POTION_CLASS: /* note: potions get some additional init below */
982         case SCROLL_CLASS:
983 #ifdef MAIL
984             if (otmp->otyp != SCR_MAIL)
985 #endif
986                 blessorcurse(otmp, 4);
987             break;
988         case SPBOOK_CLASS:
989             otmp->spestudied = 0;
990             blessorcurse(otmp, 17);
991             break;
992         case ARMOR_CLASS:
993             if (rn2(10)
994                 && (otmp->otyp == FUMBLE_BOOTS
995                     || otmp->otyp == LEVITATION_BOOTS
996                     || otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT
997                     || otmp->otyp == GAUNTLETS_OF_FUMBLING || !rn2(11))) {
998                 curse(otmp);
999                 otmp->spe = -rne(3);
1000             } else if (!rn2(10)) {
1001                 otmp->blessed = rn2(2);
1002                 otmp->spe = rne(3);
1003             } else
1004                 blessorcurse(otmp, 10);
1005             if (artif && !rn2(40))
1006                 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1007             /* simulate lacquered armor for samurai */
1008             if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL
1009                 && (moves <= 1 || In_quest(&u.uz))) {
1010 #ifdef UNIXPC
1011                 /* optimizer bitfield bug */
1012                 otmp->oerodeproof = 1;
1013                 otmp->rknown = 1;
1014 #else
1015                 otmp->oerodeproof = otmp->rknown = 1;
1016 #endif
1017             }
1018             break;
1019         case WAND_CLASS:
1020             if (otmp->otyp == WAN_WISHING)
1021                 otmp->spe = rnd(3);
1022             else
1023                 otmp->spe =
1024                     rn1(5, (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
1025             blessorcurse(otmp, 17);
1026             otmp->recharged = 0; /* used to control recharging */
1027             break;
1028         case RING_CLASS:
1029             if (objects[otmp->otyp].oc_charged) {
1030                 blessorcurse(otmp, 3);
1031                 if (rn2(10)) {
1032                     if (rn2(10) && bcsign(otmp))
1033                         otmp->spe = bcsign(otmp) * rne(3);
1034                     else
1035                         otmp->spe = rn2(2) ? rne(3) : -rne(3);
1036                 }
1037                 /* make useless +0 rings much less common */
1038                 if (otmp->spe == 0)
1039                     otmp->spe = rn2(4) - rn2(3);
1040                 /* negative rings are usually cursed */
1041                 if (otmp->spe < 0 && rn2(5))
1042                     curse(otmp);
1043             } else if (rn2(10) && (otmp->otyp == RIN_TELEPORTATION
1044                                    || otmp->otyp == RIN_POLYMORPH
1045                                    || otmp->otyp == RIN_AGGRAVATE_MONSTER
1046                                    || otmp->otyp == RIN_HUNGER || !rn2(9))) {
1047                 curse(otmp);
1048             }
1049             break;
1050         case ROCK_CLASS:
1051             switch (otmp->otyp) {
1052             case STATUE:
1053                 /* possibly overridden by mkcorpstat() */
1054                 otmp->corpsenm = rndmonnum();
1055                 if (!verysmall(&mons[otmp->corpsenm])
1056                     && rn2(level_difficulty() / 2 + 10) > 10)
1057                     (void) add_to_container(otmp, mkobj(SPBOOK_CLASS, FALSE));
1058             }
1059             break;
1060         case COIN_CLASS:
1061             break; /* do nothing */
1062         default:
1063             /* 3.6.3: this used to be impossible() followed by return 0
1064                but most callers aren't prepared to deal with Null result
1065                and cluttering them up to do so is pointless */
1066             panic("mksobj tried to make type %d, class %d.",
1067                   (int) otmp->otyp, (int) objects[otmp->otyp].oc_class);
1068             /*NOTREACHED*/
1069         }
1070     }
1071 
1072     /* some things must get done (corpsenm, timers) even if init = 0 */
1073     switch ((otmp->oclass == POTION_CLASS && otmp->otyp != POT_OIL)
1074             ? POT_WATER
1075             : otmp->otyp) {
1076     case CORPSE:
1077         if (otmp->corpsenm == NON_PM) {
1078             otmp->corpsenm = undead_to_corpse(rndmonnum());
1079             if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE | G_GONE))
1080                 otmp->corpsenm = urole.malenum;
1081         }
1082         /*FALLTHRU*/
1083     case STATUE:
1084     case FIGURINE:
1085         if (otmp->corpsenm == NON_PM)
1086             otmp->corpsenm = rndmonnum();
1087         /*FALLTHRU*/
1088     case EGG:
1089     /* case TIN: */
1090         set_corpsenm(otmp, otmp->corpsenm);
1091         break;
1092     case POT_OIL:
1093         otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
1094         /*FALLTHRU*/
1095     case POT_WATER: /* POTION_CLASS */
1096         otmp->fromsink = 0; /* overloads corpsenm, which was set to NON_PM */
1097         break;
1098     case LEASH:
1099         otmp->leashmon = 0; /* overloads corpsenm, which was set to NON_PM */
1100         break;
1101     case SPE_NOVEL:
1102         otmp->novelidx = -1; /* "none of the above"; will be changed */
1103         otmp = oname(otmp, noveltitle(&otmp->novelidx));
1104         break;
1105     }
1106 
1107     /* unique objects may have an associated artifact entry */
1108     if (objects[otyp].oc_unique && !otmp->oartifact)
1109         otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1110     otmp->owt = weight(otmp);
1111     return otmp;
1112 }
1113 
1114 /*
1115  * Several areas of the code made direct reassignments
1116  * to obj->corpsenm. Because some special handling is
1117  * required in certain cases, place that handling here
1118  * and call this routine in place of the direct assignment.
1119  *
1120  * If the object was a lizard or lichen corpse:
1121  *     - ensure that you don't end up with some
1122  *       other corpse type which has no rot-away timer.
1123  *
1124  * If the object was a troll corpse:
1125  *     - ensure that you don't end up with some other
1126  *       corpse type which resurrects from the dead.
1127  *
1128  * Re-calculates the weight of figurines and corpses to suit the
1129  * new species.
1130  *
1131  * Existing timeout value for egg hatch is preserved.
1132  *
1133  */
1134 void
set_corpsenm(obj,id)1135 set_corpsenm(obj, id)
1136 struct obj *obj;
1137 int id;
1138 {
1139     long when = 0L;
1140 
1141     if (obj->timed) {
1142         if (obj->otyp == EGG)
1143             when = stop_timer(HATCH_EGG, obj_to_any(obj));
1144         else {
1145             when = 0L;
1146             obj_stop_timers(obj); /* corpse or figurine */
1147         }
1148     }
1149     obj->corpsenm = id;
1150     switch (obj->otyp) {
1151     case CORPSE:
1152         start_corpse_timeout(obj);
1153         obj->owt = weight(obj);
1154         break;
1155     case FIGURINE:
1156         if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE)
1157             && (carried(obj) || mcarried(obj)))
1158             attach_fig_transform_timeout(obj);
1159         obj->owt = weight(obj);
1160         break;
1161     case EGG:
1162         if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
1163             attach_egg_hatch_timeout(obj, when);
1164         break;
1165     default: /* tin, etc. */
1166         obj->owt = weight(obj);
1167         break;
1168     }
1169 }
1170 
1171 /*
1172  * Start a corpse decay or revive timer.
1173  * This takes the age of the corpse into consideration as of 3.4.0.
1174  */
1175 void
start_corpse_timeout(body)1176 start_corpse_timeout(body)
1177 struct obj *body;
1178 {
1179     long when;       /* rot away when this old */
1180     long corpse_age; /* age of corpse          */
1181     int rot_adjust;
1182     short action;
1183 
1184 #define TAINT_AGE (50L)        /* age when corpses go bad */
1185 #define TROLL_REVIVE_CHANCE 37 /* 1/37 chance for 50 turns ~ 75% chance */
1186 #define ROT_AGE (250L)         /* age when corpses rot away */
1187 
1188     /* lizards and lichen don't rot or revive */
1189     if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN)
1190         return;
1191 
1192     action = ROT_CORPSE;             /* default action: rot away */
1193     rot_adjust = in_mklev ? 25 : 10; /* give some variation */
1194     corpse_age = monstermoves - body->age;
1195     if (corpse_age > ROT_AGE)
1196         when = rot_adjust;
1197     else
1198         when = ROT_AGE - corpse_age;
1199     when += (long) (rnz(rot_adjust) - rot_adjust);
1200 
1201     if (is_rider(&mons[body->corpsenm])) {
1202         /*
1203          * Riders always revive.  They have a 1/3 chance per turn
1204          * of reviving after 12 turns.  Always revive by 500.
1205          */
1206         action = REVIVE_MON;
1207         for (when = 12L; when < 500L; when++)
1208             if (!rn2(3))
1209                 break;
1210 
1211     } else if (mons[body->corpsenm].mlet == S_TROLL && !body->norevive) {
1212         long age;
1213         for (age = 2; age <= TAINT_AGE; age++)
1214             if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */
1215                 action = REVIVE_MON;
1216                 when = age;
1217                 break;
1218             }
1219     }
1220 
1221     if (body->norevive)
1222         body->norevive = 0;
1223     (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
1224 }
1225 
1226 STATIC_OVL void
maybe_adjust_light(obj,old_range)1227 maybe_adjust_light(obj, old_range)
1228 struct obj *obj;
1229 int old_range;
1230 {
1231     char buf[BUFSZ];
1232     xchar ox, oy;
1233     int new_range = arti_light_radius(obj), delta = new_range - old_range;
1234 
1235     /* radius of light emitting artifact varies by curse/bless state
1236        so will change after blessing or cursing */
1237     if (delta) {
1238         obj_adjust_light_radius(obj, new_range);
1239         /* simplifying assumptions:  hero is wielding this object;
1240            artifacts have to be in use to emit light and monsters'
1241            gear won't change bless or curse state */
1242         if (!Blind && get_obj_location(obj, &ox, &oy, 0)) {
1243             *buf = '\0';
1244             if (iflags.last_msg == PLNMSG_OBJ_GLOWS)
1245                 /* we just saw "The <obj> glows <color>." from dipping */
1246                 Strcpy(buf, (obj->quan == 1L) ? "It" : "They");
1247             else if (carried(obj) || cansee(ox, oy))
1248                 Strcpy(buf, Yname2(obj));
1249             if (*buf) {
1250                 /* initial activation says "dimly" if cursed,
1251                    "brightly" if uncursed, and "brilliantly" if blessed;
1252                    when changing intensity, using "less brightly" is
1253                    straightforward for dimming, but we need "brighter"
1254                    rather than "more brightly" for brightening; ugh */
1255                 pline("%s %s %s%s.", buf, otense(obj, "shine"),
1256                       (abs(delta) > 1) ? "much " : "",
1257                       (delta > 0) ? "brighter" : "less brightly");
1258             }
1259         }
1260     }
1261 }
1262 
1263 /*
1264  *      bless(), curse(), unbless(), uncurse() -- any relevant message
1265  *      about glowing amber/black/&c should be delivered prior to calling
1266  *      these routines to make the actual curse/bless state change.
1267  */
1268 
1269 void
bless(otmp)1270 bless(otmp)
1271 register struct obj *otmp;
1272 {
1273     int old_light = 0;
1274 
1275     if (otmp->oclass == COIN_CLASS)
1276         return;
1277     if (otmp->lamplit)
1278         old_light = arti_light_radius(otmp);
1279     otmp->cursed = 0;
1280     otmp->blessed = 1;
1281     if (carried(otmp) && confers_luck(otmp))
1282         set_moreluck();
1283     else if (otmp->otyp == BAG_OF_HOLDING)
1284         otmp->owt = weight(otmp);
1285     else if (otmp->otyp == FIGURINE && otmp->timed)
1286         (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1287     if (otmp->lamplit)
1288         maybe_adjust_light(otmp, old_light);
1289     return;
1290 }
1291 
1292 void
unbless(otmp)1293 unbless(otmp)
1294 register struct obj *otmp;
1295 {
1296     int old_light = 0;
1297 
1298     if (otmp->lamplit)
1299         old_light = arti_light_radius(otmp);
1300     otmp->blessed = 0;
1301     if (carried(otmp) && confers_luck(otmp))
1302         set_moreluck();
1303     else if (otmp->otyp == BAG_OF_HOLDING)
1304         otmp->owt = weight(otmp);
1305     if (otmp->lamplit)
1306         maybe_adjust_light(otmp, old_light);
1307 }
1308 
1309 void
curse(otmp)1310 curse(otmp)
1311 register struct obj *otmp;
1312 {
1313     unsigned already_cursed;
1314     int old_light = 0;
1315 
1316     if (otmp->oclass == COIN_CLASS)
1317         return;
1318     if (otmp->lamplit)
1319         old_light = arti_light_radius(otmp);
1320     already_cursed = otmp->cursed;
1321     otmp->blessed = 0;
1322     otmp->cursed = 1;
1323     /* welded two-handed weapon interferes with some armor removal */
1324     if (otmp == uwep && bimanual(uwep))
1325         reset_remarm();
1326     /* rules at top of wield.c state that twoweapon cannot be done
1327        with cursed alternate weapon */
1328     if (otmp == uswapwep && u.twoweap)
1329         drop_uswapwep();
1330     /* some cursed items need immediate updating */
1331     if (carried(otmp) && confers_luck(otmp)) {
1332         set_moreluck();
1333     } else if (otmp->otyp == BAG_OF_HOLDING) {
1334         otmp->owt = weight(otmp);
1335     } else if (otmp->otyp == FIGURINE) {
1336         if (otmp->corpsenm != NON_PM && !dead_species(otmp->corpsenm, TRUE)
1337             && (carried(otmp) || mcarried(otmp)))
1338             attach_fig_transform_timeout(otmp);
1339     } else if (otmp->oclass == SPBOOK_CLASS) {
1340         /* if book hero is reading becomes cursed, interrupt */
1341         if (!already_cursed)
1342             book_cursed(otmp);
1343     }
1344     if (otmp->lamplit)
1345         maybe_adjust_light(otmp, old_light);
1346     return;
1347 }
1348 
1349 void
uncurse(otmp)1350 uncurse(otmp)
1351 register struct obj *otmp;
1352 {
1353     int old_light = 0;
1354 
1355     if (otmp->lamplit)
1356         old_light = arti_light_radius(otmp);
1357     otmp->cursed = 0;
1358     if (carried(otmp) && confers_luck(otmp))
1359         set_moreluck();
1360     else if (otmp->otyp == BAG_OF_HOLDING)
1361         otmp->owt = weight(otmp);
1362     else if (otmp->otyp == FIGURINE && otmp->timed)
1363         (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1364     if (otmp->lamplit)
1365         maybe_adjust_light(otmp, old_light);
1366     return;
1367 }
1368 
1369 void
blessorcurse(otmp,chance)1370 blessorcurse(otmp, chance)
1371 register struct obj *otmp;
1372 register int chance;
1373 {
1374     if (otmp->blessed || otmp->cursed)
1375         return;
1376 
1377     if (!rn2(chance)) {
1378         if (!rn2(2)) {
1379             curse(otmp);
1380         } else {
1381             bless(otmp);
1382         }
1383     }
1384     return;
1385 }
1386 
1387 int
bcsign(otmp)1388 bcsign(otmp)
1389 register struct obj *otmp;
1390 {
1391     return (!!otmp->blessed - !!otmp->cursed);
1392 }
1393 
1394 /* set the object's bless/curse-state known flag */
1395 void
set_bknown(obj,onoff)1396 set_bknown(obj, onoff)
1397 struct obj *obj;
1398 unsigned onoff; /* 1 or 0 */
1399 {
1400     if (obj->bknown != onoff) {
1401         obj->bknown = onoff;
1402         if (obj->where == OBJ_INVENT && moves > 1L)
1403             update_inventory();
1404     }
1405 }
1406 
1407 /*
1408  *  Calculate the weight of the given object.  This will recursively follow
1409  *  and calculate the weight of any containers.
1410  *
1411  *  Note:  It is possible to end up with an incorrect weight if some part
1412  *         of the code messes with a contained object and doesn't update the
1413  *         container's weight.
1414  */
1415 int
weight(obj)1416 weight(obj)
1417 register struct obj *obj;
1418 {
1419     int wt = (int) objects[obj->otyp].oc_weight;
1420 
1421     /* glob absorpsion means that merging globs accumulates weight while
1422        quantity stays 1, so update 'wt' to reflect that, unless owt is 0,
1423        when we assume this is a brand new glob so use objects[].oc_weight */
1424     if (obj->globby && obj->owt > 0)
1425         wt = obj->owt;
1426     if (Is_container(obj) || obj->otyp == STATUE) {
1427         struct obj *contents;
1428         register int cwt = 0;
1429 
1430         if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
1431             wt = (int) obj->quan * ((int) mons[obj->corpsenm].cwt * 3 / 2);
1432 
1433         for (contents = obj->cobj; contents; contents = contents->nobj)
1434             cwt += weight(contents);
1435         /*
1436          *  The weight of bags of holding is calculated as the weight
1437          *  of the bag plus the weight of the bag's contents modified
1438          *  as follows:
1439          *
1440          *      Bag status      Weight of contents
1441          *      ----------      ------------------
1442          *      cursed                  2x
1443          *      blessed                 x/4 [rounded up: (x+3)/4]
1444          *      otherwise               x/2 [rounded up: (x+1)/2]
1445          *
1446          *  The macro DELTA_CWT in pickup.c also implements these
1447          *  weight equations.
1448          */
1449         if (obj->otyp == BAG_OF_HOLDING)
1450             cwt = obj->cursed ? (cwt * 2) : obj->blessed ? ((cwt + 3) / 4)
1451                                                          : ((cwt + 1) / 2);
1452 
1453         return wt + cwt;
1454     }
1455     if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
1456         long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
1457 
1458         wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int) long_wt;
1459         if (obj->oeaten)
1460             wt = eaten_stat(wt, obj);
1461         return wt;
1462     } else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
1463         return eaten_stat((int) obj->quan * wt, obj);
1464     } else if (obj->oclass == COIN_CLASS) {
1465         return (int) ((obj->quan + 50L) / 100L);
1466     } else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) {
1467         return (int) obj->owt; /* kludge for "very" heavy iron ball */
1468     } else if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->spe) {
1469         return wt + obj->spe * (int) objects[TALLOW_CANDLE].oc_weight;
1470     }
1471     return (wt ? wt * (int) obj->quan : ((int) obj->quan + 1) >> 1);
1472 }
1473 
1474 static int treefruits[] = { APPLE, ORANGE, PEAR, BANANA, EUCALYPTUS_LEAF };
1475 
1476 /* called when a tree is kicked; never returns Null */
1477 struct obj *
rnd_treefruit_at(x,y)1478 rnd_treefruit_at(x, y)
1479 int x, y;
1480 {
1481     return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
1482 }
1483 
1484 /* create a stack of N gold pieces; never returns Null */
1485 struct obj *
mkgold(amount,x,y)1486 mkgold(amount, x, y)
1487 long amount;
1488 int x, y;
1489 {
1490     struct obj *gold = g_at(x, y);
1491 
1492     if (amount <= 0L) {
1493         long mul = rnd(30 / max(12-depth(&u.uz), 2));
1494 
1495         amount = (long) (1 + rnd(level_difficulty() + 2) * mul);
1496     }
1497     if (gold) {
1498         gold->quan += amount;
1499     } else {
1500         gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
1501         gold->quan = amount;
1502     }
1503     gold->owt = weight(gold);
1504     return gold;
1505 }
1506 
1507 /* return TRUE if the corpse has special timing;
1508    lizards and lichen don't rot, trolls and Riders auto-revive */
1509 #define special_corpse(num) \
1510     (((num) == PM_LIZARD || (num) == PM_LICHEN)                 \
1511      || (mons[num].mlet == S_TROLL || is_rider(&mons[num])))
1512 
1513 /* mkcorpstat: make a corpse or statue; never returns Null.
1514  *
1515  * OEXTRA note: Passing mtmp causes mtraits to be saved
1516  * even if ptr passed as well, but ptr is always used for
1517  * the corpse type (corpsenm). That allows the corpse type
1518  * to be different from the original monster,
1519  *      i.e.  vampire -> human corpse
1520  * yet still allow restoration of the original monster upon
1521  * resurrection.
1522  */
1523 struct obj *
mkcorpstat(objtype,mtmp,ptr,x,y,corpstatflags)1524 mkcorpstat(objtype, mtmp, ptr, x, y, corpstatflags)
1525 int objtype; /* CORPSE or STATUE */
1526 struct monst *mtmp;
1527 struct permonst *ptr;
1528 int x, y;
1529 unsigned corpstatflags;
1530 {
1531     struct obj *otmp;
1532     boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
1533 
1534     if (objtype != CORPSE && objtype != STATUE)
1535         impossible("making corpstat type %d", objtype);
1536     if (x == 0 && y == 0) { /* special case - random placement */
1537         otmp = mksobj(objtype, init, FALSE);
1538         (void) rloco(otmp);
1539     } else {
1540         otmp = mksobj_at(objtype, x, y, init, FALSE);
1541     }
1542 
1543     /* when 'mtmp' is non-null save the monster's details with the
1544        corpse or statue; it will also force the 'ptr' override below */
1545     if (mtmp) {
1546         /* save_mtraits updates otmp->oextra->omonst in place */
1547         (void) save_mtraits(otmp, mtmp);
1548 
1549         if (!ptr)
1550             ptr = mtmp->data;
1551     }
1552 
1553     /* when 'ptr' is non-null it comes from our caller or from 'mtmp';
1554        override mkobjs()'s initialization of a random monster type */
1555     if (ptr) {
1556         int old_corpsenm = otmp->corpsenm;
1557 
1558         otmp->corpsenm = monsndx(ptr);
1559         otmp->owt = weight(otmp);
1560         if (otmp->otyp == CORPSE && (special_corpse(old_corpsenm)
1561                                      || special_corpse(otmp->corpsenm))) {
1562             obj_stop_timers(otmp);
1563             start_corpse_timeout(otmp);
1564         }
1565     }
1566     return otmp;
1567 }
1568 
1569 /*
1570  * Return the type of monster that this corpse will
1571  * revive as, even if it has a monster structure
1572  * attached to it. In that case, you can't just
1573  * use obj->corpsenm, because the stored monster
1574  * type can, and often is, different.
1575  * The return value is an index into mons[].
1576  */
1577 int
corpse_revive_type(obj)1578 corpse_revive_type(obj)
1579 struct obj *obj;
1580 {
1581     int revivetype = obj->corpsenm;
1582     struct monst *mtmp;
1583 
1584     if (has_omonst(obj) && ((mtmp = get_mtraits(obj, FALSE)) != 0)) {
1585         /* mtmp is a temporary pointer to a monster's stored
1586         attributes, not a real monster */
1587         revivetype = mtmp->mnum;
1588     }
1589     return revivetype;
1590 }
1591 
1592 /*
1593  * Attach a monster id to an object, to provide
1594  * a lasting association between the two.
1595  */
1596 struct obj *
obj_attach_mid(obj,mid)1597 obj_attach_mid(obj, mid)
1598 struct obj *obj;
1599 unsigned mid;
1600 {
1601     if (!mid || !obj)
1602         return (struct obj *) 0;
1603     newomid(obj);
1604     *OMID(obj) = mid;
1605     return obj;
1606 }
1607 
1608 static struct obj *
save_mtraits(obj,mtmp)1609 save_mtraits(obj, mtmp)
1610 struct obj *obj;
1611 struct monst *mtmp;
1612 {
1613     if (mtmp->ispriest)
1614         forget_temple_entry(mtmp); /* EPRI() */
1615     if (!has_omonst(obj))
1616         newomonst(obj);
1617     if (has_omonst(obj)) {
1618         struct monst *mtmp2 = OMONST(obj);
1619 
1620         *mtmp2 = *mtmp;
1621         mtmp2->mextra = (struct mextra *) 0;
1622         if (mtmp->data)
1623             mtmp2->mnum = monsndx(mtmp->data);
1624         /* invalidate pointers */
1625         /* m_id is needed to know if this is a revived quest leader */
1626         /* but m_id must be cleared when loading bones */
1627         mtmp2->nmon = (struct monst *) 0;
1628         mtmp2->data = (struct permonst *) 0;
1629         mtmp2->minvent = (struct obj *) 0;
1630         if (mtmp->mextra)
1631             copy_mextra(mtmp2, mtmp);
1632     }
1633     return obj;
1634 }
1635 
1636 /* returns a pointer to a new monst structure based on
1637  * the one contained within the obj.
1638  */
1639 struct monst *
get_mtraits(obj,copyof)1640 get_mtraits(obj, copyof)
1641 struct obj *obj;
1642 boolean copyof;
1643 {
1644     struct monst *mtmp = (struct monst *) 0;
1645     struct monst *mnew = (struct monst *) 0;
1646 
1647     if (has_omonst(obj))
1648         mtmp = OMONST(obj);
1649     if (mtmp) {
1650         if (copyof) {
1651             mnew = newmonst();
1652             *mnew = *mtmp;
1653             mnew->mextra = (struct mextra *) 0;
1654             if (mtmp->mextra)
1655                 copy_mextra(mnew, mtmp);
1656         } else {
1657             /* Never insert this returned pointer into mon chains! */
1658             mnew = mtmp;
1659         }
1660     }
1661     return mnew;
1662 }
1663 
1664 /* make an object named after someone listed in the scoreboard file;
1665    never returns Null */
1666 struct obj *
mk_tt_object(objtype,x,y)1667 mk_tt_object(objtype, x, y)
1668 int objtype; /* CORPSE or STATUE */
1669 int x, y;
1670 {
1671     struct obj *otmp;
1672     boolean initialize_it;
1673 
1674     /* player statues never contain books */
1675     initialize_it = (objtype != STATUE);
1676     otmp = mksobj_at(objtype, x, y, initialize_it, FALSE);
1677     /* tt_oname() will return null if the scoreboard is empty;
1678        assigning an object name used to allocate a new obj but
1679        doesn't any more so we can safely ignore the return value */
1680     (void) tt_oname(otmp);
1681 
1682     return otmp;
1683 }
1684 
1685 /* make a new corpse or statue, uninitialized if a statue (i.e. no books);
1686    never returns Null */
1687 struct obj *
mk_named_object(objtype,ptr,x,y,nm)1688 mk_named_object(objtype, ptr, x, y, nm)
1689 int objtype; /* CORPSE or STATUE */
1690 struct permonst *ptr;
1691 int x, y;
1692 const char *nm;
1693 {
1694     struct obj *otmp;
1695     unsigned corpstatflags = (objtype != STATUE) ? CORPSTAT_INIT
1696                                                  : CORPSTAT_NONE;
1697 
1698     otmp = mkcorpstat(objtype, (struct monst *) 0, ptr, x, y, corpstatflags);
1699     if (nm)
1700         otmp = oname(otmp, nm);
1701     return otmp;
1702 }
1703 
1704 boolean
is_flammable(otmp)1705 is_flammable(otmp)
1706 register struct obj *otmp;
1707 {
1708     int otyp = otmp->otyp;
1709     int omat = objects[otyp].oc_material;
1710 
1711     /* Candles can be burned, but they're not flammable in the sense that
1712      * they can't get fire damage and it makes no sense for them to be
1713      * fireproofed.
1714      */
1715     if (Is_candle(otmp))
1716         return FALSE;
1717 
1718     if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
1719         return FALSE;
1720 
1721     return (boolean) ((omat <= WOOD && omat != LIQUID) || omat == PLASTIC);
1722 }
1723 
1724 boolean
is_rottable(otmp)1725 is_rottable(otmp)
1726 register struct obj *otmp;
1727 {
1728     int otyp = otmp->otyp;
1729 
1730     return (boolean) (objects[otyp].oc_material <= WOOD
1731                       && objects[otyp].oc_material != LIQUID);
1732 }
1733 
1734 /*
1735  * These routines maintain the single-linked lists headed in level.objects[][]
1736  * and threaded through the nexthere fields in the object-instance structure.
1737  */
1738 
1739 /* put the object at the given location */
1740 void
place_object(otmp,x,y)1741 place_object(otmp, x, y)
1742 register struct obj *otmp;
1743 int x, y;
1744 {
1745     register struct obj *otmp2 = level.objects[x][y];
1746 
1747     if (!isok(x, y)) { /* validate location */
1748         void VDECL((*func), (const char *, ...)) PRINTF_F(1, 2);
1749 
1750         func = (x < 0 || y < 0 || x > COLNO - 1 || y > ROWNO - 1) ? panic
1751                : impossible;
1752         (*func)("place_object: \"%s\" [%d] off map <%d,%d>",
1753                 safe_typename(otmp->otyp), otmp->where, x, y);
1754     }
1755     if (otmp->where != OBJ_FREE)
1756         panic("place_object: obj \"%s\" [%d] not free",
1757               safe_typename(otmp->otyp), otmp->where);
1758 
1759     obj_no_longer_held(otmp);
1760     if (otmp->otyp == BOULDER) {
1761         if (!otmp2 || otmp2->otyp != BOULDER)
1762             block_point(x, y); /* vision */
1763     }
1764 
1765     /* non-boulder object goes under boulders so that map will show boulder
1766        here without display code needing to traverse pile chain to find one */
1767     if (otmp2 && otmp2->otyp == BOULDER && otmp->otyp != BOULDER) {
1768         /* 3.6.3: put otmp under last consecutive boulder rather than under
1769            just the first one; multiple boulders at same spot in new games
1770            will be consecutive due to this, ones in old games saved before
1771            this change might not be; can affect the map display if the top
1772            boulder is moved/removed by some means other than pushing */
1773         while (otmp2->nexthere && otmp2->nexthere->otyp == BOULDER)
1774             otmp2 = otmp2->nexthere;
1775         otmp->nexthere = otmp2->nexthere;
1776         otmp2->nexthere = otmp;
1777     } else {
1778         /* put on top of current pile */
1779         otmp->nexthere = otmp2;
1780         level.objects[x][y] = otmp;
1781     }
1782 
1783     /* set the new object's location */
1784     otmp->ox = x;
1785     otmp->oy = y;
1786     otmp->where = OBJ_FLOOR;
1787 
1788     /* add to floor chain */
1789     otmp->nobj = fobj;
1790     fobj = otmp;
1791     if (otmp->timed)
1792         obj_timer_checks(otmp, x, y, 0);
1793 }
1794 
1795 #define ROT_ICE_ADJUSTMENT 2 /* rotting on ice takes 2 times as long */
1796 
1797 /* If ice was affecting any objects correct that now
1798  * Also used for starting ice effects too. [zap.c]
1799  */
1800 void
obj_ice_effects(x,y,do_buried)1801 obj_ice_effects(x, y, do_buried)
1802 int x, y;
1803 boolean do_buried;
1804 {
1805     struct obj *otmp;
1806 
1807     for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) {
1808         if (otmp->timed)
1809             obj_timer_checks(otmp, x, y, 0);
1810     }
1811     if (do_buried) {
1812         for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
1813             if (otmp->ox == x && otmp->oy == y) {
1814                 if (otmp->timed)
1815                     obj_timer_checks(otmp, x, y, 0);
1816             }
1817         }
1818     }
1819 }
1820 
1821 /*
1822  * Returns an obj->age for a corpse object on ice, that would be the
1823  * actual obj->age if the corpse had just been lifted from the ice.
1824  * This is useful when just using obj->age in a check or calculation because
1825  * rot timers pertaining to the object don't have to be stopped and
1826  * restarted etc.
1827  */
1828 long
peek_at_iced_corpse_age(otmp)1829 peek_at_iced_corpse_age(otmp)
1830 struct obj *otmp;
1831 {
1832     long age, retval = otmp->age;
1833 
1834     if (otmp->otyp == CORPSE && otmp->on_ice) {
1835         /* Adjust the age; must be same as obj_timer_checks() for off ice*/
1836         age = monstermoves - otmp->age;
1837         retval += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
1838         debugpline3(
1839           "The %s age has ice modifications: otmp->age = %ld, returning %ld.",
1840                     s_suffix(doname(otmp)), otmp->age, retval);
1841         debugpline1("Effective age of corpse: %ld.", monstermoves - retval);
1842     }
1843     return retval;
1844 }
1845 
1846 STATIC_OVL void
obj_timer_checks(otmp,x,y,force)1847 obj_timer_checks(otmp, x, y, force)
1848 struct obj *otmp;
1849 xchar x, y;
1850 int force; /* 0 = no force so do checks, <0 = force off, >0 force on */
1851 {
1852     long tleft = 0L;
1853     short action = ROT_CORPSE;
1854     boolean restart_timer = FALSE;
1855     boolean on_floor = (otmp->where == OBJ_FLOOR);
1856     boolean buried = (otmp->where == OBJ_BURIED);
1857 
1858     /* Check for corpses just placed on or in ice */
1859     if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x, y)) {
1860         tleft = stop_timer(action, obj_to_any(otmp));
1861         if (tleft == 0L) {
1862             action = REVIVE_MON;
1863             tleft = stop_timer(action, obj_to_any(otmp));
1864         }
1865         if (tleft != 0L) {
1866             long age;
1867 
1868             /* mark the corpse as being on ice */
1869             otmp->on_ice = 1;
1870             debugpline3("%s is now on ice at <%d,%d>.", The(xname(otmp)), x,
1871                         y);
1872             /* Adjust the time remaining */
1873             tleft *= ROT_ICE_ADJUSTMENT;
1874             restart_timer = TRUE;
1875             /* Adjust the age; time spent off ice needs to be multiplied
1876                by the ice adjustment and subtracted from the age so that
1877                later calculations behave as if it had been on ice during
1878                that time (longwinded way of saying this is the inverse
1879                of removing it from the ice and of peeking at its age). */
1880             age = monstermoves - otmp->age;
1881             otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
1882         }
1883 
1884     /* Check for corpses coming off ice */
1885     } else if (force < 0 || (otmp->otyp == CORPSE && otmp->on_ice
1886                              && !((on_floor || buried) && is_ice(x, y)))) {
1887         tleft = stop_timer(action, obj_to_any(otmp));
1888         if (tleft == 0L) {
1889             action = REVIVE_MON;
1890             tleft = stop_timer(action, obj_to_any(otmp));
1891         }
1892         if (tleft != 0L) {
1893             long age;
1894 
1895             otmp->on_ice = 0;
1896             debugpline3("%s is no longer on ice at <%d,%d>.",
1897                         The(xname(otmp)), x, y);
1898             /* Adjust the remaining time */
1899             tleft /= ROT_ICE_ADJUSTMENT;
1900             restart_timer = TRUE;
1901             /* Adjust the age */
1902             age = monstermoves - otmp->age;
1903             otmp->age += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
1904         }
1905     }
1906 
1907     /* now re-start the timer with the appropriate modifications */
1908     if (restart_timer)
1909         (void) start_timer(tleft, TIMER_OBJECT, action, obj_to_any(otmp));
1910 }
1911 
1912 #undef ROT_ICE_ADJUSTMENT
1913 
1914 void
remove_object(otmp)1915 remove_object(otmp)
1916 register struct obj *otmp;
1917 {
1918     xchar x = otmp->ox;
1919     xchar y = otmp->oy;
1920 
1921     if (otmp->where != OBJ_FLOOR)
1922         panic("remove_object: obj not on floor");
1923     extract_nexthere(otmp, &level.objects[x][y]);
1924     extract_nobj(otmp, &fobj);
1925     /* update vision iff this was the only boulder at its spot */
1926     if (otmp->otyp == BOULDER && !sobj_at(BOULDER, x, y))
1927         unblock_point(x, y); /* vision */
1928     if (otmp->timed)
1929         obj_timer_checks(otmp, x, y, 0);
1930 }
1931 
1932 /* throw away all of a monster's inventory */
1933 void
discard_minvent(mtmp)1934 discard_minvent(mtmp)
1935 struct monst *mtmp;
1936 {
1937     struct obj *otmp, *mwep = MON_WEP(mtmp);
1938     boolean keeping_mon = (!DEADMONSTER(mtmp));
1939 
1940     while ((otmp = mtmp->minvent) != 0) {
1941         /* this has now become very similar to m_useupall()... */
1942         obj_extract_self(otmp);
1943         if (otmp->owornmask) {
1944             if (keeping_mon) {
1945                 if (otmp == mwep)
1946                     mwepgone(mtmp), mwep = 0;
1947                 mtmp->misc_worn_check &= ~otmp->owornmask;
1948                 update_mon_intrinsics(mtmp, otmp, FALSE, TRUE);
1949             }
1950             otmp->owornmask = 0L; /* obfree() expects this */
1951         }
1952         obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */
1953     }
1954 }
1955 
1956 /*
1957  * Free obj from whatever list it is on in preparation for deleting it
1958  * or moving it elsewhere; obj->where will end up set to OBJ_FREE.
1959  * Doesn't handle unwearing of objects in hero's or monsters' inventories.
1960  *
1961  * Object positions:
1962  *      OBJ_FREE        not on any list
1963  *      OBJ_FLOOR       fobj, level.locations[][] chains (use remove_object)
1964  *      OBJ_CONTAINED   cobj chain of container object
1965  *      OBJ_INVENT      hero's invent chain (use freeinv)
1966  *      OBJ_MINVENT     monster's invent chain
1967  *      OBJ_MIGRATING   migrating chain
1968  *      OBJ_BURIED      level.buriedobjs chain
1969  *      OBJ_ONBILL      on billobjs chain
1970  */
1971 void
obj_extract_self(obj)1972 obj_extract_self(obj)
1973 struct obj *obj;
1974 {
1975     switch (obj->where) {
1976     case OBJ_FREE:
1977         break;
1978     case OBJ_FLOOR:
1979         remove_object(obj);
1980         break;
1981     case OBJ_CONTAINED:
1982         extract_nobj(obj, &obj->ocontainer->cobj);
1983         container_weight(obj->ocontainer);
1984         obj->ocontainer = (struct obj *) 0; /* clear stale back-link */
1985         break;
1986     case OBJ_INVENT:
1987         freeinv(obj);
1988         break;
1989     case OBJ_MINVENT:
1990         extract_nobj(obj, &obj->ocarry->minvent);
1991         obj->ocarry = (struct monst *) 0; /* clear stale back-link */
1992         break;
1993     case OBJ_MIGRATING:
1994         extract_nobj(obj, &migrating_objs);
1995         break;
1996     case OBJ_BURIED:
1997         extract_nobj(obj, &level.buriedobjlist);
1998         break;
1999     case OBJ_ONBILL:
2000         extract_nobj(obj, &billobjs);
2001         break;
2002     default:
2003         panic("obj_extract_self");
2004         break;
2005     }
2006 }
2007 
2008 /* Extract the given object from the chain, following nobj chain. */
2009 void
extract_nobj(obj,head_ptr)2010 extract_nobj(obj, head_ptr)
2011 struct obj *obj, **head_ptr;
2012 {
2013     struct obj *curr, *prev;
2014 
2015     curr = *head_ptr;
2016     for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) {
2017         if (curr == obj) {
2018             if (prev)
2019                 prev->nobj = curr->nobj;
2020             else
2021                 *head_ptr = curr->nobj;
2022             break;
2023         }
2024     }
2025     if (!curr)
2026         panic("extract_nobj: object lost");
2027     obj->where = OBJ_FREE;
2028     obj->nobj = (struct obj *) 0;
2029 }
2030 
2031 /*
2032  * Extract the given object from the chain, following nexthere chain.
2033  *
2034  * This does not set obj->where, this function is expected to be called
2035  * in tandem with extract_nobj, which does set it.
2036  */
2037 void
extract_nexthere(obj,head_ptr)2038 extract_nexthere(obj, head_ptr)
2039 struct obj *obj, **head_ptr;
2040 {
2041     struct obj *curr, *prev;
2042 
2043     curr = *head_ptr;
2044     for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) {
2045         if (curr == obj) {
2046             if (prev)
2047                 prev->nexthere = curr->nexthere;
2048             else
2049                 *head_ptr = curr->nexthere;
2050             break;
2051         }
2052     }
2053     if (!curr)
2054         panic("extract_nexthere: object lost");
2055     obj->nexthere = (struct obj *) 0;
2056 }
2057 
2058 /*
2059  * Add obj to mon's inventory.  If obj is able to merge with something already
2060  * in the inventory, then the passed obj is deleted and 1 is returned.
2061  * Otherwise 0 is returned.
2062  */
2063 int
add_to_minv(mon,obj)2064 add_to_minv(mon, obj)
2065 struct monst *mon;
2066 struct obj *obj;
2067 {
2068     struct obj *otmp;
2069 
2070     if (obj->where != OBJ_FREE)
2071         panic("add_to_minv: obj not free");
2072 
2073     /* merge if possible */
2074     for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
2075         if (merged(&otmp, &obj))
2076             return 1; /* obj merged and then free'd */
2077     /* else insert; don't bother forcing it to end of chain */
2078     obj->where = OBJ_MINVENT;
2079     obj->ocarry = mon;
2080     obj->nobj = mon->minvent;
2081     mon->minvent = obj;
2082     return 0; /* obj on mon's inventory chain */
2083 }
2084 
2085 /*
2086  * Add obj to container, make sure obj is "free".  Returns (merged) obj.
2087  * The input obj may be deleted in the process.
2088  */
2089 struct obj *
add_to_container(container,obj)2090 add_to_container(container, obj)
2091 struct obj *container, *obj;
2092 {
2093     struct obj *otmp;
2094 
2095     if (obj->where != OBJ_FREE)
2096         panic("add_to_container: obj not free");
2097     if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT)
2098         obj_no_longer_held(obj);
2099 
2100     /* merge if possible */
2101     for (otmp = container->cobj; otmp; otmp = otmp->nobj)
2102         if (merged(&otmp, &obj))
2103             return otmp;
2104 
2105     obj->where = OBJ_CONTAINED;
2106     obj->ocontainer = container;
2107     obj->nobj = container->cobj;
2108     container->cobj = obj;
2109     return obj;
2110 }
2111 
2112 void
add_to_migration(obj)2113 add_to_migration(obj)
2114 struct obj *obj;
2115 {
2116     if (obj->where != OBJ_FREE)
2117         panic("add_to_migration: obj not free");
2118 
2119     /* lock picking context becomes stale if it's for this object */
2120     if (Is_container(obj))
2121         maybe_reset_pick(obj);
2122 
2123     obj->where = OBJ_MIGRATING;
2124     obj->nobj = migrating_objs;
2125     migrating_objs = obj;
2126 }
2127 
2128 void
add_to_buried(obj)2129 add_to_buried(obj)
2130 struct obj *obj;
2131 {
2132     if (obj->where != OBJ_FREE)
2133         panic("add_to_buried: obj not free");
2134 
2135     obj->where = OBJ_BURIED;
2136     obj->nobj = level.buriedobjlist;
2137     level.buriedobjlist = obj;
2138 }
2139 
2140 /* Recalculate the weight of this container and all of _its_ containers. */
2141 STATIC_OVL void
container_weight(container)2142 container_weight(container)
2143 struct obj *container;
2144 {
2145     container->owt = weight(container);
2146     if (container->where == OBJ_CONTAINED)
2147         container_weight(container->ocontainer);
2148     /*
2149         else if (container->where == OBJ_INVENT)
2150         recalculate load delay here ???
2151     */
2152 }
2153 
2154 /*
2155  * Deallocate the object.  _All_ objects should be run through here for
2156  * them to be deallocated.
2157  */
2158 void
dealloc_obj(obj)2159 dealloc_obj(obj)
2160 struct obj *obj;
2161 {
2162     if (obj->where != OBJ_FREE)
2163         panic("dealloc_obj: obj not free");
2164     if (obj->nobj)
2165         panic("dealloc_obj with nobj");
2166     if (obj->cobj)
2167         panic("dealloc_obj with cobj");
2168 
2169     /* free up any timers attached to the object */
2170     if (obj->timed)
2171         obj_stop_timers(obj);
2172 
2173     /*
2174      * Free up any light sources attached to the object.
2175      *
2176      * We may want to just call del_light_source() without any
2177      * checks (requires a code change there).  Otherwise this
2178      * list must track all objects that can have a light source
2179      * attached to it (and also requires lamplit to be set).
2180      */
2181     if (obj_sheds_light(obj))
2182         del_light_source(LS_OBJECT, obj_to_any(obj));
2183 
2184     if (obj == thrownobj)
2185         thrownobj = 0;
2186     if (obj == kickedobj)
2187         kickedobj = 0;
2188 
2189     if (obj->oextra)
2190         dealloc_oextra(obj);
2191     free((genericptr_t) obj);
2192 }
2193 
2194 /* create an object from a horn of plenty; mirrors bagotricks(makemon.c) */
2195 int
hornoplenty(horn,tipping)2196 hornoplenty(horn, tipping)
2197 struct obj *horn;
2198 boolean tipping; /* caller emptying entire contents; affects shop handling */
2199 {
2200     int objcount = 0;
2201 
2202     if (!horn || horn->otyp != HORN_OF_PLENTY) {
2203         impossible("bad horn o' plenty");
2204     } else if (horn->spe < 1) {
2205         pline1(nothing_happens);
2206     } else {
2207         struct obj *obj;
2208         const char *what;
2209 
2210         consume_obj_charge(horn, !tipping);
2211         if (!rn2(13)) {
2212             obj = mkobj(POTION_CLASS, FALSE);
2213             if (objects[obj->otyp].oc_magic)
2214                 do {
2215                     obj->otyp = rnd_class(POT_BOOZE, POT_WATER);
2216                 } while (obj->otyp == POT_SICKNESS);
2217             what = (obj->quan > 1L) ? "Some potions" : "A potion";
2218         } else {
2219             obj = mkobj(FOOD_CLASS, FALSE);
2220             if (obj->otyp == FOOD_RATION && !rn2(7))
2221                 obj->otyp = LUMP_OF_ROYAL_JELLY;
2222             what = "Some food";
2223         }
2224         ++objcount;
2225         pline("%s %s out.", what, vtense(what, "spill"));
2226         obj->blessed = horn->blessed;
2227         obj->cursed = horn->cursed;
2228         obj->owt = weight(obj);
2229         /* using a shop's horn of plenty entails a usage fee and also
2230            confers ownership of the created item to the shopkeeper */
2231         if (horn->unpaid)
2232             addtobill(obj, FALSE, FALSE, tipping);
2233         /* if it ended up on bill, we don't want "(unpaid, N zorkids)"
2234            being included in its formatted name during next message */
2235         iflags.suppress_price++;
2236         if (!tipping) {
2237             obj = hold_another_object(obj,
2238                                       u.uswallow
2239                                         ? "Oops!  %s out of your reach!"
2240                                         : (Is_airlevel(&u.uz)
2241                                            || Is_waterlevel(&u.uz)
2242                                            || levl[u.ux][u.uy].typ < IRONBARS
2243                                            || levl[u.ux][u.uy].typ >= ICE)
2244                                           ? "Oops!  %s away from you!"
2245                                           : "Oops!  %s to the floor!",
2246                                       The(aobjnam(obj, "slip")), (char *) 0);
2247             nhUse(obj);
2248         } else {
2249             /* assumes this is taking place at hero's location */
2250             if (!can_reach_floor(TRUE)) {
2251                 hitfloor(obj, TRUE); /* does altar check, message, drop */
2252             } else {
2253                 if (IS_ALTAR(levl[u.ux][u.uy].typ))
2254                     doaltarobj(obj); /* does its own drop message */
2255                 else
2256                     pline("%s %s to the %s.", Doname2(obj),
2257                           otense(obj, "drop"), surface(u.ux, u.uy));
2258                 dropy(obj);
2259             }
2260         }
2261         iflags.suppress_price--;
2262         if (horn->dknown)
2263             makeknown(HORN_OF_PLENTY);
2264     }
2265     return objcount;
2266 }
2267 
2268 /* support for wizard-mode's `sanity_check' option */
2269 
2270 static const char NEARDATA /* pline formats for insane_object() */
2271     ofmt0[] = "%s obj %s %s: %s",
2272     ofmt3[] = "%s [not null] %s %s: %s",
2273     /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
2274     mfmt1[] = "%s obj %s %s (%s)",
2275     mfmt2[] = "%s obj %s %s (%s) *not*";
2276 
2277 /* Check all object lists for consistency. */
2278 void
obj_sanity_check()2279 obj_sanity_check()
2280 {
2281     int x, y;
2282     struct obj *obj;
2283 
2284     /*
2285      * TODO:
2286      *  Should check whether the obj->bypass and/or obj->nomerge bits
2287      *  are set.  Those are both used for temporary purposes and should
2288      *  be clear between moves.
2289      */
2290 
2291     objlist_sanity(fobj, OBJ_FLOOR, "floor sanity");
2292 
2293     /* check that the map's record of floor objects is consistent;
2294        those objects should have already been sanity checked via
2295        the floor list so container contents are skipped here */
2296     for (x = 0; x < COLNO; x++)
2297         for (y = 0; y < ROWNO; y++)
2298             for (obj = level.objects[x][y]; obj; obj = obj->nexthere) {
2299                 /* <ox,oy> should match <x,y>; <0,*> should always be empty */
2300                 if (obj->where != OBJ_FLOOR || x == 0
2301                     || obj->ox != x || obj->oy != y) {
2302                     char at_fmt[BUFSZ];
2303 
2304                     Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
2305                             x, y, obj->ox, obj->oy);
2306                     insane_object(obj, at_fmt, "location sanity",
2307                                   (struct monst *) 0);
2308                 }
2309             }
2310 
2311     objlist_sanity(invent, OBJ_INVENT, "invent sanity");
2312     objlist_sanity(migrating_objs, OBJ_MIGRATING, "migrating sanity");
2313     objlist_sanity(level.buriedobjlist, OBJ_BURIED, "buried sanity");
2314     objlist_sanity(billobjs, OBJ_ONBILL, "bill sanity");
2315 
2316     mon_obj_sanity(fmon, "minvent sanity");
2317     mon_obj_sanity(migrating_mons, "migrating minvent sanity");
2318     /* monsters temporarily in transit;
2319        they should have arrived with hero by the time we get called */
2320     if (mydogs) {
2321         impossible("mydogs sanity [not empty]");
2322         mon_obj_sanity(mydogs, "mydogs minvent sanity");
2323     }
2324 
2325     /* objects temporarily freed from invent/floor lists;
2326        they should have arrived somewhere by the time we get called */
2327     if (thrownobj)
2328         insane_object(thrownobj, ofmt3, "thrownobj sanity",
2329                       (struct monst *) 0);
2330     if (kickedobj)
2331         insane_object(kickedobj, ofmt3, "kickedobj sanity",
2332                       (struct monst *) 0);
2333     /* current_wand isn't removed from invent while in use, but should
2334        be Null between moves when we're called */
2335     if (current_wand)
2336         insane_object(current_wand, ofmt3, "current_wand sanity",
2337                       (struct monst *) 0);
2338 }
2339 
2340 /* sanity check for objects on specified list (fobj, &c) */
2341 STATIC_OVL void
objlist_sanity(objlist,wheretype,mesg)2342 objlist_sanity(objlist, wheretype, mesg)
2343 struct obj *objlist;
2344 int wheretype;
2345 const char *mesg;
2346 {
2347     struct obj *obj;
2348 
2349     for (obj = objlist; obj; obj = obj->nobj) {
2350         if (obj->where != wheretype)
2351             insane_object(obj, ofmt0, mesg, (struct monst *) 0);
2352         if (Has_contents(obj)) {
2353             if (wheretype == OBJ_ONBILL)
2354                 /* containers on shop bill should always be empty */
2355                 insane_object(obj, "%s obj contains something! %s %s: %s",
2356                               mesg, (struct monst *) 0);
2357             check_contained(obj, mesg);
2358         }
2359         if (obj->owornmask) {
2360             char maskbuf[40];
2361             boolean bc_ok = FALSE;
2362 
2363             switch (obj->where) {
2364             case OBJ_INVENT:
2365             case OBJ_MINVENT:
2366                 sanity_check_worn(obj);
2367                 break;
2368             case OBJ_MIGRATING:
2369                 /* migrating objects overload the owornmask field
2370                    with a destination code; skip attempt to check it */
2371                 break;
2372             case OBJ_FLOOR:
2373                 /* note: ball and chain can also be OBJ_FREE, but not across
2374                    turns so this sanity check shouldn't encounter that */
2375                 bc_ok = TRUE;
2376             /*FALLTHRU*/
2377             default:
2378                 if ((obj != uchain && obj != uball) || !bc_ok) {
2379                     /* discovered an object not in inventory which
2380                        erroneously has worn mask set */
2381                     Sprintf(maskbuf, "worn mask 0x%08lx", obj->owornmask);
2382                     insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2383                 }
2384                 break;
2385             }
2386             if (obj->globby)
2387                 check_glob(obj, mesg);
2388         }
2389     }
2390 }
2391 
2392 /* sanity check for objects carried by all monsters in specified list */
2393 STATIC_OVL void
mon_obj_sanity(monlist,mesg)2394 mon_obj_sanity(monlist, mesg)
2395 struct monst *monlist;
2396 const char *mesg;
2397 {
2398     struct monst *mon;
2399     struct obj *obj, *mwep;
2400 
2401     for (mon = monlist; mon; mon = mon->nmon) {
2402         if (DEADMONSTER(mon))
2403             continue;
2404         mwep = MON_WEP(mon);
2405         if (mwep) {
2406             if (!mcarried(mwep))
2407                 insane_object(mwep, mfmt1, mesg, mon);
2408             if (mwep->ocarry != mon)
2409                 insane_object(mwep, mfmt2, mesg, mon);
2410         }
2411         for (obj = mon->minvent; obj; obj = obj->nobj) {
2412             if (obj->where != OBJ_MINVENT)
2413                 insane_object(obj, mfmt1, mesg, mon);
2414             if (obj->ocarry != mon)
2415                 insane_object(obj, mfmt2, mesg, mon);
2416             if (obj->globby)
2417                 check_glob(obj, mesg);
2418             check_contained(obj, mesg);
2419         }
2420     }
2421 }
2422 
2423 /* This must stay consistent with the defines in obj.h. */
2424 static const char *obj_state_names[NOBJ_STATES] = { "free",      "floor",
2425                                                     "contained", "invent",
2426                                                     "minvent",   "migrating",
2427                                                     "buried",    "onbill" };
2428 
2429 STATIC_OVL const char *
where_name(obj)2430 where_name(obj)
2431 struct obj *obj;
2432 {
2433     static char unknown[32]; /* big enough to handle rogue 64-bit int */
2434     int where;
2435 
2436     if (!obj)
2437         return "nowhere";
2438     where = obj->where;
2439     if (where < 0 || where >= NOBJ_STATES || !obj_state_names[where]) {
2440         Sprintf(unknown, "unknown[%d]", where);
2441         return unknown;
2442     }
2443     return obj_state_names[where];
2444 }
2445 
2446 STATIC_OVL void
insane_object(obj,fmt,mesg,mon)2447 insane_object(obj, fmt, mesg, mon)
2448 struct obj *obj;
2449 const char *fmt, *mesg;
2450 struct monst *mon;
2451 {
2452     const char *objnm, *monnm;
2453     char altfmt[BUFSZ];
2454 
2455     objnm = monnm = "null!";
2456     if (obj) {
2457         iflags.override_ID++;
2458         objnm = doname(obj);
2459         iflags.override_ID--;
2460     }
2461     if (mon || (strstri(mesg, "minvent") && !strstri(mesg, "contained"))) {
2462         Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)");
2463         if (mon)
2464             monnm = x_monnam(mon, ARTICLE_A, (char *) 0, EXACT_NAME, TRUE);
2465         impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2466               objnm, fmt_ptr((genericptr_t) mon), monnm);
2467     } else {
2468         impossible(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2469                    objnm);
2470     }
2471 }
2472 
2473 /*
2474  * Initialize a dummy obj with just enough info
2475  * to allow some of the tests in obj.h that
2476  * take an obj pointer to work.
2477  */
2478 struct obj *
init_dummyobj(obj,otyp,oquan)2479 init_dummyobj(obj, otyp, oquan)
2480 struct obj *obj;
2481 short otyp;
2482 long oquan;
2483 {
2484      if (obj) {
2485          *obj = zeroobj;
2486          obj->otyp = otyp;
2487          obj->oclass = objects[otyp].oc_class;
2488          /* obj->dknown = 0; */
2489          /* suppress known except for amulets (needed for fakes & real AoY) */
2490          obj->known = (obj->oclass == AMULET_CLASS)
2491                        ? obj->known
2492                          /* default is "on" for types which don't use it */
2493                          : !objects[otyp].oc_uses_known;
2494          obj->quan = oquan ? oquan : 1L;
2495          obj->corpsenm = NON_PM; /* suppress statue and figurine details */
2496          /* but suppressing fruit details leads to "bad fruit #0" */
2497          if (obj->otyp == SLIME_MOLD)
2498              obj->spe = context.current_fruit;
2499      }
2500      return obj;
2501 }
2502 
2503 /* obj sanity check: check objects inside container */
2504 STATIC_OVL void
check_contained(container,mesg)2505 check_contained(container, mesg)
2506 struct obj *container;
2507 const char *mesg;
2508 {
2509     struct obj *obj;
2510     /* big enough to work with, not too big to blow out stack in recursion */
2511     char mesgbuf[40], nestedmesg[120];
2512 
2513     if (!Has_contents(container))
2514         return;
2515     /* change "invent sanity" to "contained invent sanity"
2516        but leave "nested contained invent sanity" as is */
2517     if (!strstri(mesg, "contained"))
2518         mesg = strcat(strcpy(mesgbuf, "contained "), mesg);
2519 
2520     for (obj = container->cobj; obj; obj = obj->nobj) {
2521         /* catch direct cycle to avoid unbounded recursion */
2522         if (obj == container)
2523             panic("failed sanity check: container holds itself");
2524         if (obj->where != OBJ_CONTAINED)
2525             insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *) 0);
2526         else if (obj->ocontainer != container)
2527             impossible("%s obj %s in container %s, not %s", mesg,
2528                   fmt_ptr((genericptr_t) obj),
2529                   fmt_ptr((genericptr_t) obj->ocontainer),
2530                   fmt_ptr((genericptr_t) container));
2531         if (obj->globby)
2532             check_glob(obj, mesg);
2533 
2534         if (Has_contents(obj)) {
2535             /* catch most likely indirect cycle; we won't notice if
2536                parent is present when something comes before it, or
2537                notice more deeply embedded cycles (grandparent, &c) */
2538             if (obj->cobj == container)
2539                 panic("failed sanity check: container holds its parent");
2540             /* change "contained... sanity" to "nested contained... sanity"
2541                and "nested contained..." to "nested nested contained..." */
2542             Strcpy(nestedmesg, "nested ");
2543             copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg
2544                                               - (int) strlen(nestedmesg) - 1);
2545             /* recursively check contents */
2546             check_contained(obj, nestedmesg);
2547         }
2548     }
2549 }
2550 
2551 /* called when 'obj->globby' is set so we don't recheck it here */
2552 STATIC_OVL void
check_glob(obj,mesg)2553 check_glob(obj, mesg)
2554 struct obj *obj;
2555 const char *mesg;
2556 {
2557 #define LOWEST_GLOB GLOB_OF_GRAY_OOZE
2558 #define HIGHEST_GLOB GLOB_OF_BLACK_PUDDING
2559     if (obj->quan != 1L || obj->owt == 0
2560         || obj->otyp < LOWEST_GLOB || obj->otyp > HIGHEST_GLOB
2561         /* a partially eaten glob could have any non-zero weight but an
2562            intact one should weigh an exact multiple of base weight (20) */
2563         || ((obj->owt % objects[obj->otyp].oc_weight) != 0 && !obj->oeaten)) {
2564         char mesgbuf[BUFSZ], globbuf[QBUFSZ];
2565 
2566         Sprintf(globbuf, " glob %d,quan=%ld,owt=%u ",
2567                 obj->otyp, obj->quan, obj->owt);
2568         mesg = strsubst(strcpy(mesgbuf, mesg), " obj ", globbuf);
2569         insane_object(obj, ofmt0, mesg,
2570                       (obj->where == OBJ_MINVENT) ? obj->ocarry : 0);
2571     }
2572 }
2573 
2574 /* check an object in hero's or monster's inventory which has worn mask set */
2575 STATIC_OVL void
sanity_check_worn(obj)2576 sanity_check_worn(obj)
2577 struct obj *obj;
2578 {
2579 #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG)
2580     static unsigned long wearbits[] = {
2581         W_ARM,    W_ARMC,   W_ARMH,    W_ARMS, W_ARMG,  W_ARMF,  W_ARMU,
2582         W_WEP,    W_QUIVER, W_SWAPWEP, W_AMUL, W_RINGL, W_RINGR, W_TOOL,
2583         W_SADDLE, W_BALL,   W_CHAIN,   0
2584         /* [W_ART,W_ARTI are property bits for items which aren't worn] */
2585     };
2586     char maskbuf[60];
2587     const char *what;
2588     unsigned long owornmask, allmask = 0L;
2589     boolean embedded = FALSE;
2590     int i, n = 0;
2591 
2592     /* use owornmask for testing and bit twiddling, but use original
2593        obj->owornmask for printing */
2594     owornmask = obj->owornmask;
2595     /* figure out how many bits are set, and also which are viable */
2596     for (i = 0; wearbits[i]; ++i) {
2597         if ((owornmask & wearbits[i]) != 0L)
2598             ++n;
2599         allmask |= wearbits[i];
2600     }
2601     if (obj == uskin) {
2602         /* embedded dragon scales have an extra bit set;
2603            make sure it's set, then suppress it */
2604         embedded = TRUE;
2605         if ((owornmask & (W_ARM | I_SPECIAL)) == (W_ARM | I_SPECIAL))
2606             owornmask &= ~I_SPECIAL;
2607         else
2608             n = 0,  owornmask = ~0; /* force insane_object("bogus") below */
2609     }
2610     if (n == 2 && carried(obj)
2611         && obj == uball && (owornmask & W_BALL) != 0L
2612         && (owornmask & W_WEAPONS) != 0L) {
2613         /* chained ball can be wielded/alt-wielded/quivered; if so,
2614           pretend it's not chained in order to check the weapon pointer
2615           (we've already verified the ball pointer by successfully passing
2616           the if-condition to get here...) */
2617         owornmask &= ~W_BALL;
2618         n = 1;
2619     }
2620     if (n > 1) {
2621         /* multiple bits set */
2622         Sprintf(maskbuf, "worn mask (multiple) 0x%08lx", obj->owornmask);
2623         insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2624     }
2625     if ((owornmask & ~allmask) != 0L
2626         || (carried(obj) && (owornmask & W_SADDLE) != 0L)) {
2627         /* non-wearable bit(s) set */
2628         Sprintf(maskbuf, "worn mask (bogus)) 0x%08lx", obj->owornmask);
2629         insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2630     }
2631     if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L)) {
2632         what = 0;
2633         /* verify that obj in hero's invent (or ball/chain elsewhere)
2634            with owornmask of W_foo is the object pointed to by ufoo */
2635         switch (owornmask) {
2636         case W_ARM:
2637             if (obj != (embedded ? uskin : uarm))
2638                 what = embedded ? "skin" : "suit";
2639             break;
2640         case W_ARMC:
2641             if (obj != uarmc)
2642                 what = "cloak";
2643             break;
2644         case W_ARMH:
2645             if (obj != uarmh)
2646                 what = "helm";
2647             break;
2648         case W_ARMS:
2649             if (obj != uarms)
2650                 what = "shield";
2651             break;
2652         case W_ARMG:
2653             if (obj != uarmg)
2654                 what = "gloves";
2655             break;
2656         case W_ARMF:
2657             if (obj != uarmf)
2658                 what = "boots";
2659             break;
2660         case W_ARMU:
2661             if (obj != uarmu)
2662                 what = "shirt";
2663             break;
2664         case W_WEP:
2665             if (obj != uwep)
2666                 what = "primary weapon";
2667             break;
2668         case W_QUIVER:
2669             if (obj != uquiver)
2670                 what = "quiver";
2671             break;
2672         case W_SWAPWEP:
2673             if (obj != uswapwep)
2674                 what = u.twoweap ? "secondary weapon" : "alternate weapon";
2675             break;
2676         case W_AMUL:
2677             if (obj != uamul)
2678                 what = "amulet";
2679             break;
2680         case W_RINGL:
2681             if (obj != uleft)
2682                 what = "left ring";
2683             break;
2684         case W_RINGR:
2685             if (obj != uright)
2686                 what = "right ring";
2687             break;
2688         case W_TOOL:
2689             if (obj != ublindf)
2690                 what = "blindfold";
2691             break;
2692         /* case W_SADDLE: */
2693         case W_BALL:
2694             if (obj != uball)
2695                 what = "ball";
2696             break;
2697         case W_CHAIN:
2698             if (obj != uchain)
2699                 what = "chain";
2700             break;
2701         default:
2702             break;
2703         }
2704         if (what) {
2705             Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what);
2706             insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2707         }
2708     }
2709     if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L
2710                    || mcarried(obj))) {
2711         /* check for items worn in invalid slots; practically anything can
2712            be wielded/alt-wielded/quivered, so tests on those are limited */
2713         what = 0;
2714         if (owornmask & W_ARMOR) {
2715             if (obj->oclass != ARMOR_CLASS)
2716                 what = "armor";
2717             /* 3.6: dragon scale mail reverts to dragon scales when
2718                becoming embedded in poly'd hero's skin */
2719             if (embedded && !Is_dragon_scales(obj))
2720                 what = "skin";
2721         } else if (owornmask & W_WEAPONS) {
2722             /* monsters don't maintain alternate weapon or quiver */
2723             if (mcarried(obj) && (owornmask & (W_SWAPWEP | W_QUIVER)) != 0L)
2724                 what = (owornmask & W_SWAPWEP) != 0L ? "monst alt weapon?"
2725                                                      : "monst quiver?";
2726             /* hero can quiver gold but not wield it (hence not alt-wield
2727                it either); also catches monster wielding gold */
2728             else if (obj->oclass == COIN_CLASS
2729                      && (owornmask & (W_WEP | W_SWAPWEP)) != 0L)
2730                 what = (owornmask & W_WEP) != 0L ? "weapon" : "alt weapon";
2731         } else if (owornmask & W_AMUL) {
2732             if (obj->oclass != AMULET_CLASS)
2733                 what = "amulet";
2734         } else if (owornmask & W_RING) {
2735             if (obj->oclass != RING_CLASS && obj->otyp != MEAT_RING)
2736                 what = "ring";
2737         } else if (owornmask & W_TOOL) {
2738             if (obj->otyp != BLINDFOLD && obj->otyp != TOWEL
2739                 && obj->otyp != LENSES)
2740                 what = "blindfold";
2741         } else if (owornmask & W_BALL) {
2742             if (obj->oclass != BALL_CLASS)
2743                 what = "chained ball";
2744         } else if (owornmask & W_CHAIN) {
2745             if (obj->oclass != CHAIN_CLASS)
2746                 what = "chain";
2747         } else if (owornmask & W_SADDLE) {
2748             if (obj->otyp != SADDLE)
2749                 what = "saddle";
2750         }
2751         if (what) {
2752             char oclassname[30];
2753             struct monst *mon = mcarried(obj) ? obj->ocarry : 0;
2754 
2755             /* if we've found a potion worn in the amulet slot,
2756                this yields "worn (potion amulet)" */
2757             Strcpy(oclassname, def_oc_syms[(uchar) obj->oclass].name);
2758             Sprintf(maskbuf, "worn (%s %s)", makesingular(oclassname), what);
2759             insane_object(obj, ofmt0, maskbuf, mon);
2760         }
2761     }
2762 #else /* not (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || DEBUG) */
2763     /* dummy use of obj to avoid "arg not used" complaint */
2764     if (!obj)
2765         insane_object(obj, ofmt0, "<null>", (struct monst *) 0);
2766 #endif
2767 }
2768 
2769 /*
2770  * wrapper to make "near this object" convenient
2771  */
2772 struct obj *
obj_nexto(otmp)2773 obj_nexto(otmp)
2774 struct obj *otmp;
2775 {
2776     if (!otmp) {
2777         impossible("obj_nexto: wasn't given an object to check");
2778         return (struct obj *) 0;
2779     }
2780     return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
2781 }
2782 
2783 /*
2784  * looks for objects of a particular type next to x, y
2785  * skips over oid if found (lets us avoid ourselves if
2786  * we're looking for a second type of an existing object)
2787  *
2788  * TODO: return a list of all objects near us so we can more
2789  * reliably predict which one we want to 'find' first
2790  */
2791 struct obj *
obj_nexto_xy(obj,x,y,recurs)2792 obj_nexto_xy(obj, x, y, recurs)
2793 struct obj *obj;
2794 int x, y;
2795 boolean recurs;
2796 {
2797     struct obj *otmp;
2798     int fx, fy, ex, ey, otyp = obj->otyp;
2799     short dx, dy;
2800 
2801     /* check under our "feet" first */
2802     otmp = sobj_at(otyp, x, y);
2803     while (otmp) {
2804         /* don't be clever and find ourselves */
2805         if (otmp != obj && mergable(otmp, obj))
2806             return otmp;
2807         otmp = nxtobj(otmp, otyp, TRUE);
2808     }
2809 
2810     if (!recurs)
2811         return (struct obj *) 0;
2812 
2813     /* search in a random order */
2814     dx = (rn2(2) ? -1 : 1);
2815     dy = (rn2(2) ? -1 : 1);
2816     ex = x - dx;
2817     ey = y - dy;
2818 
2819     for (fx = ex; abs(fx - ex) < 3; fx += dx) {
2820         for (fy = ey; abs(fy - ey) < 3; fy += dy) {
2821             /* 0, 0 was checked above */
2822             if (isok(fx, fy) && (fx != x || fy != y)) {
2823                 if ((otmp = obj_nexto_xy(obj, fx, fy, FALSE)) != 0)
2824                     return otmp;
2825             }
2826         }
2827     }
2828     return (struct obj *) 0;
2829 }
2830 
2831 /*
2832  * Causes one object to absorb another, increasing
2833  * weight accordingly. Frees obj2; obj1 remains and
2834  * is returned.
2835  */
2836 struct obj *
obj_absorb(obj1,obj2)2837 obj_absorb(obj1, obj2)
2838 struct obj **obj1, **obj2;
2839 {
2840     struct obj *otmp1, *otmp2;
2841     int o1wt, o2wt;
2842     long agetmp;
2843 
2844     /* don't let people dumb it up */
2845     if (obj1 && obj2) {
2846         otmp1 = *obj1;
2847         otmp2 = *obj2;
2848         if (otmp1 && otmp2 && otmp1 != otmp2) {
2849             globby_bill_fixup(otmp1, otmp2);
2850             if (otmp1->bknown != otmp2->bknown)
2851                 otmp1->bknown = otmp2->bknown = 0;
2852             if (otmp1->rknown != otmp2->rknown)
2853                 otmp1->rknown = otmp2->rknown = 0;
2854             if (otmp1->greased != otmp2->greased)
2855                 otmp1->greased = otmp2->greased = 0;
2856             if (otmp1->orotten || otmp2->orotten)
2857                 otmp1->orotten = otmp2->orotten = 1;
2858             o1wt = otmp1->oeaten ? otmp1->oeaten : otmp1->owt;
2859             o2wt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
2860             /* averaging the relative ages is less likely to overflow
2861                than averaging the absolute ages directly */
2862             agetmp = (((moves - otmp1->age) * o1wt
2863                        + (moves - otmp2->age) * o2wt)
2864                       / (o1wt + o2wt));
2865             otmp1->age = moves - agetmp; /* conv. relative back to absolute */
2866             otmp1->owt += o2wt;
2867             if (otmp1->oeaten || otmp2->oeaten)
2868                 otmp1->oeaten = o1wt + o2wt;
2869             otmp1->quan = 1L;
2870             obj_extract_self(otmp2);
2871             dealloc_obj(otmp2);
2872             *obj2 = (struct obj *) 0;
2873             return otmp1;
2874         }
2875     }
2876 
2877     impossible("obj_absorb: not called with two actual objects");
2878     return (struct obj *) 0;
2879 }
2880 
2881 /*
2882  * Causes the heavier object to absorb the lighter object in
2883  * most cases, but if one object is OBJ_FREE and the other is
2884  * on the floor, the floor object goes first.
2885  *
2886  * wrapper for obj_absorb so that floor_effects works more
2887  * cleanly (since we don't know which we want to stay around)
2888  */
2889 struct obj *
obj_meld(obj1,obj2)2890 obj_meld(obj1, obj2)
2891 struct obj **obj1, **obj2;
2892 {
2893     struct obj *otmp1, *otmp2, *result = 0;
2894     int ox, oy;
2895 
2896     if (obj1 && obj2) {
2897         otmp1 = *obj1;
2898         otmp2 = *obj2;
2899         if (otmp1 && otmp2 && otmp1 != otmp2) {
2900             ox = oy = 0;
2901             /*
2902              * FIXME?
2903              *  If one of the objects is free because it's being dropped,
2904              *  we should really finish a full drop and then absorb/meld
2905              *  if it survives the flooreffects().  Then lighter-melds-into-
2906              *  heavier will be true even when heavier is the one dropped.
2907              *
2908              *  [Also, what about when one of the globs is on the shore
2909              *  and we drop the other into adjacent pool or vice versa?]
2910              */
2911             if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE)
2912                 && (otmp1->owt > otmp2->owt
2913                     || (otmp1->owt == otmp2->owt && rn2(2)))) {
2914                 if (otmp2->where == OBJ_FLOOR)
2915                     ox = otmp2->ox, oy = otmp2->oy;
2916                 result = obj_absorb(obj1, obj2);
2917             } else {
2918                 if (otmp1->where == OBJ_FLOOR)
2919                     ox = otmp1->ox, oy = otmp1->oy;
2920                 result = obj_absorb(obj2, obj1);
2921             }
2922             /* callers really ought to take care of this; glob melding is
2923                a bookkeeping issue rather than a display one */
2924             if (ox && cansee(ox, oy))
2925                 newsym(ox, oy);
2926         }
2927     } else {
2928         impossible("obj_meld: not called with two actual objects");
2929     }
2930     return result;
2931 }
2932 
2933 /* give a message if hero notices two globs merging [used to be in pline.c] */
2934 void
pudding_merge_message(otmp,otmp2)2935 pudding_merge_message(otmp, otmp2)
2936 struct obj *otmp;
2937 struct obj *otmp2;
2938 {
2939     boolean visible = (cansee(otmp->ox, otmp->oy)
2940                        || cansee(otmp2->ox, otmp2->oy)),
2941             onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR),
2942             inpack = (carried(otmp) || carried(otmp2));
2943 
2944     /* the player will know something happened inside his own inventory */
2945     if ((!Blind && visible) || inpack) {
2946         if (Hallucination) {
2947             if (onfloor) {
2948                 You_see("parts of the floor melting!");
2949             } else if (inpack) {
2950                 Your("pack reaches out and grabs something!");
2951             }
2952             /* even though we can see where they should be,
2953              * they'll be out of our view (minvent or container)
2954              * so don't actually show anything */
2955         } else if (onfloor || inpack) {
2956             boolean adj = ((otmp->ox != u.ux || otmp->oy != u.uy)
2957                            && (otmp2->ox != u.ux || otmp2->oy != u.uy));
2958 
2959             pline("The %s%s coalesce%s.",
2960                   (onfloor && adj) ? "adjacent " : "",
2961                   makeplural(obj_typename(otmp->otyp)),
2962                   inpack ? " inside your pack" : "");
2963         }
2964     } else {
2965         You_hear("a faint sloshing sound.");
2966     }
2967 }
2968 
2969 /*mkobj.c*/
2970