]> granicus.if.org Git - nethack/commitdiff
expand the pool of status condition fields
authornhmall <nhmall@nethack.org>
Sat, 8 Feb 2020 06:03:25 +0000 (01:03 -0500)
committernhmall <nhmall@nethack.org>
Sat, 8 Feb 2020 06:03:25 +0000 (01:03 -0500)
Most of the additional ones are "opt-in" meaning that unless you add them
to your config file to enable them, they won't show up.

Two that aren't "opt-in", but can be "opted-out" (as can they all) are
cond_grab (for an eel grabbing you and drowing being imminent) and
cond_lava which leads to a fatality.

All the ones that already existed are "opt-out" options, meaning that
they will still show if you do nothing.

Here's the complete list of status conditions following this patch:
 config option     internal     default mask id            mask        text1    tex2   text3
"cond_barehanded"  bl_bareh     opt_in  BL_MASK_BAREH      0x00000001L Bare     Bar    Bh
"cond_blind"       bl_blind     opt_out BL_MASK_BLIND      0x00000002L Blind    Blnd   Bl
"cond_busy"        bl_busy      opt_in  BL_MASK_BUSY       0x00000004L Busy     Bsy    By
"cond_conf"        bl_conf      opt_out BL_MASK_CONF       0x00000008L Conf     Cnf    Cf
"cond_deaf"        bl_deaf      opt_out BL_MASK_DEAF       0x00000010L Deaf     Def    Df
"cond_iron"        bl_elf_iron  opt_out BL_MASK_ELF_IRON   0x00000020L Iron     Irn    Fe
"cond_fly"         bl_fly       opt_out BL_MASK_FLY        0x00000040L Fly      Fly    Fl
"cond_foodPois"    bl_foodpois  opt_out BL_MASK_FOODPOIS   0x00000080L FoodPois Fpois  Poi
"cond_glowhands"   bl_glowhands opt_in  BL_MASK_GLOWHANDS  0x00000100L Glow     Glo    Gl
"cond_grab"        bl_grab      opt_out BL_MASK_GRAB       0x00000200L Grab     Grb    Gr
"cond_hallu"       bl_hallu     opt_out BL_MASK_HALLU      0x00000400L Hallu    Hal    Hl
"cond_held"        bl_held      opt_in  BL_MASK_HELD       0x00000800L Held     Hld    Hd
"cond_ice"         bl_icy       opt_in  BL_MASK_ICY        0x00001000L Icy      Icy    Ic
"cond_lava"        bl_inlava    opt_out BL_MASK_INLAVA     0x00002000L Lava     Lav    La
"cond_lev"         bl_lev       opt_out BL_MASK_LEV        0x00004000L Lev      Lev    Lv
"cond_paralyze"    bl_parlyz    opt_in  BL_MASK_PARLYZ     0x00008000L Parlyz   Para   Par
"cond_ride"        bl_ride      opt_out BL_MASK_RIDE       0x00010000L Ride     Rid    Rd
"cond_sleep"       bl_sleeping  opt_in  BL_MASK_SLEEPING   0x00020000L Zzz      Zzz    Zz
"cond_slime"       bl_slime     opt_out BL_MASK_SLIME      0x00040000L Slime    Slim   Slm
"cond_slip"        bl_slippery  opt_in  BL_MASK_SLIPPERY   0x00080000L Slip     Sli    Sl
"cond_stone"       bl_stone     opt_out BL_MASK_STONE      0x00100000L Stone    Ston   Sto
"cond_strngl"      bl_strngl    opt_out BL_MASK_STRNGL     0x00200000L Strngl   Stngl  Str
"cond_stun"        bl_stun      opt_out BL_MASK_STUN       0x00400000L Stun     Stun   St
"cond_submerged"   bl_submerged opt_in  BL_MASK_SUBMERGED  0x00800000L Sub      Sub    Sw
"cond_termIll"     bl_termill   opt_out BL_MASK_TERMILL    0x01000000L TermIll  Ill    Ill
"cond_tethered"    bl_tethered  opt_in  BL_MASK_TETHERED   0x02000000L Teth     Tth    Te
"cond_trap"        bl_trapped   opt_in  BL_MASK_TRAPPED    0x04000000L Trap     Trp    Tr
"cond_unconscious" bl_unconsc   opt_in  BL_MASK_UNCONSC    0x08000000L Out      Out    KO
"cond_woundedl"    bl_woundedl  opt_in  BL_MASK_WOUNDEDL   0x10000000L Legs     Leg    Lg

doc/window.doc
include/botl.h
include/extern.h
src/botl.c
src/options.c
win/curses/cursstat.c
win/tty/wintty.c

