]> granicus.if.org Git - nethack/commitdiff
Unify code for extracting an object from a monster's inventory
authorcopperwater <aosdict@gmail.com>
Sun, 24 Jan 2021 21:39:33 +0000 (16:39 -0500)
committercopperwater <aosdict@gmail.com>
Sat, 30 Jan 2021 00:19:03 +0000 (19:19 -0500)
The code for doing this (basically an obj_extract_self() call plus
handling if the object was worn or wielded) was duplicated all over, and
inconsistent - for instance, though all of them updated the monster's
misc_worn_check to indicate it was no longer wearing something in
whatever slot, only one call also set the bit that flags the monster to
consider putting on other gear afterwards.

Under a new function, extract_from_minvent, all this extra handling is
checked in one function, which can simply replace the obj_extract_self
call.

A few callers (such as stealing) have some common code *after* the
object is extracted and some other things happen such as message
printing, such as calling mselftouch if the object was worn
gloves. extract_from_minvent does not handle these cases.

include/extern.h
src/mkobj.c
src/mon.c
src/mthrowu.c
src/pickup.c
src/steal.c
src/uhitm.c
src/worn.c
src/zap.c

index 5c84a82a57efe146723e289481b34e92fa0dae38..ff3b7450314fd790caa71d1d33d3502a9e1876d7 100644 (file)
@@ -3101,6 +3101,8 @@ extern void bypass_objlist(struct obj *, boolean);
 extern struct obj *nxt_unbypassed_obj(struct obj *);
 extern struct obj *nxt_unbypassed_loot(Loot *, struct obj *);
 extern int racial_exception(struct monst *, struct obj *);
+extern void extract_from_minvent(struct monst *, struct obj *, boolean,
+                                 boolean);
 
 /* ### write.c ### */
 
