]> granicus.if.org Git - nethack/commitdiff
status condition options
authorPatR <rankin@nethack.org>
Mon, 31 Oct 2022 07:53:10 +0000 (00:53 -0700)
committerPatR <rankin@nethack.org>
Mon, 31 Oct 2022 07:53:10 +0000 (00:53 -0700)
Option parsing rejected
|OPTIONS=!cond_X
for all valid X.

Using the menu to unselect all condition options treated that as not
having made any choice and didn't make any changes.  That would be
reasonable if nothing was preselected, but things are so unselecting
all of them is a choice.  (A bizarre one, but still should be viable.)

Mostly this deals with including cond_X options when #saveoptions is
used to write a new RC file.  It now produces something like
|OPTIONS=!cond_barehanded,cond_blind,!cond_busy,cond_conf,!cond_deaf,\
|        cond_iron,cond_fly,cond_foodPois,!cond_glowhands,cond_grab,\
|        cond_hallucinat,!cond_held,!cond_ice,cond_lava,cond_levitate,\
|        !cond_paralyzed,cond_ride,!cond_sleep,cond_slime,!cond_slip,\
|        cond_stone,cond_strngl,cond_stun,!cond_submerged,cond_termIll,\
|        !cond_tethered,!cond_trap,!cond_unconscious,!cond_woundedlegs,\
|        !cond_holding
after the last alphabetical option and before the bound keys, menu
colors, and others which aren't simple OPTIONS=X settings.  This only
happens if there is already one or more OPTIONS=cond_X entries in the
old file when it was read or if 'mO' gets used to make any changes.

Not fixed:  after my RC had something similar to the above and before
I changed status conditions to accept negation, I was getting several
"the cond_ option may not both have a value and be negated" messages
written to stdout instead of the config file error handler.  So they
vanished when the screen was initialized without providing a --More--
prompt to acknowledge that they have been seen.

include/extern.h
include/optlist.h
src/botl.c
src/options.c

index 55cb0e43dd3aea8b4b1fff13a71d8fa47a3c13c1..8e54823484b91d26104437b381a44a3b1f3aeff2 100644 (file)
@@ -197,6 +197,7 @@ extern const char *bl_idx_to_fldname(int);
 extern void condopt(int, boolean *, boolean);
 extern int parse_cond_option(boolean, char *);
 extern void cond_menu(void);
+extern boolean opt_next_cond(int, char *);
 #ifdef STATUS_HILITES
 extern void status_eval_next_unhilite(void);
 extern void reset_status_hilites(void);
index 95480b489a806d7e84f19a718034d1b2245c7bd0..d1c8c7d08c05e45b7bfeed51ef12eb3ffe006944 100644 (file)
@@ -686,7 +686,7 @@ static int optfn_##a(int, int, boolean, char *, char *);
      */
 
     NHOPTP(cond_, Advanced, 0, opt_in, set_hidden,
-                No, No, Yes, Yes, NoAlias, "prefix for cond_ options")
+                Yes, No, Yes, Yes, NoAlias, "prefix for cond_ options")
     NHOPTP(font, Advanced, 0, opt_in, set_hidden,
                 Yes, Yes, Yes, No, NoAlias, "prefix for font options")
 #if defined(MICRO) && !defined(AMIGA)
index a648d2f4325deb2f027f29bf8999ceed7cff1a4b..099eb15061e9466491d6afa5cf51c44c0b0075ae 100644 (file)
@@ -1134,13 +1134,46 @@ cond_menu(void)
         }
     } while (showmenu);
 
-    if (res > 0) {
+    if (res >= 0) {
         for (i = 0; i < CONDITION_COUNT; ++i)
             if (condtests[i].enabled != condtests[i].choice) {
                 condtests[i].enabled = condtests[i].choice;
                 g.context.botl = TRUE;
             }
     }
+    return;
+}
+
+/* called by all_options_conds() to get value for next cond_xyz option
+   so that #saveoptions can collect it and write the set into new RC file */
+boolean
+opt_next_cond(int indx, char *outbuf)
+{
+    *outbuf = '\0';
+    if (indx >= CONDITION_COUNT)
+        return FALSE;
+
+    /*
+     * The entries are returned in internal order which requires the
+     * least code.  It would be easy to sort them into alphabetic order
+     * (just sort all over again for every requested entry:
+     *  int i, sequence[CONDITION_COUNT]
+     *  for (i = 0; i < CONDITION_COUNT; ++i) sequence[i] = i;
+     *  qsort(sequence, ..., menualpha_cmp);
+     *  indx = sequence[indx];
+     *  Sprintf(outbuf, ...);
+     * with no need to hang on to 'sequence[]' between calls).
+     *
+     * But using 'severity order' isn't feasible unless the player has
+     * used 'mO' on conditions in this session.  Even then, they would
+     * revert to the default order (whether internal or alphabetical)
+     * if #saveoptions got used in some later session where doset()
+     * wasn't used to choose their preferred order.
+     */
+
+    Sprintf(outbuf, "%scond_%s", condtests[indx].enabled ? "" : "!",
+            condtests[indx].useroption);
+    return TRUE;
 }
 
 static boolean
index 184904a2a5cb20544e64b7e1a6592240106bfe0d..fe0be2b5dd63a980d3f8daf48bcee52e7e95fabf 100644 (file)
@@ -300,6 +300,7 @@ static unsigned int longest_option_name(int, int);
 static int doset_simple_menu(void);
 static void doset_add_menu(winid, const char *, const char *, int, int);
 static int handle_add_list_remove(const char *, int);
