new composite status conditions: weaponstatus,\

armorstatus, and terrainstatus

This adds three special status items to show at a glance what the hero
is wielding, wearing, and standing on.

Each of the three items has its own boolean option rather than try to
fix them in with the existing opttional status conditions.  After a
lot of testing, I think the weapon and armor ones will prove useful
but the terrain one probably won't be.

Presently it is implemented for tty and curses.  When I developed it
six years ago, it was also working for X11 but I'm not able to test
the resurrection of that part so have left it out.
This commit is contained in:
PatR
2026-04-16 13:35:08 -07:00
parent 45e8305918
commit 84ddf85cb4
20 changed files with 659 additions and 72 deletions

View File

@@ -72,7 +72,9 @@ struct window_procs curses_procs = {
#endif
| WC2_FLUSH_STATUS | WC2_TERM_SIZE
| WC2_STATUSLINES | WC2_WINDOWBORDERS | WC2_PETATTR | WC2_GUICOLOR
| WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_MENU_SHIFT),
| WC2_SUPPRESS_HIST | WC2_URGENT_MESG | WC2_MENU_SHIFT
| WC2_EXTRASTATUS
),
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
curses_init_nhwindows,
curses_player_selection,

View File

@@ -254,12 +254,13 @@ draw_horizontal(boolean border)
/* almost all fields already come with a leading space;
"xspace" indicates places where we'll generate an extra one */
static const enum statusfields
twolineorder[3][16] = {
twolineorder[3][19] = {
{ BL_TITLE,
/*xspace*/ BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
/*xspace*/ BL_ALIGN,
/*xspace*/ BL_SCORE,
BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD },
BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD,
blPAD, blPAD, blPAD },
{ BL_LEVELDESC,
/*xspace*/ BL_GOLD,
/*xspace*/ BL_HP, BL_HPMAX,
@@ -267,32 +268,35 @@ draw_horizontal(boolean border)
/*xspace*/ BL_AC,
/*xspace*/ BL_XP, BL_EXP, BL_HD,
/*xspace*/ BL_TIME,
/*xspace*/ BL_HUNGER, BL_CAP, BL_CONDITION, BL_VERS,
/*xspace*/ BL_HUNGER, BL_CAP,
BL_WEAPON, BL_ARMOR, BL_TERRAIN, BL_CONDITION, BL_VERS,
BL_FLUSH },
{ BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD,
blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD }
blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD,
blPAD, blPAD, blPAD }
},
threelineorder[3][16] = { /* moves align to line 2, leveldesc+ to 3 */
threelineorder[3][19] = { /* moves align to line 2, leveldesc+ to 3 */
{ BL_TITLE,
/*xspace*/ BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
/*xspace*/ BL_SCORE,
BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD },
BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD,
blPAD, blPAD, blPAD },
{ BL_ALIGN,
/*xspace*/ BL_GOLD,
/*xspace*/ BL_HP, BL_HPMAX,
/*xspace*/ BL_ENE, BL_ENEMAX,
/*xspace*/ BL_AC,
/*xspace*/ BL_XP, BL_EXP, BL_HD,
/*xspace*/ BL_HUNGER, BL_CAP,
/*xspace*/ BL_HUNGER, BL_CAP, BL_WEAPON, BL_ARMOR, BL_TERRAIN,
BL_FLUSH, blPAD, blPAD, blPAD },
{ BL_LEVELDESC,
/*xspace*/ BL_TIME,
/*xspecial*/ BL_CONDITION,
/*xspecial*/ BL_VERS,
BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD,
blPAD, blPAD, blPAD, blPAD }
blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD }
};
const enum statusfields (*fieldorder)[16];
const enum statusfields (*fieldorder)[19];
coordxy spacing[MAXBLSTATS], valline[MAXBLSTATS];
enum statusfields fld, prev_fld;
char *text, *p, cbuf[BUFSZ], ebuf[STATVAL_WIDTH];
@@ -401,6 +405,9 @@ draw_horizontal(boolean border)
case BL_ENEMAX:
spacing[fld] = 0; /* no leading or extra space */
break;
case BL_WEAPON:
case BL_ARMOR:
case BL_TERRAIN:
case BL_DX:
case BL_CO:
case BL_IN:
@@ -705,16 +712,18 @@ draw_vertical(boolean border)
/* 6:blank (if any of hunger, encumbrance, or conditions appear) */
BL_HUNGER, BL_CAP, /* these two are shown on same line */
BL_CONDITION, /* shown three per line so may take up to four lines */
BL_WEAPON, BL_ARMOR, BL_TERRAIN, /* same line if 2, two lines if 3 */
/* 1:blank (bottom justified) */
BL_VERS,
BL_FLUSH
};
static const enum statusfields shrinkorder[] = {
BL_VERS, BL_STR, BL_SCORE, BL_TIME, BL_LEVELDESC, BL_HP,
BL_CONDITION, BL_CAP, BL_HUNGER
BL_VERS, BL_STR, BL_SCORE, BL_TIME, BL_LEVELDESC, BL_HP,
BL_TERRAIN, BL_ARMOR, BL_WEAPON,
BL_CONDITION, BL_CAP, BL_HUNGER
};
coordxy spacing[MAXBLSTATS];
int i, fld, cap_and_hunger, time_and_score, cond_count,
int i, fld, cap_and_hunger, time_and_score, cond_count, wep_arm_ter,
sho_vers, per_line;
char *text;
#ifdef STATUS_HILITES
@@ -758,6 +767,13 @@ draw_vertical(boolean border)
}
per_line = 2; /* will be changed to 3 if status becomes too tall */
sho_vers = (status_activefields[BL_VERS] ? 1 : 0);
wep_arm_ter = 0;
if (status_activefields[BL_WEAPON] && *status_vals_long[BL_WEAPON])
wep_arm_ter |= 1;
if (status_activefields[BL_ARMOR] && *status_vals_long[BL_ARMOR])
wep_arm_ter |= 2;
if (status_activefields[BL_TERRAIN] && *status_vals_long[BL_TERRAIN])
wep_arm_ter |= 4;
/* count how many lines we'll need; we normally space several groups of
fields with blank lines but might need to compress some of those out */
@@ -802,6 +818,32 @@ draw_vertical(boolean border)
if (cond_count > per_line)
height_needed += (cond_count - 1) / per_line;
break;
case BL_WEAPON:
/* two lines if no hunger or encumbrance and no conditions,
otherwise one line if weapon status being is shown */
spacing[fld] = ((wep_arm_ter & 1) == 1) /* show wep */
? ((!cond_count && !cap_and_hunger) ? 2 : 1)
: 0; /* no wep */
break;
case BL_ARMOR:
/* two lines if no hunger or encumbrance and no conditions
and no weapon status, otherwise one line if no weapon
status, else same line as weapon status */
spacing[fld] = ((wep_arm_ter & 3) == 2) /* show arm, no wep */
? ((!cond_count && !cap_and_hunger) ? 2 : 1)
: 0; /* wep and arm (on same line) or no arm */
break;
case BL_TERRAIN:
/* two lines if no hunger or encumbrance and no conditions
and no weapon status and no armor status, otherwise one
line if both weapon status and armor status or neither of
them and terrain status is being shown */
spacing[fld] = ((wep_arm_ter & 7) == 4) /* show ter, no wep|arm */
? ((!cond_count && !cap_and_hunger) ? 2 : 1)
/* if all three, put terrain on next line; else
same line for wep+ter or arm+ter or no ter */
: (((wep_arm_ter & 7) == 7) ? 1 : 0);
break;
case BL_VERS:
spacing[fld] = sho_vers ? 2 : 0;
break;
@@ -883,7 +925,11 @@ draw_vertical(boolean border)
the first (or only) and keep it for the second (if both) */
if (*text == ' '
&& (fld == BL_HUNGER
|| (fld == BL_CAP && cap_and_hunger != 3)))
|| (fld == BL_CAP && cap_and_hunger != 3)
|| fld == BL_WEAPON
|| (fld == BL_ARMOR && (wep_arm_ter & 3) == 2)
|| (fld == BL_TERRAIN && ((wep_arm_ter & 7) == 4
|| (wep_arm_ter & 7) == 7))))
++text;
#ifdef STATUS_HILITES
coloridx = curses_status_colors[fld]; /* includes attributes */
@@ -1239,6 +1285,9 @@ curs_vert_status_vals(int win_width)
case BL_EXP:
case BL_HUNGER:
case BL_CAP:
case BL_WEAPON:
case BL_ARMOR:
case BL_TERRAIN:
case BL_TITLE:
use_name = FALSE;
break;

