From: nhmall Date: Sat, 8 Feb 2020 06:03:25 +0000 (-0500) Subject: expand the pool of status condition fields X-Git-Tag: NetHack-3.7.0_WIP-2020-02-14~54^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=07a9a67fb2bab7569c70a9f9e66b8aedf0d70646;p=nethack expand the pool of status condition fields 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 --- diff --git a/doc/window.doc b/doc/window.doc index 46b00ad90..2ff17f114 100644 --- a/doc/window.doc +++ b/doc/window.doc @@ -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 diff --git a/include/botl.h b/include/botl.h index d3225153a..708cfa8a3 100644 --- a/include/botl.h +++ b/include/botl.h @@ -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: diff --git a/include/extern.h b/include/extern.h index c19f8df64..fb493078c 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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); diff --git a/src/botl.c b/src/botl.c index a9e9a9bcc..bee41e409 100644 --- a/src/botl.c +++ b/src/botl.c @@ -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; diff --git a/src/options.c b/src/options.c index c95ce0731..9d51fe2ec 100644 --- a/src/options.c +++ b/src/options.c @@ -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; diff --git a/win/curses/cursstat.c b/win/curses/cursstat.c index a9b801da6..e92e22c42 100644 --- a/win/curses/cursstat.c +++ b/win/curses/cursstat.c @@ -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); diff --git a/win/tty/wintty.c b/win/tty/wintty.c index b251057c1..2fbf28de7 100644 --- a/win/tty/wintty.c +++ b/win/tty/wintty.c @@ -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