diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 9a2667110..5dd00e1e0 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -2524,6 +2524,9 @@ Cannot be set with the `O' command. An object's inventory letter sticks to it when it's dropped (default on). If this is off, dropping an object shifts all the remaining inventory letters. Persistent. +.lp force_invmenu +Commands asking for an inventory item show a menu instead of +a text query with possible menu letters. Default is off. .lp "fruit " Name a fruit after something you enjoy eating (ex. ``fruit:mango'') (default ``slime mold''). Basically a nostalgic whimsy that NetHack uses diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 02923ba38..edd7f9995 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -3089,6 +3089,10 @@ An object's inventory letter sticks to it when it's dropped (default on). If this is off, dropping an object shifts all the remaining inventory letters. Persistent. %.lp +\item[\ib{force\_invmenu}] +Commands asking for an inventory item show a menu instead of +a text query with possible menu letters. Default is off. +%.lp \item[\ib{fruit}] Name a fruit after something you enjoy eating (ex.\ ``{\tt fruit:mango}'') (default ``{\tt slime mold}''). Basically a nostalgic whimsy that diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 27c12ef6f..b7b8ddc33 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -664,6 +664,8 @@ optional sections in the config file, selected with CHOOSE new paranoid_confirm settings: wand-break to require "yes" rather than 'y' to break a wand via (a)pply, and Were-change to require "yes" rather than 'y' when hero inflicted with lycanthropy has polymorph control +option force_invmenu to make commands asking for inventory items always + use a menu instead of a text line query Platform- and/or Interface-Specific New Features diff --git a/include/flag.h b/include/flag.h index 1a3ef3577..9cd6b3533 100644 --- a/include/flag.h +++ b/include/flag.h @@ -229,6 +229,7 @@ struct instance_flags { boolean cbreak; /* in cbreak mode, rogue format */ boolean deferred_X; /* deferred entry into explore mode */ boolean echo; /* 1 to echo characters */ + boolean force_invmenu; /* always menu when handling inventory */ /* FIXME: goldX belongs in flags, but putting it in iflags avoids breaking 3.6.[01] save files */ boolean goldX; /* for BUCX filtering, whether gold is X or U */ diff --git a/src/invent.c b/src/invent.c index b5ed81c6d..ab1ffc004 100644 --- a/src/invent.c +++ b/src/invent.c @@ -23,7 +23,7 @@ STATIC_PTR int FDECL(ckvalidcat, (struct obj *)); STATIC_PTR char *FDECL(safeq_xprname, (struct obj *)); STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *)); STATIC_DCL char FDECL(display_pickinv, (const char *, const char *, - BOOLEAN_P, long *)); + const char *, BOOLEAN_P, long *)); STATIC_DCL char FDECL(display_used_invlets, (CHAR_P)); STATIC_DCL boolean FDECL(this_type_only, (struct obj *)); STATIC_DCL void NDECL(dounpaid); @@ -1080,6 +1080,8 @@ register const char *let, *word; xchar foox = 0; long cnt; boolean cntgiven = FALSE; + boolean msggiven = FALSE; + boolean oneloop = FALSE; long dummymask; if (*let == ALLOW_COUNT) @@ -1288,15 +1290,24 @@ register const char *let, *word; for (;;) { cnt = 0; cntgiven = FALSE; - if (!buf[0]) { - Sprintf(qbuf, "What do you want to %s? [*]", word); - } else { - Sprintf(qbuf, "What do you want to %s? [%s or ?*]", word, buf); - } + Sprintf(qbuf, "What do you want to %s?", word); if (in_doagain) ilet = readchar(); - else + else if (iflags.force_invmenu) { + /* don't overwrite a possible quitchars */ + if (!oneloop) + ilet = *let ? '?' : '*'; + if (!msggiven) + putmsghistory(qbuf, FALSE); + msggiven = TRUE; + oneloop = TRUE; + } else { + if (!buf[0]) + Strcat(qbuf, " [*]"); + else + Sprintf(eos(qbuf), " [%s or ?*]", buf); ilet = yn_function(qbuf, (char *) 0, '\0'); + } if (digit(ilet)) { long tmpcnt = 0; @@ -1335,13 +1346,17 @@ register const char *let, *word; } return (allownone ? &zeroobj : (struct obj *) 0); } +redo_menu: /* since gold is now kept in inventory, we need to do processing for select-from-invent before checking whether gold has been picked */ if (ilet == '?' || ilet == '*') { char *allowed_choices = (ilet == '?') ? lets : (char *) 0; long ctmp = 0; + char menuquery[QBUFSZ]; - qbuf[0] = '\0'; + menuquery[0] = qbuf[0] = '\0'; + if (iflags.force_invmenu) + Sprintf(menuquery, "What do you want to %s?", word); if (!strcmp(word, "grease")) Sprintf(qbuf, "your %s", makeplural(body_part(FINGER))); else if (!strcmp(word, "write with")) @@ -1357,6 +1372,7 @@ register const char *let, *word; if (ilet == '?' && !*lets && *altlets) allowed_choices = altlets; ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0, + menuquery, TRUE, allowcnt ? &ctmp : (long *) 0); if (!ilet) continue; @@ -1367,6 +1383,8 @@ register const char *let, *word; pline1(Never_mind); return (struct obj *) 0; } + if (ilet == '*') + goto redo_menu; if (allowcnt && ctmp >= 0) { cnt = ctmp; cntgiven = TRUE; @@ -2144,9 +2162,10 @@ free_pickinv_cache() * any count returned from the menu selection is placed here. */ STATIC_OVL char -display_pickinv(lets, xtra_choice, want_reply, out_cnt) +display_pickinv(lets, xtra_choice, query, want_reply, out_cnt) register const char *lets; const char *xtra_choice; /* "fingers", pick hands rather than an object */ +const char *query; boolean want_reply; long *out_cnt; { @@ -2204,7 +2223,7 @@ long *out_cnt; if (!flags.invlet_constant) reassign(); - if (n == 1) { + if (n == 1 && !iflags.force_invmenu) { /* when only one item of interest, use pline instead of menus; we actually use a fake message-line menu in order to allow the user to perform selection at the --More-- prompt for tty */ @@ -2284,7 +2303,15 @@ nextclass: goto nextclass; } } - end_menu(win, (char *) 0); + + if (iflags.force_invmenu && lets && want_reply) { + any = zeroany; + add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, "Special", MENU_UNSELECTED); + any.a_char = '*'; + add_menu(win, NO_GLYPH, &any, '*', 0, ATR_NONE, "(list everything)", MENU_UNSELECTED); + } + + end_menu(win, query && *query ? query : (char *) 0); n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected); if (n > 0) { @@ -2310,7 +2337,8 @@ display_inventory(lets, want_reply) const char *lets; boolean want_reply; { - return display_pickinv(lets, (char *) 0, want_reply, (long *) 0); + return display_pickinv(lets, (char *) 0, (char *) 0, + want_reply, (long *) 0); } /* diff --git a/src/options.c b/src/options.c index b54afa0e5..467a669ff 100644 --- a/src/options.c +++ b/src/options.c @@ -125,6 +125,7 @@ static struct Bool_Opt { #else { "flush", (boolean *) 0, FALSE, SET_IN_FILE }, #endif + { "force_invmenu", &iflags.force_invmenu, FALSE, SET_IN_GAME }, { "fullscreen", &iflags.wc2_fullscreen, FALSE, SET_IN_FILE }, { "goldX", &iflags.goldX, FALSE, SET_IN_GAME }, { "help", &flags.help, TRUE, SET_IN_GAME }, diff --git a/sys/winnt/defaults.nh b/sys/winnt/defaults.nh index 46f6109fa..7dfef2713 100644 --- a/sys/winnt/defaults.nh +++ b/sys/winnt/defaults.nh @@ -76,6 +76,9 @@ MENUCOLOR=" cursed .* (being worn)" = orange&underline # or 2(on,legacy-mode) which causes 5='g', alt-5='G', alt-0='I' OPTIONS=time,noshowexp,number_pad:2,lit_corridor +# Make commands that ask for an inventory item pop up a menu +OPTIONS=force_invmenu + # # If you want to get rid of "use #quit to quit..." use: OPTIONS=suppress_alert:3.3.1