]> granicus.if.org Git - nethack/commitdiff
fix #H6928 - monster vs closed door messaging
authorPatR <rankin@nethack.org>
Sun, 21 Mar 2021 09:33:20 +0000 (02:33 -0700)
committerPatR <rankin@nethack.org>
Sun, 21 Mar 2021 09:33:20 +0000 (02:33 -0700)
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."

doc/fixes37.0
src/cmd.c
src/monmove.c

index 7583d74ae77cd3114dbd31835290dfe1822da61f..735acd131e48aa03f944b792c308ddc5c8803e0e 100644 (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
index 266b83afeed5b0fd89b759b0e963eb661c04d4c4..f05da5c71df2704c504b540b6aa638021dc9edbf 100644 (file)
--- 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 */
index 2442a5cd65e486b70835b66d872a34ade3dc56e1..7f70f4da6ddb62a8b726b4ebca8563bd30017c6e 100644 (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))