address #H5426 - inventory category selections
Report #5426 was classified as not-a-bug, but the underlying issue can be improved. For item selection where BUCX (bless/curse state) filtering is supported (mostly for menustyle:Full, but there are a few actions where Traditional and Combination handle BUCX too), 3.4.3 took the union of object class and bless/curse state (so ?!B gave all scrolls and all potions and every blessed item from other classes) but 3.6.0 changed that to the intersection (so ?!B gives blessed scrolls and blessed potions, period). Since gold is inherently not blessed or cursed it has been getting excluded during intersection handling when that includes BUCX filtering. Report #5426 was from a player who was used to choosing $X when putting newly acquired loot into a container asking to have the old behavior reinstated. The ideal fix would be to support both union ($ | X) and intersection (?! & B), but implementation would be bug prone and the interface, especially when done for menus, would be cumbersome. Instead, this adds new boolean option, goldX, to allow the player to decide whether gold is classified as uncursed--even though it is never described as such--or unknown. The new-loot-into-container issued can be solved either via $abcX, where abc lists all classes that have any X items (when gold is included as one of the classes, its BUCX state is now ignored for the current selection), or by setting the goldX option and then just picking X for the types of items to put into the container (or drop or whatever other action supports BUCX filtering). The situations where menustyle:Full allows BUCX filtering during object class specification and styles Traditional and Combination don't should to be fixed (by extending BUCX support to Traditional and Combination rather than removing it from Full, obviously).
This commit is contained in:
69
src/invent.c
69
src/invent.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 invent.c $NHDT-Date: 1472809075 2016/09/02 09:37:55 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.210 $ */
|
||||
/* NetHack 3.6 invent.c $NHDT-Date: 1498078873 2017/06/21 21:01:13 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.214 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -1680,7 +1680,7 @@ unsigned *resultflags;
|
||||
} else if (sym == 'a') {
|
||||
allflag = TRUE;
|
||||
} else if (sym == 'A') {
|
||||
/* same as the default */;
|
||||
; /* same as the default */
|
||||
} else if (sym == 'u') {
|
||||
add_valid_menu_class('u');
|
||||
ckfn = ckunpaid;
|
||||
@@ -2412,9 +2412,12 @@ int type;
|
||||
int count = 0;
|
||||
|
||||
for (; list; list = list->nobj) {
|
||||
/* coins are "none of the above" as far as BUCX filtering goes */
|
||||
if (list->oclass == COIN_CLASS)
|
||||
/* coins are either uncursed or unknown based upon option setting */
|
||||
if (list->oclass == COIN_CLASS) {
|
||||
if (type == (iflags.goldX ? BUC_UNKNOWN : BUC_UNCURSED))
|
||||
++count;
|
||||
continue;
|
||||
}
|
||||
/* priests always know bless/curse state */
|
||||
if (Role_if(PM_PRIEST))
|
||||
list->bknown = 1;
|
||||
@@ -2437,10 +2440,21 @@ tally_BUCX(list, bcp, ucp, ccp, xcp, ocp)
|
||||
struct obj *list;
|
||||
int *bcp, *ucp, *ccp, *xcp, *ocp;
|
||||
{
|
||||
/* Future extensions:
|
||||
* Add parameter for list traversal by either nexthere or nobj.
|
||||
* Skip current_container when list is invent, uchain when
|
||||
* first object of list is located on the floor. 'ocp' will then
|
||||
* have a function again (it was a counter for having skipped gold,
|
||||
* but that's not skipped anymore).
|
||||
*/
|
||||
*bcp = *ucp = *ccp = *xcp = *ocp = 0;
|
||||
for (; list; list = list->nobj) {
|
||||
/* coins are either uncursed or unknown based upon option setting */
|
||||
if (list->oclass == COIN_CLASS) {
|
||||
++(*ocp); /* "other" */
|
||||
if (iflags.goldX)
|
||||
++(*xcp);
|
||||
else
|
||||
++(*ucp);
|
||||
continue;
|
||||
}
|
||||
/* priests always know bless/curse state */
|
||||
@@ -2583,7 +2597,12 @@ struct obj *obj;
|
||||
{
|
||||
boolean res = (obj->oclass == this_type);
|
||||
|
||||
if (obj->oclass != COIN_CLASS) {
|
||||
if (obj->oclass == COIN_CLASS) {
|
||||
/* if filtering by bless/curse state, gold is classified as
|
||||
either unknown or uncursed based on user option setting */
|
||||
if (this_type && index("BUCX", this_type))
|
||||
res = (this_type == (iflags.goldX ? 'X' : 'U'));
|
||||
} else {
|
||||
switch (this_type) {
|
||||
case 'B':
|
||||
res = (obj->bknown && obj->blessed);
|
||||
@@ -2651,9 +2670,9 @@ dotypeinv()
|
||||
/* collect a list of classes of objects carried, for use as a prompt
|
||||
*/
|
||||
types[0] = 0;
|
||||
class_count =
|
||||
collect_obj_classes(types, invent, FALSE,
|
||||
(boolean FDECL((*), (OBJ_P))) 0, &itemcount);
|
||||
class_count = collect_obj_classes(types, invent, FALSE,
|
||||
(boolean FDECL((*), (OBJ_P))) 0,
|
||||
&itemcount);
|
||||
if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0)
|
||||
types[class_count++] = ' ';
|
||||
if (unpaid_count)
|
||||
@@ -2733,28 +2752,32 @@ dotypeinv()
|
||||
return doprgold();
|
||||
if (index(types, c) > index(types, '\033')) {
|
||||
/* '> ESC' => hidden choice, something known not to be carried */
|
||||
const char *which = 0;
|
||||
const char *before = "", *after = "";
|
||||
|
||||
switch (c) {
|
||||
case 'B':
|
||||
which = "known to be blessed";
|
||||
before = "known to be blessed ";
|
||||
break;
|
||||
case 'U':
|
||||
which = "known to be uncursed";
|
||||
before = "known to be uncursed ";
|
||||
break;
|
||||
case 'C':
|
||||
which = "known to be cursed";
|
||||
before = "known to be cursed ";
|
||||
break;
|
||||
case 'X':
|
||||
You(
|
||||
"have no objects whose blessed/uncursed/cursed status is unknown.");
|
||||
after = " whose blessed/uncursed/cursed status is unknown";
|
||||
break; /* better phrasing is desirable */
|
||||
default:
|
||||
which = "such";
|
||||
/* 'c' is an object class, because we've already handled
|
||||
all the non-class letters which were put into 'types[]';
|
||||
could/should move object class names[] array from below
|
||||
to somewhere above so that we can access it here (via
|
||||
lcase(strcpy(classnamebuf, names[(int) c]))), but the
|
||||
game-play value of doing so is low... */
|
||||
before = "such ";
|
||||
break;
|
||||
}
|
||||
if (which)
|
||||
You("have no %s objects.", which);
|
||||
You("have no %sobjects%s.", before, after);
|
||||
return 0;
|
||||
}
|
||||
this_type = oclass;
|
||||
@@ -3368,13 +3391,11 @@ STATIC_VAR NEARDATA const char *names[] = {
|
||||
"Comestibles", "Potions", "Scrolls", "Spellbooks", "Wands", "Coins",
|
||||
"Gems/Stones", "Boulders/Statues", "Iron balls", "Chains", "Venoms"
|
||||
};
|
||||
STATIC_VAR NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
|
||||
STATIC_VAR NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
|
||||
|
||||
static NEARDATA const char oth_symbols[] = { CONTAINED_SYM, '\0' };
|
||||
|
||||
static NEARDATA const char *oth_names[] = { "Bagged/Boxed items" };
|
||||
|
||||
static NEARDATA char *invbuf = (char *) 0;
|
||||
static NEARDATA unsigned invbufsiz = 0;
|
||||
STATIC_VAR NEARDATA char *invbuf = (char *) 0;
|
||||
STATIC_VAR NEARDATA unsigned invbufsiz = 0;
|
||||
|
||||
char *
|
||||
let_to_name(let, unpaid, showsym)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 options.c $NHDT-Date: 1497481179 2017/06/14 22:59:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.287 $ */
|
||||
/* NetHack 3.6 options.c $NHDT-Date: 1498078876 2017/06/21 21:01:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.288 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -126,6 +126,7 @@ static struct Bool_Opt {
|
||||
{ "flush", (boolean *) 0, FALSE, SET_IN_FILE },
|
||||
#endif
|
||||
{ "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE },
|
||||
{ "goldX", &iflags.goldX, FALSE, SET_IN_GAME },
|
||||
{ "help", &flags.help, TRUE, SET_IN_GAME },
|
||||
{ "hilite_pet", &iflags.wc_hilite_pet, FALSE, SET_IN_GAME }, /*WC*/
|
||||
{ "hilite_pile", &iflags.hilite_pile, FALSE, SET_IN_GAME },
|
||||
|
||||
23
src/pickup.c
23
src/pickup.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 pickup.c $NHDT-Date: 1470449858 2016/08/06 02:17:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.184 $ */
|
||||
/* NetHack 3.6 pickup.c $NHDT-Date: 1498078877 2017/06/21 21:01:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.185 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
|
||||
@@ -376,9 +376,21 @@ boolean
|
||||
allow_category(obj)
|
||||
struct obj *obj;
|
||||
{
|
||||
/* unpaid and BUC checks don't apply to coins */
|
||||
/* For coins, if any class filter is specified, accept if coins
|
||||
* are included regardless of whether either unpaid or BUC-status
|
||||
* is also specified since player has explicitly requested coins.
|
||||
* If no class filtering is specified but bless/curse state is,
|
||||
* coins are either unknown or uncursed based on an option setting.
|
||||
*/
|
||||
if (obj->oclass == COIN_CLASS)
|
||||
return index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE;
|
||||
return class_filter
|
||||
? (index(valid_menu_classes, COIN_CLASS) ? TRUE : FALSE)
|
||||
: shop_filter /* coins are never unpaid, but check anyway */
|
||||
? (obj->unpaid ? TRUE : FALSE)
|
||||
: bucx_filter
|
||||
? (index(valid_menu_classes, iflags.goldX ? 'X' : 'U')
|
||||
? TRUE : FALSE)
|
||||
: TRUE; /* catchall: no filters specified, so accept */
|
||||
|
||||
if (Role_if(PM_PRIEST))
|
||||
obj->bknown = TRUE;
|
||||
@@ -2116,6 +2128,11 @@ register struct obj *obj;
|
||||
return (current_container ? 1 : -1);
|
||||
}
|
||||
|
||||
/* askchain() filter used by in_container();
|
||||
* returns True if the container is intact and 'obj' isn't it, False if
|
||||
* container is gone (magic bag explosion) or 'obj' is the container itself;
|
||||
* also used by getobj() when picking a single item to stash
|
||||
*/
|
||||
int
|
||||
ck_bag(obj)
|
||||
struct obj *obj;
|
||||
|
||||
Reference in New Issue
Block a user