mirror of https://github.com/OpenTTD/OpenTTD
(svn r24481) -Feature [FS#5127]: Make the pathfinder decide whether ships shall leave depots towards north or south.
parent
0f0f027379
commit
d17ec934f5
|
@ -1178,6 +1178,23 @@ Track NPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir,
|
||||||
return TrackdirToTrack(ftd.best_trackdir);
|
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 ***/
|
/*** Trains ***/
|
||||||
|
|
||||||
FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_penalty)
|
FindDepotData NPFTrainFindNearestDepot(const Train *v, int max_penalty)
|
||||||
|
|
|
@ -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);
|
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
|
* 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
|
* @param v train that needs to go to some depot
|
||||||
|
|
|
@ -193,7 +193,8 @@ Track OPFShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir,
|
||||||
Track track;
|
Track track;
|
||||||
|
|
||||||
/* Let's find out how far it would be if we would reverse first */
|
/* 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
|
uint distr = UINT_MAX; // distance if we reversed
|
||||||
if (b != 0) {
|
if (b != 0) {
|
||||||
|
|
|
@ -28,6 +28,13 @@
|
||||||
*/
|
*/
|
||||||
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found);
|
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.
|
* Finds the best path for given road vehicle using YAPF.
|
||||||
* @param v the RV that needs to find a path
|
* @param v the RV that needs to find a path
|
||||||
|
|
|
@ -98,6 +98,42 @@ public:
|
||||||
}
|
}
|
||||||
return next_trackdir;
|
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 */
|
/** 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);
|
Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks, path_found);
|
||||||
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -310,13 +310,34 @@ static bool CheckShipLeaveDepot(Ship *v)
|
||||||
TileIndex tile = v->tile;
|
TileIndex tile = v->tile;
|
||||||
Axis axis = GetShipDepotAxis(tile);
|
Axis axis = GetShipDepotAxis(tile);
|
||||||
|
|
||||||
/* Check first (north) side */
|
DiagDirection north_dir = ReverseDiagDir(AxisToDiagDir(axis));
|
||||||
if (DiagdirReachesTracks((DiagDirection)axis) & GetTileShipTrackStatus(TILE_ADD(tile, ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
|
TileIndex north_neighbour = TILE_ADD(tile, ToTileIndexDiff(_ship_leave_depot_offs[axis]));
|
||||||
v->direction = ReverseDir(AxisToDirection(axis));
|
DiagDirection south_dir = AxisToDiagDir(axis);
|
||||||
/* Check second (south) side */
|
TileIndex south_neighbour = TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis]));
|
||||||
} else if (DiagdirReachesTracks((DiagDirection)(axis + 2)) & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
|
|
||||||
v->direction = AxisToDirection(axis);
|
TrackBits north_tracks = DiagdirReachesTracks(north_dir) & GetTileShipTrackStatus(north_neighbour);
|
||||||
|
TrackBits south_tracks = DiagdirReachesTracks(south_dir) & GetTileShipTrackStatus(south_neighbour);
|
||||||
|
if (north_tracks && south_tracks) {
|
||||||
|
/* Ask pathfinder for best direction */
|
||||||
|
bool reverse = false;
|
||||||
|
bool path_found;
|
||||||
|
switch (_settings_game.pf.pathfinder_for_ships) {
|
||||||
|
case VPF_OPF: reverse = OPFShipChooseTrack(v, north_neighbour, north_dir, north_tracks, path_found) == INVALID_TRACK; break; // OPF always allows reversing
|
||||||
|
case VPF_NPF: reverse = NPFShipCheckReverse(v); break;
|
||||||
|
case VPF_YAPF: reverse = YapfShipCheckReverse(v); break;
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
if (reverse) north_tracks = TRACK_BIT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (north_tracks) {
|
||||||
|
/* Leave towards north */
|
||||||
|
v->direction = DiagDirToDir(north_dir);
|
||||||
|
} else if (south_tracks) {
|
||||||
|
/* Leave towards south */
|
||||||
|
v->direction = DiagDirToDir(south_dir);
|
||||||
} else {
|
} else {
|
||||||
|
/* Both ways blocked */
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue