1
0
Fork 0

Fix #12228: Don't restrict path when checking ship reverse on first attempt

Try to mimic the same path results as ChooseShipTrack to maintain behaviour consistency.
pull/12232/head
SamuXarick 2024-02-27 21:05:57 +00:00
parent d7c5e9e8ab
commit d6584c11b6
1 changed files with 47 additions and 30 deletions

View File

@ -292,31 +292,43 @@ public:
*/ */
static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, Trackdir *trackdir) static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2, Trackdir *trackdir)
{ {
bool reverse = false;
const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1); const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
if (high_level_path.empty()) { if (high_level_path.empty()) return reverse;
if (trackdir) *trackdir = INVALID_TRACKDIR;
return false; TrackdirBits trackdirs;
if (trackdir == nullptr) {
/* Leaving station or depot. */
trackdirs = TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2);
} else {
/* 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));
} }
for (int attempt = 0; attempt < 2; ++attempt) {
/* Create pathfinder instance. */ /* Create pathfinder instance. */
Tpf pf(MAX_SHIP_PF_NODES); Tpf pf(MAX_SHIP_PF_NODES);
/* Set origin and destination nodes. */ /* Set origin and destination nodes. */
if (trackdir == nullptr) { pf.SetOrigin(tile, trackdirs);
pf.SetOrigin(tile, TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2));
} else {
DiagDirection entry = ReverseDiagDir(VehicleExitDir(v->direction, v->state));
TrackdirBits rtds = DiagdirReachesTrackdirs(entry) & TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_WATER, 0, entry));
pf.SetOrigin(tile, rtds);
}
pf.SetDestination(v); pf.SetDestination(v);
if (high_level_path.size() > 1) pf.SetIntermediateDestination(high_level_path.back()); const bool is_intermediate_destination = static_cast<int>(high_level_path.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1;
pf.RestrictSearch(high_level_path); if (is_intermediate_destination) pf.SetIntermediateDestination(high_level_path.back());
/* Restrict the search area to prevent the low level pathfinder from expanding too many nodes. This can happen
* when the terrain is very "maze-like" or when the high level path "teleports" via a very long aqueduct. */
if (attempt > 0) pf.RestrictSearch(high_level_path);
/* Find best path. */ /* Find best path. */
if (!pf.FindPath(v)) return false; if (!pf.FindPath(v)) {
if (attempt == 0) continue; // Try again with restricted search area.
break; // Returns false.
}
Node *pNode = pf.GetBestNode(); Node *pNode = pf.GetBestNode();
if (pNode == nullptr) return false; if (pNode == nullptr) break; // Returns false.
/* Path was found, walk through the path back to the origin. */ /* Path was found, walk through the path back to the origin. */
while (pNode->m_parent != nullptr) { while (pNode->m_parent != nullptr) {
@ -329,7 +341,12 @@ public:
} else { } else {
assert(best_trackdir == td1 || best_trackdir == td2); assert(best_trackdir == td1 || best_trackdir == td2);
} }
return best_trackdir != td1; reverse = best_trackdir != td1;
break;
}
return reverse;
} }
}; };