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.
This commit is contained in:
nethack.rankin
2003-12-03 07:10:24 +00:00
parent b7a2c26248
commit 3df53e952c
3 changed files with 33 additions and 29 deletions

View 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

View File

@@ -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);
}

View 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);