]> granicus.if.org Git - nethack/commitdiff
generic feature_toggle
authornethack.allison <nethack.allison>
Tue, 26 Mar 2002 05:33:04 +0000 (05:33 +0000)
committernethack.allison <nethack.allison>
Tue, 26 Mar 2002 05:33:04 +0000 (05:33 +0000)
This adds a generic feature_toggle mechanism to
the game.  Code that wants to offer two different
ways of doing something can add an entry to
feature_toggles[] (in decl.c), and create a
preprocessor macro for its array index in decl.h.

Then the code can test it using
if (feature_toggle(FEATURE_NAME))
..do_this..
else
..do_that..

The player can toggle the alternate code path
on using OPTIONS=feature_toggle:feature_name_1 feature_name_2 ...

This seems better than creating brand new options
for controlling features (ala prayconfirm, which
could switch to this single option feature_toggle
mechanism as well)

My first use of it is to allow toggling of the selectors
on the loot menu, which I'm hesitant to just change back
because now people are actively using the new selectors and
the complaints would be really loud if the interface were
to just switch back after they adjusted.

The default behaviour is the new behaviour "iob", but with an
OPTIONS=feature_toggle:loot_menu_selectors
in your config file, it will revert to using "abc" as it did
in 3.3.1. I'll add a Guidebook page of "features/behaviour
that can be toggled" later.

The toggles can only be done in defaults.nh, and are
not saved with the game.

include/decl.h
include/extern.h
src/decl.c
src/options.c
src/pickup.c

index 717a23fddcc124bf22ba629a32ecd36431298d75..dcec14aa989730a47f0b1c3e12005318ca6c939a 100644 (file)
@@ -370,6 +370,28 @@ E char *fqn_prefix[PREFIX_COUNT];
 E char *fqn_prefix_names[PREFIX_COUNT];
 #endif
 
+/*
+ * Feature toggles
+ *
+ * The following provide a way to offer two different
+ * behaviours for a game interface feature, and allow
+ * the player to toggle the alternate behaviour on.
+ * The feature_name fields stored in the feature_toggles[]
+ * array can be specified in an OPTIONS=feature_toggle:value1 value2
+ * statement in the config file.
+ */
+
+E unsigned long toggled_features;
+
+E struct features_that_toggle {
+       char *feature_name;
+       unsigned long feature_bit;
+} feature_toggles[];
+
+#define TOGGLE_INVALID                 0
+#define TOGGLE_LOOT_MENU_SELECTORS     1       /* index in feature_toogle_list[] */
+#define LAST_FEATURE_TOGGLE            1
+
 #undef E
 
 #endif /* DECL_H */
index 7bfb13e48c467e72323a1aa561aed3c3bd9d7f29..8ea32912444d55779db23231fc4a262413118f08 100644 (file)
@@ -1353,6 +1353,7 @@ E char *FDECL(nh_getenv, (const char *));
 E void FDECL(set_duplicate_opt_detection, (int));
 E void FDECL(set_wc_option_mod_status, (unsigned long, int));
 E void FDECL(set_option_mod_status, (char *, int));
+E boolean FDECL(feature_toggle, (int));
 
 /* ### pager.c ### */
 
index a82e493b7e0c91805c2d0c27ff0a6b8c58bb616c..a8f5e719c702ad16baee0e37a47ffc40e5e6e19d 100644 (file)
@@ -268,6 +268,21 @@ char *fqn_prefix_names[PREFIX_COUNT] = { "hackdir", "leveldir", "savedir",
                                        "bonesdir", "datadir", "scoredir",
                                        "lockdir", "configdir" };
 #endif
+
+/*
+ * The following provide a way to offer two different
+ * behaviours for a game interface feature, and allow
+ * the player to toggle the alternate behaviour on.
+ * The strings in the feature_toggles[] array can be
+ * specified in an OPTIONS=feature_toggle:value1 value2
+ * statement in the config file.
+ */
+unsigned long toggled_features = 0L;
+
+struct features_that_toggle feature_toggles[] = {
+       {(char *)0,     0x00000000L},           /*  0 = TOGGLE_INVALID              */
+       {"loot_menu_selectors", 0x00000001L},   /*  1 = TOGGLE_LOOT_MENU_SELECTORS  */
+};
                        
 /* dummy routine used to force linkage */
 void
