]> granicus.if.org Git - nethack/commitdiff
fix 'D' vs obj->bypass
authorPatR <rankin@nethack.org>
Wed, 29 Jun 2022 18:46:31 +0000 (11:46 -0700)
committerPatR <rankin@nethack.org>
Wed, 29 Jun 2022 18:46:31 +0000 (11:46 -0700)
Reported by entrez:  dropping items with the 'D' command sets
obj->bypass which prevents an otherwise compatible item from merging
with non-bypass floor stack.

'D' sets the bypass bit to avoid trouble if a dropped item triggers
an explosion that destroys some of inventory (making straightforward
invent traversal be unreliable).  Having bypass set prevented merging
with a floor stack that had that flag bit clear.  That was very
noticeable if a subset of a stack was picked up and then 'D' used to
drop it again, resulting in two stacks instead of recombining into
the original.

Change the test for mergability to ignore bypass so items will merge
when one has it set and other doesn't.  And when successfully merging
set bypass on the combined stack if either part had that set.

doc/fixes3-7-0.txt
src/invent.c

index ca4ef5a93e08605c3d089f5106b53cf99a4ab710..791ecbe4325b740c7f119824ec3b63fbf477bc21 100644 (file)
@@ -942,6 +942,8 @@ a migrating long worm that couldn't arrive could be placed at <0,0> while
        setting up another migration attempt to the level, triggering
         impossible "trying to place long worm tail at <0,0> mstate:8 on level"
        (message is confused; it should say "long worm" without tail)
+dropping things with 'D' wouldn't merge them with compatible items already at
+       that floor spot because use of obj->bypass made them seem incompatible
 
 
 Fixes to 3.7.0-x Problems that Were Exposed Via git Repository
index 4ed9a1d84081a49a7377a1f5f0ab7902e85209d7..9db3c1d98f894e72f3a80478139c7e15ce3c5951 100644 (file)
@@ -770,6 +770,17 @@ merged(struct obj **potmp, struct obj **pobj)
 #endif /*0*/
         }
 
+        /* mergable() no longer requires 'bypass' to match; if 'obj' has
+           the bypass bit set, force the combined stack to have that too;
+           primarily in case this merge is occurring because stackobj()
+           is operating on an object just dropped by a monster that was
+           zapped with polymorph, we want bypass set in order to inhibit
+           the same zap from affecting the new combined stack when it hits
+           objects at the monster's spot (but also in case we're called by
+           code that's using obj->bypass to track 'already processed') */
+        if (obj->bypass)
+            otmp->bypass = 1;
+
         /* handle puddings a bit differently; absorption will free the
            other object automatically so we can just return out from here */
         if (obj->globby) {
@@ -4273,6 +4284,8 @@ feel_cockatrice(struct obj *otmp, boolean force_touch)
     }
 }
 
+/* 'obj' is being placed on the floor; if it can merge with something that
+   is already there, combine them and discard obj as a separate object */
 void
 stackobj(struct obj *obj)
 {
@@ -4286,7 +4299,9 @@ stackobj(struct obj *obj)
 
 /* returns TRUE if obj & otmp can be merged; used in invent.c and mkobj.c */
 boolean
-mergable(register struct obj *otmp, register struct obj *obj)
+mergable(
+    register struct obj *otmp, /* potential 'into' stack */
+    register struct obj *obj)  /* 'combine' stack */
 {
     size_t objnamelth = 0, otmpnamelth = 0;
 
@@ -4300,9 +4315,14 @@ mergable(register struct obj *otmp, register struct obj *obj)
     if (obj->oclass == COIN_CLASS)
         return TRUE;
 
-    if (obj->bypass != otmp->bypass
-        || obj->cursed != otmp->cursed || obj->blessed != otmp->blessed)
+    if (obj->cursed != otmp->cursed || obj->blessed != otmp->blessed)
+        return FALSE;
+#if 0   /* don't require 'bypass' to match; that results in items dropped
+         * via 'D' not stacking with compatible items already on the floor;
+         * caller who wants that behavior should use 'nomerge' instead */
+    if (obj->bypass != otmp->bypass)
         return FALSE;
+#endif
 
     if (obj->globby)
         return TRUE;