another paranoid_confirm:Autoall revision

For Autoselect-all confirmation, accept yes|n|q (or yes|no|quit)
rather than just yes|n (or yes|no).  An extra query routine is needed
to support it, but the existing paranoid_query() can just call the
new paranoid_ynq() with an extra argument, keeping things painless.

For menustyle:full plus paranoid_confirmation:Autoall, if you include
'A' in the class filtering choices then you're prompted for whether
you really meant it.  (Same behavior as in the past few weeks.)  Yes
auto-selects items matching all other chosen classes, or from all
classes if 'A' is the only choice.  (Again, same behavior.)  n|no
moves on to menu:full's second menu.  If anything else was chosen
along with 'A', that's what the second menu will offer.  (Same as
past few weeks but revised from initial implementation.)  If 'A' was
the only choice, it will now use 'a' and offer a choice of everything
in the second menu.  (That's a change; it used to cancel if declining
to honor 'A' and nothing else was present.)  Now <return> without
answering or q|quit or ESC skips the second menu, whether or not the
rejected 'A' was the only choice made in the first menu.  (New.)

Other paranoid confirmations still just accept yes and n|no responses,
treating ESC as n|no.
This commit is contained in:
PatR
2023-09-18 00:17:33 -07:00
parent 11bfb09daa
commit 4f2c913925
3 changed files with 75 additions and 26 deletions

View File

@@ -310,6 +310,7 @@ extern char readchar_poskey(coordxy *, coordxy *, int *);
extern void sanity_check(void);
extern char* key2txt(uchar, char *);
extern char yn_function(const char *, const char *, char, boolean);
extern char paranoid_ynq(boolean, const char *, boolean);
extern boolean paranoid_query(boolean, const char *);
extern void makemap_prepost(boolean, boolean);

View File

@@ -6691,19 +6691,28 @@ yn_function(
return res;
}
/* for paranoid_confirm:quit,die,attack prompting */
boolean
paranoid_query(boolean be_paranoid, const char *prompt)
/* for paranoid_confirm:quit,die,attack,&c prompting; allows yes, n|no,
or q|quit; result is one of 'y' or 'n' or 'q'; ESC yields 'q' */
char
paranoid_ynq(
boolean be_paranoid,
const char *prompt,
boolean accept_q)
{
boolean confirmed_ok;
char c = 'n'; /* default result */
/* when paranoid, player must respond with "yes" rather than just 'y'
to give the go-ahead for this query; default is "no" unless the
ParanoidConfirm flag is set in which case there's no default */
if (be_paranoid) {
char pbuf[BUFSZ], qbuf[QBUFSZ], ans[BUFSZ];
const char *promptprefix = "",
*responsetype = ParanoidConfirm ? "[yes|no]" : "[yes|n] (n)";
const char *promptprefix = "", /* empty for first iteration */
*responsetype = ParanoidConfirm ? (accept_q ? "[yes|no|quit]"
: "[yes|no]")
/* default of 'n' is shown for
* the !ParanoidConfirm cases */
: (accept_q ? "[yes|n|q] (n)"
: "[yes|n] (n)");
int k, trylimit = 6; /* 1 normal, 5 more with "Yes or No:" prefix */
copynchars(pbuf, prompt, BUFSZ - 1);
@@ -6720,20 +6729,39 @@ paranoid_query(boolean be_paranoid, const char *prompt)
Strcpy(pbuf + (QBUFSZ - 1) - k - 4, "...?"); /* -4: "...?" */
}
Snprintf(qbuf, sizeof(qbuf), "%s%s %s", promptprefix, pbuf,
Snprintf(qbuf, sizeof qbuf, "%s%s %s", promptprefix, pbuf,
responsetype);
*ans = '\0';
getlin(qbuf, ans);
(void) mungspaces(ans);
confirmed_ok = !strcmpi(ans, "yes");
if (confirmed_ok || *ans == '\033')
if (!strcmpi(ans, "yes")) {
c = 'y';
break;
}
if (!strcmpi(ans, "quit") || *ans == '\033') {
c = 'q';
break;
}
/* we don't bother adding "or \"Quit\"" for the accept_q case */
promptprefix = "\"Yes\" or \"No\": ";
/* for empty input, return value c will already be 'n' */
} while (ParanoidConfirm && strcmpi(ans, "no") && --trylimit);
} else if (accept_q) {
c = ynq(prompt); /* 'y', 'n', or 'q' */
} else {
confirmed_ok = (y_n(prompt) == 'y');
c = y_n(prompt); /* 'y' or 'n' */
}
return confirmed_ok;
if (c != 'y' && (c != 'q' || !accept_q))
c = 'n';
return c;
}
/* for paranoid_confirm:quit,die,attack,&c prompting; allows yes or n|no;
result is True for yes; n|no and ESC yield False */
boolean
paranoid_query(boolean be_paranoid, const char *prompt)
{
return (paranoid_ynq(be_paranoid, prompt, FALSE) == 'y');
}
/* ^Z command, #suspend */