index 46b00ad908a44a2c7e218f9d495104736dd0aa7a..2ff17f114da9764bdd07470072d2806a01247fe9 100644 (file)
@@ -420,19 +420,35 @@ status_update(int fldindex, genericptr_t ptr, int chg, int percentage, int color
                -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
                   If fldindex is BL_CONDITION, then ptr is a long value with
                   any or none of the following bits set (from botl.h):
-                        BL_MASK_STONE           0x00000001L
-                        BL_MASK_SLIME           0x00000002L
-                        BL_MASK_STRNGL          0x00000004L
-                        BL_MASK_FOODPOIS        0x00000008L
-                        BL_MASK_TERMILL         0x00000010L
-                        BL_MASK_BLIND           0x00000020L
-                        BL_MASK_DEAF            0x00000040L
-                        BL_MASK_STUN            0x00000080L
-                        BL_MASK_CONF            0x00000100L
-                        BL_MASK_HALLU           0x00000200L
-                        BL_MASK_LEV             0x00000400L
-                        BL_MASK_FLY             0x00000800L
-                        BL_MASK_RIDE            0x00001000L
+                        BL_MASK_BAREH        0x00000001L
+                        BL_MASK_BLIND        0x00000002L
+                        BL_MASK_BUSY         0x00000004L
+                        BL_MASK_CONF         0x00000008L
+                        BL_MASK_DEAF         0x00000010L
+                        BL_MASK_ELF_IRON     0x00000020L
+                        BL_MASK_FLY          0x00000040L
+                        BL_MASK_FOODPOIS     0x00000080L
+                        BL_MASK_GLOWHANDS    0x00000100L
+                        BL_MASK_GRAB         0x00000200L
+                        BL_MASK_HALLU        0x00000400L
+                        BL_MASK_HELD         0x00000800L
+                        BL_MASK_ICY          0x00001000L
+                        BL_MASK_INLAVA       0x00002000L
+                        BL_MASK_LEV          0x00004000L
+                        BL_MASK_PARLYZ       0x00008000L
+                        BL_MASK_RIDE         0x00010000L
+                        BL_MASK_SLEEPING     0x00020000L
+                        BL_MASK_SLIME        0x00040000L
+                        BL_MASK_SLIPPERY     0x00080000L
+                        BL_MASK_STONE        0x00100000L
+                        BL_MASK_STRNGL       0x00200000L
+                        BL_MASK_STUN         0x00400000L
+                        BL_MASK_SUBMERGED    0x00800000L
+                        BL_MASK_TERMILL      0x01000000L
+                        BL_MASK_TETHERED     0x02000000L
+                        BL_MASK_TRAPPED      0x04000000L
+                        BL_MASK_UNCONSC      0x08000000L
+                        BL_MASK_WOUNDEDL     0x10000000L
                -- The value passed for BL_GOLD includes a leading
                   symbol for GOLD "$:nnn". If the window port needs to use 
                   the textual gold amount without the leading "$:" the port 
index d3225153ad2cc7123eda788857250f3cf2a83686..708cfa8a3b2de966b772309e13d66172ffefba84 100644 (file)
@@ -48,28 +48,97 @@ enum relationships { NO_LTEQGT = -1,
                      EQ_VALUE, LT_VALUE, LE_VALUE,
                      GE_VALUE, GT_VALUE, TXT_VALUE };
 
-#define BEFORE  0
-#define NOW     1
+enum blconditions {
+    bl_bareh,
+    bl_blind,
+    bl_busy,
+    bl_conf,
+    bl_deaf,
+    bl_elf_iron,
+    bl_fly,
+    bl_foodpois,
+    bl_glowhands,
+    bl_grab,
+    bl_hallu,
+    bl_held,
+    bl_icy,
+    bl_inlava,
+    bl_lev,
+    bl_parlyz,
+    bl_ride,
+    bl_sleeping,
+    bl_slime,
+    bl_slippery,
+    bl_stone,
+    bl_strngl,
+    bl_stun,
+    bl_submerged,
+    bl_termill,
+    bl_tethered,
+    bl_trapped,
+    bl_unconsc,
+    bl_woundedl,
+
+    CONDITION_COUNT
+};
 
 /* Boolean condition bits for the condition mask */
 
 /* clang-format off */
-#define BL_MASK_STONE           0x00000001L
-#define BL_MASK_SLIME           0x00000002L
-#define BL_MASK_STRNGL          0x00000004L
-#define BL_MASK_FOODPOIS        0x00000008L
-#define BL_MASK_TERMILL         0x00000010L
-#define BL_MASK_BLIND           0x00000020L
-#define BL_MASK_DEAF            0x00000040L
-#define BL_MASK_STUN            0x00000080L
-#define BL_MASK_CONF            0x00000100L
-#define BL_MASK_HALLU           0x00000200L
-#define BL_MASK_LEV             0x00000400L
-#define BL_MASK_FLY             0x00000800L
-#define BL_MASK_RIDE            0x00001000L
-#define BL_MASK_BITS            13 /* number of mask bits that can be set */
+#define BL_MASK_BAREH        0x00000001L
+#define BL_MASK_BLIND        0x00000002L
+#define BL_MASK_BUSY         0x00000004L
+#define BL_MASK_CONF         0x00000008L
+#define BL_MASK_DEAF         0x00000010L
+#define BL_MASK_ELF_IRON     0x00000020L
+#define BL_MASK_FLY          0x00000040L
+#define BL_MASK_FOODPOIS     0x00000080L
+#define BL_MASK_GLOWHANDS    0x00000100L
+#define BL_MASK_GRAB         0x00000200L
+#define BL_MASK_HALLU        0x00000400L
+#define BL_MASK_HELD         0x00000800L
+#define BL_MASK_ICY          0x00001000L
+#define BL_MASK_INLAVA       0x00002000L
+#define BL_MASK_LEV          0x00004000L
+#define BL_MASK_PARLYZ       0x00008000L
+#define BL_MASK_RIDE         0x00010000L
+#define BL_MASK_SLEEPING     0x00020000L
+#define BL_MASK_SLIME        0x00040000L
+#define BL_MASK_SLIPPERY     0x00080000L
+#define BL_MASK_STONE        0x00100000L
+#define BL_MASK_STRNGL       0x00200000L
+#define BL_MASK_STUN         0x00400000L
+#define BL_MASK_SUBMERGED    0x00800000L
+#define BL_MASK_TERMILL      0x01000000L
+#define BL_MASK_TETHERED     0x02000000L
+#define BL_MASK_TRAPPED      0x04000000L
+#define BL_MASK_UNCONSC      0x08000000L
+#define BL_MASK_WOUNDEDL     0x10000000L
+#define BL_MASK_BITS            28 /* number of mask bits that can be set */
 /* clang-format on */
 
+struct conditions_t {
+    int priority;
+    long mask;
+    enum blconditions c;
+    const char *text[3];
+};
+extern const struct conditions_t conditions[CONDITION_COUNT];
+
+enum condchoice { opt_in, opt_out};
+struct condtests_t {
+    enum blconditions c;
+    enum condchoice opt;
+    boolean enabled;
+    boolean choice;
+    boolean test;
+};
+
+extern struct condtests_t condtests[CONDITION_COUNT];
+
+#define BEFORE  0
+#define NOW     1
+
 /*
  * Possible additional conditions:
  *  major:
index c19f8df64de47d94d1913171939f0f4c2fcacbfc..fb493078c342b3222877e65ef89820acc24b56bf 100644 (file)
@@ -183,6 +183,7 @@ 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));
 #ifdef STATUS_HILITES
 E void NDECL(status_eval_next_unhilite);
 E void NDECL(reset_status_hilites);
index a9e9a9bccaae63b99292749d1a270a7661a7f336..bee41e409199f99660f438837a9350dd8c9f5a0d 100644 (file)
@@ -421,6 +421,7 @@ static int FDECL(compare_blstats, (struct istat_s *, struct istat_s *));
 static char *FDECL(anything_to_s, (char *, anything *, int));
 static int FDECL(percentage, (struct istat_s *, struct istat_s *));
 static int NDECL(exp_percentage);
+static boolean FDECL(test_condition, (enum blconditions, struct permonst *));
 
 #ifdef STATUS_HILITES
 static void FDECL(s_to_anything, (anything *, char *, int));
@@ -510,8 +511,117 @@ static struct istat_s initblstats[MAXBLSTATS] = {
 #undef INIT_BLSTAT
 #undef INIT_THRESH
 
-#ifdef STATUS_HILITES
-#endif
+const struct conditions_t conditions[] = {
+    /* priority, mask, identifier, txt1, txt2, txt3 */
+    { 3, BL_MASK_BAREH,     bl_bareh,     { "Bare",     "Bar",   "Bh"  } },
+    { 2, BL_MASK_BLIND,     bl_blind,     { "Blind",    "Blnd",  "Bl"  } },
+    { 3, BL_MASK_BUSY,      bl_busy,      { "Busy",     "Bsy",   "By"  } },
+    { 2, BL_MASK_CONF,      bl_conf,      { "Conf",     "Cnf",   "Cf"  } },
+    { 2, BL_MASK_DEAF,      bl_deaf,      { "Deaf",     "Def",   "Df"  } },
+    { 3, BL_MASK_ELF_IRON,  bl_elf_iron,  { "Iron",     "Irn",   "Fe"  } },
+    { 2, BL_MASK_FLY,       bl_fly,       { "Fly",      "Fly",   "Fl"  } },
+    { 2, BL_MASK_FOODPOIS,  bl_foodpois,  { "FoodPois", "Fpois", "Poi" } },
+    { 3, BL_MASK_GLOWHANDS, bl_glowhands, { "Glow",     "Glo",   "Gl"  } },
+    { 2, BL_MASK_GRAB,      bl_grab,      { "Grab",     "Grb",   "Gr"  } },
+    { 2, BL_MASK_HALLU,     bl_hallu,     { "Hallu",    "Hal",   "Hl"  } },
+    { 3, BL_MASK_HELD,      bl_held,      { "Held",     "Hld",   "Hd"  } },
+    { 3, BL_MASK_ICY,       bl_icy,       { "Icy",      "Icy",   "Ic"  } },
+    { 2, BL_MASK_INLAVA,    bl_inlava,    { "Lava",     "Lav",   "La"  } },
+    { 2, BL_MASK_LEV,       bl_lev,       { "Lev",      "Lev",   "Lv"  } },
+    { 3, BL_MASK_PARLYZ,    bl_parlyz,    { "Parlyz",   "Para",  "Par" } },
+    { 2, BL_MASK_RIDE,      bl_ride,      { "Ride",     "Rid",   "Rd"  } },
+    { 3, BL_MASK_SLEEPING,  bl_sleeping,  { "Zzz",      "Zzz",   "Zz"  } },
+    { 2, BL_MASK_SLIME,     bl_slime,     { "Slime",    "Slim",  "Slm" } },
+    { 3, BL_MASK_SLIPPERY,  bl_slippery,  { "Slip",     "Sli",   "Sl"  } },
+    { 2, BL_MASK_STONE,     bl_stone,     { "Stone",    "Ston",  "Sto" } },
+    { 2, BL_MASK_STRNGL,    bl_strngl,    { "Strngl",   "Stngl", "Str" } },
+    { 2, BL_MASK_STUN,      bl_stun,      { "Stun",     "Stun",  "St"  } },
+    { 3, BL_MASK_SUBMERGED, bl_submerged, { "Sub",      "Sub",   "Sw"  } },
+    { 2, BL_MASK_TERMILL,   bl_termill,   { "TermIll",  "Ill",   "Ill" } },
+    { 3, BL_MASK_TETHERED,  bl_tethered,  { "Teth",     "Tth",   "Te"  } },
+    { 3, BL_MASK_TRAPPED,   bl_trapped,   { "Trap",     "Trp",   "Tr"  } },
+    { 3, BL_MASK_UNCONSC,   bl_unconsc,   { "Out",      "Out",   "KO"  } },
+    { 3, BL_MASK_WOUNDEDL,  bl_woundedl,  { "Legs",     "Leg",   "Lg"  } },
+};
+
+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 },
+};
+
+/* cache-related */
+static boolean cache_avail[3] = { FALSE, FALSE, FALSE };
+static boolean cache_reslt[3] = { FALSE, FALSE, FALSE };
+static const char *cache_nomovemsg = NULL, *cache_multi_reason = NULL;
+static d_level cache_uz = { 0 };
+static boolean cache_underwater = FALSE;
+
+#define cond_cache_prep()                                   \
+do {                                                        \
+    boolean clear_cache = FALSE, refresh_cache = FALSE;     \
+                                                            \
+    if (g.multi < 0) {                                      \
+        if (g.nomovemsg || g.multi_reason) {                \
+            if (cache_nomovemsg != g.nomovemsg)             \
+                refresh_cache = TRUE;                       \
+            if (cache_multi_reason != g.multi_reason)       \
+                refresh_cache = TRUE;                       \
+        } else {                                            \
+            clear_cache = TRUE;                             \
+        }                                                   \
+    } else {                                                \
+        clear_cache = TRUE;                                 \
+    }                                                       \
+    if (clear_cache) {                                      \
+        cache_nomovemsg = (const char *) 0;                 \
+        cache_multi_reason = (const char *) 0;              \
+    }                                                       \
+    if (refresh_cache) {                                    \
+        cache_nomovemsg = g.nomovemsg;                      \
+        cache_multi_reason = g.multi_reason;                \
+    }                                                       \
+    if (clear_cache || refresh_cache) {                     \
+        cache_reslt[0] = cache_avail[0] = FALSE;            \
+        cache_reslt[1] = cache_avail[1] = FALSE;            \
+    }                                                       \
+    if (((cache_uz.dnum != u.uz.dnum)                       \
+        || (cache_uz.dlevel != u.uz.dlevel))                \
+        || (cache_underwater != Underwater))  {             \
+        cache_uz.dnum = 0;                                  \
+        cache_uz.dlevel = 0;                                \
+        cache_underwater = 0;                               \
+        cache_reslt[2] = cache_avail[2] = FALSE;            \
+    }                                                       \
+} while (0)
+
 /* we don't put this next declaration in #ifdef STATUS_HILITES.
  * In the absence of STATUS_HILITES, each array
  * element will be 0 however, and quite meaningless,
@@ -667,40 +777,119 @@ bot_via_windowport()
     g.valset[BL_CAP] = TRUE;
 
     /* Conditions */
