diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -1159,7 +1159,7 @@ Trackdir NPFRoadVehicleChooseTrack(const /*** Ships ***/ -Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) +Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found) { NPFFindStationOrTileData fstd; Trackdir trackdir = v->GetVehicleTrackdir(); @@ -1173,6 +1173,7 @@ Track NPFShipChooseTrack(const Ship *v, * the direction we need to take to get there, if ftd.best_bird_dist is not 0, * we did not find our target, but ftd.best_trackdir contains the direction leading * to the tile closest to our target. */ + path_found = (ftd.best_bird_dist == 0); if (ftd.best_trackdir == 0xff) return INVALID_TRACK; return TrackdirToTrack(ftd.best_trackdir); } diff --git a/src/pathfinder/npf/npf_func.h b/src/pathfinder/npf/npf_func.h --- a/src/pathfinder/npf/npf_func.h +++ b/src/pathfinder/npf/npf_func.h @@ -44,9 +44,10 @@ Trackdir NPFRoadVehicleChooseTrack(const * @param tile the tile to find the path from (should be next tile the ship is about to enter) * @param enterdir diagonal direction which the ship will enter this new tile from * @param tracks available tracks on the new tile (to choose from) + * @param path_found [out] Whether a path has been found (true) or has been guessed (false) * @return the best trackdir for next turn or INVALID_TRACK if the path could not be found */ -Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks); +Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found); /** * Used when user sends train to the nearest depot or if train needs servicing using NPF diff --git a/src/pathfinder/opf/opf_ship.cpp b/src/pathfinder/opf/opf_ship.cpp --- a/src/pathfinder/opf/opf_ship.cpp +++ b/src/pathfinder/opf/opf_ship.cpp @@ -183,7 +183,7 @@ bad:; * reverse. The tile given is the tile we are about to enter, enterdir is the * direction in which we are entering the tile */ -Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) +Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found) { assert(IsValidDiagDirection(enterdir)); @@ -202,6 +202,9 @@ Track OPFShipChooseTrack(const Ship *v, /* And if we would not reverse? */ uint dist = FindShipTrack(v, tile, enterdir, tracks, 0, &track); + /* If the dist equals zero, or distr equals one (the extra reversing penalty), + * then we found our destination and we are not lost. */ + path_found = (dist == 0 || distr == 1); if (dist <= distr) return track; return INVALID_TRACK; // We could better reverse } diff --git a/src/pathfinder/opf/opf_ship.h b/src/pathfinder/opf/opf_ship.h --- a/src/pathfinder/opf/opf_ship.h +++ b/src/pathfinder/opf/opf_ship.h @@ -23,8 +23,9 @@ * @param tile the tile to find the path from (should be next tile the ship is about to enter) * @param enterdir diagonal direction which the ship will enter this new tile from * @param tracks available tracks on the new tile (to choose from) + * @param path_found [out] Whether a path has been found (true) or has been guessed (false) * @return the best trackdir for next turn or INVALID_TRACK if the path could not be found */ -Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks); +Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found); #endif /* OPF_SHIP_H */ diff --git a/src/pathfinder/yapf/yapf.h b/src/pathfinder/yapf/yapf.h --- a/src/pathfinder/yapf/yapf.h +++ b/src/pathfinder/yapf/yapf.h @@ -23,9 +23,10 @@ * @param tile the tile to find the path from (should be next tile the ship is about to enter) * @param enterdir diagonal direction which the ship will enter this new tile from * @param tracks available tracks on the new tile (to choose from) + * @param path_found [out] Whether a path has been found (true) or has been guessed (false) * @return the best trackdir for next turn or INVALID_TRACK if the path could not be found */ -Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks); +Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found); /** * Finds the best path for given road vehicle using YAPF. diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -51,7 +51,7 @@ public: return 'w'; } - static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) + static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found) { /* handle special case - when next tile is destination tile */ if (tile == v->dest_tile) { @@ -78,7 +78,7 @@ public: pf.SetOrigin(src_tile, trackdirs); pf.SetDestination(v->dest_tile, dest_trackdirs); /* find best path */ - pf.FindPath(v); + path_found = pf.FindPath(v); Trackdir next_trackdir = INVALID_TRACKDIR; // this would mean "path not found" @@ -174,10 +174,10 @@ struct CYapfShip2 : CYapfT > {}; /** Ship controller helper - path finder invoker */ -Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) +Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found) { /* default is YAPF type 2 */ - typedef Trackdir (*PfnChooseShipTrack)(const Ship*, TileIndex, DiagDirection, TrackBits); + typedef Trackdir (*PfnChooseShipTrack)(const Ship*, TileIndex, DiagDirection, TrackBits, bool &path_found); PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack; // default: ExitDir, allow 90-deg /* check if non-default YAPF type needed */ @@ -187,6 +187,6 @@ Track YapfShipChooseTrack(const Ship *v, pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack; // Trackdir, allow 90-deg } - Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks); + Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks, path_found); return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK; } diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -353,16 +353,21 @@ static void ShipArrivesAt(const Vehicle * reverse. The tile given is the tile we are about to enter, enterdir is the * direction in which we are entering the tile */ -static Track ChooseShipTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) +static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks) { assert(IsValidDiagDirection(enterdir)); + bool path_found = true; + Track track; switch (_settings_game.pf.pathfinder_for_ships) { - case VPF_OPF: return OPFShipChooseTrack(v, tile, enterdir, tracks); - case VPF_NPF: return NPFShipChooseTrack(v, tile, enterdir, tracks); - case VPF_YAPF: return YapfShipChooseTrack(v, tile, enterdir, tracks); + case VPF_OPF: track = OPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break; + case VPF_NPF: track = NPFShipChooseTrack(v, tile, enterdir, tracks, path_found); break; + case VPF_YAPF: track = YapfShipChooseTrack(v, tile, enterdir, tracks, path_found); break; default: NOT_REACHED(); } + + v->HandlePathfindingResult(path_found); + return track; } static const Direction _new_vehicle_direction_table[] = {