Accessibility: Add location info to messages

Adds a new boolean option, accessiblemsg.  If on, some game messages
are prefixed with direction or location information, for example:

   (west): The newt bites!
   (northwest): You find a hidden door.

I added the info to the most common messages, but several are
still missing it.
This commit is contained in:
Pasi Kallinen
2024-01-01 18:19:17 +02:00
parent d86e6e9717
commit dc8d9d6cd0
18 changed files with 138 additions and 29 deletions

View File

@@ -104,6 +104,7 @@ const schar dirs_ord[N_DIRS] =
NEARDATA boolean has_strong_rngseed = FALSE;
struct engr *head_engr;
NEARDATA struct instance_flags iflags;
NEARDATA struct accessibility_data a11y;
/* NOTE: the order of these words exactly corresponds to the
order of oc_material values #define'd in objclass.h. */
const char *materialnm[] = { "mysterious", "liquid", "wax", "organic",
@@ -1057,6 +1058,7 @@ decl_globals_init(void)
ZERO(flags);
ZERO(iflags);
ZERO(a11y);
ZERO(u);
ZERO(ubirthday);
ZERO(urealtime);

View File

@@ -1824,6 +1824,7 @@ find_trap(struct trap *trap)
cleared = TRUE;
}
set_msg_xy(trap->tx, trap->ty);
You("find %s.", an(trapname(trap->ttyp, FALSE)));
if (cleared) {
@@ -1852,6 +1853,7 @@ mfind0(struct monst *mtmp, boolean via_warning)
|| hides_under(mtmp->data)
|| mtmp->data->mlet == S_EEL)) {
if (via_warning && found_something) {
set_msg_xy(x, y);
Your("danger sense causes you to take a second %s.",
Blind ? "to check nearby" : "look close by");
display_nhwindow(WIN_MESSAGE, FALSE); /* flush messages */
@@ -1871,8 +1873,10 @@ mfind0(struct monst *mtmp, boolean via_warning)
exercise(A_WIS, TRUE);
if (!canspotmon(mtmp)) {
map_invisible(x, y);
set_msg_xy(x, y);
You_feel("an unseen monster!");
} else if (!sensemon(mtmp)) {
set_msg_xy(x, y);
You("find %s.", mtmp->mtame ? y_monnam(mtmp) : a_monnam(mtmp));
}
return 1;
@@ -1914,6 +1918,7 @@ dosearch0(int aflag) /* intrinsic autosearch vs explicit searching */
exercise(A_WIS, TRUE);
nomul(0);
feel_location(x, y); /* make sure it shows up */
set_msg_xy(x, y);
You("find a hidden door.");
} else if (levl[x][y].typ == SCORR) {
if (rnl(7 - fund))
@@ -1923,6 +1928,7 @@ dosearch0(int aflag) /* intrinsic autosearch vs explicit searching */
exercise(A_WIS, TRUE);
nomul(0);
feel_newsym(x, y); /* make sure it shows up */
set_msg_xy(x, y);
You("find a hidden passage.");
} else {
/* Be careful not to find anything in an SCORR or SDOOR */

View File

@@ -437,7 +437,7 @@ dog_invent(struct monst *mtmp, struct edog *edog, int udist)
char *otmpname = distant_name(otmp, doname);
if (flags.verbose)
pline("%s picks up %s.",
pline_xy(omx, omy, "%s picks up %s.",
Monnam(mtmp), otmpname);
}
obj_extract_self(otmp);

View File

@@ -976,7 +976,7 @@ test_move(
Sprintf(buf, "solid stone");
else
Sprintf(buf, "%s", an(firstmatch));
pline("It's %s.", buf);
pline_dir(xytod(dx, dy), "It's %s.", buf);
}
}
return FALSE;
@@ -1116,7 +1116,7 @@ test_move(
if (mode != TEST_TRAV && gc.context.run >= 2
&& !(Blind || Hallucination) && !could_move_onto_boulder(x, y)) {
if (mode == DO_MOVE && flags.mention_walls)
pline("A boulder blocks your path.");
pline_dir(xytod(dx,dy), "A boulder blocks your path.");
return FALSE;
}
if (mode == DO_MOVE) {
@@ -2194,9 +2194,11 @@ avoid_moving_on_trap(coordxy x, coordxy y, boolean msg)
struct trap *trap;
if ((trap = t_at(x, y)) && trap->tseen) {
if (msg && flags.mention_walls)
if (msg && flags.mention_walls) {
set_msg_xy(x, y);
You("stop in front of %s.",
an(trapname(trap->ttyp, FALSE)));
}
return TRUE;
}
return FALSE;
@@ -2222,9 +2224,11 @@ avoid_moving_on_liquid(
polyforms are allowed to move over water */
return FALSE; /* liquid is safe to traverse */
} else if (is_pool_or_lava(x, y) && levl[x][y].seenv) {
if (msg && flags.mention_walls)
if (msg && flags.mention_walls) {
set_msg_xy(x, y);
You("stop at the edge of the %s.",
hliquid(is_pool(x,y) ? "water" : "lava"));
}
return TRUE;
}
return FALSE;
@@ -3522,7 +3526,7 @@ lookaround(void)
if ((gc.context.run != 1 && !is_safemon(mtmp))
|| (infront && !gc.context.travel)) {
if (flags.mention_walls)
pline("%s blocks your path.",
pline_xy(x, y, "%s blocks your path.",
upstart(a_monnam(mtmp)));
goto stop;
}
@@ -3553,8 +3557,10 @@ lookaround(void)
if (x != u.ux && y != u.uy)
continue;
if (gc.context.run != 1 && !gc.context.travel) {
if (flags.mention_walls)
if (flags.mention_walls) {
set_msg_xy(x, y);
You("stop in front of the door.");
}
goto stop;
}
/* we're orthogonal to a closed door, consider it a corridor */

View File

@@ -860,6 +860,7 @@ doopen_indir(coordxy x, coordxy y)
locked = TRUE;
break;
}
set_msg_xy(cc.x, cc.y);
pline("This door%s.", mesg);
if (locked && flags.autounlock) {
struct obj *unlocktool;
@@ -887,6 +888,7 @@ doopen_indir(coordxy x, coordxy y)
/* door is known to be CLOSED */
if (rnl(20) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) {
set_msg_xy(cc.x, cc.y);
pline_The("door opens.");
if (door->doormask & D_TRAPPED) {
b_trapped("door", FINGER);
@@ -899,6 +901,7 @@ doopen_indir(coordxy x, coordxy y)
unblock_point(cc.x, cc.y); /* vision: new see through there */
} else {
exercise(A_STR, TRUE);
set_msg_xy(cc.x, cc.y);
pline_The("door resists!");
}

View File

@@ -63,7 +63,8 @@ cursetxt(struct monst *mtmp, boolean undirected)
else
point_msg = "at you, then curses";
pline("%s points %s.", Monnam(mtmp), point_msg);
pline_xy(mtmp->mx, mtmp->my,
"%s points %s.", Monnam(mtmp), point_msg);
} else if ((!(gm.moves % 4) || !rn2(4))) {
if (!Deaf)
Norep("You hear a mumbled curse."); /* Deaf-aware */
@@ -238,7 +239,7 @@ castmu(
penalizing mspec_used. */
if (!foundyou && thinks_it_foundyou
&& !is_undirected_spell(mattk->adtyp, spellnum)) {
pline("%s casts a spell at %s!",
pline_xy(mtmp->mx, mtmp->my, "%s casts a spell at %s!",
canseemon(mtmp) ? Monnam(mtmp) : "Something",
is_waterwall(mtmp->mux,mtmp->muy) ? "empty water"
: "thin air");
@@ -248,12 +249,14 @@ castmu(
nomul(0);
if (rn2(ml * 10) < (mtmp->mconf ? 100 : 20)) { /* fumbled attack */
Soundeffect(se_air_crackles, 60);
if (canseemon(mtmp) && !Deaf)
if (canseemon(mtmp) && !Deaf) {
set_msg_xy(mtmp->mx, mtmp->my);
pline_The("air crackles around %s.", mon_nam(mtmp));
}
return M_ATTK_MISS;
}
if (canspotmon(mtmp) || !is_undirected_spell(mattk->adtyp, spellnum)) {
pline("%s casts a spell%s!",
pline_xy(mtmp->mx, mtmp->my, "%s casts a spell%s!",
canspotmon(mtmp) ? Monnam(mtmp) : "Something",
is_undirected_spell(mattk->adtyp, spellnum)
? ""

View File

@@ -35,7 +35,7 @@ hitmsg(struct monst *mtmp, struct attack *mattk)
if same gender, "engagingly" for nymph, normal msg for others. */
if ((compat = could_seduce(mtmp, &gy.youmonst, mattk)) != 0
&& !mtmp->mcan && !mtmp->mspec_used) {
pline("%s %s you %s.", Monst_name,
pline_xy(mtmp->mx, mtmp->my, "%s %s you %s.", Monst_name,
!Blind ? "smiles at" : !Deaf ? "talks to" : "touches",
(compat == 2) ? "engagingly" : "seductively");
} else {
@@ -73,7 +73,7 @@ hitmsg(struct monst *mtmp, struct attack *mattk)
&& gh.hitmsg_prev != NULL
&& mattk == gh.hitmsg_prev + 1
&& mattk->aatyp == gh.hitmsg_prev->aatyp) ? " again" : "";
pline("%s %s%s%s", Monst_name, verb, again, punct);
pline_xy(mtmp->mx, mtmp->my, "%s %s%s%s", Monst_name, verb, again, punct);
}
gh.hitmsg_mid = mtmp->m_id;
gh.hitmsg_prev = mattk;
@@ -90,9 +90,9 @@ missmu(struct monst *mtmp, boolean nearmiss, struct attack *mattk)
map_invisible(mtmp->mx, mtmp->my);
if (could_seduce(mtmp, &gy.youmonst, mattk) && !mtmp->mcan)
pline("%s pretends to be friendly.", Monnam(mtmp));
pline_xy(mtmp->mx, mtmp->my, "%s pretends to be friendly.", Monnam(mtmp));
else
pline("%s %smisses!", Monnam(mtmp),
pline_xy(mtmp->mx, mtmp->my, "%s %smisses!", Monnam(mtmp),
(nearmiss && flags.verbose) ? "just " : "");
stop_occupation();
@@ -132,7 +132,7 @@ mswings(
boolean bash) /* True: polearm used at too close range */
{
if (flags.verbose && !Blind && mon_visible(mtmp)) {
pline("%s %s %s%s %s.", Monnam(mtmp), mswings_verb(otemp, bash),
pline_xy(mtmp->mx, mtmp->my, "%s %s %s%s %s.", Monnam(mtmp), mswings_verb(otemp, bash),
(otemp->quan > 1L) ? "one of " : "", mhis(mtmp), xname(otemp));
}
}
@@ -198,6 +198,7 @@ wildmiss(struct monst *mtmp, struct attack *mattk)
? could_seduce(mtmp, &gy.youmonst, mattk) : 0);
Monst_name = Monnam(mtmp);
set_msg_xy(mtmp->mx, mtmp->my);
if (unotseen) { /* !mtmp->cansee || (Invis && !perceives(mtmp->data)) */
const char *swings = (mattk->aatyp == AT_BITE) ? "snaps"
: (mattk->aatyp == AT_KICK) ? "kicks"

View File

@@ -1606,8 +1606,9 @@ mpickgold(register struct monst* mtmp)
add_to_minv(mtmp, gold);
if (cansee(mtmp->mx, mtmp->my)) {
if (flags.verbose && !mtmp->isgd)
pline("%s picks up some %s.", Monnam(mtmp),
mat_idx == GOLD ? "gold" : "money");
pline_xy(mtmp->mx, mtmp->my,
"%s picks up some %s.", Monnam(mtmp),
mat_idx == GOLD ? "gold" : "money");
newsym(mtmp->mx, mtmp->my);
}
}
@@ -1666,7 +1667,8 @@ mpickstuff(struct monst *mtmp)
char *otmpname = distant_name(otmp, doname);
if (flags.verbose)
pline("%s picks up %s.", Monnam(mtmp), otmpname);
pline_xy(mtmp->mx, mtmp->my,
"%s picks up %s.", Monnam(mtmp), otmpname);
}
obj_extract_self(otmp3); /* remove from floor */
(void) mpickobj(mtmp, otmp3); /* may merge and free otmp3 */

View File

@@ -1023,7 +1023,7 @@ thrwmu(struct monst* mtmp)
if (canseemon(mtmp)) {
onm = xname(otmp);
pline("%s %s %s.", Monnam(mtmp),
pline_xy(mtmp->mx, mtmp->my, "%s %s %s.", Monnam(mtmp),
/* "thrusts" or "swings", or "bashes with" if adjacent */
mswings_verb(otmp, (rang <= 2) ? TRUE : FALSE),
obj_is_pname(otmp) ? the(onm) : an(onm));

View File

@@ -92,6 +92,47 @@ pline(const char *line, ...)
va_end(the_args);
}
void
pline_dir(int dir, const char *line, ...)
{
va_list the_args;
set_msg_dir(dir);
va_start(the_args, line);
vpline(line, the_args);
va_end(the_args);
}
void
pline_xy(coordxy x, coordxy y, const char *line, ...)
{
va_list the_args;
set_msg_xy(x, y);
va_start(the_args, line);
vpline(line, the_args);
va_end(the_args);
}
/* set the direction where next message happens */
void
set_msg_dir(int dir)
{
dtoxy(&a11y.msg_loc, dir);
a11y.msg_loc.x += u.ux;
a11y.msg_loc.y += u.uy;
}
/* set the coordinate where next message happens */
void
set_msg_xy(coordxy x, coordxy y)
{
a11y.msg_loc.x = x;
a11y.msg_loc.y = y;
}
static void
vpline(const char *line, va_list the_args)
{
@@ -110,6 +151,24 @@ vpline(const char *line, va_list the_args)
if (gp.program_state.wizkit_wishing)
return;
if (a11y.accessiblemsg && isok(a11y.msg_loc.x,a11y.msg_loc.y)) {
char *tmp;
char *dirstr;
static char dirstrbuf[BUFSZ];
int g = (iflags.getpos_coords == GPCOORDS_NONE)
? GPCOORDS_COMFULL : iflags.getpos_coords;
dirstr = coord_desc(a11y.msg_loc.x, a11y.msg_loc.y, dirstrbuf, g);
a11y.msg_loc.x = a11y.msg_loc.y = 0;
tmp = (char *)alloc(strlen(line) + sizeof ": " + strlen(dirstr));
Strcpy(tmp, dirstr);
Strcat(tmp, ": ");
Strcat(tmp, line);
vpline(tmp, the_args);
free((genericptr_t) tmp);
return;
}
if (!strchr(line, '%')) {
/* format does not specify any substitutions; use it as-is */
ln = (int) strlen(line);

View File

@@ -758,7 +758,7 @@ mdrop_obj(
}
/* obj_no_longer_held(obj); -- done by place_object */
if (verbosely && cansee(omx, omy))
pline("%s drops %s.", Monnam(mon), obj_name);
pline_xy(mon->mx, mon->my, "%s drops %s.", Monnam(mon), obj_name);
if (!flooreffects(obj, omx, omy, "fall")) {
place_object(obj, omx, omy);
stackobj(obj);

View File

@@ -1808,7 +1808,8 @@ trapeffect_pit(
/* openfallingtrap; not inescapable here */
if (in_sight) {
seetrap(trap);
pline("%s doesn't fall into the pit.", Monnam(mtmp));
pline_xy(mtmp->mx, mtmp->my,
"%s doesn't fall into the pit.", Monnam(mtmp));
}
return Trap_Effect_Finished;
}
@@ -1819,8 +1820,9 @@ trapeffect_pit(
if (!passes_walls(mptr))
mtmp->mtrapped = 1;
if (in_sight) {
pline("%s %s into %s pit!", Monnam(mtmp), fallverb,
a_your[trap->madeby_u]);
pline_xy(mtmp->mx, mtmp->my,
"%s %s into %s pit!", Monnam(mtmp), fallverb,
a_your[trap->madeby_u]);
if (mptr == &mons[PM_PIT_VIPER]
|| mptr == &mons[PM_PIT_FIEND])
pline("How pitiful. Isn't that the pits?");
@@ -1872,18 +1874,20 @@ trapeffect_hole(
if (in_sight) {
seetrap(trap);
if (tt == TRAPDOOR)
pline(
pline_xy(mtmp->mx, mtmp->my,
"A trap door opens, but %s doesn't fall through.",
mon_nam(mtmp));
else /* (tt == HOLE) */
pline("%s doesn't fall through the hole.",
Monnam(mtmp));
pline_xy(mtmp->mx, mtmp->my,
"%s doesn't fall through the hole.",
Monnam(mtmp));
}
return Trap_Effect_Finished; /* inescapable = FALSE; */
}
if (inescapable) { /* sokoban hole */
if (in_sight) {
pline("%s seems to be yanked down!", Monnam(mtmp));
pline_xy(mtmp->mx, mtmp->my,
"%s seems to be yanked down!", Monnam(mtmp));
/* suppress message in mlevel_tele_trap() */
in_sight = FALSE;
seetrap(trap);

View File

@@ -4761,7 +4761,7 @@ dobuzz(
goto buzzmonst;
} else if (zap_hit((int) u.uac, 0)) {
range -= 2;
pline("%s hits you!", The(flash_str(fltyp, FALSE)));
pline_dir(xytod(-dx,-dy), "%s hits you!", The(flash_str(fltyp, FALSE)));
if (Reflecting) {
if (!Blind) {
(void) ureflects("But %s reflects from your %s!",