]> granicus.if.org Git - nethack/commitdiff
Allow travel on water with IDed water walking
authorMichael Meyer <me@entrez.cc>
Thu, 30 Jun 2022 18:09:16 +0000 (14:09 -0400)
committerPatR <rankin@nethack.org>
Sat, 2 Jul 2022 22:10:54 +0000 (15:10 -0700)
If you have a known source of water walking (i.e. are wearing formally
IDed water walking boots), allow travel to path you over water and allow
running over water.  A transition from land to water will still cause
the hero to stop in modes other than the shift+dir "move until you hit
something" running mode, so that you don't careen across the entire
level unless you really want to.

Also, fix running over water when levitation or flying is equipped.
This stopped working after f88dce6970, only allowing the hero to move
one square at a time.  And prevent travel from pathing the hero into a
wall of water even if flying or levitation is equipped, since they don't
allow you to bypass that terrain.

src/hack.c

index 86d6f1c7be1385f91de60833e0abd8455edab715..9c66dd8be706b843cce2aa4e3c59b86876ea1710 100644 (file)
@@ -39,6 +39,16 @@ static void maybe_wail(void);
 
 #define IS_SHOP(x) (g.rooms[x].rtype >= SHOPBASE)
 
+/* XXX: if more sources of water walking than just boots are added,
+   cause_known(insight.c) should be externified and used for this */
+#define Known_wwalking \
+    (uarmf && uarmf->otyp == WATER_WALKING_BOOTS \
+     && objects[WATER_WALKING_BOOTS].oc_name_known \
+     && !u.usteed)
+#define Known_lwalking \
+    (Known_wwalking && Fire_resistance \
+     && uarmf->oerodeproof && uarmf->rknown)
+
 /* mode values for findtravelpath() */
 #define TRAVP_TRAVEL 0
 #define TRAVP_GUESS  1
@@ -1028,8 +1038,10 @@ test_move(coordxy ux, coordxy uy, coordxy dx, coordxy dy, int mode)
         struct trap *t = t_at(x, y);
 
         if ((t && t->tseen)
-            || (!Levitation && !Flying && !is_clinger(g.youmonst.data)
-                && is_pool_or_lava(x, y) && levl[x][y].seenv))
+            || (!Levitation && !Flying && !Known_lwalking
+                && !(is_pool(x, y) && Known_wwalking)
+                && is_pool_or_lava(x, y) && levl[x][y].seenv)
+            || (IS_WATERWALL(levl[x][y].typ) && levl[x][y].seenv))
             return (mode == TEST_TRAP);
     }
 
@@ -1593,19 +1605,13 @@ swim_move_danger(coordxy x, coordxy y)
     if ((newtyp != u_simple_floortyp(u.ux, u.uy))
         && !Stunned && !Confusion && levl[x][y].seenv
         && (is_pool(x, y) || is_lava(x, y) || liquid_wall)) {
-        boolean known_wwalking, known_lwalking;
 
-        known_wwalking = (uarmf && uarmf->otyp == WATER_WALKING_BOOTS
-                          && objects[WATER_WALKING_BOOTS].oc_name_known
-                          && !u.usteed);
-        known_lwalking = (known_wwalking && Fire_resistance &&
-                          uarmf->oerodeproof && uarmf->rknown);
         /* FIXME: This can be exploited to identify the ring of fire resistance
         * if the player is wearing it unidentified and has identified
         * fireproof boots of water walking and is walking over lava. However,
         * this is such a marginal case that it may not be worth fixing. */
-        if ((is_pool(x, y) && !known_wwalking)
-            || (is_lava(x, y) && !known_lwalking)
+        if ((is_pool(x, y) && !Known_wwalking)
+            || (is_lava(x, y) && !Known_lwalking)
             || liquid_wall) {
             if (g.context.nopick) {
                 /* moving with m-prefix */
@@ -2063,8 +2069,14 @@ avoid_moving_on_trap(coordxy x, coordxy y, boolean msg)
 static boolean
 avoid_moving_on_liquid(coordxy x, coordxy y, boolean msg)
 {
-    if (!Levitation && !Flying && !is_clinger(g.youmonst.data)
-        && is_pool_or_lava(x, y) && levl[x][y].seenv) {
+    if ((g.context.run < 2 || g.context.travel || is_pool_or_lava(u.ux, u.uy))
+        && (Levitation || Flying || Known_lwalking
+            || (is_pool(x, y) && Known_wwalking))
+        && !IS_WATERWALL(levl[x][y].typ)) {
+        /* XXX: should send 'is_clinger(g.youmonst.data)' here once clinging
+           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)
             You("stop at the edge of the %s.",
                 hliquid(is_pool(x,y) ? "water" : "lava"));
@@ -3340,8 +3352,8 @@ lookaround(void)
                 if (infront)
                     goto stop;
                 continue;
-            } else if (avoid_moving_on_liquid(x, y, infront)) {
-                if (infront)
+            } else if (is_pool_or_lava(x, y)) {
+                if (infront && avoid_moving_on_liquid(x, y, TRUE))
                     goto stop;
                 continue;
             } else { /* e.g. objects or trap or stairs */