]> granicus.if.org Git - nethack/commitdiff
Fix stuck travel for good
authorPasi Kallinen <paxed@alt.org>
Sat, 2 Apr 2022 15:16:19 +0000 (18:16 +0300)
committerPasi Kallinen <paxed@alt.org>
Sat, 2 Apr 2022 15:27:53 +0000 (18:27 +0300)
My fixes to the travel stuck oscillation did not fix all of them,
and I've even seen a 3-step loop - which my fixes cannot detect.
I guess there could be arbitrary-sized loops too.

To definitely fix this, keep track of all the map locations travel
has moved the hero through, and if it tries to go on a location already
used, stop travel and give the unsure -message.

include/decl.h
src/allmain.c
src/cmd.c
src/decl.c
src/hack.c

index 4b69f03f852f52895f7477968b78f98d22c293b8..c0a50aff3eaf112441c96c2c7b447710e4f52ea2 100644 (file)
@@ -938,6 +938,7 @@ struct instance_globals {
     /* hack.c */
     anything tmp_anything;
     int wc; /* current weight_cap(); valid after call to inv_weight() */
+    struct selectionvar *travelmap;
 
     /* insight.c */
 
index d13d86160cad195813957cd539203d0000387e45..2b637509bd7c54995d8692b6fe39bfed28d7fc14 100644 (file)
@@ -466,8 +466,7 @@ moveloop_core(void)
         }
         if (g.context.mv) {
             if (g.multi < COLNO && !--g.multi)
-                g.context.travel = g.context.travel1 = g.context.mv =
-                    g.context.run = 0;
+                end_running(TRUE);
             domove();
         } else {
             --g.multi;
index d5a6d642d99c704dfb6b62527b6b1848c3964aa4..2821bab5d265db946b46eb27253f002f0f162f0f 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -3855,6 +3855,10 @@ reset_cmd_vars(boolean reset_cmdq)
     g.multi = 0;
     iflags.menu_requested = FALSE;
     g.context.travel = g.context.travel1 = 0;
+    if (g.travelmap) {
+        selection_free(g.travelmap, TRUE);
+        g.travelmap = NULL;
+    }
     if (reset_cmdq)
         cmdq_clear();
 }
index 8a17770840fc7692c1a1d4878d790bda07141b1b..88602704cfdc751ca857be4695eb9aa708119402 100644 (file)
@@ -422,8 +422,9 @@ const struct instance_globals g_init = {
 
 
     /* hack.c */
-    UNDEFINED_VALUES,
-    UNDEFINED_VALUE,
+    UNDEFINED_VALUES, /* tmp_anything */
+    UNDEFINED_VALUE, /* wc */
+    NULL, /* travelmap */
 
     /* invent.c */
     51, /* lastinvr */
index 4096bc71b81f446593c902a5211c69e2b405056d..e10c2a14433e5ee63ec4e27854ce5290bc673f28 100644 (file)
@@ -1094,10 +1094,14 @@ test_move(int ux, int uy, int dx, int dy, int mode)
  * A shortest path is returned.  If guess is TRUE, consider various
  * inaccessible locations as valid intermediate path points.
  * Returns TRUE if a path was found.
+ * g.travelmap keeps track of map locations we've moved through
+ * this travel session. It will be cleared once the travel stops.
  */
 static boolean
 findtravelpath(int mode)
 {
+    if (!g.travelmap)
+        g.travelmap = selection_new();
     /* if travel to adjacent, reachable location, use normal movement rules */
     if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && g.context.travel1
         /* was '&& distmin(u.ux, u.uy, u.tx, u.ty) == 1' */
@@ -1126,7 +1130,6 @@ findtravelpath(int mode)
         int set = 0;    /* two sets current and previous */
         int radius = 1; /* search radius */
         int i;
-        xchar guessx = -1, guessy = -1;
 
         /* If guessing, first find an "obvious" goal location.  The obvious
          * goal is the position the player knows of, or might figure out
@@ -1229,19 +1232,21 @@ findtravelpath(int mode)
                             || (!Blind && couldsee(nx, ny)))) {
                         if (nx == ux && ny == uy) {
                             if (mode == TRAVP_TRAVEL || mode == TRAVP_VALID) {
+                                boolean visited =
+                                    selection_getpoint(x, y, g.travelmap);
                                 u.dx = x - ux;
                                 u.dy = y - uy;
                                 if (mode == TRAVP_TRAVEL
-                                    && ((x == u.tx && y == u.ty)
-                                        || (x == guessx && y == guessy))) {
+                                    && ((x == u.tx && y == u.ty) || visited)) {
                                     nomul(0);
                                     /* reset run so domove run checks work */
                                     g.context.run = 8;
-                                    if (x == guessx && y == guessy)
+                                    if (visited)
                                         You("stop, unsure which way to go.");
                                     else
                                         iflags.travelcc.x = iflags.travelcc.y = 0;
                                 }
+                                selection_setpoint(u.ux, u.uy, g.travelmap, 1);
                                 return TRUE;
                             }
                         } else if (!travel[nx][ny]) {
@@ -1309,8 +1314,10 @@ findtravelpath(int mode)
                 /* no guesses, just go in the general direction */
                 u.dx = sgn(u.tx - u.ux);
                 u.dy = sgn(u.ty - u.uy);
-                if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
+                if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE)) {
+                    selection_setpoint(u.ux, u.uy, g.travelmap, 1);
                     return TRUE;
+                }
                 goto found;
             }
 #ifdef DEBUG
@@ -1332,8 +1339,6 @@ findtravelpath(int mode)
             ty = py;
             ux = u.ux;
             uy = u.uy;
-            guessx = u.ux - u.dx;
-            guessy = u.uy - u.dy;
             set = 0;
             n = radius = 1;
             mode = TRAVP_TRAVEL;
@@ -3439,7 +3444,11 @@ end_running(boolean and_travel)
        all clear it too */
     if (and_travel)
         g.context.travel = g.context.travel1 = g.context.mv = 0;
-    /* cancel mutli */
+    if (g.travelmap) {
+        selection_free(g.travelmap, TRUE);
+        g.travelmap = NULL;
+    }
+    /* cancel multi */
     if (g.multi > 0)
         g.multi = 0;
 }