View File

@@ -121,6 +121,7 @@ struct window_procs tty_procs = {
#if !defined(NO_TERMS) || defined(WIN32CON)
| WC2_EXTRACOLORS
#endif
| WC2_EXTRASTATUS
),
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* color availability */
tty_init_nhwindows, tty_player_selection, tty_askname, tty_get_nh_event,
@@ -4271,27 +4272,29 @@ static const char *const encvals[3][6] = {
{ "", "Brd", "Strs", "Strn", "Ovtx", "Ovld" }
};
#define blPAD BL_FLUSH
#define MAX_PER_ROW 16
#define MAX_PER_ROW 19
/* 2 or 3 status lines */
static const enum statusfields
twolineorder[3][MAX_PER_ROW] = {
{ BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_ALIGN,
BL_SCORE, BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD },
BL_SCORE, BL_FLUSH,
blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD },
{ BL_LEVELDESC, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER,
BL_CAP, BL_CONDITION, BL_VERS, BL_FLUSH },
BL_AC, BL_XP, BL_EXP, BL_HD, BL_TIME, BL_HUNGER, BL_CAP,
BL_CONDITION, BL_WEAPON, BL_ARMOR, BL_TERRAIN, BL_VERS, BL_FLUSH },
/* third row of array isn't used for twolineorder */
{ BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD,
blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD }
},
/* Align moved from 1 to 2, Leveldesc+Time+Cond+Vers moved from 2 to 3 */
threelineorder[3][MAX_PER_ROW] = {
{ BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
BL_SCORE, BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD },
{ BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH, BL_SCORE, BL_FLUSH,
blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD },
{ BL_ALIGN, BL_GOLD, BL_HP, BL_HPMAX, BL_ENE, BL_ENEMAX,
BL_AC, BL_XP, BL_EXP, BL_HD, BL_HUNGER,
BL_CAP, BL_FLUSH, blPAD, blPAD, blPAD },
{ BL_LEVELDESC, BL_TIME, BL_CONDITION, BL_VERS, BL_FLUSH, blPAD,
BL_AC, BL_XP, BL_EXP, BL_HD, BL_HUNGER, BL_CAP,
BL_FLUSH, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD },
{ BL_LEVELDESC, BL_TIME, BL_CONDITION, BL_WEAPON, BL_ARMOR, BL_TERRAIN,
BL_VERS, BL_FLUSH, blPAD,
blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD, blPAD }
};
static const enum statusfields (*fieldorder)[MAX_PER_ROW];
@@ -4378,7 +4381,8 @@ tty_status_enablefield(
* BL_TITLE, BL_STR, BL_DX, BL_CO, BL_IN, BL_WI, BL_CH,
* BL_ALIGN, BL_SCORE, BL_CAP, BL_GOLD, BL_ENE, BL_ENEMAX,
* BL_XP, BL_AC, BL_HD, BL_TIME, BL_HUNGER, BL_HP, BL_HPMAX,
* BL_LEVELDESC, BL_EXP, BL_CONDITION, BL_VERS
* BL_LEVELDESC, BL_EXP, BL_CONDITION,
* BL_WEAPON, BL_ARMOR, BL_TERRAIN, BL_VERS
* -- fldindex could also be BL_FLUSH (-1), which is not really
* a field index, but is a special trigger to tell the
* windowport that it should output all changes received
@@ -4748,7 +4752,8 @@ status_sanity_check(void)
"BL_ENE", "BL_ENEMAX", "BL_XP", "BL_AC", "BL_HD", /* 11..15 */
"BL_TIME", "BL_HUNGER", "BL_HP", "BL_HPMAX", /* 16..19 */
"BL_LEVELDESC", "BL_EXP", "BL_CONDITION", /* 20..22 */
"BL_VERS", /* 23 */
"BL_WEAPON", "BL_ARMOR", "BL_TERRAIN", /* 23..25 */
"BL_VERS", /* 26 */
};
static boolean in_sanity_check = FALSE;
int i;
@@ -4768,8 +4773,8 @@ status_sanity_check(void)
a corresponding expansion of idxtext[] here */
if (i < SIZE(idxtext))
Strcpy(indxtxt, idxtext[i]);
else
Sprintf(indxtxt, "%d", i);
else /* blstats[] increased without doing same for idxtext[] */
Sprintf(indxtxt, "#%d", i);
Sprintf(panicmsg, "failed on tty_status[NOW][%s].", indxtxt);
paniclog("status_sanity_check", panicmsg);
tty_status[NOW][i].sanitycheck = FALSE;