1 /* NetHack 3.7	mkobj.c	$NHDT-Date: 1619919403 2021/05/02 01:36:43 $  $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.198 $ */
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 void mkbox_cnts(struct obj *);
9 static unsigned nextoid(struct obj *, struct obj *);
10 static boolean may_generate_eroded(struct obj *);
11 static void maybe_adjust_light(struct obj *, int);
12 static void obj_timer_checks(struct obj *, xchar, xchar, int);
13 static void container_weight(struct obj *);
14 static struct obj *save_mtraits(struct obj *, struct monst *);
15 static void objlist_sanity(struct obj *, int, const char *);
16 static void mon_obj_sanity(struct monst *, const char *);
17 static const char *where_name(struct obj *);
18 static void insane_object(struct obj *, const char *, const char *,
19                           struct monst *);
20 static void check_contained(struct obj *, const char *);
21 static void check_glob(struct obj *, const char *);
22 static void sanity_check_worn(struct obj *);
23 static void init_thiefstone(struct obj *);
24 static const struct icp* material_list(struct obj *);
25 static boolean invalid_obj_material(struct obj *, uchar);
26 
27 struct icp {
28     int iprob;   /* probability of an item type */
29     char iclass; /* item class */
30 };
31 
32 static const struct icp mkobjprobs[] = { { 10, WEAPON_CLASS },
33                                          { 10, ARMOR_CLASS },
34                                          { 20, FOOD_CLASS },
35                                          { 8, TOOL_CLASS },
36                                          { 8, GEM_CLASS },
37                                          { 16, POTION_CLASS },
38                                          { 16, SCROLL_CLASS },
39                                          { 4, SPBOOK_CLASS },
40                                          { 4, WAND_CLASS },
41                                          { 3, RING_CLASS },
42                                          { 1, AMULET_CLASS } };
43 
44 static const struct icp boxiprobs[] = { { 18, GEM_CLASS },
45                                         { 15, FOOD_CLASS },
46                                         { 18, POTION_CLASS },
47                                         { 18, SCROLL_CLASS },
48                                         { 12, SPBOOK_CLASS },
49                                         { 7, COIN_CLASS },
50                                         { 6, WAND_CLASS },
51                                         { 5, RING_CLASS },
52                                         { 1, AMULET_CLASS } };
53 
54 static const struct icp hellprobs[] = { { 20, WEAPON_CLASS },
55                                         { 20, ARMOR_CLASS },
56                                         { 16, FOOD_CLASS },
57                                         { 12, TOOL_CLASS },
58                                         { 10, GEM_CLASS },
59                                         { 1, POTION_CLASS },
60                                         { 1, SCROLL_CLASS },
61                                         { 8, WAND_CLASS },
62                                         { 8, RING_CLASS },
63                                         { 4, AMULET_CLASS } };
64 
65 static const struct oextra zerooextra = DUMMY;
66 
67 static void
init_oextra(struct oextra * oex)68 init_oextra(struct oextra* oex)
69 {
70     *oex = zerooextra;
71 }
72 
73 struct oextra *
newoextra(void)74 newoextra(void)
75 {
76     struct oextra *oextra;
77 
78     oextra = (struct oextra *) alloc(sizeof (struct oextra));
79     init_oextra(oextra);
80     return oextra;
81 }
82 
83 void
dealloc_oextra(struct obj * o)84 dealloc_oextra(struct obj* o)
85 {
86     struct oextra *x = o->oextra;
87 
88     if (x) {
89         if (x->oname)
90             free((genericptr_t) x->oname);
91         if (x->omonst)
92             free_omonst(o);     /* 'o' rather than 'x' */
93         if (x->omailcmd)
94             free((genericptr_t) x->omailcmd);
95 
96         free((genericptr_t) x);
97         o->oextra = (struct oextra *) 0;
98     }
99 }
100 
101 void
newomonst(struct obj * otmp)102 newomonst(struct obj* otmp)
103 {
104     if (!otmp->oextra)
105         otmp->oextra = newoextra();
106 
107     if (!OMONST(otmp)) {
108         struct monst *m = newmonst();
109 
110         *m = cg.zeromonst;
111         OMONST(otmp) = m;
112     }
113 }
114 
115 void
free_omonst(struct obj * otmp)116 free_omonst(struct obj* otmp)
117 {
118     if (otmp->oextra) {
119         struct monst *m = OMONST(otmp);
120 
121         if (m) {
122             if (m->mextra)
123                 dealloc_mextra(m);
124             free((genericptr_t) m);
125             OMONST(otmp) = (struct monst *) 0;
126         }
127     }
128 }
129 
130 void
newomid(struct obj * otmp)131 newomid(struct obj* otmp)
132 {
133     if (!otmp->oextra)
134         otmp->oextra = newoextra();
135     OMID(otmp) = 0;
136 }
137 
138 void
free_omid(struct obj * otmp)139 free_omid(struct obj* otmp)
140 {
141     OMID(otmp) = 0;
142 }
143 
144 void
new_omailcmd(struct obj * otmp,const char * response_cmd)145 new_omailcmd(struct obj* otmp, const char * response_cmd)
146 {
147     if (!otmp->oextra)
148         otmp->oextra = newoextra();
149     if (OMAILCMD(otmp))
150         free_omailcmd(otmp);
151     OMAILCMD(otmp) = dupstr(response_cmd);
152 }
153 
154 void
free_omailcmd(struct obj * otmp)155 free_omailcmd(struct obj* otmp)
156 {
157     if (otmp->oextra && OMAILCMD(otmp)) {
158         free((genericptr_t) OMAILCMD(otmp));
159         OMAILCMD(otmp) = (char *) 0;
160     }
161 }
162 
163 struct obj *
mkobj_at(char let,int x,int y,boolean artif)164 mkobj_at(char let, int x, int y, boolean artif)
165 {
166     struct obj *otmp;
167 
168     otmp = mkobj(let, artif);
169     place_object(otmp, x, y);
170     return otmp;
171 }
172 
173 struct obj *
mksobj_at(int otyp,int x,int y,boolean init,boolean artif)174 mksobj_at(int otyp, int x, int y, boolean init, boolean artif)
175 {
176     struct obj *otmp;
177 
178     otmp = mksobj(otyp, init, artif);
179     place_object(otmp, x, y);
180     return otmp;
181 }
182 
183 struct obj *
mksobj_migr_to_species(int otyp,unsigned int mflags2,boolean init,boolean artif)184 mksobj_migr_to_species(
185     int otyp,
186     unsigned int mflags2,
187     boolean init,
188     boolean artif)
189 {
190     struct obj *otmp;
191 
192     otmp = mksobj(otyp, init, artif);
193     add_to_migration(otmp);
194     otmp->owornmask = (long) MIGR_TO_SPECIES;
195     otmp->migr_species = mflags2;
196     return otmp;
197 }
198 
199 /* mkobj(): select a type of item from a class, use mksobj() to create it;
200    result is always non-Null */
201 struct obj *
mkobj(int oclass,boolean artif)202 mkobj(int oclass, boolean artif)
203 {
204     int tprob, i, prob;
205     int first_obj, last_obj, total_prob;
206 
207     if (oclass == RANDOM_CLASS) {
208         const struct icp *iprobs = Inhell ? (const struct icp *) hellprobs
209                                           : (const struct icp *) mkobjprobs;
210 
211         for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
212             continue;
213         oclass = iprobs->iclass;
214     }
215 
216     /* get total probability of objects in this class */
217     if (oclass == SPBOOK_no_NOVEL) {
218         /* Constant for when mkobj() should only produce an actual spellbook, not
219          * some other sort of book like a novel. */
220         first_obj = g.bases[SPBOOK_CLASS];
221         last_obj = SPE_BLANK_PAPER;
222         oclass = SPBOOK_CLASS; /* for sanity check below */
223     }
224     else if (oclass + 1 < MAXOCLASSES) {
225         first_obj = g.bases[(int) oclass];
226         last_obj = g.bases[(int) oclass + 1] - 1;
227     }
228     else {
229         first_obj = g.bases[(int) oclass];
230         /* bases[oclass + 1] doesn't exist in this case */
231         last_obj = NUM_OBJECTS - 1;
232     }
233     total_prob = 0;
234     for (i = first_obj; i <= last_obj; ++i) {
235         total_prob += objects[i].oc_prob;
236     }
237 
238     prob = rnd(total_prob);
239     i = first_obj;
240     while ((prob -= objects[i].oc_prob) > 0)
241         ++i;
242 
243     if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
244         panic("probtype error, oclass=%d i=%d", (int) oclass, i);
245 
246     return mksobj(i, TRUE, artif);
247 }
248 
249 static void
mkbox_cnts(struct obj * box)250 mkbox_cnts(struct obj* box)
251 {
252     register int n;
253     register struct obj *otmp;
254 
255     box->cobj = (struct obj *) 0;
256 
257     switch (box->otyp) {
258     case ICE_BOX:
259         n = 20;
260         break;
261     case CHEST:
262         n = box->olocked ? 7 : 5;
263         break;
264     case LARGE_BOX:
265         n = box->olocked ? 5 : 3;
266         break;
267     case SACK:
268     case OILSKIN_SACK:
269         /* initial inventory: sack starts out empty */
270         if (g.moves <= 1 && !g.in_mklev) {
271             n = 0;
272             break;
273         }
274         /*FALLTHRU*/
275     case BAG_OF_HOLDING:
276         n = 1;
277         break;
278     default:
279         n = 0;
280         break;
281     }
282 
283     for (n = rn2(n + 1); n > 0; n--) {
284         if (box->otyp == ICE_BOX) {
285             otmp = mksobj(CORPSE, TRUE, TRUE);
286             /* Note: setting age to 0 is correct.  Age has a different
287              * from usual meaning for objects stored in ice boxes. -KAA
288              */
289             otmp->age = 0L;
290             if (otmp->timed) {
291                 (void) stop_timer(ROT_CORPSE, obj_to_any(otmp));
292                 (void) stop_timer(MOLDY_CORPSE, obj_to_any(otmp));
293                 (void) stop_timer(REVIVE_MON, obj_to_any(otmp));
294             }
295         } else {
296             register int tprob;
297             const struct icp *iprobs = boxiprobs;
298 
299             for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
300                 ;
301             if (!(otmp = mkobj(iprobs->iclass, TRUE)))
302                 continue;
303 
304             /* handle a couple of special cases */
305             if (otmp->oclass == COIN_CLASS) {
306                 /* 2.5 x level's usual amount; weight adjusted below */
307                 otmp->quan = (long) (rnd(level_difficulty() + 2) * rnd(75));
308                 otmp->owt = weight(otmp);
309             } else
310                 while (otmp->otyp == ROCK) {
311                     otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LUCKSTONE);
312                     if (otmp->quan > 2L)
313                         otmp->quan = 1L;
314                     otmp->owt = weight(otmp);
315                 }
316             if (box->otyp == BAG_OF_HOLDING) {
317                 if (Is_mbag(otmp)) {
318                     otmp->otyp = SACK;
319                     otmp->spe = 0;
320                     otmp->owt = weight(otmp);
321                 } else
322                     while (otmp->otyp == WAN_CANCELLATION)
323                         otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
324             }
325         }
326         (void) add_to_container(box, otmp);
327     }
328 }
329 
330 /* select a random, common monster type */
331 int
rndmonnum(void)332 rndmonnum(void)
333 {
334     register struct permonst *ptr;
335     register int i;
336     unsigned short excludeflags;
337 
338     /* Plan A: get a level-appropriate common monster */
339     ptr = rndmonst();
340     if (ptr)
341         return monsndx(ptr);
342 
343     /* Plan B: get any common monster */
344     excludeflags = G_UNIQ | G_NOGEN | (Inhell ? G_NOHELL : G_HELL);
345     do {
346         i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
347         ptr = &mons[i];
348     } while ((ptr->geno & excludeflags) != 0);
349 
350     return i;
351 }
352 
353 void
copy_oextra(struct obj * obj2,struct obj * obj1)354 copy_oextra(struct obj* obj2, struct obj* obj1)
355 {
356     if (!obj2 || !obj1 || !obj1->oextra)
357         return;
358 
359     if (!obj2->oextra)
360         obj2->oextra = newoextra();
361     if (has_oname(obj1))
362         oname(obj2, ONAME(obj1));
363     if (has_omonst(obj1)) {
364         if (!OMONST(obj2))
365             newomonst(obj2);
366         (void) memcpy((genericptr_t) OMONST(obj2),
367                       (genericptr_t) OMONST(obj1), sizeof (struct monst));
368         OMONST(obj2)->mextra = (struct mextra *) 0;
369         OMONST(obj2)->nmon = (struct monst *) 0;
370 #if 0
371         OMONST(obj2)->m_id = g.context.ident++;
372         if (OMONST(obj2)->m_id) /* ident overflowed */
373             OMONST(obj2)->m_id = g.context.ident++;
374 #endif
375         if (OMONST(obj1)->mextra)
376             copy_mextra(OMONST(obj2), OMONST(obj1));
377     }
378     if (has_omailcmd(obj1)) {
379         new_omailcmd(obj2, OMAILCMD(obj1));
380     }
381     if (has_omid(obj1)) {
382         if (!OMID(obj2))
383             newomid(obj2);
384         OMID(obj2) = OMID(obj1);
385     }
386 }
387 
388 /*
389  * Split obj so that it gets size gets reduced by num. The quantity num is
390  * put in the object structure delivered by this call.  The returned object
391  * has its wornmask cleared and is positioned just following the original
392  * in the nobj chain (and nexthere chain when on the floor).
393  */
394 struct obj *
splitobj(struct obj * obj,long num)395 splitobj(struct obj* obj, long num)
396 {
397     struct obj *otmp;
398 
399     if (obj->cobj || num <= 0L || obj->quan <= num)
400         panic("splitobj"); /* can't split containers */
401     otmp = newobj();
402     *otmp = *obj; /* copies whole structure */
403     otmp->oextra = (struct oextra *) 0;
404     otmp->o_id = nextoid(obj, otmp);
405     otmp->timed = 0;                  /* not timed, yet */
406     otmp->lamplit = 0;                /* ditto */
407     otmp->owornmask = 0L;             /* new object isn't worn */
408     obj->quan -= num;
409     obj->owt = weight(obj);
410     otmp->quan = num;
411     otmp->owt = weight(otmp); /* -= obj->owt ? */
412     otmp->lua_ref_cnt = 0;
413 
414     g.context.objsplit.parent_oid = obj->o_id;
415     g.context.objsplit.child_oid = otmp->o_id;
416     obj->nobj = otmp;
417     /* Only set nexthere when on the floor, nexthere is also used */
418     /* as a back pointer to the container object when contained. */
419     if (obj->where == OBJ_FLOOR)
420         obj->nexthere = otmp;
421     copy_oextra(otmp, obj);
422     if (has_omid(otmp))
423         free_omid(otmp); /* only one association with m_id*/
424     if (obj->unpaid)
425         splitbill(obj, otmp);
426     if (obj->timed)
427         obj_split_timers(obj, otmp);
428     if (obj_sheds_light(obj))
429         obj_split_light_source(obj, otmp);
430     return otmp;
431 }
432 
433 /* when splitting a stack that has o_id-based shop prices, pick an
434    o_id value for the new stack that will maintain the same price */
435 static unsigned
nextoid(struct obj * oldobj,struct obj * newobj)436 nextoid(struct obj* oldobj, struct obj* newobj)
437 {
438     int olddif, newdif, trylimit = 256; /* limit of 4 suffices at present */
439     unsigned oid = g.context.ident - 1; /* loop increment will reverse -1 */
440 
441     olddif = oid_price_adjustment(oldobj, oldobj->o_id);
442     do {
443         ++oid;
444         if (!oid) /* avoid using 0 (in case value wrapped) */
445             ++oid;
446         newdif = oid_price_adjustment(newobj, oid);
447     } while (newdif != olddif && --trylimit >= 0);
448     g.context.ident = oid + 1; /* ready for next new object */
449     return oid;
450 }
451 
452 /* try to find the stack obj was split from, then merge them back together;
453    returns the combined object if unsplit is successful, null otherwise */
454 struct obj *
unsplitobj(struct obj * obj)455 unsplitobj(struct obj* obj)
456 {
457     unsigned target_oid = 0;
458     struct obj *oparent = 0, *ochild = 0, *list = 0;
459 
460     /*
461      * We don't operate on floor objects (we're following o->nobj rather
462      * than o->nexthere), on free objects (don't know which list to use when
463      * looking for obj's parent or child), on bill objects (too complicated,
464      * not needed), or on buried or migrating objects (not needed).
465      * [This could be improved, but at present additional generality isn't
466      * necessary.]
467      */
468     switch (obj->where) {
469     case OBJ_FREE:
470     case OBJ_FLOOR:
471     case OBJ_ONBILL:
472     case OBJ_MIGRATING:
473     case OBJ_BURIED:
474     default:
475         return (struct obj *) 0;
476     case OBJ_INVENT:
477         list = g.invent;
478         break;
479     case OBJ_MINVENT:
480         list = obj->ocarry->minvent;
481         break;
482     case OBJ_CONTAINED:
483         list = obj->ocontainer->cobj;
484         break;
485     }
486 
487     /* first try the expected case; obj is split from another stack */
488     if (obj->o_id == g.context.objsplit.child_oid) {
489         /* parent probably precedes child and will require list traversal */
490         ochild = obj;
491         target_oid = g.context.objsplit.parent_oid;
492         if (obj->nobj && obj->nobj->o_id == target_oid)
493             oparent = obj->nobj;
494     } else if (obj->o_id == g.context.objsplit.parent_oid) {
495         /* alternate scenario: another stack was split from obj;
496            child probably follows parent and will be found here */
497         oparent = obj;
498         target_oid = g.context.objsplit.child_oid;
499         if (obj->nobj && obj->nobj->o_id == target_oid)
500             ochild = obj->nobj;
501     }
502     /* if we have only half the split, scan obj's list to find other half */
503     if (ochild && !oparent) {
504         /* expected case */
505         for (obj = list; obj; obj = obj->nobj)
506             if (obj->o_id == target_oid) {
507                 oparent = obj;
508                 break;
509             }
510     } else if (oparent && !ochild) {
511         /* alternate scenario */
512         for (obj = list; obj; obj = obj->nobj)
513             if (obj->o_id == target_oid) {
514                 ochild = obj;
515                 break;
516             }
517     }
518     /* if we have both parent and child, try to merge them;
519        if successful, return the combined stack, otherwise return null */
520     return (oparent && ochild && merged(&oparent, &ochild)) ? oparent : 0;
521 }
522 
523 /* reset splitobj()/unsplitobj() context */
524 void
clear_splitobjs(void)525 clear_splitobjs(void)
526 {
527     g.context.objsplit.parent_oid = g.context.objsplit.child_oid = 0;
528 }
529 
530 /*
531  * Insert otmp right after obj in whatever chain(s) it is on.  Then extract
532  * obj from the chain(s).  This function does a literal swap.  It is up to
533  * the caller to provide a valid context for the swap.  When done, obj will
534  * still exist, but not on any chain.
535  *
536  * Note:  Don't use use obj_extract_self() -- we are doing an in-place swap,
537  * not actually moving something.
538  */
539 void
replace_object(struct obj * obj,struct obj * otmp)540 replace_object(struct obj* obj, struct obj* otmp)
541 {
542     otmp->where = obj->where;
543     switch (obj->where) {
544     case OBJ_FREE:
545         /* do nothing */
546         break;
547     case OBJ_INVENT:
548         otmp->nobj = obj->nobj;
549         obj->nobj = otmp;
550         extract_nobj(obj, &g.invent);
551         break;
552     case OBJ_CONTAINED:
553         otmp->nobj = obj->nobj;
554         otmp->ocontainer = obj->ocontainer;
555         obj->nobj = otmp;
556         extract_nobj(obj, &obj->ocontainer->cobj);
557         break;
558     case OBJ_MINVENT:
559         otmp->nobj = obj->nobj;
560         otmp->ocarry = obj->ocarry;
561         obj->nobj = otmp;
562         extract_nobj(obj, &obj->ocarry->minvent);
563         break;
564     case OBJ_FLOOR:
565         fuzl_xyi("replace_obj floor", obj->ox, obj->oy, obj->otyp);
566         otmp->nobj = obj->nobj;
567         otmp->nexthere = obj->nexthere;
568         otmp->ox = obj->ox;
569         otmp->oy = obj->oy;
570         obj->nobj = otmp;
571         obj->nexthere = otmp;
572         extract_nobj(obj, &fobj);
573         extract_nexthere(obj, &g.level.objects[obj->ox][obj->oy]);
574         break;
575     default:
576         panic("replace_object: obj position");
577         break;
578     }
579 }
580 
581 /* is 'obj' inside a container whose contents aren't known?
582    if so, return the outermost container meeting that criterium */
583 struct obj *
unknwn_contnr_contents(struct obj * obj)584 unknwn_contnr_contents(struct obj* obj)
585 {
586     struct obj *result = 0, *parent;
587 
588     while (obj->where == OBJ_CONTAINED) {
589         parent = obj->ocontainer;
590         if (!parent->cknown)
591             result = parent;
592         obj = parent;
593     }
594     return result;
595 }
596 
597 /*
598  * Create a dummy duplicate to put on shop bill.  The duplicate exists
599  * only in the billobjs chain.  This function is used when a shop object
600  * is being altered, and a copy of the original is needed for billing
601  * purposes.  For example, when eating, where an interruption will yield
602  * an object which is different from what it started out as; the "I x"
603  * command needs to display the original object.
604  *
605  * The caller is responsible for checking otmp->unpaid and
606  * costly_spot(u.ux, u.uy).  This function will make otmp no charge.
607  *
608  * Note that check_unpaid_usage() should be used instead for partial
609  * usage of an object.
610  */
611 void
bill_dummy_object(struct obj * otmp)612 bill_dummy_object(struct obj* otmp)
613 {
614     register struct obj *dummy;
615     long cost = 0L;
616 
617     if (otmp->unpaid) {
618         cost = unpaid_cost(otmp, FALSE);
619         subfrombill(otmp, shop_keeper(*u.ushops));
620     }
621     dummy = newobj();
622     *dummy = *otmp;
623     dummy->oextra = (struct oextra *) 0;
624     dummy->where = OBJ_FREE;
625     dummy->o_id = nextoid(otmp, dummy);
626     dummy->timed = 0;
627     copy_oextra(dummy, otmp);
628     if (has_omid(dummy))
629         free_omid(dummy); /* only one association with m_id*/
630     if (Is_candle(dummy))
631         dummy->lamplit = 0;
632     dummy->owornmask = 0L; /* dummy object is not worn */
633     addtobill(dummy, FALSE, TRUE, TRUE);
634     if (cost)
635         alter_cost(dummy, -cost);
636     /* no_charge is only valid for some locations */
637     otmp->no_charge = (otmp->where == OBJ_FLOOR
638                        || otmp->where == OBJ_CONTAINED) ? 1 : 0;
639     otmp->unpaid = 0;
640     return;
641 }
642 
643 /* alteration types; must match COST_xxx macros in hack.h */
644 static const char *const alteration_verbs[] = {
645     "cancel", "drain", "uncharge", "unbless", "uncurse", "disenchant",
646     "degrade", "dilute", "erase", "burn", "neutralize", "destroy", "splatter",
647     "bite", "open", "break the lock on", "rust", "rot", "tarnish", "ferment"
648 };
649 
650 /* possibly bill for an object which the player has just modified */
651 void
costly_alteration(struct obj * obj,int alter_type)652 costly_alteration(struct obj* obj, int alter_type)
653 {
654     xchar ox, oy;
655     char objroom;
656     boolean learn_bknown;
657     const char *those, *them;
658     struct monst *shkp = 0;
659 
660     if (alter_type < 0 || alter_type >= SIZE(alteration_verbs)) {
661         impossible("invalid alteration type (%d)", alter_type);
662         alter_type = 0;
663     }
664 
665     ox = oy = 0;    /* lint suppression */
666     objroom = '\0'; /* ditto */
667     if (carried(obj) || obj->where == OBJ_FREE) {
668         /* OBJ_FREE catches obj_no_longer_held()'s transformation
669            of crysknife back into worm tooth; the object has been
670            removed from inventory but not necessarily placed at
671            its new location yet--the unpaid flag will still be set
672            if this item is owned by a shop */
673         if (!obj->unpaid)
674             return;
675     } else {
676         /* this get_obj_location shouldn't fail, but if it does,
677            use hero's location */
678         if (!get_obj_location(obj, &ox, &oy, CONTAINED_TOO))
679             ox = u.ux, oy = u.uy;
680         if (!costly_spot(ox, oy))
681             return;
682         objroom = *in_rooms(ox, oy, SHOPBASE);
683         /* if no shop cares about it, we're done */
684         if (!billable(&shkp, obj, objroom, FALSE))
685             return;
686     }
687 
688     if (obj->quan == 1L)
689         those = "that", them = "it";
690     else
691         those = "those", them = "them";
692 
693     /* when shopkeeper describes the object as being uncursed or unblessed
694        hero will know that it is now uncursed; will also make the feedback
695        from `I x' after bill_dummy_object() be more specific for this item */
696     learn_bknown = (alter_type == COST_UNCURS || alter_type == COST_UNBLSS);
697 
698     switch (obj->where) {
699     case OBJ_FREE: /* obj_no_longer_held() */
700     case OBJ_INVENT:
701         if (learn_bknown)
702             set_bknown(obj, 1);
703         verbalize("You %s %s %s, you pay for %s!",
704                   alteration_verbs[alter_type], those, simpleonames(obj),
705                   them);
706         bill_dummy_object(obj);
707         break;
708     case OBJ_FLOOR:
709         if (learn_bknown)
710             obj->bknown = 1; /* ok to bypass set_bknown() here */
711         if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
712             verbalize("You %s %s, you pay for %s!",
713                       alteration_verbs[alter_type], those, them);
714             bill_dummy_object(obj);
715         } else {
716             (void) stolen_value(obj, ox, oy, FALSE, FALSE);
717         }
718         break;
719     }
720 }
721 
722 static const char dknowns[] = { WAND_CLASS,   RING_CLASS, POTION_CLASS,
723                                 SCROLL_CLASS, GEM_CLASS,  SPBOOK_CLASS,
724                                 WEAPON_CLASS, TOOL_CLASS, 0 };
725 
726 static boolean
may_generate_eroded(struct obj * otmp)727 may_generate_eroded(struct obj* otmp) {
728     /* don't generate eroded or fixed items in initial hero inventory */
729     if (g.moves <= 1 && !g.in_mklev) {
730         return FALSE;
731     }
732     /* item cannot be eroded or damaged, because of material, existing
733      * erodeproofing, etc */
734     if (otmp->oerodeproof || !erosion_matters(otmp) || !is_damageable(otmp)) {
735         return FALSE;
736     }
737     /* item is part of a monster's body and produced when it dies */
738     if (otmp->otyp == WORM_TOOTH || otmp->otyp == UNICORN_HORN) {
739         return FALSE;
740     }
741     /* item is an artifact */
742     if (otmp->oartifact) {
743         return FALSE;
744     }
745 
746     return TRUE;
747 }
748 
749 /* mksobj(): create a specific type of object; result it always non-Null */
750 struct obj *
mksobj(int otyp,boolean init,boolean artif)751 mksobj(int otyp, boolean init, boolean artif)
752 {
753     int mndx, tryct;
754     struct obj *otmp;
755     char let = objects[otyp].oc_class;
756 
757     otmp = newobj();
758     *otmp = cg.zeroobj;
759     otmp->age = g.monstermoves;
760     otmp->o_id = g.context.ident++;
761     if (!otmp->o_id)
762         otmp->o_id = g.context.ident++; /* ident overflowed */
763     otmp->quan = 1L;
764     otmp->oclass = let;
765     otmp->otyp = otyp;
766     otmp->where = OBJ_FREE;
767     otmp->dknown = index(dknowns, let) ? 0 : 1;
768     if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD)
769         || otmp->otyp == SHIELD_OF_REFLECTION
770         || objects[otmp->otyp].oc_merge)
771         otmp->dknown = 0;
772     if (!objects[otmp->otyp].oc_uses_known)
773         otmp->known = 1;
774     otmp->lknown = 0;
775     otmp->cknown = 0;
776     otmp->corpsenm = NON_PM;
777     otmp->lua_ref_cnt = 0;
778     set_material(otmp, objects[otmp->otyp].oc_material);
779 
780     if (init) {
781         init_obj_material(otmp);
782         switch (let) {
783         case WEAPON_CLASS:
784             otmp->quan = is_multigen(otmp) ? (long) rn1(6, 6) : 1L;
785             if (!rn2(11)) {
786                 otmp->spe = rne(3);
787                 otmp->blessed = rn2(2);
788             } else if (!rn2(10)) {
789                 curse(otmp);
790                 otmp->spe = -rne(3);
791             } else
792                 blessorcurse(otmp, 10);
793             if (is_poisonable(otmp) && !rn2(100))
794                 otmp->opoisoned = 1;
795 
796             if (artif && !rn2(20))
797                 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
798 
799             /* check oartifact here because mk_artifact isn't guaranteed to
800              * create an artifact */
801             if (!otmp->oartifact && !otmp->cursed
802                 && (otmp->spe + otmp->oerodeproof > (long) rnd(5)))
803                 otmp = weapon_oname(otmp);
804 
805             break;
806         case FOOD_CLASS:
807             otmp->oeaten = 0;
808             switch (otmp->otyp) {
809             case CORPSE:
810                 /* possibly overridden by mkcorpstat() */
811                 tryct = 50;
812                 do
813                     otmp->corpsenm = undead_to_corpse(rndmonnum());
814                 while ((g.mvitals[otmp->corpsenm].mvflags & G_NOCORPSE)
815                        && (--tryct > 0));
816                 if (tryct == 0) {
817                     /* perhaps rndmonnum() only wants to make G_NOCORPSE
818                        monsters on this g.level; create an adventurer's
819                        corpse instead, then */
820                     otmp->corpsenm = PM_HUMAN;
821                 }
822                 /* timer set below */
823                 break;
824             case EGG:
825                 otmp->corpsenm = NON_PM; /* generic egg */
826                 if (!rn2(3))
827                     for (tryct = 200; tryct > 0; --tryct) {
828                         mndx = can_be_hatched(rndmonnum());
829                         if (mndx != NON_PM && !dead_species(mndx, TRUE)) {
830                             otmp->corpsenm = mndx; /* typed egg */
831                             break;
832                         }
833                     }
834                 /* timer set below */
835                 break;
836             case TIN:
837                 otmp->corpsenm = NON_PM; /* empty (so far) */
838                 otmp->tinseed = rand();
839                 if (!rn2(6))
840                     set_tin_variety(otmp, SPINACH_TIN);
841                 else
842                     for (tryct = 200; tryct > 0; --tryct) {
843                         mndx = undead_to_corpse(rndmonnum());
844                         if (mons[mndx].cnutrit
845                             && !(g.mvitals[mndx].mvflags & G_NOCORPSE)) {
846                             otmp->corpsenm = mndx;
847                             set_tin_variety(otmp, RANDOM_TIN);
848                             break;
849                         }
850                     }
851                 blessorcurse(otmp, 10);
852                 if (!rn2(30))
853                     otmp->otrapped = TRUE;
854                 break;
855             case SLIME_MOLD:
856                 otmp->spe = g.context.current_fruit;
857                 if (g.in_mklev) {
858                     int holiday = current_holidays();
859                     const char* foods[10];
860                     int idx = 0;
861                     if (holiday & HOLIDAY_VALENTINES_DAY) {
862                         foods[idx++] = "box of chocolates";
863                         foods[idx++] = "chocolate-covered strawberry";
864                     }
865                     if (holiday & HOLIDAY_MARDI_GRAS) {
866                         foods[idx++] = "slice of king cake";
867                         foods[idx++] = "beignet";
868                         foods[idx++] = "bowl of gumbo";
869                         foods[idx++] = "bowl of jambalaya";
870                     }
871                     if (holiday & HOLIDAY_PI_DAY) {
872                         foods[idx++] = "irrational pie";
873                         foods[idx++] = "perfectly circular pie";
874                     }
875                     if (holiday & HOLIDAY_EASTER) {
876                         foods[idx++] = "easter egg";
877                         foods[idx++] = "chocolate bunny";
878                         foods[idx++] = "bag of jelly beans";
879                     }
880                     if (holiday & HOLIDAY_CANADA_DAY) {
881                         foods[idx++] = "maple sugar candy";
882                     }
883                     if (holiday & HOLIDAY_HALLOWEEN) {
884                         foods[idx++] = "bag of candy corn";
885                         foods[idx++] = "lollipop";
886                         foods[idx++] = "popcorn ball";
887                     }
888                     if (holiday & HOLIDAY_THANKSGIVING) {
889                         foods[idx++] = "roast turkey drumstick";
890                         foods[idx++] = "mashed potato with gravy";
891                         foods[idx++] = "cup of cranberry sauce";
892                         foods[idx++] = "slice of pumpkin pie";
893                     }
894                     if (holiday & HOLIDAY_EID_AL_FITR) {
895                         foods[idx++] = "ma'amoul";
896                         foods[idx++] = "baklava";
897                         foods[idx++] = "kleicha";
898                     }
899                     if (holiday & HOLIDAY_LOS_MUERTOS) {
900                         foods[idx++] = "pan de muerto";
901                     }
902                     if (holiday & HOLIDAY_ROSH_HASHANAH) {
903                         foods[idx++] = "honeyed apple";
904                     }
905                     if (holiday & HOLIDAY_PASSOVER) {
906                         foods[idx++] = "matzo ball";
907                     }
908                     if (holiday & HOLIDAY_HANUKKAH) {
909                         foods[idx++] = "latke";
910                         foods[idx++] = "sufganiyah";
911                     }
912                     if (holiday & HOLIDAY_CHRISTMAS) {
913                         foods[idx++] = "sugar plum";
914                         foods[idx++] = "candy cane";
915                         foods[idx++] = "figgy pudding";
916                         foods[idx++] = "fruitcake";
917                     }
918                     if (idx >= 10) {
919                         impossible("Too many holiday foods!");
920                         idx = 9;
921                     }
922                     if (idx > 0) {
923                         /* fruitadd requires a modifiable string */
924                         char foodbuf[BUFSZ];
925                         Strcpy(foodbuf, foods[rn2(idx)]);
926                         otmp->spe = fruitadd(foodbuf, NULL);
927                     }
928                 }
929                 flags.made_fruit = TRUE;
930                 break;
931             case KELP_FROND:
932                 otmp->quan = (long) rnd(2);
933                 break;
934             case CANDY_BAR:
935                 /* set otmp->spe */
936                 assign_candy_wrapper(otmp);
937                 break;
938             default:
939                 break;
940             }
941             if (Is_pudding(otmp)) {
942                 otmp->quan = 1L; /* for emphasis; glob quantity is always 1 */
943                 otmp->globby = 1;
944                 otmp->known = otmp->dknown = 1;
945                 otmp->corpsenm = PM_GRAY_OOZE
946                                  + (otmp->otyp - GLOB_OF_GRAY_OOZE);
947             } else {
948                 if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
949                     && otmp->otyp != KELP_FROND && !rn2(6)) {
950                     otmp->quan = 2L;
951                 }
952             }
953             break;
954         case GEM_CLASS:
955             if (otmp->otyp == ROCK)
956                 otmp->quan = (long) rn1(6, 6);
957             else if (otmp->otyp != LUCKSTONE && otmp->otyp != THIEFSTONE
958                      && !rn2(6))
959                 otmp->quan = 2L;
960             else if (otmp->otyp == THIEFSTONE)
961                 init_thiefstone(otmp);
962             else
963                 otmp->quan = 1L;
964             break;
965         case TOOL_CLASS:
966             switch (otmp->otyp) {
967             case TALLOW_CANDLE:
968             case WAX_CANDLE:
969                 otmp->spe = 1;
970                 otmp->age = 20L * /* 400 or 200 */
971                             (long) objects[otmp->otyp].oc_cost;
972                 otmp->lamplit = 0;
973                 otmp->quan = 1L + (long) (rn2(2) ? rn2(7) : 0);
974                 blessorcurse(otmp, 5);
975                 break;
976             case LANTERN:
977             case OIL_LAMP:
978                 otmp->spe = 1;
979                 otmp->age = (long) rn1(500, 1000);
980                 otmp->lamplit = 0;
981                 blessorcurse(otmp, 5);
982                 break;
983             case MAGIC_LAMP:
984                 otmp->spe = 1;
985                 otmp->lamplit = 0;
986                 blessorcurse(otmp, 2);
987                 break;
988             case CHEST:
989             case LARGE_BOX:
990                 otmp->olocked = !!(rn2(5));
991                 otmp->otrapped = !(rn2(10));
992                 /*FALLTHRU*/
993             case ICE_BOX:
994             case SACK:
995             case OILSKIN_SACK:
996             case BAG_OF_HOLDING:
997                 mkbox_cnts(otmp);
998                 break;
999             case EXPENSIVE_CAMERA:
1000             case TINNING_KIT:
1001             case MAGIC_MARKER:
1002                 otmp->spe = rn1(70, 30);
1003                 break;
1004             case CAN_OF_GREASE:
1005                 otmp->spe = rn1(21, 5); /* 0..20 + 5 => 5..25 */
1006                 blessorcurse(otmp, 10);
1007                 break;
1008             case CRYSTAL_BALL:
1009                 otmp->spe = rnd(25);
1010                 blessorcurse(otmp, 2);
1011                 break;
1012             case HORN_OF_PLENTY:
1013             case BAG_OF_TRICKS:
1014                 otmp->spe = rn1(18, 3); /* 0..17 + 3 => 3..20 */
1015                 break;
1016             case FIGURINE:
1017                 tryct = 0;
1018                 do
1019                     otmp->corpsenm = rndmonnum();
1020                 while (is_human(&mons[otmp->corpsenm]) && tryct++ < 30);
1021                 blessorcurse(otmp, 4);
1022                 break;
1023             case BELL_OF_OPENING:
1024                 otmp->spe = 3;
1025                 break;
1026             case MAGIC_FLUTE:
1027             case MAGIC_HARP:
1028             case FROST_HORN:
1029             case FIRE_HORN:
1030             case DRUM_OF_EARTHQUAKE:
1031                 otmp->spe = rn1(5, 4);
1032                 break;
1033             }
1034             break;
1035         case AMULET_CLASS:
1036             if (otmp->otyp == AMULET_OF_YENDOR)
1037                 g.context.made_amulet = TRUE;
1038             if (rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION
1039                             || otmp->otyp == AMULET_OF_CHANGE
1040                             || otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
1041                 curse(otmp);
1042             } else
1043                 blessorcurse(otmp, 10);
1044             break;
1045         case VENOM_CLASS:
1046         case CHAIN_CLASS:
1047         case BALL_CLASS:
1048             break;
1049         case POTION_CLASS: /* note: potions get some additional init below */
1050         case SCROLL_CLASS:
1051 #ifdef MAIL_STRUCTURES
1052             if (otmp->otyp != SCR_MAIL)
1053 #endif
1054                 blessorcurse(otmp, 4);
1055             break;
1056         case SPBOOK_CLASS:
1057             otmp->spestudied = 0;
1058             blessorcurse(otmp, 17);
1059             break;
1060         case ARMOR_CLASS:
1061             if (rn2(10)
1062                 && (otmp->otyp == FUMBLE_BOOTS
1063                     || otmp->otyp == LEVITATION_BOOTS
1064                     || otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT
1065                     || otmp->otyp == GAUNTLETS_OF_FUMBLING || !rn2(11))) {
1066                 curse(otmp);
1067                 otmp->spe = -rne(3);
1068             } else if (!rn2(10)) {
1069                 otmp->blessed = rn2(2);
1070                 otmp->spe = rne(3);
1071             } else
1072                 blessorcurse(otmp, 10);
1073             if (artif && !rn2(40))
1074                 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1075             /* simulate lacquered armor for samurai */
1076             if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL
1077                 && (g.moves <= 1 || In_quest(&u.uz))) {
1078 #ifdef UNIXPC
1079                 /* optimizer bitfield bug */
1080                 otmp->oerodeproof = 1;
1081                 otmp->rknown = 1;
1082 #else
1083                 otmp->oerodeproof = otmp->rknown = 1;
1084 #endif
1085             }
1086             break;
1087         case WAND_CLASS:
1088             if (otmp->otyp == WAN_WISHING)
1089                 otmp->spe = 1;
1090             else
1091                 otmp->spe =
1092                     rn1(5, (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
1093             blessorcurse(otmp, 17);
1094             otmp->recharged = 0; /* used to control recharging */
1095             break;
1096         case RING_CLASS:
1097             if (objects[otmp->otyp].oc_charged) {
1098                 schar multiplier = 1;
1099                 blessorcurse(otmp, 3);
1100                 /* This multiplier formula is from FIQHack:
1101                  * Beatitude |    +1 |  0 |    -1
1102                  * Blessed:      94%   2%      4%
1103                  * Uncursed:     67%   2%     31%
1104                  * Cursed:       13%   2%     85%
1105                  */
1106                 if (rn2(10)) {
1107                     /* For 81% of rings that were already cursed, and for 40.5%
1108                      * of rings that were uncursed, make enchantment negative.
1109                      */
1110                     if (rn2(10) && (otmp->cursed || (!bcsign(otmp) && !rn2(3))))
1111                         multiplier = -1;
1112                 }
1113                 else if (!rn2(5)) {
1114                     /* 2% of all charged rings are +0 */
1115                     multiplier = 0;
1116                 }
1117                 else if (!rn2(2)) {
1118                     /* 4% of all charged rings are made negative, even blessed
1119                      * ones */
1120                     multiplier = -1;
1121                 }
1122                 /* use rne(2) to get higher values; nobody really likes
1123                  * low-enchanted rings that much. */
1124                 otmp->spe = rne(2) * multiplier;
1125             } else if (rn2(10) && (otmp->otyp == RIN_TELEPORTATION
1126                                    || otmp->otyp == RIN_POLYMORPH
1127                                    || otmp->otyp == RIN_AGGRAVATE_MONSTER
1128                                    || otmp->otyp == RIN_HUNGER || !rn2(9))) {
1129                 curse(otmp);
1130             }
1131             break;
1132         case ROCK_CLASS:
1133             switch (otmp->otyp) {
1134             case STATUE:
1135                 /* possibly overridden by mkcorpstat() */
1136                 otmp->corpsenm = rndmonnum();
1137                 if (!verysmall(&mons[otmp->corpsenm])
1138                     && rn2(level_difficulty() / 2 + 10) > 10)
1139                     (void) add_to_container(otmp,
1140                                             mkobj(SPBOOK_no_NOVEL, FALSE));
1141             }
1142             break;
1143         case COIN_CLASS:
1144             break; /* do nothing */
1145         default:
1146             /* 3.6.3: this used to be impossible() followed by return 0
1147                but most callers aren't prepared to deal with Null result
1148                and cluttering them up to do so is pointless */
1149             panic("mksobj tried to make type %d, class %d.",
1150                   (int) otmp->otyp, (int) objects[otmp->otyp].oc_class);
1151             /*NOTREACHED*/
1152         }
1153         if (may_generate_eroded(otmp)) {
1154             /* A small fraction of non-artifact items will generate eroded or
1155              * possibly erodeproof. An item that generates eroded will never be
1156              * erodeproof, and vice versa. */
1157             if (!rn2(40)) {
1158                 otmp->oerodeproof = 1;
1159             }
1160             else {
1161                 if (!rn2(40) && (is_flammable(otmp) || is_rustprone(otmp))) {
1162                     do {
1163                         otmp->oeroded++;
1164                     } while (otmp->oeroded < 3 && !rn2(9));
1165                 }
1166                 if (!rn2(40) && (is_rottable(otmp) || is_corrodeable(otmp))) {
1167                     do {
1168                         otmp->oeroded2++;
1169                     } while (otmp->oeroded2 < 3 && !rn2(9));
1170                 }
1171             }
1172             /* and an extremely small fraction of the time, erodable items
1173              * will generate greased */
1174             if (!rn2(23263)) {
1175                 otmp->greased = 1;
1176             }
1177         }
1178     }
1179 
1180     /* some things must get done (corpsenm, timers) even if init = 0 */
1181     switch ((otmp->oclass == POTION_CLASS && otmp->otyp != POT_OIL)
1182             ? POT_WATER
1183             : otmp->otyp) {
1184     case CORPSE:
1185         if (otmp->corpsenm == NON_PM) {
1186             otmp->corpsenm = undead_to_corpse(rndmonnum());
1187             if (g.mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE | G_GONE))
1188                 otmp->corpsenm = g.urole.malenum;
1189         }
1190         /*FALLTHRU*/
1191     case STATUE:
1192     case FIGURINE:
1193         if (otmp->corpsenm == NON_PM)
1194             otmp->corpsenm = rndmonnum();
1195         /*FALLTHRU*/
1196     case EGG:
1197     /* case TIN: */
1198         set_corpsenm(otmp, otmp->corpsenm);
1199         break;
1200     case POT_OIL:
1201         otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
1202         /*FALLTHRU*/
1203     case POT_WATER: /* POTION_CLASS */
1204         otmp->fromsink = 0; /* overloads corpsenm, which was set to NON_PM */
1205         break;
1206     case LEASH:
1207         otmp->leashmon = 0; /* overloads corpsenm, which was set to NON_PM */
1208         break;
1209     case SPE_NOVEL:
1210         otmp->novelidx = -1; /* "none of the above"; will be changed */
1211         otmp = oname(otmp, noveltitle(&otmp->novelidx));
1212         break;
1213     }
1214 
1215     /* unique objects may have an associated artifact entry */
1216     if (objects[otyp].oc_unique && !otmp->oartifact)
1217         otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1218     otmp->owt = weight(otmp);
1219     return otmp;
1220 }
1221 
1222 /*
1223  * Several areas of the code made direct reassignments
1224  * to obj->corpsenm.  Because some special handling is
1225  * required in certain cases, place that handling here
1226  * and call this routine in place of the direct assignment.
1227  *
1228  * If the object was a lizard or lichen corpse:
1229  *     - ensure that you don't end up with some
1230  *       other corpse type which has no rot-away timer.
1231  *
1232  * If the object was a troll corpse:
1233  *     - ensure that you don't end up with some other
1234  *       corpse type which resurrects from the dead.
1235  *
1236  * Re-calculates the weight of figurines and corpses to suit the
1237  * new species.
1238  *
1239  * Existing timeout value for egg hatch is preserved.
1240  *
1241  */
1242 void
set_corpsenm(struct obj * obj,int id)1243 set_corpsenm(struct obj *obj, int id)
1244 {
1245     int old_id = obj->corpsenm;
1246     long when = 0L;
1247 
1248     if (obj->timed) {
1249         if (obj->otyp == EGG) {
1250             when = stop_timer(HATCH_EGG, obj_to_any(obj));
1251         } else {
1252             when = 0L;
1253             obj_stop_timers(obj); /* corpse or figurine */
1254         }
1255     }
1256     /* oeaten is used to determine how much nutrition is left in
1257        multiple-bite food and also used to derive how many hit points
1258        a creature resurrected from a partly eaten corpse gets; latter
1259        is of interest when a <foo> corpse revives as a <foo> zombie
1260        in case they are defined with different mons[].cnutrit values */
1261     if (obj->otyp == CORPSE && obj->oeaten != 0
1262         /* when oeaten is non-zero, index old_id can't be NON_PM
1263            and divisor mons[old_id].cnutrit can't be zero */
1264         && mons[old_id].cnutrit != mons[id].cnutrit) {
1265         /* oeaten and cnutrit are unsigned; theoretically that could
1266            be 16 bits and the calculation might overflow, so force long */
1267         obj->oeaten = (unsigned) ((long) obj->oeaten
1268                                   * (long) mons[id].cnutrit
1269                                   / (long) mons[old_id].cnutrit);
1270     }
1271 
1272     obj->corpsenm = id;
1273     switch (obj->otyp) {
1274     case CORPSE:
1275         start_corpse_timeout(obj);
1276         obj->owt = weight(obj);
1277         break;
1278     case FIGURINE:
1279         if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE)
1280             && (carried(obj) || mcarried(obj)))
1281             attach_fig_transform_timeout(obj);
1282         obj->owt = weight(obj);
1283         break;
1284     case EGG:
1285         if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
1286             attach_egg_hatch_timeout(obj, when);
1287         break;
1288     default: /* tin, etc. */
1289         obj->owt = weight(obj);
1290         break;
1291     }
1292 }
1293 
1294 /* Return the number of turns after which a Rider corpse revives */
1295 long
rider_revival_time(struct obj * body,boolean retry)1296 rider_revival_time(struct obj* body, boolean retry)
1297 {
1298     long when;
1299     long minturn = retry ? 3L : (body->corpsenm == PM_DEATH) ? 6L : 12L;
1300 
1301     /* Riders have a 1/3 chance per turn of reviving after 12, 6, or 3 turns.
1302        Always revive by 67. */
1303     for (when = minturn; when < 67L; when++)
1304         if (!rn2(3))
1305             break;
1306     return when;
1307 }
1308 
1309 /*
1310  * Start a corpse decay or revive timer.
1311  * This takes the age of the corpse into consideration as of 3.4.0.
1312  */
1313 void
start_corpse_timeout(struct obj * body)1314 start_corpse_timeout(struct obj* body)
1315 {
1316     long when;       /* rot away when this old */
1317     long age;        /* age of corpse          */
1318     int rot_adjust;
1319     short action;
1320 
1321     /*
1322      * Note:
1323      *      if body->norevive is set, the corpse will rot away instead
1324      *      of revive when its REVIVE_MON timer finishes.
1325      */
1326 
1327     /* lizards and lichen don't rot or revive */
1328     if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN)
1329         return;
1330 
1331     action = ROT_CORPSE;               /* default action: rot away */
1332     rot_adjust = g.in_mklev ? 25 : 10; /* give some variation */
1333     age = g.monstermoves - body->age;
1334     if (age > ROT_AGE)
1335         when = rot_adjust;
1336     else
1337         when = ROT_AGE - age;
1338     when += (long) (rnz(rot_adjust) - rot_adjust);
1339 
1340     if (is_rider(&mons[body->corpsenm])) {
1341         action = REVIVE_MON;
1342         when = rider_revival_time(body, FALSE);
1343     } else if (mons[body->corpsenm].mlet == S_TROLL) {
1344         for (age = 2; age <= TAINT_AGE; age++) {
1345             if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */
1346                 action = REVIVE_MON;
1347                 when = age;
1348                 break;
1349             }
1350         }
1351     } else if (g.zombify && zombie_form(&mons[body->corpsenm]) != NON_PM
1352                && !body->zombie_corpse && !body->norevive) {
1353         action = ZOMBIFY_MON;
1354         when = rn1(15, 5); /* 5..19 */
1355         if (g.zombify == ZOMBIFY_TAME) {
1356             body->tamed_zombie = 1;
1357         }
1358     } else if (body->zombie_corpse && !body->norevive) {
1359         for (age = 2; age <= ROT_AGE; age++) {
1360             if (!rn2(ZOMBIE_REVIVE_CHANCE)) { /* zombie revives */
1361                 action = REVIVE_MON;
1362                 when = age;
1363                 break;
1364             }
1365         }
1366     }
1367     /* independent if block so that a corpse which is eligible to revive but
1368      * fails to will still possibly grow mold, rather than having all troll
1369      * corpses just never grow mold. */
1370     if (action == ROT_CORPSE) {
1371         /* Corpses get moldy. */
1372         for (age = TAINT_AGE + 1; age <= ROT_AGE; age++) {
1373             if (!rn2(MOLDY_CHANCE)) {    /* "revives" as a random s_fungus */
1374                 action = MOLDY_CORPSE;
1375                 when = age;
1376                 break;
1377             }
1378         }
1379     }
1380 
1381     (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
1382 }
1383 
1384 static void
maybe_adjust_light(struct obj * obj,int old_range)1385 maybe_adjust_light(struct obj* obj, int old_range)
1386 {
1387     char buf[BUFSZ];
1388     xchar ox, oy;
1389     int new_range = arti_light_radius(obj), delta = new_range - old_range;
1390 
1391     /* radius of light emitting artifact varies by curse/bless state
1392        so will change after blessing or cursing */
1393     if (delta) {
1394         obj_adjust_light_radius(obj, new_range);
1395         /* simplifying assumptions:  hero is wielding this object;
1396            artifacts have to be in use to emit light and monsters'
1397            gear won't change bless or curse state */
1398         if (!Blind && get_obj_location(obj, &ox, &oy, 0)) {
1399             *buf = '\0';
1400             if (iflags.last_msg == PLNMSG_OBJ_GLOWS)
1401                 /* we just saw "The <obj> glows <color>." from dipping */
1402                 Strcpy(buf, (obj->quan == 1L) ? "It" : "They");
1403             else if (carried(obj) || cansee(ox, oy))
1404                 Strcpy(buf, Yname2(obj));
1405             if (*buf) {
1406                 /* initial activation says "dimly" if cursed,
1407                    "brightly" if uncursed, and "brilliantly" if blessed;
1408                    when changing intensity, using "less brightly" is
1409                    straightforward for dimming, but we need "brighter"
1410                    rather than "more brightly" for brightening; ugh */
1411                 pline("%s %s %s%s.", buf, otense(obj, "shine"),
1412                       (abs(delta) > 1) ? "much " : "",
1413                       (delta > 0) ? "brighter" : "less brightly");
1414             }
1415         }
1416     }
1417 }
1418 
1419 /*
1420  *      bless(), curse(), unbless(), uncurse() -- any relevant message
1421  *      about glowing amber/black/&c should be delivered prior to calling
1422  *      these routines to make the actual curse/bless state change.
1423  */
1424 
1425 void
bless(struct obj * otmp)1426 bless(struct obj* otmp)
1427 {
1428     int old_light = 0;
1429 
1430     if (otmp->oclass == COIN_CLASS)
1431         return;
1432     if (otmp->lamplit)
1433         old_light = arti_light_radius(otmp);
1434     otmp->cursed = 0;
1435     otmp->blessed = 1;
1436     if (carried(otmp) && confers_luck(otmp))
1437         set_moreluck();
1438     else if (otmp->otyp == BAG_OF_HOLDING)
1439         otmp->owt = weight(otmp);
1440     else if (otmp->otyp == FIGURINE && otmp->timed)
1441         (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1442     if (otmp->lamplit)
1443         maybe_adjust_light(otmp, old_light);
1444     return;
1445 }
1446 
1447 void
unbless(struct obj * otmp)1448 unbless(struct obj* otmp)
1449 {
1450     int old_light = 0;
1451 
1452     if (otmp->lamplit)
1453         old_light = arti_light_radius(otmp);
1454     otmp->blessed = 0;
1455     if (carried(otmp) && confers_luck(otmp))
1456         set_moreluck();
1457     else if (otmp->otyp == BAG_OF_HOLDING)
1458         otmp->owt = weight(otmp);
1459     if (otmp->lamplit)
1460         maybe_adjust_light(otmp, old_light);
1461 }
1462 
1463 void
curse(struct obj * otmp)1464 curse(struct obj* otmp)
1465 {
1466     unsigned already_cursed;
1467     int old_light = 0;
1468 
1469     if (otmp->oclass == COIN_CLASS)
1470         return;
1471     if (otmp->lamplit)
1472         old_light = arti_light_radius(otmp);
1473     already_cursed = otmp->cursed;
1474     otmp->blessed = 0;
1475     otmp->cursed = 1;
1476     /* welded two-handed weapon interferes with some armor removal */
1477     if (otmp == uwep && bimanual(uwep))
1478         reset_remarm();
1479     /* rules at top of wield.c state that twoweapon cannot be done
1480        with cursed alternate weapon */
1481     if (otmp == uswapwep && u.twoweap)
1482         drop_uswapwep();
1483     /* some cursed items need immediate updating */
1484     if (carried(otmp) && confers_luck(otmp)) {
1485         set_moreluck();
1486     } else if (otmp->otyp == BAG_OF_HOLDING) {
1487         otmp->owt = weight(otmp);
1488     } else if (otmp->otyp == FIGURINE) {
1489         if (otmp->corpsenm != NON_PM && !dead_species(otmp->corpsenm, TRUE)
1490             && (carried(otmp) || mcarried(otmp)))
1491             attach_fig_transform_timeout(otmp);
1492     } else if (otmp->oclass == SPBOOK_CLASS) {
1493         /* if book hero is reading becomes cursed, interrupt */
1494         if (!already_cursed)
1495             book_cursed(otmp);
1496     }
1497     if (otmp->where == OBJ_INVENT && !already_cursed) {
1498         /* Can't just check owornmask here, as some slots (e.g. W_ART) don't
1499          * actually indicate having otmp equipped. W_SWAPWEP is trickier as it
1500          * depends on whether the player is currently dual-wielding. */
1501         long really_wornmask = W_ARMOR | W_ACCESSORY | W_WEP;
1502         if (u.twoweap) {
1503             really_wornmask |= W_SWAPWEP;
1504         }
1505         if ((really_wornmask & W_WEP) && !will_weld(otmp)) {
1506             /* if player is wielding something that won't weld to their hand,
1507              * like a potion, suppress the weld message */
1508             really_wornmask &= ~W_WEP;
1509         }
1510         if (otmp->owornmask & really_wornmask) {
1511             cursed_gear_welds(otmp);
1512         }
1513     }
1514     if (otmp->lamplit)
1515         maybe_adjust_light(otmp, old_light);
1516     return;
1517 }
1518 
1519 void
uncurse(struct obj * otmp)1520 uncurse(struct obj* otmp)
1521 {
1522     int old_light = 0;
1523     /* note: welded() sets bknown = 1, so avoid it doing that if the hero
1524      * somehow is wielding a welded weapon with bknown = 0 (maybe they got hit
1525      * with a curse while wielding a non-bknown weapon?) */
1526     boolean welded_wep = (otmp == uwep && otmp->bknown && welded(uwep));
1527 
1528     if (otmp->lamplit)
1529         old_light = arti_light_radius(otmp);
1530     otmp->cursed = 0;
1531     if (carried(otmp) && confers_luck(otmp))
1532         set_moreluck();
1533     else if (otmp->otyp == BAG_OF_HOLDING)
1534         otmp->owt = weight(otmp);
1535     else if (otmp->otyp == FIGURINE && otmp->timed)
1536         (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1537     if (otmp->lamplit)
1538         maybe_adjust_light(otmp, old_light);
1539     if (otmp->where == OBJ_INVENT && otmp->owornmask && otmp->bknown) {
1540         if (welded_wep) {
1541             const char* hand = body_part(HAND);
1542             if (bimanual(uwep))
1543                 hand = makeplural(hand);
1544             pline("%s is no longer welded to your %s.",
1545                   upstart(yname(otmp)), hand);
1546         }
1547         else if (otmp->owornmask & (W_ARMOR | W_ACCESSORY)) {
1548             if (Hallucination)
1549                 pline("The adhesion of %s has diminished.", yname(otmp));
1550             else if (otmp->otyp != AMULET_OF_STRANGULATION)
1551                 pline("%s seems to loosen a bit.", upstart(yname(otmp)));
1552         }
1553     }
1554     return;
1555 }
1556 
1557 void
blessorcurse(struct obj * otmp,int chance)1558 blessorcurse(struct obj* otmp, int chance)
1559 {
1560     if (otmp->blessed || otmp->cursed)
1561         return;
1562 
1563     if (!rn2(chance)) {
1564         if (!rn2(2)) {
1565             curse(otmp);
1566         } else {
1567             bless(otmp);
1568         }
1569     }
1570     return;
1571 }
1572 
1573 int
bcsign(struct obj * otmp)1574 bcsign(struct obj* otmp)
1575 {
1576     return (!!otmp->blessed - !!otmp->cursed);
1577 }
1578 
1579 /* set the object's bless/curse-state known flag */
1580 void
set_bknown(struct obj * obj,unsigned int onoff)1581 set_bknown(struct obj* obj, unsigned int onoff /* 1 or 0 */)
1582 {
1583     if (obj->bknown != onoff) {
1584         obj->bknown = onoff;
1585         if (obj->where == OBJ_INVENT && g.moves > 1L)
1586             update_inventory();
1587     }
1588 }
1589 
1590 /* Relative weights of different materials.
1591  * This used to be an attempt at making them super realistic, with densities in
1592  * terms of their kg/m^3 and as close to real life as possible, but that just
1593  * doesn't work because it makes materials infeasible to use. Nobody wants
1594  * anything gold or platinum if it weighs three times as much as its iron
1595  * counterpart, and things such as wooden plate mails were incredibly
1596  * overpowered by weighing about one-tenth as much as the iron counterpart.
1597  * Instead, use arbitrary units. */
1598 static
1599 const int matdensities[] = {
1600     0,   // will cause div/0 errors if anything is this material
1601     10,  // LIQUID
1602     15,  // WAX
1603     10,  // VEGGY
1604     10,  // FLESH
1605     5,   // PAPER
1606     10,  // CLOTH
1607     15,  // LEATHER
1608     30,  // WOOD
1609     25,  // BONE
1610     20,  // DRAGONHIDE
1611     80,  // IRON
1612     70,  // METAL
1613     85,  // COPPER
1614     90,  // SILVER
1615     120, // GOLD
1616     120, // PLATINUM
1617     50,  // MITHRIL
1618     20,  // PLASTIC
1619     60,  // GLASS
1620     55,  // GEMSTONE
1621     70   // MINERAL
1622 };
1623 
1624 /*
1625  *  Calculate the weight of the given object.  This will recursively follow
1626  *  and calculate the weight of any containers.
1627  *
1628  *  Note:  It is possible to end up with an incorrect weight if some part
1629  *         of the code messes with a contained object and doesn't update the
1630  *         container's weight.
1631  */
1632 int
weight(struct obj * obj)1633 weight(struct obj* obj)
1634 {
1635     int wt = (int) objects[obj->otyp].oc_weight;
1636 
1637     /* Modify weight according to the relative densities of the two materials,
1638      * if they differ. */
1639     if (obj->material != objects[obj->otyp].oc_material) {
1640         wt = (wt * matdensities[obj->material])
1641              / matdensities[objects[obj->otyp].oc_material];
1642     }
1643 
1644     /* glob absorpsion means that merging globs accumulates weight while
1645        quantity stays 1, so update 'wt' to reflect that, unless owt is 0,
1646        when we assume this is a brand new glob so use objects[].oc_weight */
1647     if (obj->globby && obj->owt > 0)
1648         wt = obj->owt;
1649     if (Is_container(obj) || obj->otyp == STATUE) {
1650         struct obj *contents;
1651         register int cwt = 0;
1652 
1653         if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
1654             wt = (int) obj->quan * ((int) mons[obj->corpsenm].cwt * 3 / 2);
1655 
1656         for (contents = obj->cobj; contents; contents = contents->nobj)
1657             cwt += weight(contents);
1658         /*
1659          *  The weight of bags of holding is calculated as the weight
1660          *  of the bag plus the weight of the bag's contents modified
1661          *  as follows:
1662          *
1663          *      Bag status      Weight of contents
1664          *      ----------      ------------------
1665          *      cursed                  2x
1666          *      blessed                 x/4 [rounded up: (x+3)/4]
1667          *      otherwise               x/2 [rounded up: (x+1)/2]
1668          *
1669          *  The macro DELTA_CWT in pickup.c also implements these
1670          *  weight equations.
1671          */
1672         if (obj->otyp == BAG_OF_HOLDING)
1673             cwt = obj->cursed ? (cwt * 2) : obj->blessed ? ((cwt + 3) / 4)
1674                                                          : ((cwt + 1) / 2);
1675 
1676         return wt + cwt;
1677     }
1678     if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
1679         long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
1680 
1681         wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int) long_wt;
1682         if (obj->oeaten)
1683             wt = eaten_stat(wt, obj);
1684         return wt;
1685     } else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
1686         return eaten_stat((int) obj->quan * wt, obj);
1687     } else if (obj->oclass == COIN_CLASS) {
1688         return (int) ((obj->quan + 50L) / 100L);
1689     } else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) {
1690         return (int) obj->owt; /* kludge for "very" heavy iron ball */
1691     } else if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->spe) {
1692         return wt + obj->spe * (int) objects[TALLOW_CANDLE].oc_weight;
1693     } else if (obj->oclass == ARMOR_CLASS && (obj->owornmask & W_ARMOR)) {
1694         return ((wt * 3) + 3) / 4;
1695     }
1696     return (wt ? wt * (int) obj->quan : ((int) obj->quan + 1) >> 1);
1697 }
1698 
1699 /* Relative defensiveness of various materials. The only thing that should ever
1700  * matter is the difference between two of these quantities, so the values are
1701  * adjusted up so that there are no negatives.
1702  * The units involved here are AC points (but again, only the difference
1703  * matters.) */
1704 const int matac[] = {
1705      0,
1706      0,  // LIQUID
1707      1,  // WAX
1708      1,  // VEGGY
1709      3,  // FLESH
1710      1,  // PAPER
1711      2,  // CLOTH
1712      3,  // LEATHER
1713      4,  // WOOD
1714      4,  // BONE
1715      10, // DRAGON_HIDE
1716      5,  // IRON - de facto baseline for metal armor
1717      5,  // METAL
1718      4,  // COPPER
1719      5,  // SILVER
1720      3,  // GOLD
1721      4,  // PLATINUM
1722      6,  // MITHRIL
1723      3,  // PLASTIC
1724      5,  // GLASS
1725      7,  // GEMSTONE
1726      6   // MINERAL
1727 };
1728 
1729 /* Compute the bonus or penalty to AC an armor piece should get for being a
1730  * non-default material. */
1731 int
material_bonus(struct obj * obj)1732 material_bonus(struct obj *obj)
1733 {
1734     int diff = matac[obj->material] - matac[objects[obj->otyp].oc_material];
1735 
1736     /* don't allow the armor's base AC to go below 0...
1737      * or go below 1, if the armor is metallic */
1738     const int min_ac = is_metallic(obj) ? 1 : 0;
1739     if (objects[obj->otyp].a_ac + diff < min_ac) {
1740         diff = min_ac - objects[obj->otyp].a_ac;
1741     }
1742     return diff;
1743 }
1744 
1745 static const int treefruits[] = { APPLE, ORANGE, PEAR, BANANA, EUCALYPTUS_LEAF };
1746 
1747 /* called when a tree is kicked; never returns Null */
1748 struct obj *
rnd_treefruit_at(int x,int y)1749 rnd_treefruit_at(int x, int y)
1750 {
1751     return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
1752 }
1753 
1754 /* create a stack of N gold pieces; never returns Null */
1755 struct obj *
mkgold(long amount,int x,int y)1756 mkgold(long amount, int x, int y)
1757 {
1758     struct obj *gold = g_at(x, y);
1759 
1760     if (amount <= 0L) {
1761         long mul = rnd(30 / max(12-depth(&u.uz), 2));
1762 
1763         amount = (long) (1 + rnd(level_difficulty() + 2) * mul);
1764     }
1765     if (gold) {
1766         gold->quan += amount;
1767     } else {
1768         gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
1769         gold->quan = amount;
1770     }
1771     gold->owt = weight(gold);
1772     return gold;
1773 }
1774 
1775 /* return TRUE if the corpse has special timing;
1776    lizards and lichen don't rot, trolls and Riders and zombies auto-revive */
1777 #define special_corpse(num) \
1778     (((num) == PM_LIZARD || (num) == PM_LICHEN) || is_reviver(&mons[num]))
1779 
1780 /* mkcorpstat: make a corpse or statue; never returns Null.
1781  *
1782  * OEXTRA note: Passing mtmp causes mtraits to be saved
1783  * even if ptr passed as well, but ptr is always used for
1784  * the corpse type (corpsenm). That allows the corpse type
1785  * to be different from the original monster,
1786  *      i.e.  vampire -> human corpse
1787  * yet still allow restoration of the original monster upon
1788  * resurrection.
1789  */
1790 struct obj *
mkcorpstat(int objtype,struct monst * mtmp,struct permonst * ptr,int x,int y,unsigned corpstatflags)1791 mkcorpstat(
1792     int objtype,          /* CORPSE or STATUE */
1793     struct monst *mtmp,   /* dead monster, might be Null */
1794     struct permonst *ptr, /* if non-Null, overrides mtmp->mndx */
1795     int x, int y,         /* where to place corpse; <0,0> => random */
1796     unsigned corpstatflags)
1797 {
1798     struct obj *otmp;
1799     boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
1800 
1801     if (objtype != CORPSE && objtype != STATUE)
1802         impossible("making corpstat type %d", objtype);
1803     if (x == 0 && y == 0) { /* special case - random placement */
1804         otmp = mksobj(objtype, init, FALSE);
1805         (void) rloco(otmp);
1806     } else {
1807         otmp = mksobj_at(objtype, x, y, init, FALSE);
1808     }
1809     otmp->norevive = g.mkcorpstat_norevive;
1810 
1811     if ((corpstatflags & CORPSTAT_ZOMBIE) != 0) {
1812         otmp->zombie_corpse = 1;
1813     }
1814 
1815     /* when 'mtmp' is non-null save the monster's details with the
1816        corpse or statue; it will also force the 'ptr' override below */
1817     if (mtmp) {
1818         /* save_mtraits updates otmp->oextra->omonst in place */
1819         (void) save_mtraits(otmp, mtmp);
1820 
1821         if (!ptr)
1822             ptr = mtmp->data;
1823 
1824         /* don't give a revive timer to a cancelled troll's corpse */
1825         if (mtmp->mcan && !is_rider(ptr))
1826             otmp->norevive = 1;
1827     }
1828 
1829     /* when 'ptr' is non-null it comes from our caller or from 'mtmp';
1830        override mkobjs()'s initialization of a random monster type */
1831     if (ptr) {
1832         int old_corpsenm = otmp->corpsenm;
1833 
1834         otmp->corpsenm = monsndx(ptr);
1835         otmp->owt = weight(otmp);
1836         if (otmp->otyp == CORPSE && (g.zombify || special_corpse(old_corpsenm)
1837                                      || special_corpse(otmp->corpsenm))) {
1838             obj_stop_timers(otmp);
1839             if (mtmp && is_reviver(mtmp->data) && !is_rider(mtmp->data)
1840                 && mtmp->mcan) {
1841                 otmp->norevive = 1;
1842             }
1843             start_corpse_timeout(otmp);
1844         }
1845     }
1846     return otmp;
1847 }
1848 
1849 /*
1850  * Return the type of monster that this corpse will
1851  * revive as, even if it has a monster structure
1852  * attached to it. In that case, you can't just
1853  * use obj->corpsenm, because the stored monster
1854  * type can, and often is, different.
1855  * The return value is an index into mons[].
1856  */
1857 int
corpse_revive_type(struct obj * obj)1858 corpse_revive_type(struct obj* obj)
1859 {
1860     int revivetype = obj->corpsenm;
1861     struct monst *mtmp;
1862 
1863     if (has_omonst(obj) && ((mtmp = get_mtraits(obj, FALSE)) != 0)) {
1864         /* mtmp is a temporary pointer to a monster's stored
1865         attributes, not a real monster */
1866         revivetype = mtmp->mnum;
1867     }
1868     return revivetype;
1869 }
1870 
1871 /*
1872  * Attach a monster id to an object, to provide
1873  * a lasting association between the two.
1874  */
1875 struct obj *
obj_attach_mid(struct obj * obj,unsigned int mid)1876 obj_attach_mid(struct obj* obj, unsigned int mid)
1877 {
1878     if (!mid || !obj)
1879         return (struct obj *) 0;
1880     newomid(obj);
1881     OMID(obj) = mid;
1882     return obj;
1883 }
1884 
1885 static struct obj *
save_mtraits(struct obj * obj,struct monst * mtmp)1886 save_mtraits(struct obj* obj, struct monst* mtmp)
1887 {
1888     if (mtmp->ispriest)
1889         forget_temple_entry(mtmp); /* EPRI() */
1890     if (!has_omonst(obj))
1891         newomonst(obj);
1892     if (has_omonst(obj)) {
1893         int baselevel = mtmp->data->mlevel;
1894         struct monst *mtmp2 = OMONST(obj);
1895 
1896         *mtmp2 = *mtmp;
1897         mtmp2->mextra = (struct mextra *) 0;
1898         if (mtmp->data)
1899             mtmp2->mnum = monsndx(mtmp->data);
1900         /* invalidate pointers */
1901         /* m_id is needed to know if this is a revived quest leader */
1902         /* but m_id must be cleared when loading bones */
1903         mtmp2->nmon = (struct monst *) 0;
1904         mtmp2->data = (struct permonst *) 0;
1905         mtmp2->minvent = (struct obj *) 0;
1906         if (mtmp->mextra)
1907             copy_mextra(mtmp2, mtmp);
1908         /* if mtmp is a long worm with segments, its saved traits will
1909            be one without any segments */
1910         mtmp2->wormno = 0;
1911         /* mtmp might have been killed by repeated life draining; make sure
1912            mtmp2 can survive if revived ('baselevel' will be 0 for 1d4 mon) */
1913         if (mtmp2->mhpmax <= baselevel)
1914             mtmp2->mhpmax = baselevel + 1;
1915         /* mtmp is assumed to be dead but we don't kill it or its saved
1916            traits, just force those to have a sane value for current HP */
1917         if (mtmp2->mhp > mtmp2->mhpmax)
1918             mtmp2->mhp = mtmp2->mhpmax;
1919         if (mtmp2->mhp < 1)
1920             mtmp2->mhp = 0;
1921     }
1922     return obj;
1923 }
1924 
1925 /* returns a pointer to a new monst structure based on
1926  * the one contained within the obj.
1927  */
1928 struct monst *
get_mtraits(struct obj * obj,boolean copyof)1929 get_mtraits(struct obj* obj, boolean copyof)
1930 {
1931     struct monst *mtmp = (struct monst *) 0;
1932     struct monst *mnew = (struct monst *) 0;
1933 
1934     if (has_omonst(obj))
1935         mtmp = OMONST(obj);
1936     if (mtmp) {
1937         if (copyof) {
1938             mnew = newmonst();
1939             *mnew = *mtmp;
1940             mnew->mextra = (struct mextra *) 0;
1941             if (mtmp->mextra)
1942                 copy_mextra(mnew, mtmp);
1943         } else {
1944             /* Never insert this returned pointer into mon chains! */
1945             mnew = mtmp;
1946         }
1947         mnew->data = &mons[mnew->mnum];
1948     }
1949     return mnew;
1950 }
1951 
1952 /* make an object named after someone listed in the scoreboard file;
1953    never returns Null */
1954 struct obj *
mk_tt_object(int objtype,int x,int y)1955 mk_tt_object(
1956     int objtype, /* CORPSE or STATUE */
1957     int x, int y)
1958 {
1959     struct obj *otmp;
1960     boolean initialize_it;
1961 
1962     /* player statues never contain books */
1963     initialize_it = (objtype != STATUE);
1964     otmp = mksobj_at(objtype, x, y, initialize_it, FALSE);
1965 
1966     /* tt_oname() will return null if the scoreboard is empty, which in
1967        turn leaves the random corpsenm value; force it to match a player */
1968     if (!tt_oname(otmp)) {
1969         int pm = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1, PM_ARCHEOLOGIST);
1970 
1971         /* update weight for either, force timer sanity for corpses */
1972         set_corpsenm(otmp, pm);
1973     }
1974 
1975     return otmp;
1976 }
1977 
1978 /* make a new corpse or statue, uninitialized if a statue (i.e. no books);
1979    never returns Null */
1980 struct obj *
mk_named_object(int objtype,struct permonst * ptr,int x,int y,const char * nm)1981 mk_named_object(
1982 int objtype, /* CORPSE or STATUE */
1983 struct permonst *ptr,
1984 int x, int y,
1985 const char *nm)
1986 {
1987     struct obj *otmp;
1988     unsigned corpstatflags = (objtype != STATUE) ? CORPSTAT_INIT
1989                                                  : CORPSTAT_NONE;
1990 
1991     otmp = mkcorpstat(objtype, (struct monst *) 0, ptr, x, y, corpstatflags);
1992     if (nm)
1993         otmp = oname(otmp, nm);
1994     return otmp;
1995 }
1996 
1997 boolean
is_flammable(struct obj * otmp)1998 is_flammable(struct obj* otmp)
1999 {
2000     int otyp = otmp->otyp;
2001     int omat = otmp->material;
2002 
2003     /* Candles can be burned, but they're not flammable in the sense that
2004      * they can't get fire damage and it makes no sense for them to be
2005      * fireproofed.
2006      */
2007     if (Is_candle(otmp))
2008         return FALSE;
2009 
2010     if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
2011         return FALSE;
2012 
2013     return (boolean) ((omat <= BONE && omat != LIQUID) || omat == PLASTIC);
2014 }
2015 
2016 boolean
is_rottable(struct obj * otmp)2017 is_rottable(struct obj* otmp)
2018 {
2019     return (boolean) (otmp->material <= WOOD && otmp->material != LIQUID);
2020 }
2021 
2022 /*
2023  * These routines maintain the single-linked lists headed in g.level.objects[][]
2024  * and threaded through the nexthere fields in the object-instance structure.
2025  */
2026 
2027 /* put the object at the given location */
2028 void
place_object(struct obj * otmp,int x,int y)2029 place_object(struct obj* otmp, int x, int y)
2030 {
2031     register struct obj *otmp2 = g.level.objects[x][y];
2032     fuzl_xyi("place_object", x,y, otmp->otyp);
2033 
2034     if (!isok(x, y)) { /* validate location */
2035         void (*func)(const char *, ...);
2036 
2037         func = (x < 0 || y < 0 || x > COLNO - 1 || y > ROWNO - 1) ? panic
2038                : impossible;
2039         (*func)("place_object: \"%s\" [%d] off map <%d,%d>",
2040                 safe_typename(otmp->otyp), otmp->where, x, y);
2041     }
2042     if (otmp->where != OBJ_FREE)
2043         panic("place_object: obj \"%s\" [%d] not free",
2044               safe_typename(otmp->otyp), otmp->where);
2045 
2046     obj_no_longer_held(otmp);
2047     if (otmp->otyp == BOULDER) {
2048         if (!otmp2 || otmp2->otyp != BOULDER)
2049             block_point(x, y); /* vision */
2050     }
2051 
2052     /* non-boulder object goes under boulders so that map will show boulder
2053        here without display code needing to traverse pile chain to find one */
2054     if (otmp2 && otmp2->otyp == BOULDER && otmp->otyp != BOULDER) {
2055         /* 3.6.3: put otmp under last consecutive boulder rather than under
2056            just the first one; multiple boulders at same spot in new games
2057            will be consecutive due to this, ones in old games saved before
2058            this change might not be; can affect the map display if the top
2059            boulder is moved/removed by some means other than pushing */
2060         while (otmp2->nexthere && otmp2->nexthere->otyp == BOULDER)
2061             otmp2 = otmp2->nexthere;
2062         otmp->nexthere = otmp2->nexthere;
2063         otmp2->nexthere = otmp;
2064     } else {
2065         /* put on top of current pile */
2066         otmp->nexthere = otmp2;
2067         g.level.objects[x][y] = otmp;
2068     }
2069 
2070     /* set the new object's location */
2071     otmp->ox = x;
2072     otmp->oy = y;
2073     otmp->where = OBJ_FLOOR;
2074 
2075     /* add to floor chain */
2076     otmp->nobj = fobj;
2077     fobj = otmp;
2078     if (otmp->timed)
2079         obj_timer_checks(otmp, x, y, 0);
2080 }
2081 
2082 #define ROT_ICE_ADJUSTMENT 2 /* rotting on ice takes 2 times as long */
2083 
2084 /* If ice was affecting any objects correct that now
2085  * Also used for starting ice effects too. [zap.c]
2086  */
2087 void
obj_ice_effects(int x,int y,boolean do_buried)2088 obj_ice_effects(int x, int y, boolean do_buried)
2089 {
2090     struct obj *otmp;
2091 
2092     for (otmp = g.level.objects[x][y]; otmp; otmp = otmp->nexthere) {
2093         if (otmp->timed)
2094             obj_timer_checks(otmp, x, y, 0);
2095     }
2096     if (do_buried) {
2097         for (otmp = g.level.buriedobjlist; otmp; otmp = otmp->nobj) {
2098             if (otmp->ox == x && otmp->oy == y) {
2099                 if (otmp->timed)
2100                     obj_timer_checks(otmp, x, y, 0);
2101             }
2102         }
2103     }
2104 }
2105 
2106 /*
2107  * Returns an obj->age for a corpse object on ice, that would be the
2108  * actual obj->age if the corpse had just been lifted from the ice.
2109  * This is useful when just using obj->age in a check or calculation because
2110  * rot timers pertaining to the object don't have to be stopped and
2111  * restarted etc.
2112  */
2113 long
peek_at_iced_corpse_age(struct obj * otmp)2114 peek_at_iced_corpse_age(struct obj* otmp)
2115 {
2116     long age, retval = otmp->age;
2117 
2118     if (otmp->otyp == CORPSE && otmp->on_ice) {
2119         /* Adjust the age; must be same as obj_timer_checks() for off ice*/
2120         age = g.monstermoves - otmp->age;
2121         retval += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
2122         debugpline3(
2123           "The %s age has ice modifications: otmp->age = %ld, returning %ld.",
2124                     s_suffix(doname(otmp)), otmp->age, retval);
2125         debugpline1("Effective age of corpse: %ld.", g.monstermoves - retval);
2126     }
2127     return retval;
2128 }
2129 
2130 static void
obj_timer_checks(struct obj * otmp,xchar x,xchar y,int force)2131 obj_timer_checks(
2132     struct obj* otmp,
2133     xchar x, xchar y,
2134     int force) /* 0 = no force so do checks, <0 = force off, >0 force on */
2135 {
2136     long tleft = 0L;
2137     short action = ROT_CORPSE;
2138     boolean restart_timer = FALSE;
2139     boolean on_floor = (otmp->where == OBJ_FLOOR);
2140     boolean buried = (otmp->where == OBJ_BURIED);
2141 
2142     /* Check for corpses just placed on or in ice */
2143     if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x, y)) {
2144         tleft = stop_timer(action, obj_to_any(otmp));
2145         if (tleft == 0L) {
2146             action = MOLDY_CORPSE;
2147             tleft = stop_timer(action, obj_to_any(otmp));
2148         }
2149         if (tleft == 0L) {
2150             action = REVIVE_MON;
2151             tleft = stop_timer(action, obj_to_any(otmp));
2152         }
2153         if (tleft != 0L) {
2154             long age;
2155 
2156             /* mark the corpse as being on ice */
2157             otmp->on_ice = 1;
2158             debugpline3("%s is now on ice at <%d,%d>.", The(xname(otmp)), x,
2159                         y);
2160             /* Adjust the time remaining */
2161             tleft *= ROT_ICE_ADJUSTMENT;
2162             restart_timer = TRUE;
2163             /* Adjust the age; time spent off ice needs to be multiplied
2164                by the ice adjustment and subtracted from the age so that
2165                later calculations behave as if it had been on ice during
2166                that time (longwinded way of saying this is the inverse
2167                of removing it from the ice and of peeking at its age). */
2168             age = g.monstermoves - otmp->age;
2169             otmp->age = g.monstermoves - (age * ROT_ICE_ADJUSTMENT);
2170         }
2171 
2172     /* Check for corpses coming off ice */
2173     } else if (force < 0 || (otmp->otyp == CORPSE && otmp->on_ice
2174                              && !((on_floor || buried) && is_ice(x, y)))) {
2175         tleft = stop_timer(action, obj_to_any(otmp));
2176         if (tleft == 0L) {
2177             action = MOLDY_CORPSE;
2178             tleft = stop_timer(action, obj_to_any(otmp));
2179         }
2180         if (tleft == 0L) {
2181             action = REVIVE_MON;
2182             tleft = stop_timer(action, obj_to_any(otmp));
2183         }
2184         if (tleft != 0L) {
2185             long age;
2186 
2187             otmp->on_ice = 0;
2188             debugpline3("%s is no longer on ice at <%d,%d>.",
2189                         The(xname(otmp)), x, y);
2190             /* Adjust the remaining time */
2191             tleft /= ROT_ICE_ADJUSTMENT;
2192             restart_timer = TRUE;
2193             /* Adjust the age */
2194             age = g.monstermoves - otmp->age;
2195             otmp->age += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
2196         }
2197     }
2198 
2199     /* now re-start the timer with the appropriate modifications */
2200     if (restart_timer)
2201         (void) start_timer(tleft, TIMER_OBJECT, action, obj_to_any(otmp));
2202 }
2203 
2204 #undef ROT_ICE_ADJUSTMENT
2205 
2206 void
remove_object(struct obj * otmp)2207 remove_object(struct obj* otmp)
2208 {
2209     xchar x = otmp->ox;
2210     xchar y = otmp->oy;
2211 
2212     if (otmp->where != OBJ_FLOOR)
2213         panic("remove_object: obj not on floor");
2214     extract_nexthere(otmp, &g.level.objects[x][y]);
2215     extract_nobj(otmp, &fobj);
2216     /* update vision iff this was the only boulder at its spot */
2217     if (otmp->otyp == BOULDER && !sobj_at(BOULDER, x, y))
2218         unblock_point(x, y); /* vision */
2219     if (otmp->timed)
2220         obj_timer_checks(otmp, x, y, 0);
2221 }
2222 
2223 /* throw away all of a monster's inventory */
2224 void
discard_minvent(struct monst * mtmp,boolean uncreate_artifacts)2225 discard_minvent(struct monst* mtmp, boolean uncreate_artifacts)
2226 {
2227     struct obj *otmp;
2228 
2229     while ((otmp = mtmp->minvent) != 0) {
2230         /* this has now become very similar to m_useupall()... */
2231         extract_from_minvent(mtmp, otmp, TRUE, TRUE);
2232         if (uncreate_artifacts && otmp->oartifact)
2233             artifact_exists(otmp, safe_oname(otmp), FALSE);
2234         obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */
2235     }
2236 }
2237 
2238 /*
2239  * Free obj from whatever list it is on in preparation for deleting it
2240  * or moving it elsewhere; obj->where will end up set to OBJ_FREE.
2241  * Doesn't handle unwearing of objects in hero's or monsters' inventories.
2242  *
2243  * Object positions:
2244  *      OBJ_FREE        not on any list
2245  *      OBJ_FLOOR       fobj, level.locations[][] chains (use remove_object)
2246  *      OBJ_CONTAINED   cobj chain of container object
2247  *      OBJ_INVENT      hero's invent chain (use freeinv)
2248  *      OBJ_MINVENT     monster's invent chain
2249  *      OBJ_MIGRATING   migrating chain
2250  *      OBJ_BURIED      level.buriedobjs chain
2251  *      OBJ_ONBILL      on g.billobjs chain
2252  *      OBJ_LUAFREE     obj is dealloc'd from core, but still used by lua
2253  *      OBJ_INTRAP      obj is in a trap as ammo (use extract_nobj instead)
2254  */
2255 void
obj_extract_self(struct obj * obj)2256 obj_extract_self(struct obj* obj)
2257 {
2258     switch (obj->where) {
2259     case OBJ_FREE:
2260     case OBJ_LUAFREE:
2261         break;
2262     case OBJ_FLOOR:
2263         remove_object(obj);
2264         break;
2265     case OBJ_CONTAINED:
2266         extract_nobj(obj, &obj->ocontainer->cobj);
2267         container_weight(obj->ocontainer);
2268         obj->ocontainer = (struct obj *) 0; /* clear stale back-link */
2269         break;
2270     case OBJ_INVENT:
2271         freeinv(obj);
2272         break;
2273     case OBJ_MINVENT:
2274         extract_nobj(obj, &obj->ocarry->minvent);
2275         obj->ocarry = (struct monst *) 0; /* clear stale back-link */
2276         break;
2277     case OBJ_MIGRATING:
2278         extract_nobj(obj, &g.migrating_objs);
2279         break;
2280     case OBJ_BURIED:
2281         extract_nobj(obj, &g.level.buriedobjlist);
2282         break;
2283     case OBJ_ONBILL:
2284         extract_nobj(obj, &g.billobjs);
2285         break;
2286     case OBJ_INTRAP:
2287         /* Objects don't store a pointer to their containing trap.
2288          * The only place that we should be trying to extract an object inside a
2289          * trap is from within trap code that has a pointer to the trap that
2290          * contains the object. We should never be trying to extract an object
2291          * inside a trap without that context. */
2292         panic("trying to extract object from trap with no trap info");
2293         break;
2294     default:
2295         panic("obj_extract_self");
2296         break;
2297     }
2298 }
2299 
2300 /* Extract the given object from the chain, following nobj chain. */
2301 void
extract_nobj(struct obj * obj,struct obj ** head_ptr)2302 extract_nobj(struct obj* obj, struct obj** head_ptr)
2303 {
2304     struct obj *curr, *prev;
2305 
2306     curr = *head_ptr;
2307     for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) {
2308         if (curr == obj) {
2309             if (prev)
2310                 prev->nobj = curr->nobj;
2311             else
2312                 *head_ptr = curr->nobj;
2313             break;
2314         }
2315     }
2316     if (!curr)
2317         panic("extract_nobj: object lost");
2318     obj->where = OBJ_FREE;
2319     obj->nobj = (struct obj *) 0;
2320 }
2321 
2322 /*
2323  * Extract the given object from the chain, following nexthere chain.
2324  *
2325  * This does not set obj->where, this function is expected to be called
2326  * in tandem with extract_nobj, which does set it.
2327  */
2328 void
extract_nexthere(struct obj * obj,struct obj ** head_ptr)2329 extract_nexthere(struct obj* obj, struct obj** head_ptr)
2330 {
2331     struct obj *curr, *prev;
2332 
2333     curr = *head_ptr;
2334     for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) {
2335         if (curr == obj) {
2336             if (prev)
2337                 prev->nexthere = curr->nexthere;
2338             else
2339                 *head_ptr = curr->nexthere;
2340             break;
2341         }
2342     }
2343     if (!curr)
2344         panic("extract_nexthere: object lost");
2345     obj->nexthere = (struct obj *) 0;
2346 }
2347 
2348 /*
2349  * Add obj to mon's inventory.  If obj is able to merge with something already
2350  * in the inventory, then the passed obj is deleted and 1 is returned.
2351  * Otherwise 0 is returned.
2352  */
2353 int
add_to_minv(struct monst * mon,struct obj * obj)2354 add_to_minv(struct monst *mon, struct obj* obj)
2355 {
2356     struct obj *otmp;
2357 
2358     if (obj->where != OBJ_FREE)
2359         panic("add_to_minv: obj not free");
2360 
2361     /* merge if possible */
2362     for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
2363         if (merged(&otmp, &obj))
2364             return 1; /* obj merged and then free'd */
2365     /* else insert; don't bother forcing it to end of chain */
2366     obj->where = OBJ_MINVENT;
2367     obj->ocarry = mon;
2368     obj->nobj = mon->minvent;
2369     mon->minvent = obj;
2370     return 0; /* obj on mon's inventory chain */
2371 }
2372 
2373 /*
2374  * Add obj to container, make sure obj is "free".  Returns (merged) obj.
2375  * The input obj may be deleted in the process.
2376  */
2377 struct obj *
add_to_container(struct obj * container,struct obj * obj)2378 add_to_container(struct obj* container, struct obj* obj)
2379 {
2380     struct obj *otmp;
2381 
2382     if (obj->where != OBJ_FREE)
2383         panic("add_to_container: obj not free");
2384     if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT)
2385         obj_no_longer_held(obj);
2386 
2387     /* merge if possible */
2388     for (otmp = container->cobj; otmp; otmp = otmp->nobj)
2389         if (merged(&otmp, &obj))
2390             return otmp;
2391 
2392     obj->where = OBJ_CONTAINED;
2393     obj->ocontainer = container;
2394     obj->nobj = container->cobj;
2395     container->cobj = obj;
2396     return obj;
2397 }
2398 
2399 void
add_to_migration(struct obj * obj)2400 add_to_migration(struct obj* obj)
2401 {
2402     if (obj->where != OBJ_FREE)
2403         panic("add_to_migration: obj not free");
2404 
2405     /* lock picking context becomes stale if it's for this object */
2406     if (Is_container(obj))
2407         maybe_reset_pick(obj);
2408 
2409     obj->where = OBJ_MIGRATING;
2410     obj->nobj = g.migrating_objs;
2411     obj->omigr_from_dnum = u.uz.dnum;
2412     obj->omigr_from_dlevel = u.uz.dlevel;
2413     g.migrating_objs = obj;
2414 }
2415 
2416 void
add_to_buried(struct obj * obj)2417 add_to_buried(struct obj* obj)
2418 {
2419     if (obj->where != OBJ_FREE)
2420         panic("add_to_buried: obj not free");
2421 
2422     obj->where = OBJ_BURIED;
2423     obj->nobj = g.level.buriedobjlist;
2424     g.level.buriedobjlist = obj;
2425 }
2426 
2427 /* Recalculate the weight of this container and all of _its_ containers. */
2428 static void
container_weight(struct obj * container)2429 container_weight(struct obj* container)
2430 {
2431     container->owt = weight(container);
2432     if (container->where == OBJ_CONTAINED)
2433         container_weight(container->ocontainer);
2434     /*
2435         else if (container->where == OBJ_INVENT)
2436         recalculate load delay here ???
2437     */
2438 }
2439 
2440 /*
2441  * Deallocate the object.  _All_ objects should be run through here for
2442  * them to be deallocated.
2443  */
2444 void
dealloc_obj(struct obj * obj)2445 dealloc_obj(struct obj* obj)
2446 {
2447     if (obj->where != OBJ_FREE && obj->where != OBJ_LUAFREE)
2448         panic("dealloc_obj: obj not free");
2449     if (obj->nobj)
2450         panic("dealloc_obj with nobj");
2451     if (obj->cobj)
2452         panic("dealloc_obj with cobj");
2453 
2454     /* free up any timers attached to the object */
2455     if (obj->timed)
2456         obj_stop_timers(obj);
2457 
2458     /*
2459      * Free up any light sources attached to the object.
2460      *
2461      * We may want to just call del_light_source() without any
2462      * checks (requires a code change there).  Otherwise this
2463      * list must track all objects that can have a light source
2464      * attached to it (and also requires lamplit to be set).
2465      */
2466     if (obj_sheds_light(obj)) {
2467         del_light_source(LS_OBJECT, obj_to_any(obj));
2468         obj->lamplit = 0;
2469     }
2470 
2471     if (obj == g.thrownobj)
2472         g.thrownobj = 0;
2473     if (obj == g.kickedobj)
2474         g.kickedobj = 0;
2475 
2476     if (obj->oextra)
2477         dealloc_oextra(obj);
2478     if (obj->lua_ref_cnt) {
2479         /* obj is referenced from a lua script, let lua gc free it */
2480         obj->where = OBJ_LUAFREE;
2481         return;
2482     }
2483     free((genericptr_t) obj);
2484 }
2485 
2486 /* create an object from a horn of plenty; mirrors bagotricks(makemon.c) */
2487 int
hornoplenty(struct obj * horn,boolean tipping)2488 hornoplenty(
2489     struct obj* horn,
2490     boolean tipping) /* caller emptying entire contents; affects shop handling */
2491 {
2492     int objcount = 0;
2493 
2494     if (!horn || horn->otyp != HORN_OF_PLENTY) {
2495         impossible("bad horn o' plenty");
2496     } else if (horn->spe < 1) {
2497         pline1(nothing_happens);
2498     } else {
2499         struct obj *obj;
2500         const char *what;
2501 
2502         consume_obj_charge(horn, !tipping);
2503         if (!rn2(13)) {
2504             obj = mkobj(POTION_CLASS, FALSE);
2505             if (objects[obj->otyp].oc_magic)
2506                 do {
2507                     obj->otyp = rnd_class(POT_BOOZE, POT_WATER);
2508                 } while (obj->otyp == POT_SICKNESS);
2509             what = (obj->quan > 1L) ? "Some potions" : "A potion";
2510         } else {
2511             obj = mkobj(FOOD_CLASS, FALSE);
2512             if (obj->otyp == FOOD_RATION && !rn2(7))
2513                 obj->otyp = LUMP_OF_ROYAL_JELLY;
2514             what = "Some food";
2515         }
2516         ++objcount;
2517         pline("%s %s out.", what, vtense(what, "spill"));
2518         obj->blessed = horn->blessed;
2519         obj->cursed = horn->cursed;
2520         obj->owt = weight(obj);
2521         /* using a shop's horn of plenty entails a usage fee and also
2522            confers ownership of the created item to the shopkeeper */
2523         if (horn->unpaid)
2524             addtobill(obj, FALSE, FALSE, tipping);
2525         /* if it ended up on bill, we don't want "(unpaid, N zorkids)"
2526            being included in its formatted name during next message */
2527         iflags.suppress_price++;
2528         if (!tipping) {
2529             obj = hold_another_object(obj,
2530                                       u.uswallow
2531                                         ? "Oops!  %s out of your reach!"
2532                                         : (Is_airlevel(&u.uz)
2533                                            || Is_waterlevel(&u.uz)
2534                                            || levl[u.ux][u.uy].typ < IRONBARS
2535                                            || levl[u.ux][u.uy].typ >= ICE)
2536                                           ? "Oops!  %s away from you!"
2537                                           : "Oops!  %s to the floor!",
2538                                       The(aobjnam(obj, "slip")), (char *) 0);
2539             nhUse(obj);
2540         } else {
2541             /* assumes this is taking place at hero's location */
2542             if (!can_reach_floor(TRUE)) {
2543                 hitfloor(obj, TRUE); /* does altar check, message, drop */
2544             } else {
2545                 if (IS_ALTAR(levl[u.ux][u.uy].typ))
2546                     doaltarobj(obj); /* does its own drop message */
2547                 else
2548                     pline("%s %s to the %s.", Doname2(obj),
2549                           otense(obj, "drop"), surface(u.ux, u.uy));
2550                 dropy(obj);
2551             }
2552         }
2553         iflags.suppress_price--;
2554         if (horn->dknown)
2555             makeknown(HORN_OF_PLENTY);
2556     }
2557     return objcount;
2558 }
2559 
2560 /* support for wizard-mode's `sanity_check' option */
2561 
2562 static const char NEARDATA /* pline formats for insane_object() */
2563     ofmt0[] = "%s obj %s %s: %s",
2564     ofmt3[] = "%s [not null] %s %s: %s",
2565     /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
2566     mfmt1[] = "%s obj %s %s (%s)",
2567     mfmt2[] = "%s obj %s %s (%s) *not*";
2568 
2569 /* Check all object lists for consistency. */
2570 void
obj_sanity_check(void)2571 obj_sanity_check(void)
2572 {
2573     int x, y;
2574     struct obj *obj;
2575 
2576     /*
2577      * TODO:
2578      *  Should check whether the obj->bypass and/or obj->nomerge bits
2579      *  are set.  Those are both used for temporary purposes and should
2580      *  be clear between moves.
2581      */
2582 
2583     objlist_sanity(fobj, OBJ_FLOOR, "floor sanity");
2584 
2585     /* check that the map's record of floor objects is consistent;
2586        those objects should have already been sanity checked via
2587        the floor list so container contents are skipped here */
2588     for (x = 0; x < COLNO; x++)
2589         for (y = 0; y < ROWNO; y++)
2590             for (obj = g.level.objects[x][y]; obj; obj = obj->nexthere) {
2591                 /* <ox,oy> should match <x,y>; <0,*> should always be empty */
2592                 if (obj->where != OBJ_FLOOR || x == 0
2593                     || obj->ox != x || obj->oy != y) {
2594                     char at_fmt[BUFSZ];
2595 
2596                     Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
2597                             x, y, obj->ox, obj->oy);
2598                     insane_object(obj, at_fmt, "location sanity",
2599                                   (struct monst *) 0);
2600                 }
2601             }
2602 
2603     objlist_sanity(g.invent, OBJ_INVENT, "invent sanity");
2604     objlist_sanity(g.migrating_objs, OBJ_MIGRATING, "migrating sanity");
2605     objlist_sanity(g.level.buriedobjlist, OBJ_BURIED, "buried sanity");
2606     objlist_sanity(g.billobjs, OBJ_ONBILL, "bill sanity");
2607 
2608     mon_obj_sanity(fmon, "minvent sanity");
2609     mon_obj_sanity(g.migrating_mons, "migrating minvent sanity");
2610     /* monsters temporarily in transit;
2611        they should have arrived with hero by the time we get called */
2612     if (g.mydogs) {
2613         impossible("g.mydogs sanity [not empty]");
2614         mon_obj_sanity(g.mydogs, "mydogs minvent sanity");
2615     }
2616 
2617     /* objects temporarily freed from invent/floor lists;
2618        they should have arrived somewhere by the time we get called */
2619     if (g.thrownobj)
2620         insane_object(g.thrownobj, ofmt3, "g.thrownobj sanity",
2621                       (struct monst *) 0);
2622     if (g.kickedobj)
2623         insane_object(g.kickedobj, ofmt3, "g.kickedobj sanity",
2624                       (struct monst *) 0);
2625     /* g.current_wand isn't removed from invent while in use, but should
2626        be Null between moves when we're called */
2627     if (g.current_wand)
2628         insane_object(g.current_wand, ofmt3, "g.current_wand sanity",
2629                       (struct monst *) 0);
2630 }
2631 
2632 /* sanity check for objects on specified list (fobj, &c) */
2633 static void
objlist_sanity(struct obj * objlist,int wheretype,const char * mesg)2634 objlist_sanity(struct obj* objlist, int wheretype, const char * mesg)
2635 {
2636     struct obj *obj;
2637 
2638     for (obj = objlist; obj; obj = obj->nobj) {
2639         if (obj->where != wheretype)
2640             insane_object(obj, ofmt0, mesg, (struct monst *) 0);
2641         if (Has_contents(obj)) {
2642             if (wheretype == OBJ_ONBILL)
2643                 /* containers on shop bill should always be empty */
2644                 insane_object(obj, "%s obj contains something! %s %s: %s",
2645                               mesg, (struct monst *) 0);
2646             check_contained(obj, mesg);
2647         }
2648         if (obj->owornmask) {
2649             char maskbuf[40];
2650             boolean bc_ok = FALSE;
2651 
2652             switch (obj->where) {
2653             case OBJ_INVENT:
2654             case OBJ_MINVENT:
2655                 sanity_check_worn(obj);
2656                 break;
2657             case OBJ_MIGRATING:
2658                 /* migrating objects overload the owornmask field
2659                    with a destination code; skip attempt to check it */
2660                 break;
2661             case OBJ_FLOOR:
2662                 /* note: ball and chain can also be OBJ_FREE, but not across
2663                    turns so this sanity check shouldn't encounter that */
2664                 bc_ok = TRUE;
2665             /*FALLTHRU*/
2666             default:
2667                 if ((obj != uchain && obj != uball) || !bc_ok) {
2668                     /* discovered an object not in inventory which
2669                        erroneously has worn mask set */
2670                     Sprintf(maskbuf, "worn mask 0x%08lx", obj->owornmask);
2671                     insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2672                 }
2673                 break;
2674             }
2675             if (obj->globby)
2676                 check_glob(obj, mesg);
2677         }
2678     }
2679 }
2680 
2681 /* sanity check for objects carried by all monsters in specified list */
2682 static void
mon_obj_sanity(struct monst * monlist,const char * mesg)2683 mon_obj_sanity(struct monst* monlist, const char* mesg)
2684 {
2685     struct monst *mon;
2686     struct obj *obj, *mwep;
2687 
2688     for (mon = monlist; mon; mon = mon->nmon) {
2689         if (DEADMONSTER(mon))
2690             continue;
2691         mwep = MON_WEP(mon);
2692         if (mwep) {
2693             if (!mcarried(mwep))
2694                 insane_object(mwep, mfmt1, mesg, mon);
2695             if (mwep->ocarry != mon)
2696                 insane_object(mwep, mfmt2, mesg, mon);
2697         }
2698         for (obj = mon->minvent; obj; obj = obj->nobj) {
2699             if (obj->where != OBJ_MINVENT)
2700                 insane_object(obj, mfmt1, mesg, mon);
2701             if (obj->ocarry != mon)
2702                 insane_object(obj, mfmt2, mesg, mon);
2703             if (obj->globby)
2704                 check_glob(obj, mesg);
2705             check_contained(obj, mesg);
2706         }
2707     }
2708 }
2709 
2710 /* This must stay consistent with the defines in obj.h. */
2711 static const char *obj_state_names[NOBJ_STATES] = { "free",      "floor",
2712                                                     "contained", "invent",
2713                                                     "minvent",   "migrating",
2714                                                     "buried",    "onbill",
2715                                                     "luafree" };
2716 
2717 static const char *
where_name(struct obj * obj)2718 where_name(struct obj* obj)
2719 {
2720     static char unknown[32]; /* big enough to handle rogue 64-bit int */
2721     int where;
2722 
2723     if (!obj)
2724         return "nowhere";
2725     where = obj->where;
2726     if (where < 0 || where >= NOBJ_STATES || !obj_state_names[where]) {
2727         Sprintf(unknown, "unknown[%d]", where);
2728         return unknown;
2729     }
2730     return obj_state_names[where];
2731 }
2732 
2733 static void
insane_object(struct obj * obj,const char * fmt,const char * mesg,struct monst * mon)2734 insane_object(
2735     struct obj* obj,
2736     const char* fmt,
2737     const char* mesg,
2738     struct monst* mon)
2739 {
2740     const char *objnm, *monnm;
2741     char altfmt[BUFSZ];
2742 
2743     objnm = monnm = "null!";
2744     if (obj) {
2745         iflags.override_ID++;
2746         objnm = doname(obj);
2747         iflags.override_ID--;
2748     }
2749     if (mon || (strstri(mesg, "minvent") && !strstri(mesg, "contained"))) {
2750         Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)");
2751         if (mon)
2752             monnm = x_monnam(mon, ARTICLE_A, (char *) 0, EXACT_NAME, TRUE);
2753         impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2754               objnm, fmt_ptr((genericptr_t) mon), monnm);
2755     } else {
2756         impossible(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2757                    objnm);
2758     }
2759 }
2760 
2761 /*
2762  * Initialize a dummy obj with just enough info
2763  * to allow some of the tests in obj.h that
2764  * take an obj pointer to work.
2765  */
2766 struct obj *
init_dummyobj(struct obj * obj,short otyp,long oquan)2767 init_dummyobj(struct obj* obj, short otyp, long oquan)
2768 {
2769      if (obj) {
2770          *obj = cg.zeroobj;
2771          obj->otyp = otyp;
2772          obj->oclass = objects[otyp].oc_class;
2773          /* obj->dknown = 0; */
2774          /* suppress known except for amulets (needed for fakes & real AoY) */
2775          obj->known = (obj->oclass == AMULET_CLASS)
2776                        ? obj->known
2777                          /* default is "on" for types which don't use it */
2778                          : !objects[otyp].oc_uses_known;
2779          obj->quan = oquan ? oquan : 1L;
2780          obj->corpsenm = NON_PM; /* suppress statue and figurine details */
2781          /* but suppressing fruit details leads to "bad fruit #0" */
2782          if (obj->otyp == SLIME_MOLD)
2783              obj->spe = g.context.current_fruit;
2784      }
2785      return obj;
2786 }
2787 
2788 /* obj sanity check: check objects inside container */
2789 static void
check_contained(struct obj * container,const char * mesg)2790 check_contained(struct obj* container, const char *mesg)
2791 {
2792     struct obj *obj;
2793     /* big enough to work with, not too big to blow out stack in recursion */
2794     char mesgbuf[40], nestedmesg[120];
2795 
2796     if (!Has_contents(container))
2797         return;
2798     /* change "invent sanity" to "contained invent sanity"
2799        but leave "nested contained invent sanity" as is */
2800     if (!strstri(mesg, "contained"))
2801         mesg = strcat(strcpy(mesgbuf, "contained "), mesg);
2802 
2803     for (obj = container->cobj; obj; obj = obj->nobj) {
2804         /* catch direct cycle to avoid unbounded recursion */
2805         if (obj == container)
2806             panic("failed sanity check: container holds itself");
2807         if (obj->where != OBJ_CONTAINED)
2808             insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *) 0);
2809         else if (obj->ocontainer != container)
2810             impossible("%s obj %s in container %s, not %s", mesg,
2811                   fmt_ptr((genericptr_t) obj),
2812                   fmt_ptr((genericptr_t) obj->ocontainer),
2813                   fmt_ptr((genericptr_t) container));
2814         if (obj->globby)
2815             check_glob(obj, mesg);
2816 
2817         if (Has_contents(obj)) {
2818             /* catch most likely indirect cycle; we won't notice if
2819                parent is present when something comes before it, or
2820                notice more deeply embedded cycles (grandparent, &c) */
2821             if (obj->cobj == container)
2822                 panic("failed sanity check: container holds its parent");
2823             /* change "contained... sanity" to "nested contained... sanity"
2824                and "nested contained..." to "nested nested contained..." */
2825             Strcpy(nestedmesg, "nested ");
2826             copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg
2827                                               - (int) strlen(nestedmesg) - 1);
2828             /* recursively check contents */
2829             check_contained(obj, nestedmesg);
2830         }
2831     }
2832 }
2833 
2834 /* called when 'obj->globby' is set so we don't recheck it here */
2835 static void
check_glob(struct obj * obj,const char * mesg)2836 check_glob(struct obj* obj, const char *mesg)
2837 {
2838 #define LOWEST_GLOB GLOB_OF_GRAY_OOZE
2839 #define HIGHEST_GLOB GLOB_OF_BLACK_PUDDING
2840     if (obj->quan != 1L || obj->owt == 0
2841         || obj->otyp < LOWEST_GLOB || obj->otyp > HIGHEST_GLOB
2842         /* a partially eaten glob could have any non-zero weight but an
2843            intact one should weigh an exact multiple of base weight (20) */
2844         || ((obj->owt % objects[obj->otyp].oc_weight) != 0 && !obj->oeaten)) {
2845         char mesgbuf[BUFSZ], globbuf[QBUFSZ];
2846 
2847         Sprintf(globbuf, " glob %d,quan=%ld,owt=%u ",
2848                 obj->otyp, obj->quan, obj->owt);
2849         mesg = strsubst(strcpy(mesgbuf, mesg), " obj ", globbuf);
2850         insane_object(obj, ofmt0, mesg,
2851                       (obj->where == OBJ_MINVENT) ? obj->ocarry : 0);
2852     }
2853 }
2854 
2855 /* check an object in hero's or monster's inventory which has worn mask set */
2856 static void
sanity_check_worn(struct obj * obj)2857 sanity_check_worn(struct obj* obj)
2858 {
2859 #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG)
2860     static unsigned long wearbits[] = {
2861         W_ARM,    W_ARMC,   W_ARMH,    W_ARMS, W_ARMG,  W_ARMF,  W_ARMU,
2862         W_WEP,    W_QUIVER, W_SWAPWEP, W_AMUL, W_RINGL, W_RINGR, W_TOOL,
2863         W_SADDLE, W_BALL,   W_CHAIN,   0
2864         /* [W_ART,W_ARTI are property bits for items which aren't worn] */
2865     };
2866     char maskbuf[60];
2867     const char *what;
2868     unsigned long owornmask, allmask = 0L;
2869     boolean embedded = FALSE;
2870     int i, n = 0;
2871 
2872     /* use owornmask for testing and bit twiddling, but use original
2873        obj->owornmask for printing */
2874     owornmask = obj->owornmask;
2875     /* figure out how many bits are set, and also which are viable */
2876     for (i = 0; wearbits[i]; ++i) {
2877         if ((owornmask & wearbits[i]) != 0L)
2878             ++n;
2879         allmask |= wearbits[i];
2880     }
2881     if (obj == uskin) {
2882         /* embedded dragon scales have an extra bit set;
2883            make sure it's set, then suppress it */
2884         embedded = TRUE;
2885         if ((owornmask & (W_ARM | I_SPECIAL)) == (W_ARM | I_SPECIAL))
2886             owornmask &= ~I_SPECIAL;
2887         else
2888             n = 0,  owornmask = ~0; /* force insane_object("bogus") below */
2889     }
2890     if (n == 2 && carried(obj)
2891         && obj == uball && (owornmask & W_BALL) != 0L
2892         && (owornmask & W_WEAPONS) != 0L) {
2893         /* chained ball can be wielded/alt-wielded/quivered; if so,
2894           pretend it's not chained in order to check the weapon pointer
2895           (we've already verified the ball pointer by successfully passing
2896           the if-condition to get here...) */
2897         owornmask &= ~W_BALL;
2898         n = 1;
2899     }
2900     if (n > 1) {
2901         /* multiple bits set */
2902         Sprintf(maskbuf, "worn mask (multiple) 0x%08lx", obj->owornmask);
2903         insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2904     }
2905     if ((owornmask & ~allmask) != 0L
2906         || (carried(obj) && (owornmask & W_SADDLE) != 0L)) {
2907         /* non-wearable bit(s) set */
2908         Sprintf(maskbuf, "worn mask (bogus)) 0x%08lx", obj->owornmask);
2909         insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2910     }
2911     if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L)) {
2912         what = 0;
2913         /* verify that obj in hero's invent (or ball/chain elsewhere)
2914            with owornmask of W_foo is the object pointed to by ufoo */
2915         switch (owornmask) {
2916         case W_ARM:
2917             if (obj != (embedded ? uskin : uarm))
2918                 what = embedded ? "skin" : "suit";
2919             break;
2920         case W_ARMC:
2921             if (obj != (embedded ? uskin : uarmc))
2922                 what = embedded ? "skin" : "cloak";
2923             break;
2924         case W_ARMH:
2925             if (obj != uarmh)
2926                 what = "helm";
2927             break;
2928         case W_ARMS:
2929             if (obj != uarms)
2930                 what = "shield";
2931             break;
2932         case W_ARMG:
2933             if (obj != uarmg)
2934                 what = "gloves";
2935             break;
2936         case W_ARMF:
2937             if (obj != uarmf)
2938                 what = "boots";
2939             break;
2940         case W_ARMU:
2941             if (obj != uarmu)
2942                 what = "shirt";
2943             break;
2944         case W_WEP:
2945             if (obj != uwep)
2946                 what = "primary weapon";
2947             break;
2948         case W_QUIVER:
2949             if (obj != uquiver)
2950                 what = "quiver";
2951             break;
2952         case W_SWAPWEP:
2953             if (obj != uswapwep)
2954                 what = u.twoweap ? "secondary weapon" : "alternate weapon";
2955             break;
2956         case W_AMUL:
2957             if (obj != uamul)
2958                 what = "amulet";
2959             break;
2960         case W_RINGL:
2961             if (obj != uleft)
2962                 what = "left ring";
2963             break;
2964         case W_RINGR:
2965             if (obj != uright)
2966                 what = "right ring";
2967             break;
2968         case W_TOOL:
2969             if (obj != ublindf)
2970                 what = "blindfold";
2971             break;
2972         /* case W_SADDLE: */
2973         case W_BALL:
2974             if (obj != uball)
2975                 what = "ball";
2976             break;
2977         case W_CHAIN:
2978             if (obj != uchain)
2979                 what = "chain";
2980             break;
2981         default:
2982             break;
2983         }
2984         if (what) {
2985             Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what);
2986             insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2987         }
2988     }
2989     if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L
2990                    || mcarried(obj))) {
2991         /* check for items worn in invalid slots; practically anything can
2992            be wielded/alt-wielded/quivered, so tests on those are limited */
2993         what = 0;
2994         if (owornmask & W_ARMOR) {
2995             if (obj->oclass != ARMOR_CLASS)
2996                 what = "armor";
2997             if (embedded && !Is_dragon_armor(obj))
2998                 what = "skin";
2999         } else if (owornmask & W_WEAPONS) {
3000             /* monsters don't maintain alternate weapon or quiver */
3001             if (mcarried(obj) && (owornmask & (W_SWAPWEP | W_QUIVER)) != 0L)
3002                 what = (owornmask & W_SWAPWEP) != 0L ? "monst alt weapon?"
3003                                                      : "monst quiver?";
3004             /* hero can quiver gold but not wield it (hence not alt-wield
3005                it either); also catches monster wielding gold */
3006             else if (obj->oclass == COIN_CLASS
3007                      && (owornmask & (W_WEP | W_SWAPWEP)) != 0L)
3008                 what = (owornmask & W_WEP) != 0L ? "weapon" : "alt weapon";
3009         } else if (owornmask & W_AMUL) {
3010             if (obj->oclass != AMULET_CLASS)
3011                 what = "amulet";
3012         } else if (owornmask & W_RING) {
3013             if (obj->oclass != RING_CLASS && obj->otyp != MEAT_RING)
3014                 what = "ring";
3015         } else if (owornmask & W_TOOL) {
3016             if (obj->otyp != BLINDFOLD && obj->otyp != TOWEL
3017                 && obj->otyp != LENSES)
3018                 what = "blindfold";
3019         } else if (owornmask & W_BALL) {
3020             if (obj->oclass != BALL_CLASS)
3021                 what = "chained ball";
3022         } else if (owornmask & W_CHAIN) {
3023             if (obj->oclass != CHAIN_CLASS)
3024                 what = "chain";
3025         } else if (owornmask & W_SADDLE) {
3026             if (obj->otyp != SADDLE)
3027                 what = "saddle";
3028         }
3029         if (what) {
3030             char oclassname[30];
3031             struct monst *mon = mcarried(obj) ? obj->ocarry : 0;
3032 
3033             /* if we've found a potion worn in the amulet slot,
3034                this yields "worn (potion amulet)" */
3035             Strcpy(oclassname, def_oc_syms[(uchar) obj->oclass].name);
3036             Sprintf(maskbuf, "worn (%s %s)", makesingular(oclassname), what);
3037             insane_object(obj, ofmt0, maskbuf, mon);
3038         }
3039     }
3040 #else /* not (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || DEBUG) */
3041     /* dummy use of obj to avoid "arg not used" complaint */
3042     if (!obj)
3043         insane_object(obj, ofmt0, "<null>", (struct monst *) 0);
3044 #endif
3045 }
3046 
3047 /*
3048  * wrapper to make "near this object" convenient
3049  */
3050 struct obj *
obj_nexto(struct obj * otmp)3051 obj_nexto(struct obj* otmp)
3052 {
3053     if (!otmp) {
3054         impossible("obj_nexto: wasn't given an object to check");
3055         return (struct obj *) 0;
3056     }
3057     return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
3058 }
3059 
3060 /*
3061  * looks for objects of a particular type next to x, y
3062  * skips over oid if found (lets us avoid ourselves if
3063  * we're looking for a second type of an existing object)
3064  *
3065  * TODO: return a list of all objects near us so we can more
3066  * reliably predict which one we want to 'find' first
3067  */
3068 struct obj *
obj_nexto_xy(struct obj * obj,int x,int y,boolean recurs)3069 obj_nexto_xy(struct obj* obj, int x, int y, boolean recurs)
3070 {
3071     struct obj *otmp;
3072     int fx, fy, ex, ey, otyp = obj->otyp;
3073     short dx, dy;
3074 
3075     /* check under our "feet" first */
3076     otmp = sobj_at(otyp, x, y);
3077     while (otmp) {
3078         /* don't be clever and find ourselves */
3079         if (otmp != obj && mergable(otmp, obj))
3080             return otmp;
3081         otmp = nxtobj(otmp, otyp, TRUE);
3082     }
3083 
3084     if (!recurs)
3085         return (struct obj *) 0;
3086 
3087     /* search in a random order */
3088     dx = (rn2(2) ? -1 : 1);
3089     dy = (rn2(2) ? -1 : 1);
3090     ex = x - dx;
3091     ey = y - dy;
3092 
3093     for (fx = ex; abs(fx - ex) < 3; fx += dx) {
3094         for (fy = ey; abs(fy - ey) < 3; fy += dy) {
3095             /* 0, 0 was checked above */
3096             if (isok(fx, fy) && (fx != x || fy != y)) {
3097                 if ((otmp = obj_nexto_xy(obj, fx, fy, FALSE)) != 0)
3098                     return otmp;
3099             }
3100         }
3101     }
3102     return (struct obj *) 0;
3103 }
3104 
3105 /*
3106  * Causes one object to absorb another, increasing
3107  * weight accordingly. Frees obj2; obj1 remains and
3108  * is returned.
3109  */
3110 struct obj *
obj_absorb(struct obj ** obj1,struct obj ** obj2)3111 obj_absorb(struct obj** obj1, struct obj** obj2)
3112 {
3113     struct obj *otmp1, *otmp2;
3114     int o1wt, o2wt;
3115     long agetmp;
3116 
3117     /* don't let people dumb it up */
3118     if (obj1 && obj2) {
3119         otmp1 = *obj1;
3120         otmp2 = *obj2;
3121         if (otmp1 && otmp2 && otmp1 != otmp2) {
3122             globby_bill_fixup(otmp1, otmp2);
3123             if (otmp1->bknown != otmp2->bknown)
3124                 otmp1->bknown = otmp2->bknown = 0;
3125             if (otmp1->rknown != otmp2->rknown)
3126                 otmp1->rknown = otmp2->rknown = 0;
3127             if (otmp1->greased != otmp2->greased)
3128                 otmp1->greased = otmp2->greased = 0;
3129             if (otmp1->orotten || otmp2->orotten)
3130                 otmp1->orotten = otmp2->orotten = 1;
3131             o1wt = otmp1->oeaten ? otmp1->oeaten : otmp1->owt;
3132             o2wt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
3133             /* averaging the relative ages is less likely to overflow
3134                than averaging the absolute ages directly */
3135             agetmp = (((g.moves - otmp1->age) * o1wt
3136                        + (g.moves - otmp2->age) * o2wt)
3137                       / (o1wt + o2wt));
3138             otmp1->age = g.moves - agetmp; /* conv. relative back to absolute */
3139             otmp1->owt += o2wt;
3140             if (otmp1->oeaten || otmp2->oeaten)
3141                 otmp1->oeaten = o1wt + o2wt;
3142             otmp1->quan = 1L;
3143             obj_extract_self(otmp2);
3144             dealloc_obj(otmp2);
3145             *obj2 = (struct obj *) 0;
3146             return otmp1;
3147         }
3148     }
3149 
3150     impossible("obj_absorb: not called with two actual objects");
3151     return (struct obj *) 0;
3152 }
3153 
3154 /*
3155  * Causes the heavier object to absorb the lighter object in
3156  * most cases, but if one object is OBJ_FREE and the other is
3157  * on the floor, the floor object goes first.
3158  *
3159  * wrapper for obj_absorb so that floor_effects works more
3160  * cleanly (since we don't know which we want to stay around)
3161  */
3162 struct obj *
obj_meld(struct obj ** obj1,struct obj ** obj2)3163 obj_meld(struct obj** obj1, struct obj** obj2)
3164 {
3165     struct obj *otmp1, *otmp2, *result = 0;
3166     int ox, oy;
3167 
3168     if (obj1 && obj2) {
3169         otmp1 = *obj1;
3170         otmp2 = *obj2;
3171         if (otmp1 && otmp2 && otmp1 != otmp2) {
3172             ox = oy = 0;
3173             /*
3174              * FIXME?
3175              *  If one of the objects is free because it's being dropped,
3176              *  we should really finish a full drop and then absorb/meld
3177              *  if it survives the flooreffects().  Then lighter-melds-into-
3178              *  heavier will be true even when heavier is the one dropped.
3179              *
3180              *  [Also, what about when one of the globs is on the shore
3181              *  and we drop the other into adjacent pool or vice versa?]
3182              */
3183             if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE)
3184                 && (otmp1->owt > otmp2->owt
3185                     || (otmp1->owt == otmp2->owt && rn2(2)))) {
3186                 if (otmp2->where == OBJ_FLOOR)
3187                     ox = otmp2->ox, oy = otmp2->oy;
3188                 result = obj_absorb(obj1, obj2);
3189             } else {
3190                 if (otmp1->where == OBJ_FLOOR)
3191                     ox = otmp1->ox, oy = otmp1->oy;
3192                 result = obj_absorb(obj2, obj1);
3193             }
3194             /* callers really ought to take care of this; glob melding is
3195                a bookkeeping issue rather than a display one */
3196             if (ox && cansee(ox, oy))
3197                 newsym(ox, oy);
3198         }
3199     } else {
3200         impossible("obj_meld: not called with two actual objects");
3201     }
3202     return result;
3203 }
3204 
3205 /* give a message if hero notices two globs merging [used to be in pline.c] */
3206 void
pudding_merge_message(struct obj * otmp,struct obj * otmp2)3207 pudding_merge_message(struct obj* otmp, struct obj* otmp2)
3208 {
3209     boolean visible = (cansee(otmp->ox, otmp->oy)
3210                        || cansee(otmp2->ox, otmp2->oy)),
3211             onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR),
3212             inpack = (carried(otmp) || carried(otmp2));
3213 
3214     /* the player will know something happened inside his own inventory */
3215     if ((!Blind && visible) || inpack) {
3216         if (Hallucination) {
3217             if (onfloor) {
3218                 You_see("parts of the floor melting!");
3219             } else if (inpack) {
3220                 Your("pack reaches out and grabs something!");
3221             }
3222             /* even though we can see where they should be,
3223              * they'll be out of our view (minvent or container)
3224              * so don't actually show anything */
3225         } else if (onfloor || inpack) {
3226             boolean adj = ((otmp->ox != u.ux || otmp->oy != u.uy)
3227                            && (otmp2->ox != u.ux || otmp2->oy != u.uy));
3228 
3229             pline("The %s%s coalesce%s.",
3230                   (onfloor && adj) ? "adjacent " : "",
3231                   makeplural(obj_typename(otmp->otyp)),
3232                   inpack ? " inside your pack" : "");
3233         }
3234     } else {
3235         You_hear("a faint sloshing sound.");
3236     }
3237 }
3238 
3239 /* The algorithm that determines where a thiefstone will be keyed to. */
3240 void
choose_thiefstone_loc(coord * cc)3241 choose_thiefstone_loc(coord *cc)
3242 {
3243     /* Choose a suitable location on the current level.
3244      * Prefers, in this order: vaults, closets, spaces with containers on them.
3245      * Failing this, will try to find a suitable walkable space, preferring
3246      * floor to any other terrain type.
3247      * The interior of a shop is always considered unsuitable.
3248      * Trapped spaces are considered unsuitable unless no other space can be
3249      * found. */
3250 
3251     /* try vault... */
3252     struct mkroom* croom = search_special(VAULT);
3253     if (croom) {
3254         somexy(croom, cc);
3255         return;
3256     }
3257     /* No vault? No luck. Scan all spaces on the level, assess each one and
3258      * give it a "quality" score for how good it would be as a possible stash
3259      * location. This is not particularly biased towards where players would
3260      * want to put stashes.
3261      * The algorithm for choosing a spot is as follows:
3262      * 1. Assess a space and get a "quality" score.
3263      * 2. If the quality of this space equals the current maximum known quality,
3264      *    increment N, the number of spaces known to have this score, and select
3265      *    it with probability 1/N.
3266      * 3. If the quality of this space is better than any other space, select
3267      *    it and set N = 1.
3268      * The whole thing works because for any space with the current maximum
3269      * quality, assuming M such spaces exist, the chance of being selected is
3270      * 1/N * N/N+1 * N+1/N+2 * ... * M-1/M = 1/M.
3271      */
3272     int x, y;
3273     int max_quality = -1;
3274     int nmax = 0;
3275     cc->x = cc->y = -1;
3276     for (x = 1; x < COLNO; x++) {
3277         for (y = 1; y < ROWNO; y++) {
3278             int quality = 0;
3279             if (*in_rooms(x, y, SHOPBASE)) {
3280                 quality -= 100;
3281             }
3282             if (levl[x][y].typ == ROOM || levl[x][y].typ == CORR ||
3283                 levl[x][y].typ == SCORR) {
3284                 /* other terrain might be walkable but we don't want to put it
3285                  * on another feature */
3286                 quality += 2;
3287                 if (!t_at(x,y)) {
3288                     quality += 7;
3289                 }
3290                 if ((levl[x][y].typ == CORR || levl[x][y].typ == SCORR)
3291                     && levl[x][y].is_niche) {
3292                     quality += 20;
3293                 }
3294                 if (container_at(x, y, FALSE)) {
3295                     quality += 15;
3296                 }
3297             }
3298             if (levl[x][y].typ == STAIRS) {
3299                 /* Absolute last resort: even if an entire level has no
3300                  * walkable terrain, there are probably stairs.
3301                  */
3302                 quality += 1;
3303             }
3304             /* TODO: favor non-joined rooms */
3305             /* TODO: examine surrounding spaces and give quality boost to
3306              * a space that has few walkable neighbors */
3307             if (quality > 0) {
3308                 if (quality == max_quality) {
3309                     nmax++;
3310                     if (!rn2(nmax)) {
3311                         cc->x = x;
3312                         cc->y = y;
3313                     }
3314                 } else if (quality > max_quality) {
3315                     nmax = 1;
3316                     cc->x = x;
3317                     cc->y = y;
3318                     max_quality = quality;
3319                 }
3320             }
3321         }
3322     }
3323     if (cc->x < 0 || cc->y < 0) {
3324         impossible("choose_thiefstone_loc: couldn't find a good space");
3325         cc->x = 1;
3326         cc->y = 1;
3327     }
3328 }
3329 
3330 /* Set up the data associated with a thiefstone. (This involves both selecting
3331  * its keyed location and recording that location in the stone.) */
3332 static void
init_thiefstone(struct obj * stone)3333 init_thiefstone(struct obj *stone)
3334 {
3335     curse(stone); /* always generated cursed */
3336 
3337     if (In_endgame(&u.uz)) {
3338         /* stones that generate in the endgame won't do anything */
3339         stone->keyed_ledger = THIEFSTONE_LEDGER_CANCELLED;
3340         return;
3341     }
3342 
3343     stone->keyed_ledger = ledger_no(&u.uz);
3344     if (!thiefstone_ledger_valid(stone)) {
3345         impossible("init_thiefstone: invalid ledger number %d", stone->keyed_ledger);
3346     }
3347     coord cc;
3348     choose_thiefstone_loc(&cc);
3349     set_keyed_loc(stone, cc.x, cc.y);
3350     /* also put a chest here, but only at level creation; wishing or polypiling
3351      * thiefstones should not spontaneously create chests */
3352     if (g.in_mklev && !container_at(cc.x, cc.y, FALSE)) {
3353         mksobj_at(CHEST, cc.x, cc.y, TRUE, FALSE);
3354     }
3355 }
3356 
3357 /* Object material probabilities. */
3358 /* for objects which are normally iron or metal */
3359 static const struct icp metal_materials[] = {
3360     {74, 0}, /* default to base type, iron or metal */
3361     { 5, IRON},
3362     { 5, WOOD},
3363     { 5, SILVER},
3364     { 3, COPPER},
3365     { 3, MITHRIL},
3366     { 1, GOLD},
3367     { 1, BONE},
3368     { 1, GLASS},
3369     { 1, PLATINUM},
3370     { 1, PLASTIC}
3371 };
3372 
3373 /* for objects which are normally wooden */
3374 static const struct icp wood_materials[] = {
3375     {80, WOOD},
3376     {10, MINERAL},
3377     { 5, IRON},
3378     { 3, BONE},
3379     { 1, COPPER},
3380     { 0, GOLD}, /* can exist in certain special levels but not randomly
3381                  * generated */
3382     { 1, SILVER}
3383 };
3384 
3385 /* for objects which are normally cloth */
3386 static const struct icp cloth_materials[] = {
3387     {80, CLOTH},
3388     {10, LEATHER},
3389     { 7, PLASTIC},
3390     { 3, PAPER}
3391 };
3392 
3393 /* for objects which are normally leather */
3394 static const struct icp leather_materials[] = {
3395     {76, LEATHER},
3396     {17, CLOTH},
3397     { 7, PLASTIC},
3398 };
3399 
3400 /* for objects of dwarvish make */
3401 static const struct icp dwarvish_materials[] = {
3402     {85, IRON},
3403     {10, MITHRIL},
3404     { 2, COPPER},
3405     { 1, SILVER},
3406     { 1, GOLD},
3407     { 1, PLATINUM}
3408 };
3409 
3410 /* for objects of orcish make - no valuables */
3411 static const struct icp crude_materials[] = {
3412     {60, 0}, /* use base */
3413     {20, IRON},
3414     { 8, BONE},
3415     { 7, WOOD},
3416     { 5, MINERAL}
3417 };
3418 
3419 /* for armor-y objects of elven make - no iron!
3420  * Does not cover clothy items; those use the regular cloth probs. */
3421 static const struct icp elven_materials[] = {
3422     {60, 0}, /* use base material */
3423     {20, WOOD},
3424     {10, COPPER},
3425     { 5, MITHRIL},
3426     { 3, SILVER},
3427     { 2, GOLD}
3428 };
3429 
3430 /* Reflectable items - for the shield of reflection; anything that can hold a
3431  * polish. Amulets also arbitrarily use this list. */
3432 static const struct icp shiny_materials[] = {
3433     {30, SILVER},
3434     {22, COPPER},
3435     {12, GOLD},
3436     {12, IRON}, /* stainless steel */
3437     {10, GLASS},
3438     { 7, MITHRIL},
3439     { 5, METAL}, /* aluminum, or similar */
3440     { 2, PLATINUM}
3441 };
3442 
3443 /* for bells and other tools, especially instruments, which are normally copper
3444  * or metal.  Wood and glass in other lists precludes us from using those. */
3445 static const struct icp resonant_materials[] = {
3446     {55, 0}, /* use base material */
3447     {25, COPPER},
3448     { 6, SILVER},
3449     { 5, IRON},
3450     { 5, MITHRIL},
3451     { 3, GOLD},
3452     { 1, PLATINUM}
3453 };
3454 
3455 /* for horns, currently. */
3456 static const struct icp horn_materials[] = {
3457     {70, BONE},
3458     {10, COPPER},
3459     { 8, MITHRIL},
3460     { 5, WOOD},
3461     { 5, SILVER},
3462     { 2, GOLD}
3463 };
3464 
3465 /* hacks for specific objects... not great because it's a lot of data, but it's
3466  * a relatively clean solution */
3467 static const struct icp statue_materials[] = {
3468     {95, MINERAL},
3469     { 4, COPPER},
3470     { 1, GOLD}
3471 };
3472 static const struct icp figurine_materials[] = {
3473     {45, MINERAL},
3474     {35, WOOD},
3475     {10, PLASTIC},
3476     { 5, METAL},
3477     { 4, COPPER},
3478     { 1, GOLD}
3479 };
3480 static const struct icp elvenhelm_materials[] = {
3481     {70, LEATHER},
3482     {20, COPPER},
3483     {10, WOOD}
3484 };
3485 static const struct icp bow_materials[] = {
3486     /* assumes all bows will be wood by default, fairly safe assumption */
3487     {75, WOOD},
3488     { 7, IRON},
3489     { 5, MITHRIL},
3490     { 4, COPPER},
3491     { 4, BONE},
3492     { 2, SILVER},
3493     { 2, PLASTIC},
3494     { 1, GOLD}
3495 };
3496 
3497 /* Return the appropriate above list for a given object, or NULL if there isn't
3498  * an appropriate list. */
3499 const struct icp*
material_list(struct obj * obj)3500 material_list(struct obj* obj)
3501 {
3502     unsigned short otyp = obj->otyp;
3503     int default_material = objects[otyp].oc_material;
3504 
3505     /* Cases for specific object types. */
3506     switch (otyp) {
3507         /* Special exceptions to the whole randomized materials system - where
3508          * we ALWAYS want an object to use its base material regardless of
3509          * other cases in this function - go here.
3510          * Return NULL so that init_obj_material and valid_obj_material both
3511          * work properly. */
3512         case BULLWHIP:
3513         case WORM_TOOTH:
3514         case CRYSKNIFE:
3515         case ELVEN_BOOTS:
3516         case LEATHER_DRUM:
3517         case DRUM_OF_EARTHQUAKE:
3518         case LAND_MINE:
3519         case TOWEL:
3520         case MUMMY_WRAPPING:
3521         case AMULET_OF_YENDOR:
3522         case FAKE_AMULET_OF_YENDOR:
3523             return NULL;
3524         /* Any other cases for specific object types go here. */
3525         case SHIELD_OF_REFLECTION:
3526             return shiny_materials;
3527         case BOW:
3528         case ELVEN_BOW:
3529         case ORCISH_BOW:
3530         case YUMI:
3531         case BOOMERANG: /* wooden base, similar shape */
3532             return bow_materials;
3533         case ELVEN_HELM:
3534             return elvenhelm_materials;
3535         case BELL:
3536         case BUGLE:
3537         case LANTERN:
3538         case OIL_LAMP:
3539         case MAGIC_LAMP:
3540         case PEA_WHISTLE:
3541         case MAGIC_WHISTLE:
3542         case FLUTE:
3543         case MAGIC_FLUTE:
3544         case HARP:
3545         case MAGIC_HARP:
3546             return resonant_materials;
3547         case TOOLED_HORN:
3548         case FIRE_HORN:
3549         case FROST_HORN:
3550         case HORN_OF_PLENTY:
3551             return horn_materials;
3552         case STATUE:
3553             if (Is_medusa_level(&u.uz) && g.in_mklev) {
3554                 /* All statues generated with the Medusa level must be stone. */
3555                 return NULL;
3556             }
3557             return statue_materials;
3558         case FIGURINE:
3559             return figurine_materials;
3560         default:
3561             break;
3562     }
3563 
3564     /* Otherwise, select an appropriate list, or return NULL if no appropriate
3565      * list exists. */
3566     if (is_elven_obj(obj) && default_material != CLOTH) {
3567         return elven_materials;
3568     }
3569     else if (is_dwarvish_obj(obj) && default_material != CLOTH) {
3570         return dwarvish_materials;
3571     }
3572     else if (is_orcish_obj(obj) && default_material != CLOTH) {
3573         return crude_materials;
3574     }
3575     else if (obj->oclass == AMULET_CLASS) {
3576         /* could use metal_materials too */
3577         return shiny_materials;
3578     }
3579     else if (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS
3580              || obj->oclass == TOOL_CLASS) {
3581         if (default_material == IRON || default_material == METAL) {
3582             return metal_materials;
3583         }
3584         else if (default_material == WOOD) {
3585             return wood_materials;
3586         }
3587         else if (default_material == CLOTH) {
3588             return cloth_materials;
3589         } else if (default_material == LEATHER) {
3590             return leather_materials;
3591         }
3592     }
3593     return NULL;
3594 }
3595 
3596 /* Initialize the material field of an object, possibly randomizing it from the
3597  * above lists. */
3598 void
init_obj_material(struct obj * obj)3599 init_obj_material(struct obj* obj)
3600 {
3601     const struct icp* materials = material_list(obj);
3602 
3603     /* always set the material to its base, this is the default for objects
3604      * which do not have a list */
3605     set_material(obj, objects[obj->otyp].oc_material);
3606 
3607     if (materials) {
3608         int i = rnd(100);
3609         while (i > 0) {
3610             if (i <= materials->iprob)
3611                 break;
3612             i -= materials->iprob;
3613             materials++;
3614         }
3615         /* Only set the new material if:
3616          * 1) it is not marked as invalid for this specific object
3617          * 2) iclass is non-zero (a zero indicates base material should be used)
3618          */
3619         if (!invalid_obj_material(obj, materials->iclass)
3620             && materials->iclass != 0) {
3621             set_material(obj, materials->iclass);
3622         }
3623     }
3624 }
3625 
3626 /* Return TRUE iff an object-material combination is specifically *invalid*,
3627  * usually a bad or illogical material combination that is OK according to the
3628  * material lists, but shouldn't exist in practice, such as a glass digging
3629  * tool. This avoids having to create new lists for those specific items which
3630  * are basically the same as the regular list but excluding one or two
3631  * materials.
3632  * This should be treated as subsidiary to valid_obj_material. */
3633 static boolean
invalid_obj_material(struct obj * obj,uchar mat)3634 invalid_obj_material(struct obj *obj, uchar mat)
3635 {
3636     int oclass = obj->oclass;
3637 
3638     /* flimsy/brittle digging tools... */
3639     if (is_pick(obj) && (mat == PLASTIC || mat == GLASS)) {
3640         return TRUE;
3641     }
3642 
3643     /* paper weapons and armor... */
3644     if ((oclass == WEAPON_CLASS || oclass == ARMOR_CLASS) && mat == PAPER) {
3645         return TRUE;
3646     }
3647 
3648     return FALSE;
3649 }
3650 
3651 /* Return TRUE if mat is a valid material for a given object of obj's type
3652  * (whether a random object of this type could generate as that material). */
3653 boolean
valid_obj_material(struct obj * obj,uchar mat)3654 valid_obj_material(struct obj *obj, uchar mat)
3655 {
3656     if (obj->oartifact) {
3657         /* shenanigans possible here, ignore them */
3658         return TRUE;
3659     }
3660 
3661     /* if it is what it's defined as in objects.c, always valid, don't bother
3662      * with lists */
3663     if (objects[obj->otyp].oc_material == mat) {
3664         return TRUE;
3665     }
3666     else {
3667         if (invalid_obj_material(obj, mat)) {
3668             return FALSE;
3669         }
3670         const struct icp* materials = material_list(obj);
3671 
3672         if (materials) {
3673             int i = 100; /* guarantee going through everything */
3674             while (i > 0) {
3675                 if (materials->iclass == mat)
3676                     return TRUE;
3677                 i -= materials->iprob;
3678                 materials++;
3679             }
3680         }
3681         /* no valid materials in list, or no valid list */
3682         return FALSE;
3683     }
3684 }
3685 
3686 /* Change the object's material, and any properties derived from it.
3687  * This includes weight, and erosion/erodeproofing (i.e. materials which
3688  * can't corrode will not be generated corroded or corrode-proofed).
3689  */
3690 void
set_material(struct obj * otmp,uchar material)3691 set_material(struct obj *otmp, uchar material)
3692 {
3693     if (!valid_obj_material(otmp, material)) {
3694         impossible("setting material of %s to invalid material %d",
3695                    OBJ_NAME(objects[otmp->otyp]), material);
3696     }
3697     otmp->material = material;
3698     otmp->owt = weight(otmp);
3699     if ((otmp->oeroded) && !is_rustprone(otmp) && !is_flammable(otmp))
3700         otmp->oeroded = 0;
3701     if ((otmp->oeroded2) && !is_corrodeable(otmp) && !is_rottable(otmp))
3702         otmp->oeroded2 = 0;
3703     if (otmp->oerodeproof && !is_damageable(otmp) && (otmp->material != GLASS))
3704         otmp->oerodeproof = FALSE;
3705 }
3706 
3707 /*mkobj.c*/
3708