From 3df53e952cb7b4a65949096f89fba3418ed0bab3 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Wed, 3 Dec 2003 07:10:24 +0000 Subject: [PATCH] loadstone dropping fix 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 | 2 ++ src/do.c | 44 ++++++++++++++++++++++++-------------------- src/invent.c | 16 +++++++--------- 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/doc/fixes34.3 b/doc/fixes34.3 index 6ceb3dea0..f3631b89e 100644 --- a/doc/fixes34.3 +++ b/doc/fixes34.3 @@ -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 diff --git a/src/do.c b/src/do.c index 80ea45811..c0f175663 100644 --- 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); } diff --git a/src/invent.c b/src/invent.c index ceb632f3e..e6d359674 100644 --- a/src/invent.c +++ b/src/invent.c @@ -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);