]> granicus.if.org Git - nethack/commitdiff
fix #H2642 - escaping from drowning by moving diagonally
authornethack.rankin <nethack.rankin>
Mon, 30 Apr 2012 21:25:05 +0000 (21:25 +0000)
committernethack.rankin <nethack.rankin>
Mon, 30 Apr 2012 21:25:05 +0000 (21:25 +0000)
     From a bug report, you could crawl
out of water to avoid drowning by moving diagonally into an intact doorway
even though regular movement won't allow that.  (Second version of Medusa's
level has a door adjacent to water.)  You could also escape diagonally when
polymorphed into a grid bug.

doc/fixes35.0
include/extern.h
src/hack.c
src/trap.c

index 6e92e6f5e7ec84b9c45584274c62645b1e5b0f49..5badb34e980f9cd66a76c2dd48241aaf060f52b1 100644 (file)
@@ -832,6 +832,7 @@ adjust turning-to-stone or -slime messages when you have no limbs
 wizard mode ^F on Plane of Water marked portal as seen but didn't display it
 magic mapping now displays furniture in preference to known or remembered traps
        or objects and known traps in preference to remembered objects
+restrictions on diagonal movement were ignored when crawling out of water
 
 
 Platform- and/or Interface-Specific Fixes
index c40260a0708c2dff490aef1a54b60b0948f17c23..bb279fd7fa95c95e25190f674da169237509d615 100644 (file)
@@ -810,6 +810,7 @@ E boolean FDECL(in_town, (int,int));
 E void FDECL(check_special_room, (BOOLEAN_P));
 E int NDECL(dopickup);
 E void NDECL(lookaround);
+E boolean FDECL(crawl_destination, (int,int));
 E int NDECL(monster_nearby);
 E void FDECL(nomul, (int));
 E void FDECL(unmul, (const char *));
index ed56ac9eef8b393dceae419c38e22ad314830e8e..2899a931227d69f624e19c2d99c086b05d8eaba6 100644 (file)
@@ -2390,6 +2390,28 @@ int x, y;
     return !(lev_p->doormask & ~(D_NODOOR|D_BROKEN));
 }
 
+/* used by drown() to check whether hero can crawl from water to <x,y> */
+boolean
+crawl_destination(x, y)
+int x, y;
+{
+    /* is location ok in general? */
+    if (!goodpos(x, y, &youmonst, 0)) return FALSE;
+
+    /* orthogonal movement is unrestricted when destination is ok */
+    if (x == u.ux || y == u.uy) return TRUE;
+
+    /* diagonal movement has some restrictions */
+    if (NODIAG(u.umonnum)) return FALSE;       /* poly'd into a grid bug... */
+    if (Passes_walls) return TRUE;             /* or a xorn... */
+    /* pool could be next to a door, conceivably even inside a shop */
+    if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
+       return FALSE;
+    /* finally, are we trying to squeeze through a too-narrow gap? */
+    return !(bad_rock(youmonst.data, u.ux, y) &&
+            bad_rock(youmonst.data, x, u.uy));
+}
+
 /* something like lookaround, but we are not running */
 /* react only to monsters that might hit us */
 int
index ce41423de1af0f682866893ecf64c243c49fb282..2b9a9fe704e70a6e4d1a55ceb33fdb232ca144ad 100644 (file)
@@ -8,8 +8,8 @@ extern const char * const destroy_strings[][3]; /* from zap.c */
 
 STATIC_DCL void FDECL(dofiretrap, (struct obj *));
 STATIC_DCL void NDECL(domagictrap);
-STATIC_DCL boolean FDECL(emergency_disrobe,(boolean *));
-STATIC_DCL int FDECL(untrap_prob, (struct trap *ttmp));
+STATIC_DCL boolean FDECL(emergency_disrobe, (boolean *));
+STATIC_DCL int FDECL(untrap_prob, (struct trap *));
 STATIC_DCL void FDECL(move_into_trap, (struct trap *));
 STATIC_DCL int FDECL(try_disarm, (struct trap *,BOOLEAN_P));
 STATIC_DCL void FDECL(reward_untrap, (struct trap *, struct monst *));
@@ -3376,7 +3376,7 @@ drown()
        for (i = 0; i < 100; i++) {
                x = rn1(3,u.ux - 1);
                y = rn1(3,u.uy - 1);
-               if (goodpos(x, y, &youmonst, 0)) {
+               if (crawl_destination(x, y)) {
                        crawl_ok = TRUE;
                        goto crawl;
                }
@@ -3384,7 +3384,7 @@ drown()
        /* one more scan */
        for (x = u.ux - 1; x <= u.ux + 1; x++)
                for (y = u.uy - 1; y <= u.uy + 1; y++)
-                       if (goodpos(x, y, &youmonst, 0)) {
+                       if (crawl_destination(x, y)) {
                                crawl_ok = TRUE;
                                goto crawl;
                        }