From: PatR Date: Sun, 21 Mar 2021 09:33:20 +0000 (-0700) Subject: fix #H6928 - monster vs closed door messaging X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f209cac5f6c9318a5f9d45ee5b5995bc09ee7a47;p=nethack fix #H6928 - monster vs closed door messaging Report from roughly two and half years ago was about " opens the door" without displaying . 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." --- diff --git a/doc/fixes37.0 b/doc/fixes37.0 index 7583d74ae..735acd131 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/src/cmd.c b/src/cmd.c index 266b83afe..f05da5c71 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -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 */ diff --git a/src/monmove.c b/src/monmove.c index 2442a5cd6..7f70f4da6 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -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 , @@ -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))