replace getenv("TTYINV") with perminv_mode option

Add a new option 'perminv_mode' to augment perm_invent.  It handles
the same choices as the temporary TTYINV method:  show all items other
than gold, show full inventory including gold, or only show in-use
items (similar to the '*' command).

For tty, both the all-except-gold and full-inventory modes can add
the poorly named 'sparse' variation which populates unused slots in
its fixed grid with the inventory letter that would go in each.

For others, the default has been changed from full-inventory to
all-except-gold.  Note that gold is treated as part of 'all' or of
'in-use' if it is quivered because having the amount be shown on the
status line doesn't make that redundant.

Changing the default may mess up WinGUI if it assumes that perm_invent
is full inventory with gold.

Initially I was going to change perm_invent into a compound but this
leaves it as an on/off toggle and adds perminv_mode as a separate
option for how to show the inventory when the toggle is on.  It may
make sense to combine them since dual controls is a little confusing,
but right now setting perm_invent On when perminv_mode is 'none'
changes that to 'all' and changing perminv_mode away from 'none' when
perm_invent is Off toggles it to On.

Guidebook.mn has been updated but as usual Guidebook.tex is lagging.
This commit is contained in:
PatR
2023-11-05 02:31:26 -08:00
parent e16f80395b
commit 2ee7509945
8 changed files with 369 additions and 79 deletions

View File

