From 98ddbbf2621c1c0b2ed7a0ee7a7ce900f22fd1b3 Mon Sep 17 00:00:00 2001 From: SamuXarick <43006711+SamuXarick@users.noreply.github.com> Date: Mon, 11 Mar 2024 22:25:22 +0000 Subject: [PATCH] Fix #12231: Pick a random trackdir if no path is found when force reversing --- src/pathfinder/yapf/yapf_ship.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp index ced5818c8a..31a2c6905e 100644 --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -172,6 +172,14 @@ public: return 'w'; } + static Trackdir PickRandomTrackdir(TrackdirBits trackdirs) + { + assert(trackdirs != TRACKDIR_BIT_NONE); + const int strip_amount = RandomRange(CountBits(trackdirs)); + for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&trackdirs); + return FindFirstTrackdir(trackdirs); + } + /** Returns a random tile/trackdir that can be reached from the current tile/trackdir, or tile/INVALID_TRACK if none is available. */ static std::pair GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir) { @@ -180,9 +188,7 @@ public: TrackdirBits dirs = follower.m_new_td_bits; const TrackdirBits dirs_without_90_degree = dirs & ~TrackdirCrossesTrackdirs(dir); if (dirs_without_90_degree != TRACKDIR_BIT_NONE) dirs = dirs_without_90_degree; - const int strip_amount = RandomRange(CountBits(dirs)); - for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&dirs); - return { follower.m_new_tile, FindFirstTrackdir(dirs) }; + return { follower.m_new_tile, PickRandomTrackdir(dirs) }; } return { follower.m_new_tile, INVALID_TRACKDIR }; } @@ -295,7 +301,7 @@ public: bool reverse = false; const std::vector high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1); - if (high_level_path.empty()) return reverse; + if (high_level_path.empty() && trackdir == nullptr) return reverse; TrackdirBits trackdirs; if (trackdir == nullptr) { @@ -305,6 +311,10 @@ public: /* At the end of path, no path ahead, reversing. */ DiagDirection entry = ReverseDiagDir(VehicleExitDir(v->direction, v->state)); trackdirs = DiagdirReachesTrackdirs(entry) & TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, entry)); + if (high_level_path.empty()) { + *trackdir = PickRandomTrackdir(trackdirs); + return reverse; + } } for (int attempt = 0; attempt < 2; ++attempt) { @@ -324,11 +334,19 @@ public: /* Find best path. */ if (!pf.FindPath(v)) { if (attempt == 0) continue; // Try again with restricted search area. + if (trackdir != nullptr) { + *trackdir = PickRandomTrackdir(trackdirs); + } break; // Returns false. } Node *pNode = pf.GetBestNode(); - if (pNode == nullptr) break; // Returns false. + if (pNode == nullptr) { + if (trackdir != nullptr) { + *trackdir = PickRandomTrackdir(trackdirs); + } + break; // Returns false. + } /* Path was found, walk through the path back to the origin. */ while (pNode->m_parent != nullptr) {