There's been occasional reports (perhaps once or twice a year)
of travel getting stuck moving repeatedly between two locations
next to each other, but it has never been reproduced before.
This special level lua code fragment is a minimal test case
which triggers it:
--- special level lua fragment, indented
des.map([[
--##---
###----
#-+----
####--L
]]);
des.door("open", 2,2)
--- end of special level lua fragment
The open door is required.
Magic map the level. Start from somewhere NW of the door, and try
to travel to the lava pool. Hero will get stuck oscillating between NW
of the door and two steps west of the door.
Here are the maps of the travel[][] array values from findtravelpath()
in those two steps in the above map:
------------- -------------
| . . 2 3 | | . . 1 2 |
| 1 1 2 . | | 1 @ 1 . |
| @ . . . | | 1 . 2 . |
| 1 1 2 . | | 2 . 3 4 |
------------- -------------
There are two possible closest locations to the lava pool,
the one marked with "3" on the left map, and "4" on the right map.
Based on that alone, both would be valid places to path to.
But, in the left case, hero could not see the bottom location, so
the code won't even consider pathing to it, so it will start moving
towards the "3".
When hero moves to the second position, in the right map, now the "4"
could be seen. Now there are two possible closest locations we could
choose from. The code that scans the possible locations goes from top-left
to bottom-right, first going down (y-axis). So, the code sees the
"2" on the right. distmin() to there is 2. Good, we pick that location
to path to. Next, going down, the code considers the "4" ... which is
also equally close to the lava pool. and distmin does not consider terrain,
so ignores the door, so it has the same distmin value of "2", so the
code picks this location.
But: this was just a guess, because there's no known valid path to the
lava pool. The code loops back up to rebuild the travel[][] array
with a new starting location as the "4" from the right map, pathing
back to hero.
This is that travel array map:
-------------
| . . . . |
| 4 @ 3 . |
| 3 . 2 . |
| 3 2 1 x |
-------------
The way travelstepx and travelstepy arrays are built means that the first
location that considers the hero's location is the "3" SW of hero, so
hero will move there next. Repeat from beginning. If there was no door,
the travelsteps would reach hero's location first from SE.
(I left the travel[][] array rebuild and travelstepx/travelstrepy build
off from the other movement position, as it's not relevant)
The fix: When considering which of the two possible closest places to the
lava pool to path to, use the one with the lowest value in the travel array.
That value is the real number of moves it takes for the hero to walk there,
so the code will consistently path to the upper location, as it is "2",
instead of considering the "4" below it.
Also some minor code reorg, so it considers couldsee first instead of
later in two separate places.