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