]> granicus.if.org Git - nethack/commitdiff
yet another pass at 'A' bugs
authorPatR <rankin@nethack.org>
Thu, 8 Jun 2017 22:05:24 +0000 (15:05 -0700)
committerPatR <rankin@nethack.org>
Thu, 8 Jun 2017 22:05:24 +0000 (15:05 -0700)
I think this finally quashes the "cursed without otmp" issue.
Various ways of destroying wielded weapon used setnotworn() rather
than unwield(), so the previous change to have unwield() clear the
pending W_WEP bit from takeoff.mask wasn't sufficient to prevent
'A' moving on from another item (blindfold--it's the only thing
processed before primary weapon) to weapon which wasn't there any
more.  Also, if weapon was already set in takeoff.what to be
processed on the next move, clearing W_WEP from takeoff.mask wasn't
sufficient either.

Move the previous unwield() 'fix' to setworn() and setnotworn() and
extend it to include cancel_don() if the item being replaced or
removed is in progress or scheduled for next.  (Most of the time,
remove_worn_item() has already done that before setworn() or
setnotworn() is called.)

doc/fixes36.1
include/extern.h
src/do_wear.c
src/wield.c
src/worn.c

index 4a43125d109ec3698923fbb125aa892c78807b82..bf5df58cb7914b13349634f6529c07e2feb16174 100644 (file)
@@ -379,7 +379,9 @@ levitation vs encumbrance message sequencing issues:  putting on boots of
        and float-up messages, taking off such boots didn't report increase
        of encumbrance until player took another action
 removing a blindfold with 'A' took two turns, with 'R' (and 'T') only one,
-       and could result in a panic if the blindfold was stolen during removal
+       and could result in a crash if the blindfold was stolen during removal
+removing a blindfold and wielded weapon with 'A' could result in crash if the
+       weapon was destroyed by various methods
 cmdassist help for movement prefix followed by invalid direction was strange
        when the direction was up, down, or self disallowed for that prefix
 poor message when shape-shifted vampire reverts to vampire if it has a name:
@@ -396,6 +398,7 @@ adult green dragons and the Chromatic Dragon were blinded by gas clouds
 named floating eye (when hit by another monster with reflection) or named
        silver weapon (when hero hits silver-hating monster) could disrupt
        message formatting and conceivably trigger crash if name had '%' in it
+crashes for 'A' above were downgraded to impossible "cursed without otmp"
 
 
 Fixes to Post-3.6.0 Problems that Were Exposed Via git Repository
index 58a451c67aefe4fa1f25d3cbba41f635f680eaa9..72df6d58dee17fd5ec673a096ab580d1ef24be7b 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 extern.h        $NHDT-Date: 1496860756 2017/06/07 18:39:16 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.590 $ */
+/* NetHack 3.6 extern.h        $NHDT-Date: 1496959470 2017/06/08 22:04:30 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.591 $ */
 /* Copyright (c) Steve Creps, 1988.                              */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -436,6 +436,7 @@ E void FDECL(off_msg, (struct obj *));
 E void FDECL(set_wear, (struct obj *));
 E boolean FDECL(donning, (struct obj *));
 E boolean FDECL(doffing, (struct obj *));
+E void FDECL(cancel_doff, (struct obj *, long));
 E void NDECL(cancel_don);
 E int FDECL(stop_donning, (struct obj *));
 E int NDECL(Armor_off);
index 2d16d34d1da01b43b78fdffdf228fcc762d2caee..71599fd7a74a39598bb1470787a7c79fe8d956f8 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 do_wear.c       $NHDT-Date: 1496614914 2017/06/04 22:21:54 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.97 $ */
+/* NetHack 3.6 do_wear.c       $NHDT-Date: 1496959478 2017/06/08 22:04:38 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.98 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1207,7 +1207,7 @@ struct obj *otmp;
 {
     boolean result = FALSE;
 
-    /* 'W' and 'T' set afternmv, 'A' sets context.takeoff.what */
+    /* 'W' (or 'P' used for armor) sets afternmv */
     if (doffing(otmp))
         result = TRUE;
     else if (otmp == uarm)
@@ -1237,7 +1237,7 @@ struct obj *otmp;
     long what = context.takeoff.what;
     boolean result = FALSE;
 
-    /* 'T' (also 'W') sets afternmv, 'A' sets context.takeoff.what */
+    /* 'T' (or 'R' used for armor) sets afternmv, 'A' sets takeoff.what */
     if (otmp == uarm)
         result = (afternmv == Armor_off || what == WORN_ARMOR);
     else if (otmp == uarmu)
@@ -1252,8 +1252,7 @@ struct obj *otmp;
         result = (afternmv == Gloves_off || what == WORN_GLOVES);
     else if (otmp == uarms)
         result = (afternmv == Shield_off || what == WORN_SHIELD);
-    /* these 1-turn items don't need 'afternmv' checks
-       [and may not actually need 'what' checks] */
+    /* these 1-turn items don't need 'afternmv' checks */
     else if (otmp == uamul)
         result = (what == WORN_AMUL);
     else if (otmp == uleft)
@@ -1272,6 +1271,29 @@ struct obj *otmp;
     return result;
 }
 
