OSDN Git Service

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