+
     g.blstats[idx][BL_CONDITION].a.a_ulong = 0L;
-    if (Stoned)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STONE;
-    if (Slimed)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_SLIME;
-    if (Strangled)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STRNGL;
-    if (Sick && (u.usick_type & SICK_VOMITABLE) != 0)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FOODPOIS;
-    if (Sick && (u.usick_type & SICK_NONVOMITABLE) != 0)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_TERMILL;
-    /*
-     * basic formatting puts hunger status and encumbrance here
-     */
-    if (Blind)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_BLIND;
-    if (Deaf)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_DEAF;
-    if (Stunned)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_STUN;
-    if (Confusion)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_CONF;
-    if (Hallucination)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_HALLU;
-    /* levitation and flying are mututally exclusive */
-    if (Levitation)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_LEV;
-    if (Flying)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FLY;
-    if (u.usteed)
-        g.blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_RIDE;
+
+    /* avoid anything that does string comparisons in here because this
+       is called *extremely* often, for every screen update and the same
+       string comparisons would be repeated, thus contributing toward
+       performance degradation. If it is essential that string comparisons
+       are needed for a particular condition, consider adding a caching
+       mechanism to limit the string comparisons to the first occurrence
+       for that cache lifetime. There is caching of that nature done for
+       unconsc (1) and parlyz (2)  because the suggested way of being able
+       to distinguish unconsc, parlyz, sleeping, and busy involves multiple
+       string comparisons. There is also caching done for submerged (3) to
+       avoid repeatedly calling the on_level() function unnecessarily. */
+
+#define test_if_enabled(c) if (condtests[(c)].enabled) condtests[(c)].test
+
+    condtests[bl_blind].test     = (Blind);
+    condtests[bl_conf].test      = (Confusion) ? TRUE : FALSE;
+    condtests[bl_deaf].test      = (Deaf);
+    condtests[bl_fly].test       = (Flying);
+    condtests[bl_foodpois].test  = (Sick && (u.usick_type & SICK_VOMITABLE) != 0);
+    condtests[bl_glowhands].test = (u.umconf);
+    condtests[bl_grab].test      = (u.ustuck && u.ustuck->data->mlet == S_EEL);
+    condtests[bl_hallu].test     = (Hallucination);
+    condtests[bl_inlava].test    = (u.utrap && u.utraptype == TT_LAVA);
+    condtests[bl_lev].test       = (Levitation);
+    condtests[bl_ride].test      = (u.usteed) ? TRUE : FALSE;
+    condtests[bl_slime].test     = (Slimed) ? TRUE : FALSE;
+    condtests[bl_stone].test     = (Stoned) ? TRUE : FALSE;
+    condtests[bl_strngl].test    = (Strangled) ? TRUE : FALSE;
+    condtests[bl_stun].test      = (Stunned) ? TRUE : FALSE;
+    condtests[bl_termill].test   = (Sick && (u.usick_type & SICK_NONVOMITABLE) != 0);
+    test_if_enabled(bl_elf_iron) = (FALSE);
+    test_if_enabled(bl_bareh)    = (!uarmg && !uwep);
+    test_if_enabled(bl_held)     = (u.ustuck && !condtests[bl_grab].test);
+    test_if_enabled(bl_icy)      = levl[u.ux][u.uy].typ == ICE;
+    test_if_enabled(bl_slippery) = (Glib) ? TRUE : FALSE;
+    test_if_enabled(bl_trapped)  = (u.utrap && u.utraptype != TT_BURIEDBALL
+                                            && u.utraptype != TT_LAVA);
+    test_if_enabled(bl_tethered) = (u.utrap && u.utraptype == TT_BURIEDBALL);
+    test_if_enabled(bl_woundedl) = (Wounded_legs);
+
+    cond_cache_prep();
+
+    if (condtests[bl_unconsc].enabled) {
+        if (cache_nomovemsg && !cache_avail[0]) {
+            cache_reslt[0] = unconscious();
+            cache_avail[0] = TRUE;
+        }
+    }
+    if (condtests[bl_parlyz].enabled) {
+        if (cache_multi_reason && !cache_avail[1]) {
+            cache_reslt[1] = (!strncmp(cache_multi_reason, "paralyzed", 9)
+                              || !strncmp(cache_multi_reason, "frozen", 6));
+            cache_avail[1] = TRUE;
+        }
+    }
+
+    /* unconsc */
+    if (cache_avail[0] && condtests[bl_unconsc].enabled) {
+        condtests[bl_unconsc].test = cache_reslt[0];
+    } else {
+        condtests[bl_unconsc].test = FALSE;
+    }
+    /* parlyz */
+    if (cache_avail[1] && condtests[bl_parlyz].enabled
+                       && !condtests[bl_unconsc].test) {
+        condtests[bl_parlyz].test = cache_reslt[1];
+    } else {
+        condtests[bl_parlyz].test = FALSE;
+    }
+    /* sleeping */
+    if (!condtests[bl_unconsc].test && !condtests[bl_parlyz].test) {
+        condtests[bl_sleeping].test = u.usleep ? TRUE : FALSE;
+    } else {
+        condtests[bl_sleeping].test = FALSE;
+    }
+    /* busy */
+    if (!condtests[bl_unconsc].test && !condtests[bl_parlyz].test
+                                    && !condtests[bl_sleeping].test) {
+        condtests[bl_busy].test = (g.multi < 0);
+    } else {
+        condtests[bl_busy].test = FALSE;
+    }
+
+    /* submerged */
+    if (condtests[bl_submerged].enabled) {
+        if (!cache_avail[2] && cache_underwater == 0
+            && (cache_uz.dlevel == 0 && cache_uz.dnum == 0)) {
+            cache_uz = u.uz;
+            cache_underwater = (Underwater) ? TRUE : FALSE;
+            cache_reslt[2] = (Underwater && !Is_waterlevel(&u.uz));
+            cache_avail[2] = TRUE;
+        }
+        if (cache_avail[2]) {
+            condtests[bl_submerged].test = cache_reslt[2];
+        } else {
+            condtests[bl_submerged].test = FALSE;
+        }
+    }
+
+#define cond_bitset(c) \
+        g.blstats[idx][BL_CONDITION].a.a_ulong |= conditions[(c)].mask;
+
+    for (i = 0; i < CONDITION_COUNT; ++i) {
+        if (condtests[i].enabled && condtests[i].test)
+            cond_bitset(i);
+    }
     evaluate_and_notify_windowport(g.valset, idx);
 }
 
 /* update just the status lines' 'time' field */
 static void
 stat_update_time()