View File

@@ -1244,16 +1244,16 @@ query_category(
ATR_NONE, NO_COLOR, "", MENU_ITEMFLAGS_NONE);
}
invlet = 'a';
if ((qflags & ALL_TYPES) && (ccount > 1)) {
invlet = 'a';
any = cg.zeroany;
any.a_int = ALL_TYPES_SELECTED;
add_menu(win, &nul_glyphinfo, &any, invlet, 0, ATR_NONE, clr,
(qflags & WORN_TYPES) ? "All worn types" : "All types",
MENU_ITEMFLAGS_SKIPINVERT);
invlet = 'b';
} else
invlet = 'a';
++invlet; /* invlet = 'b'; */
}
do {
collected_type_name = FALSE;
for (curr = olist; curr; curr = FOLLOW(curr, qflags)) {
@@ -1355,6 +1355,7 @@ query_category(
}
end_menu(win, qstr);
n = select_menu(win, how, pick_list);
/* handle ParanoidAutoAll by confirming 'A' choice if present */
if (n > 0 && verify_All) {
int i, j;
@@ -1363,18 +1364,37 @@ query_category(
if ((*pick_list)[i].item.a_int == 'A') {
/* ParanoidAutoAll is set (otherwise verify_All is false);
if ParanoidConfirm is also set, require "yes" rather than
just "y" to accept (and "no" rather than "n" to decline) */
if (!paranoid_query(ParanoidConfirm,
"Really autoselect All?")) {
/* answer is "no", so take 'A' out of the list;
if it is the only entry, we'll return nothing,
otherwise go on to next menu without autoselect */
for (j = i + 1; j < n; ++j)
(*pick_list)[j - 1] = (*pick_list)[j];
if (!--n)
free((genericptr_t) *pick_list), *pick_list = 0;
just "y" to accept (and "no" rather than "n" to decline;
accepts "quit" and ESC without converting them to 'n') */
switch (paranoid_ynq(ParanoidConfirm,
"Really autoselect All?", TRUE)) {
case 'y':
/* yes => honor Auto-select All */
break;
case 'n':
/* no => remove 'A' from the list; if that would make
it empty then replace with 'a' */
if (n > 1) {
for (j = i + 1; j < n; ++j)
(*pick_list)[j - 1] = (*pick_list)[j];
--n;
break; /* from switch */
} else if ((qflags & ALL_TYPES) != 0) {
/* 'A' was the only choice; convert it to 'a' and
then let the next menu offer a choice of all */
(*pick_list)[0].item.a_int = ALL_TYPES_SELECTED;
/* assert( n == 1 ); */
break; /* from switch */
}
/*FALLTHRU*/
case 'q':
default:
/* quit | ESC => cancel, no Auto-select and no 2nd menu */
n = 0;
free((genericptr_t) *pick_list), *pick_list = 0;
break;
}
break; /* goto query_done; */
break; /* from for => goto query_done; */
}
}
query_done: