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. */
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 *));
25 int iprob; /* probability of an item type */
26 char iclass; /* item class */
29 static const struct icp mkobjprobs[] = { { 10, WEAPON_CLASS },
39 { 1, AMULET_CLASS } };
41 static const struct icp boxiprobs[] = { { 18, GEM_CLASS },
49 { 1, AMULET_CLASS } };
51 static const struct icp rogueprobs[] = { { 12, WEAPON_CLASS },
59 static const struct icp hellprobs[] = { { 20, WEAPON_CLASS },
68 { 4, AMULET_CLASS } };
73 struct oextra *oextra;
75 oextra = (struct oextra *) alloc(sizeof (struct oextra));
88 struct oextra *x = o->oextra;
92 free((genericptr_t) x->oname);
94 free_omonst(o); /* 'o' rather than 'x' */
96 free((genericptr_t) x->omid);
98 free((genericptr_t) x->olong);
100 free((genericptr_t) x->omailcmd);
102 free((genericptr_t) x);
103 o->oextra = (struct oextra *) 0;
112 otmp->oextra = newoextra();
115 struct monst *m = newmonst();
127 struct monst *m = OMONST(otmp);
132 free((genericptr_t) m);
133 OMONST(otmp) = (struct monst *) 0;
143 otmp->oextra = newoextra();
145 OMID(otmp) = (unsigned *) alloc(sizeof (unsigned));
146 (void) memset((genericptr_t) OMID(otmp), 0, sizeof (unsigned));
154 if (otmp->oextra && OMID(otmp)) {
155 free((genericptr_t) OMID(otmp));
156 OMID(otmp) = (unsigned *) 0;
165 otmp->oextra = newoextra();
167 OLONG(otmp) = (long *) alloc(sizeof (long));
168 (void) memset((genericptr_t) OLONG(otmp), 0, sizeof (long));
176 if (otmp->oextra && OLONG(otmp)) {
177 free((genericptr_t) OLONG(otmp));
178 OLONG(otmp) = (long *) 0;
183 new_omailcmd(otmp, response_cmd)
185 const char *response_cmd;
188 otmp->oextra = newoextra();
191 OMAILCMD(otmp) = dupstr(response_cmd);
198 if (otmp->oextra && OMAILCMD(otmp)) {
199 free((genericptr_t) OMAILCMD(otmp));
200 OMAILCMD(otmp) = (char *) 0;
205 mkobj_at(let, x, y, artif)
212 otmp = mkobj(let, artif);
213 place_object(otmp, x, y);
218 mksobj_at(otyp, x, y, init, artif)
224 otmp = mksobj(otyp, init, artif);
225 place_object(otmp, x, y);
230 mksobj_migr_to_species(otyp, mflags2, init, artif)
237 otmp = mksobj(otyp, init, artif);
238 add_to_migration(otmp);
239 otmp->owornmask = (long) MIGR_TO_SPECIES;
240 otmp->corpsenm = mflags2;
244 /* mkobj(): select a type of item from a class, use mksobj() to create it;
245 result is always non-Null */
251 int tprob, i, prob = rnd(1000);
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;
259 for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
261 oclass = iprobs->iclass;
264 i = bases[(int) oclass];
265 while ((prob -= objects[i].oc_prob) > 0)
268 if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
269 panic("probtype error, oclass=%d i=%d", (int) oclass, i);
271 return mksobj(i, TRUE, artif);
279 register struct obj *otmp;
281 box->cobj = (struct obj *) 0;
288 n = box->olocked ? 7 : 5;
291 n = box->olocked ? 5 : 3;
295 /* initial inventory: sack starts out empty */
296 if (moves <= 1 && !in_mklev) {
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
317 (void) stop_timer(ROT_CORPSE, obj_to_any(otmp));
318 (void) stop_timer(REVIVE_MON, obj_to_any(otmp));
322 const struct icp *iprobs = boxiprobs;
324 for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
326 if (!(otmp = mkobj(iprobs->iclass, TRUE)))
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);
335 while (otmp->otyp == ROCK) {
336 otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE);
339 otmp->owt = weight(otmp);
341 if (box->otyp == BAG_OF_HOLDING) {
345 otmp->owt = weight(otmp);
347 while (otmp->otyp == WAN_CANCELLATION)
348 otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
351 (void) add_to_container(box, otmp);
355 /* select a random, common monster type */
359 register struct permonst *ptr;
361 unsigned short excludeflags;
363 /* Plan A: get a level-appropriate common monster */
368 /* Plan B: get any common monster */
369 excludeflags = G_UNIQ | G_NOGEN | (Inhell ? G_NOHELL : G_HELL);
371 i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
373 } while ((ptr->geno & excludeflags) != 0);
379 copy_oextra(obj2, obj1)
380 struct obj *obj2, *obj1;
382 if (!obj2 || !obj1 || !obj1->oextra)
386 obj2->oextra = newoextra();
388 oname(obj2, ONAME(obj1));
389 if (has_omonst(obj1)) {
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;
397 OMONST(obj2)->m_id = context.ident++;
398 if (OMONST(obj2)->m_id) /* ident overflowed */
399 OMONST(obj2)->m_id = context.ident++;
401 if (OMONST(obj1)->mextra)
402 copy_mextra(OMONST(obj2), OMONST(obj1));
404 if (has_omid(obj1)) {
407 (void) memcpy((genericptr_t) OMID(obj2), (genericptr_t) OMID(obj1),
410 if (has_olong(obj1)) {
413 (void) memcpy((genericptr_t) OLONG(obj2), (genericptr_t) OLONG(obj1),
416 if (has_omailcmd(obj1)) {
417 new_omailcmd(obj2, OMAILCMD(obj1));
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).
434 if (obj->cobj || num <= 0L || obj->quan <= num)
435 panic("splitobj"); /* can't split containers */
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 */
444 obj->owt = weight(obj);
446 otmp->owt = weight(otmp); /* -= obj->owt ? */
448 context.objsplit.parent_oid = obj->o_id;
449 context.objsplit.child_oid = otmp->o_id;
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);
457 free_omid(otmp); /* only one association with m_id*/
459 splitbill(obj, otmp);
461 obj_split_timers(obj, otmp);
462 if (obj_sheds_light(obj))
463 obj_split_light_source(obj, otmp);
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 */
470 nextoid(oldobj, newobj)
471 struct obj *oldobj, *newobj;
473 int olddif, newdif, trylimit = 256; /* limit of 4 suffices at present */
474 unsigned oid = context.ident - 1; /* loop increment will reverse -1 */
476 olddif = oid_price_adjustment(oldobj, oldobj->o_id);
479 if (!oid) /* avoid using 0 (in case value wrapped) */
481 newdif = oid_price_adjustment(newobj, oid);
482 } while (newdif != olddif && --trylimit >= 0);
483 context.ident = oid + 1; /* ready for next new object */
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 */
493 unsigned target_oid = 0;
494 struct obj *oparent = 0, *ochild = 0, *list = 0;
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
504 switch (obj->where) {
511 return (struct obj *) 0;
516 list = obj->ocarry->minvent;
519 list = obj->ocontainer->cobj;
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 */
527 target_oid = context.objsplit.parent_oid;
528 if (obj->nobj && obj->nobj->o_id == target_oid)
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 */
534 target_oid = context.objsplit.child_oid;
535 if (obj->nobj && obj->nobj->o_id == target_oid)
538 /* if we have only half the split, scan obj's list to find other half */
539 if (ochild && !oparent) {
541 for (obj = list; obj; obj = obj->nobj)
542 if (obj->o_id == target_oid) {
546 } else if (oparent && !ochild) {
547 /* alternate scenario */
548 for (obj = list; obj; obj = obj->nobj)
549 if (obj->o_id == target_oid) {
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;
559 /* reset splitobj()/unsplitobj() context */
563 context.objsplit.parent_oid = context.objsplit.child_oid = 0;
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.
572 * Note: Don't use use obj_extract_self() -- we are doing an in-place swap,
573 * not actually moving something.
576 replace_object(obj, otmp)
580 otmp->where = obj->where;
581 switch (obj->where) {
586 otmp->nobj = obj->nobj;
588 extract_nobj(obj, &invent);
591 otmp->nobj = obj->nobj;
592 otmp->ocontainer = obj->ocontainer;
594 extract_nobj(obj, &obj->ocontainer->cobj);
597 otmp->nobj = obj->nobj;
598 otmp->ocarry = obj->ocarry;
600 extract_nobj(obj, &obj->ocarry->minvent);
603 otmp->nobj = obj->nobj;
604 otmp->nexthere = obj->nexthere;
608 obj->nexthere = otmp;
609 extract_nobj(obj, &fobj);
610 extract_nexthere(obj, &level.objects[obj->ox][obj->oy]);
613 panic("replace_object: obj position");
618 /* is 'obj' inside a container whose contents aren't known?
619 if so, return the outermost container meeting that criterium */
621 unknwn_contnr_contents(obj)
624 struct obj *result = 0, *parent;
626 while (obj->where == OBJ_CONTAINED) {
627 parent = obj->ocontainer;
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.
643 * The caller is responsible for checking otmp->unpaid and
644 * costly_spot(u.ux, u.uy). This function will make otmp no charge.
646 * Note that check_unpaid_usage() should be used instead for partial
647 * usage of an object.
650 bill_dummy_object(otmp)
651 register struct obj *otmp;
653 register struct obj *dummy;
657 cost = unpaid_cost(otmp, FALSE);
658 subfrombill(otmp, shop_keeper(*u.ushops));
662 dummy->oextra = (struct oextra *) 0;
663 dummy->where = OBJ_FREE;
664 dummy->o_id = context.ident++;
666 dummy->o_id = context.ident++; /* ident overflowed */
668 copy_oextra(dummy, otmp);
670 free_omid(dummy); /* only one association with m_id*/
671 if (Is_candle(dummy))
673 dummy->owornmask = 0L; /* dummy object is not worn */
674 addtobill(dummy, FALSE, TRUE, TRUE);
676 alter_cost(dummy, -cost);
677 /* no_charge is only valid for some locations */
679 (otmp->where == OBJ_FLOOR || otmp->where == OBJ_CONTAINED) ? 1 : 0;
684 /* alteration types; must match COST_xxx macros in hack.h */
685 static const char *const alteration_verbs[] = {
687 "cancel", "drain", "uncharge", "unbless", "uncurse", "disenchant",
688 "degrade", "dilute", "erase", "burn", "neutralize", "destroy", "splatter",
689 "bite", "open", "break the lock on", "rust", "rot", "tarnish"
691 "
\96³
\8cø
\89»
\82µ
\82½", "
\97ò
\89»
\82³
\82¹
\82½", "
\95ú
\8fo
\82³
\82¹
\82½", "
\8fj
\95\9f\82ð
\89ð
\82¢
\82½", "
\8eô
\82¢
\82ð
\89ð
\82¢
\82½", "
\96\82\97Í
\82ð
\8c¸
\82ç
\82µ
\82½",
692 "
\97ò
\89»
\82³
\82¹
\82½", "
\94\96\82ß
\82½", "
\8fÁ
\82µ
\82½", "
\94R
\82â
\82µ
\82½", "
\96³
\93Å
\89»
\82µ
\82½", "
\89ó
\82µ
\82½", "
\8eg
\82Á
\82½",
693 "
\90H
\82×
\82½", "
\8aJ
\82¯
\82½", "
\8c®
\82ð
\89ó
\82µ
\82½", "
\8eK
\82Ñ
\82³
\82¹
\82½", "
\95\85\82ç
\82¹
\82½", "
\8f\9d\82Â
\82¯
\82½"
697 /* possibly bill for an object which the player has just modified */
699 costly_alteration(obj, alter_type)
705 boolean learn_bknown;
706 #if 0 /*JP*//*
\8eg
\82í
\82È
\82¢*/
707 const char *those, *them;
709 struct monst *shkp = 0;
711 if (alter_type < 0 || alter_type >= SIZE(alteration_verbs)) {
712 impossible("invalid alteration type (%d)", alter_type);
716 ox = oy = 0; /* lint suppression */
717 objroom = '\0'; /* ditto */
718 if (carried(obj) || obj->where == OBJ_FREE) {
719 /* OBJ_FREE catches obj_no_longer_held()'s transformation
720 of crysknife back into worm tooth; the object has been
721 removed from inventory but not necessarily placed at
722 its new location yet--the unpaid flag will still be set
723 if this item is owned by a shop */
727 /* this get_obj_location shouldn't fail, but if it does,
728 use hero's location */
729 if (!get_obj_location(obj, &ox, &oy, CONTAINED_TOO))
730 ox = u.ux, oy = u.uy;
731 if (!costly_spot(ox, oy))
733 objroom = *in_rooms(ox, oy, SHOPBASE);
734 /* if no shop cares about it, we're done */
735 if (!billable(&shkp, obj, objroom, FALSE))
739 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
741 those = "that", them = "it";
743 those = "those", them = "them";
746 /* when shopkeeper describes the object as being uncursed or unblessed
747 hero will know that it is now uncursed; will also make the feedback
748 from `I x' after bill_dummy_object() be more specific for this item */
749 learn_bknown = (alter_type == COST_UNCURS || alter_type == COST_UNBLSS);
751 switch (obj->where) {
752 case OBJ_FREE: /* obj_no_longer_held() */
757 verbalize("You %s %s %s, you pay for %s!",
758 alteration_verbs[alter_type], those, simpleonames(obj),
761 verbalize("%s
\82ð%s
\82Ì
\82È
\82ç
\81C
\94\83\82Á
\82Ä
\82à
\82ç
\82¤
\82æ
\81I",
762 simpleonames(obj), alteration_verbs[alter_type]);
764 bill_dummy_object(obj);
768 obj->bknown = 1; /* ok to bypass set_bknown() here */
769 if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
771 verbalize("You %s %s, you pay for %s!",
772 alteration_verbs[alter_type], those, them);
774 verbalize("%s
\82Ì
\82È
\82ç
\81C
\94\83\82Á
\82Ä
\82à
\82ç
\82¤
\82æ
\81I",
775 alteration_verbs[alter_type]);
777 bill_dummy_object(obj);
779 (void) stolen_value(obj, ox, oy, FALSE, FALSE);
785 static const char dknowns[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
786 SCROLL_CLASS, GEM_CLASS, SPBOOK_CLASS,
787 WEAPON_CLASS, TOOL_CLASS, 0 };
789 /* mksobj(): create a specific type of object; result it always non-Null */
791 mksobj(otyp, init, artif)
798 char let = objects[otyp].oc_class;
802 otmp->age = monstermoves;
803 otmp->o_id = context.ident++;
805 otmp->o_id = context.ident++; /* ident overflowed */
809 otmp->where = OBJ_FREE;
810 otmp->dknown = index(dknowns, let) ? 0 : 1;
811 if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD)
812 || otmp->otyp == SHIELD_OF_REFLECTION
813 || objects[otmp->otyp].oc_merge)
815 if (!objects[otmp->otyp].oc_uses_known)
819 otmp->corpsenm = NON_PM;
824 otmp->quan = is_multigen(otmp) ? (long) rn1(6, 6) : 1L;
827 otmp->blessed = rn2(2);
828 } else if (!rn2(10)) {
832 blessorcurse(otmp, 10);
833 if (is_poisonable(otmp) && !rn2(100))
836 if (artif && !rn2(20))
837 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
841 switch (otmp->otyp) {
843 /* possibly overridden by mkcorpstat() */
846 otmp->corpsenm = undead_to_corpse(rndmonnum());
847 while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE)
850 /* perhaps rndmonnum() only wants to make G_NOCORPSE
851 monsters on this level; create an adventurer's
852 corpse instead, then */
853 otmp->corpsenm = PM_HUMAN;
855 /* timer set below */
858 otmp->corpsenm = NON_PM; /* generic egg */
860 for (tryct = 200; tryct > 0; --tryct) {
861 mndx = can_be_hatched(rndmonnum());
862 if (mndx != NON_PM && !dead_species(mndx, TRUE)) {
863 otmp->corpsenm = mndx; /* typed egg */
867 /* timer set below */
870 otmp->corpsenm = NON_PM; /* empty (so far) */
872 set_tin_variety(otmp, SPINACH_TIN);
874 for (tryct = 200; tryct > 0; --tryct) {
875 mndx = undead_to_corpse(rndmonnum());
876 if (mons[mndx].cnutrit
877 && !(mvitals[mndx].mvflags & G_NOCORPSE)) {
878 otmp->corpsenm = mndx;
879 set_tin_variety(otmp, RANDOM_TIN);
883 blessorcurse(otmp, 10);
886 otmp->spe = context.current_fruit;
887 flags.made_fruit = TRUE;
890 otmp->quan = (long) rnd(2);
893 if (Is_pudding(otmp)) {
894 otmp->quan = 1L; /* for emphasis; glob quantity is always 1 */
896 otmp->known = otmp->dknown = 1;
897 otmp->corpsenm = PM_GRAY_OOZE
898 + (otmp->otyp - GLOB_OF_GRAY_OOZE);
900 if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
901 && otmp->otyp != KELP_FROND && !rn2(6)) {
907 otmp->corpsenm = 0; /* LOADSTONE hack */
908 if (otmp->otyp == LOADSTONE)
910 else if (otmp->otyp == ROCK)
911 otmp->quan = (long) rn1(6, 6);
912 else if (otmp->otyp != LUCKSTONE && !rn2(6))
918 switch (otmp->otyp) {
922 otmp->age = 20L * /* 400 or 200 */
923 (long) objects[otmp->otyp].oc_cost;
925 otmp->quan = 1L + (long) (rn2(2) ? rn2(7) : 0);
926 blessorcurse(otmp, 5);
931 otmp->age = (long) rn1(500, 1000);
933 blessorcurse(otmp, 5);
938 blessorcurse(otmp, 2);
942 otmp->olocked = !!(rn2(5));
943 otmp->otrapped = !(rn2(10));
951 case EXPENSIVE_CAMERA:
954 otmp->spe = rn1(70, 30);
958 blessorcurse(otmp, 10);
962 blessorcurse(otmp, 2);
971 otmp->corpsenm = rndmonnum();
972 while (is_human(&mons[otmp->corpsenm]) && tryct++ < 30);
973 blessorcurse(otmp, 4);
975 case BELL_OF_OPENING:
982 case DRUM_OF_EARTHQUAKE:
983 otmp->spe = rn1(5, 4);
988 if (otmp->otyp == AMULET_OF_YENDOR)
989 context.made_amulet = TRUE;
990 if (rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION
991 || otmp->otyp == AMULET_OF_CHANGE
992 || otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
995 blessorcurse(otmp, 10);
1001 case POTION_CLASS: /* note: potions get some additional init below */
1004 if (otmp->otyp != SCR_MAIL)
1006 blessorcurse(otmp, 4);
1009 otmp->spestudied = 0;
1010 blessorcurse(otmp, 17);
1014 && (otmp->otyp == FUMBLE_BOOTS
1015 || otmp->otyp == LEVITATION_BOOTS
1016 || otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT
1017 || otmp->otyp == GAUNTLETS_OF_FUMBLING || !rn2(11))) {
1019 otmp->spe = -rne(3);
1020 } else if (!rn2(10)) {
1021 otmp->blessed = rn2(2);
1024 blessorcurse(otmp, 10);
1025 if (artif && !rn2(40))
1026 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1027 /* simulate lacquered armor for samurai */
1028 if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL
1029 && (moves <= 1 || In_quest(&u.uz))) {
1031 /* optimizer bitfield bug */
1032 otmp->oerodeproof = 1;
1035 otmp->oerodeproof = otmp->rknown = 1;
1040 if (otmp->otyp == WAN_WISHING)
1044 rn1(5, (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
1045 blessorcurse(otmp, 17);
1046 otmp->recharged = 0; /* used to control recharging */
1049 if (objects[otmp->otyp].oc_charged) {
1050 blessorcurse(otmp, 3);
1052 if (rn2(10) && bcsign(otmp))
1053 otmp->spe = bcsign(otmp) * rne(3);
1055 otmp->spe = rn2(2) ? rne(3) : -rne(3);
1057 /* make useless +0 rings much less common */
1059 otmp->spe = rn2(4) - rn2(3);
1060 /* negative rings are usually cursed */
1061 if (otmp->spe < 0 && rn2(5))
1063 } else if (rn2(10) && (otmp->otyp == RIN_TELEPORTATION
1064 || otmp->otyp == RIN_POLYMORPH
1065 || otmp->otyp == RIN_AGGRAVATE_MONSTER
1066 || otmp->otyp == RIN_HUNGER || !rn2(9))) {
1071 switch (otmp->otyp) {
1073 /* possibly overridden by mkcorpstat() */
1074 otmp->corpsenm = rndmonnum();
1075 if (!verysmall(&mons[otmp->corpsenm])
1076 && rn2(level_difficulty() / 2 + 10) > 10)
1077 (void) add_to_container(otmp, mkobj(SPBOOK_CLASS, FALSE));
1081 break; /* do nothing */
1083 /* 3.6.3: this used to be impossible() followed by return 0
1084 but most callers aren't prepared to deal with Null result
1085 and cluttering them up to do so is pointless */
1086 panic("mksobj tried to make type %d, class %d.",
1087 (int) otmp->otyp, (int) objects[otmp->otyp].oc_class);
1092 /* some things must get done (corpsenm, timers) even if init = 0 */
1093 switch ((otmp->oclass == POTION_CLASS && otmp->otyp != POT_OIL)
1097 if (otmp->corpsenm == NON_PM) {
1098 otmp->corpsenm = undead_to_corpse(rndmonnum());
1099 if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE | G_GONE))
1100 otmp->corpsenm = urole.malenum;
1105 if (otmp->corpsenm == NON_PM)
1106 otmp->corpsenm = rndmonnum();
1110 set_corpsenm(otmp, otmp->corpsenm);
1113 otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
1115 case POT_WATER: /* POTION_CLASS */
1116 otmp->fromsink = 0; /* overloads corpsenm, which was set to NON_PM */
1119 otmp->leashmon = 0; /* overloads corpsenm, which was set to NON_PM */
1122 otmp->novelidx = -1; /* "none of the above"; will be changed */
1123 otmp = oname(otmp, noveltitle(&otmp->novelidx));
1127 /* unique objects may have an associated artifact entry */
1128 if (objects[otyp].oc_unique && !otmp->oartifact)
1129 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1130 otmp->owt = weight(otmp);
1135 * Several areas of the code made direct reassignments
1136 * to obj->corpsenm. Because some special handling is
1137 * required in certain cases, place that handling here
1138 * and call this routine in place of the direct assignment.
1140 * If the object was a lizard or lichen corpse:
1141 * - ensure that you don't end up with some
1142 * other corpse type which has no rot-away timer.
1144 * If the object was a troll corpse:
1145 * - ensure that you don't end up with some other
1146 * corpse type which resurrects from the dead.
1148 * Re-calculates the weight of figurines and corpses to suit the
1151 * Existing timeout value for egg hatch is preserved.
1155 set_corpsenm(obj, id)
1162 if (obj->otyp == EGG)
1163 when = stop_timer(HATCH_EGG, obj_to_any(obj));
1166 obj_stop_timers(obj); /* corpse or figurine */
1170 switch (obj->otyp) {
1172 start_corpse_timeout(obj);
1173 obj->owt = weight(obj);
1176 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE)
1177 && (carried(obj) || mcarried(obj)))
1178 attach_fig_transform_timeout(obj);
1179 obj->owt = weight(obj);
1182 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
1183 attach_egg_hatch_timeout(obj, when);
1185 default: /* tin, etc. */
1186 obj->owt = weight(obj);
1192 * Start a corpse decay or revive timer.
1193 * This takes the age of the corpse into consideration as of 3.4.0.
1196 start_corpse_timeout(body)
1199 long when; /* rot away when this old */
1200 long corpse_age; /* age of corpse */
1204 #define TAINT_AGE (50L) /* age when corpses go bad */
1205 #define TROLL_REVIVE_CHANCE 37 /* 1/37 chance for 50 turns ~ 75% chance */
1206 #define ROT_AGE (250L) /* age when corpses rot away */
1208 /* lizards and lichen don't rot or revive */
1209 if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN)
1212 action = ROT_CORPSE; /* default action: rot away */
1213 rot_adjust = in_mklev ? 25 : 10; /* give some variation */
1214 corpse_age = monstermoves - body->age;
1215 if (corpse_age > ROT_AGE)
1218 when = ROT_AGE - corpse_age;
1219 when += (long) (rnz(rot_adjust) - rot_adjust);
1221 if (is_rider(&mons[body->corpsenm])) {
1223 * Riders always revive. They have a 1/3 chance per turn
1224 * of reviving after 12 turns. Always revive by 500.
1226 action = REVIVE_MON;
1227 for (when = 12L; when < 500L; when++)
1231 } else if (mons[body->corpsenm].mlet == S_TROLL && !body->norevive) {
1233 for (age = 2; age <= TAINT_AGE; age++)
1234 if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */
1235 action = REVIVE_MON;
1243 (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
1247 maybe_adjust_light(obj, old_range)
1253 int new_range = arti_light_radius(obj), delta = new_range - old_range;
1255 /* radius of light emitting artifact varies by curse/bless state
1256 so will change after blessing or cursing */
1258 obj_adjust_light_radius(obj, new_range);
1259 /* simplifying assumptions: hero is wielding this object;
1260 artifacts have to be in use to emit light and monsters'
1261 gear won't change bless or curse state */
1262 if (!Blind && get_obj_location(obj, &ox, &oy, 0)) {
1264 if (iflags.last_msg == PLNMSG_OBJ_GLOWS)
1265 /* we just saw "The <obj> glows <color>." from dipping */
1267 Strcpy(buf, (obj->quan == 1L) ? "It" : "They");
1269 Strcpy(buf, "
\82»
\82ê");
1271 else if (carried(obj) || cansee(ox, oy))
1272 Strcpy(buf, Yname2(obj));
1274 /* initial activation says "dimly" if cursed,
1275 "brightly" if uncursed, and "brilliantly" if blessed;
1276 when changing intensity, using "less brightly" is
1277 straightforward for dimming, but we need "brighter"
1278 rather than "more brightly" for brightening; ugh */
1280 pline("%s %s %s%s.", buf, otense(obj, "shine"),
1281 (abs(delta) > 1) ? "much " : "",
1282 (delta > 0) ? "brighter" : "less brightly");
1284 pline("%s
\82Ì
\8bP
\82«
\82Í%s%s
\81D", buf,
1285 (abs(delta) > 1) ? "
\82©
\82È
\82è" : "",
1286 (delta > 0) ? "
\91\9d\82µ
\82½" : "
\8c¸
\82Á
\82½");
1294 * bless(), curse(), unbless(), uncurse() -- any relevant message
1295 * about glowing amber/black/&c should be delivered prior to calling
1296 * these routines to make the actual curse/bless state change.
1301 register struct obj *otmp;
1305 if (otmp->oclass == COIN_CLASS)
1308 old_light = arti_light_radius(otmp);
1311 if (carried(otmp) && confers_luck(otmp))
1313 else if (otmp->otyp == BAG_OF_HOLDING)
1314 otmp->owt = weight(otmp);
1315 else if (otmp->otyp == FIGURINE && otmp->timed)
1316 (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1318 maybe_adjust_light(otmp, old_light);
1324 register struct obj *otmp;
1329 old_light = arti_light_radius(otmp);
1331 if (carried(otmp) && confers_luck(otmp))
1333 else if (otmp->otyp == BAG_OF_HOLDING)
1334 otmp->owt = weight(otmp);
1336 maybe_adjust_light(otmp, old_light);
1341 register struct obj *otmp;
1343 unsigned already_cursed;
1346 if (otmp->oclass == COIN_CLASS)
1349 old_light = arti_light_radius(otmp);
1350 already_cursed = otmp->cursed;
1353 /* welded two-handed weapon interferes with some armor removal */
1354 if (otmp == uwep && bimanual(uwep))
1356 /* rules at top of wield.c state that twoweapon cannot be done
1357 with cursed alternate weapon */
1358 if (otmp == uswapwep && u.twoweap)
1360 /* some cursed items need immediate updating */
1361 if (carried(otmp) && confers_luck(otmp)) {
1363 } else if (otmp->otyp == BAG_OF_HOLDING) {
1364 otmp->owt = weight(otmp);
1365 } else if (otmp->otyp == FIGURINE) {
1366 if (otmp->corpsenm != NON_PM && !dead_species(otmp->corpsenm, TRUE)
1367 && (carried(otmp) || mcarried(otmp)))
1368 attach_fig_transform_timeout(otmp);
1369 } else if (otmp->oclass == SPBOOK_CLASS) {
1370 /* if book hero is reading becomes cursed, interrupt */
1371 if (!already_cursed)
1375 maybe_adjust_light(otmp, old_light);
1381 register struct obj *otmp;
1386 old_light = arti_light_radius(otmp);
1388 if (carried(otmp) && confers_luck(otmp))
1390 else if (otmp->otyp == BAG_OF_HOLDING)
1391 otmp->owt = weight(otmp);
1392 else if (otmp->otyp == FIGURINE && otmp->timed)
1393 (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1395 maybe_adjust_light(otmp, old_light);
1400 blessorcurse(otmp, chance)
1401 register struct obj *otmp;
1402 register int chance;
1404 if (otmp->blessed || otmp->cursed)
1419 register struct obj *otmp;
1421 return (!!otmp->blessed - !!otmp->cursed);
1424 /* set the object's bless/curse-state known flag */
1426 set_bknown(obj, onoff)
1428 unsigned onoff; /* 1 or 0 */
1430 if (obj->bknown != onoff) {
1431 obj->bknown = onoff;
1432 if (obj->where == OBJ_INVENT && moves > 1L)
1438 * Calculate the weight of the given object. This will recursively follow
1439 * and calculate the weight of any containers.
1441 * Note: It is possible to end up with an incorrect weight if some part
1442 * of the code messes with a contained object and doesn't update the
1443 * container's weight.
1447 register struct obj *obj;
1449 int wt = (int) objects[obj->otyp].oc_weight;
1451 /* glob absorpsion means that merging globs accumulates weight while
1452 quantity stays 1, so update 'wt' to reflect that, unless owt is 0,
1453 when we assume this is a brand new glob so use objects[].oc_weight */
1454 if (obj->globby && obj->owt > 0)
1456 if (Is_container(obj) || obj->otyp == STATUE) {
1457 struct obj *contents;
1458 register int cwt = 0;
1460 if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
1461 wt = (int) obj->quan * ((int) mons[obj->corpsenm].cwt * 3 / 2);
1463 for (contents = obj->cobj; contents; contents = contents->nobj)
1464 cwt += weight(contents);
1466 * The weight of bags of holding is calculated as the weight
1467 * of the bag plus the weight of the bag's contents modified
1470 * Bag status Weight of contents
1471 * ---------- ------------------
1473 * blessed x/4 [rounded up: (x+3)/4]
1474 * otherwise x/2 [rounded up: (x+1)/2]
1476 * The macro DELTA_CWT in pickup.c also implements these
1479 if (obj->otyp == BAG_OF_HOLDING)
1480 cwt = obj->cursed ? (cwt * 2) : obj->blessed ? ((cwt + 3) / 4)
1485 if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
1486 long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
1488 wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int) long_wt;
1490 wt = eaten_stat(wt, obj);
1492 } else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
1493 return eaten_stat((int) obj->quan * wt, obj);
1494 } else if (obj->oclass == COIN_CLASS) {
1495 return (int) ((obj->quan + 50L) / 100L);
1496 } else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) {
1497 return (int) obj->owt; /* kludge for "very" heavy iron ball */
1498 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->spe) {
1499 return wt + obj->spe * (int) objects[TALLOW_CANDLE].oc_weight;
1501 return (wt ? wt * (int) obj->quan : ((int) obj->quan + 1) >> 1);
1504 static int treefruits[] = { APPLE, ORANGE, PEAR, BANANA, EUCALYPTUS_LEAF };
1506 /* called when a tree is kicked; never returns Null */
1508 rnd_treefruit_at(x, y)
1511 return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
1514 /* create a stack of N gold pieces; never returns Null */
1516 mkgold(amount, x, y)
1520 struct obj *gold = g_at(x, y);
1523 long mul = rnd(30 / max(12-depth(&u.uz), 2));
1525 amount = (long) (1 + rnd(level_difficulty() + 2) * mul);
1528 gold->quan += amount;
1530 gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
1531 gold->quan = amount;
1533 gold->owt = weight(gold);
1537 /* return TRUE if the corpse has special timing;
1538 lizards and lichen don't rot, trolls and Riders auto-revive */
1539 #define special_corpse(num) \
1540 (((num) == PM_LIZARD || (num) == PM_LICHEN) \
1541 || (mons[num].mlet == S_TROLL || is_rider(&mons[num])))
1543 /* mkcorpstat: make a corpse or statue; never returns Null.
1545 * OEXTRA note: Passing mtmp causes mtraits to be saved
1546 * even if ptr passed as well, but ptr is always used for
1547 * the corpse type (corpsenm). That allows the corpse type
1548 * to be different from the original monster,
1549 * i.e. vampire -> human corpse
1550 * yet still allow restoration of the original monster upon
1554 mkcorpstat(objtype, mtmp, ptr, x, y, corpstatflags)
1555 int objtype; /* CORPSE or STATUE */
1557 struct permonst *ptr;
1559 unsigned corpstatflags;
1562 boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
1564 if (objtype != CORPSE && objtype != STATUE)
1565 impossible("making corpstat type %d", objtype);
1566 if (x == 0 && y == 0) { /* special case - random placement */
1567 otmp = mksobj(objtype, init, FALSE);
1570 otmp = mksobj_at(objtype, x, y, init, FALSE);
1573 /* when 'mtmp' is non-null save the monster's details with the
1574 corpse or statue; it will also force the 'ptr' override below */
1576 /* save_mtraits updates otmp->oextra->omonst in place */
1577 (void) save_mtraits(otmp, mtmp);
1583 /* when 'ptr' is non-null it comes from our caller or from 'mtmp';
1584 override mkobjs()'s initialization of a random monster type */
1586 int old_corpsenm = otmp->corpsenm;
1588 otmp->corpsenm = monsndx(ptr);
1589 otmp->owt = weight(otmp);
1590 if (otmp->otyp == CORPSE && (special_corpse(old_corpsenm)
1591 || special_corpse(otmp->corpsenm))) {
1592 obj_stop_timers(otmp);
1593 start_corpse_timeout(otmp);
1600 * Return the type of monster that this corpse will
1601 * revive as, even if it has a monster structure
1602 * attached to it. In that case, you can't just
1603 * use obj->corpsenm, because the stored monster
1604 * type can, and often is, different.
1605 * The return value is an index into mons[].
1608 corpse_revive_type(obj)
1611 int revivetype = obj->corpsenm;
1614 if (has_omonst(obj) && ((mtmp = get_mtraits(obj, FALSE)) != 0)) {
1615 /* mtmp is a temporary pointer to a monster's stored
1616 attributes, not a real monster */
1617 revivetype = mtmp->mnum;
1623 * Attach a monster id to an object, to provide
1624 * a lasting association between the two.
1627 obj_attach_mid(obj, mid)
1632 return (struct obj *) 0;
1639 save_mtraits(obj, mtmp)
1644 forget_temple_entry(mtmp); /* EPRI() */
1645 if (!has_omonst(obj))
1647 if (has_omonst(obj)) {
1648 struct monst *mtmp2 = OMONST(obj);
1651 mtmp2->mextra = (struct mextra *) 0;
1653 mtmp2->mnum = monsndx(mtmp->data);
1654 /* invalidate pointers */
1655 /* m_id is needed to know if this is a revived quest leader */
1656 /* but m_id must be cleared when loading bones */
1657 mtmp2->nmon = (struct monst *) 0;
1658 mtmp2->data = (struct permonst *) 0;
1659 mtmp2->minvent = (struct obj *) 0;
1661 copy_mextra(mtmp2, mtmp);
1666 /* returns a pointer to a new monst structure based on
1667 * the one contained within the obj.
1670 get_mtraits(obj, copyof)
1674 struct monst *mtmp = (struct monst *) 0;
1675 struct monst *mnew = (struct monst *) 0;
1677 if (has_omonst(obj))
1683 mnew->mextra = (struct mextra *) 0;
1685 copy_mextra(mnew, mtmp);
1687 /* Never insert this returned pointer into mon chains! */
1694 /* make an object named after someone listed in the scoreboard file;
1695 never returns Null */
1697 mk_tt_object(objtype, x, y)
1698 int objtype; /* CORPSE or STATUE */
1702 boolean initialize_it;
1704 /* player statues never contain books */
1705 initialize_it = (objtype != STATUE);
1706 otmp = mksobj_at(objtype, x, y, initialize_it, FALSE);
1707 /* tt_oname() will return null if the scoreboard is empty;
1708 assigning an object name used to allocate a new obj but
1709 doesn't any more so we can safely ignore the return value */
1710 (void) tt_oname(otmp);
1715 /* make a new corpse or statue, uninitialized if a statue (i.e. no books);
1716 never returns Null */
1718 mk_named_object(objtype, ptr, x, y, nm)
1719 int objtype; /* CORPSE or STATUE */
1720 struct permonst *ptr;
1725 unsigned corpstatflags = (objtype != STATUE) ? CORPSTAT_INIT
1728 otmp = mkcorpstat(objtype, (struct monst *) 0, ptr, x, y, corpstatflags);
1730 otmp = oname(otmp, nm);
1736 register struct obj *otmp;
1738 int otyp = otmp->otyp;
1739 int omat = objects[otyp].oc_material;
1741 /* Candles can be burned, but they're not flammable in the sense that
1742 * they can't get fire damage and it makes no sense for them to be
1745 if (Is_candle(otmp))
1748 if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
1751 return (boolean) ((omat <= WOOD && omat != LIQUID) || omat == PLASTIC);
1756 register struct obj *otmp;
1758 int otyp = otmp->otyp;
1760 return (boolean) (objects[otyp].oc_material <= WOOD
1761 && objects[otyp].oc_material != LIQUID);
1765 * These routines maintain the single-linked lists headed in level.objects[][]
1766 * and threaded through the nexthere fields in the object-instance structure.
1769 /* put the object at the given location */
1771 place_object(otmp, x, y)
1772 register struct obj *otmp;
1775 register struct obj *otmp2 = level.objects[x][y];
1777 if (!isok(x, y)) { /* validate location */
1778 void VDECL((*func), (const char *, ...)) PRINTF_F(1, 2);
1780 func = (x < 0 || y < 0 || x > COLNO - 1 || y > ROWNO - 1) ? panic
1782 (*func)("place_object: \"%s\" [%d] off map <%d,%d>",
1783 safe_typename(otmp->otyp), otmp->where, x, y);
1785 if (otmp->where != OBJ_FREE)
1786 panic("place_object: obj \"%s\" [%d] not free",
1787 safe_typename(otmp->otyp), otmp->where);
1789 obj_no_longer_held(otmp);
1790 if (otmp->otyp == BOULDER) {
1791 if (!otmp2 || otmp2->otyp != BOULDER)
1792 block_point(x, y); /* vision */
1795 /* non-boulder object goes under boulders so that map will show boulder
1796 here without display code needing to traverse pile chain to find one */
1797 if (otmp2 && otmp2->otyp == BOULDER && otmp->otyp != BOULDER) {
1798 /* 3.6.3: put otmp under last consecutive boulder rather than under
1799 just the first one; multiple boulders at same spot in new games
1800 will be consecutive due to this, ones in old games saved before
1801 this change might not be; can affect the map display if the top
1802 boulder is moved/removed by some means other than pushing */
1803 while (otmp2->nexthere && otmp2->nexthere->otyp == BOULDER)
1804 otmp2 = otmp2->nexthere;
1805 otmp->nexthere = otmp2->nexthere;
1806 otmp2->nexthere = otmp;
1808 /* put on top of current pile */
1809 otmp->nexthere = otmp2;
1810 level.objects[x][y] = otmp;
1813 /* set the new object's location */
1816 otmp->where = OBJ_FLOOR;
1818 /* add to floor chain */
1822 obj_timer_checks(otmp, x, y, 0);
1825 #define ROT_ICE_ADJUSTMENT 2 /* rotting on ice takes 2 times as long */
1827 /* If ice was affecting any objects correct that now
1828 * Also used for starting ice effects too. [zap.c]
1831 obj_ice_effects(x, y, do_buried)
1837 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) {
1839 obj_timer_checks(otmp, x, y, 0);
1842 for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
1843 if (otmp->ox == x && otmp->oy == y) {
1845 obj_timer_checks(otmp, x, y, 0);
1852 * Returns an obj->age for a corpse object on ice, that would be the
1853 * actual obj->age if the corpse had just been lifted from the ice.
1854 * This is useful when just using obj->age in a check or calculation because
1855 * rot timers pertaining to the object don't have to be stopped and
1859 peek_at_iced_corpse_age(otmp)
1862 long age, retval = otmp->age;
1864 if (otmp->otyp == CORPSE && otmp->on_ice) {
1865 /* Adjust the age; must be same as obj_timer_checks() for off ice*/
1866 age = monstermoves - otmp->age;
1867 retval += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
1869 "The %s age has ice modifications: otmp->age = %ld, returning %ld.",
1870 s_suffix(doname(otmp)), otmp->age, retval);
1871 debugpline1("Effective age of corpse: %ld.", monstermoves - retval);
1877 obj_timer_checks(otmp, x, y, force)
1880 int force; /* 0 = no force so do checks, <0 = force off, >0 force on */
1883 short action = ROT_CORPSE;
1884 boolean restart_timer = FALSE;
1885 boolean on_floor = (otmp->where == OBJ_FLOOR);
1886 boolean buried = (otmp->where == OBJ_BURIED);
1888 /* Check for corpses just placed on or in ice */
1889 if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x, y)) {
1890 tleft = stop_timer(action, obj_to_any(otmp));
1892 action = REVIVE_MON;
1893 tleft = stop_timer(action, obj_to_any(otmp));
1898 /* mark the corpse as being on ice */
1900 debugpline3("%s is now on ice at <%d,%d>.", The(xname(otmp)), x,
1902 /* Adjust the time remaining */
1903 tleft *= ROT_ICE_ADJUSTMENT;
1904 restart_timer = TRUE;
1905 /* Adjust the age; time spent off ice needs to be multiplied
1906 by the ice adjustment and subtracted from the age so that
1907 later calculations behave as if it had been on ice during
1908 that time (longwinded way of saying this is the inverse
1909 of removing it from the ice and of peeking at its age). */
1910 age = monstermoves - otmp->age;
1911 otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
1914 /* Check for corpses coming off ice */
1915 } else if (force < 0 || (otmp->otyp == CORPSE && otmp->on_ice
1916 && !((on_floor || buried) && is_ice(x, y)))) {
1917 tleft = stop_timer(action, obj_to_any(otmp));
1919 action = REVIVE_MON;
1920 tleft = stop_timer(action, obj_to_any(otmp));
1926 debugpline3("%s is no longer on ice at <%d,%d>.",
1927 The(xname(otmp)), x, y);
1928 /* Adjust the remaining time */
1929 tleft /= ROT_ICE_ADJUSTMENT;
1930 restart_timer = TRUE;
1931 /* Adjust the age */
1932 age = monstermoves - otmp->age;
1933 otmp->age += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
1937 /* now re-start the timer with the appropriate modifications */
1939 (void) start_timer(tleft, TIMER_OBJECT, action, obj_to_any(otmp));
1942 #undef ROT_ICE_ADJUSTMENT
1946 register struct obj *otmp;
1951 if (otmp->where != OBJ_FLOOR)
1952 panic("remove_object: obj not on floor");
1953 extract_nexthere(otmp, &level.objects[x][y]);
1954 extract_nobj(otmp, &fobj);
1955 /* update vision iff this was the only boulder at its spot */
1956 if (otmp->otyp == BOULDER && !sobj_at(BOULDER, x, y))
1957 unblock_point(x, y); /* vision */
1959 obj_timer_checks(otmp, x, y, 0);
1962 /* throw away all of a monster's inventory */
1964 discard_minvent(mtmp)
1967 struct obj *otmp, *mwep = MON_WEP(mtmp);
1968 boolean keeping_mon = (!DEADMONSTER(mtmp));
1970 while ((otmp = mtmp->minvent) != 0) {
1971 /* this has now become very similar to m_useupall()... */
1972 obj_extract_self(otmp);
1973 if (otmp->owornmask) {
1976 mwepgone(mtmp), mwep = 0;
1977 mtmp->misc_worn_check &= ~otmp->owornmask;
1978 update_mon_intrinsics(mtmp, otmp, FALSE, TRUE);
1980 otmp->owornmask = 0L; /* obfree() expects this */
1982 obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */
1987 * Free obj from whatever list it is on in preparation for deleting it
1988 * or moving it elsewhere; obj->where will end up set to OBJ_FREE.
1989 * Doesn't handle unwearing of objects in hero's or monsters' inventories.
1992 * OBJ_FREE not on any list
1993 * OBJ_FLOOR fobj, level.locations[][] chains (use remove_object)
1994 * OBJ_CONTAINED cobj chain of container object
1995 * OBJ_INVENT hero's invent chain (use freeinv)
1996 * OBJ_MINVENT monster's invent chain
1997 * OBJ_MIGRATING migrating chain
1998 * OBJ_BURIED level.buriedobjs chain
1999 * OBJ_ONBILL on billobjs chain
2002 obj_extract_self(obj)
2005 switch (obj->where) {
2012 extract_nobj(obj, &obj->ocontainer->cobj);
2013 container_weight(obj->ocontainer);
2014 obj->ocontainer = (struct obj *) 0; /* clear stale back-link */
2020 extract_nobj(obj, &obj->ocarry->minvent);
2021 obj->ocarry = (struct monst *) 0; /* clear stale back-link */
2024 extract_nobj(obj, &migrating_objs);
2027 extract_nobj(obj, &level.buriedobjlist);
2030 extract_nobj(obj, &billobjs);
2033 panic("obj_extract_self");
2038 /* Extract the given object from the chain, following nobj chain. */
2040 extract_nobj(obj, head_ptr)
2041 struct obj *obj, **head_ptr;
2043 struct obj *curr, *prev;
2046 for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) {
2049 prev->nobj = curr->nobj;
2051 *head_ptr = curr->nobj;
2056 panic("extract_nobj: object lost");
2057 obj->where = OBJ_FREE;
2058 obj->nobj = (struct obj *) 0;
2062 * Extract the given object from the chain, following nexthere chain.
2064 * This does not set obj->where, this function is expected to be called
2065 * in tandem with extract_nobj, which does set it.
2068 extract_nexthere(obj, head_ptr)
2069 struct obj *obj, **head_ptr;
2071 struct obj *curr, *prev;
2074 for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) {
2077 prev->nexthere = curr->nexthere;
2079 *head_ptr = curr->nexthere;
2084 panic("extract_nexthere: object lost");
2085 obj->nexthere = (struct obj *) 0;
2089 * Add obj to mon's inventory. If obj is able to merge with something already
2090 * in the inventory, then the passed obj is deleted and 1 is returned.
2091 * Otherwise 0 is returned.
2094 add_to_minv(mon, obj)
2100 if (obj->where != OBJ_FREE)
2101 panic("add_to_minv: obj not free");
2103 /* merge if possible */
2104 for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
2105 if (merged(&otmp, &obj))
2106 return 1; /* obj merged and then free'd */
2107 /* else insert; don't bother forcing it to end of chain */
2108 obj->where = OBJ_MINVENT;
2110 obj->nobj = mon->minvent;
2112 return 0; /* obj on mon's inventory chain */
2116 * Add obj to container, make sure obj is "free". Returns (merged) obj.
2117 * The input obj may be deleted in the process.
2120 add_to_container(container, obj)
2121 struct obj *container, *obj;
2125 if (obj->where != OBJ_FREE)
2126 panic("add_to_container: obj not free");
2127 if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT)
2128 obj_no_longer_held(obj);
2130 /* merge if possible */
2131 for (otmp = container->cobj; otmp; otmp = otmp->nobj)
2132 if (merged(&otmp, &obj))
2135 obj->where = OBJ_CONTAINED;
2136 obj->ocontainer = container;
2137 obj->nobj = container->cobj;
2138 container->cobj = obj;
2143 add_to_migration(obj)
2146 if (obj->where != OBJ_FREE)
2147 panic("add_to_migration: obj not free");
2149 /* lock picking context becomes stale if it's for this object */
2150 if (Is_container(obj))
2151 maybe_reset_pick(obj);
2153 obj->where = OBJ_MIGRATING;
2154 obj->nobj = migrating_objs;
2155 migrating_objs = obj;
2162 if (obj->where != OBJ_FREE)
2163 panic("add_to_buried: obj not free");
2165 obj->where = OBJ_BURIED;
2166 obj->nobj = level.buriedobjlist;
2167 level.buriedobjlist = obj;
2170 /* Recalculate the weight of this container and all of _its_ containers. */
2172 container_weight(container)
2173 struct obj *container;
2175 container->owt = weight(container);
2176 if (container->where == OBJ_CONTAINED)
2177 container_weight(container->ocontainer);
2179 else if (container->where == OBJ_INVENT)
2180 recalculate load delay here ???
2185 * Deallocate the object. _All_ objects should be run through here for
2186 * them to be deallocated.
2192 if (obj->where != OBJ_FREE)
2193 panic("dealloc_obj: obj not free");
2195 panic("dealloc_obj with nobj");
2197 panic("dealloc_obj with cobj");
2199 /* free up any timers attached to the object */
2201 obj_stop_timers(obj);
2204 * Free up any light sources attached to the object.
2206 * We may want to just call del_light_source() without any
2207 * checks (requires a code change there). Otherwise this
2208 * list must track all objects that can have a light source
2209 * attached to it (and also requires lamplit to be set).
2211 if (obj_sheds_light(obj))
2212 del_light_source(LS_OBJECT, obj_to_any(obj));
2214 if (obj == thrownobj)
2216 if (obj == kickedobj)
2220 dealloc_oextra(obj);
2221 free((genericptr_t) obj);
2224 /* create an object from a horn of plenty; mirrors bagotricks(makemon.c) */
2226 hornoplenty(horn, tipping)
2228 boolean tipping; /* caller emptying entire contents; affects shop handling */
2232 if (!horn || horn->otyp != HORN_OF_PLENTY) {
2233 impossible("bad horn o' plenty");
2234 } else if (horn->spe < 1) {
2235 pline1(nothing_happens);
2240 consume_obj_charge(horn, !tipping);
2242 obj = mkobj(POTION_CLASS, FALSE);
2243 if (objects[obj->otyp].oc_magic)
2245 obj->otyp = rnd_class(POT_BOOZE, POT_WATER);
2246 } while (obj->otyp == POT_SICKNESS);
2248 what = (obj->quan > 1L) ? "Some potions" : "A potion";
2252 obj = mkobj(FOOD_CLASS, FALSE);
2253 if (obj->otyp == FOOD_RATION && !rn2(7))
2254 obj->otyp = LUMP_OF_ROYAL_JELLY;
2258 what = "
\90H
\82×
\95¨";
2262 pline("%s %s out.", what, vtense(what, "spill"));
2264 pline("%s
\82ª
\94ò
\82Ñ
\8fo
\82Ä
\82«
\82½
\81D", what);
2265 obj->blessed = horn->blessed;
2266 obj->cursed = horn->cursed;
2267 obj->owt = weight(obj);
2268 /* using a shop's horn of plenty entails a usage fee and also
2269 confers ownership of the created item to the shopkeeper */
2271 addtobill(obj, FALSE, FALSE, tipping);
2272 /* if it ended up on bill, we don't want "(unpaid, N zorkids)"
2273 being included in its formatted name during next message */
2274 iflags.suppress_price++;
2277 obj = hold_another_object(obj,
2279 ? "Oops! %s out of your reach!"
2280 : (Is_airlevel(&u.uz)
2281 || Is_waterlevel(&u.uz)
2282 || levl[u.ux][u.uy].typ < IRONBARS
2283 || levl[u.ux][u.uy].typ >= ICE)
2284 ? "Oops! %s away from you!"
2285 : "Oops! %s to the floor!",
2286 The(aobjnam(obj, "slip")), (char *) 0);
2288 obj = hold_another_object(obj,
2290 ? "
\82¨
\82Á
\82Æ
\81I%s
\82Í
\93Í
\82©
\82È
\82¢
\81I"
2291 : (Is_airlevel(&u.uz)
2292 || Is_waterlevel(&u.uz)
2293 || levl[u.ux][u.uy].typ < IRONBARS
2294 || levl[u.ux][u.uy].typ >= ICE)
2295 ? "
\82¨
\82Á
\82Æ
\81I%s
\82Í
\82 \82È
\82½
\82Ì
\8eè
\82©
\82ç
\8a\8a\82è
\97\8e\82¿
\82½
\81I"
2296 : "
\82¨
\82Á
\82Æ
\81I%s
\82Í
\8f°
\82É
\8a\8a\82è
\97\8e\82¿
\82½
\81I",
2297 xname(obj), (char *)0);
2301 /* assumes this is taking place at hero's location */
2302 if (!can_reach_floor(TRUE)) {
2303 hitfloor(obj, TRUE); /* does altar check, message, drop */
2305 if (IS_ALTAR(levl[u.ux][u.uy].typ))
2306 doaltarobj(obj); /* does its own drop message */
2309 pline("%s %s to the %s.", Doname2(obj),
2310 otense(obj, "drop"), surface(u.ux, u.uy));
2312 pline("%s
\82Í%s
\82É
\97\8e\82¿
\82½
\81D", Doname2(obj),
2313 surface(u.ux, u.uy));
2318 iflags.suppress_price--;
2320 makeknown(HORN_OF_PLENTY);
2325 /* support for wizard-mode's `sanity_check' option */
2327 static const char NEARDATA /* pline formats for insane_object() */
2328 ofmt0[] = "%s obj %s %s: %s",
2329 ofmt3[] = "%s [not null] %s %s: %s",
2330 /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
2331 mfmt1[] = "%s obj %s %s (%s)",
2332 mfmt2[] = "%s obj %s %s (%s) *not*";
2334 /* Check all object lists for consistency. */
2343 * Should check whether the obj->bypass and/or obj->nomerge bits
2344 * are set. Those are both used for temporary purposes and should
2345 * be clear between moves.
2348 objlist_sanity(fobj, OBJ_FLOOR, "floor sanity");
2350 /* check that the map's record of floor objects is consistent;
2351 those objects should have already been sanity checked via
2352 the floor list so container contents are skipped here */
2353 for (x = 0; x < COLNO; x++)
2354 for (y = 0; y < ROWNO; y++)
2355 for (obj = level.objects[x][y]; obj; obj = obj->nexthere) {
2356 /* <ox,oy> should match <x,y>; <0,*> should always be empty */
2357 if (obj->where != OBJ_FLOOR || x == 0
2358 || obj->ox != x || obj->oy != y) {
2361 Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
2362 x, y, obj->ox, obj->oy);
2363 insane_object(obj, at_fmt, "location sanity",
2364 (struct monst *) 0);
2368 objlist_sanity(invent, OBJ_INVENT, "invent sanity");
2369 objlist_sanity(migrating_objs, OBJ_MIGRATING, "migrating sanity");
2370 objlist_sanity(level.buriedobjlist, OBJ_BURIED, "buried sanity");
2371 objlist_sanity(billobjs, OBJ_ONBILL, "bill sanity");
2373 mon_obj_sanity(fmon, "minvent sanity");
2374 mon_obj_sanity(migrating_mons, "migrating minvent sanity");
2375 /* monsters temporarily in transit;
2376 they should have arrived with hero by the time we get called */
2378 impossible("mydogs sanity [not empty]");
2379 mon_obj_sanity(mydogs, "mydogs minvent sanity");
2382 /* objects temporarily freed from invent/floor lists;
2383 they should have arrived somewhere by the time we get called */
2385 insane_object(thrownobj, ofmt3, "thrownobj sanity",
2386 (struct monst *) 0);
2388 insane_object(kickedobj, ofmt3, "kickedobj sanity",
2389 (struct monst *) 0);
2390 /* current_wand isn't removed from invent while in use, but should
2391 be Null between moves when we're called */
2393 insane_object(current_wand, ofmt3, "current_wand sanity",
2394 (struct monst *) 0);
2397 /* sanity check for objects on specified list (fobj, &c) */
2399 objlist_sanity(objlist, wheretype, mesg)
2400 struct obj *objlist;
2406 for (obj = objlist; obj; obj = obj->nobj) {
2407 if (obj->where != wheretype)
2408 insane_object(obj, ofmt0, mesg, (struct monst *) 0);
2409 if (Has_contents(obj)) {
2410 if (wheretype == OBJ_ONBILL)
2411 /* containers on shop bill should always be empty */
2412 insane_object(obj, "%s obj contains something! %s %s: %s",
2413 mesg, (struct monst *) 0);
2414 check_contained(obj, mesg);
2416 if (obj->owornmask) {
2418 boolean bc_ok = FALSE;
2420 switch (obj->where) {
2423 sanity_check_worn(obj);
2426 /* migrating objects overload the owornmask field
2427 with a destination code; skip attempt to check it */
2430 /* note: ball and chain can also be OBJ_FREE, but not across
2431 turns so this sanity check shouldn't encounter that */
2435 if ((obj != uchain && obj != uball) || !bc_ok) {
2436 /* discovered an object not in inventory which
2437 erroneously has worn mask set */
2438 Sprintf(maskbuf, "worn mask 0x%08lx", obj->owornmask);
2439 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2444 check_glob(obj, mesg);
2449 /* sanity check for objects carried by all monsters in specified list */
2451 mon_obj_sanity(monlist, mesg)
2452 struct monst *monlist;
2456 struct obj *obj, *mwep;
2458 for (mon = monlist; mon; mon = mon->nmon) {
2459 if (DEADMONSTER(mon))
2461 mwep = MON_WEP(mon);
2463 if (!mcarried(mwep))
2464 insane_object(mwep, mfmt1, mesg, mon);
2465 if (mwep->ocarry != mon)
2466 insane_object(mwep, mfmt2, mesg, mon);
2468 for (obj = mon->minvent; obj; obj = obj->nobj) {
2469 if (obj->where != OBJ_MINVENT)
2470 insane_object(obj, mfmt1, mesg, mon);
2471 if (obj->ocarry != mon)
2472 insane_object(obj, mfmt2, mesg, mon);
2474 check_glob(obj, mesg);
2475 check_contained(obj, mesg);
2480 /* This must stay consistent with the defines in obj.h. */
2481 static const char *obj_state_names[NOBJ_STATES] = { "free", "floor",
2482 "contained", "invent",
2483 "minvent", "migrating",
2484 "buried", "onbill" };
2486 STATIC_OVL const char *
2490 static char unknown[32]; /* big enough to handle rogue 64-bit int */
2496 if (where < 0 || where >= NOBJ_STATES || !obj_state_names[where]) {
2497 Sprintf(unknown, "unknown[%d]", where);
2500 return obj_state_names[where];
2504 insane_object(obj, fmt, mesg, mon)
2506 const char *fmt, *mesg;
2509 const char *objnm, *monnm;
2512 objnm = monnm = "null!";
2514 iflags.override_ID++;
2515 objnm = doname(obj);
2516 iflags.override_ID--;
2518 if (mon || (strstri(mesg, "minvent") && !strstri(mesg, "contained"))) {
2519 Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)");
2521 monnm = x_monnam(mon, ARTICLE_A, (char *) 0, EXACT_NAME, TRUE);
2522 impossible(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2523 objnm, fmt_ptr((genericptr_t) mon), monnm);
2525 impossible(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2531 * Initialize a dummy obj with just enough info
2532 * to allow some of the tests in obj.h that
2533 * take an obj pointer to work.
2536 init_dummyobj(obj, otyp, oquan)
2544 obj->oclass = objects[otyp].oc_class;
2545 /* obj->dknown = 0; */
2546 /* suppress known except for amulets (needed for fakes & real AoY) */
2547 obj->known = (obj->oclass == AMULET_CLASS)
2549 /* default is "on" for types which don't use it */
2550 : !objects[otyp].oc_uses_known;
2551 obj->quan = oquan ? oquan : 1L;
2552 obj->corpsenm = NON_PM; /* suppress statue and figurine details */
2553 /* but suppressing fruit details leads to "bad fruit #0" */
2554 if (obj->otyp == SLIME_MOLD)
2555 obj->spe = context.current_fruit;
2560 /* obj sanity check: check objects inside container */
2562 check_contained(container, mesg)
2563 struct obj *container;
2567 /* big enough to work with, not too big to blow out stack in recursion */
2568 char mesgbuf[40], nestedmesg[120];
2570 if (!Has_contents(container))
2572 /* change "invent sanity" to "contained invent sanity"
2573 but leave "nested contained invent sanity" as is */
2574 if (!strstri(mesg, "contained"))
2575 mesg = strcat(strcpy(mesgbuf, "contained "), mesg);
2577 for (obj = container->cobj; obj; obj = obj->nobj) {
2578 /* catch direct cycle to avoid unbounded recursion */
2579 if (obj == container)
2580 panic("failed sanity check: container holds itself");
2581 if (obj->where != OBJ_CONTAINED)
2582 insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *) 0);
2583 else if (obj->ocontainer != container)
2584 impossible("%s obj %s in container %s, not %s", mesg,
2585 fmt_ptr((genericptr_t) obj),
2586 fmt_ptr((genericptr_t) obj->ocontainer),
2587 fmt_ptr((genericptr_t) container));
2589 check_glob(obj, mesg);
2591 if (Has_contents(obj)) {
2592 /* catch most likely indirect cycle; we won't notice if
2593 parent is present when something comes before it, or
2594 notice more deeply embedded cycles (grandparent, &c) */
2595 if (obj->cobj == container)
2596 panic("failed sanity check: container holds its parent");
2597 /* change "contained... sanity" to "nested contained... sanity"
2598 and "nested contained..." to "nested nested contained..." */
2599 Strcpy(nestedmesg, "nested ");
2600 copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg
2601 - (int) strlen(nestedmesg) - 1);
2602 /* recursively check contents */
2603 check_contained(obj, nestedmesg);
2608 /* called when 'obj->globby' is set so we don't recheck it here */
2610 check_glob(obj, mesg)
2614 #define LOWEST_GLOB GLOB_OF_GRAY_OOZE
2615 #define HIGHEST_GLOB GLOB_OF_BLACK_PUDDING
2616 if (obj->quan != 1L || obj->owt == 0
2617 || obj->otyp < LOWEST_GLOB || obj->otyp > HIGHEST_GLOB
2618 /* a partially eaten glob could have any non-zero weight but an
2619 intact one should weigh an exact multiple of base weight (20) */
2620 || ((obj->owt % objects[obj->otyp].oc_weight) != 0 && !obj->oeaten)) {
2621 char mesgbuf[BUFSZ], globbuf[QBUFSZ];
2623 Sprintf(globbuf, " glob %d,quan=%ld,owt=%u ",
2624 obj->otyp, obj->quan, obj->owt);
2625 mesg = strsubst(strcpy(mesgbuf, mesg), " obj ", globbuf);
2626 insane_object(obj, ofmt0, mesg,
2627 (obj->where == OBJ_MINVENT) ? obj->ocarry : 0);
2631 /* check an object in hero's or monster's inventory which has worn mask set */
2633 sanity_check_worn(obj)
2636 #if (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || defined(DEBUG)
2637 static unsigned long wearbits[] = {
2638 W_ARM, W_ARMC, W_ARMH, W_ARMS, W_ARMG, W_ARMF, W_ARMU,
2639 W_WEP, W_QUIVER, W_SWAPWEP, W_AMUL, W_RINGL, W_RINGR, W_TOOL,
2640 W_SADDLE, W_BALL, W_CHAIN, 0
2641 /* [W_ART,W_ARTI are property bits for items which aren't worn] */
2645 unsigned long owornmask, allmask = 0L;
2646 boolean embedded = FALSE;
2649 /* use owornmask for testing and bit twiddling, but use original
2650 obj->owornmask for printing */
2651 owornmask = obj->owornmask;
2652 /* figure out how many bits are set, and also which are viable */
2653 for (i = 0; wearbits[i]; ++i) {
2654 if ((owornmask & wearbits[i]) != 0L)
2656 allmask |= wearbits[i];
2659 /* embedded dragon scales have an extra bit set;
2660 make sure it's set, then suppress it */
2662 if ((owornmask & (W_ARM | I_SPECIAL)) == (W_ARM | I_SPECIAL))
2663 owornmask &= ~I_SPECIAL;
2665 n = 0, owornmask = ~0; /* force insane_object("bogus") below */
2667 if (n == 2 && carried(obj)
2668 && obj == uball && (owornmask & W_BALL) != 0L
2669 && (owornmask & W_WEAPONS) != 0L) {
2670 /* chained ball can be wielded/alt-wielded/quivered; if so,
2671 pretend it's not chained in order to check the weapon pointer
2672 (we've already verified the ball pointer by successfully passing
2673 the if-condition to get here...) */
2674 owornmask &= ~W_BALL;
2678 /* multiple bits set */
2679 Sprintf(maskbuf, "worn mask (multiple) 0x%08lx", obj->owornmask);
2680 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2682 if ((owornmask & ~allmask) != 0L
2683 || (carried(obj) && (owornmask & W_SADDLE) != 0L)) {
2684 /* non-wearable bit(s) set */
2685 Sprintf(maskbuf, "worn mask (bogus)) 0x%08lx", obj->owornmask);
2686 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2688 if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L)) {
2690 /* verify that obj in hero's invent (or ball/chain elsewhere)
2691 with owornmask of W_foo is the object pointed to by ufoo */
2692 switch (owornmask) {
2694 if (obj != (embedded ? uskin : uarm))
2695 what = embedded ? "skin" : "suit";
2723 what = "primary weapon";
2730 if (obj != uswapwep)
2731 what = u.twoweap ? "secondary weapon" : "alternate weapon";
2743 what = "right ring";
2749 /* case W_SADDLE: */
2762 Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what);
2763 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2766 if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L
2767 || mcarried(obj))) {
2768 /* check for items worn in invalid slots; practically anything can
2769 be wielded/alt-wielded/quivered, so tests on those are limited */
2771 if (owornmask & W_ARMOR) {
2772 if (obj->oclass != ARMOR_CLASS)
2774 /* 3.6: dragon scale mail reverts to dragon scales when
2775 becoming embedded in poly'd hero's skin */
2776 if (embedded && !Is_dragon_scales(obj))
2778 } else if (owornmask & W_WEAPONS) {
2779 /* monsters don't maintain alternate weapon or quiver */
2780 if (mcarried(obj) && (owornmask & (W_SWAPWEP | W_QUIVER)) != 0L)
2781 what = (owornmask & W_SWAPWEP) != 0L ? "monst alt weapon?"
2783 /* hero can quiver gold but not wield it (hence not alt-wield
2784 it either); also catches monster wielding gold */
2785 else if (obj->oclass == COIN_CLASS
2786 && (owornmask & (W_WEP | W_SWAPWEP)) != 0L)
2787 what = (owornmask & W_WEP) != 0L ? "weapon" : "alt weapon";
2788 } else if (owornmask & W_AMUL) {
2789 if (obj->oclass != AMULET_CLASS)
2791 } else if (owornmask & W_RING) {
2792 if (obj->oclass != RING_CLASS && obj->otyp != MEAT_RING)
2794 } else if (owornmask & W_TOOL) {
2795 if (obj->otyp != BLINDFOLD && obj->otyp != TOWEL
2796 && obj->otyp != LENSES)
2798 } else if (owornmask & W_BALL) {
2799 if (obj->oclass != BALL_CLASS)
2800 what = "chained ball";
2801 } else if (owornmask & W_CHAIN) {
2802 if (obj->oclass != CHAIN_CLASS)
2804 } else if (owornmask & W_SADDLE) {
2805 if (obj->otyp != SADDLE)
2809 char oclassname[30];
2810 struct monst *mon = mcarried(obj) ? obj->ocarry : 0;
2812 /* if we've found a potion worn in the amulet slot,
2813 this yields "worn (potion amulet)" */
2814 Strcpy(oclassname, def_oc_syms[(uchar) obj->oclass].name);
2815 Sprintf(maskbuf, "worn (%s %s)", makesingular(oclassname), what);
2816 insane_object(obj, ofmt0, maskbuf, mon);
2819 #else /* not (NH_DEVEL_STATUS != NH_STATUS_RELEASED) || DEBUG) */
2820 /* dummy use of obj to avoid "arg not used" complaint */
2822 insane_object(obj, ofmt0, "<null>", (struct monst *) 0);
2827 * wrapper to make "near this object" convenient
2834 impossible("obj_nexto: wasn't given an object to check");
2835 return (struct obj *) 0;
2837 return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
2841 * looks for objects of a particular type next to x, y
2842 * skips over oid if found (lets us avoid ourselves if
2843 * we're looking for a second type of an existing object)
2845 * TODO: return a list of all objects near us so we can more
2846 * reliably predict which one we want to 'find' first
2849 obj_nexto_xy(obj, x, y, recurs)
2855 int fx, fy, ex, ey, otyp = obj->otyp;
2858 /* check under our "feet" first */
2859 otmp = sobj_at(otyp, x, y);
2861 /* don't be clever and find ourselves */
2862 if (otmp != obj && mergable(otmp, obj))
2864 otmp = nxtobj(otmp, otyp, TRUE);
2868 return (struct obj *) 0;
2870 /* search in a random order */
2871 dx = (rn2(2) ? -1 : 1);
2872 dy = (rn2(2) ? -1 : 1);
2876 for (fx = ex; abs(fx - ex) < 3; fx += dx) {
2877 for (fy = ey; abs(fy - ey) < 3; fy += dy) {
2878 /* 0, 0 was checked above */
2879 if (isok(fx, fy) && (fx != x || fy != y)) {
2880 if ((otmp = obj_nexto_xy(obj, fx, fy, FALSE)) != 0)
2885 return (struct obj *) 0;
2889 * Causes one object to absorb another, increasing
2890 * weight accordingly. Frees obj2; obj1 remains and
2894 obj_absorb(obj1, obj2)
2895 struct obj **obj1, **obj2;
2897 struct obj *otmp1, *otmp2;
2901 /* don't let people dumb it up */
2905 if (otmp1 && otmp2 && otmp1 != otmp2) {
2906 globby_bill_fixup(otmp1, otmp2);
2907 if (otmp1->bknown != otmp2->bknown)
2908 otmp1->bknown = otmp2->bknown = 0;
2909 if (otmp1->rknown != otmp2->rknown)
2910 otmp1->rknown = otmp2->rknown = 0;
2911 if (otmp1->greased != otmp2->greased)
2912 otmp1->greased = otmp2->greased = 0;
2913 if (otmp1->orotten || otmp2->orotten)
2914 otmp1->orotten = otmp2->orotten = 1;
2915 o1wt = otmp1->oeaten ? otmp1->oeaten : otmp1->owt;
2916 o2wt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
2917 /* averaging the relative ages is less likely to overflow
2918 than averaging the absolute ages directly */
2919 agetmp = (((moves - otmp1->age) * o1wt
2920 + (moves - otmp2->age) * o2wt)
2922 otmp1->age = moves - agetmp; /* conv. relative back to absolute */
2924 if (otmp1->oeaten || otmp2->oeaten)
2925 otmp1->oeaten = o1wt + o2wt;
2927 obj_extract_self(otmp2);
2929 *obj2 = (struct obj *) 0;
2934 impossible("obj_absorb: not called with two actual objects");
2935 return (struct obj *) 0;
2939 * Causes the heavier object to absorb the lighter object in
2940 * most cases, but if one object is OBJ_FREE and the other is
2941 * on the floor, the floor object goes first.
2943 * wrapper for obj_absorb so that floor_effects works more
2944 * cleanly (since we don't know which we want to stay around)
2947 obj_meld(obj1, obj2)
2948 struct obj **obj1, **obj2;
2950 struct obj *otmp1, *otmp2, *result = 0;
2956 if (otmp1 && otmp2 && otmp1 != otmp2) {
2960 * If one of the objects is free because it's being dropped,
2961 * we should really finish a full drop and then absorb/meld
2962 * if it survives the flooreffects(). Then lighter-melds-into-
2963 * heavier will be true even when heavier is the one dropped.
2965 * [Also, what about when one of the globs is on the shore
2966 * and we drop the other into adjacent pool or vice versa?]
2968 if (!(otmp2->where == OBJ_FLOOR && otmp1->where == OBJ_FREE)
2969 && (otmp1->owt > otmp2->owt
2970 || (otmp1->owt == otmp2->owt && rn2(2)))) {
2971 if (otmp2->where == OBJ_FLOOR)
2972 ox = otmp2->ox, oy = otmp2->oy;
2973 result = obj_absorb(obj1, obj2);
2975 if (otmp1->where == OBJ_FLOOR)
2976 ox = otmp1->ox, oy = otmp1->oy;
2977 result = obj_absorb(obj2, obj1);
2979 /* callers really ought to take care of this; glob melding is
2980 a bookkeeping issue rather than a display one */
2981 if (ox && cansee(ox, oy))
2985 impossible("obj_meld: not called with two actual objects");
2990 /* give a message if hero notices two globs merging [used to be in pline.c] */
2992 pudding_merge_message(otmp, otmp2)
2996 boolean visible = (cansee(otmp->ox, otmp->oy)
2997 || cansee(otmp2->ox, otmp2->oy)),
2998 onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR),
2999 inpack = (carried(otmp) || carried(otmp2));
3001 /* the player will know something happened inside his own inventory */
3002 if ((!Blind && visible) || inpack) {
3003 if (Hallucination) {
3006 You_see("parts of the floor melting!");
3008 You_see("
\8f°
\82Ì
\88ê
\95\94\82ª
\97n
\82¯
\82Ä
\82¢
\82é
\82Ì
\82ð
\8c©
\82½
\81I");
3009 } else if (inpack) {
3011 Your("pack reaches out and grabs something!");
3013 Your("
\82©
\82Î
\82ñ
\82ª
\8eè
\82ð
\90L
\82Î
\82µ
\82Ä
\89½
\82©
\82ð
\82Â
\82©
\82ñ
\82¾
\81I");
3015 /* even though we can see where they should be,
3016 * they'll be out of our view (minvent or container)
3017 * so don't actually show anything */
3018 } else if (onfloor || inpack) {
3019 boolean adj = ((otmp->ox != u.ux || otmp->oy != u.uy)
3020 && (otmp2->ox != u.ux || otmp2->oy != u.uy));
3023 pline("The %s%s coalesce%s.",
3024 (onfloor && adj) ? "adjacent " : "",
3025 makeplural(obj_typename(otmp->otyp)),
3026 inpack ? " inside your pack" : "");
3028 pline("%s%s
\82ª%s
\8d\87\91Ì
\82µ
\82½
\81D",
3029 (onfloor && adj) ? "
\97×
\82Ì" : "",
3030 obj_typename(otmp->otyp),
3031 inpack ? "
\82 \82È
\82½
\82Ì
\82©
\82Î
\82ñ
\82Ì
\92\86\82Å" : "");
3036 You_hear("a faint sloshing sound.");
3038 You_hear("
\82©
\82·
\82©
\82È
\83o
\83V
\83\83\83o
\83V
\83\83\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");