+/* despite their names, cancel_don() and cancel_doff() both apply to both
+   donning and doffing... */
+void
+cancel_doff(obj, slotmask)
+struct obj *obj;
+long slotmask;
+{
+    /* Called by setworn() for old item in specified slot or by setnotworn()
+     * for specified item.  We don't want to call cancel_don() if we got
+     * here via <X>_off() -> setworn((struct obj *)0) -> cancel_doff()
+     * because that would stop the 'A' command from continuing with next
+     * selected item.  So do_takeoff() sets a flag in takeoff.mask for us.
+     * [For taking off an individual item with 'T'/'R'/'w-', it doesn't
+     * matter whether cancel_don() gets called here--the item has already
+     * been removed by now.]
+     */
+    if (!(context.takeoff.mask & I_SPECIAL) && donning(obj))
+        cancel_don(); /* applies to doffing too */
+    context.takeoff.mask &= ~slotmask;
+}
+
+/* despite their names, cancel_don() and cancel_doff() both apply to both
+   donning and doffing... */
 void
 cancel_don()
 {
@@ -1308,7 +1330,7 @@ struct obj *stolenobj; /* no message if stolenobj is already being doffing */
 
     /* donning() returns True when doffing too; doffing() is more specific */
     putting_on = !doffing(otmp);
-    /* cancel_don() looks at afternmv; it also serves as cancel_doff() */
+    /* cancel_don() looks at afternmv; it can also cancel doffing */
     cancel_don();
     /* don't want <armor>_on() or <armor>_off() being called
        by unmul() since the on or off action isn't completing */
@@ -2302,6 +2324,7 @@ do_takeoff()
     struct obj *otmp = (struct obj *) 0;
     struct takeoff_info *doff = &context.takeoff;
 
+    context.takeoff.mask |= I_SPECIAL; /* set flag for cancel_doff() */
     if (doff->what == W_WEP) {
         if (!cursed(uwep)) {
             setuwep((struct obj *) 0);
@@ -2361,6 +2384,7 @@ do_takeoff()
     } else {
         impossible("do_takeoff: taking off %lx", doff->what);
     }
+    context.takeoff.mask &= ~I_SPECIAL; /* clear cancel_doff() flag */
 
     return otmp;
 }
@@ -2378,10 +2402,9 @@ take_off(VOID_ARGS)
         if (doff->delay > 0) {
             doff->delay--;
             return 1; /* still busy */
-        } else {
-            if ((otmp = do_takeoff()))
-                off_msg(otmp);
         }
+        if ((otmp = do_takeoff()) != 0)
+            off_msg(otmp);
         doff->mask &= ~doff->what;
         doff->what = 0L;
     }
index d2f51a2ee3e71ff449fbbf95e4e223346d8fa5ad..bd176a8126e3c106a07dc6088ee374e7f2a048d1 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 wield.c $NHDT-Date: 1496614915 2017/06/04 22:21:55 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */
+/* NetHack 3.6 wield.c $NHDT-Date: 1496959480 2017/06/08 22:04:40 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.54 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -676,10 +676,6 @@ uwepgone()
                 pline("%s shining.", Tobjnam(uwep, "stop"));
         }
         setworn((struct obj *) 0, W_WEP);
-        /* update takeoff mask in case uwep has just gone away while
-           its removal via 'A' was pending, similar to what the various
-           Xyzzy_off(do_wear.c) routines do for armor and accessories */
-        context.takeoff.mask &= ~W_WEP;
         unweapon = TRUE;
         update_inventory();
     }
@@ -690,7 +686,6 @@ uswapwepgone()
 {
     if (uswapwep) {
         setworn((struct obj *) 0, W_SWAPWEP);
-        context.takeoff.mask &= ~W_SWAPWEP;
         update_inventory();
     }
 }
@@ -700,7 +695,6 @@ uqwepgone()
 {
     if (uquiver) {
         setworn((struct obj *) 0, W_QUIVER);
-        context.takeoff.mask &= ~W_QUIVER;
         update_inventory();
     }
 }
index a99d1336d80cafeeb14683a16359944f33405989..abc1d4c3e8d91d1d1ca06947b2db2e21325bb2a6 100644 (file)
@@ -1,4 +1,4 @@
-/* NetHack 3.6 worn.c  $NHDT-Date: 1493510127 2017/04/29 23:55:27 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
+/* NetHack 3.6 worn.c  $NHDT-Date: 1496959481 2017/06/08 22:04:41 $  $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -77,6 +77,9 @@ long mask;
                         if (oobj->oartifact)
                             set_artifact_intrinsic(oobj, 0, mask);
                     }
+                    /* in case wearing or removal is in progress or removal
+                       is pending (via 'A' command for multiple items) */
+                    cancel_doff(oobj, wp->w_mask);
                 }
                 *(wp->w_obj) = obj;
                 if (obj) {
@@ -119,6 +122,10 @@ register struct obj *obj;
         u.twoweap = 0;
     for (wp = worn; wp->w_mask; wp++)
         if (obj == *(wp->w_obj)) {
+            /* in case wearing or removal is in progress or removal
+               is pending (via 'A' command for multiple items) */
+            cancel_doff(obj, wp->w_mask);
+
             *(wp->w_obj) = 0;
             p = objects[obj->otyp].oc_oprop;
             u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;