]> granicus.if.org Git - nethack/commitdiff
loadstone dropping fix
authornethack.rankin <nethack.rankin>
Wed, 3 Dec 2003 07:10:24 +0000 (07:10 +0000)
committernethack.rankin <nethack.rankin>
Wed, 3 Dec 2003 07:10:24 +0000 (07:10 +0000)
     Fix the reported problem of bad inventory management if the user
specified a count (with traditional menu style) when attempting to drop
part of a stack of cursed loadstones.  After the "you can't drop that"
message, it tried to undo the stack split, but splitobj was changed
sometime back and the undo hack wasn't adjusted to account for the fact
that it needed to merge with the previous object instead of the next one.
The result was that it would incorrectly increment the count of the next
item instead of the original loadstone, or crash in canletgo() if the
split off stone was the last item in the list.

     This prevents cursed loadstones from being split (via getobj()'s
count handling) in the first place, so there's nothing to undo later.
It still uses a similar kludge so that the "can't drop that" message can
be adjusted, but it's now a simpler kludge and I hope a more robust one.

doc/fixes34.3
src/do.c
src/invent.c

index 6ceb3dea06ba9a2edca4c390a2aefb7dd619986d..f3631b89e73ebe379d1421ef20fa33e98828211a 100644 (file)
@@ -97,6 +97,8 @@ must be able to reach floor in order to use stethoscope on corpse or statue
 fix a few coordinate (y,y) -> (x,y) typos in apply.c, mon.c, and wizard.c
 killing a long worm on a drawbridge could produce a panic
 prevent "see it drop from your pack" when figurine monster becomes undetected
+attempting to drop a subset of a stack of multiple cursed loadstones could
+       corrupt inventory or cause a crash
 
 
 Platform- and/or Interface-Specific Fixes
index 80ea458113bf191a505107d7f9897b1d6b2168f3..c0f175663eb06e6c6ce876175fdeaa719e90a8ba 100644 (file)
--- a/src/do.c
+++ b/src/do.c
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)do.c       3.4     2003/04/25      */
+/*     SCCS Id: @(#)do.c       3.4     2003/12/02      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -406,20 +406,18 @@ register const char *word;
                return(FALSE);
        }
        if (obj->otyp == LOADSTONE && obj->cursed) {
-               if (*word)
-                       pline("For some reason, you cannot %s the stone%s!",
-                               word, plur(obj->quan));
-               /* Kludge -- see invent.c */
-               if (obj->corpsenm) {
-                       struct obj *otmp;
-
-                       otmp = obj;
-                       obj = obj->nobj;
-                       obj->quan += otmp->quan;
-                       obj->owt = weight(obj);
-                       freeinv(otmp);
-                       obfree(otmp, obj);
+               /* getobj() kludge sets corpsenm to user's specified count
+                  when refusing to split a stack of cursed loadstones */
+               if (*word) {
+                       /* getobj() ignores a count for throwing since that is
+                          implicitly forced to be 1; replicate its kludge... */
+                       if (!strcmp(word, "throw") && obj->quan > 1L)
+                           obj->corpsenm = 1;
+                       pline("For some reason, you cannot %s%s the stone%s!",
+                             word, obj->corpsenm ? " any of" : "",
+                             plur(obj->quan));
                }
+               obj->corpsenm = 0;              /* reset */
                obj->bknown = 1;
                return(FALSE);
        }
@@ -694,14 +692,20 @@ int retry;
            for (i = 0; i < n; i++) {
                otmp = pick_list[i].item.a_obj;
                cnt = pick_list[i].count;
-               if (cnt < otmp->quan && !welded(otmp) &&
-                       (!otmp->cursed || otmp->otyp != LOADSTONE)) {
+               if (cnt < otmp->quan) {
+                   if (welded(otmp)) {
+                       ;       /* don't split */
+                   } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
+                       /* same kludge as getobj(), for canletgo()'s use */
+                       otmp->corpsenm = (int) cnt;     /* don't split */
+                   } else {
 #ifndef GOLDOBJ
-                   if (otmp->oclass == COIN_CLASS)
-                       (void) splitobj(otmp, otmp->quan - cnt);
-                   else
+                       if (otmp->oclass == COIN_CLASS)
+                           (void) splitobj(otmp, otmp->quan - cnt);
+                       else
 #endif
-                   otmp = splitobj(otmp, cnt);
+                           otmp = splitobj(otmp, cnt);
+                   }
                }
                n_dropped += drop(otmp);
            }
index ceb632f3e577fd66cd35d8a5f4a8b15e598be6ba..e6d359674d6739e3d0f573c46b93f8fbf0657fb7 100644 (file)
@@ -1,4 +1,4 @@
-/*     SCCS Id: @(#)invent.c   3.4     2003/11/18      */
+/*     SCCS Id: @(#)invent.c   3.4     2003/12/02      */
 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
 /* NetHack may be freely redistributed.  See license for details. */
 
@@ -1065,14 +1065,12 @@ register const char *let,*word;
        if(allowcnt == 2) {     /* cnt given */
            if(cnt == 0) return (struct obj *)0;
            if(cnt != otmp->quan) {
-               otmp = splitobj(otmp, cnt);
-               /* Very ugly kludge necessary to prevent someone from trying
-                * to drop one of several loadstones and having the loadstone
-                * now be separate.
-                */
-               if (!strcmp(word, "drop") &&
-                   otmp->otyp == LOADSTONE && otmp->cursed)
-                   otmp->corpsenm = otmp->invlet;
+               /* don't split a stack of cursed loadstones */
+               if (otmp->otyp == LOADSTONE && otmp->cursed)
+                   /* kludge for canletgo()'s can't-drop-this message */
+                   otmp->corpsenm = (int) cnt;
+               else
+                   otmp = splitobj(otmp, cnt);
            }
        }
        return(otmp);