index e57d7b40e72f999ecb5b603b779b43fd4875e818..9cae221457c29394f1a74869b7c956b434880890 100644 (file)
@@ -1878,21 +1878,11 @@ remove_object(struct obj* otmp)
 void
 discard_minvent(struct monst* mtmp, boolean uncreate_artifacts)
 {
-    struct obj *otmp, *mwep = MON_WEP(mtmp);
-    boolean keeping_mon = !DEADMONSTER(mtmp);
+    struct obj *otmp;
 
     while ((otmp = mtmp->minvent) != 0) {
         /* this has now become very similar to m_useupall()... */
-        obj_extract_self(otmp);
-        if (otmp->owornmask) {
-            if (keeping_mon) {
-                if (otmp == mwep)
-                    mwepgone(mtmp), mwep = 0;
-                mtmp->misc_worn_check &= ~otmp->owornmask;
-                update_mon_intrinsics(mtmp, otmp, FALSE, TRUE);
-            }
-            otmp->owornmask = 0L; /* obfree() expects this */
-        }
+        extract_from_minvent(mtmp, otmp, TRUE, TRUE);
         if (uncreate_artifacts && otmp->oartifact)
             artifact_exists(otmp, safe_oname(otmp), FALSE);
         obfree(otmp, (struct obj *) 0); /* dealloc_obj() isn't sufficient */
index 9932594bdb781fc07d65c0d109e9870ee091deae..782d68a7d37e3a8f3314e4983de7cdad8b655c2c 100644 (file)
--- a/src/mon.c
+++ b/src/mon.c
@@ -2597,13 +2597,7 @@ monstone(struct monst* mdef)
         oldminvent = 0;
         /* some objects may end up outside the statue */
         while ((obj = mdef->minvent) != 0) {
-            obj_extract_self(obj);
-            if (obj->owornmask)
-                update_mon_intrinsics(mdef, obj, FALSE, TRUE);
-            obj_no_longer_held(obj);
-            if (obj->owornmask & W_WEP)
-                setmnotwielded(mdef, obj);
-            obj->owornmask = 0L;
+            extract_from_minvent(mdef, obj, TRUE, TRUE);
             if (obj->otyp == BOULDER
 #if 0 /* monsters don't carry statues */
                 ||  (obj->otyp == STATUE
index 8dd7be62660cc6c1e73c826f891cea992e9d3201..a4507f4e6f334eeecf919155d0d7125729061abc 100644 (file)
@@ -842,20 +842,11 @@ breamm(struct monst* mtmp, struct attack* mattk, struct monst* mtarg)
     return MM_HIT;
 }
 
-
-
 /* remove an entire item from a monster's inventory; destroy that item */
 void
 m_useupall(struct monst* mon, struct obj* obj)
 {
-    obj_extract_self(obj);
-    if (obj->owornmask) {
-        if (obj == MON_WEP(mon))
-            mwepgone(mon);
-        mon->misc_worn_check &= ~obj->owornmask;
-        update_mon_intrinsics(mon, obj, FALSE, FALSE);
-        obj->owornmask = 0L;
-    }
+    extract_from_minvent(mon, obj, TRUE, FALSE);
     obfree(obj, (struct obj *) 0);
 }
 
index 6db657dd7f1d272451d8607a1d0b32f42508c46a..25a860671090aad10ab2db6abf06ce881e7efcc6 100644 (file)
@@ -2104,8 +2104,6 @@ loot_mon(struct monst *mtmp, int *passed_info, boolean *prev_loot)
      *  *prev_loot is set to TRUE if something was actually acquired in here.
      */
     if (mtmp && mtmp != u.usteed && (otmp = which_armor(mtmp, W_SADDLE))) {
-        long unwornmask;
-
         if (passed_info)
             *passed_info = 1;
         Sprintf(qbuf, "Do you want to remove the saddle from %s?",
@@ -2123,12 +2121,7 @@ loot_mon(struct monst *mtmp, int *passed_info, boolean *prev_loot)
                 /* the attempt costs you time */
                 return 1;
             }
-            obj_extract_self(otmp);
-            if ((unwornmask = otmp->owornmask) != 0L) {
-                mtmp->misc_worn_check &= ~unwornmask;
-                otmp->owornmask = 0L;
-                update_mon_intrinsics(mtmp, otmp, FALSE, FALSE);
-            }
+            extract_from_minvent(mtmp, otmp, TRUE, FALSE);
             otmp = hold_another_object(otmp, "You drop %s!", doname(otmp),
                                        (const char *) 0);
             nhUse(otmp);
index cfd3fcfdfb73251936450de35a40fe14cdeff76a..b5e40329dbee0d4ace227212c2a5e9fc824e6609 100644 (file)
@@ -671,27 +671,16 @@ mdrop_obj(
     boolean verbosely)
 {
     int omx = mon->mx, omy = mon->my;
-    boolean update_mon = FALSE;
-
-    if (obj->owornmask) {
-        /* perform worn item handling if the monster is still alive */
-        if (!DEADMONSTER(mon)) {
-            mon->misc_worn_check &= ~obj->owornmask;
-            update_mon = TRUE;
-
-        /* don't charge for an owned saddle on dead steed (provided
-           that the hero is within the same shop at the time) */
-        } else if (mon->mtame && (obj->owornmask & W_SADDLE) != 0L
-                   && !obj->unpaid && costly_spot(omx, omy)
-                   /* being at costly_spot guarantees lev->roomno is not 0 */
-                   && index(in_rooms(u.ux, u.uy, SHOPBASE),
-                            levl[omx][omy].roomno)) {
-            obj->no_charge = 1;
-        }
-        /* this should be done even if the monster has died */
-        if (obj->owornmask & W_WEP)
-            setmnotwielded(mon, obj);
-        obj->owornmask = 0L;
+    boolean unwornmask = obj->owornmask;
+
+    extract_from_minvent(mon, obj, FALSE, TRUE);
+    /* don't charge for an owned saddle on dead steed (provided
+        that the hero is within the same shop at the time) */
+    if (unwornmask && mon->mtame && (unwornmask & W_SADDLE) != 0L
+        && !obj->unpaid && costly_spot(omx, omy)
+        /* being at costly_spot guarantees lev->roomno is not 0 */
+        && index(in_rooms(u.ux, u.uy, SHOPBASE), levl[omx][omy].roomno)) {
+        obj->no_charge = 1;
     }
     /* obj_no_longer_held(obj); -- done by place_object */
     if (verbosely && cansee(omx, omy))
@@ -701,8 +690,9 @@ mdrop_obj(
         stackobj(obj);
     }
     /* do this last, after placing obj on floor; removing steed's saddle
-       throws rider, possibly inflicting fatal damage and producing bones */
-    if (update_mon)
+       throws rider, possibly inflicting fatal damage and producing bones; this
+       is why we had to call extract_from_minvent() with do_intrinsics=FALSE */
+    if (!DEADMONSTER(mon) && unwornmask)
         update_mon_intrinsics(mon, obj, FALSE, TRUE);
 }
 
@@ -721,16 +711,10 @@ mdrop_special_objs(struct monst* mon)
            current role's quest artifact is rescued too--quest artifacts
            for the other roles are not */
         if (obj_resists(obj, 0, 0) || is_quest_artifact(obj)) {
-            obj_extract_self(obj);
             if (mon->mx) {
                 mdrop_obj(mon, obj, FALSE);
             } else { /* migrating monster not on map */
-                if (obj->owornmask) {
-                    mon->misc_worn_check &= ~obj->owornmask;
-                    if (obj->owornmask & W_WEP)
-                        setmnotwielded(mon, obj);
-                    obj->owornmask = 0L;
-                }
+                extract_from_minvent(mon, obj, TRUE, TRUE);
                 rloco(obj);
             }
         }
@@ -757,7 +741,6 @@ relobj(
     } /* isgd && has gold */
 
     while ((otmp = (is_pet ? droppables(mtmp) : mtmp->minvent)) != 0) {
-        obj_extract_self(otmp);
         mdrop_obj(mtmp, otmp, is_pet && flags.verbose);
     }
 
index 3456259f29ef6b600a8028e07b2cc6efacfeb1a0..756929f24d55be4bc96ad2f781f585be057d3747 100644 (file)
@@ -1626,22 +1626,14 @@ steal_it(struct monst *mdef, struct attack *mattk)
             mpickobj(mdef, gold), gold = 0;
         if (!Upolyd)
             break; /* no longer have ability to steal */
+        unwornmask = otmp->owornmask;
         /* take the object away from the monster */
-        obj_extract_self(otmp);
-        if ((unwornmask = otmp->owornmask) != 0L) {
-            mdef->misc_worn_check &= ~unwornmask;
-            if (otmp->owornmask & W_WEP)
-                setmnotwielded(mdef, otmp);
-            otmp->owornmask = 0L;
-            update_mon_intrinsics(mdef, otmp, FALSE, FALSE);
-            /* give monster a chance to wear other equipment on its next
-               move instead of waiting until it picks something up */
-            mdef->misc_worn_check |= I_SPECIAL;
-
-            if (otmp == ustealo) /* special message for final item */
-                pline("%s finishes taking off %s suit.", Monnam(mdef),
-                      mhis(mdef));
-        }
+        extract_from_minvent(mdef, otmp, TRUE, FALSE);
+        /* special message for final item; no need to check owornmask because
+         * ustealo is only set on objects with (owornmask & W_ARM) */
+        if (otmp == ustealo)
+            pline("%s finishes taking off %s suit.", Monnam(mdef),
+                  mhis(mdef));
         /* give the object to the character */
         otmp = hold_another_object(otmp, "You snatched but dropped %s.",
                                    doname(otmp), "You steal: ");
@@ -3917,17 +3909,7 @@ mhitm_ad_sedu(struct monst *magr, struct attack *mattk, struct monst *mdef,
             if (u.usteed == mdef && obj == which_armor(mdef, W_SADDLE))
                 /* "You can no longer ride <steed>." */
                 dismount_steed(DISMOUNT_POLY);
-            obj_extract_self(obj);
-            if (obj->owornmask) {
-                mdef->misc_worn_check &= ~obj->owornmask;
-                if (obj->owornmask & W_WEP)
-                    mwepgone(mdef);
-                obj->owornmask = 0L;
-                update_mon_intrinsics(mdef, obj, FALSE, FALSE);
-                /* give monster a chance to wear other equipment on its next
-                   move instead of waiting until it picks something up */
-                mdef->misc_worn_check |= I_SPECIAL;
-            }
+            extract_from_minvent(mdef, obj, TRUE, FALSE);
             /* add_to_minv() might free 'obj' [if it merges] */
             if (g.vis)
                 Strcpy(onambuf, doname(obj));
index 0b35ad4925bd41f0396f3a6a54f7f11a7f8e9db8..53c9b951ccb51f92f8cbac5c289f15dd88fa3678 100644 (file)
@@ -709,12 +709,7 @@ which_armor(struct monst *mon, long flag)
 static void
 m_lose_armor(struct monst *mon, struct obj *obj)
 {
-    mon->misc_worn_check &= ~obj->owornmask;
-    if (obj->owornmask)
-        update_mon_intrinsics(mon, obj, FALSE, FALSE);
-    obj->owornmask = 0L;
-
-    obj_extract_self(obj);
+    extract_from_minvent(mon, obj, TRUE, FALSE);
     place_object(obj, mon->mx, mon->my);
     /* call stackobj() if we ever drop anything that can merge */
     newsym(mon->mx, mon->my);
@@ -1039,4 +1034,39 @@ racial_exception(struct monst *mon, struct obj *obj)
 
     return 0;
 }
+
+/* Remove an object from a monster's inventory.
+ * At its core this is just obj_extract_self(), but it also handles any updates
+ * that needs to happen if the gear is equipped or in some other sort of state
+ * that needs handling.
+ * Note that like obj_extract_self(), this leaves obj free. */
+void
+extract_from_minvent(struct monst *mon, struct obj *obj,
+                     boolean do_intrinsics, /* whether to call
+                                               update_mon_intrinsics */
+                     boolean silently) /* doesn't affect all possible messages,
+                                          just update_mon_intrinsics's */
+{
+    long unwornmask = obj->owornmask;
+
+    if (obj->where != OBJ_MINVENT) {
+        impossible("extract_from_minvent called on object not in minvent");
+        return;
+    }
+    obj_extract_self(obj);
+    obj->owornmask = 0L;
+    if (unwornmask) {
+        if (!DEADMONSTER(mon) && do_intrinsics) {
+            update_mon_intrinsics(mon, obj, FALSE, silently);
+        }
+        mon->misc_worn_check &= ~unwornmask;
+        /* give monster a chance to wear other equipment on its next
+           move instead of waiting until it picks something up */
+        mon->misc_worn_check |= I_SPECIAL;
+    }
+    obj_no_longer_held(obj);
+    if (unwornmask & W_WEP) {
+        mwepgone(mon); /* unwields and sets weapon_check to NEED_WEAPON */
+    }
+}
 /*worn.c*/
index 67de59d3b83c33872d76f2c3cfbfa022629fcd70..3b210789de437abb166bd0c82ea612b91a0f701e 100644 (file)
--- a/src/zap.c
+++ b/src/zap.c
@@ -347,7 +347,6 @@ bhitm(struct monst *mtmp, struct obj *otmp)
             } else if (canspotmon(mtmp)) {
                 pline("%s falls off.", buf);
             }
-            obj_extract_self(obj);
             mdrop_obj(mtmp, obj, FALSE);
         }
         break;
@@ -4052,16 +4051,7 @@ disintegrate_mon(struct monst *mon,
     for (otmp = mon->minvent; otmp; otmp = otmp2) {
         otmp2 = otmp->nobj;
         if (!oresist_disintegration(otmp)) {
-            if (otmp->owornmask) {
-                /* in case monster's life gets saved */
-                mon->misc_worn_check &= ~otmp->owornmask;
-                if (otmp->owornmask & W_WEP)
-                    setmnotwielded(mon, otmp);
-                /* also dismounts hero if this object is steed's saddle */
-                update_mon_intrinsics(mon, otmp, FALSE, TRUE);
-                otmp->owornmask = 0L;
-            }
-            obj_extract_self(otmp);
+            extract_from_minvent(mon, otmp, TRUE, TRUE);
             obfree(otmp, (struct obj *) 0);
         }
     }