Merge branch 'NetHack-3.6.2' of https://rodney.nethack.org:20040/git/NHsource into NetHack-3.6.2

This commit is contained in:
nhmall
2018-05-21 09:55:44 -04:00
3 changed files with 258 additions and 147 deletions
+4
View File
@@ -58,6 +58,10 @@ unix: Makefile.src and Makefile.utl inadvertently relied on a 'gnu make'
General New Features General New Features
-------------------- --------------------
integrate aklys feature introduced in 3.6.1 into display integrate aklys feature introduced in 3.6.1 into display
status_hilite options which use comparisons may now use <= and >= in
addition to previous < and >; in 3.6.1 the latter operated as if
they were <= and >= but now behave as conventional less than and
greater than; old highlight rules using them should be updated
Code Cleanup and Reorganization Code Cleanup and Reorganization
+6 -4
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 botl.h $NHDT-Date: 1452660165 2016/01/13 04:42:45 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $ */ /* NetHack 3.6 botl.h $NHDT-Date: 1526907469 2018/05/21 12:57:49 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.19 $ */
/* Copyright (c) Michael Allison, 2003 */ /* Copyright (c) Michael Allison, 2003 */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -32,11 +32,13 @@ enum statusfields {
BL_FLUSH = -1, BL_TITLE = 0, BL_FLUSH = -1, BL_TITLE = 0,
BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, /* 1..6 */ BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, /* 1..6 */
BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, /* 7..12 */ BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX, /* 7..12 */
BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX, BL_LEVELDESC, /* 13..20 */ BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, /* 13..18 */
BL_EXP, BL_CONDITION BL_HPMAX, BL_LEVELDESC, BL_EXP, BL_CONDITION /* 19..22 */
}; };
enum relationships { LT_VALUE = -1, EQ_VALUE, GT_VALUE, TXT_VALUE }; enum relationships { NO_LTEQGT = -1,
EQ_VALUE, LT_VALUE, LE_VALUE,
GE_VALUE, GT_VALUE, TXT_VALUE };
#define MAXBLSTATS (BL_CONDITION + 1) #define MAXBLSTATS (BL_CONDITION + 1)
+248 -143
View File
@@ -1,4 +1,4 @@
/* NetHack 3.6 botl.c $NHDT-Date: 1526804444 2018/05/20 08:20:44 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.95 $ */ /* NetHack 3.6 botl.c $NHDT-Date: 1526907473 2018/05/21 12:57:53 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.96 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */ /*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -455,12 +455,15 @@ STATIC_DCL void FDECL(split_clridx, (int, int *, int *));
STATIC_DCL char *FDECL(hlattr2attrname, (int, char *, int)); STATIC_DCL char *FDECL(hlattr2attrname, (int, char *, int));
STATIC_DCL void FDECL(status_hilite_linestr_add, (int, struct hilite_s *, STATIC_DCL void FDECL(status_hilite_linestr_add, (int, struct hilite_s *,
unsigned long, const char *)); unsigned long, const char *));
STATIC_DCL void NDECL(status_hilite_linestr_done); STATIC_DCL void NDECL(status_hilite_linestr_done);
STATIC_DCL int FDECL(status_hilite_linestr_countfield, (int)); STATIC_DCL int FDECL(status_hilite_linestr_countfield, (int));
STATIC_DCL void NDECL(status_hilite_linestr_gather_conditions); STATIC_DCL void NDECL(status_hilite_linestr_gather_conditions);
STATIC_DCL void NDECL(status_hilite_linestr_gather); STATIC_DCL void NDECL(status_hilite_linestr_gather);
STATIC_DCL char *FDECL(status_hilite2str, (struct hilite_s *)); STATIC_DCL char *FDECL(status_hilite2str, (struct hilite_s *));
STATIC_DCL int NDECL(status_hilite_menu_choose_field);
STATIC_DCL int FDECL(status_hilite_menu_choose_behavior, (int));
STATIC_DCL int FDECL(status_hilite_menu_choose_updownboth, (int,
const char *));
STATIC_DCL boolean FDECL(status_hilite_menu_add, (int)); STATIC_DCL boolean FDECL(status_hilite_menu_add, (int));
#define has_hilite(i) (blstats[0][(i)].thresholds) #define has_hilite(i) (blstats[0][(i)].thresholds)
#endif #endif
@@ -1357,14 +1360,18 @@ int *colorptr;
if (blstats[idx][fldidx].thresholds) { if (blstats[idx][fldidx].thresholds) {
/* there are hilites set here */ /* there are hilites set here */
int max_pc = 0, min_pc = 100; int max_pc = -1, min_pc = 101;
int max_val = -LARGEST_INT, min_val = LARGEST_INT; int max_val = -LARGEST_INT, min_val = LARGEST_INT;
boolean exactmatch = FALSE; boolean exactmatch = FALSE, updown = FALSE, changed = FALSE;
hl = blstats[idx][fldidx].thresholds;
/* min_/max_ are used to track best fit */ /* min_/max_ are used to track best fit */
while (hl) { for (hl = blstats[idx][fldidx].thresholds; hl; hl = hl->next) {
/* if we've already matched a temporary highlight, it takes
precedence over all persistent ones; we still process
updown rules to get the last one which qualifies */
if ((updown || changed) && hl->behavior != BL_TH_UPDOWN)
continue;
switch (hl->behavior) { switch (hl->behavior) {
case BL_TH_VAL_PERCENTAGE: case BL_TH_VAL_PERCENTAGE:
if (hl->rel == EQ_VALUE && pc == hl->value.a_int) { if (hl->rel == EQ_VALUE && pc == hl->value.a_int) {
@@ -1376,24 +1383,43 @@ int *colorptr;
&& (hl->value.a_int <= min_pc)) { && (hl->value.a_int <= min_pc)) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
min_pc = hl->value.a_int; min_pc = hl->value.a_int;
} else if (hl->rel == LE_VALUE && !exactmatch
&& (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 } else if (hl->rel == GT_VALUE && !exactmatch
&& (pc > hl->value.a_int) && (pc > hl->value.a_int)
&& (hl->value.a_int >= max_pc)) { && (hl->value.a_int >= max_pc)) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
max_pc = hl->value.a_int; max_pc = hl->value.a_int;
} else if (hl->rel == GE_VALUE && !exactmatch
&& (pc >= hl->value.a_int)
&& (hl->value.a_int >= max_pc)) {
merge_bestcolor(&bestcolor, hl->coloridx);
max_pc = hl->value.a_int;
} }
break; break;
case BL_TH_UPDOWN: case BL_TH_UPDOWN:
/* specific 'up' or 'down' takes precedence over general
'changed' regardless of their order in the rule set */
if (chg < 0 && hl->rel == LT_VALUE) { if (chg < 0 && hl->rel == LT_VALUE) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
updown = TRUE;
} else if (chg > 0 && hl->rel == GT_VALUE) { } else if (chg > 0 && hl->rel == GT_VALUE) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
} else if (hl->rel == EQ_VALUE && chg) { updown = TRUE;
} else if (chg != 0 && hl->rel == EQ_VALUE && !updown) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
min_val = max_val = hl->value.a_int; changed = TRUE;
} }
break; break;
case BL_TH_VAL_ABSOLUTE: case BL_TH_VAL_ABSOLUTE:
/*
* TODO:
* This covers data type ANY_INT. We need to handle ANY_LONG
* separately using a_long and new min_lval, max_lval.
*/
if (hl->rel == EQ_VALUE && hl->value.a_int == value->a_int) { if (hl->rel == EQ_VALUE && hl->value.a_int == value->a_int) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
min_val = max_val = hl->value.a_int; min_val = max_val = hl->value.a_int;
@@ -1403,18 +1429,29 @@ int *colorptr;
&& (hl->value.a_int <= min_val)) { && (hl->value.a_int <= min_val)) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
min_val = hl->value.a_int; min_val = hl->value.a_int;
} else if (hl->rel == LE_VALUE && !exactmatch
&& (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 } else if (hl->rel == GT_VALUE && !exactmatch
&& (value->a_int > hl->value.a_int) && (value->a_int > hl->value.a_int)
&& (hl->value.a_int >= max_val)) { && (hl->value.a_int >= max_val)) {
merge_bestcolor(&bestcolor, hl->coloridx); merge_bestcolor(&bestcolor, hl->coloridx);
max_val = hl->value.a_int; max_val = hl->value.a_int;
} else if (hl->rel == GE_VALUE && !exactmatch
&& (value->a_int >= hl->value.a_int)
&& (hl->value.a_int >= max_val)) {
merge_bestcolor(&bestcolor, hl->coloridx);
max_val = hl->value.a_int;
} }
break; break;
case BL_TH_TEXTMATCH: case BL_TH_TEXTMATCH:
txtstr = dupstr(blstats[idx][fldidx].val); txtstr = dupstr(blstats[idx][fldidx].val);
cmpstr = txtstr; cmpstr = txtstr;
if (fldidx == BL_TITLE) { if (fldidx == BL_TITLE) {
int len = (strlen(plname) + sizeof(" the")); int len = (int) (strlen(plname) + sizeof (" the"));
cmpstr += len; cmpstr += len;
} }
(void) trimspaces(cmpstr); (void) trimspaces(cmpstr);
@@ -1432,7 +1469,6 @@ int *colorptr;
default: default:
break; break;
} }
hl = hl->next;
} }
} }
*colorptr = bestcolor; *colorptr = bestcolor;
@@ -1444,9 +1480,9 @@ split_clridx(idx, coloridx, attrib)
int idx; int idx;
int *coloridx, *attrib; int *coloridx, *attrib;
{ {
if (idx && coloridx && attrib) { if (coloridx && attrib) {
*coloridx = idx & 0x00FF; *coloridx = idx & 0x00FF;
*attrib = (idx & 0xFF00) >> 8; *attrib = (idx >> 8) & 0x00FF;
} }
} }
@@ -1516,7 +1552,7 @@ boolean from_configfile;
return TRUE; return TRUE;
} }
/* is str in the format of "[<>]?[-+]?[0-9]+%?" regex */ /* is str in the format of "[<>]?=?[-+]?[0-9]+%?" regex */
STATIC_OVL boolean STATIC_OVL boolean
is_ltgt_percentnumber(str) is_ltgt_percentnumber(str)
const char *str; const char *str;
@@ -1525,6 +1561,8 @@ const char *str;
if (*s == '<' || *s == '>') if (*s == '<' || *s == '>')
s++; s++;
if (*s == '=')
s++;
if (*s == '-' || *s == '+') if (*s == '-' || *s == '+')
s++; s++;
if (!digit(*s)) if (!digit(*s))
@@ -1536,7 +1574,7 @@ const char *str;
return (*s == '\0'); return (*s == '\0');
} }
/* does str only contain "<>-+0-9%" chars */ /* does str only contain "<>=-+0-9%" chars */
STATIC_OVL boolean STATIC_OVL boolean
has_ltgt_percentnumber(str) has_ltgt_percentnumber(str)
const char *str; const char *str;
@@ -1544,7 +1582,7 @@ const char *str;
const char *s = str; const char *s = str;
while (*s) { while (*s) {
if (!index("<>-+0123456789%", *s)) if (!index("<>=-+0123456789%", *s))
return FALSE; return FALSE;
s++; s++;
} }
@@ -1661,22 +1699,15 @@ struct hilite_s *hilite;
return; return;
/* alloc and initialize a new hilite_s struct */ /* alloc and initialize a new hilite_s struct */
new_hilite = (struct hilite_s *) alloc(sizeof(struct hilite_s)); new_hilite = (struct hilite_s *) alloc(sizeof (struct hilite_s));
*new_hilite = *hilite; /* copy struct */ *new_hilite = *hilite; /* copy struct */
new_hilite->set = TRUE; new_hilite->set = TRUE;
new_hilite->fld = fld; new_hilite->fld = fld;
new_hilite->next = (struct hilite_s *)0; new_hilite->next = blstats[0][fld].thresholds;
blstats[0][fld].thresholds = new_hilite;
/* sort_hilites(fld) */
/* Does that status field currently have any hilite thresholds? */
if (!blstats[0][fld].thresholds) {
blstats[0][fld].thresholds = new_hilite;
} else {
struct hilite_s *temp_hilite = blstats[0][fld].thresholds;
new_hilite->next = temp_hilite;
blstats[0][fld].thresholds = new_hilite;
/* sort_hilites(fld) */
}
/* current and prev must both point at the same hilites */ /* current and prev must both point at the same hilites */
blstats[1][fld].thresholds = blstats[0][fld].thresholds; blstats[1][fld].thresholds = blstats[0][fld].thresholds;
} }
@@ -1691,11 +1722,8 @@ boolean from_configfile;
int sidx = 0, i = -1, dt = -1; int sidx = 0, i = -1, dt = -1;
int coloridx = -1, successes = 0; int coloridx = -1, successes = 0;
int disp_attrib = 0; int disp_attrib = 0;
boolean percent = FALSE, changed = FALSE, numeric = FALSE; boolean percent, changed, numeric, down, up,
boolean down= FALSE, up = FALSE; gt, lt, ge, le, eq, txtval, always;
boolean gt = FALSE, lt = FALSE, eq = FALSE, neq = FALSE;
boolean txtval = FALSE;
boolean always = FALSE;
const char *txt; const char *txt;
enum statusfields fld = BL_FLUSH; enum statusfields fld = BL_FLUSH;
struct hilite_s hilite; struct hilite_s hilite;
@@ -1744,10 +1772,9 @@ boolean from_configfile;
int kidx; int kidx;
txt = (const char *)0; txt = (const char *)0;
percent = changed = numeric = FALSE; percent = numeric = always = FALSE;
down = up = FALSE; down = up = changed = FALSE;
gt = eq = lt = neq = txtval = FALSE; gt = ge = eq = le = lt = txtval = FALSE;
always = FALSE;
/* threshold value */ /* threshold value */
if (!s[sidx][0]) if (!s[sidx][0])
@@ -1786,29 +1813,38 @@ boolean from_configfile;
} else if (!strcmpi(s[sidx], "changed")) { } else if (!strcmpi(s[sidx], "changed")) {
changed = TRUE; changed = TRUE;
} else if (is_ltgt_percentnumber(s[sidx])) { } else if (is_ltgt_percentnumber(s[sidx])) {
tmp = s[sidx]; /* is_ltgt_() guarantees [<>]?[-+]?[0-9]+%? */ tmp = s[sidx]; /* is_ltgt_() guarantees [<>]?=?[-+]?[0-9]+%? */
if (strchr(tmp, '%')) if (strchr(tmp, '%'))
percent = TRUE; percent = TRUE;
if (*tmp == '<') if (*tmp == '<') {
lt = TRUE; if (tmp[1] == '=')
else if (*tmp == '>') le = TRUE;
gt = TRUE; else
/* '%', '<', '>' have served their purpose, unary '+' is lt = TRUE;
} else if (*tmp == '>') {
if (tmp[1] == '=')
ge = TRUE;
else
gt = TRUE;
}
/* '%', '<', '>' have served their purpose, '=' is either
part of '<' or '>' or optional for '=N', unary '+' is
just decorative, so get rid of them, leaving -?[0-9]+ */ just decorative, so get rid of them, leaving -?[0-9]+ */
tmp = stripchars(tmpbuf, "%<>+", tmp); tmp = stripchars(tmpbuf, "%<>=+", tmp);
numeric = TRUE; numeric = TRUE;
dt = percent ? ANY_INT : initblstats[fld].anytype; dt = percent ? ANY_INT : initblstats[fld].anytype;
(void) s_to_anything(&hilite.value, tmp, dt); (void) s_to_anything(&hilite.value, tmp, dt);
if (dt == ANY_INT if (dt == ANY_INT
/* AC is the only field where negative values make sense but /* AC is the only field where negative values make sense but
accept >-1 for other fields since we don't support >=0 accept >-1 for other fields */
which someone might want to use in a catch-all rule */
&& (hilite.value.a_int < (fld == BL_AC ? -128 : gt ? -1 : 0) && (hilite.value.a_int < (fld == BL_AC ? -128 : gt ? -1 : 0)
/* percentages have another more comprehensive check below */ /* percentages have another more comprehensive check below */
|| hilite.value.a_int > (percent ? 100 : LARGEST_INT))) { || hilite.value.a_int > (percent ? (lt ? 101 : 100)
: LARGEST_INT))) {
config_error_add( config_error_add(
"hilite_status threshold '%s%d%s' is out of range", "hilite_status threshold '%s%d%s' is out of range",
gt ? ">" : lt ? "<" : "", gt ? ">" : ge ? ">="
: lt ? "<" : le ? "<=" : "=",
hilite.value.a_int, hilite.value.a_int,
percent ? "%" : ""); percent ? "%" : "");
return FALSE; return FALSE;
@@ -1836,22 +1872,16 @@ boolean from_configfile;
return FALSE; return FALSE;
} }
/* relationships { LT_VALUE, GT_VALUE, EQ_VALUE} */ /* relationships {LT_VALUE, LE_VALUE, EQ_VALUE, GE_VALUE, GT_VALUE} */
if (gt) if (gt || up)
hilite.rel = GT_VALUE; hilite.rel = GT_VALUE;
else if (eq) else if (lt || down)
hilite.rel = EQ_VALUE;
else if (lt)
hilite.rel = LT_VALUE; hilite.rel = LT_VALUE;
else if (percent) else if (ge)
hilite.rel = EQ_VALUE; hilite.rel = GE_VALUE;
else if (numeric) else if (le)
hilite.rel = EQ_VALUE; hilite.rel = LE_VALUE;
else if (down) else if (eq || percent || numeric || changed)
hilite.rel = LT_VALUE;
else if (up)
hilite.rel = GT_VALUE;
else if (changed)
hilite.rel = EQ_VALUE; hilite.rel = EQ_VALUE;
else if (txtval) else if (txtval)
hilite.rel = TXT_VALUE; hilite.rel = TXT_VALUE;
@@ -1869,13 +1899,24 @@ boolean from_configfile;
config_error_add("Cannot use percent with '%s'", config_error_add("Cannot use percent with '%s'",
initblstats[fld].fldname); initblstats[fld].fldname);
return FALSE; return FALSE;
} else if ((hilite.value.a_int < 0) } else if ((hilite.value.a_int < -1)
|| (hilite.value.a_int == -1
&& hilite.value.a_int != GT_VALUE)
|| (hilite.value.a_int == 0 || (hilite.value.a_int == 0
&& hilite.rel == LT_VALUE) && hilite.rel == LT_VALUE)
|| (hilite.value.a_int > 100)
|| (hilite.value.a_int == 100 || (hilite.value.a_int == 100
&& hilite.rel == GT_VALUE)) { && hilite.rel == GT_VALUE)
config_error_add("Illegal percentage value"); || (hilite.value.a_int == 101
&& hilite.value.a_int != LT_VALUE)
|| (hilite.value.a_int > 101)) {
config_error_add(
"hilite_status: invalid percentage value '%s%d%%'",
(hilite.rel == LT_VALUE) ? "<"
: (hilite.rel == LE_VALUE) ? "<="
: (hilite.rel == GT_VALUE) ? ">"
: (hilite.rel == GE_VALUE) ? ">="
: "=",
hilite.value.a_int);
return FALSE; return FALSE;
} }
} }
@@ -1898,6 +1939,7 @@ boolean from_configfile;
for (i = 0; i < sf; ++i) { for (i = 0; i < sf; ++i) {
int a = match_str2attr(subfields[i], FALSE); int a = match_str2attr(subfields[i], FALSE);
if (a == ATR_DIM) if (a == ATR_DIM)
disp_attrib |= HL_DIM; disp_attrib |= HL_DIM;
else if (a == ATR_BLINK) else if (a == ATR_BLINK)
@@ -1942,7 +1984,7 @@ boolean from_configfile;
hilite.anytype = dt; hilite.anytype = dt;
if (hilite.behavior == BL_TH_TEXTMATCH && txt if (hilite.behavior == BL_TH_TEXTMATCH && txt
&& strlen(txt) < QBUFSZ-1) { && strlen(txt) < QBUFSZ - 1) {
Strcpy(hilite.textmatch, txt); Strcpy(hilite.textmatch, txt);
(void) trimspaces(hilite.textmatch); (void) trimspaces(hilite.textmatch);
} }
@@ -2466,21 +2508,24 @@ struct hilite_s *hl;
char clrbuf[BUFSZ]; char clrbuf[BUFSZ];
char attrbuf[BUFSZ]; char attrbuf[BUFSZ];
char *tmpattr; char *tmpattr;
const char *op;
if (!hl) if (!hl)
return (char *) 0; return (char *) 0;
behavebuf[0] = '\0'; behavebuf[0] = '\0';
clrbuf[0] = '\0'; clrbuf[0] = '\0';
op = (hl->rel == LT_VALUE) ? "<"
: (hl->rel == LE_VALUE) ? "<="
: (hl->rel == GT_VALUE) ? ">"
: (hl->rel == GE_VALUE) ? ">="
: (hl->rel == EQ_VALUE) ? "="
: 0;
switch (hl->behavior) { switch (hl->behavior) {
case BL_TH_VAL_PERCENTAGE: case BL_TH_VAL_PERCENTAGE:
if (hl->rel == LT_VALUE) if (op)
Sprintf(behavebuf, "<%i%%", hl->value.a_int); Sprintf(behavebuf, "%s%d%%", op, hl->value.a_int);
else if (hl->rel == GT_VALUE)
Sprintf(behavebuf, ">%i%%", hl->value.a_int);
else if (hl->rel == EQ_VALUE)
Sprintf(behavebuf, "%i%%", hl->value.a_int);
else else
impossible("hl->behavior=percentage, rel error"); impossible("hl->behavior=percentage, rel error");
break; break;
@@ -2495,12 +2540,8 @@ struct hilite_s *hl;
impossible("hl->behavior=updown, rel error"); impossible("hl->behavior=updown, rel error");
break; break;
case BL_TH_VAL_ABSOLUTE: case BL_TH_VAL_ABSOLUTE:
if (hl->rel == LT_VALUE) if (op)
Sprintf(behavebuf, "<%i", hl->value.a_int); Sprintf(behavebuf, "%s%d", op, hl->value.a_int);
else if (hl->rel == GT_VALUE)
Sprintf(behavebuf, ">%i", hl->value.a_int);
else if (hl->rel == EQ_VALUE)
Sprintf(behavebuf, "%i", hl->value.a_int);
else else
impossible("hl->behavior=absolute, rel error"); impossible("hl->behavior=absolute, rel error");
break; break;
@@ -2540,7 +2581,7 @@ struct hilite_s *hl;
return buf; return buf;
} }
int STATIC_OVL int
status_hilite_menu_choose_field() status_hilite_menu_choose_field()
{ {
winid tmpwin; winid tmpwin;
@@ -2569,7 +2610,7 @@ status_hilite_menu_choose_field()
return fld; return fld;
} }
int STATIC_OVL int
status_hilite_menu_choose_behavior(fld) status_hilite_menu_choose_behavior(fld)
int fld; int fld;
{ {
@@ -2615,7 +2656,8 @@ int fld;
nopts++; nopts++;
} }
if (fld != BL_CAP && fld != BL_HUNGER && (at == ANY_INT || at == ANY_LONG || at == ANY_UINT)) { if (fld != BL_CAP && fld != BL_HUNGER
&& (at == ANY_INT || at == ANY_LONG || at == ANY_UINT)) {
any = zeroany; any = zeroany;
any.a_int = onlybeh = BL_TH_VAL_ABSOLUTE; any.a_int = onlybeh = BL_TH_VAL_ABSOLUTE;
add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE, add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE,
@@ -2631,7 +2673,8 @@ int fld;
nopts++; nopts++;
} }
if (initblstats[fld].anytype == ANY_STR || fld == BL_CAP || fld == BL_HUNGER) { if (initblstats[fld].anytype == ANY_STR
|| fld == BL_CAP || fld == BL_HUNGER) {
any = zeroany; any = zeroany;
any.a_int = onlybeh = BL_TH_TEXTMATCH; any.a_int = onlybeh = BL_TH_TEXTMATCH;
Sprintf(buf, "%s text match", initblstats[fld].fldname); Sprintf(buf, "%s text match", initblstats[fld].fldname);
@@ -2659,12 +2702,12 @@ int fld;
return beh; return beh;
} }
int STATIC_OVL int
status_hilite_menu_choose_updownboth(fld, str) status_hilite_menu_choose_updownboth(fld, str)
int fld; int fld;
const char *str; const char *str;
{ {
int res, ret = -2; int res, ret = NO_LTEQGT;
winid tmpwin; winid tmpwin;
char buf[BUFSZ]; char buf[BUFSZ];
anything any; anything any;
@@ -2674,7 +2717,8 @@ const char *str;
start_menu(tmpwin); start_menu(tmpwin);
if (str) if (str)
Sprintf(buf, "%s than %s", (fld == BL_AC) ? "Better" : "Less", str); Sprintf(buf, "%s than %s",
(fld == BL_AC) ? "Better (lower)" : "Less", str);
else else
Sprintf(buf, "Value goes down"); Sprintf(buf, "Value goes down");
any = zeroany; any = zeroany;
@@ -2682,6 +2726,15 @@ const char *str;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
buf, MENU_UNSELECTED); buf, MENU_UNSELECTED);
if (str) {
Sprintf(buf, "%s or %s",
str, (fld == BL_AC) ? "better (lower)" : "less");
any = zeroany;
any.a_int = 10 + LE_VALUE;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
buf, MENU_UNSELECTED);
}
if (str) if (str)
Sprintf(buf, "Exactly %s", str); Sprintf(buf, "Exactly %s", str);
else else
@@ -2691,8 +2744,18 @@ const char *str;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE, add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
buf, MENU_UNSELECTED); buf, MENU_UNSELECTED);
if (str) {
Sprintf(buf, "%s or %s",
str, (fld == BL_AC) ? "worse (higher)" : "more");
any = zeroany;
any.a_int = 10 + GE_VALUE;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
buf, MENU_UNSELECTED);
}
if (str) if (str)
Sprintf(buf, "%s than %s", (fld == BL_AC) ? "Worse" : "More", str); Sprintf(buf, "%s than %s",
(fld == BL_AC) ? "Worse (higher)" : "More", str);
else else
Sprintf(buf, "Value goes up"); Sprintf(buf, "Value goes up");
any = zeroany; any = zeroany;
@@ -2719,7 +2782,7 @@ int origfld;
{ {
int fld; int fld;
int behavior; int behavior;
int lt_gt_eq = 0; int lt_gt_eq = NO_LTEQGT; /* not set up yet */
int clr = NO_COLOR, atr = HL_UNDEF; int clr = NO_COLOR, atr = HL_UNDEF;
struct hilite_s hilite; struct hilite_s hilite;
unsigned long cond = 0UL; unsigned long cond = 0UL;
@@ -2740,55 +2803,63 @@ choose_field:
colorqry[0] = '\0'; colorqry[0] = '\0';
attrqry[0] = '\0'; attrqry[0] = '\0';
memset((genericptr_t) &hilite, 0, sizeof(struct hilite_s)); memset((genericptr_t) &hilite, 0, sizeof (struct hilite_s));
hilite.set = FALSE; /* mark it "unset" */ hilite.set = FALSE; /* mark it "unset" */
hilite.fld = fld; hilite.fld = fld;
choose_behavior: choose_behavior:
behavior = status_hilite_menu_choose_behavior(fld); behavior = status_hilite_menu_choose_behavior(fld);
if (behavior == (BL_TH_NONE-1)) { if (behavior == (BL_TH_NONE - 1)) {
return FALSE; return FALSE;
} else if (behavior == BL_TH_NONE) { } else if (behavior == BL_TH_NONE) {
if (origfld == BL_FLUSH) if (origfld == BL_FLUSH)
goto choose_field; goto choose_field;
else return FALSE;
return FALSE;
} }
hilite.behavior = behavior; hilite.behavior = behavior;
choose_value: choose_value:
if (behavior == BL_TH_VAL_PERCENTAGE if (behavior == BL_TH_VAL_PERCENTAGE
|| behavior == BL_TH_VAL_ABSOLUTE) { || behavior == BL_TH_VAL_ABSOLUTE) {
char inbuf[BUFSZ] = DUMMY, buf[BUFSZ]; char inbuf[BUFSZ], buf[BUFSZ];
int val; anything aval;
boolean skipltgt = FALSE; int val, dt;
boolean gotnum = FALSE; boolean skipltgt = FALSE, gotnum = FALSE,
char *inp = inbuf; percent = (behavior == BL_TH_VAL_PERCENTAGE);
char *numstart = inbuf; char *inp, *numstart;
inbuf[0] = '\0'; inbuf[0] = '\0';
Sprintf(buf, "Enter %svalue for %s threshold:", Sprintf(buf, "Enter %svalue for %s threshold:",
(behavior == BL_TH_VAL_PERCENTAGE) ? "percentage " : "", percent ? "percentage " : "",
initblstats[fld].fldname); initblstats[fld].fldname);
getlin(buf, inbuf); getlin(buf, inbuf);
if (inbuf[0] == '\0' || inbuf[0] == '\033') if (inbuf[0] == '\0' || inbuf[0] == '\033')
goto choose_behavior; goto choose_behavior;
inp = trimspaces(inbuf); inp = numstart = trimspaces(inbuf);
if (!*inp) if (!*inp)
goto choose_behavior; goto choose_behavior;
/* allow user to enter "<50%" or ">50" or just "50" */ /* allow user to enter "<50%" or ">50" or just "50"
or <=50% or >=50 or =50 */
if (*inp == '>' || *inp == '<' || *inp == '=') { if (*inp == '>' || *inp == '<' || *inp == '=') {
lt_gt_eq = (*inp == '>') ? GT_VALUE lt_gt_eq = (*inp == '>') ? ((inp[1] == '=') ? GE_VALUE : GT_VALUE)
: (*inp == '<') ? LT_VALUE : EQ_VALUE; : (*inp == '<') ? ((inp[1] == '=') ? LE_VALUE : LT_VALUE)
: EQ_VALUE;
skipltgt = TRUE; skipltgt = TRUE;
*inp = ' '; *inp++ = ' ';
numstart++;
if (lt_gt_eq == GE_VALUE || lt_gt_eq == LE_VALUE) {
*inp++ = ' ';
numstart++;
}
}
if (*inp == '-') {
inp++; inp++;
} else if (*inp == '+') {
*inp++ = ' ';
numstart++; numstart++;
} }
while (digit(*inp)) { while (digit(*inp)) {
@@ -2796,11 +2867,12 @@ choose_value:
gotnum = TRUE; gotnum = TRUE;
} }
if (*inp == '%') { if (*inp == '%') {
behavior = BL_TH_VAL_PERCENTAGE; if (!percent) {
*inp = '\0'; pline("Not expecting a percentage.");
} else if (!*inp) { goto choose_behavior;
behavior = BL_TH_VAL_ABSOLUTE; }
} else { *inp = '\0'; /* strip '%' [this accepts trailing junk!] */
} else if (*inp) {
/* some random characters */ /* some random characters */
pline("\"%s\" is not a recognized number.", inp); pline("\"%s\" is not a recognized number.", inp);
goto choose_value; goto choose_value;
@@ -2810,64 +2882,92 @@ choose_value:
goto choose_value; goto choose_value;
} }
val = atoi(numstart); aval = zeroany;
if (behavior == BL_TH_VAL_PERCENTAGE) { dt = percent ? ANY_INT : initblstats[fld].anytype;
(void) s_to_anything(&aval, numstart, dt);
if (percent) {
val = aval.a_int;
if (initblstats[fld].idxmax == -1) { if (initblstats[fld].idxmax == -1) {
pline("Field '%s' does not support percentage values.", pline("Field '%s' does not support percentage values.",
initblstats[fld].fldname); initblstats[fld].fldname);
behavior = BL_TH_VAL_ABSOLUTE; behavior = BL_TH_VAL_ABSOLUTE;
goto choose_value; goto choose_value;
} }
if (val < 0 || val > 100) { /* if player only specified a number then lt_gt_eq isn't set
pline("Not a valid percent value."); up yet and the >-1 and <101 exceptions can't be honored;
deliberate use of those should be uncommon enough for
that to be palatable; unfortunately, it also lets 0 with
later < and 100 with later > through too but those won't
break anything, just end up as no-ops */
if ((val < 0 && (val != -1 || lt_gt_eq != GT_VALUE))
|| (val == 0 && lt_gt_eq == LT_VALUE)
|| (val == 100 && lt_gt_eq == GT_VALUE)
|| (val > 100 && (val != 101 || lt_gt_eq != LT_VALUE))) {
pline("'%s%d%%' is not a valid percent value.",
(lt_gt_eq == LT_VALUE) ? "<"
: (lt_gt_eq == LE_VALUE) ? "<="
: (lt_gt_eq == GT_VALUE) ? ">"
: (lt_gt_eq == GE_VALUE) ? ">="
: (lt_gt_eq == EQ_VALUE) ? "="
/* didn't specify lt_gt_eq with number */
: "",
val);
goto choose_value; goto choose_value;
} }
/* restore suffix for use in color and attribute prompts */
if (!index(numstart, '%'))
Strcat(numstart, "%");
} }
if (!skipltgt) { if (!skipltgt) {
lt_gt_eq = status_hilite_menu_choose_updownboth(fld, inbuf); lt_gt_eq = status_hilite_menu_choose_updownboth(fld, inbuf);
if (lt_gt_eq == -2) if (lt_gt_eq == NO_LTEQGT)
goto choose_value; goto choose_value;
} }
Sprintf(colorqry, "Choose a color for when %s is %s%s:", Sprintf(colorqry, "Choose a color for when %s is %s%s%s:",
initblstats[fld].fldname, initblstats[fld].fldname,
(lt_gt_eq == LT_VALUE) ? "less than "
: (lt_gt_eq == GT_VALUE) ? "more than "
: "",
numstart, numstart,
(lt_gt_eq == EQ_VALUE) ? "" (lt_gt_eq == LE_VALUE) ? " or less"
: (lt_gt_eq == LT_VALUE) ? " or less" : (lt_gt_eq == GE_VALUE) ? " or more"
: " or more"); : "");
Sprintf(attrqry, "Choose attribute for when %s is %s%s%s:",
Sprintf(attrqry, "Choose attribute for when %s is %s%s:",
initblstats[fld].fldname, initblstats[fld].fldname,
inbuf, (lt_gt_eq == LT_VALUE) ? "less than "
(lt_gt_eq == EQ_VALUE) ? "" : (lt_gt_eq == GT_VALUE) ? "more than "
: (lt_gt_eq == LT_VALUE) ? " or less" : "",
: " or more"); numstart,
(lt_gt_eq == LE_VALUE) ? " or less"
: (lt_gt_eq == GE_VALUE) ? " or more"
: "");
hilite.rel = lt_gt_eq; hilite.rel = lt_gt_eq;
hilite.value.a_int = val; hilite.value = aval;
} else if (behavior == BL_TH_UPDOWN) { } else if (behavior == BL_TH_UPDOWN) {
lt_gt_eq = status_hilite_menu_choose_updownboth(fld, (char *)0); lt_gt_eq = status_hilite_menu_choose_updownboth(fld, (char *)0);
if (lt_gt_eq == -2) if (lt_gt_eq == NO_LTEQGT)
goto choose_behavior; goto choose_behavior;
Sprintf(colorqry, "Choose a color for when %s %s:", Sprintf(colorqry, "Choose a color for when %s %s:",
initblstats[fld].fldname, initblstats[fld].fldname,
(lt_gt_eq == EQ_VALUE) ? "changes" (lt_gt_eq == EQ_VALUE) ? "changes"
: (lt_gt_eq == LT_VALUE) ? "decreases" : (lt_gt_eq == LT_VALUE) ? "decreases"
: "increases"); : "increases");
Sprintf(attrqry, "Choose attribute for when %s %s:", Sprintf(attrqry, "Choose attribute for when %s %s:",
initblstats[fld].fldname, initblstats[fld].fldname,
(lt_gt_eq == EQ_VALUE) ? "changes" (lt_gt_eq == EQ_VALUE) ? "changes"
: (lt_gt_eq == LT_VALUE) ? "decreases" : (lt_gt_eq == LT_VALUE) ? "decreases"
: "increases"); : "increases");
hilite.rel = lt_gt_eq; hilite.rel = lt_gt_eq;
} else if (behavior == BL_TH_CONDITION) { } else if (behavior == BL_TH_CONDITION) {
cond = query_conditions(); cond = query_conditions();
if (!cond) { if (!cond) {
if (origfld == BL_FLUSH) if (origfld == BL_FLUSH)
goto choose_field; goto choose_field;
else return FALSE;
return FALSE;
} }
Sprintf(colorqry, "Choose a color for conditions %s:", Sprintf(colorqry, "Choose a color for conditions %s:",
conditionbitmask2str(cond)); conditionbitmask2str(cond));
@@ -2875,6 +2975,7 @@ choose_value:
conditionbitmask2str(cond)); conditionbitmask2str(cond));
} else if (behavior == BL_TH_TEXTMATCH) { } else if (behavior == BL_TH_TEXTMATCH) {
char qry_buf[BUFSZ]; char qry_buf[BUFSZ];
Sprintf(qry_buf, "%s %s text value to match:", Sprintf(qry_buf, "%s %s text value to match:",
(fld == BL_CAP (fld == BL_CAP
|| fld == BL_ALIGN || fld == BL_ALIGN
@@ -2884,27 +2985,31 @@ choose_value:
if (fld == BL_CAP) { if (fld == BL_CAP) {
int rv = query_arrayvalue(qry_buf, int rv = query_arrayvalue(qry_buf,
enc_stat, enc_stat,
SLT_ENCUMBER, OVERLOADED+1); SLT_ENCUMBER, OVERLOADED + 1);
if (rv < SLT_ENCUMBER) if (rv < SLT_ENCUMBER)
goto choose_behavior; goto choose_behavior;
hilite.rel = TXT_VALUE; hilite.rel = TXT_VALUE;
Strcpy(hilite.textmatch, enc_stat[rv]); Strcpy(hilite.textmatch, enc_stat[rv]);
} else if (fld == BL_ALIGN) { } else if (fld == BL_ALIGN) {
const char *aligntxt[] = {"chaotic", "neutral", "lawful"}; static const char *aligntxt[] = { "chaotic", "neutral", "lawful" };
int rv = query_arrayvalue(qry_buf, int rv = query_arrayvalue(qry_buf,
aligntxt, 0, 3); aligntxt, 0, 2 + 1);
if (rv < 0) if (rv < 0)
goto choose_behavior; goto choose_behavior;
hilite.rel = TXT_VALUE; hilite.rel = TXT_VALUE;
Strcpy(hilite.textmatch, aligntxt[rv]); Strcpy(hilite.textmatch, aligntxt[rv]);
} else if (fld == BL_HUNGER) { } else if (fld == BL_HUNGER) {
const char *hutxt[] = {"Satiated", (char *)0, "Hungry", "Weak", static const char *hutxt[] = { "Satiated", (char *) 0, "Hungry",
"Fainting", "Fainted", "Starved"}; "Weak", "Fainting", "Fainted",
"Starved" };
int rv = query_arrayvalue(qry_buf, int rv = query_arrayvalue(qry_buf,
hutxt, hutxt,
SATIATED, STARVED+1); SATIATED, STARVED + 1);
if (rv < SATIATED) if (rv < SATIATED)
goto choose_behavior; goto choose_behavior;
@@ -2925,7 +3030,7 @@ choose_value:
hilite.rel = TXT_VALUE; hilite.rel = TXT_VALUE;
Strcpy(hilite.textmatch, rolelist[rv]); Strcpy(hilite.textmatch, rolelist[rv]);
} else { } else {
char inbuf[BUFSZ] = DUMMY; char inbuf[BUFSZ];
inbuf[0] = '\0'; inbuf[0] = '\0';
getlin(qry_buf, inbuf); getlin(qry_buf, inbuf);
@@ -2933,7 +3038,7 @@ choose_value:
goto choose_behavior; goto choose_behavior;
hilite.rel = TXT_VALUE; hilite.rel = TXT_VALUE;
if (strlen(inbuf) < QBUFSZ-1) if (strlen(inbuf) < QBUFSZ - 1)
Strcpy(hilite.textmatch, inbuf); Strcpy(hilite.textmatch, inbuf);
else else
return FALSE; return FALSE;
@@ -2950,7 +3055,6 @@ choose_value:
} }
choose_color: choose_color:
clr = query_color(colorqry); clr = query_color(colorqry);
if (clr == -1) { if (clr == -1) {
if (behavior != BL_TH_ALWAYS_HILITE) if (behavior != BL_TH_ALWAYS_HILITE)
@@ -2984,6 +3088,7 @@ choose_color:
char clrbuf[BUFSZ]; char clrbuf[BUFSZ];
char attrbuf[BUFSZ]; char attrbuf[BUFSZ];
char *tmpattr; char *tmpattr;
if (atr == HL_DIM) if (atr == HL_DIM)
cond_hilites[HL_ATTCLR_DIM] |= cond; cond_hilites[HL_ATTCLR_DIM] |= cond;
else if (atr == HL_BLINK) else if (atr == HL_BLINK)