fix pull request #487 - one-step diagonal travel

When travel destination is one step away the code stops probing
for a path and reverts to normal movement, but it wasn't handling
the case where the one step was an impossible diagonal except for
hero being a grid bug.  If the situation was a diagonal that's
too narrow to squeeze through, travel would end and regular move
would fail.

I've rejected the suggested fix and done it differently, without
attempting to figure out why the change to end_running() would
have been wrong.  Clearly it was code that called end_running()
which needed to be fixed.

The test case was
 ..x|.
 ..|@.
 .....
while carrying enough that directly moving from '@' to 'x' will
not be allowed.  '@' would move one step south west and then stop
because findtravelpath() had ended travel due to single step move.
A similar case is
   ###
  |x-#-
  |0@.|
where 'x' is a doorway with intact open door and '0' is a boulder.
Prior to this fix, player would get "a boulder blocks the way" and
not move.  After, '@' will move northeast then northwest then west
to get into orthogonal position and finally south into the doorway.

Even though it definitely fixes both mentioned test cases, I won't
be surprised if this results in regressions for other situations.

Fixes #487
This commit is contained in:
PatR
2021-04-04 17:23:46 -07:00
parent 097e746bc3
commit 7d77267f93
2 changed files with 11 additions and 6 deletions

View File

@@ -442,6 +442,9 @@ for menustyle:full, the 'A' menu choice to auto-select everything now only
does so if no other choices have been picked; when any have (object
class or BUCX state or both), it auto-selects every item that matches
those choices (so still skips the second menu) rather than every item
using travel to move one step diagonally where that step was blocked by being
too narrow to squeeze through stopped travel instead of considering
alternate routes to the destination
Fixes to 3.7.0-x Problems that Were Exposed Via git Repository

View File

@@ -958,8 +958,10 @@ findtravelpath(int mode)
{
/* if travel to adjacent, reachable location, use normal movement rules */
if ((mode == TRAVP_TRAVEL || mode == TRAVP_VALID) && g.context.travel1
&& distmin(u.ux, u.uy, u.tx, u.ty) == 1
&& !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
/* was '&& distmin(u.ux, u.uy, u.tx, u.ty) == 1' */
&& distu(u.tx, u.ty) <= 2 /* one step away */
/* handle restricted diagonals */
&& crawl_destination(u.tx, u.ty)) {
end_running(FALSE);
if (test_move(u.ux, u.uy, u.tx - u.ux, u.ty - u.uy, TEST_MOVE)) {
if (mode == TRAVP_TRAVEL) {
@@ -2939,7 +2941,8 @@ doorless_door(int x, int y)
return !(lev_p->doormask & ~(D_NODOOR | D_BROKEN));
}
/* used by drown() to check whether hero can crawl from water to <x,y> */
/* used by drown() to check whether hero can crawl from water to <x,y>;
also used by findtravelpath() when destination is one step away */
boolean
crawl_destination(int x, int y)
{
@@ -3002,9 +3005,8 @@ 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.multi > 0)
/* cancel mutli */
if (g.multi > 0)
g.multi = 0;
}