From f8bd79354c4546c9a6b6e36227e1a5a2de5b9747 Mon Sep 17 00:00:00 2001 From: Pasi Kallinen Date: Wed, 25 Mar 2026 13:46:03 +0200 Subject: [PATCH] Add a history menu for wizwish Use the 'm' Prefix to make wizwish show the history menu. Also entries wished via WIZKIT are added to the history. While debugging, I often need to wish the same thing multiple times, and typing or pasting it with mouse is annoying... --- doc/Guidebook.mn | 2 ++ doc/Guidebook.tex | 2 ++ doc/fixes3-7-0.txt | 1 + include/extern.h | 1 + src/cmd.c | 2 +- src/files.c | 4 ++- src/zap.c | 84 +++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 93 insertions(+), 3 deletions(-) diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index 314567f71..fd295e786 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -1935,6 +1935,7 @@ Wish for something. Autocompletes. Debug mode only. Default key is \(oq\(haW\(cq. +Precede this command with the \(oq\f(CRm\fP\(cq prefix to show a wish history menu. .lp "#wmode " Show wall modes. Autocompletes. @@ -3747,6 +3748,7 @@ Debug mode only: extra items to add to initial inventory. Value is the name of a text file containing a list of item names, one per line, up to a maximum of 128 lines. Each line is processed by the function that handles wishing. +Entries are added to the wish history; see the wizwish-command. .lp "" Example: .sd diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 7fa1724af..7bfa18221 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -2028,6 +2028,7 @@ Wish for something. Autocompletes. Debug mode only. Default key is `\texttt{\textasciicircum W}'. +Precede this command with the `\texttt{m}' prefix to show a wish history menu. %.lp \item[\#wmode] Show wall modes. @@ -4074,6 +4075,7 @@ Debug mode only: extra items to add to initial inventory. Value is the name of a text file containing a list of item names, one per line, up to a maximum of 128 lines. Each line is processed by the function that handles wishing. +Entries are added to the wish history; see the wizwish-command. %.lp "" Example: diff --git a/doc/fixes3-7-0.txt b/doc/fixes3-7-0.txt index 0d85f432f..506dcdd5a 100644 --- a/doc/fixes3-7-0.txt +++ b/doc/fixes3-7-0.txt @@ -1590,6 +1590,7 @@ change some command keys, 'v' is now chronicle, 'V' is versionshort, m-prefix 'V' is longer version, remove key binding of #history one orc-town shaman has a higher level, affecting spellcasting hero has a small chance of catching items thrown at them +wizard mode: history menu for #wizwish and WIZKIT Fixes to 3.7.0-x General Problems Exposed Via git Repository diff --git a/include/extern.h b/include/extern.h index 39e70fb0b..ac0992b05 100644 --- a/include/extern.h +++ b/include/extern.h @@ -3988,6 +3988,7 @@ extern boolean inventory_resistance_check(int); extern char *item_what(int); extern int destroy_items(struct monst *, int, int) NONNULLARG1; extern int resist(struct monst *, char, int, int) NONNULLARG1; +extern void wish_history_add(char *); extern void makewish(void); extern const char *flash_str(int, boolean) NONNULL; diff --git a/src/cmd.c b/src/cmd.c index a88b2d7a7..8b34060b6 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1996,7 +1996,7 @@ struct ext_func_tab extcmdlist[] = { { '\0', "wizwhere", "show locations of special levels", wiz_where, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, { C('w'), "wizwish", "wish for something", - wiz_wish, IFBURIED | WIZMODECMD, NULL }, + wiz_wish, IFBURIED | CMD_M_PREFIX | WIZMODECMD, NULL }, { '\0', "wmode", "show wall modes", wiz_show_wmodes, IFBURIED | AUTOCOMPLETE | WIZMODECMD, NULL }, { 'z', "zap", "zap a wand", diff --git a/src/files.c b/src/files.c index d2c81a4a9..ae45f6c07 100644 --- a/src/files.c +++ b/src/files.c @@ -2546,8 +2546,10 @@ proc_wizkit_line(char *buf) otmp = readobjnam(buf, (struct obj *) 0); if (otmp) { - if (otmp != &hands_obj) + if (otmp != &hands_obj) { + wish_history_add(buf); wizkit_addinv(otmp); + } } else { /* .60 limits output line width to 79 chars */ config_error_add("Bad wizkit item: \"%.60s\"", buf); diff --git a/src/zap.c b/src/zap.c index 12c482227..a1466e1d5 100644 --- a/src/zap.c +++ b/src/zap.c @@ -40,6 +40,7 @@ staticfn int maybe_destroy_item(struct monst *, struct obj *, int) NONNULLPTRS; staticfn boolean destroyable(struct obj *, int); staticfn void wishcmdassist(int); +staticfn void wish_history_menu(char *); #define ZT_MAGIC_MISSILE (AD_MAGM - 1) #define ZT_FIRE (AD_FIRE - 1) @@ -6210,6 +6211,81 @@ wishcmdassist(int triesleft) destroy_nhwindow(win); } +#define MAX_WISH_HISTORY 20 +static char *wish_history[MAX_WISH_HISTORY] = { NULL }; +static int wish_history_idx = 0; + +/* add string to wish history list */ +void +wish_history_add(char *buf) +{ +#ifdef DEBUG + int i; + + if (!wizard) + return; + + for (i = 0; i < MAX_WISH_HISTORY; i++) { + int idx = (wish_history_idx + i) % MAX_WISH_HISTORY; + + if (!wish_history[idx]) + continue; + if (!strncmpi(wish_history[idx], buf, strlen(wish_history[idx]))) + break; + + } + + if (i == MAX_WISH_HISTORY) { + int idx = (wish_history_idx + i) % MAX_WISH_HISTORY; + + if (wish_history[idx]) + free(wish_history[idx]); + wish_history[idx] = (char *)alloc(strlen(buf) + 1); + strcpy(wish_history[idx], buf); + wish_history_idx = (wish_history_idx + 1) % MAX_WISH_HISTORY; + } +#endif /* DEBUG */ +} + +/* shows menu of previous wishes, copies selected into buf, max BUFSZ len. + buf is not modified, if nothing was selected. */ +staticfn void +wish_history_menu(char *buf) +{ +#ifdef DEBUG + winid win; + anything any; + int i = 0, npick; + menu_item *picks = (menu_item *) 0; + int idx; + + win = create_nhwindow(NHW_MENU); + start_menu(win, MENU_BEHAVE_STANDARD); + any = cg.zeroany; + + for (i = MAX_WISH_HISTORY-1; i >= 0; i--) { + idx = (wish_history_idx + i) % MAX_WISH_HISTORY; + if (wish_history[idx]) { + any.a_int = (i + 1); + add_menu(win, &nul_glyphinfo, &any, '\0', 0, ATR_NONE, NO_COLOR, + wish_history[idx], MENU_ITEMFLAGS_NONE); + } + } + + end_menu(win, "Wish what?"); + npick = select_menu(win, PICK_ONE, &picks); + destroy_nhwindow(win); + if (npick > 0) { + i = picks->item.a_int; + i--; + idx = (wish_history_idx + i) % MAX_WISH_HISTORY; + + if (wish_history[idx]) + strcpy(buf, wish_history[idx]); + } +#endif /* DEBUG */ +} + RESTORE_WARNING_FORMAT_NONLITERAL void @@ -6232,7 +6308,11 @@ makewish(void) if (iflags.cmdassist && tries > 0) Strcat(promptbuf, " (enter 'help' for assistance)"); Strcat(promptbuf, "?"); - getlin(promptbuf, buf); + + if (iflags.menu_requested && wish_history[0] && (tries == 0)) + wish_history_menu(buf); + else + getlin(promptbuf, buf); if (iflags.term_gone) { if (!iflags.debug_fuzzer) @@ -6270,9 +6350,11 @@ makewish(void) livelog_printf(LL_WISH, "declined to make a wish"); return; } else if (otmp == &hands_obj) { + wish_history_add(bufcpy); /* wizard mode terrain wish: skip livelogging, etc */ return; } + wish_history_add(bufcpy); if (otmp->oartifact) { /* update artifact bookkeeping; doesn't produce a livelog event */