@@ -1368,6 +1557,28 @@ int idx;
     return (const char *) 0;
 }
 
+/* deal with player's choice to change processing of a condition */
+void
+condopt(addr, negated)
+boolean *addr;
+boolean negated;
+{
+    int i;
+
+    for (i = 0; i < CONDITION_COUNT; ++i) {
+        if (!addr) {
+             /* special: indicates a request to init so
+                set the choice values to match the defaults */
+            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;
+    }
+}
+
 #ifdef STATUS_HILITES
 
 /****************************************************************************/
@@ -2269,22 +2480,6 @@ boolean from_configfile;
 }
 #endif /* STATUS_HILITES */
 
-const struct condmap valid_conditions[] = {
-    { "stone",    BL_MASK_STONE },
-    { "slime",    BL_MASK_SLIME },
-    { "strngl",   BL_MASK_STRNGL },
-    { "foodPois", BL_MASK_FOODPOIS },
-    { "termIll",  BL_MASK_TERMILL },
-    { "blind",    BL_MASK_BLIND },
-    { "deaf",     BL_MASK_DEAF },
-    { "stun",     BL_MASK_STUN },
-    { "conf",     BL_MASK_CONF },
-    { "hallu",    BL_MASK_HALLU },
-    { "lev",      BL_MASK_LEV },
-    { "fly",      BL_MASK_FLY },
-    { "ride",     BL_MASK_RIDE },
-};
-
 #ifdef STATUS_HILITES
 
 const struct condmap condition_aliases[] = {
@@ -2293,12 +2488,14 @@ const struct condmap condition_aliases[] = {
                         | BL_MASK_FOODPOIS | BL_MASK_TERMILL
                         | BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN
                         | BL_MASK_CONF | BL_MASK_HALLU
-                        | BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE },
+                        | BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE
+                        | BL_MASK_ELF_IRON },
     { "major_troubles", BL_MASK_STONE | BL_MASK_SLIME | BL_MASK_STRNGL
                         | BL_MASK_FOODPOIS | BL_MASK_TERMILL },
     { "minor_troubles", BL_MASK_BLIND | BL_MASK_DEAF | BL_MASK_STUN
                         | BL_MASK_CONF | BL_MASK_HALLU },
