From c7c0c87859e11be2ea29c3b989829b5cf7156915 Mon Sep 17 00:00:00 2001 From: nhmall Date: Sun, 9 Feb 2020 14:56:37 -0500 Subject: [PATCH] move status condition field selection to its own menu --- include/botl.h | 1 + include/extern.h | 4 +- src/botl.c | 163 ++++++++++++++++++++++++++++++++++------------- src/options.c | 82 ++++++++++++++---------- 4 files changed, 169 insertions(+), 81 deletions(-) diff --git a/include/botl.h b/include/botl.h index 386fd5eaa..579e2efdb 100644 --- a/include/botl.h +++ b/include/botl.h @@ -128,6 +128,7 @@ extern const struct conditions_t conditions[CONDITION_COUNT]; enum condchoice { opt_in, opt_out}; struct condtests_t { enum blconditions c; + const char *useroption; enum condchoice opt; boolean enabled; boolean choice; diff --git a/include/extern.h b/include/extern.h index 88131fcea..4ad7d6a59 100644 --- a/include/extern.h +++ b/include/extern.h @@ -183,7 +183,9 @@ E boolean NDECL(exp_percent_changing); E int NDECL(stat_cap_indx); E int NDECL(stat_hunger_indx); E const char *FDECL(bl_idx_to_fldname, (int)); -E void FDECL(condopt, (boolean *, BOOLEAN_P)); +E void FDECL(condopt, (int, boolean *, BOOLEAN_P)); +E int FDECL(parse_cond_option, (BOOLEAN_P, char *)); +E void NDECL(cond_menu); #ifdef STATUS_HILITES E void NDECL(status_eval_next_unhilite); E void NDECL(reset_status_hilites); diff --git a/src/botl.c b/src/botl.c index cb7cc9fed..89f1ff29e 100644 --- a/src/botl.c +++ b/src/botl.c @@ -576,36 +576,36 @@ const struct conditions_t conditions[] = { }; struct condtests_t condtests[CONDITION_COUNT] = { - /* id, opt_in or out, enabled, configchoice, testresult */ - { bl_bareh, opt_in, FALSE, FALSE, FALSE }, - { bl_blind, opt_out, TRUE, FALSE, FALSE }, - { bl_busy, opt_in, FALSE, FALSE, FALSE }, - { bl_conf, opt_out, TRUE, FALSE, FALSE }, - { bl_deaf, opt_out, TRUE, FALSE, FALSE }, - { bl_elf_iron, opt_out, TRUE, FALSE, FALSE }, - { bl_fly, opt_out, TRUE, FALSE, FALSE }, - { bl_foodpois, opt_out, TRUE, FALSE, FALSE }, - { bl_glowhands, opt_in, FALSE, FALSE, FALSE }, - { bl_grab, opt_out, TRUE, FALSE, FALSE }, - { bl_hallu, opt_out, TRUE, FALSE, FALSE }, - { bl_held, opt_in, FALSE, FALSE, FALSE }, - { bl_icy, opt_in, FALSE, FALSE, FALSE }, - { bl_inlava, opt_out, TRUE, FALSE, FALSE }, - { bl_lev, opt_out, TRUE, FALSE, FALSE }, - { bl_parlyz, opt_in, FALSE, FALSE, FALSE }, - { bl_ride, opt_out, TRUE, FALSE, FALSE }, - { bl_sleeping, opt_in, FALSE, FALSE, FALSE }, - { bl_slime, opt_out, TRUE, FALSE, FALSE }, - { bl_slippery, opt_in, FALSE, FALSE, FALSE }, - { bl_stone, opt_out, TRUE, FALSE, FALSE }, - { bl_strngl, opt_out, TRUE, FALSE, FALSE }, - { bl_stun, opt_out, TRUE, FALSE, FALSE }, - { bl_submerged, opt_in, FALSE, FALSE, FALSE }, - { bl_termill, opt_out, TRUE, FALSE, FALSE }, - { bl_tethered, opt_in, FALSE, FALSE, FALSE }, - { bl_trapped, opt_in, FALSE, FALSE, FALSE }, - { bl_unconsc, opt_in, FALSE, FALSE, FALSE }, - { bl_woundedl, opt_in, FALSE, FALSE, FALSE }, + /* id, useropt, opt_in or out, enabled, configchoice, testresult */ + { bl_bareh, "barehanded", opt_in, FALSE, FALSE, FALSE }, + { bl_blind, "blind", opt_out, TRUE, FALSE, FALSE }, + { bl_busy, "busy", opt_in, FALSE, FALSE, FALSE }, + { bl_conf, "conf", opt_out, TRUE, FALSE, FALSE }, + { bl_deaf, "deaf", opt_out, TRUE, FALSE, FALSE }, + { bl_elf_iron, "iron", opt_out, TRUE, FALSE, FALSE }, + { bl_fly, "fly", opt_out, TRUE, FALSE, FALSE }, + { bl_foodpois, "foodPois", opt_out, TRUE, FALSE, FALSE }, + { bl_glowhands, "glowhands", opt_in, FALSE, FALSE, FALSE }, + { bl_grab, "grab", opt_out, TRUE, FALSE, FALSE }, + { bl_hallu, "hallucinat", opt_out, TRUE, FALSE, FALSE }, + { bl_held, "held", opt_in, FALSE, FALSE, FALSE }, + { bl_icy, "ice", opt_in, FALSE, FALSE, FALSE }, + { bl_inlava, "lava", opt_out, TRUE, FALSE, FALSE }, + { bl_lev, "levitate", opt_out, TRUE, FALSE, FALSE }, + { bl_parlyz, "paralyzed", opt_in, FALSE, FALSE, FALSE }, + { bl_ride, "ride", opt_out, TRUE, FALSE, FALSE }, + { bl_sleeping, "sleep", opt_in, FALSE, FALSE, FALSE }, + { bl_slime, "slime", opt_out, TRUE, FALSE, FALSE }, + { bl_slippery, "slip", opt_in, FALSE, FALSE, FALSE }, + { bl_stone, "stone", opt_out, TRUE, FALSE, FALSE }, + { bl_strngl, "strngl", opt_out, TRUE, FALSE, FALSE }, + { bl_stun, "stun", opt_out, TRUE, FALSE, FALSE }, + { bl_submerged, "submerged", opt_in, FALSE, FALSE, FALSE }, + { bl_termill, "termIll", opt_out, TRUE, FALSE, FALSE }, + { bl_tethered, "tethered", opt_in, FALSE, FALSE, FALSE }, + { bl_trapped, "trap", opt_in, FALSE, FALSE, FALSE }, + { bl_unconsc, "unconscious", opt_in, FALSE, FALSE, FALSE }, + { bl_woundedl, "woundedlegs", opt_in, FALSE, FALSE, FALSE }, }; /* condition indexing */ int cond_idx[CONDITION_COUNT] = { 0 }; @@ -922,7 +922,7 @@ bot_via_windowport() evaluate_and_notify_windowport(g.valset, idx); } - + /* update just the status lines' 'time' field */ static void stat_update_time() @@ -943,30 +943,35 @@ stat_update_time() /* deal with player's choice to change processing of a condition */ void -condopt(addr, negated) +condopt(idx, addr, negated) +int idx; boolean *addr; boolean negated; { int i; - boolean is_init = FALSE; - for (i = 0; i < CONDITION_COUNT; ++i) { - if (!addr) { - /* special: indicates a request to init so - set the choice values to match the defaults */ - is_init = TRUE; + /* sanity check */ + if ((idx < 0 || idx >= CONDITION_COUNT) + || (addr && addr != &condtests[idx].choice)) + return; + + if (!addr) { + /* special: indicates a request to init so + set the choice values to match the defaults */ + for (i = 0; i < CONDITION_COUNT; ++i) { cond_idx[i] = i; condtests[i].choice = condtests[i].enabled; - } else if (addr == &condtests[i].choice) { - condtests[i].enabled = negated ? FALSE : TRUE; } - /* avoid lingering false positives if test is no longer run */ - if (!condtests[i].enabled) - condtests[i].test = FALSE; - } - if (is_init) qsort((genericptr_t) cond_idx, CONDITION_COUNT, sizeof cond_idx[0], cond_cmp); + } else { + /* (addr == &condtests[idx].choice) */ + condtests[idx].enabled = negated ? FALSE : TRUE; + condtests[idx].choice = condtests[idx].enabled; + /* avoid lingering false positives if test is no longer run */ + if (!condtests[idx].enabled) + condtests[idx].test = FALSE; + } } /* qsort callback routine for sorting the condition index */ @@ -984,6 +989,74 @@ const genericptr vptr2; return strcmpi(conditions[indx1].text[0], conditions[indx2].text[0]); } +int +parse_cond_option(negated, opts) +boolean negated; +char *opts; +{ + int i; + size_t sl; + const char *compareto, *uniqpart, prefix[] = "cond_"; + + if (!opts || strlen(opts) <= sizeof prefix - 1) + return 2; + uniqpart = opts + (sizeof prefix - 1); + for (i = 0; i < CONDITION_COUNT; ++i) { + compareto = condtests[i].useroption; + sl = strlen(compareto); + if (match_optname(uniqpart, compareto, (sl >= 4) ? 4 : sl, FALSE)) { + condopt(i, &condtests[i].choice, negated); + return 0; + } + } + return 1; /* !0 indicates error */ +} + +void +cond_menu(VOID_ARGS) +{ + int i, res, idx = 0; + unsigned long ret = 0UL; + winid tmpwin; + anything any; + menu_item *picks = (menu_item *) 0; + char mbuf[QBUFSZ]; + + tmpwin = create_nhwindow(NHW_MENU); + start_menu(tmpwin); + + any = cg.zeroany; + Sprintf(mbuf, "%-21s (ranking)", "field option"); + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, iflags.menu_headings, mbuf, + MENU_ITEMFLAGS_NONE); + for (i = 0; i < SIZE(conditions); i++) { + Sprintf(mbuf, "cond_%-14s (%3d)", condtests[i].useroption, cond_idx[i]); + any = cg.zeroany; + any.a_int = i + 1; /* avoid zero */ + condtests[i].choice = FALSE; + add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, + mbuf, + condtests[i].enabled + ? MENU_ITEMFLAGS_SELECTED : MENU_ITEMFLAGS_NONE); + } + + end_menu(tmpwin, "Choose status conditions to toggle"); + + res = select_menu(tmpwin, PICK_ANY, &picks); + destroy_nhwindow(tmpwin); + if (res > 0) { + for (i = 0; i < res; i++) { + idx = picks[i].item.a_int - 1; + condtests[idx].choice = TRUE; + } + free((genericptr_t) picks); + } + for (i = 0; i < CONDITION_COUNT; ++i) { + if (condtests[i].enabled != condtests[i].choice) + condtests[i].enabled = condtests[i].choice; + } +} + static boolean eval_notify_windowport_field(fld, valsetlist, idx) int fld, idx; diff --git a/src/options.c b/src/options.c index 0b258dbc3..13ece0927 100644 --- a/src/options.c +++ b/src/options.c @@ -115,35 +115,6 @@ static const struct Bool_Opt { { "color", &iflags.wc_color, FALSE, SET_IN_GAME }, #endif { "confirm", &flags.confirm, TRUE, SET_IN_GAME }, - { "cond_barehanded", &condtests[bl_bareh].choice, opt_in, SET_IN_GAME }, - { "cond_blind", &condtests[bl_blind].choice, opt_out, SET_IN_GAME }, - { "cond_busy", &condtests[bl_busy].choice, opt_in, SET_IN_GAME }, - { "cond_conf", &condtests[bl_conf].choice, opt_out, SET_IN_GAME }, - { "cond_deaf", &condtests[bl_deaf].choice, opt_out, SET_IN_GAME }, - { "cond_fly", &condtests[bl_fly].choice, opt_out, SET_IN_GAME }, - { "cond_foodPois", &condtests[bl_foodpois].choice, opt_out, SET_IN_GAME }, - { "cond_glowhands", &condtests[bl_glowhands].choice, opt_in, SET_IN_GAME }, - { "cond_grab", &condtests[bl_grab].choice, opt_out, SET_IN_GAME }, - { "cond_hallu", &condtests[bl_hallu].choice, opt_out, SET_IN_GAME }, - { "cond_held", &condtests[bl_held].choice, opt_in, SET_IN_GAME }, - { "cond_ice" , &condtests[bl_icy].choice, opt_in, SET_IN_GAME }, - { "cond_iron", &condtests[bl_elf_iron].choice, opt_out, SET_IN_GAME }, - { "cond_lava", &condtests[bl_inlava].choice, opt_out, SET_IN_GAME }, - { "cond_lev", &condtests[bl_lev].choice, opt_out, SET_IN_GAME }, - { "cond_unconscious", &condtests[bl_unconsc].choice, opt_in, SET_IN_GAME }, - { "cond_paralyze", &condtests[bl_parlyz].choice, opt_in, SET_IN_GAME }, - { "cond_ride", &condtests[bl_ride].choice, opt_out, SET_IN_GAME }, - { "cond_sleep" , &condtests[bl_sleeping].choice, opt_in, SET_IN_GAME }, - { "cond_slime", &condtests[bl_slime].choice, opt_out, SET_IN_GAME }, - { "cond_slip", &condtests[bl_slippery].choice, opt_in, SET_IN_GAME }, - { "cond_stone", &condtests[bl_stone].choice, opt_out, SET_IN_GAME }, - { "cond_strngl", &condtests[bl_strngl].choice, opt_out, SET_IN_GAME }, - { "cond_stun", &condtests[bl_stun].choice, opt_out, SET_IN_GAME }, - { "cond_submerged" , &condtests[bl_submerged].choice, opt_in, SET_IN_GAME }, - { "cond_termIll", &condtests[bl_termill].choice, opt_out, SET_IN_GAME }, - { "cond_tethered", &condtests[bl_tethered].choice, opt_in, SET_IN_GAME }, - { "cond_trap", &condtests[bl_trapped].choice, opt_in, SET_IN_GAME }, - { "cond_woundedl", &condtests[bl_woundedl].choice, opt_in, SET_IN_GAME }, { "dark_room", &flags.dark_room, TRUE, SET_IN_GAME }, { "eight_bit_tty", &iflags.wc_eight_bit_input, FALSE, SET_IN_GAME }, /*WC*/ #if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS) || defined(X11_GRAPHICS) @@ -732,7 +703,7 @@ initoptions_init() if (boolopt[i].addr) *(boolopt[i].addr) = boolopt[i].initvalue; } - condopt((boolean *) 0, 0); /* make the choices match defaults */ + condopt(0, (boolean *) 0, 0); /* make the choices match defaults */ #ifdef SYSFLAGS Strcpy(sysflags.sysflagsid, "sysflags"); sysflags.sysflagsid[9] = (char) sizeof (struct sysflag); @@ -2002,6 +1973,8 @@ char c; return FALSE; } +#define is_cond_option(x) (!strncmpi((x), "cond_", sizeof "cond_" - 1)) + boolean parseoptions(opts, tinitial, tfrom_file) register char *opts; @@ -2076,6 +2049,29 @@ boolean tinitial, tfrom_file; return retval; } + /* some prefix-based options */ + + if (is_cond_option(opts)) { + int reslt; + + if ((reslt = parse_cond_option(negated, opts)) != 0) { + switch(reslt) { + case 3: + config_error_add("Ambiguous condition option %s", opts); + break; + case 1: + case 2: + default: + config_error_add("Unknown condition option %s (%d)", + opts, reslt); + break; + } + return FALSE; + } + g.opt_need_redraw = TRUE; + return retval; + } + #if defined(MICRO) && !defined(AMIGA) /* included for compatibility with old NetHack.cnf files */ if (match_optname(opts, "IBM_", 4, FALSE)) { @@ -4118,10 +4114,7 @@ boolean tinitial, tfrom_file; map if ascii map isn't supported? */ iflags.wc_ascii_map = negated; } - if (!strncmpi(opts, "cond_", sizeof "cond_" - 1)) { - condopt(boolopt[i].addr, negated); - g.opt_need_redraw = TRUE; - } + /* only do processing below if setting with doset() */ if (g.opt_initial) return retval; @@ -4473,6 +4466,18 @@ int nset; add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, buf, MENU_ITEMFLAGS_NONE); } +static int +count_cond(VOID_ARGS) +{ + int i, cnt = 0; + + for (i = 0; i < CONDITION_COUNT; ++i) { + if (condtests[i].enabled) + cnt++; + } + return cnt; +} + int count_apes(VOID_ARGS) { @@ -4488,6 +4493,7 @@ count_apes(VOID_ARGS) } enum opt_other_enums { + OPT_OTHER_COND = -5, OPT_OTHER_MSGTYPE = -4, OPT_OTHER_MENUCOLOR = -3, OPT_OTHER_STATHILITE = -2, @@ -4502,6 +4508,8 @@ static struct other_opts { int NDECL((*othr_count_func)); } othropt[] = { { "autopickup exceptions", SET_IN_GAME, OPT_OTHER_APEXC, count_apes }, + { "status condition fields", SET_IN_GAME, + OPT_OTHER_COND, count_cond }, { "menu colors", SET_IN_GAME, OPT_OTHER_MENUCOLOR, count_menucolors }, { "message types", SET_IN_GAME, OPT_OTHER_MSGTYPE, msgtype_count }, #ifdef STATUS_HILITES @@ -4675,6 +4683,9 @@ doset() /* changing options via menu by Per Liboriussen */ } else if (opt_indx == OPT_OTHER_MENUCOLOR) { (void) special_handling("menu_colors", setinitial, fromfile); + } else if (opt_indx == OPT_OTHER_COND) { + (void) special_handling("condition_options", setinitial, + fromfile); } else if (opt_indx == OPT_OTHER_MSGTYPE) { (void) special_handling("msgtype", setinitial, fromfile); } else if (opt_indx < boolcount) { @@ -5595,7 +5606,8 @@ boolean setinitial, setfromfile; assign_graphics(PRIMARY); preference_update("symset"); g.opt_need_redraw = TRUE; - + } else if (!strcmp("condition_options", optname)) { + cond_menu(); /* in botl.c */ } else { /* didn't match any of the special options */ return FALSE;