more status_hilite threshold handling
Negative AC needed one extra change to support >-N since there was a place in the code that assumed 0 was the lowest possible value. (My earlier testing was with <-N which didn't have that issue.) Make '/<N/' work as 'val < N' instead of 'val <= N', and />N/ work as 'val > N' instead of >=. The <= and >= behavior might have been intentional but the only support for that I could find was that the 'O' menu used "N or less" for '<' and "N or more" for '>' when setting up 'absolute' rules. If we actually want <= and >= (and we probably do...), we should add them as more relationship operators instead of misusing < and >. Simplify the is_ltgt_percentnumber() case when parsing options since input has been fully validated by the point that that test passes. Among other things, /<-0/ and />-0' are now accepted (as synonums for 0; -0 doesn't mean anything special) instead of being silently rejected and then discarding the rest of the config file. (That bad behavior is a separate issue not dealt with here.)
This commit is contained in:
90
src/botl.c
90
src/botl.c
@@ -1,4 +1,4 @@
|
||||
/* NetHack 3.6 botl.c $NHDT-Date: 1526709371 2018/05/19 05:56:11 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.94 $ */
|
||||
/* NetHack 3.6 botl.c $NHDT-Date: 1526804444 2018/05/20 08:20:44 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.95 $ */
|
||||
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
|
||||
/*-Copyright (c) Michael Allison, 2006. */
|
||||
/* NetHack may be freely redistributed. See license for details. */
|
||||
@@ -1349,7 +1349,7 @@ int *colorptr;
|
||||
{
|
||||
int bestcolor = NO_COLOR;
|
||||
struct hilite_s *hl;
|
||||
anything *value = (anything *)vp;
|
||||
anything *value = (anything *) vp;
|
||||
char *txtstr, *cmpstr;
|
||||
|
||||
if (!colorptr || fldidx < 0 || fldidx >= MAXBLSTATS)
|
||||
@@ -1358,11 +1358,12 @@ int *colorptr;
|
||||
if (blstats[idx][fldidx].thresholds) {
|
||||
/* there are hilites set here */
|
||||
int max_pc = 0, min_pc = 100;
|
||||
int max_val = 0, min_val = LARGEST_INT;
|
||||
int max_val = -LARGEST_INT, min_val = LARGEST_INT;
|
||||
boolean exactmatch = FALSE;
|
||||
|
||||
hl = blstats[idx][fldidx].thresholds;
|
||||
|
||||
/* min_/max_ are used to track best fit */
|
||||
while (hl) {
|
||||
switch (hl->behavior) {
|
||||
case BL_TH_VAL_PERCENTAGE:
|
||||
@@ -1371,12 +1372,12 @@ int *colorptr;
|
||||
min_pc = max_pc = hl->value.a_int;
|
||||
exactmatch = TRUE;
|
||||
} else if (hl->rel == LT_VALUE && !exactmatch
|
||||
&& (hl->value.a_int >= pc)
|
||||
&& (pc < hl->value.a_int)
|
||||
&& (hl->value.a_int <= min_pc)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
min_pc = hl->value.a_int;
|
||||
} else if (hl->rel == GT_VALUE && !exactmatch
|
||||
&& (hl->value.a_int <= pc)
|
||||
&& (pc > hl->value.a_int)
|
||||
&& (hl->value.a_int >= max_pc)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
max_pc = hl->value.a_int;
|
||||
@@ -1398,13 +1399,13 @@ int *colorptr;
|
||||
min_val = max_val = hl->value.a_int;
|
||||
exactmatch = TRUE;
|
||||
} else if (hl->rel == LT_VALUE && !exactmatch
|
||||
&& (hl->value.a_int >= value->a_int)
|
||||
&& (hl->value.a_int < min_val)) {
|
||||
&& (value->a_int < hl->value.a_int)
|
||||
&& (hl->value.a_int <= min_val)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
min_val = hl->value.a_int;
|
||||
} else if (hl->rel == GT_VALUE && !exactmatch
|
||||
&& (hl->value.a_int <= value->a_int)
|
||||
&& (hl->value.a_int > max_val)) {
|
||||
&& (value->a_int > hl->value.a_int)
|
||||
&& (hl->value.a_int >= max_val)) {
|
||||
merge_bestcolor(&bestcolor, hl->coloridx);
|
||||
max_val = hl->value.a_int;
|
||||
}
|
||||
@@ -1535,7 +1536,7 @@ const char *str;
|
||||
return (*s == '\0');
|
||||
}
|
||||
|
||||
/* does str only contain "<>0-9%" chars */
|
||||
/* does str only contain "<>-+0-9%" chars */
|
||||
STATIC_OVL boolean
|
||||
has_ltgt_percentnumber(str)
|
||||
const char *str;
|
||||
@@ -1543,7 +1544,7 @@ const char *str;
|
||||
const char *s = str;
|
||||
|
||||
while (*s) {
|
||||
if (!index("<>-0123456789%", *s))
|
||||
if (!index("<>-+0123456789%", *s))
|
||||
return FALSE;
|
||||
s++;
|
||||
}
|
||||
@@ -1761,73 +1762,80 @@ boolean from_configfile;
|
||||
always = TRUE;
|
||||
if (*s[sidx + 1] == '\0')
|
||||
sidx--;
|
||||
goto do_rel;
|
||||
} else if (!strcmpi(s[sidx], "up") || !strcmpi(s[sidx], "down")) {
|
||||
if (!strcmpi(s[sidx], "down"))
|
||||
down = TRUE;
|
||||
else
|
||||
up = TRUE;
|
||||
changed = TRUE;
|
||||
goto do_rel;
|
||||
} else if (fld == BL_CAP
|
||||
&& is_fld_arrayvalues(s[sidx], enc_stat,
|
||||
SLT_ENCUMBER, OVERLOADED + 1,
|
||||
&kidx)) {
|
||||
txt = enc_stat[kidx];
|
||||
txtval = TRUE;
|
||||
goto do_rel;
|
||||
} else if (fld == BL_ALIGN
|
||||
&& is_fld_arrayvalues(s[sidx], aligntxt, 0, 3, &kidx)) {
|
||||
txt = aligntxt[kidx];
|
||||
txtval = TRUE;
|
||||
goto do_rel;
|
||||
} else if (fld == BL_HUNGER
|
||||
&& is_fld_arrayvalues(s[sidx], hutxt,
|
||||
SATIATED, STARVED + 1, &kidx)) {
|
||||
txt = hu_stat[kidx]; /* store hu_stat[] val, not hutxt[] */
|
||||
txtval = TRUE;
|
||||
goto do_rel;
|
||||
} else if (!strcmpi(s[sidx], "changed")) {
|
||||
changed = TRUE;
|
||||
goto do_rel;
|
||||
} else if (is_ltgt_percentnumber(s[sidx])) {
|
||||
tmp = s[sidx];
|
||||
tmp = s[sidx]; /* is_ltgt_() guarantees [<>]?[-+]?[0-9]+%? */
|
||||
if (strchr(tmp, '%'))
|
||||
percent = TRUE;
|
||||
if (*tmp == '<')
|
||||
lt = TRUE;
|
||||
else if (*tmp == '>')
|
||||
gt = TRUE;
|
||||
(void) stripchars(tmpbuf, "%<>+", tmp);
|
||||
tmp = tmpbuf;
|
||||
while (*tmp) {
|
||||
if (!index("0123456789", *tmp)
|
||||
&& (*tmp != '-' || tmp > tmpbuf))
|
||||
return FALSE;
|
||||
tmp++;
|
||||
}
|
||||
/* '%', '<', '>' have served their purpose, unary '+' is
|
||||
just decorative, so get rid of them, leaving -?[0-9]+ */
|
||||
tmp = stripchars(tmpbuf, "%<>+", tmp);
|
||||
numeric = TRUE;
|
||||
tmp = tmpbuf;
|
||||
if (strlen(tmp) > 0) {
|
||||
dt = initblstats[fld].anytype;
|
||||
if (percent)
|
||||
dt = ANY_INT;
|
||||
(void) s_to_anything(&hilite.value, tmp, dt);
|
||||
} else
|
||||
return FALSE;
|
||||
if (!hilite.value.a_void && (strcmp(tmp, "0") != 0))
|
||||
return FALSE;
|
||||
dt = percent ? ANY_INT : initblstats[fld].anytype;
|
||||
(void) s_to_anything(&hilite.value, tmp, dt);
|
||||
if (dt == ANY_INT
|
||||
/* AC is the only field where negative values make sense but
|
||||
accept >-1 for other fields since we don't support >=0
|
||||
which someone might want to use in a catch-all rule */
|
||||
&& (hilite.value.a_int < (fld == BL_AC ? -128 : gt ? -1 : 0)
|
||||
/* percentages have another more comprehensive check below */
|
||||
|| hilite.value.a_int > (percent ? 100 : LARGEST_INT))) {
|
||||
config_error_add(
|
||||
"hilite_status threshold '%s%d%s' is out of range",
|
||||
gt ? ">" : lt ? "<" : "",
|
||||
hilite.value.a_int,
|
||||
percent ? "%" : "");
|
||||
return FALSE;
|
||||
}
|
||||
/*
|
||||
* Note: the only check for ANY_LONG would be
|
||||
* if (hilite.value.a_long < (gt ? -1L : 0L)) { }
|
||||
* so we might as well skip it instead of replicating
|
||||
* the above config_error_add() for hilite.value.a_long.
|
||||
* The only non-int/non-long numeric is BL_HUNGER
|
||||
* (unsigned: ANY_UINT) and it should be changed to int
|
||||
* instead of trying to support one oddball field,
|
||||
* particularly since users are encouraged to use the
|
||||
* "satiated"/"hungry"/"weak"/&c strings instead of
|
||||
* their internal numeric values.
|
||||
*/
|
||||
} else if (initblstats[fld].anytype == ANY_STR) {
|
||||
txt = s[sidx];
|
||||
txtval = TRUE;
|
||||
goto do_rel;
|
||||
} else {
|
||||
config_error_add(has_ltgt_percentnumber(s[sidx])
|
||||
? "Wrong format '%s', expected a threshold number or percent"
|
||||
: "Unknown behavior '%s'", s[sidx]);
|
||||
: "Unknown behavior '%s'",
|
||||
s[sidx]);
|
||||
return FALSE;
|
||||
}
|
||||
do_rel:
|
||||
|
||||
/* relationships { LT_VALUE, GT_VALUE, EQ_VALUE} */
|
||||
if (gt)
|
||||
hilite.rel = GT_VALUE;
|
||||
@@ -2666,7 +2674,7 @@ const char *str;
|
||||
start_menu(tmpwin);
|
||||
|
||||
if (str)
|
||||
Sprintf(buf, "%s or less", str);
|
||||
Sprintf(buf, "%s than %s", (fld == BL_AC) ? "Better" : "Less", str);
|
||||
else
|
||||
Sprintf(buf, "Value goes down");
|
||||
any = zeroany;
|
||||
@@ -2684,7 +2692,7 @@ const char *str;
|
||||
buf, MENU_UNSELECTED);
|
||||
|
||||
if (str)
|
||||
Sprintf(buf, "%s or more", str);
|
||||
Sprintf(buf, "%s than %s", (fld == BL_AC) ? "Worse" : "More", str);
|
||||
else
|
||||
Sprintf(buf, "Value goes up");
|
||||
any = zeroany;
|
||||
|
||||
Reference in New Issue
Block a user