-    { "movement",       BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE }
+    { "movement",       BL_MASK_LEV | BL_MASK_FLY | BL_MASK_RIDE },
+    { "moreconditions",    BL_MASK_ELF_IRON },
 };
 
 unsigned long
@@ -2313,11 +2510,11 @@ query_conditions()
     tmpwin = create_nhwindow(NHW_MENU);
     start_menu(tmpwin);
 
-    for (i = 0; i < SIZE(valid_conditions); i++) {
+    for (i = 0; i < SIZE(conditions); i++) {
         any = cg.zeroany;
-        any.a_ulong = valid_conditions[i].bitmask;
+        any.a_ulong = conditions[i].mask;
         add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
-                 valid_conditions[i].id, MENU_ITEMFLAGS_NONE);
+                 conditions[i].text[0], MENU_ITEMFLAGS_NONE);
     }
 
     end_menu(tmpwin, "Choose status conditions");
@@ -2350,10 +2547,10 @@ unsigned long ul;
         if (condition_aliases[i].bitmask == ul)
             alias = condition_aliases[i].id;
 
-    for (i = 0; i < SIZE(valid_conditions); i++)
-        if ((valid_conditions[i].bitmask & ul) != 0UL) {
+    for (i = 0; i < SIZE(conditions); i++)
+        if ((conditions[i].mask & ul) != 0UL) {
             Sprintf(eos(buf), "%s%s", (first) ? "" : "+",
-                    valid_conditions[i].id);
+                    conditions[i].text[0]);
             first = FALSE;
         }
 
