From d17ec934f55f5000cf30aa752437cc48cff19645 Mon Sep 17 00:00:00 2001 From: frosch Date: Sat, 18 Aug 2012 11:37:47 +0000 Subject: (svn r24481) -Feature [FS#5127]: Make the pathfinder decide whether ships shall leave depots towards north or south. --- src/pathfinder/npf/npf.cpp | 17 ++++++++++++ src/pathfinder/npf/npf_func.h | 7 +++++ src/pathfinder/opf/opf_ship.cpp | 3 ++- src/pathfinder/yapf/yapf.h | 7 +++++ src/pathfinder/yapf/yapf_ship.cpp | 57 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 1 deletion(-) (limited to 'src/pathfinder') diff --git a/src/pathfinder/npf/npf.cpp b/src/pathfinder/npf/npf.cpp index 976767319..1b8d2f17f 100644 --- a/src/pathfinder/npf/npf.cpp +++ b/src/pathfinder/npf/npf.cpp @@ -1178,6 +1178,23 @@ Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, return TrackdirToTrack(ftd.best_trackdir); } +bool NPFShipCheckReverse(const Ship *v) +{ + NPFFindStationOrTileData fstd; + NPFFoundTargetData ftd; + + NPFFillWithOrderData(&fstd, v); + + Trackdir trackdir = v->GetVehicleTrackdir(); + Trackdir trackdir_rev = ReverseTrackdir(trackdir); + assert(trackdir != INVALID_TRACKDIR); + assert(trackdir_rev != INVALID_TRACKDIR); + + ftd = NPFRouteToStationOrTileTwoWay(v->tile, trackdir, false, v->tile, trackdir_rev, false, &fstd, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPES); + /* If we didn't find anything, just keep on going straight ahead, otherwise take the reverse flag */ + return ftd.best_bird_dist == 0 && NPFGetFlag(&ftd.node, NPF_FLAG_REVERSE); +} + /*** Trains ***/ FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_penalty) diff --git a/src/pathfinder/npf/npf_func.h b/src/pathfinder/npf/npf_func.h index f83c06f13..6507f4ec5 100644 --- a/src/pathfinder/npf/npf_func.h +++ b/src/pathfinder/npf/npf_func.h @@ -49,6 +49,13 @@ Trackdir NPFRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDir */ Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found); +/** + * Returns true if it is better to reverse the ship before leaving depot using NPF. + * @param v the ship leaving the depot + * @return true if reversing is better + */ +bool NPFShipCheckReverse(const Ship *v); + /** * Used when user sends train to the nearest depot or if train needs servicing using NPF * @param v train that needs to go to some depot diff --git a/src/pathfinder/opf/opf_ship.cpp b/src/pathfinder/opf/opf_ship.cpp index 9cf574484..850577de1 100644 --- a/src/pathfinder/opf/opf_ship.cpp +++ b/src/pathfinder/opf/opf_ship.cpp @@ -193,7 +193,8 @@ Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, Track track; /* Let's find out how far it would be if we would reverse first */ - TrackBits b = TrackStatusToTrackBits(GetTileTrackStatus(tile2, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(ReverseDiagDir(enterdir)) & v->state; + Trackdir trackdir = v->GetVehicleTrackdir(); + TrackBits b = TrackStatusToTrackBits(GetTileTrackStatus(tile2, TRANSPORT_WATER, 0)) & DiagdirReachesTracks(ReverseDiagDir(enterdir)) & TrackdirBitsToTrackBits(TrackdirToTrackdirBits(trackdir)); uint distr = UINT_MAX; // distance if we reversed if (b != 0) { diff --git a/src/pathfinder/yapf/yapf.h b/src/pathfinder/yapf/yapf.h index b02d9d0ee..00eb7e562 100644 --- a/src/pathfinder/yapf/yapf.h +++ b/src/pathfinder/yapf/yapf.h @@ -28,6 +28,13 @@ */ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found); +/** + * Returns true if it is better to reverse the ship before leaving depot using YAPF. + * @param v the ship leaving the depot + * @return true if reversing is better + */ +bool YapfShipCheckReverse(const Ship *v); + /** * Finds the best path for given road vehicle using YAPF. * @param v the RV that needs to find a path diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp index dfcda3858..a4113144e 100644 --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -98,6 +98,42 @@ public: } return next_trackdir; } + + /** + * Check whether a ship should reverse to reach its destination. + * Called when leaving depot. + * @param v Ship + * @param tile Current position + * @param td1 Forward direction + * @param td2 Reverse direction + * @return true if the reverse direction is better + */ + static bool CheckShipReverse(const Ship *v, TileIndex tile, Trackdir td1, Trackdir td2) + { + /* get available trackdirs on the destination tile */ + TrackdirBits dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0)); + + /* create pathfinder instance */ + Tpf pf; + /* set origin and destination nodes */ + pf.SetOrigin(tile, TrackdirToTrackdirBits(td1) | TrackdirToTrackdirBits(td2)); + pf.SetDestination(v->dest_tile, dest_trackdirs); + /* find best path */ + if (!pf.FindPath(v)) return false; + + Node *pNode = pf.GetBestNode(); + if (pNode == NULL) return false; + + /* path was found + * walk through the path back to the origin */ + while (pNode->m_parent != NULL) { + pNode = pNode->m_parent; + } + + Trackdir best_trackdir = pNode->GetTrackdir(); + assert(best_trackdir == td1 || best_trackdir == td2); + return best_trackdir == td2; + } }; /** Cost Provider module of YAPF for ships */ @@ -197,3 +233,24 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks, path_found); return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK; } + +bool YapfShipCheckReverse(const Ship *v) +{ + Trackdir td = v->GetVehicleTrackdir(); + Trackdir td_rev = ReverseTrackdir(td); + TileIndex tile = v->tile; + + typedef bool (*PfnCheckReverseShip)(const Ship*, TileIndex, Trackdir, Trackdir); + PfnCheckReverseShip pfnCheckReverseShip = CYapfShip2::CheckShipReverse; // default: ExitDir, allow 90-deg + + /* check if non-default YAPF type needed */ + if (_settings_game.pf.forbid_90_deg) { + pfnCheckReverseShip = &CYapfShip3::CheckShipReverse; // Trackdir, forbid 90-deg + } else if (_settings_game.pf.yapf.disable_node_optimization) { + pfnCheckReverseShip = &CYapfShip1::CheckShipReverse; // Trackdir, allow 90-deg + } + + bool reverse = pfnCheckReverseShip(v, tile, td, td_rev); + + return reverse; +} -- cgit v1.2.3-54-g00ecf