index a63de72d5eeb90e4f929f28ab7b19534ea38260a..4568766d7e7bcb06896842acf7a983c95e688d15 100644 (file)
@@ -219,6 +219,7 @@ static struct Comp_Opt
                                                MAXDCHARS+1, SET_IN_FILE },
        { "effects",  "the symbols to use in drawing special effects",
                                                MAXECHARS+1, SET_IN_FILE },
+       { "feature_toggle",   "alternate feature behaviour", 79, SET_IN_FILE },
        { "font_map", "the font to use in the map window", 40, DISP_IN_GAME },  /*WC*/
        { "font_menu", "the font to use in menus", 40, DISP_IN_GAME },          /*WC*/
        { "font_message", "the font to use in the message window",
@@ -1041,6 +1042,43 @@ boolean tinitial, tfrom_file;
                return;
        }
 
+       fullname = "feature_toggle";
+       if (match_optname(opts, fullname, 11, TRUE)) {
+               char buf[BUFSZ];
+               char *feature;
+               boolean matched = FALSE;
+               if (!(op = string_for_opt(opts, FALSE)))
+                       return;
+               if (!negated) {
+                   boolean has_badfield = FALSE;
+                   char badfields[BUFSZ];
+                   buf[BUFSZ-1] = '\0';
+
+                   Strcpy(badfields, "feature_toggle:");
+                   (void)strncpy(buf, op, BUFSZ - 1);
+                   (void)mungspaces(buf);
+                   feature = strtok(buf, " \n");
+                   while(feature && *feature && *feature != ' ') {
+                       matched = FALSE;
+                       for (num = 1; num <= LAST_FEATURE_TOGGLE; num++) {
+                           if (!strcmpi(feature, feature_toggles[num].feature_name)) {
+                               toggled_features |= feature_toggles[num].feature_bit;
+                               matched = TRUE;
+                           }
+                       }
+                       if (!matched) {
+                               if (has_badfield) Strcat(badfields, " ");
+                               Strcat(badfields, feature);
+                               has_badfield = TRUE;
+                       }
+                       feature = strtok((char *)0, " \n");
+                   }
+                   if (has_badfield) badoption(badfields);
+               } else
+                       bad_negation(fullname, FALSE);
+               return;
+       }
+
        fullname = "horsename";
        if (match_optname(opts, fullname, 5, TRUE)) {
                if (negated) bad_negation(fullname, FALSE);
@@ -3249,6 +3287,16 @@ char *op;
        return 1;
 }
 
+boolean
+feature_toggle(ftidx)
+int ftidx;
+{
+       if (ftidx > 0 && ftidx <= LAST_FEATURE_TOGGLE) {
+               if (toggled_features & feature_toggles[ftidx].feature_bit)
+                       return TRUE;
+       }
+       return FALSE;
+}
 #endif /* OPTION_LISTS_ONLY */
 
 /*options.c*/
index 19a8bf5ea5c22f1a2e062f953ea7dac32386a7e7..0cadd6382e4d5c166639af039ab206e00086a715 100644 (file)
@@ -2197,18 +2197,21 @@ struct obj *obj;
     menu_item *pick_list;
     char buf[BUFSZ];
     int n;
+    char oldmenu[3] = {'a', 'b', 'c'}, newmenu[3] = {'o', 'i', 'b'};
+    char *menuselector = newmenu;
 
+    if (feature_toggle(TOGGLE_LOOT_MENU_SELECTORS)) menuselector = oldmenu;
     any.a_void = 0;
     win = create_nhwindow(NHW_MENU);
     start_menu(win);
     any.a_int = 1;
     Sprintf(buf,"Take %s out of %s", something, the(xname(obj)));
-    add_menu(win, NO_GLYPH, &any, 'o', 0, ATR_NONE, buf, MENU_UNSELECTED);
+    add_menu(win, NO_GLYPH, &any, *menuselector++, 0, ATR_NONE, buf, MENU_UNSELECTED);
     any.a_int = 2;
     Sprintf(buf,"Put %s into %s", something, the(xname(obj)));
-    add_menu(win, NO_GLYPH, &any, 'i', 0, ATR_NONE, buf, MENU_UNSELECTED);
+    add_menu(win, NO_GLYPH, &any, *menuselector++, 0, ATR_NONE, buf, MENU_UNSELECTED);
     any.a_int = 3;
-    add_menu(win, NO_GLYPH, &any, 'b', 0, ATR_NONE,
+    add_menu(win, NO_GLYPH, &any, *menuselector, 0, ATR_NONE,
                "Both of the above", MENU_UNSELECTED);
     end_menu(win, prompt);
     n = select_menu(win, PICK_ONE, &pick_list);