@@ -2372,9 +2569,9 @@ const char *str;
 
     if (str && *str) {
         /* check matches to canonical names */
-        for (i = 0; i < SIZE(valid_conditions); i++)
-            if (fuzzymatch(valid_conditions[i].id, str, " -_", TRUE)) {
-                mask |= valid_conditions[i].bitmask;
+        for (i = 0; i < SIZE(conditions); i++)
+            if (fuzzymatch(conditions[i].text[0], str, " -_", TRUE)) {
+                mask |= conditions[i].mask;
                 nmatches++;
             }
 
@@ -2410,7 +2607,7 @@ char *str;
     char **subfields;
     int i, sf;
 
-    sf = splitsubfields(str, &subfields, SIZE(valid_conditions));
+    sf = splitsubfields(str, &subfields, SIZE(conditions));
 
     if (sf < 1)
         return 0UL;
@@ -2694,30 +2891,30 @@ status_hilite_linestr_gather_conditions()
     struct _cond_map {
         unsigned long bm;
         unsigned long clratr;
-    } cond_maps[SIZE(valid_conditions)];
+    } cond_maps[SIZE(conditions)];
 
     (void) memset(cond_maps, 0,
-                  SIZE(valid_conditions) * sizeof (struct _cond_map));
+                  SIZE(conditions) * sizeof (struct _cond_map));
 
