-/* NetHack 3.6 botl.c $NHDT-Date: 1526907473 2018/05/21 12:57:53 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.96 $ */
+/* NetHack 3.6 botl.c $NHDT-Date: 1526955073 2018/05/22 02:11:13 $ $NHDT-Branch: NetHack-3.6.2 $:$NHDT-Revision: 1.98 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
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 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)
#endif
INIT_BLSTAT("armor-class", " AC:%s", ANY_INT, 10, BL_AC),
INIT_BLSTAT("HD", " HD:%s", ANY_INT, 10, BL_HD),
INIT_BLSTAT("time", " T:%s", ANY_LONG, 20, BL_TIME),
- INIT_BLSTAT("hunger", " %s", ANY_UINT, 40, BL_HUNGER),
+ /* hunger used to be 'ANY_UINT'; see note below in bot_via_windowport() */
+ 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),
blstats[idx][BL_TIME].a.a_long = moves;
/* Hunger */
- blstats[idx][BL_HUNGER].a.a_uint = u.uhs;
+ /* note: u.uhs is unsigned, and 3.6.1's STATUS_HILITE defined
+ BL_HUNGER to be ANY_UINT, but that was the only non-int/non-long
+ numeric field so it's far simpler to treat it as plain int and
+ not need ANY_UINT handling at all */
+ blstats[idx][BL_HUNGER].a.a_int = (int) u.uhs;
Strcpy(blstats[idx][BL_HUNGER].val,
(u.uhs != NOT_HUNGRY) ? hu_stat[u.uhs] : "");
valset[BL_HUNGER] = TRUE;
{0, BL_FLUSH}
};
+/* format arguments */
+static const char threshold_value[] = "hilite_status threshold ",
+ is_out_of_range[] = " is out of range";
+
/* field name to bottom line index */
STATIC_OVL enum statusfields
fldname_to_bl_indx(name)
int coloridx = -1, successes = 0;
int disp_attrib = 0;
boolean percent, changed, numeric, down, up,
- gt, lt, ge, le, eq, txtval, always;
+ gt, lt, ge, le, eq, txtval, always;
const char *txt;
enum statusfields fld = BL_FLUSH;
struct hilite_s hilite;
} else if (!strcmpi(s[sidx], "changed")) {
changed = TRUE;
} else if (is_ltgt_percentnumber(s[sidx])) {
+ const char *op;
+
tmp = s[sidx]; /* is_ltgt_() guarantees [<>]?=?[-+]?[0-9]+%? */
if (strchr(tmp, '%'))
percent = TRUE;
numeric = TRUE;
dt = percent ? ANY_INT : initblstats[fld].anytype;
(void) s_to_anything(&hilite.value, tmp, dt);
+
+ op = gt ? ">" : ge ? ">=" : lt ? "<" : le ? "<=" : "=";
if (dt == ANY_INT
/* AC is the only field where negative values make sense but
- accept >-1 for other fields */
- && (hilite.value.a_int < (fld == BL_AC ? -128 : gt ? -1 : 0)
+ accept >-1 for other fields; reject <0 for non-AC */
+ && (hilite.value.a_int
+ < ((fld == BL_AC) ? -128 : gt ? -1 : lt ? 1 : 0)
/* percentages have another more comprehensive check below */
|| hilite.value.a_int > (percent ? (lt ? 101 : 100)
: LARGEST_INT))) {
- config_error_add(
- "hilite_status threshold '%s%d%s' is out of range",
- gt ? ">" : ge ? ">="
- : lt ? "<" : le ? "<=" : "=",
- hilite.value.a_int,
- percent ? "%" : "");
- return FALSE;
+ config_error_add("%s'%s%d%s'%s", threshold_value,
+ op, hilite.value.a_int, percent ? "%" : "",
+ is_out_of_range);
+ return FALSE;
+ } else if (dt == ANY_LONG
+ && (hilite.value.a_long < (gt ? -1L : lt ? 1L : 0L))) {
+ config_error_add("%s'%s%ld'%s", threshold_value,
+ op, hilite.value.a_long, is_out_of_range);
+ 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;
}
if (fld != BL_CAP && fld != BL_HUNGER
- && (at == ANY_INT || at == ANY_LONG || at == ANY_UINT)) {
+ && (at == ANY_INT || at == ANY_LONG)) {
any = zeroany;
any.a_int = onlybeh = BL_TH_VAL_ABSOLUTE;
add_menu(tmpwin, NO_GLYPH, &any, 'n', 0, ATR_NONE,
}
STATIC_OVL int
-status_hilite_menu_choose_updownboth(fld, str)
+status_hilite_menu_choose_updownboth(fld, str, ltok, gtok)
int fld;
const char *str;
+boolean ltok, gtok;
{
int res, ret = NO_LTEQGT;
winid tmpwin;
tmpwin = create_nhwindow(NHW_MENU);
start_menu(tmpwin);
- if (str)
- Sprintf(buf, "%s than %s",
- (fld == BL_AC) ? "Better (lower)" : "Less", str);
- else
- Sprintf(buf, "Value goes down");
- any = zeroany;
- any.a_int = 10 + LT_VALUE;
- add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
- buf, MENU_UNSELECTED);
-
- if (str) {
- Sprintf(buf, "%s or %s",
- str, (fld == BL_AC) ? "better (lower)" : "less");
+ if (ltok) {
+ if (str)
+ Sprintf(buf, "%s than %s",
+ (fld == BL_AC) ? "Better (lower)" : "Less", str);
+ else
+ Sprintf(buf, "Value goes down");
any = zeroany;
- any.a_int = 10 + LE_VALUE;
+ any.a_int = 10 + LT_VALUE;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
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)
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
buf, MENU_UNSELECTED);
- if (str) {
- Sprintf(buf, "%s or %s",
- str, (fld == BL_AC) ? "worse (higher)" : "more");
+ if (gtok) {
+ 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)
+ Sprintf(buf, "%s than %s",
+ (fld == BL_AC) ? "Worse (higher)" : "More", str);
+ else
+ Sprintf(buf, "Value goes up");
any = zeroany;
- any.a_int = 10 + GE_VALUE;
+ any.a_int = 10 + GT_VALUE;
add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
- buf, MENU_UNSELECTED);
- }
-
- if (str)
- Sprintf(buf, "%s than %s",
- (fld == BL_AC) ? "Worse (higher)" : "More", str);
- else
- Sprintf(buf, "Value goes up");
- any = zeroany;
- any.a_int = 10 + GT_VALUE;
- add_menu(tmpwin, NO_GLYPH, &any, 0, 0, ATR_NONE,
buf, MENU_UNSELECTED);
-
+ }
Sprintf(buf, "Select field %s value:", initblstats[fld].fldname);
end_menu(tmpwin, buf);
{
int fld;
int behavior;
- int lt_gt_eq = NO_LTEQGT; /* not set up yet */
+ int lt_gt_eq;
int clr = NO_COLOR, atr = HL_UNDEF;
struct hilite_s hilite;
unsigned long cond = 0UL;
char inbuf[BUFSZ], buf[BUFSZ];
anything aval;
int val, dt;
- boolean skipltgt = FALSE, gotnum = FALSE,
- percent = (behavior == BL_TH_VAL_PERCENTAGE);
+ boolean gotnum = FALSE, percent = (behavior == BL_TH_VAL_PERCENTAGE);
char *inp, *numstart;
+ const char *op;
+ lt_gt_eq = NO_LTEQGT; /* not set up yet */
inbuf[0] = '\0';
Sprintf(buf, "Enter %svalue for %s threshold:",
percent ? "percentage " : "",
lt_gt_eq = (*inp == '>') ? ((inp[1] == '=') ? GE_VALUE : GT_VALUE)
: (*inp == '<') ? ((inp[1] == '=') ? LE_VALUE : LT_VALUE)
: EQ_VALUE;
- skipltgt = TRUE;
*inp++ = ' ';
numstart++;
if (lt_gt_eq == GE_VALUE || lt_gt_eq == LE_VALUE) {
pline("Is that an invisible number?");
goto choose_value;
}
+ op = (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 */
aval = zeroany;
dt = percent ? ANY_INT : initblstats[fld].anytype;
/* if player only specified a number then lt_gt_eq isn't set
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 */
+ that to be palatable; for 0 and 100, choose_updown_both()
+ will prevent useless operations */
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);
+ pline("'%s%d%%' is not a valid percent value.", op, val);
goto choose_value;
}
/* restore suffix for use in color and attribute prompts */
if (!index(numstart, '%'))
Strcat(numstart, "%");
+
+ /* reject negative values except for AC and >-1; reject 0 for < */
+ } else if (dt == ANY_INT
+ && (aval.a_int < ((fld == BL_AC) ? -128
+ : (lt_gt_eq == GT_VALUE) ? -1
+ : (lt_gt_eq == LT_VALUE) ? 1 : 0))) {
+ pline("%s'%s%d'%s", threshold_value,
+ op, aval.a_int, is_out_of_range);
+ goto choose_value;
+ } else if (dt == ANY_LONG
+ && (aval.a_long < (lt_gt_eq == GT_VALUE) ? -1L
+ : (lt_gt_eq == LT_VALUE) ? 1L : 0L)) {
+ pline("%s'%s%ld'%s", threshold_value,
+ op, aval.a_long, is_out_of_range);
+ goto choose_value;
}
- if (!skipltgt) {
- lt_gt_eq = status_hilite_menu_choose_updownboth(fld, inbuf);
+ if (lt_gt_eq == NO_LTEQGT) {
+ boolean ltok = ((dt == ANY_INT)
+ ? (aval.a_int > 0 || fld == BL_AC)
+ : (aval.a_long > 0L)),
+ gtok = (!percent || aval.a_long < 100);
+
+ lt_gt_eq = status_hilite_menu_choose_updownboth(fld, inbuf,
+ ltok, gtok);
if (lt_gt_eq == NO_LTEQGT)
goto choose_value;
}
hilite.rel = lt_gt_eq;
hilite.value = aval;
} 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,
+ TRUE, TRUE);
if (lt_gt_eq == NO_LTEQGT)
goto choose_behavior;
Sprintf(colorqry, "Choose a color for when %s %s:",