bogus status updates
I finally figured out why status gets updated periodically even if
none of the fields have changed. Once a temporary highlight times
out, it starts a cycle of timeouts every 'statushilites' turns. When
I worked on this before, it was convoluted but not this convoluted.
In moveloop, if 'context.botl' call bot; in bot
call evaluate_and_notify_windowport;
for each field, call evaluate_and_notify_windowport_field:
call hilite_reset_needed and set 'reset' to the result;
if 'reset' is True then do status_update
and set 'curr->chg' and 'prev->chg' to True.
Then in moveloop call status_eval_next_unhilite:
for each field
if 'curr->chg' set 'curr->time' to moves+hilite_delta;
on the call after hilite_delta ('statushilites') moves,
call hilite_reset_needed which returns True if there is any
rule for temporary highlight and set 'context.botl'.
Go back to start. If multiple fields had temporary timeouts and
they were activated on different turns so expired on different turns
you could conceivably end up with context.botl being set every turn.
My first writeup trying to explain all this was wrong. I won't
testify about the accuracy of this one in court....
This extends the highlighting data structure to track the current
rule that's in use. And for that to make sense, it eliminates the
merging of settings from multiple matching rules. So anybody with
hit-points/up/inverse
hit-points/up/green
hit-points/up/bold
will need to manually merge their rules like
hit-points/up/green&inverse+bold
or else whichever rule matches last will be the only one in effect.
There are a lot of miscellaneous changes made as I flailed about.
The three most significant ones are that there is no guesswork over
what kind of highlight rule is in effect, status_eval_next_unhilite
will only set a timeout value if the current rule is for a temporary
highlight, and hilite_reset_needed will only return True if a timeout
is for a temporary highlight (probably moot after the _next_unhilite
change).
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.290 $ $NHDT-Date: 1553904170 2019/03/30 00:02:50 $
|
||||
$NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.291 $ $NHDT-Date: 1554017610 2019/03/31 07:33:30 $
|
||||
|
||||
This fixes36.2 file is here to capture information about updates in the 3.6.x
|
||||
lineage following the release of 3.6.1 in April 2018. Please note, however,
|
||||
@@ -403,6 +403,9 @@ Valkyrie quest was supposed to have a 50:50 chance that northern drawbridge
|
||||
lowered: 3/8, S down+N up: 3/8, N down+S up: 1/8, both raised: 1/8
|
||||
shorten the getpos prompt for teleport destination so that it won't yield a
|
||||
--More-- prompt for the help hint (--More-- still possible when riding)
|
||||
once a status highlight for a temporary rule ('up', 'down', 'changed') timed
|
||||
out, further spurious status updates (evaluating all fields) would
|
||||
occur every 'statushilites' turns even if no fields had changed
|
||||
|
||||
|
||||
Fixes to Post-3.6.1 Problems that Were Exposed Via git Repository
|
||||
|
||||
327
src/botl.c
327
src/botl.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 botl.c $NHDT-Date: 1553993169 2019/03/31 00:46:09 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.138 $ */
|
||||
/* NetHack 3.6 botl.c $NHDT-Date: 1554017610 2019/03/31 07:33:30 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.139 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Michael Allison, 2006. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -399,6 +399,8 @@ char *buf;
|
||||
|
||||
/* structure that tracks the status details in the core */
|
||||
|
||||
#define MAXVALWIDTH 80 /* actually less, but was using 80 to allocate title
|
||||
* and leveldesc then using QBUFSZ everywhere else */
|
||||
#ifdef STATUS_HILITES
|
||||
struct hilite_s {
|
||||
enum statusfields fld;
|
||||
@@ -406,7 +408,7 @@ struct hilite_s {
|
||||
unsigned anytype;
|
||||
anything value;
|
||||
int behavior;
|
||||
char textmatch[QBUFSZ];
|
||||
char textmatch[MAXVALWIDTH];
|
||||
enum relationships rel;
|
||||
int coloridx;
|
||||
struct hilite_s *next;
|
||||
@@ -425,30 +427,29 @@ struct istat_s {
|
||||
enum statusfields idxmax;
|
||||
enum statusfields fld;
|
||||
#ifdef STATUS_HILITES
|
||||
struct hilite_s *hilite_rule; /* the entry, if any, in 'thresholds'
|
||||
* list that currently applies */
|
||||
struct hilite_s *thresholds;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
STATIC_DCL void NDECL(init_blstats);
|
||||
STATIC_DCL char *FDECL(anything_to_s, (char *, anything *, int));
|
||||
STATIC_OVL int FDECL(percentage, (struct istat_s *, struct istat_s *));
|
||||
STATIC_OVL int FDECL(compare_blstats, (struct istat_s *, struct istat_s *));
|
||||
STATIC_DCL boolean FDECL(evaluate_and_notify_windowport_field,
|
||||
(int, boolean *, int, int));
|
||||
STATIC_DCL void FDECL(evaluate_and_notify_windowport, (boolean *, int, int));
|
||||
STATIC_DCL boolean FDECL(eval_notify_windowport_field, (int, boolean *, int));
|
||||
STATIC_DCL void FDECL(evaluate_and_notify_windowport, (boolean *, int));
|
||||
|
||||
#ifdef STATUS_HILITES
|
||||
STATIC_DCL boolean FDECL(hilite_reset_needed, (struct istat_s *, long));
|
||||
STATIC_DCL void FDECL(s_to_anything, (anything *, char *, int));
|
||||
STATIC_DCL boolean FDECL(is_ltgt_percentnumber, (const char *));
|
||||
STATIC_DCL boolean FDECL(has_ltgt_percentnumber, (const char *));
|
||||
STATIC_DCL boolean FDECL(parse_status_hl2, (char (*)[QBUFSZ],BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(parse_status_hl2, (char (*)[QBUFSZ], BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(parse_condition, (char (*)[QBUFSZ], int));
|
||||
STATIC_DCL boolean FDECL(noneoftheabove, (const char *));
|
||||
STATIC_DCL void FDECL(merge_bestcolor, (int *, int));
|
||||
STATIC_DCL void FDECL(get_hilite_color, (int, int, genericptr_t, int,
|
||||
int, int *));
|
||||
STATIC_DCL struct hilite_s *FDECL(get_hilite, (int, int, genericptr_t,
|
||||
int, int, int *));
|
||||
STATIC_DCL unsigned long FDECL(match_str2conditionbitmask, (const char *));
|
||||
STATIC_DCL unsigned long FDECL(str2conditionbitmask, (char *));
|
||||
STATIC_DCL void FDECL(split_clridx, (int, int *, int *));
|
||||
@@ -466,18 +467,25 @@ STATIC_DCL int FDECL(status_hilite_menu_choose_updownboth, (int, const char *,
|
||||
BOOLEAN_P, BOOLEAN_P));
|
||||
STATIC_DCL boolean FDECL(status_hilite_menu_add, (int));
|
||||
#define has_hilite(i) (blstats[0][(i)].thresholds)
|
||||
/* TH_UPDOWN encompasses specific 'up' and 'down' also general 'changed' */
|
||||
#define Is_Temp_Hilite(rule) ((rule) && (rule)->behavior == BL_TH_UPDOWN)
|
||||
|
||||
/* pointers to current hilite rule and list of this field's defined rules */
|
||||
#define INIT_THRESH , (struct hilite_s *) 0, (struct hilite_s *) 0
|
||||
#else /* !STATUS_HILITES */
|
||||
#define INIT_THRESH /*empty*/
|
||||
#endif
|
||||
|
||||
#define INIT_BLSTAT(name, fmtstr, anytyp, wid, fld) \
|
||||
{ name, fmtstr, 0L, FALSE, anytyp, { (genericptr_t) 0 }, (char *) 0, \
|
||||
wid, -1, fld }
|
||||
wid, -1, fld INIT_THRESH }
|
||||
#define INIT_BLSTATP(name, fmtstr, anytyp, wid, maxfld, fld) \
|
||||
{ name, fmtstr, 0L, FALSE, anytyp, { (genericptr_t) 0 }, (char *) 0, \
|
||||
wid, maxfld, fld }
|
||||
wid, maxfld, fld INIT_THRESH }
|
||||
|
||||
/* If entries are added to this, botl.h will require updating too */
|
||||
STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = {
|
||||
INIT_BLSTAT("title", "%s", ANY_STR, 80, BL_TITLE),
|
||||
INIT_BLSTAT("title", "%s", ANY_STR, MAXVALWIDTH, BL_TITLE),
|
||||
INIT_BLSTAT("strength", " St:%s", ANY_INT, 10, BL_STR),
|
||||
INIT_BLSTAT("dexterity", " Dx:%s", ANY_INT, 10, BL_DX),
|
||||
INIT_BLSTAT("constitution", " Co:%s", ANY_INT, 10, BL_CO),
|
||||
@@ -498,18 +506,18 @@ STATIC_DCL struct istat_s initblstats[MAXBLSTATS] = {
|
||||
INIT_BLSTAT("hunger", " %s", ANY_INT, 40, BL_HUNGER),
|
||||
INIT_BLSTATP("hitpoints", " HP:%s", ANY_INT, 10, BL_HPMAX, BL_HP),
|
||||
INIT_BLSTAT("hitpoints-max", "(%s)", ANY_INT, 10, BL_HPMAX),
|
||||
INIT_BLSTAT("dungeon-level", "%s", ANY_STR, 80, BL_LEVELDESC),
|
||||
INIT_BLSTAT("dungeon-level", "%s", ANY_STR, MAXVALWIDTH, BL_LEVELDESC),
|
||||
INIT_BLSTAT("experience", "/%s", ANY_LONG, 20, BL_EXP),
|
||||
INIT_BLSTAT("condition", "%s", ANY_MASK32, 0, BL_CONDITION)
|
||||
};
|
||||
|
||||
#undef INIT_BLSTATP
|
||||
#undef INIT_BLSTAT
|
||||
#undef INIT_THRESH
|
||||
|
||||
struct istat_s blstats[2][MAXBLSTATS];
|
||||
static boolean blinit = FALSE, update_all = FALSE;
|
||||
static boolean valset[MAXBLSTATS];
|
||||
unsigned long blcolormasks[CLR_MAX];
|
||||
static long bl_hilite_moves = 0L;
|
||||
|
||||
/* we don't put this next declaration in #ifdef STATUS_HILITES.
|
||||
@@ -519,7 +527,7 @@ static long bl_hilite_moves = 0L;
|
||||
* the final argument of status_update, with or
|
||||
* without STATUS_HILITES.
|
||||
*/
|
||||
unsigned long cond_hilites[BL_ATTCLR_MAX];
|
||||
static unsigned long cond_hilites[BL_ATTCLR_MAX];
|
||||
|
||||
void
|
||||
bot_via_windowport()
|
||||
@@ -528,13 +536,13 @@ bot_via_windowport()
|
||||
char buf[BUFSZ];
|
||||
const char *titl;
|
||||
register char *nb;
|
||||
int i, idx_p, cap;
|
||||
int i, cap;
|
||||
long money;
|
||||
|
||||
if (!blinit)
|
||||
panic("bot before init.");
|
||||
|
||||
idx_p = idx;
|
||||
/* toggle from previous iteration */
|
||||
idx = 1 - idx; /* 0 -> 1, 1 -> 0 */
|
||||
|
||||
/* clear the "value set" indicators */
|
||||
@@ -699,12 +707,12 @@ bot_via_windowport()
|
||||
blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_FLY;
|
||||
if (u.usteed)
|
||||
blstats[idx][BL_CONDITION].a.a_ulong |= BL_MASK_RIDE;
|
||||
evaluate_and_notify_windowport(valset, idx, idx_p);
|
||||
evaluate_and_notify_windowport(valset, idx);
|
||||
}
|
||||
|
||||
STATIC_OVL boolean
|
||||
evaluate_and_notify_windowport_field(fld, valsetlist, idx, idx_p)
|
||||
int fld, idx, idx_p;
|
||||
eval_notify_windowport_field(fld, valsetlist, idx)
|
||||
int fld, idx;
|
||||
boolean *valsetlist;
|
||||
{
|
||||
static int oldrndencode = 0;
|
||||
@@ -720,7 +728,7 @@ boolean *valsetlist;
|
||||
*/
|
||||
anytype = blstats[idx][fld].anytype;
|
||||
curr = &blstats[idx][fld];
|
||||
prev = &blstats[idx_p][fld];
|
||||
prev = &blstats[1 - idx][fld];
|
||||
color = NO_COLOR;
|
||||
|
||||
chg = update_all ? 0 : compare_blstats(prev, curr);
|
||||
@@ -753,7 +761,7 @@ boolean *valsetlist;
|
||||
|
||||
reset = FALSE;
|
||||
#ifdef STATUS_HILITES
|
||||
if (!update_all && !chg) {
|
||||
if (!update_all && !chg && curr->time) {
|
||||
reset = hilite_reset_needed(prev, bl_hilite_moves);
|
||||
if (reset)
|
||||
curr->time = prev->time = 0L;
|
||||
@@ -769,9 +777,11 @@ boolean *valsetlist;
|
||||
|
||||
if (anytype != ANY_MASK32) {
|
||||
#ifdef STATUS_HILITES
|
||||
if ((chg || *curr->val)) {
|
||||
get_hilite_color(idx, fld, (genericptr_t) &curr->a,
|
||||
chg, pc, &color);
|
||||
if (chg || *curr->val) {
|
||||
curr->hilite_rule = get_hilite(idx, fld,
|
||||
(genericptr_t) &curr->a,
|
||||
chg, pc, &color);
|
||||
prev->hilite_rule = curr->hilite_rule;
|
||||
if (chg == 2) {
|
||||
color = NO_COLOR;
|
||||
chg = 0;
|
||||
@@ -779,11 +789,11 @@ boolean *valsetlist;
|
||||
}
|
||||
#endif /* STATUS_HILITES */
|
||||
status_update(fld, (genericptr_t) curr->val,
|
||||
chg, pc, color, &cond_hilites[0]);
|
||||
chg, pc, color, (unsigned long *) 0);
|
||||
} else {
|
||||
/* Color for conditions is done through cond_hilites[] */
|
||||
status_update(fld, (genericptr_t) &curr->a.a_ulong, chg, pc,
|
||||
color, &cond_hilites[0]);
|
||||
status_update(fld, (genericptr_t) &curr->a.a_ulong,
|
||||
chg, pc, color, cond_hilites);
|
||||
}
|
||||
curr->chg = prev->chg = TRUE;
|
||||
updated = TRUE;
|
||||
@@ -792,8 +802,8 @@ boolean *valsetlist;
|
||||
}
|
||||
|
||||
static void
|
||||
evaluate_and_notify_windowport(valsetlist, idx, idx_p)
|
||||
int idx, idx_p;
|
||||
evaluate_and_notify_windowport(valsetlist, idx)
|
||||
int idx;
|
||||
boolean *valsetlist;
|
||||
{
|
||||
int i, updated = 0, notpresent = 0;
|
||||
@@ -810,7 +820,7 @@ boolean *valsetlist;
|
||||
notpresent++;
|
||||
continue;
|
||||
}
|
||||
if (evaluate_and_notify_windowport_field(i, valsetlist, idx, idx_p))
|
||||
if (eval_notify_windowport_field(i, valsetlist, idx))
|
||||
updated++;
|
||||
}
|
||||
/*
|
||||
@@ -838,13 +848,13 @@ boolean *valsetlist;
|
||||
*/
|
||||
if (context.botlx && (windowprocs.wincap2 & WC2_RESET_STATUS) != 0L)
|
||||
status_update(BL_RESET, (genericptr_t) 0, 0, 0,
|
||||
NO_COLOR, &cond_hilites[0]);
|
||||
NO_COLOR, (unsigned long *) 0);
|
||||
else if ((updated || context.botlx) &&
|
||||
(windowprocs.wincap2 & WC2_FLUSH_STATUS) != 0L)
|
||||
status_update(BL_FLUSH, (genericptr_t) 0, 0, 0,
|
||||
NO_COLOR, &cond_hilites[0]);
|
||||
NO_COLOR, (unsigned long *) 0);
|
||||
|
||||
context.botl = context.botlx = 0;
|
||||
context.botl = context.botlx = FALSE;
|
||||
update_all = FALSE;
|
||||
}
|
||||
|
||||
@@ -852,11 +862,12 @@ void
|
||||
status_eval_next_unhilite()
|
||||
{
|
||||
int i;
|
||||
struct istat_s *curr = NULL;
|
||||
struct istat_s *curr;
|
||||
long next_unhilite, this_unhilite;
|
||||
|
||||
bl_hilite_moves = moves;
|
||||
/* figure out when the next unhilight needs to be performed */
|
||||
bl_hilite_moves = moves; /* simpllfied; used to try to encode fractional
|
||||
* amounts for multiple moves within same turn */
|
||||
/* figure out whether an unhilight needs to be performed now */
|
||||
next_unhilite = 0L;
|
||||
for (i = 0; i < MAXBLSTATS; ++i) {
|
||||
curr = &blstats[0][i]; /* blstats[0][*].time == blstats[1][*].time */
|
||||
@@ -865,10 +876,17 @@ status_eval_next_unhilite()
|
||||
struct istat_s *prev = &blstats[1][i];
|
||||
|
||||
#ifdef STATUS_HILITES
|
||||
curr->time = prev->time = (bl_hilite_moves + iflags.hilite_delta);
|
||||
if (Is_Temp_Hilite(curr->hilite_rule))
|
||||
curr->time = prev->time = (bl_hilite_moves
|
||||
+ iflags.hilite_delta);
|
||||
else
|
||||
curr->time = prev->time = 0L;
|
||||
#endif
|
||||
curr->chg = prev->chg = FALSE;
|
||||
context.botl = TRUE;
|
||||
}
|
||||
if (context.botl)
|
||||
continue; /* just process other blstats[][].time and .chg */
|
||||
|
||||
this_unhilite = curr->time;
|
||||
if (this_unhilite > 0L
|
||||
@@ -876,21 +894,22 @@ status_eval_next_unhilite()
|
||||
#ifdef STATUS_HILITES
|
||||
&& hilite_reset_needed(curr, this_unhilite + 1L)
|
||||
#endif
|
||||
)
|
||||
) {
|
||||
next_unhilite = this_unhilite;
|
||||
if (next_unhilite < bl_hilite_moves)
|
||||
context.botl = TRUE;
|
||||
}
|
||||
}
|
||||
if (next_unhilite > 0L && next_unhilite < bl_hilite_moves)
|
||||
context.botl = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
status_initialize(reassessment)
|
||||
boolean
|
||||
reassessment; /* TRUE = just reassess fields w/o other initialization*/
|
||||
boolean reassessment; /* TRUE: just recheck fields w/o other initialization */
|
||||
{
|
||||
enum statusfields fld;
|
||||
boolean fldenabl;
|
||||
int i;
|
||||
const char *fieldfmt = (const char *) 0;
|
||||
const char *fieldname = (const char *) 0;
|
||||
const char *fieldfmt, *fieldname;
|
||||
|
||||
if (!reassessment) {
|
||||
if (blinit)
|
||||
@@ -898,22 +917,22 @@ boolean
|
||||
init_blstats();
|
||||
(*windowprocs.win_status_init)();
|
||||
blinit = TRUE;
|
||||
} else if (!blinit) {
|
||||
panic("status 'reassess' before init");
|
||||
}
|
||||
for (i = 0; i < MAXBLSTATS; ++i) {
|
||||
enum statusfields fld = initblstats[i].fld;
|
||||
boolean fldenabled = (fld == BL_SCORE) ? flags.showscore
|
||||
: (fld == BL_XP) ? (boolean) !Upolyd
|
||||
: (fld == BL_HD) ? (boolean) Upolyd
|
||||
: (fld == BL_TIME) ? flags.time
|
||||
: (fld == BL_EXP) ? (boolean) (flags.showexp && !Upolyd)
|
||||
: TRUE;
|
||||
fld = initblstats[i].fld;
|
||||
fldenabl = (fld == BL_SCORE) ? flags.showscore
|
||||
: (fld == BL_TIME) ? flags.time
|
||||
: (fld == BL_EXP) ? (boolean) (flags.showexp && !Upolyd)
|
||||
: (fld == BL_XP) ? (boolean) !Upolyd
|
||||
: (fld == BL_HD) ? (boolean) Upolyd
|
||||
: TRUE;
|
||||
|
||||
fieldname = initblstats[i].fldname;
|
||||
if (fld == BL_TITLE && iflags.wc2_hitpointbar)
|
||||
fieldfmt = "%-30s";
|
||||
else
|
||||
fieldfmt = initblstats[i].fldfmt;
|
||||
status_enablefield(fld, fieldname, fieldfmt, fldenabled);
|
||||
fieldfmt = (fld == BL_TITLE && iflags.wc2_hitpointbar) ? "%-30.30s"
|
||||
: initblstats[i].fldfmt;
|
||||
status_enablefield(fld, fieldname, fieldfmt, fldenabl);
|
||||
}
|
||||
update_all = TRUE;
|
||||
}
|
||||
@@ -934,14 +953,17 @@ status_finish()
|
||||
if (blstats[1][i].val)
|
||||
free((genericptr_t) blstats[1][i].val), blstats[1][i].val = 0;
|
||||
#ifdef STATUS_HILITES
|
||||
/* pointer to an entry in thresholds list; Null it out since
|
||||
that list is about to go away */
|
||||
blstats[0][i].hilite_rule = blstats[1][i].hilite_rule = 0;
|
||||
if (blstats[0][i].thresholds) {
|
||||
struct hilite_s *temp, *next = 0;
|
||||
struct hilite_s *temp, *next;
|
||||
|
||||
for (temp = blstats[0][i].thresholds; temp; temp = next) {
|
||||
next = temp->next;
|
||||
free((genericptr_t) temp);
|
||||
blstats[0][i].thresholds = blstats[1][i].thresholds = 0;
|
||||
}
|
||||
blstats[0][i].thresholds = blstats[1][i].thresholds = 0;
|
||||
}
|
||||
#endif /* STATUS_HILITES */
|
||||
}
|
||||
@@ -957,9 +979,7 @@ init_blstats()
|
||||
impossible("init_blstats called more than once.");
|
||||
return;
|
||||
}
|
||||
|
||||
initalready = TRUE;
|
||||
for (i = BEFORE; i <= NOW; ++i) {
|
||||
for (i = 0; i <= 1; ++i) {
|
||||
for (j = 0; j < MAXBLSTATS; ++j) {
|
||||
#ifdef STATUS_HILITES
|
||||
struct hilite_s *keep_hilite_chain = blstats[i][j].thresholds;
|
||||
@@ -977,6 +997,7 @@ init_blstats()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
initalready = TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1327,26 +1348,19 @@ hilite_reset_needed(bl_p, augmented_time)
|
||||
struct istat_s *bl_p;
|
||||
long augmented_time;
|
||||
{
|
||||
struct hilite_s *tl = bl_p->thresholds;
|
||||
|
||||
/*
|
||||
* This 'multi' handling may need some tuning...
|
||||
*/
|
||||
if (multi)
|
||||
return FALSE;
|
||||
|
||||
if (!Is_Temp_Hilite(bl_p->hilite_rule))
|
||||
return FALSE;
|
||||
|
||||
if (bl_p->time == 0 || bl_p->time >= augmented_time)
|
||||
return FALSE;
|
||||
|
||||
while (tl) {
|
||||
/* only this style times out (includes general 'changed'
|
||||
as well as specific 'up' and 'down') */
|
||||
if (tl->behavior == BL_TH_UPDOWN)
|
||||
return TRUE;
|
||||
tl = tl->next;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* called by options handling when 'statushilites' boolean is toggled */
|
||||
@@ -1377,33 +1391,13 @@ const char *hl_text;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
merge_bestcolor(bestcolor, newcolor)
|
||||
int *bestcolor;
|
||||
int newcolor;
|
||||
{
|
||||
int natr = HL_UNDEF, nclr = NO_COLOR;
|
||||
|
||||
split_clridx(newcolor, &nclr, &natr);
|
||||
|
||||
if (nclr != NO_COLOR)
|
||||
*bestcolor = (*bestcolor & 0xff00) | nclr;
|
||||
|
||||
if (natr != HL_UNDEF) {
|
||||
if (natr == HL_NONE)
|
||||
*bestcolor = *bestcolor & 0x00ff; /* reset all attributes */
|
||||
else
|
||||
*bestcolor |= (natr << 8); /* merge attributes */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* get_hilite_color
|
||||
* get_hilite
|
||||
*
|
||||
* Figures out, based on the value and the direction it is moving,
|
||||
* the color that the field should be displayed in.
|
||||
* Returns, based on the value and the direction it is moving,
|
||||
* the highlight rule that applies to the specified field.
|
||||
*
|
||||
* Provide get_hilite_color() with the following to work with:
|
||||
* Provide get_hilite() with the following to work with:
|
||||
* actual value vp
|
||||
* useful for BL_TH_VAL_ABSOLUTE
|
||||
* indicator of down, up, or the same (-1, 1, 0) chg
|
||||
@@ -1412,28 +1406,22 @@ int newcolor;
|
||||
* useful for BL_TH_VAL_PERCENTAGE
|
||||
*
|
||||
* Get back:
|
||||
* color based on user thresholds set in config file.
|
||||
* The rightmost 8 bits contain a color index.
|
||||
* The 8 bits to the left of that contain
|
||||
* the attribute bits.
|
||||
* color = 0x00FF
|
||||
* attrib= 0xFF00
|
||||
* pointer to rule that applies; Null if no rule does.
|
||||
*/
|
||||
STATIC_OVL void
|
||||
get_hilite_color(idx, fldidx, vp, chg, pc, colorptr)
|
||||
STATIC_OVL struct hilite_s *
|
||||
get_hilite(idx, fldidx, vp, chg, pc, colorptr)
|
||||
int idx, fldidx, chg, pc;
|
||||
genericptr_t vp;
|
||||
int *colorptr;
|
||||
{
|
||||
int bestcolor = NO_COLOR;
|
||||
struct hilite_s *hl;
|
||||
struct hilite_s *hl, *rule = 0;
|
||||
anything *value = (anything *) vp;
|
||||
char *txtstr;
|
||||
|
||||
if (!colorptr || fldidx < 0 || fldidx >= MAXBLSTATS)
|
||||
return;
|
||||
if (fldidx < 0 || fldidx >= MAXBLSTATS)
|
||||
return (struct hilite_s *) 0;
|
||||
|
||||
if (blstats[idx][fldidx].thresholds) {
|
||||
if (has_hilite(fldidx)) {
|
||||
int dt;
|
||||
/* there are hilites set here */
|
||||
int max_pc = -1, min_pc = 101;
|
||||
@@ -1447,7 +1435,7 @@ int *colorptr;
|
||||
perc_or_abs = FALSE;
|
||||
|
||||
/* min_/max_ are used to track best fit */
|
||||
for (hl = blstats[idx][fldidx].thresholds; hl; hl = hl->next) {
|
||||
for (hl = blstats[0][fldidx].thresholds; hl; hl = hl->next) {
|
||||
dt = initblstats[fldidx].anytype; /* only needed for 'absolute' */
|
||||
/* if we've already matched a temporary highlight, it takes
|
||||
precedence over all persistent ones; we still process
|
||||
@@ -1462,7 +1450,7 @@ int *colorptr;
|
||||
switch (hl->behavior) {
|
||||
case BL_TH_VAL_PERCENTAGE: /* percent values are always ANY_INT */
|
||||
if (hl->rel == EQ_VALUE && pc == hl->value.a_int) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_pc = max_pc = hl->value.a_int;
|
||||
exactmatch = perc_or_abs = TRUE;
|
||||
} else if (exactmatch) {
|
||||
@@ -1470,25 +1458,25 @@ int *colorptr;
|
||||
} else if (hl->rel == LT_VALUE
|
||||
&& (pc < hl->value.a_int)
|
||||
&& (hl->value.a_int <= min_pc)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_pc = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == LE_VALUE
|
||||
&& (pc <= hl->value.a_int)
|
||||
&& (hl->value.a_int <= min_pc)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_pc = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == GT_VALUE
|
||||
&& (pc > hl->value.a_int)
|
||||
&& (hl->value.a_int >= max_pc)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
max_pc = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == GE_VALUE
|
||||
&& (pc >= hl->value.a_int)
|
||||
&& (hl->value.a_int >= max_pc)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
max_pc = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
}
|
||||
@@ -1497,13 +1485,13 @@ int *colorptr;
|
||||
/* specific 'up' or 'down' takes precedence over general
|
||||
'changed' regardless of their order in the rule set */
|
||||
if (chg < 0 && hl->rel == LT_VALUE) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
updown = TRUE;
|
||||
} else if (chg > 0 && hl->rel == GT_VALUE) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
updown = TRUE;
|
||||
} else if (chg != 0 && hl->rel == EQ_VALUE && !updown) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
changed = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -1516,7 +1504,7 @@ int *colorptr;
|
||||
if (dt == ANY_INT) {
|
||||
if (hl->rel == EQ_VALUE
|
||||
&& hl->value.a_int == value->a_int) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_ival = max_ival = hl->value.a_int;
|
||||
exactmatch = perc_or_abs = TRUE;
|
||||
} else if (exactmatch) {
|
||||
@@ -1524,32 +1512,32 @@ int *colorptr;
|
||||
} else if (hl->rel == LT_VALUE
|
||||
&& (value->a_int < hl->value.a_int)
|
||||
&& (hl->value.a_int <= min_ival)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_ival = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == LE_VALUE
|
||||
&& (value->a_int <= hl->value.a_int)
|
||||
&& (hl->value.a_int <= min_ival)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_ival = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == GT_VALUE
|
||||
&& (value->a_int > hl->value.a_int)
|
||||
&& (hl->value.a_int >= max_ival)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
max_ival = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == GE_VALUE
|
||||
&& (value->a_int >= hl->value.a_int)
|
||||
&& (hl->value.a_int >= max_ival)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
max_ival = hl->value.a_int;
|
||||
perc_or_abs = TRUE;
|
||||
}
|
||||
} else { /* ANY_LONG */
|
||||
if (hl->rel == EQ_VALUE
|
||||
&& hl->value.a_long == value->a_long) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_lval = max_lval = hl->value.a_long;
|
||||
exactmatch = perc_or_abs = TRUE;
|
||||
} else if (exactmatch) {
|
||||
@@ -1557,25 +1545,25 @@ int *colorptr;
|
||||
} else if (hl->rel == LT_VALUE
|
||||
&& (value->a_long < hl->value.a_long)
|
||||
&& (hl->value.a_long <= min_lval)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_lval = hl->value.a_long;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == LE_VALUE
|
||||
&& (value->a_long <= hl->value.a_long)
|
||||
&& (hl->value.a_long <= min_lval)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
min_lval = hl->value.a_long;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == GT_VALUE
|
||||
&& (value->a_long > hl->value.a_long)
|
||||
&& (hl->value.a_long >= max_lval)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
max_lval = hl->value.a_long;
|
||||
perc_or_abs = TRUE;
|
||||
} else if (hl->rel == GE_VALUE
|
||||
&& (value->a_long >= hl->value.a_long)
|
||||
&& (hl->value.a_long >= max_lval)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
max_lval = hl->value.a_long;
|
||||
perc_or_abs = TRUE;
|
||||
}
|
||||
@@ -1588,18 +1576,18 @@ int *colorptr;
|
||||
txtstr += (strlen(plname) + sizeof " the " - sizeof "");
|
||||
if (hl->rel == TXT_VALUE && hl->textmatch[0]) {
|
||||
if (fuzzymatch(hl->textmatch, txtstr, "\" -_", TRUE)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
exactmatch = TRUE;
|
||||
} else if (exactmatch) {
|
||||
; /* already found best fit, skip "noneoftheabove" */
|
||||
} else if (fldidx == BL_TITLE
|
||||
&& Upolyd && noneoftheabove(hl->textmatch)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BL_TH_ALWAYS_HILITE:
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
rule = hl;
|
||||
break;
|
||||
case BL_TH_NONE:
|
||||
break;
|
||||
@@ -1608,8 +1596,8 @@ int *colorptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
*colorptr = bestcolor;
|
||||
return;
|
||||
*colorptr = rule ? rule->coloridx : NO_COLOR;
|
||||
return rule;
|
||||
}
|
||||
|
||||
STATIC_OVL void
|
||||
@@ -2119,9 +2107,9 @@ boolean from_configfile;
|
||||
|
||||
hilite.anytype = dt;
|
||||
|
||||
if (hilite.behavior == BL_TH_TEXTMATCH && txt
|
||||
&& strlen(txt) < QBUFSZ - 1) {
|
||||
Strcpy(hilite.textmatch, txt);
|
||||
if (hilite.behavior == BL_TH_TEXTMATCH && txt) {
|
||||
(void) strncpy(hilite.textmatch, txt, sizeof hilite.textmatch);
|
||||
hilite.textmatch[sizeof hilite.textmatch - 1] = '\0';
|
||||
(void) trimspaces(hilite.textmatch);
|
||||
}
|
||||
|
||||
@@ -2307,6 +2295,15 @@ int sidx;
|
||||
/*3.6.1:
|
||||
OPTION=hilite_status: condition/stone+slime+foodPois/red&inverse */
|
||||
|
||||
/*
|
||||
* TODO?
|
||||
* It would be simpler to treat each condition (also hunger state
|
||||
* and encumbrance level) as if it were a separate field. That
|
||||
* way they could have either or both 'changed' temporary rule and
|
||||
* 'always' persistent rule and wouldn't need convoluted access to
|
||||
* the intended color and attributes.
|
||||
*/
|
||||
|
||||
sidx++;
|
||||
while(s[sidx]) {
|
||||
int sf = 0; /* subfield count */
|
||||
@@ -2410,17 +2407,15 @@ clear_status_hilites()
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXBLSTATS; ++i) {
|
||||
if (blstats[0][i].thresholds) {
|
||||
struct hilite_s *temp = blstats[0][i].thresholds,
|
||||
*next = (struct hilite_s *)0;
|
||||
while (temp) {
|
||||
next = temp->next;
|
||||
free(temp);
|
||||
blstats[0][i].thresholds = (struct hilite_s *)0;
|
||||
blstats[1][i].thresholds = blstats[0][i].thresholds;
|
||||
temp = next;
|
||||
}
|
||||
struct hilite_s *temp, *next;
|
||||
|
||||
for (temp = blstats[0][i].thresholds; temp; temp = next) {
|
||||
next = temp->next;
|
||||
free(temp);
|
||||
}
|
||||
blstats[0][i].thresholds = blstats[1][i].thresholds = 0;
|
||||
/* pointer into thresholds list, now stale */
|
||||
blstats[0][i].hilite_rule = blstats[1][i].hilite_rule = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3200,7 +3195,7 @@ choose_value:
|
||||
Strcpy(hilite.textmatch, hutxt[rv]);
|
||||
} else if (fld == BL_TITLE) {
|
||||
const char *rolelist[3 * 9 + 1];
|
||||
char mbuf[QBUFSZ], fbuf[QBUFSZ], obuf[QBUFSZ];
|
||||
char mbuf[MAXVALWIDTH], fbuf[MAXVALWIDTH], obuf[MAXVALWIDTH];
|
||||
int i, j, rv;
|
||||
|
||||
for (i = j = 0; i < 9; i++) {
|
||||
@@ -3247,7 +3242,7 @@ choose_value:
|
||||
goto choose_behavior;
|
||||
|
||||
hilite.rel = TXT_VALUE;
|
||||
if (strlen(inbuf) < QBUFSZ - 1)
|
||||
if (strlen(inbuf) < sizeof hilite.textmatch)
|
||||
Strcpy(hilite.textmatch, inbuf);
|
||||
else
|
||||
return FALSE;
|
||||
@@ -3357,25 +3352,25 @@ int id;
|
||||
return TRUE;
|
||||
} else {
|
||||
int fld = hlstr->fld;
|
||||
struct hilite_s *hl = blstats[0][fld].thresholds;
|
||||
struct hilite_s *hlprev = (struct hilite_s *) 0;
|
||||
struct hilite_s *hl, *hlprev = (struct hilite_s *) 0;
|
||||
|
||||
if (hl) {
|
||||
while (hl) {
|
||||
if (hlstr->hl == hl) {
|
||||
if (hlprev) {
|
||||
hlprev->next = hl->next;
|
||||
} else {
|
||||
blstats[0][fld].thresholds = hl->next;
|
||||
blstats[1][fld].thresholds =
|
||||
blstats[0][fld].thresholds;
|
||||
}
|
||||
free((genericptr_t) hl);
|
||||
return TRUE;
|
||||
for (hl = blstats[0][fld].thresholds; hl; hl = hl->next) {
|
||||
if (hlstr->hl == hl) {
|
||||
if (hlprev) {
|
||||
hlprev->next = hl->next;
|
||||
} else {
|
||||
blstats[0][fld].thresholds = hl->next;
|
||||
blstats[1][fld].thresholds = blstats[0][fld].thresholds;
|
||||
}
|
||||
hlprev = hl;
|
||||
hl = hl->next;
|
||||
if (blstats[0][fld].hilite_rule == hl) {
|
||||
blstats[0][fld].hilite_rule
|
||||
= blstats[1][fld].hilite_rule = (struct hilite_s *) 0;
|
||||
blstats[0][fld].time = blstats[1][fld].time = 0L;
|
||||
}
|
||||
free((genericptr_t) hl);
|
||||
return TRUE;
|
||||
}
|
||||
hlprev = hl;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
Reference in New Issue
Block a user