Fix stuck travel for good

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.
This commit is contained in:
Pasi Kallinen
2022-04-02 18:16:19 +03:00
parent fd355d6f6c
commit 6977aef436
5 changed files with 26 additions and 12 deletions

View 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 */

View 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;

View File

@@ -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();
}

View 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 */

View 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;
}