+static void all_options_conds(strbuf_t *);
 static void all_options_menucolors(strbuf_t *);
 static void all_options_msgtypes(strbuf_t *);
 static void all_options_apes(strbuf_t *);
@@ -324,7 +325,7 @@ static int handler_sortloot(void);
 static int handler_symset(int);
 static int handler_whatis_coord(void);
 static int handler_whatis_filter(void);
-/* next few are not allopts[] entries, so will only be called
+/* next few are not allopt[] entries, so will only be called
    directly from doset, not from individual optfn's */
 static int handler_autopickup_exception(void);
 static int handler_menu_colors(void);
@@ -4224,30 +4225,36 @@ optfn_windowtype(int optidx, int req, boolean negated UNUSED,
  */
 
 static int
-pfxfn_cond_(int optidx UNUSED, int req, boolean negated,
-            char *opts, char *op UNUSED)
+pfxfn_cond_(
+    int optidx,
+    int req,
+    boolean negated,
+    char *opts,
+    char *op UNUSED)
 {
-    int reslt;
-
     if (req == do_init) {
         condopt(0, (boolean *) 0, 0); /* make the choices match defaults */
         return optn_ok;
     }
     if (req == do_set) {
-        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 optn_err;
+        int reslt = parse_cond_option(negated, opts);
+
+        switch (reslt) {
+        case 0:
+            opt_set_in_config[optidx] = TRUE;
+            break;
+        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;
         }
+        if (reslt != 0)
+            return optn_err;
+        /* [FIXME?  redraw seems like overkill; botl update should suffice] */
         g.opt_need_redraw = TRUE;
         return optn_ok;
     }
@@ -4418,8 +4425,13 @@ pfxfn_IBM_(int optidx UNUSED, int req, boolean negated UNUSED,
 #endif
 
 #ifndef NO_VERBOSE_GRANULARITY
-int pfxfn_verbose(int optidx UNUSED, int req, boolean negated,
-           char *opts, char *op)
+int
+pfxfn_verbose(
+    int optidx UNUSED,
+    int req,
+     boolean negated,
+    char *opts,
+    char *op)
 {
     long ltmp = 0;
     int reslt;
@@ -7838,20 +7850,28 @@ optfn_o_message_types(int optidx UNUSED, int req, boolean negated UNUSED,
 }
 
 static int
-optfn_o_status_cond(int optidx UNUSED, int req, boolean negated UNUSED,
-              char *opts, char *op UNUSED)
+optfn_o_status_cond(
+    int optidx UNUSED,
+    int req,
+    boolean negated UNUSED,
+    char *opts,
+    char *op UNUSED)
 {
     if (req == do_init) {
         return optn_ok;
     }
     if (req == do_set) {
+        ; /* setting status condition options goes through pfxfn_cond_() */
     }
-    if (req == get_val || req == get_cnf_val) {
-        if (!opts)
+    if (req == get_val) {
+        if (!opts) /* opts[] is used as an output argument */
             return optn_err;
         Sprintf(opts, n_currently_set, count_cond());
         return optn_ok;
     }
+    if (req == get_cnf_val) {
+        ; /* handled inline by all_options_stringbuf() */
+    }
     if (req == do_handler) {
         cond_menu();
         return optn_ok;
@@ -8879,6 +8899,34 @@ option_help(void)
     return;
 }
 
+static void
+all_options_conds(strbuf_t *sbuf)
+{
+    char tmp[BUFSZ], buf[BUFSZ];
+    int idx = 0;
+
+    tmp[0] = '\0';
+    while (opt_next_cond(idx, buf)) {
+        /* 75: room for about 5 conditions, with enough space for player
+           to edit the resulting file manually and insert '!' */
+        if (idx == 0 || Strlen(tmp) + 1 + Strlen(buf) >= 75) {
+            if (idx > 0) {
+                /* finish off previous line */
+                Strcat(tmp, ",");
+                Strcat(tmp, "\\\n"); /* backslash+newline */
+                strbuf_append(sbuf, tmp);
+            }
+            Sprintf(tmp, "%-8s%s", (idx == 0) ? "OPTIONS=" : " ", buf);
+        } else {
+            Sprintf(eos(tmp), ",%s", buf);
+        }
+        ++idx;
+    }
+    /* finish off final line */
+    Strcat(tmp, "\n");
+    strbuf_append(sbuf, tmp);
+}
+
 /* append menucolor lines to strbuf */
 static void
 all_options_menucolors(strbuf_t *sbuf)
@@ -8892,7 +8940,7 @@ all_options_menucolors(strbuf_t *sbuf)
         return;
 
     /* reverse the order */
-    arr = (struct menucoloring **)alloc(ncolors * sizeof(struct menucoloring *));
+    arr = (struct menucoloring **) alloc(ncolors * sizeof *arr);
     while (tmp) {
         arr[i++] = tmp;
         tmp = tmp->next;
@@ -8993,6 +9041,11 @@ all_options_strbuf(strbuf_t *sbuf)
         }
     }
 
+    /* cond_xyz are closer to regular options than the other 'other opts'
+       so put them next */
+    if (opt_set_in_config[opt_o_status_cond])
+        all_options_conds(sbuf);
+
     get_changed_key_binds(sbuf);
     savedsym_strbuf(sbuf);
     all_options_menucolors(sbuf);