]> granicus.if.org Git - nethack/commitdiff
retouch_equipment() bypass handling
authornethack.rankin <nethack.rankin>
Thu, 7 Nov 2013 01:03:16 +0000 (01:03 +0000)
committernethack.rankin <nethack.rankin>
Thu, 7 Nov 2013 01:03:16 +0000 (01:03 +0000)
     Simplify retouch_equipment (post-3.4.3.code, called when hero
changes alignment or turns into a silver-hating critter; inventory
traversal must cope with the possibility of losing object->nobj when
processing object) by switching to recently added object->bypass code.

src/artifact.c

index 9d6e7f327efa89f784e1434d9126a0b15b9a7788..52ebef02d0a1816c8512109a46c21988df3f249c 100644 (file)
@@ -1809,9 +1809,6 @@ boolean drop_untouchable;
     boolean beingworn, carryeffect, invoked;
     long wearmask = ~(W_QUIVER | (u.twoweap ? 0L : W_SWAPWEP) | W_BALL);
 
-    if (obj->bypass) return FALSE;     /* already handled */
-    bypass_obj(obj);   /* mark it as handled now */
-
     beingworn = (obj->owornmask & wearmask) != 0L ||
                /* some items in use don't have any wornmask setting */
                (obj->oclass == TOOL_CLASS &&
@@ -1841,16 +1838,27 @@ boolean drop_untouchable;
     return FALSE;
 }
 
-/* check items currently in use (mostly worn) for touchability */
+/* check all items currently in use (mostly worn) for touchability */
 void
 retouch_equipment(dropflag)
 int dropflag;  /* 0==don't drop, 1==drop all, 2==drop weapon */
 {
     static int nesting = 0;    /* recursion control */
     struct obj *obj;
-    boolean scanagain, dropit, had_gloves = (uarmg != 0);
+    boolean dropit, had_gloves = (uarmg != 0);
     int had_rings = (!!uleft + !!uright);
 
+    /*
+     * We can potentially be called recursively if losing/unwearing
+     * an item causes worn helm of opposite alignment to come off or
+     * be destroyed.
+     *
+     * BUG: if the initial call was due to putting on a helm of
+     * opposite alignment and it does come off to trigger recursion,
+     * after the inner call executes, the outer call will finish
+     * using the non-helm alignment rather than the helm alignment
+     * which triggered this in the first place.
+     */
     if (!nesting++) clear_bypasses();  /* init upon initial entry */
 
     dropit = (dropflag > 0);   /* drop all or drop weapon */
@@ -1872,27 +1880,17 @@ int dropflag;   /* 0==don't drop, 1==drop all, 2==drop weapon */
      * TODO?  Force off gloves if either or both rings are going to
      * become unworn; force off cloak [suit] before suit [shirt].
      * The torso handling is hyphothetical; the case for gloves is
-     * not due the possibility of unwearing silver rings.
+     * not, due to the possibility of unwearing silver rings.
      */
 
     dropit = (dropflag == 1);  /* all untouchable items */
-    do {
-       scanagain = FALSE;  
-
-       for (obj = invent; obj; obj = obj->nobj) {
-           if (obj->bypass) continue;
-
-           if (untouchable(obj, dropit)) {     /* always sets obj->bypass */
-               /* can't directly continue inventory traversal;
-                  hero might have lost levitation, causing items to
-                  be dropped or destroyed (poly trap, water, lava);
-                  might even have lost helm of opposite alignment
-                  and caused us to be called recursively... */
-               scanagain = TRUE;
-               break;  /* use outer loop to restart inner one */
-           }
-       }
-    } while (scanagain);
+    /* loss of levitation (silver ring, or Heart of Ahriman invocation)
+       might cause hero to lose inventory items (by dropping into lava,
+       for instance), so inventory traversal needs to rescan the whole
+       invent chain each time it moves on to another object; we use bypass
+       handling to keep track of which items have already been processed */
+    while ((obj = nxt_unbypassed_obj(invent)) != 0)
+       (void) untouchable(obj, dropit);
 
     if (had_rings != (!!uleft + !!uright) && uarmg && uarmg->cursed)
        uncurse(uarmg); /* temporary? hack for ring removal plausibility */