-    for (i = 0; i < SIZE(valid_conditions); i++) {
+    for (i = 0; i < SIZE(conditions); i++) {
         int clr = NO_COLOR;
         int atr = HL_NONE;
         int j;
 
         for (j = 0; j < CLR_MAX; j++)
-            if (g.cond_hilites[j] & valid_conditions[i].bitmask) {
+            if (g.cond_hilites[j] & conditions[i].mask) {
                 clr = j;
                 break;
             }
-        if (g.cond_hilites[HL_ATTCLR_DIM] & valid_conditions[i].bitmask)
+        if (g.cond_hilites[HL_ATTCLR_DIM] & conditions[i].mask)
             atr |= HL_DIM;
-        if (g.cond_hilites[HL_ATTCLR_BOLD] & valid_conditions[i].bitmask)
+        if (g.cond_hilites[HL_ATTCLR_BOLD] & conditions[i].mask)
             atr |= HL_BOLD;
-        if (g.cond_hilites[HL_ATTCLR_BLINK] & valid_conditions[i].bitmask)
+        if (g.cond_hilites[HL_ATTCLR_BLINK] & conditions[i].mask)
             atr |= HL_BLINK;
-        if (g.cond_hilites[HL_ATTCLR_ULINE] & valid_conditions[i].bitmask)
+        if (g.cond_hilites[HL_ATTCLR_ULINE] & conditions[i].mask)
             atr |= HL_ULINE;
-        if (g.cond_hilites[HL_ATTCLR_INVERSE] & valid_conditions[i].bitmask)
+        if (g.cond_hilites[HL_ATTCLR_INVERSE] & conditions[i].mask)
             atr |= HL_INVERSE;
         if (atr != HL_NONE)
             atr &= ~HL_NONE;
@@ -2726,16 +2923,16 @@ status_hilite_linestr_gather_conditions()
             unsigned long ca = clr | (atr << 8);
             boolean added_condmap = FALSE;
 
-            for (j = 0; j < SIZE(valid_conditions); j++)
+            for (j = 0; j < SIZE(conditions); j++)
                 if (cond_maps[j].clratr == ca) {
-                    cond_maps[j].bm |= valid_conditions[i].bitmask;
+                    cond_maps[j].bm |= conditions[i].mask;
                     added_condmap = TRUE;
                     break;
                 }
             if (!added_condmap) {
-                for (j = 0; j < SIZE(valid_conditions); j++)
+                for (j = 0; j < SIZE(conditions); j++)
                     if (!cond_maps[j].bm) {
-                        cond_maps[j].bm = valid_conditions[i].bitmask;
+                        cond_maps[j].bm = conditions[i].mask;
                         cond_maps[j].clratr = ca;
                         break;
                     }
@@ -2743,7 +2940,7 @@ status_hilite_linestr_gather_conditions()
         }
     }
 
-    for (i = 0; i < SIZE(valid_conditions); i++)
+    for (i = 0; i < SIZE(conditions); i++)
         if (cond_maps[i].bm) {
             int clr = NO_COLOR, atr = HL_NONE;
 
index c95ce0731b01e65d0aa7c99b071c88eded77cfd8..9d51fe2ec638134172e5b4c82687ea7edf6c1640 100644 (file)
@@ -115,6 +115,35 @@ 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, FALSE, SET_IN_GAME },
+    { "cond_blind", &condtests[bl_blind].choice, FALSE, SET_IN_GAME },
+    { "cond_busy", &condtests[bl_busy].choice, FALSE, SET_IN_GAME },
+    { "cond_conf", &condtests[bl_conf].choice, FALSE, SET_IN_GAME },
+    { "cond_deaf", &condtests[bl_deaf].choice, FALSE, SET_IN_GAME },
+    { "cond_fly", &condtests[bl_fly].choice, FALSE, SET_IN_GAME },
+    { "cond_foodPois", &condtests[bl_foodpois].choice, FALSE, SET_IN_GAME },
+    { "cond_glowhands", &condtests[bl_glowhands].choice, FALSE, SET_IN_GAME },
+    { "cond_grab", &condtests[bl_grab].choice, FALSE, SET_IN_GAME },
+    { "cond_hallu", &condtests[bl_hallu].choice, FALSE, SET_IN_GAME },
+    { "cond_held", &condtests[bl_held].choice, FALSE, SET_IN_GAME },
+    { "cond_ice" , &condtests[bl_icy].choice, FALSE, SET_IN_GAME },
+    { "cond_iron", &condtests[bl_elf_iron].choice, FALSE, SET_IN_GAME },
+    { "cond_lava", &condtests[bl_inlava].choice, FALSE, SET_IN_GAME },
+    { "cond_lev", &condtests[bl_lev].choice, FALSE, SET_IN_GAME },
+    { "cond_unconscious", &condtests[bl_unconsc].choice, FALSE, SET_IN_GAME },
+    { "cond_paralyze", &condtests[bl_parlyz].choice, FALSE, SET_IN_GAME },
+    { "cond_ride", &condtests[bl_ride].choice, FALSE, SET_IN_GAME },
+    { "cond_sleep" , &condtests[bl_sleeping].choice, FALSE, SET_IN_GAME },
+    { "cond_slime", &condtests[bl_slime].choice, FALSE, SET_IN_GAME },
+    { "cond_slip", &condtests[bl_slippery].choice, FALSE, SET_IN_GAME },
+    { "cond_stone", &condtests[bl_stone].choice, FALSE, SET_IN_GAME },
+    { "cond_strngl", &condtests[bl_strngl].choice, FALSE, SET_IN_GAME },
+    { "cond_stun", &condtests[bl_stun].choice, FALSE, SET_IN_GAME },
+    { "cond_submerged" , &condtests[bl_submerged].choice, FALSE, SET_IN_GAME },
+    { "cond_termIll", &condtests[bl_termill].choice, FALSE, SET_IN_GAME },
+    { "cond_tethered", &condtests[bl_tethered].choice, FALSE, SET_IN_GAME },
+    { "cond_trap", &condtests[bl_trapped].choice, FALSE, SET_IN_GAME },
+    { "cond_woundedl", &condtests[bl_woundedl].choice, FALSE, 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)
@@ -703,7 +732,7 @@ initoptions_init()
         if (boolopt[i].addr)
             *(boolopt[i].addr) = boolopt[i].initvalue;
     }
-
+    condopt((boolean *) 0, 0);  /* make the choices match defaults */
 #ifdef SYSFLAGS
     Strcpy(sysflags.sysflagsid, "sysflags");
     sysflags.sysflagsid[9] = (char) sizeof (struct sysflag);
@@ -4089,6 +4118,9 @@ 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);
+            }
             /* only do processing below if setting with doset() */
             if (g.opt_initial)
                 return retval;
index a9b801da6d7c925686df818228a92807c8fa2881..e92e22c42be1286361f7c2f36fb1a4271cd8561d 100644 (file)
@@ -972,9 +972,9 @@ curs_HPbar(char *text, /* pre-padded with trailing spaces if short */
     waddch(win, ']');
 }
 
-/* valid_conditions[] is used primarily for parsing hilite_status rules, but
+/* conditions[] is used primarily for parsing hilite_status rules, but
    we can use it for condition names and mask bits, avoiding duplication */
-extern const struct condmap valid_conditions[]; /* botl.c */
+extern const struct conditions_t conditions[]; /* botl.c */
 
 static void
 curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
