fix #K3603 - multiple stacks of gold in container

When taking stuff out of a container, specifying a subset count for
an item and getting the pickup_burden prompt, answering 'q' undid the
subset split but answering 'n' did not.  If the item in question was
a stack of gold, the container would end up with two stacks.  That
action could be repeated as long as any of the stacks was big enough
to trigger pickup_burden confirmation so an arbitrary number of gold
stacks could be produced.  (Eventually they would be too small for a
subset to cause an increase in encumbrance, or possibly all reduced
to just one gold piece, then no more stacks could be created.)

Situation occurred for all menustyles; traditional and via-menu needed
separate fixes.  It didn't occur for pickup off the floor.

Report was for 3.6.6 but the bug was still present in dev version.
This commit is contained in:
PatR
2022-06-02 14:44:30 -07:00
parent 57cfd7e7ed
commit afbb7e2827
3 changed files with 33 additions and 22 deletions

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 invent.c $NHDT-Date: 1652861830 2022/05/18 08:17:10 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.389 $ */
/* NetHack 3.7 invent.c $NHDT-Date: 1654205933 2022/06/02 21:38:53 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.391 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Derek S. Ray, 2015. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2205,16 +2205,17 @@ askchain(
/*FALLTHRU*/
case 'y':
tmp = (*fn)(otmp);
if (tmp < 0) {
if (tmp <= 0) {
if (container_gone(fn)) {
/* otmp caused magic bag to explode;
both are now gone */
otmp = 0; /* and return */
} else if (otmp && otmp != otmpo) {
/* split occurred, merge again */
(void) merged(&otmpo, &otmp);
(void) unsplitobj(otmp);
}
goto ret;
if (tmp < 0)
goto ret;
}
cnt += tmp;
if (--mx == 0)

View File

@@ -1,4 +1,4 @@
/* NetHack 3.7 pickup.c $NHDT-Date: 1608673693 2020/12/22 21:48:13 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.273 $ */
/* NetHack 3.7 pickup.c $NHDT-Date: 1654205934 2022/06/02 21:38:54 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.308 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1526,10 +1526,11 @@ carry_count(struct obj *obj, /* object to pick up... */
/* determine whether character is able and player is willing to carry `obj' */
static
int
lift_object(struct obj *obj, /* object to pick up... */
struct obj *container, /* ...bag it's coming out of */
long *cnt_p,
boolean telekinesis)
lift_object(
struct obj *obj, /* object to pick up... */
struct obj *container, /* ...bag it's coming out of */
long *cnt_p,
boolean telekinesis)
{
int result, old_wt, new_wt, prev_encumbr, next_encumbr;
@@ -1621,8 +1622,10 @@ lift_object(struct obj *obj, /* object to pick up... */
* up, 1 if otherwise.
*/
int
pickup_object(struct obj *obj, long count,
boolean telekinesis) /* not picking it up directly by hand */
pickup_object(
struct obj *obj,
long count,
boolean telekinesis) /* not picking it up directly by hand */
{
int res, nearload;
@@ -3119,16 +3122,17 @@ menu_loot(int retry, boolean put_in)
/* special split case also handled by askchain() */
}
res = put_in ? in_container(otmp) : out_container(otmp);
if (res < 0) {
if (res <= 0) {
if (!g.current_container) {
/* otmp caused current_container to explode;
both are now gone */
otmp = 0; /* and break loop */
} else if (otmp && otmp != pick_list[i].item.a_obj) {
/* split occurred, merge again */
(void) merged(&pick_list[i].item.a_obj, &otmp);
(void) unsplitobj(otmp);
}
break;
if (res < 0)
break;
}
}
free((genericptr_t) pick_list);
@@ -3138,8 +3142,13 @@ menu_loot(int retry, boolean put_in)
}
static char
in_or_out_menu(const char *prompt, struct obj *obj, boolean outokay,
boolean inokay, boolean alreadyused, boolean more_containers)
in_or_out_menu(
const char *prompt,
struct obj *obj,
boolean outokay, /* can take out */
boolean inokay, /* can put in */
boolean alreadyused, /* controls phrasing of the decline choice */
boolean more_containers)
{
/* underscore is not a choice; it's used to skip element [0] */
static const char lootchars[] = "_:oibrsnq", abc_chars[] = "_:abcdenq";