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