fix #H6928 - monster vs closed door messaging

Report from roughly two and half years ago was about "<monster>
opens the door" without displaying <monster>.

Monster movement first decides whether a monster can pass closed
door.  If so, the monster is placed at the door spot, a message
is given about that movement (unlock, open, smash down, &c), and
finally the map is updated.

Changing the sequence to update the map before issuing the door
message was not sufficient to fix this.  In the corridor plus
closed door plus lit room map fragment shown here, when 'O' moved
to '+', you would see it there if the hero is at '1' or '2', but
not if at '3', '4', or '5'; open door was shown instead.  But the
message described 'O' accurately rather than as "it" for all those
hero locations.
:   -----
: #O+1...
:   |2...
:   |3...
:   |4...
:   |5...
:   -----

For 3,4,5 the #vision command shows the closed door as 3 before
the O move, but blank (0) after.  In other words, the closed door
is within line of sight but once opened, the doorway spot isn't.
It makes sense that the closed door behaves like a wall but I'm
not sure whether the behavior for an open door's breach does too.

I had an awful workaround that successfully displayed the monster,
but it wouldn't show the same thing if the door was already open,
so I've changed the situation to yield "You see a door open."
This commit is contained in:
PatR
2021-03-21 02:33:20 -07:00
parent fb7b7d5721
commit f209cac5f6
3 changed files with 34 additions and 33 deletions

View File

@@ -420,6 +420,8 @@ quivering a partial stack of gold succeeded and put the partial stack in an
if player managed to get multiple $ items, all but the last could be moved to
normal letter slots via #adjust and then subsequent #adjust with a
count could split them into even more slots
when a monster on the far side of a closed door opens it, sometimes the hero
was told about the monster without it being displayed on the map
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -1213,14 +1213,11 @@ wiz_show_vision(void)
putstr(win, 0, "");
for (y = 0; y < ROWNO; y++) {
for (x = 1; x < COLNO; x++) {
if (x == u.ux && y == u.uy)
if (x == u.ux && y == u.uy) {
row[x] = '@';
else {
} else {
v = g.viz_array[y][x]; /* data access should be hidden */
if (v == 0)
row[x] = ' ';
else
row[x] = '0' + g.viz_array[y][x];
row[x] = (v == 0) ? ' ' : ('0' + v);
}
}
/* remove trailing spaces */

View File

@@ -1315,7 +1315,8 @@ m_move(register struct monst* mtmp, register int after)
}
postmov:
if (mmoved == 1 || mmoved == 3) {
boolean canseeit = cansee(mtmp->mx, mtmp->my);
boolean canseeit = cansee(mtmp->mx, mtmp->my),
didseeit = canseeit;
if (mmoved == 1) {
/* normal monster move will already have <nix,niy>,
@@ -1364,8 +1365,18 @@ m_move(register struct monst* mtmp, register int after)
&& !passes_walls(ptr) /* doesn't need to open doors */
&& !can_tunnel) { /* taken care of below */
struct rm *here = &levl[mtmp->mx][mtmp->my];
boolean btrapped = (here->doormask & D_TRAPPED) != 0,
observeit = canseeit && canspotmon(mtmp);
boolean btrapped = (here->doormask & D_TRAPPED) != 0;
/* used after monster 'who' has been moved to closed door spot 'where'
which will now be changed to door state 'what' with map update */
#define UnblockDoor(where,who,what) \
do { \
(where)->doormask = (what); \
newsym((who)->mx, (who)->my); \
unblock_point((who)->mx, (who)->my); \
vision_recalc(0); \
/* update cached value since it might change */ \
canseeit = didseeit || cansee((who)->mx, (who)->my); \
} while (0)
/* if mon has MKoT, disarm door trap; no message given */
if (btrapped && has_magic_key(mtmp)) {
@@ -1384,15 +1395,17 @@ m_move(register struct monst* mtmp, register int after)
(ptr == &mons[PM_FOG_CLOUD]
|| ptr->mlet == S_LIGHT) ? "flows" : "oozes");
} else if (here->doormask & D_LOCKED && can_unlock) {
/* like the vampshift hack above, there are sequencing
issues when the monster is moved to the door's spot
first then door handling plus feedback comes after */
UnblockDoor(here, mtmp, !btrapped ? D_ISOPEN : D_NODOOR);
if (btrapped) {
here->doormask = D_NODOOR;
newsym(mtmp->mx, mtmp->my);
unblock_point(mtmp->mx, mtmp->my); /* vision */
if (mb_trapped(mtmp))
return 2;
} else {
if (flags.verbose) {
if (observeit)
if (canseeit && canspotmon(mtmp))
pline("%s unlocks and opens a door.",
Monnam(mtmp));
else if (canseeit)
@@ -1400,41 +1413,36 @@ m_move(register struct monst* mtmp, register int after)
else if (!Deaf)
You_hear("a door unlock and open.");
}
here->doormask = D_ISOPEN;
/* newsym(mtmp->mx, mtmp->my); */
unblock_point(mtmp->mx, mtmp->my); /* vision */
}
} else if (here->doormask == D_CLOSED && can_open) {
UnblockDoor(here, mtmp, !btrapped ? D_ISOPEN : D_NODOOR);
if (btrapped) {
here->doormask = D_NODOOR;
newsym(mtmp->mx, mtmp->my);
unblock_point(mtmp->mx, mtmp->my); /* vision */
if (mb_trapped(mtmp))
return 2;
} else {
if (flags.verbose) {
if (observeit)
if (canseeit && canspotmon(mtmp))
pline("%s opens a door.", Monnam(mtmp));
else if (canseeit)
You_see("a door open.");
else if (!Deaf)
You_hear("a door open.");
}
here->doormask = D_ISOPEN;
/* newsym(mtmp->mx, mtmp->my); */ /* done below */
unblock_point(mtmp->mx, mtmp->my); /* vision */
}
} else if (here->doormask & (D_LOCKED | D_CLOSED)) {
/* mfndpos guarantees this must be a doorbuster */
unsigned mask;
mask = ((btrapped || ((here->doormask & D_LOCKED) != 0
&& !rn2(2))) ? D_NODOOR
: D_BROKEN);
UnblockDoor(here, mtmp, mask);
if (btrapped) {
here->doormask = D_NODOOR;
newsym(mtmp->mx, mtmp->my);
unblock_point(mtmp->mx, mtmp->my); /* vision */
if (mb_trapped(mtmp))
return 2;
} else {
if (flags.verbose) {
if (observeit)
if (canseeit && canspotmon(mtmp))
pline("%s smashes down a door.",
Monnam(mtmp));
else if (canseeit)
@@ -1442,12 +1450,6 @@ m_move(register struct monst* mtmp, register int after)
else if (!Deaf)
You_hear("a door crash open.");
}
if ((here->doormask & D_LOCKED) != 0 && !rn2(2))
here->doormask = D_NODOOR;
else
here->doormask = D_BROKEN;
/* newsym(mtmp->mx, mtmp->my); */ /* done below */
unblock_point(mtmp->mx, mtmp->my); /* vision */
}
/* if it's a shop door, schedule repair */
if (*in_rooms(mtmp->mx, mtmp->my, SHOPBASE))