1 /* NetHack 3.6 mkobj.c $NHDT-Date: 1518053380 2018/02/08 01:29:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.130 $ */
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 void FDECL(maybe_adjust_light, (struct obj *, int));
10 STATIC_DCL void FDECL(obj_timer_checks, (struct obj *,
11 XCHAR_P, XCHAR_P, int));
12 STATIC_DCL void FDECL(container_weight, (struct obj *));
13 STATIC_DCL struct obj *FDECL(save_mtraits, (struct obj *, struct monst *));
14 STATIC_DCL void FDECL(objlist_sanity, (struct obj *, int, const char *));
15 STATIC_DCL void FDECL(mon_obj_sanity, (struct monst *, const char *));
16 STATIC_DCL const char *FDECL(where_name, (struct obj *));
17 STATIC_DCL void FDECL(insane_object, (struct obj *, const char *,
18 const char *, struct monst *));
19 STATIC_DCL void FDECL(check_contained, (struct obj *, const char *));
20 STATIC_DCL void FDECL(sanity_check_worn, (struct obj *));
23 int iprob; /* probability of an item type */
24 char iclass; /* item class */
27 static const struct icp mkobjprobs[] = { { 10, WEAPON_CLASS },
37 { 1, AMULET_CLASS } };
39 static const struct icp boxiprobs[] = { { 18, GEM_CLASS },
47 { 1, AMULET_CLASS } };
49 static const struct icp rogueprobs[] = { { 12, WEAPON_CLASS },
57 static const struct icp hellprobs[] = { { 20, WEAPON_CLASS },
66 { 4, AMULET_CLASS } };
71 struct oextra *oextra;
73 oextra = (struct oextra *) alloc(sizeof(struct oextra));
86 struct oextra *x = o->oextra;
90 free((genericptr_t) x->oname);
92 free_omonst(o); /* 'o' rather than 'x' */
94 free((genericptr_t) x->omid);
96 free((genericptr_t) x->olong);
98 free((genericptr_t) x->omailcmd);
100 free((genericptr_t) x);
101 o->oextra = (struct oextra *) 0;
110 otmp->oextra = newoextra();
113 struct monst *m = newmonst();
125 struct monst *m = OMONST(otmp);
130 free((genericptr_t) m);
131 OMONST(otmp) = (struct monst *) 0;
141 otmp->oextra = newoextra();
143 OMID(otmp) = (unsigned *) alloc(sizeof (unsigned));
144 (void) memset((genericptr_t) OMID(otmp), 0, sizeof (unsigned));
152 if (otmp->oextra && OMID(otmp)) {
153 free((genericptr_t) OMID(otmp));
154 OMID(otmp) = (unsigned *) 0;
163 otmp->oextra = newoextra();
165 OLONG(otmp) = (long *) alloc(sizeof (long));
166 (void) memset((genericptr_t) OLONG(otmp), 0, sizeof (long));
174 if (otmp->oextra && OLONG(otmp)) {
175 free((genericptr_t) OLONG(otmp));
176 OLONG(otmp) = (long *) 0;
181 new_omailcmd(otmp, response_cmd)
183 const char *response_cmd;
186 otmp->oextra = newoextra();
189 OMAILCMD(otmp) = dupstr(response_cmd);
196 if (otmp->oextra && OMAILCMD(otmp)) {
197 free((genericptr_t) OMAILCMD(otmp));
198 OMAILCMD(otmp) = (char *) 0;
203 mkobj_at(let, x, y, artif)
210 otmp = mkobj(let, artif);
211 place_object(otmp, x, y);
216 mksobj_at(otyp, x, y, init, artif)
222 otmp = mksobj(otyp, init, artif);
223 place_object(otmp, x, y);
227 /* mkobj(): select a type of item from a class, use mksobj() to create it */
233 int tprob, i, prob = rnd(1000);
235 if (oclass == RANDOM_CLASS) {
236 const struct icp *iprobs = Is_rogue_level(&u.uz)
237 ? (const struct icp *) rogueprobs
238 : Inhell ? (const struct icp *) hellprobs
239 : (const struct icp *) mkobjprobs;
241 for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
243 oclass = iprobs->iclass;
246 i = bases[(int) oclass];
247 while ((prob -= objects[i].oc_prob) > 0)
250 if (objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
251 panic("probtype error, oclass=%d i=%d", (int) oclass, i);
253 return mksobj(i, TRUE, artif);
261 register struct obj *otmp;
263 box->cobj = (struct obj *) 0;
270 n = box->olocked ? 7 : 5;
273 n = box->olocked ? 5 : 3;
277 /* initial inventory: sack starts out empty */
278 if (moves <= 1 && !in_mklev) {
291 for (n = rn2(n + 1); n > 0; n--) {
292 if (box->otyp == ICE_BOX) {
293 if (!(otmp = mksobj(CORPSE, TRUE, TRUE)))
295 /* Note: setting age to 0 is correct. Age has a different
296 * from usual meaning for objects stored in ice boxes. -KAA
300 (void) stop_timer(ROT_CORPSE, obj_to_any(otmp));
301 (void) stop_timer(REVIVE_MON, obj_to_any(otmp));
305 const struct icp *iprobs = boxiprobs;
307 for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
309 if (!(otmp = mkobj(iprobs->iclass, TRUE)))
312 /* handle a couple of special cases */
313 if (otmp->oclass == COIN_CLASS) {
314 /* 2.5 x level's usual amount; weight adjusted below */
315 otmp->quan = (long) (rnd(level_difficulty() + 2) * rnd(75));
316 otmp->owt = weight(otmp);
318 while (otmp->otyp == ROCK) {
319 otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE);
322 otmp->owt = weight(otmp);
324 if (box->otyp == BAG_OF_HOLDING) {
328 otmp->owt = weight(otmp);
330 while (otmp->otyp == WAN_CANCELLATION)
331 otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
334 (void) add_to_container(box, otmp);
338 /* select a random, common monster type */
342 register struct permonst *ptr;
344 unsigned short excludeflags;
346 /* Plan A: get a level-appropriate common monster */
351 /* Plan B: get any common monster */
352 excludeflags = G_UNIQ | G_NOGEN | (Inhell ? G_NOHELL : G_HELL);
354 i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
356 } while ((ptr->geno & excludeflags) != 0);
362 copy_oextra(obj2, obj1)
363 struct obj *obj2, *obj1;
365 if (!obj2 || !obj1 || !obj1->oextra)
369 obj2->oextra = newoextra();
371 oname(obj2, ONAME(obj1));
372 if (has_omonst(obj1)) {
375 (void) memcpy((genericptr_t) OMONST(obj2),
376 (genericptr_t) OMONST(obj1), sizeof(struct monst));
377 OMONST(obj2)->mextra = (struct mextra *) 0;
378 OMONST(obj2)->nmon = (struct monst *) 0;
380 OMONST(obj2)->m_id = context.ident++;
381 if (OMONST(obj2)->m_id) /* ident overflowed */
382 OMONST(obj2)->m_id = context.ident++;
384 if (OMONST(obj1)->mextra)
385 copy_mextra(OMONST(obj2), OMONST(obj1));
387 if (has_omid(obj1)) {
390 (void) memcpy((genericptr_t) OMID(obj2), (genericptr_t) OMID(obj1),
393 if (has_olong(obj1)) {
396 (void) memcpy((genericptr_t) OLONG(obj2), (genericptr_t) OLONG(obj1),
399 if (has_omailcmd(obj1)) {
400 new_omailcmd(obj2, OMAILCMD(obj1));
405 * Split obj so that it gets size gets reduced by num. The quantity num is
406 * put in the object structure delivered by this call. The returned object
407 * has its wornmask cleared and is positioned just following the original
408 * in the nobj chain (and nexthere chain when on the floor).
417 if (obj->cobj || num <= 0L || obj->quan <= num)
418 panic("splitobj"); /* can't split containers */
420 *otmp = *obj; /* copies whole structure */
421 otmp->oextra = (struct oextra *) 0;
422 otmp->o_id = context.ident++;
424 otmp->o_id = context.ident++; /* ident overflowed */
425 otmp->timed = 0; /* not timed, yet */
426 otmp->lamplit = 0; /* ditto */
427 otmp->owornmask = 0L; /* new object isn't worn */
429 obj->owt = weight(obj);
431 otmp->owt = weight(otmp); /* -= obj->owt ? */
433 context.objsplit.parent_oid = obj->o_id;
434 context.objsplit.child_oid = otmp->o_id;
436 /* Only set nexthere when on the floor, nexthere is also used */
437 /* as a back pointer to the container object when contained. */
438 if (obj->where == OBJ_FLOOR)
439 obj->nexthere = otmp;
440 copy_oextra(otmp, obj);
442 free_omid(otmp); /* only one association with m_id*/
444 splitbill(obj, otmp);
446 obj_split_timers(obj, otmp);
447 if (obj_sheds_light(obj))
448 obj_split_light_source(obj, otmp);
452 /* try to find the stack obj was split from, then merge them back together;
453 returns the combined object if unsplit is successful, null otherwise */
458 unsigned target_oid = 0;
459 struct obj *oparent = 0, *ochild = 0, *list = 0;
462 * We don't operate on floor objects (we're following o->nobj rather
463 * than o->nexthere), on free objects (don't know which list to use when
464 * looking for obj's parent or child), on bill objects (too complicated,
465 * not needed), or on buried or migrating objects (not needed).
466 * [This could be improved, but at present additional generality isn't
469 switch (obj->where) {
476 return (struct obj *) 0;
481 list = obj->ocarry->minvent;
484 list = obj->ocontainer->cobj;
488 /* first try the expected case; obj is split from another stack */
489 if (obj->o_id == context.objsplit.child_oid) {
490 /* parent probably precedes child and will require list traversal */
492 target_oid = context.objsplit.parent_oid;
493 if (obj->nobj && obj->nobj->o_id == target_oid)
495 } else if (obj->o_id == context.objsplit.parent_oid) {
496 /* alternate scenario: another stack was split from obj;
497 child probably follows parent and will be found here */
499 target_oid = context.objsplit.child_oid;
500 if (obj->nobj && obj->nobj->o_id == target_oid)
503 /* if we have only half the split, scan obj's list to find other half */
504 if (ochild && !oparent) {
506 for (obj = list; obj; obj = obj->nobj)
507 if (obj->o_id == target_oid) {
511 } else if (oparent && !ochild) {
512 /* alternate scenario */
513 for (obj = list; obj; obj = obj->nobj)
514 if (obj->o_id == target_oid) {
519 /* if we have both parent and child, try to merge them;
520 if successful, return the combined stack, otherwise return null */
521 return (oparent && ochild && merged(&oparent, &ochild)) ? oparent : 0;
524 /* reset splitobj()/unsplitobj() context */
528 context.objsplit.parent_oid = context.objsplit.child_oid = 0;
532 * Insert otmp right after obj in whatever chain(s) it is on. Then extract
533 * obj from the chain(s). This function does a literal swap. It is up to
534 * the caller to provide a valid context for the swap. When done, obj will
535 * still exist, but not on any chain.
537 * Note: Don't use use obj_extract_self() -- we are doing an in-place swap,
538 * not actually moving something.
541 replace_object(obj, otmp)
545 otmp->where = obj->where;
546 switch (obj->where) {
551 otmp->nobj = obj->nobj;
553 extract_nobj(obj, &invent);
556 otmp->nobj = obj->nobj;
557 otmp->ocontainer = obj->ocontainer;
559 extract_nobj(obj, &obj->ocontainer->cobj);
562 otmp->nobj = obj->nobj;
563 otmp->ocarry = obj->ocarry;
565 extract_nobj(obj, &obj->ocarry->minvent);
568 otmp->nobj = obj->nobj;
569 otmp->nexthere = obj->nexthere;
573 obj->nexthere = otmp;
574 extract_nobj(obj, &fobj);
575 extract_nexthere(obj, &level.objects[obj->ox][obj->oy]);
578 panic("replace_object: obj position");
583 /* is 'obj' inside a container whose contents aren't known?
584 if so, return the outermost container meeting that criterium */
586 unknwn_contnr_contents(obj)
589 struct obj *result = 0, *parent;
591 while (obj->where == OBJ_CONTAINED) {
592 parent = obj->ocontainer;
601 * Create a dummy duplicate to put on shop bill. The duplicate exists
602 * only in the billobjs chain. This function is used when a shop object
603 * is being altered, and a copy of the original is needed for billing
604 * purposes. For example, when eating, where an interruption will yield
605 * an object which is different from what it started out as; the "I x"
606 * command needs to display the original object.
608 * The caller is responsible for checking otmp->unpaid and
609 * costly_spot(u.ux, u.uy). This function will make otmp no charge.
611 * Note that check_unpaid_usage() should be used instead for partial
612 * usage of an object.
615 bill_dummy_object(otmp)
616 register struct obj *otmp;
618 register struct obj *dummy;
622 cost = unpaid_cost(otmp, FALSE);
623 subfrombill(otmp, shop_keeper(*u.ushops));
627 dummy->oextra = (struct oextra *) 0;
628 dummy->where = OBJ_FREE;
629 dummy->o_id = context.ident++;
631 dummy->o_id = context.ident++; /* ident overflowed */
633 copy_oextra(dummy, otmp);
635 free_omid(dummy); /* only one association with m_id*/
636 if (Is_candle(dummy))
638 dummy->owornmask = 0L; /* dummy object is not worn */
639 addtobill(dummy, FALSE, TRUE, TRUE);
641 alter_cost(dummy, -cost);
642 /* no_charge is only valid for some locations */
644 (otmp->where == OBJ_FLOOR || otmp->where == OBJ_CONTAINED) ? 1 : 0;
649 /* alteration types; must match COST_xxx macros in hack.h */
650 static const char *const alteration_verbs[] = {
652 "cancel", "drain", "uncharge", "unbless", "uncurse", "disenchant",
653 "degrade", "dilute", "erase", "burn", "neutralize", "destroy", "splatter",
654 "bite", "open", "break the lock on", "rust", "rot", "tarnish"
656 "
\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½",
657 "
\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½",
658 "
\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½"
662 /* possibly bill for an object which the player has just modified */
664 costly_alteration(obj, alter_type)
671 #if 0 /*JP*//*
\8eg
\82í
\82È
\82¢*/
672 const char *those, *them;
674 struct monst *shkp = 0;
676 if (alter_type < 0 || alter_type >= SIZE(alteration_verbs)) {
677 impossible("invalid alteration type (%d)", alter_type);
681 ox = oy = 0; /* lint suppression */
682 objroom = '\0'; /* ditto */
683 if (carried(obj) || obj->where == OBJ_FREE) {
684 /* OBJ_FREE catches obj_no_longer_held()'s transformation
685 of crysknife back into worm tooth; the object has been
686 removed from inventory but not necessarily placed at
687 its new location yet--the unpaid flag will still be set
688 if this item is owned by a shop */
692 /* this get_obj_location shouldn't fail, but if it does,
693 use hero's location */
694 if (!get_obj_location(obj, &ox, &oy, CONTAINED_TOO))
695 ox = u.ux, oy = u.uy;
696 if (!costly_spot(ox, oy))
698 objroom = *in_rooms(ox, oy, SHOPBASE);
699 /* if no shop cares about it, we're done */
700 if (!billable(&shkp, obj, objroom, FALSE))
704 #if 0 /*JP*//*
\93ú
\96{
\8cê
\82Å
\82Í
\95s
\97v*/
706 those = "that", them = "it";
708 those = "those", them = "them";
711 /* when shopkeeper describes the object as being uncursed or unblessed
712 hero will know that it is now uncursed; will also make the feedback
713 from `I x' after bill_dummy_object() be more specific for this item */
714 set_bknown = (alter_type == COST_UNCURS || alter_type == COST_UNBLSS);
716 switch (obj->where) {
717 case OBJ_FREE: /* obj_no_longer_held() */
722 verbalize("You %s %s %s, you pay for %s!",
723 alteration_verbs[alter_type], those, simpleonames(obj),
726 verbalize("%s
\82ð%s
\82Ì
\82È
\82ç
\81C
\94\83\82Á
\82Ä
\82à
\82ç
\82¤
\82æ
\81I",
727 simpleonames(obj), alteration_verbs[alter_type]);
729 bill_dummy_object(obj);
734 if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
736 verbalize("You %s %s, you pay for %s!",
737 alteration_verbs[alter_type], those, them);
739 verbalize("%s
\82Ì
\82È
\82ç
\81C
\94\83\82Á
\82Ä
\82à
\82ç
\82¤
\82æ
\81I",
740 alteration_verbs[alter_type]);
742 bill_dummy_object(obj);
744 (void) stolen_value(obj, ox, oy, FALSE, FALSE);
750 static const char dknowns[] = { WAND_CLASS, RING_CLASS, POTION_CLASS,
751 SCROLL_CLASS, GEM_CLASS, SPBOOK_CLASS,
752 WEAPON_CLASS, TOOL_CLASS, 0 };
754 /* mksobj(): create a specific type of object */
756 mksobj(otyp, init, artif)
763 char let = objects[otyp].oc_class;
767 otmp->age = monstermoves;
768 otmp->o_id = context.ident++;
770 otmp->o_id = context.ident++; /* ident overflowed */
774 otmp->where = OBJ_FREE;
775 otmp->dknown = index(dknowns, let) ? 0 : 1;
776 if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD)
777 || otmp->otyp == SHIELD_OF_REFLECTION
778 || objects[otmp->otyp].oc_merge)
780 if (!objects[otmp->otyp].oc_uses_known)
784 otmp->corpsenm = NON_PM;
789 otmp->quan = is_multigen(otmp) ? (long) rn1(6, 6) : 1L;
792 otmp->blessed = rn2(2);
793 } else if (!rn2(10)) {
797 blessorcurse(otmp, 10);
798 if (is_poisonable(otmp) && !rn2(100))
801 if (artif && !rn2(20))
802 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
806 switch (otmp->otyp) {
808 /* possibly overridden by mkcorpstat() */
811 otmp->corpsenm = undead_to_corpse(rndmonnum());
812 while ((mvitals[otmp->corpsenm].mvflags & G_NOCORPSE)
815 /* perhaps rndmonnum() only wants to make G_NOCORPSE
816 monsters on this level; create an adventurer's
817 corpse instead, then */
818 otmp->corpsenm = PM_HUMAN;
820 /* timer set below */
823 otmp->corpsenm = NON_PM; /* generic egg */
825 for (tryct = 200; tryct > 0; --tryct) {
826 mndx = can_be_hatched(rndmonnum());
827 if (mndx != NON_PM && !dead_species(mndx, TRUE)) {
828 otmp->corpsenm = mndx; /* typed egg */
832 /* timer set below */
835 otmp->corpsenm = NON_PM; /* empty (so far) */
837 set_tin_variety(otmp, SPINACH_TIN);
839 for (tryct = 200; tryct > 0; --tryct) {
840 mndx = undead_to_corpse(rndmonnum());
841 if (mons[mndx].cnutrit
842 && !(mvitals[mndx].mvflags & G_NOCORPSE)) {
843 otmp->corpsenm = mndx;
844 set_tin_variety(otmp, RANDOM_TIN);
848 blessorcurse(otmp, 10);
851 otmp->spe = context.current_fruit;
852 flags.made_fruit = TRUE;
855 otmp->quan = (long) rnd(2);
858 if (Is_pudding(otmp)) {
860 otmp->known = otmp->dknown = 1;
861 otmp->corpsenm = PM_GRAY_OOZE
862 + (otmp->otyp - GLOB_OF_GRAY_OOZE);
864 if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
865 && otmp->otyp != KELP_FROND && !rn2(6)) {
871 otmp->corpsenm = 0; /* LOADSTONE hack */
872 if (otmp->otyp == LOADSTONE)
874 else if (otmp->otyp == ROCK)
875 otmp->quan = (long) rn1(6, 6);
876 else if (otmp->otyp != LUCKSTONE && !rn2(6))
882 switch (otmp->otyp) {
886 otmp->age = 20L * /* 400 or 200 */
887 (long) objects[otmp->otyp].oc_cost;
889 otmp->quan = 1L + (long) (rn2(2) ? rn2(7) : 0);
890 blessorcurse(otmp, 5);
895 otmp->age = (long) rn1(500, 1000);
897 blessorcurse(otmp, 5);
902 blessorcurse(otmp, 2);
906 otmp->olocked = !!(rn2(5));
907 otmp->otrapped = !(rn2(10));
915 case EXPENSIVE_CAMERA:
918 otmp->spe = rn1(70, 30);
922 blessorcurse(otmp, 10);
926 blessorcurse(otmp, 2);
935 otmp->corpsenm = rndmonnum();
936 while (is_human(&mons[otmp->corpsenm]) && tryct++ < 30);
937 blessorcurse(otmp, 4);
939 case BELL_OF_OPENING:
946 case DRUM_OF_EARTHQUAKE:
947 otmp->spe = rn1(5, 4);
952 if (otmp->otyp == AMULET_OF_YENDOR)
953 context.made_amulet = TRUE;
954 if (rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION
955 || otmp->otyp == AMULET_OF_CHANGE
956 || otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
959 blessorcurse(otmp, 10);
965 case POTION_CLASS: /* note: potions get some additional init below */
968 if (otmp->otyp != SCR_MAIL)
970 blessorcurse(otmp, 4);
973 otmp->spestudied = 0;
974 blessorcurse(otmp, 17);
978 && (otmp->otyp == FUMBLE_BOOTS
979 || otmp->otyp == LEVITATION_BOOTS
980 || otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT
981 || otmp->otyp == GAUNTLETS_OF_FUMBLING || !rn2(11))) {
984 } else if (!rn2(10)) {
985 otmp->blessed = rn2(2);
988 blessorcurse(otmp, 10);
989 if (artif && !rn2(40))
990 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
991 /* simulate lacquered armor for samurai */
992 if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL
993 && (moves <= 1 || In_quest(&u.uz))) {
995 /* optimizer bitfield bug */
996 otmp->oerodeproof = 1;
999 otmp->oerodeproof = otmp->rknown = 1;
1004 if (otmp->otyp == WAN_WISHING)
1008 rn1(5, (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
1009 blessorcurse(otmp, 17);
1010 otmp->recharged = 0; /* used to control recharging */
1013 if (objects[otmp->otyp].oc_charged) {
1014 blessorcurse(otmp, 3);
1016 if (rn2(10) && bcsign(otmp))
1017 otmp->spe = bcsign(otmp) * rne(3);
1019 otmp->spe = rn2(2) ? rne(3) : -rne(3);
1021 /* make useless +0 rings much less common */
1023 otmp->spe = rn2(4) - rn2(3);
1024 /* negative rings are usually cursed */
1025 if (otmp->spe < 0 && rn2(5))
1027 } else if (rn2(10) && (otmp->otyp == RIN_TELEPORTATION
1028 || otmp->otyp == RIN_POLYMORPH
1029 || otmp->otyp == RIN_AGGRAVATE_MONSTER
1030 || otmp->otyp == RIN_HUNGER || !rn2(9))) {
1035 switch (otmp->otyp) {
1037 /* possibly overridden by mkcorpstat() */
1038 otmp->corpsenm = rndmonnum();
1039 if (!verysmall(&mons[otmp->corpsenm])
1040 && rn2(level_difficulty() / 2 + 10) > 10)
1041 (void) add_to_container(otmp, mkobj(SPBOOK_CLASS, FALSE));
1045 break; /* do nothing */
1047 impossible("impossible mkobj %d, sym '%c'.", otmp->otyp,
1048 objects[otmp->otyp].oc_class);
1049 return (struct obj *) 0;
1053 /* some things must get done (corpsenm, timers) even if init = 0 */
1054 switch ((otmp->oclass == POTION_CLASS && otmp->otyp != POT_OIL)
1058 if (otmp->corpsenm == NON_PM) {
1059 otmp->corpsenm = undead_to_corpse(rndmonnum());
1060 if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE | G_GONE))
1061 otmp->corpsenm = urole.malenum;
1066 if (otmp->corpsenm == NON_PM)
1067 otmp->corpsenm = rndmonnum();
1071 set_corpsenm(otmp, otmp->corpsenm);
1074 otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
1076 case POT_WATER: /* POTION_CLASS */
1077 otmp->fromsink = 0; /* overloads corpsenm, which was set to NON_PM */
1080 otmp->leashmon = 0; /* overloads corpsenm, which was set to NON_PM */
1083 otmp->novelidx = -1; /* "none of the above"; will be changed */
1084 otmp = oname(otmp, noveltitle(&otmp->novelidx));
1088 /* unique objects may have an associated artifact entry */
1089 if (objects[otyp].oc_unique && !otmp->oartifact)
1090 otmp = mk_artifact(otmp, (aligntyp) A_NONE);
1091 otmp->owt = weight(otmp);
1096 * Several areas of the code made direct reassignments
1097 * to obj->corpsenm. Because some special handling is
1098 * required in certain cases, place that handling here
1099 * and call this routine in place of the direct assignment.
1101 * If the object was a lizard or lichen corpse:
1102 * - ensure that you don't end up with some
1103 * other corpse type which has no rot-away timer.
1105 * If the object was a troll corpse:
1106 * - ensure that you don't end up with some other
1107 * corpse type which resurrects from the dead.
1109 * Re-calculates the weight of figurines and corpses to suit the
1112 * Existing timeout value for egg hatch is preserved.
1116 set_corpsenm(obj, id)
1123 if (obj->otyp == EGG)
1124 when = stop_timer(HATCH_EGG, obj_to_any(obj));
1127 obj_stop_timers(obj); /* corpse or figurine */
1131 switch (obj->otyp) {
1133 start_corpse_timeout(obj);
1134 obj->owt = weight(obj);
1137 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE)
1138 && (carried(obj) || mcarried(obj)))
1139 attach_fig_transform_timeout(obj);
1140 obj->owt = weight(obj);
1143 if (obj->corpsenm != NON_PM && !dead_species(obj->corpsenm, TRUE))
1144 attach_egg_hatch_timeout(obj, when);
1146 default: /* tin, etc. */
1147 obj->owt = weight(obj);
1153 * Start a corpse decay or revive timer.
1154 * This takes the age of the corpse into consideration as of 3.4.0.
1157 start_corpse_timeout(body)
1160 long when; /* rot away when this old */
1161 long corpse_age; /* age of corpse */
1165 #define TAINT_AGE (50L) /* age when corpses go bad */
1166 #define TROLL_REVIVE_CHANCE 37 /* 1/37 chance for 50 turns ~ 75% chance */
1167 #define ROT_AGE (250L) /* age when corpses rot away */
1169 /* lizards and lichen don't rot or revive */
1170 if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN)
1173 action = ROT_CORPSE; /* default action: rot away */
1174 rot_adjust = in_mklev ? 25 : 10; /* give some variation */
1175 corpse_age = monstermoves - body->age;
1176 if (corpse_age > ROT_AGE)
1179 when = ROT_AGE - corpse_age;
1180 when += (long) (rnz(rot_adjust) - rot_adjust);
1182 if (is_rider(&mons[body->corpsenm])) {
1184 * Riders always revive. They have a 1/3 chance per turn
1185 * of reviving after 12 turns. Always revive by 500.
1187 action = REVIVE_MON;
1188 for (when = 12L; when < 500L; when++)
1192 } else if (mons[body->corpsenm].mlet == S_TROLL && !body->norevive) {
1194 for (age = 2; age <= TAINT_AGE; age++)
1195 if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */
1196 action = REVIVE_MON;
1204 (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
1208 maybe_adjust_light(obj, old_range)
1214 int new_range = arti_light_radius(obj), delta = new_range - old_range;
1216 /* radius of light emitting artifact varies by curse/bless state
1217 so will change after blessing or cursing */
1219 obj_adjust_light_radius(obj, new_range);
1220 /* simplifying assumptions: hero is wielding this object;
1221 artifacts have to be in use to emit light and monsters'
1222 gear won't change bless or curse state */
1223 if (!Blind && get_obj_location(obj, &ox, &oy, 0)) {
1225 if (iflags.last_msg == PLNMSG_OBJ_GLOWS)
1226 /* we just saw "The <obj> glows <color>." from dipping */
1228 Strcpy(buf, (obj->quan == 1L) ? "It" : "They");
1230 Strcpy(buf, "
\82»
\82ê");
1232 else if (carried(obj) || cansee(ox, oy))
1233 Strcpy(buf, Yname2(obj));
1235 /* initial activation says "dimly" if cursed,
1236 "brightly" if uncursed, and "brilliantly" if blessed;
1237 when changing intensity, using "less brightly" is
1238 straightforward for dimming, but we need "brighter"
1239 rather than "more brightly" for brightening; ugh */
1241 pline("%s %s %s%s.", buf, otense(obj, "shine"),
1242 (abs(delta) > 1) ? "much " : "",
1243 (delta > 0) ? "brighter" : "less brightly");
1245 pline("%s
\82Ì
\8bP
\82«
\82Í%s%s
\81D", buf,
1246 (abs(delta) > 1) ? "
\82©
\82È
\82è" : "",
1247 (delta > 0) ? "
\91\9d\82µ
\82½" : "
\8c¸
\82Á
\82½");
1255 * bless(), curse(), unbless(), uncurse() -- any relevant message
1256 * about glowing amber/black/&c should be delivered prior to calling
1257 * these routines to make the actual curse/bless state change.
1262 register struct obj *otmp;
1266 if (otmp->oclass == COIN_CLASS)
1269 old_light = arti_light_radius(otmp);
1272 if (carried(otmp) && confers_luck(otmp))
1274 else if (otmp->otyp == BAG_OF_HOLDING)
1275 otmp->owt = weight(otmp);
1276 else if (otmp->otyp == FIGURINE && otmp->timed)
1277 (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1279 maybe_adjust_light(otmp, old_light);
1285 register struct obj *otmp;
1290 old_light = arti_light_radius(otmp);
1292 if (carried(otmp) && confers_luck(otmp))
1294 else if (otmp->otyp == BAG_OF_HOLDING)
1295 otmp->owt = weight(otmp);
1297 maybe_adjust_light(otmp, old_light);
1302 register struct obj *otmp;
1304 unsigned already_cursed;
1307 if (otmp->oclass == COIN_CLASS)
1310 old_light = arti_light_radius(otmp);
1311 already_cursed = otmp->cursed;
1314 /* welded two-handed weapon interferes with some armor removal */
1315 if (otmp == uwep && bimanual(uwep))
1317 /* rules at top of wield.c state that twoweapon cannot be done
1318 with cursed alternate weapon */
1319 if (otmp == uswapwep && u.twoweap)
1321 /* some cursed items need immediate updating */
1322 if (carried(otmp) && confers_luck(otmp)) {
1324 } else if (otmp->otyp == BAG_OF_HOLDING) {
1325 otmp->owt = weight(otmp);
1326 } else if (otmp->otyp == FIGURINE) {
1327 if (otmp->corpsenm != NON_PM && !dead_species(otmp->corpsenm, TRUE)
1328 && (carried(otmp) || mcarried(otmp)))
1329 attach_fig_transform_timeout(otmp);
1330 } else if (otmp->oclass == SPBOOK_CLASS) {
1331 /* if book hero is reading becomes cursed, interrupt */
1332 if (!already_cursed)
1336 maybe_adjust_light(otmp, old_light);
1342 register struct obj *otmp;
1347 old_light = arti_light_radius(otmp);
1349 if (carried(otmp) && confers_luck(otmp))
1351 else if (otmp->otyp == BAG_OF_HOLDING)
1352 otmp->owt = weight(otmp);
1353 else if (otmp->otyp == FIGURINE && otmp->timed)
1354 (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
1356 maybe_adjust_light(otmp, old_light);
1361 blessorcurse(otmp, chance)
1362 register struct obj *otmp;
1363 register int chance;
1365 if (otmp->blessed || otmp->cursed)
1380 register struct obj *otmp;
1382 return (!!otmp->blessed - !!otmp->cursed);
1386 * Calculate the weight of the given object. This will recursively follow
1387 * and calculate the weight of any containers.
1389 * Note: It is possible to end up with an incorrect weight if some part
1390 * of the code messes with a contained object and doesn't update the
1391 * container's weight.
1395 register struct obj *obj;
1397 int wt = (int) objects[obj->otyp].oc_weight;
1399 /* glob absorpsion means that merging globs accumulates weight while
1400 quantity stays 1, so update 'wt' to reflect that, unless owt is 0,
1401 when we assume this is a brand new glob so use objects[].oc_weight */
1402 if (obj->globby && obj->owt > 0)
1404 if (SchroedingersBox(obj))
1405 wt += mons[PM_HOUSECAT].cwt;
1406 if (Is_container(obj) || obj->otyp == STATUE) {
1407 struct obj *contents;
1408 register int cwt = 0;
1410 if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
1411 wt = (int) obj->quan * ((int) mons[obj->corpsenm].cwt * 3 / 2);
1413 for (contents = obj->cobj; contents; contents = contents->nobj)
1414 cwt += weight(contents);
1416 * The weight of bags of holding is calculated as the weight
1417 * of the bag plus the weight of the bag's contents modified
1420 * Bag status Weight of contents
1421 * ---------- ------------------
1423 * blessed x/4 [rounded up: (x+3)/4]
1424 * otherwise x/2 [rounded up: (x+1)/2]
1426 * The macro DELTA_CWT in pickup.c also implements these
1429 if (obj->otyp == BAG_OF_HOLDING)
1430 cwt = obj->cursed ? (cwt * 2) : obj->blessed ? ((cwt + 3) / 4)
1435 if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
1436 long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
1438 wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int) long_wt;
1440 wt = eaten_stat(wt, obj);
1442 } else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
1443 return eaten_stat((int) obj->quan * wt, obj);
1444 } else if (obj->oclass == COIN_CLASS) {
1445 return (int) ((obj->quan + 50L) / 100L);
1446 } else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0) {
1447 return (int) obj->owt; /* kludge for "very" heavy iron ball */
1448 } else if (obj->otyp == CANDELABRUM_OF_INVOCATION && obj->spe) {
1449 return wt + obj->spe * (int) objects[TALLOW_CANDLE].oc_weight;
1451 return (wt ? wt * (int) obj->quan : ((int) obj->quan + 1) >> 1);
1454 static int treefruits[] = { APPLE, ORANGE, PEAR, BANANA, EUCALYPTUS_LEAF };
1457 rnd_treefruit_at(x, y)
1460 return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
1464 mkgold(amount, x, y)
1468 register struct obj *gold = g_at(x, y);
1471 long mul = rnd(30 / max(12-depth(&u.uz), 2));
1472 amount = (long) (1 + rnd(level_difficulty() + 2) * mul);
1475 gold->quan += amount;
1477 gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
1478 gold->quan = amount;
1480 gold->owt = weight(gold);
1484 /* return TRUE if the corpse has special timing */
1485 #define special_corpse(num) \
1486 (((num) == PM_LIZARD) || ((num) == PM_LICHEN) || (is_rider(&mons[num])) \
1487 || (mons[num].mlet == S_TROLL))
1490 * OEXTRA note: Passing mtmp causes mtraits to be saved
1491 * even if ptr passed as well, but ptr is always used for
1492 * the corpse type (corpsenm). That allows the corpse type
1493 * to be different from the original monster,
1494 * i.e. vampire -> human corpse
1495 * yet still allow restoration of the original monster upon
1499 mkcorpstat(objtype, mtmp, ptr, x, y, corpstatflags)
1500 int objtype; /* CORPSE or STATUE */
1502 struct permonst *ptr;
1504 unsigned corpstatflags;
1506 register struct obj *otmp;
1507 boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
1509 if (objtype != CORPSE && objtype != STATUE)
1510 impossible("making corpstat type %d", objtype);
1511 if (x == 0 && y == 0) { /* special case - random placement */
1512 otmp = mksobj(objtype, init, FALSE);
1516 otmp = mksobj_at(objtype, x, y, init, FALSE);
1523 /* save_mtraits frees original data pointed to by otmp */
1524 otmp2 = save_mtraits(otmp, mtmp);
1528 /* use the corpse or statue produced by mksobj() as-is
1529 unless `ptr' is non-null */
1531 int old_corpsenm = otmp->corpsenm;
1533 otmp->corpsenm = monsndx(ptr);
1534 otmp->owt = weight(otmp);
1535 if (otmp->otyp == CORPSE && (special_corpse(old_corpsenm)
1536 || special_corpse(otmp->corpsenm))) {
1537 obj_stop_timers(otmp);
1538 start_corpse_timeout(otmp);
1546 * Return the type of monster that this corpse will
1547 * revive as, even if it has a monster structure
1548 * attached to it. In that case, you can't just
1549 * use obj->corpsenm, because the stored monster
1550 * type can, and often is, different.
1551 * The return value is an index into mons[].
1554 corpse_revive_type(obj)
1560 && ((mtmp = get_mtraits(obj, FALSE)) != (struct monst *) 0)) {
1561 /* mtmp is a temporary pointer to a monster's stored
1562 attributes, not a real monster */
1563 revivetype = mtmp->mnum;
1565 revivetype = obj->corpsenm;
1570 * Attach a monster id to an object, to provide
1571 * a lasting association between the two.
1574 obj_attach_mid(obj, mid)
1579 return (struct obj *) 0;
1586 save_mtraits(obj, mtmp)
1591 forget_temple_entry(mtmp); /* EPRI() */
1592 if (!has_omonst(obj))
1594 if (has_omonst(obj)) {
1595 struct monst *mtmp2 = OMONST(obj);
1598 mtmp2->mextra = (struct mextra *) 0;
1600 mtmp2->mnum = monsndx(mtmp->data);
1601 /* invalidate pointers */
1602 /* m_id is needed to know if this is a revived quest leader */
1603 /* but m_id must be cleared when loading bones */
1604 mtmp2->nmon = (struct monst *) 0;
1605 mtmp2->data = (struct permonst *) 0;
1606 mtmp2->minvent = (struct obj *) 0;
1608 copy_mextra(mtmp2, mtmp);
1613 /* returns a pointer to a new monst structure based on
1614 * the one contained within the obj.
1617 get_mtraits(obj, copyof)
1621 struct monst *mtmp = (struct monst *) 0;
1622 struct monst *mnew = (struct monst *) 0;
1624 if (has_omonst(obj))
1630 mnew->mextra = (struct mextra *) 0;
1632 copy_mextra(mnew, mtmp);
1634 /* Never insert this returned pointer into mon chains! */
1641 /* make an object named after someone listed in the scoreboard file */
1643 mk_tt_object(objtype, x, y)
1644 int objtype; /* CORPSE or STATUE */
1647 register struct obj *otmp, *otmp2;
1648 boolean initialize_it;
1650 /* player statues never contain books */
1651 initialize_it = (objtype != STATUE);
1652 if ((otmp = mksobj_at(objtype, x, y, initialize_it, FALSE)) != 0) {
1653 /* tt_oname will return null if the scoreboard is empty */
1654 if ((otmp2 = tt_oname(otmp)) != 0)
1660 /* make a new corpse or statue, uninitialized if a statue (i.e. no books) */
1662 mk_named_object(objtype, ptr, x, y, nm)
1663 int objtype; /* CORPSE or STATUE */
1664 struct permonst *ptr;
1669 unsigned corpstatflags =
1670 (objtype != STATUE) ? CORPSTAT_INIT : CORPSTAT_NONE;
1672 otmp = mkcorpstat(objtype, (struct monst *) 0, ptr, x, y, corpstatflags);
1674 otmp = oname(otmp, nm);
1680 register struct obj *otmp;
1682 int otyp = otmp->otyp;
1683 int omat = objects[otyp].oc_material;
1685 /* Candles can be burned, but they're not flammable in the sense that
1686 * they can't get fire damage and it makes no sense for them to be
1689 if (Is_candle(otmp))
1692 if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
1695 return (boolean) ((omat <= WOOD && omat != LIQUID) || omat == PLASTIC);
1700 register struct obj *otmp;
1702 int otyp = otmp->otyp;
1704 return (boolean) (objects[otyp].oc_material <= WOOD
1705 && objects[otyp].oc_material != LIQUID);
1709 * These routines maintain the single-linked lists headed in level.objects[][]
1710 * and threaded through the nexthere fields in the object-instance structure.
1713 /* put the object at the given location */
1715 place_object(otmp, x, y)
1716 register struct obj *otmp;
1719 register struct obj *otmp2 = level.objects[x][y];
1721 if (otmp->where != OBJ_FREE)
1722 panic("place_object: obj not free");
1724 obj_no_longer_held(otmp);
1725 /* (could bypass this vision update if there is already a boulder here) */
1726 if (otmp->otyp == BOULDER)
1727 block_point(x, y); /* vision */
1729 /* obj goes under boulders */
1730 if (otmp2 && (otmp2->otyp == BOULDER)) {
1731 otmp->nexthere = otmp2->nexthere;
1732 otmp2->nexthere = otmp;
1734 otmp->nexthere = otmp2;
1735 level.objects[x][y] = otmp;
1738 /* set the new object's location */
1742 otmp->where = OBJ_FLOOR;
1744 /* add to floor chain */
1748 obj_timer_checks(otmp, x, y, 0);
1751 #define ROT_ICE_ADJUSTMENT 2 /* rotting on ice takes 2 times as long */
1753 /* If ice was affecting any objects correct that now
1754 * Also used for starting ice effects too. [zap.c]
1757 obj_ice_effects(x, y, do_buried)
1763 for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) {
1765 obj_timer_checks(otmp, x, y, 0);
1768 for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
1769 if (otmp->ox == x && otmp->oy == y) {
1771 obj_timer_checks(otmp, x, y, 0);
1778 * Returns an obj->age for a corpse object on ice, that would be the
1779 * actual obj->age if the corpse had just been lifted from the ice.
1780 * This is useful when just using obj->age in a check or calculation because
1781 * rot timers pertaining to the object don't have to be stopped and
1785 peek_at_iced_corpse_age(otmp)
1788 long age, retval = otmp->age;
1790 if (otmp->otyp == CORPSE && otmp->on_ice) {
1791 /* Adjust the age; must be same as obj_timer_checks() for off ice*/
1792 age = monstermoves - otmp->age;
1793 retval += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
1795 "The %s age has ice modifications: otmp->age = %ld, returning %ld.",
1796 s_suffix(doname(otmp)), otmp->age, retval);
1797 debugpline1("Effective age of corpse: %ld.", monstermoves - retval);
1803 obj_timer_checks(otmp, x, y, force)
1806 int force; /* 0 = no force so do checks, <0 = force off, >0 force on */
1809 short action = ROT_CORPSE;
1810 boolean restart_timer = FALSE;
1811 boolean on_floor = (otmp->where == OBJ_FLOOR);
1812 boolean buried = (otmp->where == OBJ_BURIED);
1814 /* Check for corpses just placed on or in ice */
1815 if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x, y)) {
1816 tleft = stop_timer(action, obj_to_any(otmp));
1818 action = REVIVE_MON;
1819 tleft = stop_timer(action, obj_to_any(otmp));
1824 /* mark the corpse as being on ice */
1826 debugpline3("%s is now on ice at <%d,%d>.", The(xname(otmp)), x,
1828 /* Adjust the time remaining */
1829 tleft *= ROT_ICE_ADJUSTMENT;
1830 restart_timer = TRUE;
1831 /* Adjust the age; time spent off ice needs to be multiplied
1832 by the ice adjustment and subtracted from the age so that
1833 later calculations behave as if it had been on ice during
1834 that time (longwinded way of saying this is the inverse
1835 of removing it from the ice and of peeking at its age). */
1836 age = monstermoves - otmp->age;
1837 otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
1840 /* Check for corpses coming off ice */
1841 } else if (force < 0 || (otmp->otyp == CORPSE && otmp->on_ice
1842 && !((on_floor || buried) && is_ice(x, y)))) {
1843 tleft = stop_timer(action, obj_to_any(otmp));
1845 action = REVIVE_MON;
1846 tleft = stop_timer(action, obj_to_any(otmp));
1852 debugpline3("%s is no longer on ice at <%d,%d>.",
1853 The(xname(otmp)), x, y);
1854 /* Adjust the remaining time */
1855 tleft /= ROT_ICE_ADJUSTMENT;
1856 restart_timer = TRUE;
1857 /* Adjust the age */
1858 age = monstermoves - otmp->age;
1859 otmp->age += age * (ROT_ICE_ADJUSTMENT - 1) / ROT_ICE_ADJUSTMENT;
1863 /* now re-start the timer with the appropriate modifications */
1865 (void) start_timer(tleft, TIMER_OBJECT, action, obj_to_any(otmp));
1868 #undef ROT_ICE_ADJUSTMENT
1872 register struct obj *otmp;
1877 if (otmp->where != OBJ_FLOOR)
1878 panic("remove_object: obj not on floor");
1879 extract_nexthere(otmp, &level.objects[x][y]);
1880 extract_nobj(otmp, &fobj);
1881 /* update vision iff this was the only boulder at its spot */
1882 if (otmp->otyp == BOULDER && !sobj_at(BOULDER, x, y))
1883 unblock_point(x, y); /* vision */
1885 obj_timer_checks(otmp, x, y, 0);
1888 /* throw away all of a monster's inventory */
1890 discard_minvent(mtmp)
1893 struct obj *otmp, *mwep = MON_WEP(mtmp);
1894 boolean keeping_mon = (mtmp->mhp > 0);
1896 while ((otmp = mtmp->minvent) != 0) {
1897 /* this has now become very similar to m_useupall()... */
1898 obj_extract_self(otmp);
1899 if (otmp->owornmask) {
1902 mwepgone(mtmp), mwep = 0;
1903 mtmp->misc_worn_check &= ~otmp->owornmask;
1904 update_mon_intrinsics(mtmp, otmp, FALSE, TRUE);
1906 otmp->owornmask = 0L; /* obfree() expects this */
1908 obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */
1913 * Free obj from whatever list it is on in preparation for deleting it
1914 * or moving it elsewhere; obj->where will end up set to OBJ_FREE.
1915 * Doesn't handle unwearing of objects in hero's or monsters' inventories.
1918 * OBJ_FREE not on any list
1919 * OBJ_FLOOR fobj, level.locations[][] chains (use remove_object)
1920 * OBJ_CONTAINED cobj chain of container object
1921 * OBJ_INVENT hero's invent chain (use freeinv)
1922 * OBJ_MINVENT monster's invent chain
1923 * OBJ_MIGRATING migrating chain
1924 * OBJ_BURIED level.buriedobjs chain
1925 * OBJ_ONBILL on billobjs chain
1928 obj_extract_self(obj)
1931 switch (obj->where) {
1938 extract_nobj(obj, &obj->ocontainer->cobj);
1939 container_weight(obj->ocontainer);
1945 extract_nobj(obj, &obj->ocarry->minvent);
1948 extract_nobj(obj, &migrating_objs);
1951 extract_nobj(obj, &level.buriedobjlist);
1954 extract_nobj(obj, &billobjs);
1957 panic("obj_extract_self");
1962 /* Extract the given object from the chain, following nobj chain. */
1964 extract_nobj(obj, head_ptr)
1965 struct obj *obj, **head_ptr;
1967 struct obj *curr, *prev;
1970 for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) {
1973 prev->nobj = curr->nobj;
1975 *head_ptr = curr->nobj;
1980 panic("extract_nobj: object lost");
1981 obj->where = OBJ_FREE;
1986 * Extract the given object from the chain, following nexthere chain.
1988 * This does not set obj->where, this function is expected to be called
1989 * in tandem with extract_nobj, which does set it.
1992 extract_nexthere(obj, head_ptr)
1993 struct obj *obj, **head_ptr;
1995 struct obj *curr, *prev;
1998 for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) {
2001 prev->nexthere = curr->nexthere;
2003 *head_ptr = curr->nexthere;
2008 panic("extract_nexthere: object lost");
2012 * Add obj to mon's inventory. If obj is able to merge with something already
2013 * in the inventory, then the passed obj is deleted and 1 is returned.
2014 * Otherwise 0 is returned.
2017 add_to_minv(mon, obj)
2023 if (obj->where != OBJ_FREE)
2024 panic("add_to_minv: obj not free");
2026 /* merge if possible */
2027 for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
2028 if (merged(&otmp, &obj))
2029 return 1; /* obj merged and then free'd */
2030 /* else insert; don't bother forcing it to end of chain */
2031 obj->where = OBJ_MINVENT;
2033 obj->nobj = mon->minvent;
2035 return 0; /* obj on mon's inventory chain */
2039 * Add obj to container, make sure obj is "free". Returns (merged) obj.
2040 * The input obj may be deleted in the process.
2043 add_to_container(container, obj)
2044 struct obj *container, *obj;
2048 if (obj->where != OBJ_FREE)
2049 panic("add_to_container: obj not free");
2050 if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT)
2051 obj_no_longer_held(obj);
2053 /* merge if possible */
2054 for (otmp = container->cobj; otmp; otmp = otmp->nobj)
2055 if (merged(&otmp, &obj))
2058 obj->where = OBJ_CONTAINED;
2059 obj->ocontainer = container;
2060 obj->nobj = container->cobj;
2061 container->cobj = obj;
2066 add_to_migration(obj)
2069 if (obj->where != OBJ_FREE)
2070 panic("add_to_migration: obj not free");
2072 obj->where = OBJ_MIGRATING;
2073 obj->nobj = migrating_objs;
2074 migrating_objs = obj;
2081 if (obj->where != OBJ_FREE)
2082 panic("add_to_buried: obj not free");
2084 obj->where = OBJ_BURIED;
2085 obj->nobj = level.buriedobjlist;
2086 level.buriedobjlist = obj;
2089 /* Recalculate the weight of this container and all of _its_ containers. */
2091 container_weight(container)
2092 struct obj *container;
2094 container->owt = weight(container);
2095 if (container->where == OBJ_CONTAINED)
2096 container_weight(container->ocontainer);
2098 else if (container->where == OBJ_INVENT)
2099 recalculate load delay here ???
2104 * Deallocate the object. _All_ objects should be run through here for
2105 * them to be deallocated.
2111 if (obj->where != OBJ_FREE)
2112 panic("dealloc_obj: obj not free");
2114 panic("dealloc_obj with nobj");
2116 panic("dealloc_obj with cobj");
2118 /* free up any timers attached to the object */
2120 obj_stop_timers(obj);
2123 * Free up any light sources attached to the object.
2125 * We may want to just call del_light_source() without any
2126 * checks (requires a code change there). Otherwise this
2127 * list must track all objects that can have a light source
2128 * attached to it (and also requires lamplit to be set).
2130 if (obj_sheds_light(obj))
2131 del_light_source(LS_OBJECT, obj_to_any(obj));
2133 if (obj == thrownobj)
2135 if (obj == kickedobj)
2139 dealloc_oextra(obj);
2140 free((genericptr_t) obj);
2143 /* create an object from a horn of plenty; mirrors bagotricks(makemon.c) */
2145 hornoplenty(horn, tipping)
2147 boolean tipping; /* caller emptying entire contents; affects shop handling */
2151 if (!horn || horn->otyp != HORN_OF_PLENTY) {
2152 impossible("bad horn o' plenty");
2153 } else if (horn->spe < 1) {
2154 pline1(nothing_happens);
2159 consume_obj_charge(horn, !tipping);
2161 obj = mkobj(POTION_CLASS, FALSE);
2162 if (objects[obj->otyp].oc_magic)
2164 obj->otyp = rnd_class(POT_BOOZE, POT_WATER);
2165 } while (obj->otyp == POT_SICKNESS);
2167 what = (obj->quan > 1L) ? "Some potions" : "A potion";
2171 obj = mkobj(FOOD_CLASS, FALSE);
2172 if (obj->otyp == FOOD_RATION && !rn2(7))
2173 obj->otyp = LUMP_OF_ROYAL_JELLY;
2177 what = "
\90H
\82×
\95¨";
2181 pline("%s %s out.", what, vtense(what, "spill"));
2183 pline("%s
\82ª
\94ò
\82Ñ
\8fo
\82Ä
\82«
\82½
\81D", what);
2184 obj->blessed = horn->blessed;
2185 obj->cursed = horn->cursed;
2186 obj->owt = weight(obj);
2187 /* using a shop's horn of plenty entails a usage fee and also
2188 confers ownership of the created item to the shopkeeper */
2190 addtobill(obj, FALSE, FALSE, tipping);
2191 /* if it ended up on bill, we don't want "(unpaid, N zorkids)"
2192 being included in its formatted name during next message */
2193 iflags.suppress_price++;
2196 obj = hold_another_object(
2197 obj, u.uswallow ? "Oops! %s out of your reach!"
2198 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
2199 || levl[u.ux][u.uy].typ < IRONBARS
2200 || levl[u.ux][u.uy].typ >= ICE)
2201 ? "Oops! %s away from you!"
2202 : "Oops! %s to the floor!",
2203 The(aobjnam(obj, "slip")), (const char *) 0);
2205 obj = hold_another_object(
2206 obj, u.uswallow ? "
\82¨
\82Á
\82Æ
\81I%s
\82Í
\93Í
\82©
\82È
\82¢
\81I"
2207 : (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)
2208 || levl[u.ux][u.uy].typ < IRONBARS
2209 || levl[u.ux][u.uy].typ >= ICE)
2210 ? "
\82¨
\82Á
\82Æ
\81I%s
\82Í
\82 \82È
\82½
\82Ì
\8eè
\82©
\82ç
\8a\8a\82è
\97\8e\82¿
\82½
\81I"
2211 : "
\82¨
\82Á
\82Æ
\81I%s
\82Í
\8f°
\82É
\8a\8a\82è
\97\8e\82¿
\82½
\81I",
2212 xname(obj), (const char *)0);
2215 /* assumes this is taking place at hero's location */
2216 if (!can_reach_floor(TRUE)) {
2217 hitfloor(obj); /* does altar check, message, drop */
2219 if (IS_ALTAR(levl[u.ux][u.uy].typ))
2220 doaltarobj(obj); /* does its own drop message */
2223 pline("%s %s to the %s.", Doname2(obj),
2224 otense(obj, "drop"), surface(u.ux, u.uy));
2226 pline("%s
\82Í%s
\82É
\97\8e\82¿
\82½
\81D", Doname2(obj),
2227 surface(u.ux, u.uy));
2232 iflags.suppress_price--;
2234 makeknown(HORN_OF_PLENTY);
2239 /* support for wizard-mode's `sanity_check' option */
2241 static const char NEARDATA /* pline formats for insane_object() */
2242 ofmt0[] = "%s obj %s %s: %s",
2243 ofmt3[] = "%s [not null] %s %s: %s",
2244 /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
2245 mfmt1[] = "%s obj %s %s (%s)",
2246 mfmt2[] = "%s obj %s %s (%s) *not*";
2248 /* Check all object lists for consistency. */
2257 * Should check whether the obj->bypass and/or obj->nomerge bits
2258 * are set. Those are both used for temporary purposes and should
2259 * be clear between moves.
2262 objlist_sanity(fobj, OBJ_FLOOR, "floor sanity");
2264 /* check that the map's record of floor objects is consistent;
2265 those objects should have already been sanity checked via
2266 the floor list so container contents are skipped here */
2267 for (x = 0; x < COLNO; x++)
2268 for (y = 0; y < ROWNO; y++)
2269 for (obj = level.objects[x][y]; obj; obj = obj->nexthere) {
2270 /* <ox,oy> should match <x,y>; <0,*> should always be empty */
2271 if (obj->where != OBJ_FLOOR || x == 0
2272 || obj->ox != x || obj->oy != y) {
2275 Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
2276 x, y, obj->ox, obj->oy);
2277 insane_object(obj, at_fmt, "location sanity",
2278 (struct monst *) 0);
2282 objlist_sanity(invent, OBJ_INVENT, "invent sanity");
2283 objlist_sanity(migrating_objs, OBJ_MIGRATING, "migrating sanity");
2284 objlist_sanity(level.buriedobjlist, OBJ_BURIED, "buried sanity");
2285 objlist_sanity(billobjs, OBJ_ONBILL, "bill sanity");
2287 mon_obj_sanity(fmon, "minvent sanity");
2288 mon_obj_sanity(migrating_mons, "migrating minvent sanity");
2289 /* monsters temporarily in transit;
2290 they should have arrived with hero by the time we get called */
2292 pline("mydogs sanity [not empty]");
2293 mon_obj_sanity(mydogs, "mydogs minvent sanity");
2296 /* objects temporarily freed from invent/floor lists;
2297 they should have arrived somewhere by the time we get called */
2299 insane_object(thrownobj, ofmt3, "thrownobj sanity",
2300 (struct monst *) 0);
2302 insane_object(kickedobj, ofmt3, "kickedobj sanity",
2303 (struct monst *) 0);
2304 /* current_wand isn't removed from invent while in use, but should
2305 be Null between moves when we're called */
2307 insane_object(current_wand, ofmt3, "current_wand sanity",
2308 (struct monst *) 0);
2311 /* sanity check for objects on specified list (fobj, &c) */
2313 objlist_sanity(objlist, wheretype, mesg)
2314 struct obj *objlist;
2320 for (obj = objlist; obj; obj = obj->nobj) {
2321 if (obj->where != wheretype)
2322 insane_object(obj, ofmt0, mesg, (struct monst *) 0);
2323 if (Has_contents(obj)) {
2324 if (wheretype == OBJ_ONBILL)
2325 /* containers on shop bill should always be empty */
2326 insane_object(obj, "%s obj contains something! %s %s: %s",
2327 mesg, (struct monst *) 0);
2328 check_contained(obj, mesg);
2330 if (obj->owornmask) {
2332 boolean bc_ok = FALSE;
2334 switch (obj->where) {
2337 sanity_check_worn(obj);
2340 /* migrating objects overload the owornmask field
2341 with a destination code; skip attempt to check it */
2344 /* note: ball and chain can also be OBJ_FREE, but not across
2345 turns so this sanity check shouldn't encounter that */
2349 if ((obj != uchain && obj != uball) || !bc_ok) {
2350 /* discovered an object not in inventory which
2351 erroneously has worn mask set */
2352 Sprintf(maskbuf, "worn mask 0x%08lx", obj->owornmask);
2353 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2361 /* sanity check for objects carried by all monsters in specified list */
2363 mon_obj_sanity(monlist, mesg)
2364 struct monst *monlist;
2368 struct obj *obj, *mwep;
2370 for (mon = monlist; mon; mon = mon->nmon) {
2371 if (DEADMONSTER(mon)) continue;
2372 mwep = MON_WEP(mon);
2374 if (!mcarried(mwep))
2375 insane_object(mwep, mfmt1, mesg, mon);
2376 if (mwep->ocarry != mon)
2377 insane_object(mwep, mfmt2, mesg, mon);
2379 for (obj = mon->minvent; obj; obj = obj->nobj) {
2380 if (obj->where != OBJ_MINVENT)
2381 insane_object(obj, mfmt1, mesg, mon);
2382 if (obj->ocarry != mon)
2383 insane_object(obj, mfmt2, mesg, mon);
2384 check_contained(obj, mesg);
2389 /* This must stay consistent with the defines in obj.h. */
2390 static const char *obj_state_names[NOBJ_STATES] = { "free", "floor",
2391 "contained", "invent",
2392 "minvent", "migrating",
2393 "buried", "onbill" };
2395 STATIC_OVL const char *
2399 static char unknown[32]; /* big enough to handle rogue 64-bit int */
2405 if (where < 0 || where >= NOBJ_STATES || !obj_state_names[where]) {
2406 Sprintf(unknown, "unknown[%d]", where);
2409 return obj_state_names[where];
2413 insane_object(obj, fmt, mesg, mon)
2415 const char *fmt, *mesg;
2418 const char *objnm, *monnm;
2421 objnm = monnm = "null!";
2423 iflags.override_ID++;
2424 objnm = doname(obj);
2425 iflags.override_ID--;
2427 if (mon || (strstri(mesg, "minvent") && !strstri(mesg, "contained"))) {
2428 Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)");
2430 monnm = x_monnam(mon, ARTICLE_A, (char *) 0, EXACT_NAME, TRUE);
2431 pline(altfmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj),
2432 objnm, fmt_ptr((genericptr_t) mon), monnm);
2434 pline(fmt, mesg, fmt_ptr((genericptr_t) obj), where_name(obj), objnm);
2438 /* obj sanity check: check objects inside container */
2440 check_contained(container, mesg)
2441 struct obj *container;
2445 /* big enough to work with, not too big to blow out stack in recursion */
2446 char mesgbuf[40], nestedmesg[120];
2448 if (!Has_contents(container))
2450 /* change "invent sanity" to "contained invent sanity"
2451 but leave "nested contained invent sanity" as is */
2452 if (!strstri(mesg, "contained"))
2453 mesg = strcat(strcpy(mesgbuf, "contained "), mesg);
2455 for (obj = container->cobj; obj; obj = obj->nobj) {
2456 /* catch direct cycle to avoid unbounded recursion */
2457 if (obj == container)
2458 panic("failed sanity check: container holds itself");
2459 if (obj->where != OBJ_CONTAINED)
2460 insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *) 0);
2461 else if (obj->ocontainer != container)
2462 pline("%s obj %s in container %s, not %s", mesg,
2463 fmt_ptr((genericptr_t) obj),
2464 fmt_ptr((genericptr_t) obj->ocontainer),
2465 fmt_ptr((genericptr_t) container));
2467 if (Has_contents(obj)) {
2468 /* catch most likely indirect cycle; we won't notice if
2469 parent is present when something comes before it, or
2470 notice more deeply embedded cycles (grandparent, &c) */
2471 if (obj->cobj == container)
2472 panic("failed sanity check: container holds its parent");
2473 /* change "contained... sanity" to "nested contained... sanity"
2474 and "nested contained..." to "nested nested contained..." */
2475 Strcpy(nestedmesg, "nested ");
2476 copynchars(eos(nestedmesg), mesg, (int) sizeof nestedmesg
2477 - (int) strlen(nestedmesg)
2479 /* recursively check contents */
2480 check_contained(obj, nestedmesg);
2485 /* check an object in hero's or monster's inventory which has worn mask set */
2487 sanity_check_worn(obj)
2490 #if defined(BETA) || defined(DEBUG)
2491 static unsigned long wearbits[] = {
2492 W_ARM, W_ARMC, W_ARMH, W_ARMS, W_ARMG, W_ARMF, W_ARMU,
2493 W_WEP, W_QUIVER, W_SWAPWEP, W_AMUL, W_RINGL, W_RINGR, W_TOOL,
2494 W_SADDLE, W_BALL, W_CHAIN, 0
2495 /* [W_ART,W_ARTI are property bits for items which aren't worn] */
2499 unsigned long owornmask, allmask = 0L;
2500 boolean embedded = FALSE;
2503 /* use owornmask for testing and bit twiddling, but use original
2504 obj->owornmask for printing */
2505 owornmask = obj->owornmask;
2506 /* figure out how many bits are set, and also which are viable */
2507 for (i = 0; wearbits[i]; ++i) {
2508 if ((owornmask & wearbits[i]) != 0L)
2510 allmask |= wearbits[i];
2513 /* embedded dragon scales have an extra bit set;
2514 make sure it's set, then suppress it */
2516 if ((owornmask & (W_ARM | I_SPECIAL)) == (W_ARM | I_SPECIAL))
2517 owornmask &= ~I_SPECIAL;
2519 n = 0, owornmask = ~0; /* force insane_object("bogus") below */
2521 if (n == 2 && carried(obj)
2522 && obj == uball && (owornmask & W_BALL) != 0L
2523 && (owornmask & W_WEAPON) != 0L) {
2524 /* chained ball can be wielded/alt-wielded/quivered; if so,
2525 pretend it's not chained in order to check the weapon pointer
2526 (we've already verified the ball pointer by successfully passing
2527 the if-condition to get here...) */
2528 owornmask &= ~W_BALL;
2532 /* multiple bits set */
2533 Sprintf(maskbuf, "worn mask (multiple) 0x%08lx", obj->owornmask);
2534 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2536 if ((owornmask & ~allmask) != 0L
2537 || (carried(obj) && (owornmask & W_SADDLE) != 0L)) {
2538 /* non-wearable bit(s) set */
2539 Sprintf(maskbuf, "worn mask (bogus)) 0x%08lx", obj->owornmask);
2540 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2542 if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L)) {
2544 /* verify that obj in hero's invent (or ball/chain elsewhere)
2545 with owornmask of W_foo is the object pointed to by ufoo */
2546 switch (owornmask) {
2548 if (obj != (embedded ? uskin : uarm))
2549 what = embedded ? "skin" : "suit";
2577 what = "primary weapon";
2584 if (obj != uswapwep)
2585 what = u.twoweap ? "secondary weapon" : "alternate weapon";
2597 what = "right ring";
2603 /* case W_SADDLE: */
2616 Sprintf(maskbuf, "worn mask 0x%08lx != %s", obj->owornmask, what);
2617 insane_object(obj, ofmt0, maskbuf, (struct monst *) 0);
2620 if (n == 1 && (carried(obj) || (owornmask & (W_BALL | W_CHAIN)) != 0L
2621 || mcarried(obj))) {
2622 /* check for items worn in invalid slots; practically anything can
2623 be wielded/alt-wielded/quivered, so tests on those are limited */
2625 if (owornmask & W_ARMOR) {
2626 if (obj->oclass != ARMOR_CLASS)
2628 /* 3.6: dragon scale mail reverts to dragon scales when
2629 becoming embedded in poly'd hero's skin */
2630 if (embedded && !Is_dragon_scales(obj))
2632 } else if (owornmask & W_WEAPON) {
2633 /* monsters don't maintain alternate weapon or quiver */
2634 if (mcarried(obj) && (owornmask & (W_SWAPWEP | W_QUIVER)) != 0L)
2635 what = (owornmask & W_SWAPWEP) != 0L ? "monst alt weapon?"
2637 /* hero can quiver gold but not wield it (hence not alt-wield
2638 it either); also catches monster wielding gold */
2639 else if (obj->oclass == COIN_CLASS
2640 && (owornmask & (W_WEP | W_SWAPWEP)) != 0L)
2641 what = (owornmask & W_WEP) != 0L ? "weapon" : "alt weapon";
2642 } else if (owornmask & W_AMUL) {
2643 if (obj->oclass != AMULET_CLASS)
2645 } else if (owornmask & W_RING) {
2646 if (obj->oclass != RING_CLASS && obj->otyp != MEAT_RING)
2648 } else if (owornmask & W_TOOL) {
2649 if (obj->otyp != BLINDFOLD && obj->otyp != TOWEL
2650 && obj->otyp != LENSES)
2652 } else if (owornmask & W_BALL) {
2653 if (obj->oclass != BALL_CLASS)
2654 what = "chained ball";
2655 } else if (owornmask & W_CHAIN) {
2656 if (obj->oclass != CHAIN_CLASS)
2658 } else if (owornmask & W_SADDLE) {
2659 if (obj->otyp != SADDLE)
2663 char oclassname[30];
2664 struct monst *mon = mcarried(obj) ? obj->ocarry : 0;
2666 /* if we've found a potion worn in the amulet slot,
2667 this yields "worn (potion amulet)" */
2668 Strcpy(oclassname, def_oc_syms[(uchar) obj->oclass].name);
2669 Sprintf(maskbuf, "worn (%s %s)", makesingular(oclassname), what);
2670 insane_object(obj, ofmt0, maskbuf, mon);
2673 #else /* not (BETA || DEBUG) */
2674 /* dummy use of obj to avoid "arg not used" complaint */
2676 insane_object(obj, ofmt0, "<null>", (struct monst *) 0);
2681 * wrapper to make "near this object" convenient
2688 impossible("obj_nexto: wasn't given an object to check");
2689 return (struct obj *) 0;
2691 return obj_nexto_xy(otmp, otmp->ox, otmp->oy, TRUE);
2695 * looks for objects of a particular type next to x, y
2696 * skips over oid if found (lets us avoid ourselves if
2697 * we're looking for a second type of an existing object)
2699 * TODO: return a list of all objects near us so we can more
2700 * reliably predict which one we want to 'find' first
2703 obj_nexto_xy(obj, x, y, recurs)
2709 int fx, fy, ex, ey, otyp = obj->otyp;
2712 /* check under our "feet" first */
2713 otmp = sobj_at(otyp, x, y);
2715 /* don't be clever and find ourselves */
2716 if (otmp != obj && mergable(otmp, obj))
2718 otmp = nxtobj(otmp, otyp, TRUE);
2722 return (struct obj *) 0;
2724 /* search in a random order */
2725 dx = (rn2(2) ? -1 : 1);
2726 dy = (rn2(2) ? -1 : 1);
2730 for (fx = ex; abs(fx - ex) < 3; fx += dx) {
2731 for (fy = ey; abs(fy - ey) < 3; fy += dy) {
2732 /* 0, 0 was checked above */
2733 if (isok(fx, fy) && (fx != x || fy != y)) {
2734 if ((otmp = obj_nexto_xy(obj, fx, fy, FALSE)) != 0)
2739 return (struct obj *) 0;
2743 * Causes one object to absorb another, increasing
2744 * weight accordingly. Frees obj2; obj1 remains and
2748 obj_absorb(obj1, obj2)
2749 struct obj **obj1, **obj2;
2751 struct obj *otmp1, *otmp2;
2755 /* don't let people dumb it up */
2759 if (otmp1 && otmp2 && otmp1 != otmp2) {
2760 if (otmp1->bknown != otmp2->bknown)
2761 otmp1->bknown = otmp2->bknown = 0;
2762 if (otmp1->rknown != otmp2->rknown)
2763 otmp1->rknown = otmp2->rknown = 0;
2764 if (otmp1->greased != otmp2->greased)
2765 otmp1->greased = otmp2->greased = 0;
2766 if (otmp1->orotten || otmp2->orotten)
2767 otmp1->orotten = otmp2->orotten = 1;
2768 o1wt = otmp1->oeaten ? otmp1->oeaten : otmp1->owt;
2769 o2wt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
2770 /* averaging the relative ages is less likely to overflow
2771 than averaging the absolute ages directly */
2772 agetmp = (((moves - otmp1->age) * o1wt
2773 + (moves - otmp2->age) * o2wt)
2775 otmp1->age = moves - agetmp; /* conv. relative back to absolute */
2778 otmp1->oeaten += o2wt;
2780 obj_extract_self(otmp2);
2781 newsym(otmp2->ox, otmp2->oy); /* in case of floor */
2783 *obj2 = (struct obj *) 0;
2788 impossible("obj_absorb: not called with two actual objects");
2789 return (struct obj *) 0;
2793 * Causes the heavier object to absorb the lighter object;
2794 * wrapper for obj_absorb so that floor_effects works more
2795 * cleanly (since we don't know which we want to stay around)
2798 obj_meld(obj1, obj2)
2799 struct obj **obj1, **obj2;
2801 struct obj *otmp1, *otmp2;
2806 if (otmp1 && otmp2 && otmp1 != otmp2) {
2807 if (otmp1->owt > otmp2->owt
2808 || (otmp1->owt == otmp2->owt && rn2(2))) {
2809 return obj_absorb(obj1, obj2);
2811 return obj_absorb(obj2, obj1);
2815 impossible("obj_meld: not called with two actual objects");
2816 return (struct obj *) 0;
2819 /* give a message if hero notices two globs merging [used to be in pline.c] */
2821 pudding_merge_message(otmp, otmp2)
2825 boolean visible = (cansee(otmp->ox, otmp->oy)
2826 || cansee(otmp2->ox, otmp2->oy)),
2827 onfloor = (otmp->where == OBJ_FLOOR || otmp2->where == OBJ_FLOOR),
2828 inpack = (carried(otmp) || carried(otmp2));
2830 /* the player will know something happened inside his own inventory */
2831 if ((!Blind && visible) || inpack) {
2832 if (Hallucination) {
2835 You_see("parts of the floor melting!");
2837 You_see("
\8f°
\82Ì
\88ê
\95\94\82ª
\97n
\82¯
\82Ä
\82¢
\82é
\82Ì
\82ð
\8c©
\82½
\81I");
2838 } else if (inpack) {
2840 Your("pack reaches out and grabs something!");
2842 Your("
\82©
\82Î
\82ñ
\82ª
\8eè
\82ð
\90L
\82Î
\82µ
\82Ä
\89½
\82©
\82ð
\82Â
\82©
\82ñ
\82¾
\81I");
2844 /* even though we can see where they should be,
2845 * they'll be out of our view (minvent or container)
2846 * so don't actually show anything */
2847 } else if (onfloor || inpack) {
2849 pline("The %s coalesce%s.", makeplural(obj_typename(otmp->otyp)),
2850 inpack ? " inside your pack" : "");
2852 pline("%s
\82ª%s
\8d\87\91Ì
\82µ
\82½
\81D", obj_typename(otmp->otyp),
2853 inpack ? "
\82 \82È
\82½
\82Ì
\82©
\82Î
\82ñ
\82Ì
\92\86\82Å" : "");
2858 You_hear("a faint sloshing sound.");
2860 You_hear("
\82©
\82·
\82©
\82È
\83o
\83V
\83\83\83o
\83V
\83\83\82Æ
\82¢
\82¤
\89¹
\82ð
\95·
\82¢
\82½
\81D");