@@ -996,9 +996,9 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
         if (nohilite)
             *nohilite = TRUE; /* assume ok */
         for (i = 0; i < BL_MASK_BITS; ++i) {
-            bitmsk = valid_conditions[i].bitmask;
+            bitmsk = conditions[i].mask;
             if (curses_condition_bits & bitmsk) {
-                Strcpy(condnam, valid_conditions[i].id);
+                Strcpy(condnam, conditions[i].text[0]);
                 Strcat(strcat(condbuf, " "), upstart(condnam));
 #ifdef STATUS_HILITES
                 if (nohilite && *nohilite
@@ -1024,9 +1024,9 @@ curs_stat_conds(int vert_cond, /* 0 => horizontal, 1 => vertical */
         cond_bits = curses_condition_bits;
         /* show active conditions directly; for vertical, three per line */
         for (i = 0; i < BL_MASK_BITS; ++i) {
-            bitmsk = valid_conditions[i].bitmask;
+            bitmsk = conditions[i].mask;
             if (cond_bits & bitmsk) {
-                Strcpy(condnam, valid_conditions[i].id);
+                Strcpy(condnam, conditions[i].text[0]);
                 cndlen = 1 + (int) strlen(condnam); /* count leading space */
                 if (!do_vert) {
                     getyx(win, cy, cx);
index b251057c1e08e86d7468ca5df7eeecca58178252..2fbf28de79fc5db93d9e8c169e6d81e5e01fd5fe 100644 (file)
@@ -3691,25 +3691,8 @@ static unsigned long *tty_colormasks;
 static long tty_condition_bits;
 static struct tty_status_fields tty_status[2][MAXBLSTATS]; /* 2: NOW,BEFORE */
 static int hpbar_percent, hpbar_color;
-static struct condition_t {
-    long mask;
-    const char *text[3]; /* 3: potential display vals, progressively shorter */
-} conditions[] = {
-    /* The sequence order of these matters */
-    { BL_MASK_STONE,    { "Stone",    "Ston",  "Sto" } },
-    { BL_MASK_SLIME,    { "Slime",    "Slim",  "Slm" } },
-    { BL_MASK_STRNGL,   { "Strngl",   "Stngl", "Str" } },
-    { BL_MASK_FOODPOIS, { "FoodPois", "Fpois", "Poi" } },
-    { BL_MASK_TERMILL,  { "TermIll" , "Ill",   "Ill" } },
-    { BL_MASK_BLIND,    { "Blind",    "Blnd",  "Bl"  } },
-    { BL_MASK_DEAF,     { "Deaf",     "Def",   "Df"  } },
-    { BL_MASK_STUN,     { "Stun",     "Stun",  "St"  } },
-    { BL_MASK_CONF,     { "Conf",     "Cnf",   "Cf"  } },
-    { BL_MASK_HALLU,    { "Hallu",    "Hal",   "Hl"  } },
-    { BL_MASK_LEV,      { "Lev",      "Lev",   "Lv"  } },
-    { BL_MASK_FLY,      { "Fly",      "Fly",   "Fl"  } },
-    { BL_MASK_RIDE,     { "Ride",     "Rid",   "Rd"  } },
-};
+extern const struct conditions_t conditions[CONDITION_COUNT];
+
 static const char *encvals[3][6] = {
     { "", "Burdened", "Stressed", "Strained", "Overtaxed", "Overloaded" },
     { "", "Burden",   "Stress",   "Strain",   "Overtax",   "Overload"   },
@@ -3833,19 +3816,36 @@ boolean enable;
  *      -- ptr is usually a "char *", unless fldindex is BL_CONDITION.
  *         If fldindex is BL_CONDITION, then ptr is a long value with
  *         any or none of the following bits set (from botl.h):
- *              BL_MASK_STONE           0x00000001L
- *              BL_MASK_SLIME           0x00000002L
- *              BL_MASK_STRNGL          0x00000004L
- *              BL_MASK_FOODPOIS        0x00000008L
- *              BL_MASK_TERMILL         0x00000010L
- *              BL_MASK_BLIND           0x00000020L
- *              BL_MASK_DEAF            0x00000040L
- *              BL_MASK_STUN            0x00000080L
- *              BL_MASK_CONF            0x00000100L
- *              BL_MASK_HALLU           0x00000200L
- *              BL_MASK_LEV             0x00000400L
- *              BL_MASK_FLY             0x00000800L
- *              BL_MASK_RIDE            0x00001000L
+ *               BL_MASK_BAREH        0x00000001L
+ *               BL_MASK_BLIND        0x00000002L
+ *               BL_MASK_BUSY         0x00000004L
+ *               BL_MASK_CONF         0x00000008L
+ *               BL_MASK_DEAF         0x00000010L
+ *               BL_MASK_ELF_IRON     0x00000020L
+ *               BL_MASK_FLY          0x00000040L
+ *               BL_MASK_FOODPOIS     0x00000080L
+ *               BL_MASK_GLOWHANDS    0x00000100L
+ *               BL_MASK_GRAB         0x00000200L
+ *               BL_MASK_HALLU        0x00000400L
+ *               BL_MASK_HELD         0x00000800L
+ *               BL_MASK_ICY          0x00001000L
+ *               BL_MASK_INLAVA       0x00002000L
+ *               BL_MASK_LEV          0x00004000L
+ *               BL_MASK_PARLYZ       0x00008000L
+ *               BL_MASK_RIDE         0x00010000L
+ *               BL_MASK_SLEEPING     0x00020000L
+ *               BL_MASK_SLIME        0x00040000L
+ *               BL_MASK_SLIPPERY     0x00080000L
+ *               BL_MASK_STONE        0x00100000L
+ *               BL_MASK_STRNGL       0x00200000L
+ *               BL_MASK_STUN         0x00400000L
+ *               BL_MASK_SUBMERGED    0x00800000L
+ *               BL_MASK_TERMILL      0x01000000L
+ *               BL_MASK_TETHERED     0x02000000L
+ *               BL_MASK_TRAPPED      0x04000000L
+ *               BL_MASK_UNCONSC      0x08000000L
+ *               BL_MASK_WOUNDEDL     0x10000000L
+ *
  *      -- The value passed for BL_GOLD usually includes an encoded leading
  *         symbol for GOLD "\GXXXXNNNN:nnn". If the window port needs to use
  *         the textual gold amount without the leading "$:" the port will