@@ -47,7 +47,7 @@ static void mime_action(const char *);
/* enum and structs are defined in wintype.h */
static win_request_info zerowri = { { 0L, 0, 0, 0, 0, 0, 0, 0 }, { 0, 0 } };
static win_request_info wri_info;
static int done_setting_perminv_flags = 0;
static int perminv_flags = InvOptNone;
static boolean in_perm_invent_toggled;
/* wizards can wish for venom, which will become an invisible inventory
@@ -3288,7 +3288,7 @@ display_pickinv(
struct obj *otmp, wizid_fakeobj;
char ilet, ret, *formattedobj;
const char *invlet = flags.inv_order;
int n, classcount;
int n, classcount, inusecount = 0;
winid win; /* windows being used */
anything any;
menu_item *selected;
@@ -3310,7 +3310,7 @@ display_pickinv(
#endif
if (lets || xtra_choice || wizid || want_reply
#ifdef TTY_PERM_INVENT
|| !gi.in_sync_perminvent
/*|| !gi.in_sync_perminvent*/
#endif
|| WIN_INVEN == WIN_ERR) {
/* partial inventory in perm_invent setting; don't operate on
@@ -3342,7 +3342,7 @@ display_pickinv(
* more than 1; for the last one, we don't need a precise number.
* For perm_invent update we force 'more than 1'.
*/
n = (iflags.perm_invent && !lets && !want_reply) ? 2
n = (doing_perm_invent && !lets && !want_reply) ? 2
: lets ? (int) strlen(lets)
: !gi.invent ? 0 : !gi.invent->nobj ? 1 : 2;
/* for xtra_choice, there's another 'item' not included in initial 'n';
@@ -3455,18 +3455,20 @@ display_pickinv(
if (wizid && !not_fully_identified(otmp))
continue;
if (doing_perm_invent) {
/* when showing equipment in use, gold shouldn't be excluded
just because !show_gold is set; it might be quivered;
tool_being_used() matches lit lamps/candles and active
leashes, neither of which set owornmask */
/* don't skip gold if it is quivered, even for !show_gold */
if (inuse_only) {
if (!otmp->owornmask && !tool_being_used(otmp)) {
skipped_noninuse = TRUE;
continue;
}
} else if (otmp->invlet == GOLD_SYM && !show_gold) {
skipped_gold = TRUE;
continue;
/* for inuse-only, start with an extra header */
if (!inusecount++)
add_menu_str(win, "In use");
} else if (!show_gold) {
if (otmp->invlet == GOLD_SYM && !otmp->owornmask) {
skipped_gold = TRUE;
continue;
}
}
}
any = cg.zeroany; /* all bits zero */
@@ -3519,11 +3521,10 @@ display_pickinv(
/* for permanent inventory where nothing has been listed (because
there isn't anything applicable to list; the n==0 case above
gets skipped for perm_invent), put something into the menu */
if (iflags.perm_invent && !lets && !gotsomething) {
add_menu_str(win,
(inuse_only && skipped_noninuse) ? not_using_anything
: (!show_gold && skipped_gold) ? only_carrying_gold
: not_carrying_anything);
if (doing_perm_invent && !lets && !gotsomething) {
add_menu_str(win, inuse_only ? not_using_anything
: (!show_gold && skipped_gold) ? only_carrying_gold
: not_carrying_anything);
want_reply = FALSE;
}
#ifdef TTY_PERM_INVENT
@@ -5608,23 +5609,15 @@ void
prepare_perminvent(winid window)
{
win_request_info *wri;
int invmode = (int) iflags.perminv_mode;
if (!done_setting_perminv_flags) {
/*TEMPORARY*/
char *envtmp = !gp.program_state.gameover ? nh_getenv("TTYINV") : 0;
/* default for non-tty includes gold, for tty excludes gold;
if non-tty specifies any value, gold will be excluded unless
that value includes the show-gold bit (1) */
int invmode = envtmp ? atoi(envtmp)
: !WINDOWPORT(tty) ? InvShowGold
: InvNormal;
if (perminv_flags != invmode) {
wri_info = zerowri;
wri_info.fromcore.invmode = invmode;
/* relay the mode settings to the window port */
wri = ctrl_nhwindow(window, set_mode, &wri_info);
perminv_flags = invmode;
nhUse(wri);
done_setting_perminv_flags = 1;
}
}
@@ -5641,8 +5634,7 @@ sync_perminvent(void)
&& gp.perm_invent_toggling_direction == toggling_on))
return;
}
if (!done_setting_perminv_flags && WIN_INVEN != WIN_ERR)
prepare_perminvent(WIN_INVEN);
prepare_perminvent(WIN_INVEN);
if ((!iflags.perm_invent && gc.core_invent_state)) {
/* Odd - but this could be end-of-game disclosure
@@ -5662,33 +5654,34 @@ sync_perminvent(void)
* 1. iflags.perm_invent is on
* AND
* gc.core_invent_state is still zero.
*
* OR
*
* 2. iflags.perm_invent is off, but we're in the
* midst of toggling it on.
* OR
* 3. iflags.perminv_mode has been changed via 'm O'.
*/
if ((iflags.perm_invent && !gc.core_invent_state)
|| ((!iflags.perm_invent
|| (!iflags.perm_invent
&& (in_perm_invent_toggled
&& gp.perm_invent_toggling_direction == toggling_on)))) {
&& gp.perm_invent_toggling_direction == toggling_on))) {
/* Send windowport a request to return the related settings to us */
if ((iflags.perm_invent && !gc.core_invent_state)
|| in_perm_invent_toggled) {
if ((wri = ctrl_nhwindow(WIN_INVEN, request_settings, &wri_info))
!= 0) {
if ((wri->tocore.tocore_flags & prohibited) != 0) {
wri = ctrl_nhwindow(WIN_INVEN, request_settings, &wri_info);
if (wri != 0) {
if ((wri->tocore.tocore_flags & (too_small | prohibited))
!= 0) {
/* sizes aren't good enough */
set_option_mod_status("perm_invent", set_gameview);
if ((wri->tocore.tocore_flags & prohibited) != 0) {
set_option_mod_status("perm_invent", set_gameview);
set_option_mod_status("perminv_mode", set_gameview);
}
iflags.perm_invent = FALSE;
if (WIN_INVEN != WIN_ERR)
destroy_nhwindow(WIN_INVEN), WIN_INVEN = WIN_ERR;
if (WINDOWPORT(tty) && iflags.perm_invent)
wport_id = "tty perm_invent";
else
wport_id = "perm_invent";
wport_id = WINDOWPORT(tty) ? "tty perm_invent"
: "perm_invent";
pline("%s could not be enabled.", wport_id);
pline("%s needs a terminal that is at least %dx%d, yours "
"is %dx%d.",
@@ -5729,6 +5722,8 @@ perm_invent_toggled(boolean negated)
gc.core_invent_state = 0;
} else {
gp.perm_invent_toggling_direction = toggling_on;
if (iflags.perminv_mode == InvOptNone)
iflags.perminv_mode = InvOptOn; /* all inventory except gold */
sync_perminvent();
}
gp.perm_invent_toggling_direction = toggling_not;

View File

@@ -234,6 +234,24 @@ static NEARDATA const char *runmodes[] = {
static NEARDATA const char *sortltype[] = {
"none", "loot", "full"
};
/* second column is an alias for the first; third is brief explanation;
entries 5 and 6 are 1|4 and 2|4 (tty only) */
static NEARDATA const char *perminv_modes[][3] = {
/*0*/ { "none", "off", "no permanent inventory window" },
/*1*/ { "all" , "on", "all inventory except for gold" },
/*2*/ { "full", "gold", "full inventory including gold" },
/*3*/ { NULL, NULL, NULL },
/*4*/ { NULL, NULL, NULL },
#ifdef TTY_PERM_INVENT
/*5*/ { "on+grid", "all+grid", "all except gold, plus unused letters" },
/*6*/ { "gold+grid", "full+grid", "full inventory, plus unused letters" },
#else
/*5*/ { NULL, NULL, NULL },
/*6*/ { NULL, NULL, NULL },
#endif
/*7*/ { NULL, NULL, NULL },
/*8*/ { "in-use", "inuse-only", "subset: items currently in use" },
};
/*
* Default menu manipulation command accelerators. These may _not_ be:
@@ -340,7 +358,7 @@ static int count_apes(void);
static int count_cond(void);
static void enhance_menu_text(char *, size_t, int, boolean *,
struct allopt_t *);
static boolean can_set_perm_invent(void);
static int handler_align_misc(int);
static int handler_autounlock(int);
static int handler_disclose(void);
@@ -349,6 +367,7 @@ static int handler_menustyle(void);
static int handler_msg_window(void);
static int handler_number_pad(void);
static int handler_paranoid_confirmation(void);
static int handler_perminv_mode(void);
static int handler_pickup_burden(void);
static int handler_pickup_types(void);
static int handler_runmode(void);
@@ -2855,6 +2874,98 @@ optfn_paranoid_confirmation(
return optn_ok;
}
static int
optfn_perminv_mode(
int optidx, int req, boolean negated,
char *opts, char *op)
{
boolean old_perm_invent = iflags.perm_invent;
uchar old_perminv_mode = iflags.perminv_mode;
int retval = optn_ok;
if (req == do_init) {
#if 0
/* old, TEMPORARY method of controlling 'perm_invent';
note: the bits used now have been changed, hence 'n << 1' */
char *envtmp = nh_getenv("TTYINV") : 0;
int invmode = envtmp ? (atoi(envtmp) << 1) : 0;
iflags.perminv_mode = (uchar) invmode;
iflags.perm_invent = iflags.perminv_mode != 0;
#endif
return optn_ok;
} else if (req == do_set) {
op = string_for_opt(opts, negated);
if (op != empty_optstr && negated) { /* reject "!perminv_mode=foo" */
bad_negation(allopt[optidx].name, TRUE);
retval = optn_silenterr;
} else if (op != empty_optstr) { /* "perminv_mode=foo" */
const char *pi0, *pi1;
int i;
unsigned ln = (unsigned) strlen(op); /* guaranteed > 0 */
for (i = 0; i < SIZE(perminv_modes); ++i) {
if (!(pi0 = perminv_modes[i][0]))
continue;
pi1 = perminv_modes[i][1];
if (!strncmpi(op, pi0, ln) || !strncmpi(op, pi1, ln)
|| op[0] == i + '0') { /* also accept '0'..'8' */
#if 1 /*#ifdef TTY_PERM_INVENT*/
if (strstri(pi0, "+grid") && !WINDOWPORT(tty)) {
i &= ~InvSparse;
config_error_add(
"%s: unavailable perm_invent mode '%s', using '%s'",
allopt[optidx].name, pi0,
perminv_modes[i][0]);
}
#endif
iflags.perminv_mode = (uchar) i;
iflags.perm_invent = TRUE;
break;
}
}
if (i == SIZE(perminv_modes)) {
config_error_add("Unknown %s parameter '%s'",
allopt[optidx].name, op);
iflags.perminv_mode = InvOptNone;
iflags.perm_invent = FALSE;
retval = optn_silenterr;
}
} else if (negated) { /* "!perminv_mode" */
iflags.perminv_mode = InvOptNone;
iflags.perm_invent = FALSE;
}
if (!go.opt_initial) {
if (iflags.perminv_mode != old_perminv_mode
|| iflags.perm_invent != old_perm_invent)
go.opt_need_redraw = TRUE;
}
} else if (req == do_handler) {
/* use a menu to choose new value for perminv_mode */
retval = handler_perminv_mode();
} else if (req == get_val) {
/* value shown when examining current option settings; exclosed
within square brackets for 'O', shown as-is when setting value */
Sprintf(opts, "%s", perminv_modes[iflags.perminv_mode][2]);
if (iflags.perminv_mode != InvOptNone && !iflags.perm_invent
/* 'op' is Null when called by handler_perminv_mode() while
setting, non-Null when 'm O' shows current option values */
&& op) {
/* perminv_mode is set but isn't useful because perm_invent is
Off; say so after squeezing out enough for it to barely fit */
if (iflags.perminv_mode == InvOptInUse)
(void) strsubst(opts, " currently", "");
else
(void) strsubst(opts, " inventory", " invent");
Strcat(opts, (((iflags.perminv_mode & InvSparse) != 0) ? " (Off)"
: " ('perm_invent' is Off)"));
}
} else if (req == get_cnf_val) {
Sprintf(opts, "%s", perminv_modes[iflags.perminv_mode][0]);
}
return retval;
}
static int
optfn_petattr(
int optidx, int req, boolean negated,
@@ -3035,7 +3146,10 @@ optfn_pickup_burden(
}
static int
optfn_pickup_types(int optidx, int req, boolean negated, char *opts, char *op)
optfn_pickup_types(
int optidx, int req,
boolean negated,
char *opts, char *op)
{
char ocl[MAXOCLASSES + 1], tbuf[MAXOCLASSES + 1], qbuf[QBUFSZ],
abuf[BUFSZ];
@@ -3131,7 +3245,10 @@ optfn_pickup_types(int optidx, int req, boolean negated, char *opts, char *op)
}
static int
optfn_pile_limit(int optidx, int req, boolean negated, char *opts, char *op)
optfn_pile_limit(
int optidx, int req,
boolean negated,
char *opts, char *op)
{
if (req == do_init) {
return optn_ok;
@@ -4971,23 +5088,9 @@ optfn_boolean(int optidx, int req, boolean negated, char *opts, char *op)
}
break;
case opt_perm_invent:
#ifdef TTY_PERM_INVENT
/* if attempting to enable perm_invent fails, say so and return
before "'perm_invent' option toggled on" would be given below;
perm_invent_toggled() and routines it calls don't check
iflags.perm_invent so it doesn't matter that 'SET IT HERE'
hasn't been executed yet */
if (WINDOWPORT(tty) && !go.opt_initial && !negated) {
perm_invent_toggled(FALSE);
/* perm_invent_toggled()
-> sync_perminvent()
-> tty_create_nhwindow(NHW_PERMINVENT)
gives feedback for failure (terminal too small) */
if (WIN_INVEN == WIN_ERR)
return optn_silenterr;
}
#endif
break; /* from opt_perm_invent */
if (!negated && !can_set_perm_invent())
return optn_silenterr;
break;
default:
break;
}
@@ -5172,6 +5275,40 @@ spcfn_misc_menu_cmd(int midx, int req, boolean negated, char *opts, char *op)
**********************************
*/
/* test whether 'perm_invent' can be toggled On */
static boolean
can_set_perm_invent(void)
{
/*
* Assumption: only called when iflags.perm_invent is False
* and is about to be changed to True.
*/
uchar old_perminv_mode = iflags.perminv_mode;
if (!(windowprocs.wincap & WC_PERM_INVENT))
return FALSE; /* should never happen */
if (iflags.perminv_mode == InvOptNone)
iflags.perminv_mode = InvOptOn;
#ifdef TTY_PERM_INVENT
if (WINDOWPORT(tty) && !go.opt_initial) {
perm_invent_toggled(FALSE);
/* perm_invent_toggled()
-> sync_perminvent()
-> tty_create_nhwindow(NHW_PERMINVENT)
gives feedback for failure (terminal too small) */
if (WIN_INVEN == WIN_ERR) {
iflags.perminv_mode = old_perminv_mode;
return FALSE;
}
}
#else
nhUse(old_perminv_mode);
#endif
return TRUE;
}
static int
handler_menustyle(void)
{
@@ -5599,6 +5736,80 @@ handler_paranoid_confirmation(void)
return optn_ok;
}
static int
handler_perminv_mode(void)
{
winid tmpwin;
anything any;
char let, buf[BUFSZ], sepbuf[10];
const char *pi0, *pi1;
menu_item *pi_pick = (menu_item *) 0;
boolean old_perm_invent = iflags.perm_invent;
int i, n, old_pi = (int) iflags.perminv_mode, new_pi = old_pi,
widest = !WINDOWPORT(tty) ? 8 : 11; /* "in-use__" or "full+grid__" */
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
any = cg.zeroany;
for (i = 0; i < SIZE(perminv_modes); ++i) {
if (!(pi0 = perminv_modes[i][0]))
continue;
#ifdef TTY_PERM_INVENT
if (strstri(pi0, "+grid") != 0 && !WINDOWPORT(tty))
continue;
#endif
pi1 = perminv_modes[i][1];
if (!iflags.menu_tab_sep) {
int numspaces = widest - (int) strlen(pi0);
Sprintf(sepbuf, "%*s", max(numspaces, 1), " ");
} else {
Strcpy(sepbuf, "\t");
}
Sprintf(buf, "%s%s%s", pi0, sepbuf, perminv_modes[i][2]);
let = ((i & (int) InvSparse) != 0) ? highc(pi1[0]) : pi0[0];
any.a_int = i + 1;
add_menu(tmpwin, &nul_glyphinfo, &any, let, '0' + i, ATR_NONE, 0,
buf, (i == old_pi) ? MENU_ITEMFLAGS_SELECTED
: MENU_ITEMFLAGS_NONE);
}
end_menu(tmpwin, "Choose permanent inventory mode:");
n = select_menu(tmpwin, PICK_ONE, &pi_pick);
destroy_nhwindow(tmpwin);
if (n > 0) {
new_pi = pi_pick[0].item.a_int - 1;
if (n > 1 && new_pi == old_pi)
new_pi = pi_pick[1].item.a_int - 1;
free((genericptr_t) pi_pick);
iflags.perminv_mode = new_pi;
}
if (n >= 0) { /* not ESC */
buf[0] = '\0';
(void) optfn_perminv_mode(opt_perm_invent, get_val, FALSE, buf, NULL);
pline("'perminv_mode' %s '%s' (%s).",
(new_pi != old_pi) ? "changed to" : "is still",
perminv_modes[new_pi][0], buf);
if (new_pi != InvOptNone && !old_perm_invent)
iflags.perm_invent = can_set_perm_invent();
else if (new_pi == InvOptNone && old_perm_invent)
iflags.perm_invent = FALSE;
if (new_pi != old_pi || iflags.perm_invent != old_perm_invent) {
#ifdef TTY_PERM_INVENT
/* FIXME: TTY_PERM_INVENT will blank WIN_INVEN when changing
perminv_mode while perm_invent is already on; to remedy that,
turn it off and then back on when already on */
if (WINDOWPORT(tty) && iflags.perm_invent && old_perm_invent) {
perm_invent_toggled(TRUE); /*TEMP?*/
perm_invent_toggled(FALSE); /*TEMP?*/
}
#endif
go.opt_need_redraw = TRUE;
}
}
return optn_ok;
}
static int
handler_pickup_burden(void)
{
@@ -8278,8 +8489,12 @@ optfn_o_menu_colors(int optidx UNUSED, int req, boolean negated UNUSED,
}
static int
optfn_o_message_types(int optidx UNUSED, int req, boolean negated UNUSED,
char *opts, char *op UNUSED)
optfn_o_message_types(
int optidx UNUSED,
int req,
boolean negated UNUSED,
char *opts,
char *op UNUSED)
{
if (req == do_init) {
return optn_ok;
@@ -9724,6 +9939,7 @@ static struct wc_Opt wc_options[] = {
{ "eight_bit_tty", WC_EIGHT_BIT_IN },
{ "hilite_pet", WC_HILITE_PET },
{ "perm_invent", WC_PERM_INVENT },
{ "perminv_mode", WC_PERM_INVENT }, /* shares WC_PERM_INVENT */
{ "popup_dialog", WC_POPUP_DIALOG },
{ "player_selection", WC_PLAYER_SELECTION },
{ "preload_tiles", WC_PRELOAD_TILES },
@@ -10063,7 +10279,7 @@ enhance_menu_text(
nowsz = strlen(buf) + 1;
availsz = sz - nowsz;
#ifdef TTY_PERM_INVENT
#if 0 /*#ifdef TTY_PERM_INVENT*/
if (bool_p == &iflags.perm_invent && WINDOWPORT(tty)) {
if (thisopt->setwhere == set_gameview)
Snprintf(eos(buf), availsz, " *terminal size is too small");