mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Remove `m_` prefix from pathfinders.
parent
a496e9397c
commit
a171939ec3
|
@ -1229,7 +1229,7 @@ static int32_t River_CalculateG(AyStar *, AyStarNode *, PathNode *)
|
|||
/* AyStar callback for getting the estimated cost to the destination. */
|
||||
static int32_t River_CalculateH(AyStar *aystar, AyStarNode *current, PathNode *)
|
||||
{
|
||||
return DistanceManhattan(*(TileIndex*)aystar->user_target, current->m_tile);
|
||||
return DistanceManhattan(*(TileIndex*)aystar->user_target, current->tile);
|
||||
}
|
||||
|
||||
/* AyStar callback for getting the neighbouring nodes of the given node. */
|
||||
|
@ -1242,8 +1242,8 @@ static void River_GetNeighbours(AyStar *aystar, PathNode *current)
|
|||
TileIndex t2 = tile + TileOffsByDiagDir(d);
|
||||
if (IsValidTile(t2) && FlowsDown(tile, t2)) {
|
||||
auto &neighbour = aystar->neighbours.emplace_back();
|
||||
neighbour.m_tile = t2;
|
||||
neighbour.m_td = INVALID_TRACKDIR;
|
||||
neighbour.tile = t2;
|
||||
neighbour.td = INVALID_TRACKDIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1255,7 +1255,7 @@ static void River_FoundEndNode(AyStar *aystar, PathNode *current)
|
|||
|
||||
/* First, build the river without worrying about its width. */
|
||||
uint cur_pos = 0;
|
||||
for (PathNode *path = current->m_parent; path != nullptr; path = path->m_parent, cur_pos++) {
|
||||
for (PathNode *path = current->parent; path != nullptr; path = path->parent, cur_pos++) {
|
||||
TileIndex tile = path->GetTile();
|
||||
if (!IsWaterTile(tile)) {
|
||||
MakeRiverAndModifyDesertZoneAround(tile);
|
||||
|
@ -1271,14 +1271,14 @@ static void River_FoundEndNode(AyStar *aystar, PathNode *current)
|
|||
uint radius;
|
||||
|
||||
cur_pos = 0;
|
||||
for (PathNode *path = current->m_parent; path != nullptr; path = path->m_parent, cur_pos++) {
|
||||
for (PathNode *path = current->parent; path != nullptr; path = path->parent, cur_pos++) {
|
||||
TileIndex tile = path->GetTile();
|
||||
|
||||
/* Check if we should widen river depending on how far we are away from the source. */
|
||||
current_river_length = DistanceManhattan(data->spring, tile);
|
||||
radius = std::min(3u, (current_river_length / (long_river_length / 3u)) + 1u);
|
||||
|
||||
if (radius > 1) CircularTileSearch(&tile, radius, RiverMakeWider, (void *)&path->m_key.m_tile);
|
||||
if (radius > 1) CircularTileSearch(&tile, radius, RiverMakeWider, (void *)&path->key.tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1304,8 +1304,8 @@ static void BuildRiver(TileIndex begin, TileIndex end, TileIndex spring, bool ma
|
|||
finder.user_data = &user_data;
|
||||
|
||||
AyStarNode start;
|
||||
start.m_tile = begin;
|
||||
start.m_td = INVALID_TRACKDIR;
|
||||
start.tile = begin;
|
||||
start.td = INVALID_TRACKDIR;
|
||||
finder.AddStartNode(&start, 0);
|
||||
finder.Main();
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ void AyStar::OpenListAdd(PathNode *parent, const AyStarNode *node, int f, int g)
|
|||
{
|
||||
/* Add a new Node to the OpenList */
|
||||
PathNode *new_node = this->nodes.CreateNewNode();
|
||||
new_node->Set(parent, node->m_tile, node->m_td, true);
|
||||
new_node->m_estimate = f;
|
||||
new_node->m_cost = g;
|
||||
new_node->Set(parent, node->tile, node->td, true);
|
||||
new_node->estimate = f;
|
||||
new_node->cost = g;
|
||||
this->nodes.InsertOpenNode(*new_node);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ void AyStar::CheckTile(AyStarNode *current, PathNode *parent)
|
|||
/* There should not be given any other error-code.. */
|
||||
assert(new_g >= 0);
|
||||
/* Add the parent g-value to the new g-value */
|
||||
new_g += parent->m_cost;
|
||||
new_g += parent->cost;
|
||||
if (this->max_path_cost != 0 && new_g > this->max_path_cost) return;
|
||||
|
||||
/* Calculate the h-value */
|
||||
|
@ -60,18 +60,18 @@ void AyStar::CheckTile(AyStarNode *current, PathNode *parent)
|
|||
int new_f = new_g + new_h;
|
||||
|
||||
/* Get the pointer to the parent in the ClosedList (the current one is to a copy of the one in the OpenList) */
|
||||
PathNode *closedlist_parent = this->nodes.FindClosedNode(parent->m_key);
|
||||
PathNode *closedlist_parent = this->nodes.FindClosedNode(parent->key);
|
||||
|
||||
/* Check if this item is already in the OpenList */
|
||||
PathNode *check = this->nodes.FindOpenNode(*current);
|
||||
if (check != nullptr) {
|
||||
/* Yes, check if this g value is lower.. */
|
||||
if (new_g > check->m_cost) return;
|
||||
this->nodes.PopOpenNode(check->m_key);
|
||||
if (new_g > check->cost) return;
|
||||
this->nodes.PopOpenNode(check->key);
|
||||
/* It is lower, so change it to this item */
|
||||
check->m_estimate = new_f;
|
||||
check->m_cost = new_g;
|
||||
check->m_parent = closedlist_parent;
|
||||
check->estimate = new_f;
|
||||
check->cost = new_g;
|
||||
check->parent = closedlist_parent;
|
||||
/* Re-add it in the openlist_queue. */
|
||||
this->nodes.InsertOpenNode(*check);
|
||||
} else {
|
||||
|
@ -97,7 +97,7 @@ int AyStar::Loop()
|
|||
if (current == nullptr) return AYSTAR_EMPTY_OPENLIST;
|
||||
|
||||
/* Check for end node and if found, return that code */
|
||||
if (this->EndNodeCheck(this, current) == AYSTAR_FOUND_END_NODE && current->m_parent != nullptr) {
|
||||
if (this->EndNodeCheck(this, current) == AYSTAR_FOUND_END_NODE && current->parent != nullptr) {
|
||||
if (this->FoundEndNode != nullptr) {
|
||||
this->FoundEndNode(this, current);
|
||||
}
|
||||
|
|
|
@ -36,19 +36,19 @@ struct CFollowTrackT
|
|||
EC_RESERVED,
|
||||
};
|
||||
|
||||
const VehicleType *m_veh; ///< moving vehicle
|
||||
Owner m_veh_owner; ///< owner of the vehicle
|
||||
TileIndex m_old_tile; ///< the origin (vehicle moved from) before move
|
||||
Trackdir m_old_td; ///< the trackdir (the vehicle was on) before move
|
||||
TileIndex m_new_tile; ///< the new tile (the vehicle has entered)
|
||||
TrackdirBits m_new_td_bits; ///< the new set of available trackdirs
|
||||
DiagDirection m_exitdir; ///< exit direction (leaving the old tile)
|
||||
bool m_is_tunnel; ///< last turn passed tunnel
|
||||
bool m_is_bridge; ///< last turn passed bridge ramp
|
||||
bool m_is_station; ///< last turn passed station
|
||||
int m_tiles_skipped; ///< number of skipped tunnel or station tiles
|
||||
ErrorCode m_err;
|
||||
RailTypes m_railtypes;
|
||||
const VehicleType *veh; ///< moving vehicle
|
||||
Owner veh_owner; ///< owner of the vehicle
|
||||
TileIndex old_tile; ///< the origin (vehicle moved from) before move
|
||||
Trackdir old_td; ///< the trackdir (the vehicle was on) before move
|
||||
TileIndex new_tile; ///< the new tile (the vehicle has entered)
|
||||
TrackdirBits new_td_bits; ///< the new set of available trackdirs
|
||||
DiagDirection exitdir; ///< exit direction (leaving the old tile)
|
||||
bool is_tunnel; ///< last turn passed tunnel
|
||||
bool is_bridge; ///< last turn passed bridge ramp
|
||||
bool is_station; ///< last turn passed station
|
||||
int tiles_skipped; ///< number of skipped tunnel or station tiles
|
||||
ErrorCode err;
|
||||
RailTypes railtypes;
|
||||
|
||||
inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES)
|
||||
{
|
||||
|
@ -58,40 +58,40 @@ struct CFollowTrackT
|
|||
inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES)
|
||||
{
|
||||
assert(IsRailTT());
|
||||
this->m_veh = nullptr;
|
||||
this->veh = nullptr;
|
||||
Init(o, railtype_override);
|
||||
}
|
||||
|
||||
inline void Init(const VehicleType *v, RailTypes railtype_override)
|
||||
{
|
||||
assert(!IsRailTT() || (v != nullptr && v->type == VEH_TRAIN));
|
||||
this->m_veh = v;
|
||||
this->veh = v;
|
||||
Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override);
|
||||
}
|
||||
|
||||
inline void Init(Owner o, RailTypes railtype_override)
|
||||
{
|
||||
assert(!IsRoadTT() || this->m_veh != nullptr);
|
||||
assert(!IsRoadTT() || this->veh != nullptr);
|
||||
assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES);
|
||||
this->m_veh_owner = o;
|
||||
this->veh_owner = o;
|
||||
/* don't worry, all is inlined so compiler should remove unnecessary initializations */
|
||||
this->m_old_tile = INVALID_TILE;
|
||||
this->m_old_td = INVALID_TRACKDIR;
|
||||
this->m_new_tile = INVALID_TILE;
|
||||
this->m_new_td_bits = TRACKDIR_BIT_NONE;
|
||||
this->m_exitdir = INVALID_DIAGDIR;
|
||||
this->m_is_station = false;
|
||||
this->m_is_bridge = false;
|
||||
this->m_is_tunnel = false;
|
||||
this->m_tiles_skipped = 0;
|
||||
this->m_err = EC_NONE;
|
||||
this->m_railtypes = railtype_override;
|
||||
this->old_tile = INVALID_TILE;
|
||||
this->old_td = INVALID_TRACKDIR;
|
||||
this->new_tile = INVALID_TILE;
|
||||
this->new_td_bits = TRACKDIR_BIT_NONE;
|
||||
this->exitdir = INVALID_DIAGDIR;
|
||||
this->is_station = false;
|
||||
this->is_bridge = false;
|
||||
this->is_tunnel = false;
|
||||
this->tiles_skipped = 0;
|
||||
this->err = EC_NONE;
|
||||
this->railtypes = railtype_override;
|
||||
}
|
||||
|
||||
debug_inline static TransportType TT() { return Ttr_type_; }
|
||||
debug_inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; }
|
||||
debug_inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; }
|
||||
inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(this->m_veh)->roadtype); }
|
||||
inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(this->veh)->roadtype); }
|
||||
debug_inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; }
|
||||
inline static bool Allow90degTurns() { return T90deg_turns_allowed_; }
|
||||
inline static bool DoTrackMasking() { return Tmask_reserved_tracks; }
|
||||
|
@ -120,24 +120,24 @@ struct CFollowTrackT
|
|||
*/
|
||||
inline bool Follow(TileIndex old_tile, Trackdir old_td)
|
||||
{
|
||||
this->m_old_tile = old_tile;
|
||||
this->m_old_td = old_td;
|
||||
this->m_err = EC_NONE;
|
||||
this->old_tile = old_tile;
|
||||
this->old_td = old_td;
|
||||
this->err = EC_NONE;
|
||||
|
||||
assert([&]() {
|
||||
if (this->IsTram() && this->GetSingleTramBit(this->m_old_tile) != INVALID_DIAGDIR) return true; // Skip the check for single tram bits
|
||||
const uint sub_mode = (IsRoadTT() && this->m_veh != nullptr) ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0;
|
||||
const TrackdirBits old_tile_valid_dirs = TrackStatusToTrackdirBits(GetTileTrackStatus(this->m_old_tile, TT(), sub_mode));
|
||||
return (old_tile_valid_dirs & TrackdirToTrackdirBits(this->m_old_td)) != TRACKDIR_BIT_NONE;
|
||||
if (this->IsTram() && this->GetSingleTramBit(this->old_tile) != INVALID_DIAGDIR) return true; // Skip the check for single tram bits
|
||||
const uint sub_mode = (IsRoadTT() && this->veh != nullptr) ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0;
|
||||
const TrackdirBits old_tile_valid_dirs = TrackStatusToTrackdirBits(GetTileTrackStatus(this->old_tile, TT(), sub_mode));
|
||||
return (old_tile_valid_dirs & TrackdirToTrackdirBits(this->old_td)) != TRACKDIR_BIT_NONE;
|
||||
}());
|
||||
|
||||
this->m_exitdir = TrackdirToExitdir(this->m_old_td);
|
||||
this->exitdir = TrackdirToExitdir(this->old_td);
|
||||
if (this->ForcedReverse()) return true;
|
||||
if (!this->CanExitOldTile()) return false;
|
||||
this->FollowTileExit();
|
||||
if (!this->QueryNewTileTrackStatus()) return TryReverse();
|
||||
this->m_new_td_bits &= DiagdirReachesTrackdirs(this->m_exitdir);
|
||||
if (this->m_new_td_bits == TRACKDIR_BIT_NONE || !this->CanEnterNewTile()) {
|
||||
this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
|
||||
if (this->new_td_bits == TRACKDIR_BIT_NONE || !this->CanEnterNewTile()) {
|
||||
/* In case we can't enter the next tile, but are
|
||||
* a normal road vehicle, then we can actually
|
||||
* try to reverse as this is the end of the road.
|
||||
|
@ -154,14 +154,14 @@ struct CFollowTrackT
|
|||
/* CanEnterNewTile already set a reason.
|
||||
* Do NOT overwrite it (important for example for EC_RAIL_ROAD_TYPE).
|
||||
* Only set a reason if CanEnterNewTile was not called */
|
||||
if (this->m_new_td_bits == TRACKDIR_BIT_NONE) this->m_err = EC_NO_WAY;
|
||||
if (this->new_td_bits == TRACKDIR_BIT_NONE) this->err = EC_NO_WAY;
|
||||
|
||||
return false;
|
||||
}
|
||||
if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(this->m_old_tile), GetTileRailType(this->m_new_tile), !Allow90degTurns()))) {
|
||||
this->m_new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(this->m_old_td);
|
||||
if (this->m_new_td_bits == TRACKDIR_BIT_NONE) {
|
||||
this->m_err = EC_90DEG;
|
||||
if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(this->old_tile), GetTileRailType(this->new_tile), !Allow90degTurns()))) {
|
||||
this->new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(this->old_td);
|
||||
if (this->new_td_bits == TRACKDIR_BIT_NONE) {
|
||||
this->err = EC_90DEG;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -172,200 +172,200 @@ struct CFollowTrackT
|
|||
{
|
||||
if (!DoTrackMasking()) return true;
|
||||
|
||||
if (this->m_is_station) {
|
||||
if (this->is_station) {
|
||||
/* Check skipped station tiles as well. */
|
||||
TileIndexDiff diff = TileOffsByDiagDir(this->m_exitdir);
|
||||
for (TileIndex tile = this->m_new_tile - diff * this->m_tiles_skipped; tile != this->m_new_tile; tile += diff) {
|
||||
TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
|
||||
for (TileIndex tile = this->new_tile - diff * this->tiles_skipped; tile != this->new_tile; tile += diff) {
|
||||
if (HasStationReservation(tile)) {
|
||||
this->m_new_td_bits = TRACKDIR_BIT_NONE;
|
||||
this->m_err = EC_RESERVED;
|
||||
this->new_td_bits = TRACKDIR_BIT_NONE;
|
||||
this->err = EC_RESERVED;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TrackBits reserved = GetReservedTrackbits(this->m_new_tile);
|
||||
TrackBits reserved = GetReservedTrackbits(this->new_tile);
|
||||
/* Mask already reserved trackdirs. */
|
||||
this->m_new_td_bits &= ~TrackBitsToTrackdirBits(reserved);
|
||||
this->new_td_bits &= ~TrackBitsToTrackdirBits(reserved);
|
||||
/* Mask out all trackdirs that conflict with the reservation. */
|
||||
for (Track t : SetTrackBitIterator(TrackdirBitsToTrackBits(this->m_new_td_bits))) {
|
||||
if (TracksOverlap(reserved | TrackToTrackBits(t))) this->m_new_td_bits &= ~TrackToTrackdirBits(t);
|
||||
for (Track t : SetTrackBitIterator(TrackdirBitsToTrackBits(this->new_td_bits))) {
|
||||
if (TracksOverlap(reserved | TrackToTrackBits(t))) this->new_td_bits &= ~TrackToTrackdirBits(t);
|
||||
}
|
||||
if (this->m_new_td_bits == TRACKDIR_BIT_NONE) {
|
||||
this->m_err = EC_RESERVED;
|
||||
if (this->new_td_bits == TRACKDIR_BIT_NONE) {
|
||||
this->err = EC_RESERVED;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Follow the m_exitdir from m_old_tile and fill m_new_tile and m_tiles_skipped */
|
||||
/** Follow the exitdir from old_tile and fill new_tile and tiles_skipped */
|
||||
inline void FollowTileExit()
|
||||
{
|
||||
this->m_is_station = false;
|
||||
this->m_is_bridge = false;
|
||||
this->m_is_tunnel = false;
|
||||
this->m_tiles_skipped = 0;
|
||||
this->is_station = false;
|
||||
this->is_bridge = false;
|
||||
this->is_tunnel = false;
|
||||
this->tiles_skipped = 0;
|
||||
|
||||
/* extra handling for tunnels and bridges in our direction */
|
||||
if (IsTileType(this->m_old_tile, MP_TUNNELBRIDGE)) {
|
||||
DiagDirection enterdir = GetTunnelBridgeDirection(this->m_old_tile);
|
||||
if (enterdir == this->m_exitdir) {
|
||||
if (IsTileType(this->old_tile, MP_TUNNELBRIDGE)) {
|
||||
DiagDirection enterdir = GetTunnelBridgeDirection(this->old_tile);
|
||||
if (enterdir == this->exitdir) {
|
||||
/* we are entering the tunnel / bridge */
|
||||
if (IsTunnel(this->m_old_tile)) {
|
||||
this->m_is_tunnel = true;
|
||||
this->m_new_tile = GetOtherTunnelEnd(this->m_old_tile);
|
||||
} else { // IsBridge(m_old_tile)
|
||||
this->m_is_bridge = true;
|
||||
this->m_new_tile = GetOtherBridgeEnd(this->m_old_tile);
|
||||
if (IsTunnel(this->old_tile)) {
|
||||
this->is_tunnel = true;
|
||||
this->new_tile = GetOtherTunnelEnd(this->old_tile);
|
||||
} else { // IsBridge(old_tile)
|
||||
this->is_bridge = true;
|
||||
this->new_tile = GetOtherBridgeEnd(this->old_tile);
|
||||
}
|
||||
this->m_tiles_skipped = GetTunnelBridgeLength(this->m_new_tile, this->m_old_tile);
|
||||
this->tiles_skipped = GetTunnelBridgeLength(this->new_tile, this->old_tile);
|
||||
return;
|
||||
}
|
||||
assert(ReverseDiagDir(enterdir) == this->m_exitdir);
|
||||
assert(ReverseDiagDir(enterdir) == this->exitdir);
|
||||
}
|
||||
|
||||
/* normal or station tile, do one step */
|
||||
this->m_new_tile = TileAddByDiagDir(this->m_old_tile, this->m_exitdir);
|
||||
this->new_tile = TileAddByDiagDir(this->old_tile, this->exitdir);
|
||||
|
||||
/* special handling for stations */
|
||||
if (IsRailTT() && HasStationTileRail(this->m_new_tile)) {
|
||||
this->m_is_station = true;
|
||||
} else if (IsRoadTT() && IsStationRoadStopTile(this->m_new_tile)) {
|
||||
this->m_is_station = true;
|
||||
if (IsRailTT() && HasStationTileRail(this->new_tile)) {
|
||||
this->is_station = true;
|
||||
} else if (IsRoadTT() && IsStationRoadStopTile(this->new_tile)) {
|
||||
this->is_station = true;
|
||||
}
|
||||
}
|
||||
|
||||
/** stores track status (available trackdirs) for the new tile into m_new_td_bits */
|
||||
/** stores track status (available trackdirs) for the new tile into new_td_bits */
|
||||
inline bool QueryNewTileTrackStatus()
|
||||
{
|
||||
if (IsRailTT() && IsPlainRailTile(this->m_new_tile)) {
|
||||
this->m_new_td_bits = (TrackdirBits)(GetTrackBits(this->m_new_tile) * 0x101);
|
||||
if (IsRailTT() && IsPlainRailTile(this->new_tile)) {
|
||||
this->new_td_bits = (TrackdirBits)(GetTrackBits(this->new_tile) * 0x101);
|
||||
} else if (IsRoadTT()) {
|
||||
this->m_new_td_bits = GetTrackdirBitsForRoad(this->m_new_tile, this->IsTram() ? RTT_TRAM : RTT_ROAD);
|
||||
this->new_td_bits = GetTrackdirBitsForRoad(this->new_tile, this->IsTram() ? RTT_TRAM : RTT_ROAD);
|
||||
} else {
|
||||
this->m_new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(this->m_new_tile, TT(), 0));
|
||||
this->new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(this->new_tile, TT(), 0));
|
||||
}
|
||||
return (this->m_new_td_bits != TRACKDIR_BIT_NONE);
|
||||
return (this->new_td_bits != TRACKDIR_BIT_NONE);
|
||||
}
|
||||
|
||||
/** return true if we can leave m_old_tile in m_exitdir */
|
||||
/** return true if we can leave old_tile in exitdir */
|
||||
inline bool CanExitOldTile()
|
||||
{
|
||||
/* road stop can be left at one direction only unless it's a drive-through stop */
|
||||
if (IsRoadTT() && IsBayRoadStopTile(this->m_old_tile)) {
|
||||
DiagDirection exitdir = GetBayRoadStopDir(this->m_old_tile);
|
||||
if (exitdir != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
if (IsRoadTT() && IsBayRoadStopTile(this->old_tile)) {
|
||||
DiagDirection exitdir = GetBayRoadStopDir(this->old_tile);
|
||||
if (exitdir != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* single tram bits can only be left in one direction */
|
||||
if (this->IsTram()) {
|
||||
DiagDirection single_tram = GetSingleTramBit(this->m_old_tile);
|
||||
if (single_tram != INVALID_DIAGDIR && single_tram != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
DiagDirection single_tram = GetSingleTramBit(this->old_tile);
|
||||
if (single_tram != INVALID_DIAGDIR && single_tram != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* road depots can be also left in one direction only */
|
||||
if (IsRoadTT() && IsDepotTypeTile(this->m_old_tile, TT())) {
|
||||
DiagDirection exitdir = GetRoadDepotDirection(this->m_old_tile);
|
||||
if (exitdir != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
if (IsRoadTT() && IsDepotTypeTile(this->old_tile, TT())) {
|
||||
DiagDirection exitdir = GetRoadDepotDirection(this->old_tile);
|
||||
if (exitdir != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** return true if we can enter m_new_tile from m_exitdir */
|
||||
/** return true if we can enter new_tile from exitdir */
|
||||
inline bool CanEnterNewTile()
|
||||
{
|
||||
if (IsRoadTT() && IsBayRoadStopTile(this->m_new_tile)) {
|
||||
if (IsRoadTT() && IsBayRoadStopTile(this->new_tile)) {
|
||||
/* road stop can be entered from one direction only unless it's a drive-through stop */
|
||||
DiagDirection exitdir = GetBayRoadStopDir(this->m_new_tile);
|
||||
if (ReverseDiagDir(exitdir) != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
DiagDirection exitdir = GetBayRoadStopDir(this->new_tile);
|
||||
if (ReverseDiagDir(exitdir) != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* single tram bits can only be entered from one direction */
|
||||
if (this->IsTram()) {
|
||||
DiagDirection single_tram = this->GetSingleTramBit(this->m_new_tile);
|
||||
if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(this->m_exitdir)) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
DiagDirection single_tram = this->GetSingleTramBit(this->new_tile);
|
||||
if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(this->exitdir)) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* road and rail depots can also be entered from one direction only */
|
||||
if (IsRoadTT() && IsDepotTypeTile(this->m_new_tile, TT())) {
|
||||
DiagDirection exitdir = GetRoadDepotDirection(this->m_new_tile);
|
||||
if (ReverseDiagDir(exitdir) != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
if (IsRoadTT() && IsDepotTypeTile(this->new_tile, TT())) {
|
||||
DiagDirection exitdir = GetRoadDepotDirection(this->new_tile);
|
||||
if (ReverseDiagDir(exitdir) != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
/* don't try to enter other company's depots */
|
||||
if (GetTileOwner(this->m_new_tile) != this->m_veh_owner) {
|
||||
this->m_err = EC_OWNER;
|
||||
if (GetTileOwner(this->new_tile) != this->veh_owner) {
|
||||
this->err = EC_OWNER;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (IsRailTT() && IsDepotTypeTile(this->m_new_tile, TT())) {
|
||||
DiagDirection exitdir = GetRailDepotDirection(this->m_new_tile);
|
||||
if (ReverseDiagDir(exitdir) != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
if (IsRailTT() && IsDepotTypeTile(this->new_tile, TT())) {
|
||||
DiagDirection exitdir = GetRailDepotDirection(this->new_tile);
|
||||
if (ReverseDiagDir(exitdir) != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* rail transport is possible only on tiles with the same owner as vehicle */
|
||||
if (IsRailTT() && GetTileOwner(this->m_new_tile) != this->m_veh_owner) {
|
||||
if (IsRailTT() && GetTileOwner(this->new_tile) != this->veh_owner) {
|
||||
/* different owner */
|
||||
this->m_err = EC_NO_WAY;
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* rail transport is possible only on compatible rail types */
|
||||
if (IsRailTT()) {
|
||||
RailType rail_type = GetTileRailType(this->m_new_tile);
|
||||
if (!HasBit(this->m_railtypes, rail_type)) {
|
||||
RailType rail_type = GetTileRailType(this->new_tile);
|
||||
if (!HasBit(this->railtypes, rail_type)) {
|
||||
/* incompatible rail type */
|
||||
this->m_err = EC_RAIL_ROAD_TYPE;
|
||||
this->err = EC_RAIL_ROAD_TYPE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* road transport is possible only on compatible road types */
|
||||
if (IsRoadTT()) {
|
||||
const RoadVehicle *v = RoadVehicle::From(this->m_veh);
|
||||
RoadType roadtype = GetRoadType(this->m_new_tile, GetRoadTramType(v->roadtype));
|
||||
const RoadVehicle *v = RoadVehicle::From(this->veh);
|
||||
RoadType roadtype = GetRoadType(this->new_tile, GetRoadTramType(v->roadtype));
|
||||
if (!HasBit(v->compatible_roadtypes, roadtype)) {
|
||||
/* incompatible road type */
|
||||
this->m_err = EC_RAIL_ROAD_TYPE;
|
||||
this->err = EC_RAIL_ROAD_TYPE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* tunnel holes and bridge ramps can be entered only from proper direction */
|
||||
if (IsTileType(this->m_new_tile, MP_TUNNELBRIDGE)) {
|
||||
if (IsTunnel(this->m_new_tile)) {
|
||||
if (!this->m_is_tunnel) {
|
||||
DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(this->m_new_tile);
|
||||
if (tunnel_enterdir != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
if (IsTileType(this->new_tile, MP_TUNNELBRIDGE)) {
|
||||
if (IsTunnel(this->new_tile)) {
|
||||
if (!this->is_tunnel) {
|
||||
DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(this->new_tile);
|
||||
if (tunnel_enterdir != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else { // IsBridge(m_new_tile)
|
||||
if (!this->m_is_bridge) {
|
||||
DiagDirection ramp_enderdir = GetTunnelBridgeDirection(this->m_new_tile);
|
||||
if (ramp_enderdir != this->m_exitdir) {
|
||||
this->m_err = EC_NO_WAY;
|
||||
} else { // IsBridge(new_tile)
|
||||
if (!this->is_bridge) {
|
||||
DiagDirection ramp_enderdir = GetTunnelBridgeDirection(this->new_tile);
|
||||
if (ramp_enderdir != this->exitdir) {
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -373,16 +373,16 @@ protected:
|
|||
}
|
||||
|
||||
/* special handling for rail stations - get to the end of platform */
|
||||
if (IsRailTT() && this->m_is_station) {
|
||||
if (IsRailTT() && this->is_station) {
|
||||
/* entered railway station
|
||||
* get platform length */
|
||||
uint length = BaseStation::GetByTile(this->m_new_tile)->GetPlatformLength(this->m_new_tile, TrackdirToExitdir(this->m_old_td));
|
||||
uint length = BaseStation::GetByTile(this->new_tile)->GetPlatformLength(this->new_tile, TrackdirToExitdir(this->old_td));
|
||||
/* how big step we must do to get to the last platform tile? */
|
||||
this->m_tiles_skipped = length - 1;
|
||||
this->tiles_skipped = length - 1;
|
||||
/* move to the platform end */
|
||||
TileIndexDiff diff = TileOffsByDiagDir(this->m_exitdir);
|
||||
diff *= this->m_tiles_skipped;
|
||||
this->m_new_tile = TileAdd(this->m_new_tile, diff);
|
||||
TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
|
||||
diff *= this->tiles_skipped;
|
||||
this->new_tile = TileAdd(this->new_tile, diff);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -393,32 +393,32 @@ protected:
|
|||
inline bool ForcedReverse()
|
||||
{
|
||||
/* rail and road depots cause reversing */
|
||||
if (!IsWaterTT() && IsDepotTypeTile(this->m_old_tile, TT())) {
|
||||
DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(this->m_old_tile) : GetRoadDepotDirection(this->m_old_tile);
|
||||
if (exitdir != this->m_exitdir) {
|
||||
if (!IsWaterTT() && IsDepotTypeTile(this->old_tile, TT())) {
|
||||
DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(this->old_tile) : GetRoadDepotDirection(this->old_tile);
|
||||
if (exitdir != this->exitdir) {
|
||||
/* reverse */
|
||||
this->m_new_tile = this->m_old_tile;
|
||||
this->m_new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->m_old_td));
|
||||
this->m_exitdir = exitdir;
|
||||
this->m_tiles_skipped = 0;
|
||||
this->m_is_tunnel = false;
|
||||
this->m_is_bridge = false;
|
||||
this->m_is_station = false;
|
||||
this->new_tile = this->old_tile;
|
||||
this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
|
||||
this->exitdir = exitdir;
|
||||
this->tiles_skipped = 0;
|
||||
this->is_tunnel = false;
|
||||
this->is_bridge = false;
|
||||
this->is_station = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Single tram bits and standard road stops cause reversing. */
|
||||
if (IsRoadTT() && ((this->IsTram() && GetSingleTramBit(this->m_old_tile) == ReverseDiagDir(this->m_exitdir)) ||
|
||||
(IsBayRoadStopTile(this->m_old_tile) && GetBayRoadStopDir(this->m_old_tile) == ReverseDiagDir(this->m_exitdir)))) {
|
||||
if (IsRoadTT() && ((this->IsTram() && GetSingleTramBit(this->old_tile) == ReverseDiagDir(this->exitdir)) ||
|
||||
(IsBayRoadStopTile(this->old_tile) && GetBayRoadStopDir(this->old_tile) == ReverseDiagDir(this->exitdir)))) {
|
||||
/* reverse */
|
||||
this->m_new_tile = this->m_old_tile;
|
||||
this->m_new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->m_old_td));
|
||||
this->m_exitdir = ReverseDiagDir(this->m_exitdir);
|
||||
this->m_tiles_skipped = 0;
|
||||
this->m_is_tunnel = false;
|
||||
this->m_is_bridge = false;
|
||||
this->m_is_station = false;
|
||||
this->new_tile = this->old_tile;
|
||||
this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
|
||||
this->exitdir = ReverseDiagDir(this->exitdir);
|
||||
this->tiles_skipped = 0;
|
||||
this->is_tunnel = false;
|
||||
this->is_bridge = false;
|
||||
this->is_station = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -430,42 +430,42 @@ protected:
|
|||
{
|
||||
if (IsRoadTT() && !this->IsTram()) {
|
||||
/* if we reached the end of road, we can reverse the RV and continue moving */
|
||||
this->m_exitdir = ReverseDiagDir(this->m_exitdir);
|
||||
this->exitdir = ReverseDiagDir(this->exitdir);
|
||||
/* new tile will be the same as old one */
|
||||
this->m_new_tile = this->m_old_tile;
|
||||
this->new_tile = this->old_tile;
|
||||
/* set new trackdir bits to all reachable trackdirs */
|
||||
QueryNewTileTrackStatus();
|
||||
this->m_new_td_bits &= DiagdirReachesTrackdirs(this->m_exitdir);
|
||||
if (this->m_new_td_bits != TRACKDIR_BIT_NONE) {
|
||||
this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
|
||||
if (this->new_td_bits != TRACKDIR_BIT_NONE) {
|
||||
/* we have some trackdirs reachable after reversal */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
this->m_err = EC_NO_WAY;
|
||||
this->err = EC_NO_WAY;
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
/** Helper for pathfinders - get min/max speed on the m_old_tile/m_old_td */
|
||||
/** Helper for pathfinders - get min/max speed on the old_tile/old_td */
|
||||
int GetSpeedLimit(int *pmin_speed = nullptr) const
|
||||
{
|
||||
int min_speed = 0;
|
||||
int max_speed = INT_MAX; // no limit
|
||||
|
||||
/* Check for on-bridge speed limit */
|
||||
if (!IsWaterTT() && IsBridgeTile(this->m_old_tile)) {
|
||||
int spd = GetBridgeSpec(GetBridgeType(this->m_old_tile))->speed;
|
||||
if (!IsWaterTT() && IsBridgeTile(this->old_tile)) {
|
||||
int spd = GetBridgeSpec(GetBridgeType(this->old_tile))->speed;
|
||||
if (IsRoadTT()) spd *= 2;
|
||||
max_speed = std::min(max_speed, spd);
|
||||
}
|
||||
/* Check for speed limit imposed by railtype */
|
||||
if (IsRailTT()) {
|
||||
uint16_t rail_speed = GetRailTypeInfo(GetRailType(this->m_old_tile))->max_speed;
|
||||
uint16_t rail_speed = GetRailTypeInfo(GetRailType(this->old_tile))->max_speed;
|
||||
if (rail_speed > 0) max_speed = std::min<int>(max_speed, rail_speed);
|
||||
}
|
||||
if (IsRoadTT()) {
|
||||
/* max_speed is already in roadvehicle units, no need to further modify (divide by 2) */
|
||||
uint16_t road_speed = GetRoadTypeInfo(GetRoadType(this->m_old_tile, GetRoadTramType(RoadVehicle::From(this->m_veh)->roadtype)))->max_speed;
|
||||
uint16_t road_speed = GetRoadTypeInfo(GetRoadType(this->old_tile, GetRoadTramType(RoadVehicle::From(this->veh)->roadtype)))->max_speed;
|
||||
if (road_speed > 0) max_speed = std::min<int>(max_speed, road_speed);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,11 +165,11 @@ public:
|
|||
/* By using a TrackFollower we "play by the same rules" as the actual ship pathfinder */
|
||||
CFollowTrackWater ft;
|
||||
if (ft.Follow(tile, dir)) {
|
||||
if (this->tile_area.Contains(ft.m_new_tile)) {
|
||||
tiles_to_check.push_back(ft.m_new_tile);
|
||||
} else if (!ft.m_is_bridge) {
|
||||
assert(DistanceManhattan(ft.m_new_tile, tile) == 1);
|
||||
const auto side = DiagdirBetweenTiles(tile, ft.m_new_tile);
|
||||
if (this->tile_area.Contains(ft.new_tile)) {
|
||||
tiles_to_check.push_back(ft.new_tile);
|
||||
} else if (!ft.is_bridge) {
|
||||
assert(DistanceManhattan(ft.new_tile, tile) == 1);
|
||||
const auto side = DiagdirBetweenTiles(tile, ft.new_tile);
|
||||
const int local_x_or_y = DiagDirToAxis(side) == AXIS_X ? TileY(tile) - TileY(this->tile_area.tile) : TileX(tile) - TileX(this->tile_area.tile);
|
||||
SetBit(this->data.edge_traversability_bits[side], local_x_or_y);
|
||||
} else {
|
||||
|
|
|
@ -29,17 +29,17 @@ public:
|
|||
typedef CBinaryHeapT<Titem_> CPriorityQueue; ///< How the priority queue will be managed.
|
||||
|
||||
protected:
|
||||
CItemArray m_arr; ///< Here we store full item data (Titem_).
|
||||
COpenList m_open; ///< Hash table of pointers to open item data.
|
||||
CClosedList m_closed; ///< Hash table of pointers to closed item data.
|
||||
CPriorityQueue m_open_queue; ///< Priority queue of pointers to open item data.
|
||||
Titem *m_new_node; ///< New open node under construction.
|
||||
CItemArray items; ///< Here we store full item data (Titem_).
|
||||
COpenList open_nodes; ///< Hash table of pointers to open item data.
|
||||
CClosedList closed_nodes; ///< Hash table of pointers to closed item data.
|
||||
CPriorityQueue open_queue; ///< Priority queue of pointers to open item data.
|
||||
Titem *new_node; ///< New open node under construction.
|
||||
|
||||
public:
|
||||
/** default constructor */
|
||||
CNodeList_HashTableT() : m_open_queue(2048)
|
||||
CNodeList_HashTableT() : open_queue(2048)
|
||||
{
|
||||
this->m_new_node = nullptr;
|
||||
this->new_node = nullptr;
|
||||
}
|
||||
|
||||
/** destructor */
|
||||
|
@ -50,28 +50,28 @@ public:
|
|||
/** return number of open nodes */
|
||||
inline int OpenCount()
|
||||
{
|
||||
return this->m_open.Count();
|
||||
return this->open_nodes.Count();
|
||||
}
|
||||
|
||||
/** return number of closed nodes */
|
||||
inline int ClosedCount()
|
||||
{
|
||||
return this->m_closed.Count();
|
||||
return this->closed_nodes.Count();
|
||||
}
|
||||
|
||||
/** allocate new data item from m_arr */
|
||||
/** allocate new data item from items */
|
||||
inline Titem_ *CreateNewNode()
|
||||
{
|
||||
if (this->m_new_node == nullptr) this->m_new_node = &this->m_arr.emplace_back();
|
||||
return this->m_new_node;
|
||||
if (this->new_node == nullptr) this->new_node = &this->items.emplace_back();
|
||||
return this->new_node;
|
||||
}
|
||||
|
||||
/** Notify the nodelist that we don't want to discard the given node. */
|
||||
inline void FoundBestNode(Titem_ &item)
|
||||
{
|
||||
/* for now it is enough to invalidate m_new_node if it is our given node */
|
||||
if (&item == this->m_new_node) {
|
||||
this->m_new_node = nullptr;
|
||||
if (&item == this->new_node) {
|
||||
this->new_node = nullptr;
|
||||
}
|
||||
/* TODO: do we need to store best nodes found in some extra list/array? Probably not now. */
|
||||
}
|
||||
|
@ -79,19 +79,19 @@ public:
|
|||
/** insert given item as open node (into m_open and m_open_queue) */
|
||||
inline void InsertOpenNode(Titem_ &item)
|
||||
{
|
||||
assert(this->m_closed.Find(item.GetKey()) == nullptr);
|
||||
this->m_open.Push(item);
|
||||
this->m_open_queue.Include(&item);
|
||||
if (&item == this->m_new_node) {
|
||||
this->m_new_node = nullptr;
|
||||
assert(this->closed_nodes.Find(item.GetKey()) == nullptr);
|
||||
this->open_nodes.Push(item);
|
||||
this->open_queue.Include(&item);
|
||||
if (&item == this->new_node) {
|
||||
this->new_node = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/** return the best open node */
|
||||
inline Titem_ *GetBestOpenNode()
|
||||
{
|
||||
if (!this->m_open_queue.IsEmpty()) {
|
||||
return this->m_open_queue.Begin();
|
||||
if (!this->open_queue.IsEmpty()) {
|
||||
return this->open_queue.Begin();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -99,9 +99,9 @@ public:
|
|||
/** remove and return the best open node */
|
||||
inline Titem_ *PopBestOpenNode()
|
||||
{
|
||||
if (!this->m_open_queue.IsEmpty()) {
|
||||
Titem_ *item = this->m_open_queue.Shift();
|
||||
this->m_open.Pop(*item);
|
||||
if (!this->open_queue.IsEmpty()) {
|
||||
Titem_ *item = this->open_queue.Shift();
|
||||
this->open_nodes.Pop(*item);
|
||||
return item;
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -110,49 +110,49 @@ public:
|
|||
/** return the open node specified by a key or nullptr if not found */
|
||||
inline Titem_ *FindOpenNode(const Key &key)
|
||||
{
|
||||
Titem_ *item = this->m_open.Find(key);
|
||||
Titem_ *item = this->open_nodes.Find(key);
|
||||
return item;
|
||||
}
|
||||
|
||||
/** remove and return the open node specified by a key */
|
||||
inline Titem_ &PopOpenNode(const Key &key)
|
||||
{
|
||||
Titem_ &item = this->m_open.Pop(key);
|
||||
size_t idxPop = this->m_open_queue.FindIndex(item);
|
||||
this->m_open_queue.Remove(idxPop);
|
||||
Titem_ &item = this->open_nodes.Pop(key);
|
||||
size_t idxPop = this->open_queue.FindIndex(item);
|
||||
this->open_queue.Remove(idxPop);
|
||||
return item;
|
||||
}
|
||||
|
||||
/** close node */
|
||||
inline void InsertClosedNode(Titem_ &item)
|
||||
{
|
||||
assert(this->m_open.Find(item.GetKey()) == nullptr);
|
||||
this->m_closed.Push(item);
|
||||
assert(this->open_nodes.Find(item.GetKey()) == nullptr);
|
||||
this->closed_nodes.Push(item);
|
||||
}
|
||||
|
||||
/** return the closed node specified by a key or nullptr if not found */
|
||||
inline Titem_ *FindClosedNode(const Key &key)
|
||||
{
|
||||
Titem_ *item = this->m_closed.Find(key);
|
||||
Titem_ *item = this->closed_nodes.Find(key);
|
||||
return item;
|
||||
}
|
||||
|
||||
/** The number of items. */
|
||||
inline int TotalCount()
|
||||
{
|
||||
return this->m_arr.Length();
|
||||
return this->items.Length();
|
||||
}
|
||||
|
||||
/** Get a particular item. */
|
||||
inline Titem_ &ItemAt(int idx)
|
||||
{
|
||||
return this->m_arr[idx];
|
||||
return this->items[idx];
|
||||
}
|
||||
|
||||
/** Helper for creating output of this array. */
|
||||
template <class D> void Dump(D &dmp) const
|
||||
{
|
||||
dmp.WriteStructT("m_arr", &this->m_arr);
|
||||
dmp.WriteStructT("data", &this->items);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -56,24 +56,24 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables
|
||||
|
||||
|
||||
NodeList m_nodes; ///< node list multi-container
|
||||
NodeList nodes; ///< node list multi-container
|
||||
|
||||
protected:
|
||||
Node *m_pBestDestNode = nullptr; ///< pointer to the destination node found at last round
|
||||
Node *m_pBestIntermediateNode = nullptr; ///< here should be node closest to the destination if path not found
|
||||
const YAPFSettings *m_settings; ///< current settings (_settings_game.yapf)
|
||||
int m_max_search_nodes; ///< maximum number of nodes we are allowed to visit before we give up
|
||||
const VehicleType *m_veh = nullptr; ///< vehicle that we are trying to drive
|
||||
Node *best_dest_node = nullptr; ///< pointer to the destination node found at last round
|
||||
Node *best_intermediate_node = nullptr; ///< here should be node closest to the destination if path not found
|
||||
const YAPFSettings *settings; ///< current settings (_settings_game.yapf)
|
||||
int max_search_nodes; ///< maximum number of nodes we are allowed to visit before we give up
|
||||
const VehicleType *vehicle = nullptr; ///< vehicle that we are trying to drive
|
||||
|
||||
int m_stats_cost_calcs = 0; ///< stats - how many node's costs were calculated
|
||||
int m_stats_cache_hits = 0; ///< stats - how many node's costs were reused from cache
|
||||
int stats_cost_calcs = 0; ///< stats - how many node's costs were calculated
|
||||
int stats_cache_hits = 0; ///< stats - how many node's costs were reused from cache
|
||||
|
||||
public:
|
||||
int m_num_steps = 0; ///< this is there for debugging purposes (hope it doesn't hurt)
|
||||
int num_steps = 0; ///< this is there for debugging purposes (hope it doesn't hurt)
|
||||
|
||||
public:
|
||||
/** default constructor */
|
||||
inline CYapfBaseT() : m_settings(&_settings_game.pf.yapf), m_max_search_nodes(PfGetSettings().max_search_nodes) {}
|
||||
inline CYapfBaseT() : settings(&_settings_game.pf.yapf), max_search_nodes(PfGetSettings().max_search_nodes) {}
|
||||
|
||||
/** default destructor */
|
||||
~CYapfBaseT() {}
|
||||
|
@ -89,7 +89,7 @@ public:
|
|||
/** return current settings (can be custom - company based - but later) */
|
||||
inline const YAPFSettings &PfGetSettings() const
|
||||
{
|
||||
return *this->m_settings;
|
||||
return *this->settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -98,43 +98,43 @@ public:
|
|||
* - main loop that stops if:
|
||||
* - the destination was found
|
||||
* - or the open list is empty (no route to destination).
|
||||
* - or the maximum amount of loops reached - m_max_search_nodes (default = 10000)
|
||||
* - or the maximum amount of loops reached - max_search_nodes (default = 10000)
|
||||
* @return true if the path was found
|
||||
*/
|
||||
inline bool FindPath(const VehicleType *v)
|
||||
{
|
||||
this->m_veh = v;
|
||||
this->vehicle = v;
|
||||
|
||||
Yapf().PfSetStartupNodes();
|
||||
|
||||
for (;;) {
|
||||
this->m_num_steps++;
|
||||
Node *best_open_node = this->m_nodes.GetBestOpenNode();
|
||||
this->num_steps++;
|
||||
Node *best_open_node = this->nodes.GetBestOpenNode();
|
||||
if (best_open_node == nullptr) break;
|
||||
|
||||
if (Yapf().PfDetectDestination(*best_open_node)) {
|
||||
this->m_pBestDestNode = best_open_node;
|
||||
this->best_dest_node = best_open_node;
|
||||
break;
|
||||
}
|
||||
|
||||
Yapf().PfFollowNode(*best_open_node);
|
||||
if (this->m_max_search_nodes != 0 && this->m_nodes.ClosedCount() >= this->m_max_search_nodes) break;
|
||||
if (this->max_search_nodes != 0 && this->nodes.ClosedCount() >= this->max_search_nodes) break;
|
||||
|
||||
this->m_nodes.PopOpenNode(best_open_node->GetKey());
|
||||
this->m_nodes.InsertClosedNode(*best_open_node);
|
||||
this->nodes.PopOpenNode(best_open_node->GetKey());
|
||||
this->nodes.InsertClosedNode(*best_open_node);
|
||||
}
|
||||
|
||||
const bool destination_found = (this->m_pBestDestNode != nullptr);
|
||||
const bool destination_found = (this->best_dest_node != nullptr);
|
||||
|
||||
if (_debug_yapf_level >= 3) {
|
||||
const UnitID veh_idx = (this->m_veh != nullptr) ? this->m_veh->unitnumber : 0;
|
||||
const UnitID veh_idx = (this->vehicle != nullptr) ? this->vehicle->unitnumber : 0;
|
||||
const char ttc = Yapf().TransportTypeChar();
|
||||
const float cache_hit_ratio = (this->m_stats_cache_hits == 0) ? 0.0f : ((float)this->m_stats_cache_hits / (float)(this->m_stats_cache_hits + this->m_stats_cost_calcs) * 100.0f);
|
||||
const int cost = destination_found ? this->m_pBestDestNode->m_cost : -1;
|
||||
const int dist = destination_found ? this->m_pBestDestNode->m_estimate - this->m_pBestDestNode->m_cost : -1;
|
||||
const float cache_hit_ratio = (this->stats_cache_hits == 0) ? 0.0f : ((float)this->stats_cache_hits / (float)(this->stats_cache_hits + this->stats_cost_calcs) * 100.0f);
|
||||
const int cost = destination_found ? this->best_dest_node->cost : -1;
|
||||
const int dist = destination_found ? this->best_dest_node->estimate - this->best_dest_node->cost : -1;
|
||||
|
||||
Debug(yapf, 3, "[YAPF{}]{}{:4d} - {} rounds - {} open - {} closed - CHR {:4.1f}% - C {} D {}",
|
||||
ttc, destination_found ? '-' : '!', veh_idx, this->m_num_steps, this->m_nodes.OpenCount(), this->m_nodes.ClosedCount(), cache_hit_ratio, cost, dist
|
||||
ttc, destination_found ? '-' : '!', veh_idx, this->num_steps, this->nodes.OpenCount(), this->nodes.ClosedCount(), cache_hit_ratio, cost, dist
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ public:
|
|||
*/
|
||||
inline Node *GetBestNode()
|
||||
{
|
||||
return (this->m_pBestDestNode != nullptr) ? this->m_pBestDestNode : this->m_pBestIntermediateNode;
|
||||
return (this->best_dest_node != nullptr) ? this->best_dest_node : this->best_intermediate_node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,7 +156,7 @@ public:
|
|||
*/
|
||||
inline Node &CreateNewNode()
|
||||
{
|
||||
Node &node = *this->m_nodes.CreateNewNode();
|
||||
Node &node = *this->nodes.CreateNewNode();
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -165,8 +165,8 @@ public:
|
|||
{
|
||||
Yapf().PfNodeCacheFetch(n);
|
||||
/* insert the new node only if it is not there */
|
||||
if (this->m_nodes.FindOpenNode(n.m_key) == nullptr) {
|
||||
this->m_nodes.InsertOpenNode(n);
|
||||
if (this->nodes.FindOpenNode(n.key) == nullptr) {
|
||||
this->nodes.InsertOpenNode(n);
|
||||
} else {
|
||||
/* if we are here, it means that node is already there - how it is possible?
|
||||
* probably the train is in the position that both its ends point to the same tile/exit-dir
|
||||
|
@ -177,11 +177,11 @@ public:
|
|||
/** add multiple nodes - direct children of the given node */
|
||||
inline void AddMultipleNodes(Node *parent, const TrackFollower &tf)
|
||||
{
|
||||
bool is_choice = (KillFirstBit(tf.m_new_td_bits) != TRACKDIR_BIT_NONE);
|
||||
for (TrackdirBits rtds = tf.m_new_td_bits; rtds != TRACKDIR_BIT_NONE; rtds = KillFirstBit(rtds)) {
|
||||
bool is_choice = (KillFirstBit(tf.new_td_bits) != TRACKDIR_BIT_NONE);
|
||||
for (TrackdirBits rtds = tf.new_td_bits; rtds != TRACKDIR_BIT_NONE; rtds = KillFirstBit(rtds)) {
|
||||
Trackdir td = (Trackdir)FindFirstBit(rtds);
|
||||
Node &n = Yapf().CreateNewNode();
|
||||
n.Set(parent, tf.m_new_tile, td, is_choice);
|
||||
n.Set(parent, tf.new_tile, td, is_choice);
|
||||
Yapf().AddNewNode(n, tf);
|
||||
}
|
||||
}
|
||||
|
@ -197,11 +197,11 @@ public:
|
|||
void PruneIntermediateNodeBranch(Node *n)
|
||||
{
|
||||
bool intermediate_on_branch = false;
|
||||
while (n != nullptr && (n->m_segment->m_end_segment_reason & ESRB_CHOICE_FOLLOWS) == 0) {
|
||||
if (n == Yapf().m_pBestIntermediateNode) intermediate_on_branch = true;
|
||||
n = n->m_parent;
|
||||
while (n != nullptr && (n->segment->end_segment_reason & ESRB_CHOICE_FOLLOWS) == 0) {
|
||||
if (n == Yapf().best_intermediate_node) intermediate_on_branch = true;
|
||||
n = n->parent;
|
||||
}
|
||||
if (intermediate_on_branch) Yapf().m_pBestIntermediateNode = n;
|
||||
if (intermediate_on_branch) Yapf().best_intermediate_node = n;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,47 +211,47 @@ public:
|
|||
void AddNewNode(Node &n, const TrackFollower &tf)
|
||||
{
|
||||
/* evaluate the node */
|
||||
bool bCached = Yapf().PfNodeCacheFetch(n);
|
||||
if (!bCached) {
|
||||
this->m_stats_cost_calcs++;
|
||||
bool cached = Yapf().PfNodeCacheFetch(n);
|
||||
if (!cached) {
|
||||
this->stats_cost_calcs++;
|
||||
} else {
|
||||
this->m_stats_cache_hits++;
|
||||
this->stats_cache_hits++;
|
||||
}
|
||||
|
||||
bool bValid = Yapf().PfCalcCost(n, &tf);
|
||||
bool valid = Yapf().PfCalcCost(n, &tf);
|
||||
|
||||
if (bValid) bValid = Yapf().PfCalcEstimate(n);
|
||||
if (valid) valid = Yapf().PfCalcEstimate(n);
|
||||
|
||||
/* have the cost or estimate callbacks marked this node as invalid? */
|
||||
if (!bValid) return;
|
||||
if (!valid) return;
|
||||
|
||||
/* The new node can be set as the best intermediate node only once we're
|
||||
* certain it will be finalized by being inserted into the open list. */
|
||||
bool set_intermediate = this->m_max_search_nodes > 0 && (this->m_pBestIntermediateNode == nullptr || (this->m_pBestIntermediateNode->GetCostEstimate() - this->m_pBestIntermediateNode->GetCost()) > (n.GetCostEstimate() - n.GetCost()));
|
||||
bool set_intermediate = this->max_search_nodes > 0 && (this->best_intermediate_node == nullptr || (this->best_intermediate_node->GetCostEstimate() - this->best_intermediate_node->GetCost()) > (n.GetCostEstimate() - n.GetCost()));
|
||||
|
||||
/* check new node against open list */
|
||||
Node *openNode = this->m_nodes.FindOpenNode(n.GetKey());
|
||||
if (openNode != nullptr) {
|
||||
Node *open_node = this->nodes.FindOpenNode(n.GetKey());
|
||||
if (open_node != nullptr) {
|
||||
/* another node exists with the same key in the open list
|
||||
* is it better than new one? */
|
||||
if (n.GetCostEstimate() < openNode->GetCostEstimate()) {
|
||||
if (n.GetCostEstimate() < open_node->GetCostEstimate()) {
|
||||
/* update the old node by value from new one */
|
||||
this->m_nodes.PopOpenNode(n.GetKey());
|
||||
*openNode = n;
|
||||
this->nodes.PopOpenNode(n.GetKey());
|
||||
*open_node = n;
|
||||
/* add the updated old node back to open list */
|
||||
this->m_nodes.InsertOpenNode(*openNode);
|
||||
if (set_intermediate) this->m_pBestIntermediateNode = openNode;
|
||||
this->nodes.InsertOpenNode(*open_node);
|
||||
if (set_intermediate) this->best_intermediate_node = open_node;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* check new node against closed list */
|
||||
Node *closedNode = this->m_nodes.FindClosedNode(n.GetKey());
|
||||
if (closedNode != nullptr) {
|
||||
Node *closed_node = this->nodes.FindClosedNode(n.GetKey());
|
||||
if (closed_node != nullptr) {
|
||||
/* another node exists with the same key in the closed list
|
||||
* is it better than new one? */
|
||||
int node_est = n.GetCostEstimate();
|
||||
int closed_est = closedNode->GetCostEstimate();
|
||||
int closed_est = closed_node->GetCostEstimate();
|
||||
if (node_est < closed_est) {
|
||||
/* If this assert occurs, you have probably problem in
|
||||
* your Tderived::PfCalcCost() or Tderived::PfCalcEstimate().
|
||||
|
@ -265,19 +265,19 @@ public:
|
|||
}
|
||||
/* the new node is really new
|
||||
* add it to the open list */
|
||||
this->m_nodes.InsertOpenNode(n);
|
||||
if (set_intermediate) this->m_pBestIntermediateNode = &n;
|
||||
this->nodes.InsertOpenNode(n);
|
||||
if (set_intermediate) this->best_intermediate_node = &n;
|
||||
}
|
||||
|
||||
const VehicleType * GetVehicle() const
|
||||
{
|
||||
return this->m_veh;
|
||||
return this->vehicle;
|
||||
}
|
||||
|
||||
void DumpBase(DumpTarget &dmp) const
|
||||
{
|
||||
dmp.WriteStructT("m_nodes", &this->m_nodes);
|
||||
dmp.WriteValue("m_num_steps", this->m_num_steps);
|
||||
dmp.WriteStructT("nodes", &this->nodes);
|
||||
dmp.WriteValue("num_steps", this->num_steps);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables
|
||||
|
||||
protected:
|
||||
TileIndex m_orgTile; ///< origin tile
|
||||
TrackdirBits m_orgTrackdirs; ///< origin trackdir mask
|
||||
TileIndex origin_tile; ///< origin tile
|
||||
TrackdirBits origin_trackdirs; ///< origin trackdir mask
|
||||
|
||||
/** to access inherited path finder */
|
||||
inline Tpf &Yapf()
|
||||
|
@ -40,18 +40,18 @@ public:
|
|||
/** Set origin tile / trackdir mask */
|
||||
void SetOrigin(TileIndex tile, TrackdirBits trackdirs)
|
||||
{
|
||||
this->m_orgTile = tile;
|
||||
this->m_orgTrackdirs = trackdirs;
|
||||
this->origin_tile = tile;
|
||||
this->origin_trackdirs = trackdirs;
|
||||
}
|
||||
|
||||
/** Called when YAPF needs to place origin nodes into open list */
|
||||
void PfSetStartupNodes()
|
||||
{
|
||||
bool is_choice = (KillFirstBit(this->m_orgTrackdirs) != TRACKDIR_BIT_NONE);
|
||||
for (TrackdirBits tdb = this->m_orgTrackdirs; tdb != TRACKDIR_BIT_NONE; tdb = KillFirstBit(tdb)) {
|
||||
bool is_choice = (KillFirstBit(this->origin_trackdirs) != TRACKDIR_BIT_NONE);
|
||||
for (TrackdirBits tdb = this->origin_trackdirs; tdb != TRACKDIR_BIT_NONE; tdb = KillFirstBit(tdb)) {
|
||||
Trackdir td = (Trackdir)FindFirstBit(tdb);
|
||||
Node &n1 = Yapf().CreateNewNode();
|
||||
n1.Set(nullptr, this->m_orgTile, td, is_choice);
|
||||
n1.Set(nullptr, this->origin_tile, td, is_choice);
|
||||
Yapf().AddStartupNode(n1);
|
||||
}
|
||||
}
|
||||
|
@ -67,12 +67,12 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables
|
||||
|
||||
protected:
|
||||
TileIndex m_orgTile; ///< first origin tile
|
||||
Trackdir m_orgTd; ///< first origin trackdir
|
||||
TileIndex m_revTile; ///< second (reversed) origin tile
|
||||
Trackdir m_revTd; ///< second (reversed) origin trackdir
|
||||
int m_reverse_penalty; ///< penalty to be added for using the reversed origin
|
||||
bool m_treat_first_red_two_way_signal_as_eol; ///< in some cases (leaving station) we need to handle first two-way signal differently
|
||||
TileIndex origin_tile; ///< first origin tile
|
||||
Trackdir origin_td; ///< first origin trackdir
|
||||
TileIndex reverse_tile; ///< second (reverse) origin tile
|
||||
Trackdir reverse_td; ///< second (reverse) origin trackdir
|
||||
int reverse_penalty; ///< penalty to be added for using the reverse origin
|
||||
bool treat_first_red_two_way_signal_as_eol; ///< in some cases (leaving station) we need to handle first two-way signal differently
|
||||
|
||||
/** to access inherited path finder */
|
||||
inline Tpf &Yapf()
|
||||
|
@ -84,26 +84,26 @@ public:
|
|||
/** set origin (tiles, trackdirs, etc.) */
|
||||
void SetOrigin(TileIndex tile, Trackdir td, TileIndex tiler = INVALID_TILE, Trackdir tdr = INVALID_TRACKDIR, int reverse_penalty = 0, bool treat_first_red_two_way_signal_as_eol = true)
|
||||
{
|
||||
this->m_orgTile = tile;
|
||||
this->m_orgTd = td;
|
||||
this->m_revTile = tiler;
|
||||
this->m_revTd = tdr;
|
||||
this->m_reverse_penalty = reverse_penalty;
|
||||
this->m_treat_first_red_two_way_signal_as_eol = treat_first_red_two_way_signal_as_eol;
|
||||
this->origin_tile = tile;
|
||||
this->origin_td = td;
|
||||
this->reverse_tile = tiler;
|
||||
this->reverse_td = tdr;
|
||||
this->reverse_penalty = reverse_penalty;
|
||||
this->treat_first_red_two_way_signal_as_eol = treat_first_red_two_way_signal_as_eol;
|
||||
}
|
||||
|
||||
/** Called when YAPF needs to place origin nodes into open list */
|
||||
void PfSetStartupNodes()
|
||||
{
|
||||
if (this->m_orgTile != INVALID_TILE && this->m_orgTd != INVALID_TRACKDIR) {
|
||||
if (this->origin_tile != INVALID_TILE && this->origin_td != INVALID_TRACKDIR) {
|
||||
Node &n1 = Yapf().CreateNewNode();
|
||||
n1.Set(nullptr, this->m_orgTile, this->m_orgTd, false);
|
||||
n1.Set(nullptr, this->origin_tile, this->origin_td, false);
|
||||
Yapf().AddStartupNode(n1);
|
||||
}
|
||||
if (this->m_revTile != INVALID_TILE && this->m_revTd != INVALID_TRACKDIR) {
|
||||
if (this->reverse_tile != INVALID_TILE && this->reverse_td != INVALID_TRACKDIR) {
|
||||
Node &n2 = Yapf().CreateNewNode();
|
||||
n2.Set(nullptr, this->m_revTile, this->m_revTd, false);
|
||||
n2.m_cost = this->m_reverse_penalty;
|
||||
n2.Set(nullptr, this->reverse_tile, this->reverse_td, false);
|
||||
n2.cost = this->reverse_penalty;
|
||||
Yapf().AddStartupNode(n2);
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ public:
|
|||
/** return true if first two-way signal should be treated as dead end */
|
||||
inline bool TreatFirstRedTwoWaySignalAsEOL()
|
||||
{
|
||||
return Yapf().PfGetSettings().rail_firstred_twoway_eol && this->m_treat_first_red_two_way_signal_as_eol;
|
||||
return Yapf().PfGetSettings().rail_firstred_twoway_eol && this->treat_first_red_two_way_signal_as_eol;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -125,15 +125,15 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables
|
||||
|
||||
protected:
|
||||
TileIndex m_destTile; ///< destination tile
|
||||
TrackdirBits m_destTrackdirs; ///< destination trackdir mask
|
||||
TileIndex dest_tile; ///< destination tile
|
||||
TrackdirBits dest_trackdirs; ///< destination trackdir mask
|
||||
|
||||
public:
|
||||
/** set the destination tile / more trackdirs */
|
||||
void SetDestination(TileIndex tile, TrackdirBits trackdirs)
|
||||
{
|
||||
this->m_destTile = tile;
|
||||
this->m_destTrackdirs = trackdirs;
|
||||
this->dest_tile = tile;
|
||||
this->dest_trackdirs = trackdirs;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -147,19 +147,19 @@ public:
|
|||
/** Called by YAPF to detect if node ends in the desired destination */
|
||||
inline bool PfDetectDestination(Node &n)
|
||||
{
|
||||
return (n.m_key.m_tile == this->m_destTile) && HasTrackdir(this->m_destTrackdirs, n.GetTrackdir());
|
||||
return (n.key.tile == this->dest_tile) && HasTrackdir(this->dest_trackdirs, n.GetTrackdir());
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::m_estimate
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::estimate
|
||||
*/
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
|
||||
static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
|
||||
if (this->PfDetectDestination(n)) {
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -167,15 +167,15 @@ public:
|
|||
DiagDirection exitdir = TrackdirToExitdir(n.GetTrackdir());
|
||||
int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
|
||||
int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
|
||||
int x2 = 2 * TileX(this->m_destTile);
|
||||
int y2 = 2 * TileY(this->m_destTile);
|
||||
int x2 = 2 * TileX(this->dest_tile);
|
||||
int y2 = 2 * TileY(this->dest_tile);
|
||||
int dx = abs(x1 - x2);
|
||||
int dy = abs(y1 - y2);
|
||||
int dmin = std::min(dx, dy);
|
||||
int dxy = abs(dx - dy);
|
||||
int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
||||
n.m_estimate = n.m_cost + d;
|
||||
assert(n.m_estimate >= n.m_parent->m_estimate);
|
||||
n.estimate = n.cost + d;
|
||||
assert(n.estimate >= n.parent->estimate);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -73,25 +73,25 @@ struct CSegmentCostCacheT : public CSegmentCostCacheBase {
|
|||
using Heap = std::deque<Tsegment>;
|
||||
typedef typename Tsegment::Key Key; ///< key to hash table
|
||||
|
||||
HashTable m_map;
|
||||
Heap m_heap;
|
||||
HashTable map;
|
||||
Heap heap;
|
||||
|
||||
inline CSegmentCostCacheT() {}
|
||||
|
||||
/** flush (clear) the cache */
|
||||
inline void Flush()
|
||||
{
|
||||
this->m_map.Clear();
|
||||
this->m_heap.clear();
|
||||
this->map.Clear();
|
||||
this->heap.clear();
|
||||
}
|
||||
|
||||
inline Tsegment &Get(Key &key, bool *found)
|
||||
{
|
||||
Tsegment *item = this->m_map.Find(key);
|
||||
Tsegment *item = this->map.Find(key);
|
||||
if (item == nullptr) {
|
||||
*found = false;
|
||||
item = &m_heap.emplace_back(key);
|
||||
this->m_map.Push(*item);
|
||||
item = &heap.emplace_back(key);
|
||||
this->map.Push(*item);
|
||||
} else {
|
||||
*found = true;
|
||||
}
|
||||
|
@ -116,10 +116,10 @@ public:
|
|||
using LocalCache = std::deque<CachedData>;
|
||||
|
||||
protected:
|
||||
Cache &m_global_cache;
|
||||
LocalCache m_local_cache;
|
||||
Cache &global_cache;
|
||||
LocalCache local_cache;
|
||||
|
||||
inline CYapfSegmentCostCacheGlobalT() : m_global_cache(stGetGlobalCache()) {};
|
||||
inline CYapfSegmentCostCacheGlobalT() : global_cache(stGetGlobalCache()) {};
|
||||
|
||||
/** to access inherited path finder */
|
||||
inline Tpf &Yapf()
|
||||
|
@ -150,12 +150,12 @@ public:
|
|||
CacheKey key(n.GetKey());
|
||||
|
||||
if (!Yapf().CanUseGlobalCache(n)) {
|
||||
Yapf().ConnectNodeToCachedData(n, this->m_local_cache.emplace_back(key));
|
||||
Yapf().ConnectNodeToCachedData(n, this->local_cache.emplace_back(key));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool found;
|
||||
CachedData &item = this->m_global_cache.Get(key, &found);
|
||||
CachedData &item = this->global_cache.Get(key, &found);
|
||||
Yapf().ConnectNodeToCachedData(n, item);
|
||||
return found;
|
||||
}
|
||||
|
|
|
@ -45,26 +45,26 @@ protected:
|
|||
* @note maximum cost doesn't work with caching enabled
|
||||
* @todo fix maximum cost failing with caching (e.g. FS#2900)
|
||||
*/
|
||||
int m_max_cost;
|
||||
bool m_disable_cache;
|
||||
std::vector<int> m_sig_look_ahead_costs;
|
||||
int max_cost;
|
||||
bool disable_cache;
|
||||
std::vector<int> sig_look_ahead_costs;
|
||||
|
||||
public:
|
||||
bool m_stopped_on_first_two_way_signal;
|
||||
protected:
|
||||
bool stopped_on_first_two_way_signal;
|
||||
|
||||
protected:
|
||||
static const int s_max_segment_cost = 10000;
|
||||
|
||||
CYapfCostRailT() : m_max_cost(0), m_disable_cache(false), m_stopped_on_first_two_way_signal(false)
|
||||
CYapfCostRailT() : max_cost(0), disable_cache(false), stopped_on_first_two_way_signal(false)
|
||||
{
|
||||
/* pre-compute look-ahead penalties into array */
|
||||
int p0 = Yapf().PfGetSettings().rail_look_ahead_signal_p0;
|
||||
int p1 = Yapf().PfGetSettings().rail_look_ahead_signal_p1;
|
||||
int p2 = Yapf().PfGetSettings().rail_look_ahead_signal_p2;
|
||||
this->m_sig_look_ahead_costs.clear();
|
||||
this->m_sig_look_ahead_costs.reserve(Yapf().PfGetSettings().rail_look_ahead_max_signals);
|
||||
this->sig_look_ahead_costs.clear();
|
||||
this->sig_look_ahead_costs.reserve(Yapf().PfGetSettings().rail_look_ahead_max_signals);
|
||||
for (uint i = 0; i < Yapf().PfGetSettings().rail_look_ahead_max_signals; i++) {
|
||||
this->m_sig_look_ahead_costs.push_back(p0 + i * (p1 + i * p2));
|
||||
this->sig_look_ahead_costs.push_back(p0 + i * (p1 + i * p2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,8 @@ public:
|
|||
/** The cost for reserved tiles, including skipped ones. */
|
||||
inline int ReservationCost(Node &n, TileIndex tile, Trackdir trackdir, int skipped)
|
||||
{
|
||||
if (n.m_num_signals_passed >= this->m_sig_look_ahead_costs.size() / 2) return 0;
|
||||
if (!IsPbsSignal(n.m_last_signal_type)) return 0;
|
||||
if (n.num_signals_passed >= this->sig_look_ahead_costs.size() / 2) return 0;
|
||||
if (!IsPbsSignal(n.last_signal_type)) return 0;
|
||||
|
||||
if (IsRailStationTile(tile) && IsAnyStationTileReserved(tile, trackdir, skipped)) {
|
||||
return Yapf().PfGetSettings().rail_pbs_station_penalty * (skipped + 1);
|
||||
|
@ -167,19 +167,19 @@ public:
|
|||
bool has_signal_along = HasSignalOnTrackdir(tile, trackdir);
|
||||
if (has_signal_against && !has_signal_along && IsOnewaySignal(tile, TrackdirToTrack(trackdir))) {
|
||||
/* one-way signal in opposite direction */
|
||||
n.m_segment->m_end_segment_reason |= ESRB_DEAD_END;
|
||||
n.segment->end_segment_reason |= ESRB_DEAD_END;
|
||||
} else {
|
||||
if (has_signal_along) {
|
||||
SignalState sig_state = GetSignalStateByTrackdir(tile, trackdir);
|
||||
SignalType sig_type = GetSignalType(tile, TrackdirToTrack(trackdir));
|
||||
|
||||
n.m_last_signal_type = sig_type;
|
||||
n.last_signal_type = sig_type;
|
||||
|
||||
/* cache the look-ahead polynomial constant only if we didn't pass more signals than the look-ahead limit is */
|
||||
int look_ahead_cost = (n.m_num_signals_passed < this->m_sig_look_ahead_costs.size()) ? this->m_sig_look_ahead_costs[n.m_num_signals_passed] : 0;
|
||||
int look_ahead_cost = (n.num_signals_passed < this->sig_look_ahead_costs.size()) ? this->sig_look_ahead_costs[n.num_signals_passed] : 0;
|
||||
if (sig_state != SIGNAL_STATE_RED) {
|
||||
/* green signal */
|
||||
n.flags_u.flags_s.m_last_signal_was_red = false;
|
||||
n.flags_u.flags_s.last_signal_was_red = false;
|
||||
/* negative look-ahead red-signal penalties would cause problems later, so use them as positive penalties for green signal */
|
||||
if (look_ahead_cost < 0) {
|
||||
/* add its negation to the cost */
|
||||
|
@ -188,15 +188,15 @@ public:
|
|||
} else {
|
||||
/* we have a red signal in our direction
|
||||
* was it first signal which is two-way? */
|
||||
if (!IsPbsSignal(sig_type) && Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.m_choice_seen && has_signal_against && n.m_num_signals_passed == 0) {
|
||||
if (!IsPbsSignal(sig_type) && Yapf().TreatFirstRedTwoWaySignalAsEOL() && n.flags_u.flags_s.choice_seen && has_signal_against && n.num_signals_passed == 0) {
|
||||
/* yes, the first signal is two-way red signal => DEAD END. Prune this branch... */
|
||||
Yapf().PruneIntermediateNodeBranch(&n);
|
||||
n.m_segment->m_end_segment_reason |= ESRB_DEAD_END;
|
||||
Yapf().m_stopped_on_first_two_way_signal = true;
|
||||
n.segment->end_segment_reason |= ESRB_DEAD_END;
|
||||
Yapf().stopped_on_first_two_way_signal = true;
|
||||
return -1;
|
||||
}
|
||||
n.m_last_red_signal_type = sig_type;
|
||||
n.flags_u.flags_s.m_last_signal_was_red = true;
|
||||
n.last_red_signal_type = sig_type;
|
||||
n.flags_u.flags_s.last_signal_was_red = true;
|
||||
|
||||
/* look-ahead signal penalty */
|
||||
if (!IsPbsSignal(sig_type) && look_ahead_cost > 0) {
|
||||
|
@ -205,7 +205,7 @@ public:
|
|||
}
|
||||
|
||||
/* special signal penalties */
|
||||
if (n.m_num_signals_passed == 0) {
|
||||
if (n.num_signals_passed == 0) {
|
||||
switch (sig_type) {
|
||||
case SIGTYPE_COMBO:
|
||||
case SIGTYPE_EXIT: cost += Yapf().PfGetSettings().rail_firstred_exit_penalty; break; // first signal is red pre-signal-exit
|
||||
|
@ -216,13 +216,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
n.m_num_signals_passed++;
|
||||
n.m_segment->m_last_signal_tile = tile;
|
||||
n.m_segment->m_last_signal_td = trackdir;
|
||||
n.num_signals_passed++;
|
||||
n.segment->last_signal_tile = tile;
|
||||
n.segment->last_signal_td = trackdir;
|
||||
}
|
||||
|
||||
if (has_signal_against && IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) {
|
||||
cost += n.m_num_signals_passed < Yapf().PfGetSettings().rail_look_ahead_max_signals ? Yapf().PfGetSettings().rail_pbs_signal_back_penalty : 0;
|
||||
cost += n.num_signals_passed < Yapf().PfGetSettings().rail_look_ahead_max_signals ? Yapf().PfGetSettings().rail_pbs_signal_back_penalty : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ public:
|
|||
public:
|
||||
inline void SetMaxCost(int max_cost)
|
||||
{
|
||||
this->m_max_cost = max_cost;
|
||||
this->max_cost = max_cost;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -260,18 +260,18 @@ public:
|
|||
*/
|
||||
inline bool PfCalcCost(Node &n, const TrackFollower *tf)
|
||||
{
|
||||
assert(!n.flags_u.flags_s.m_targed_seen);
|
||||
assert(tf->m_new_tile == n.m_key.m_tile);
|
||||
assert((HasTrackdir(tf->m_new_td_bits, n.m_key.m_td)));
|
||||
assert(!n.flags_u.flags_s.target_seen);
|
||||
assert(tf->new_tile == n.key.tile);
|
||||
assert((HasTrackdir(tf->new_td_bits, n.key.td)));
|
||||
|
||||
/* Does the node have some parent node? */
|
||||
bool has_parent = (n.m_parent != nullptr);
|
||||
bool has_parent = (n.parent != nullptr);
|
||||
|
||||
/* Do we already have a cached segment? */
|
||||
CachedData &segment = *n.m_segment;
|
||||
bool is_cached_segment = (segment.m_cost >= 0);
|
||||
CachedData &segment = *n.segment;
|
||||
bool is_cached_segment = (segment.cost >= 0);
|
||||
|
||||
int parent_cost = has_parent ? n.m_parent->m_cost : 0;
|
||||
int parent_cost = has_parent ? n.parent->cost : 0;
|
||||
|
||||
/* Each node cost contains 2 or 3 main components:
|
||||
* 1. Transition cost - cost of the move from previous node (tile):
|
||||
|
@ -305,11 +305,11 @@ public:
|
|||
|
||||
const Train *v = Yapf().GetVehicle();
|
||||
|
||||
/* start at n.m_key.m_tile / n.m_key.m_td and walk to the end of segment */
|
||||
TILE cur(n.m_key.m_tile, n.m_key.m_td);
|
||||
/* start at n.key.tile / n.key.td and walk to the end of segment */
|
||||
TILE cur(n.key.tile, n.key.td);
|
||||
|
||||
/* the previous tile will be needed for transition cost calculations */
|
||||
TILE prev = !has_parent ? TILE() : TILE(n.m_parent->GetLastTile(), n.m_parent->GetLastTrackdir());
|
||||
TILE prev = !has_parent ? TILE() : TILE(n.parent->GetLastTile(), n.parent->GetLastTrackdir());
|
||||
|
||||
EndSegmentReasonBits end_segment_reason = ESRB_NONE;
|
||||
|
||||
|
@ -337,17 +337,17 @@ public:
|
|||
/* It is the right time now to look if we can reuse the cached segment cost. */
|
||||
if (is_cached_segment) {
|
||||
/* Yes, we already know the segment cost. */
|
||||
segment_cost = segment.m_cost;
|
||||
segment_cost = segment.cost;
|
||||
/* We know also the reason why the segment ends. */
|
||||
end_segment_reason = segment.m_end_segment_reason;
|
||||
end_segment_reason = segment.end_segment_reason;
|
||||
/* We will need also some information about the last signal (if it was red). */
|
||||
if (segment.m_last_signal_tile != INVALID_TILE) {
|
||||
assert(HasSignalOnTrackdir(segment.m_last_signal_tile, segment.m_last_signal_td));
|
||||
SignalState sig_state = GetSignalStateByTrackdir(segment.m_last_signal_tile, segment.m_last_signal_td);
|
||||
if (segment.last_signal_tile != INVALID_TILE) {
|
||||
assert(HasSignalOnTrackdir(segment.last_signal_tile, segment.last_signal_td));
|
||||
SignalState sig_state = GetSignalStateByTrackdir(segment.last_signal_tile, segment.last_signal_td);
|
||||
bool is_red = (sig_state == SIGNAL_STATE_RED);
|
||||
n.flags_u.flags_s.m_last_signal_was_red = is_red;
|
||||
n.flags_u.flags_s.last_signal_was_red = is_red;
|
||||
if (is_red) {
|
||||
n.m_last_red_signal_type = GetSignalType(segment.m_last_signal_tile, TrackdirToTrack(segment.m_last_signal_td));
|
||||
n.last_red_signal_type = GetSignalType(segment.last_signal_tile, TrackdirToTrack(segment.last_signal_td));
|
||||
}
|
||||
}
|
||||
/* No further calculation needed. */
|
||||
|
@ -365,7 +365,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
segment_cost += Yapf().OneTileCost(cur.tile, cur.td);
|
||||
|
||||
/* If we skipped some tunnel/bridge/station tiles, add their base cost */
|
||||
segment_cost += YAPF_TILE_LENGTH * tf->m_tiles_skipped;
|
||||
segment_cost += YAPF_TILE_LENGTH * tf->tiles_skipped;
|
||||
|
||||
/* Slope cost. */
|
||||
segment_cost += Yapf().SlopeCost(cur.tile, cur.td);
|
||||
|
@ -374,9 +374,9 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
segment_cost += Yapf().SignalCost(n, cur.tile, cur.td);
|
||||
|
||||
/* Reserved tiles. */
|
||||
segment_cost += Yapf().ReservationCost(n, cur.tile, cur.td, tf->m_tiles_skipped);
|
||||
segment_cost += Yapf().ReservationCost(n, cur.tile, cur.td, tf->tiles_skipped);
|
||||
|
||||
end_segment_reason = segment.m_end_segment_reason;
|
||||
end_segment_reason = segment.end_segment_reason;
|
||||
|
||||
/* Tests for 'potential target' reasons to close the segment. */
|
||||
if (cur.tile == prev.tile) {
|
||||
|
@ -401,21 +401,21 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
/* Arbitrary maximum tiles to follow to avoid infinite loops. */
|
||||
uint max_tiles = 20;
|
||||
while (ft.Follow(t, td)) {
|
||||
assert(t != ft.m_new_tile);
|
||||
t = ft.m_new_tile;
|
||||
assert(t != ft.new_tile);
|
||||
t = ft.new_tile;
|
||||
if (t == cur.tile || --max_tiles == 0) {
|
||||
/* We looped back on ourself or found another loop, bail out. */
|
||||
td = INVALID_TRACKDIR;
|
||||
break;
|
||||
}
|
||||
if (KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
|
||||
if (KillFirstBit(ft.new_td_bits) != TRACKDIR_BIT_NONE) {
|
||||
/* We encountered a junction; it's going to be too complex to
|
||||
* handle this perfectly, so just bail out. There is no simple
|
||||
* free path, so try the other possibilities. */
|
||||
td = INVALID_TRACKDIR;
|
||||
break;
|
||||
}
|
||||
td = RemoveFirstTrackdir(&ft.m_new_td_bits);
|
||||
td = RemoveFirstTrackdir(&ft.new_td_bits);
|
||||
/* If this is a safe waiting position we're done searching for it */
|
||||
if (IsSafeWaitingPosition(v, t, td, true, _settings_game.pf.forbid_90_deg)) break;
|
||||
}
|
||||
|
@ -432,9 +432,9 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
/* Waypoint is also a good reason to finish. */
|
||||
end_segment_reason |= ESRB_WAYPOINT;
|
||||
|
||||
} else if (tf->m_is_station) {
|
||||
} else if (tf->is_station) {
|
||||
/* Station penalties. */
|
||||
uint platform_length = tf->m_tiles_skipped + 1;
|
||||
uint platform_length = tf->tiles_skipped + 1;
|
||||
/* We don't know yet if the station is our target or not. Act like
|
||||
* if it is pass-through station (not our destination). */
|
||||
segment_cost += Yapf().PfGetSettings().rail_station_penalty * platform_length;
|
||||
|
@ -450,13 +450,13 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
|
||||
/* Apply min/max speed penalties only when inside the look-ahead radius. Otherwise
|
||||
* it would cause desync in MP. */
|
||||
if (n.m_num_signals_passed < this->m_sig_look_ahead_costs.size())
|
||||
if (n.num_signals_passed < this->sig_look_ahead_costs.size())
|
||||
{
|
||||
int min_speed = 0;
|
||||
int max_speed = tf->GetSpeedLimit(&min_speed);
|
||||
int max_veh_speed = std::min<int>(v->GetDisplayMaxSpeed(), v->current_order.GetMaxSpeed());
|
||||
if (max_speed < max_veh_speed) {
|
||||
extra_cost += YAPF_TILE_LENGTH * (max_veh_speed - max_speed) * (4 + tf->m_tiles_skipped) / max_veh_speed;
|
||||
extra_cost += YAPF_TILE_LENGTH * (max_veh_speed - max_speed) * (4 + tf->tiles_skipped) / max_veh_speed;
|
||||
}
|
||||
if (min_speed > max_veh_speed) {
|
||||
extra_cost += YAPF_TILE_LENGTH * (min_speed - max_veh_speed);
|
||||
|
@ -465,7 +465,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
|
||||
/* Finish if we already exceeded the maximum path cost (i.e. when
|
||||
* searching for the nearest depot). */
|
||||
if (this->m_max_cost > 0 && (parent_cost + segment_entry_cost + segment_cost) > this->m_max_cost) {
|
||||
if (this->max_cost > 0 && (parent_cost + segment_entry_cost + segment_cost) > this->max_cost) {
|
||||
end_segment_reason |= ESRB_PATH_TOO_LONG;
|
||||
}
|
||||
|
||||
|
@ -474,9 +474,9 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
tf_local.Init(v, Yapf().GetCompatibleRailTypes());
|
||||
|
||||
if (!tf_local.Follow(cur.tile, cur.td)) {
|
||||
assert(tf_local.m_err != TrackFollower::EC_NONE);
|
||||
assert(tf_local.err != TrackFollower::EC_NONE);
|
||||
/* Can't move to the next tile (EOL?). */
|
||||
if (tf_local.m_err == TrackFollower::EC_RAIL_ROAD_TYPE) {
|
||||
if (tf_local.err == TrackFollower::EC_RAIL_ROAD_TYPE) {
|
||||
end_segment_reason |= ESRB_RAIL_TYPE;
|
||||
} else {
|
||||
end_segment_reason |= ESRB_DEAD_END;
|
||||
|
@ -489,14 +489,14 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
}
|
||||
|
||||
/* Check if the next tile is not a choice. */
|
||||
if (KillFirstBit(tf_local.m_new_td_bits) != TRACKDIR_BIT_NONE) {
|
||||
if (KillFirstBit(tf_local.new_td_bits) != TRACKDIR_BIT_NONE) {
|
||||
/* More than one segment will follow. Close this one. */
|
||||
end_segment_reason |= ESRB_CHOICE_FOLLOWS;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Gather the next tile/trackdir/tile_type/rail_type. */
|
||||
TILE next(tf_local.m_new_tile, (Trackdir)FindFirstBit(tf_local.m_new_td_bits));
|
||||
TILE next(tf_local.new_tile, (Trackdir)FindFirstBit(tf_local.new_td_bits));
|
||||
|
||||
if (TrackFollower::DoTrackMasking() && IsTileType(next.tile, MP_RAILWAY)) {
|
||||
if (HasSignalOnTrackdir(next.tile, next.td) && IsPbsSignal(GetSignalType(next.tile, TrackdirToTrack(next.td)))) {
|
||||
|
@ -517,7 +517,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
}
|
||||
|
||||
/* Avoid infinite looping. */
|
||||
if (next.tile == n.m_key.m_tile && next.td == n.m_key.m_td) {
|
||||
if (next.tile == n.key.tile && next.td == n.key.td) {
|
||||
end_segment_reason |= ESRB_INFINITE_LOOP;
|
||||
break;
|
||||
}
|
||||
|
@ -525,7 +525,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
if (segment_cost > s_max_segment_cost) {
|
||||
/* Potentially in the infinite loop (or only very long segment?). We should
|
||||
* not force it to finish prematurely unless we are on a regular tile. */
|
||||
if (IsTileType(tf->m_new_tile, MP_RAILWAY)) {
|
||||
if (IsTileType(tf->new_tile, MP_RAILWAY)) {
|
||||
end_segment_reason |= ESRB_SEGMENT_TOO_LONG;
|
||||
break;
|
||||
}
|
||||
|
@ -557,8 +557,8 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
/* Update the segment if needed. */
|
||||
if (!is_cached_segment) {
|
||||
/* Write back the segment information so it can be reused the next time. */
|
||||
segment.m_cost = segment_cost;
|
||||
segment.m_end_segment_reason = end_segment_reason & ESRB_CACHED_MASK;
|
||||
segment.cost = segment_cost;
|
||||
segment.end_segment_reason = end_segment_reason & ESRB_CACHED_MASK;
|
||||
/* Save end of segment back to the node. */
|
||||
n.SetLastTileTrackdir(cur.tile, cur.td);
|
||||
}
|
||||
|
@ -571,13 +571,13 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
|
||||
/* Special costs for the case we have reached our target. */
|
||||
if (target_seen) {
|
||||
n.flags_u.flags_s.m_targed_seen = true;
|
||||
n.flags_u.flags_s.target_seen = true;
|
||||
/* Last-red and last-red-exit penalties. */
|
||||
if (n.flags_u.flags_s.m_last_signal_was_red) {
|
||||
if (n.m_last_red_signal_type == SIGTYPE_EXIT) {
|
||||
if (n.flags_u.flags_s.last_signal_was_red) {
|
||||
if (n.last_red_signal_type == SIGTYPE_EXIT) {
|
||||
/* last signal was red pre-signal-exit */
|
||||
extra_cost += Yapf().PfGetSettings().rail_lastred_exit_penalty;
|
||||
} else if (!IsPbsSignal(n.m_last_red_signal_type)) {
|
||||
} else if (!IsPbsSignal(n.last_red_signal_type)) {
|
||||
/* Last signal was red, but not exit or path signal. */
|
||||
extra_cost += Yapf().PfGetSettings().rail_lastred_penalty;
|
||||
}
|
||||
|
@ -596,30 +596,30 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
|
|||
}
|
||||
|
||||
/* total node cost */
|
||||
n.m_cost = parent_cost + segment_entry_cost + segment_cost + extra_cost;
|
||||
n.cost = parent_cost + segment_entry_cost + segment_cost + extra_cost;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool CanUseGlobalCache(Node &n) const
|
||||
{
|
||||
return !this->m_disable_cache
|
||||
&& (n.m_parent != nullptr)
|
||||
&& (n.m_parent->m_num_signals_passed >= this->m_sig_look_ahead_costs.size());
|
||||
return !this->disable_cache
|
||||
&& (n.parent != nullptr)
|
||||
&& (n.parent->num_signals_passed >= this->sig_look_ahead_costs.size());
|
||||
}
|
||||
|
||||
inline void ConnectNodeToCachedData(Node &n, CachedData &ci)
|
||||
{
|
||||
n.m_segment = &ci;
|
||||
if (n.m_segment->m_cost < 0) {
|
||||
n.m_segment->m_last_tile = n.m_key.m_tile;
|
||||
n.m_segment->m_last_td = n.m_key.m_td;
|
||||
n.segment = &ci;
|
||||
if (n.segment->cost < 0) {
|
||||
n.segment->last_tile = n.key.tile;
|
||||
n.segment->last_td = n.key.td;
|
||||
}
|
||||
}
|
||||
|
||||
void DisableCache(bool disable)
|
||||
{
|
||||
this->m_disable_cache = disable;
|
||||
this->disable_cache = disable;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -16,23 +16,23 @@
|
|||
|
||||
class CYapfDestinationRailBase {
|
||||
protected:
|
||||
RailTypes m_compatible_railtypes;
|
||||
RailTypes compatible_railtypes;
|
||||
|
||||
public:
|
||||
void SetDestination(const Train *v, bool override_rail_type = false)
|
||||
{
|
||||
this->m_compatible_railtypes = v->compatible_railtypes;
|
||||
if (override_rail_type) this->m_compatible_railtypes |= GetRailTypeInfo(v->railtype)->compatible_railtypes;
|
||||
this->compatible_railtypes = v->compatible_railtypes;
|
||||
if (override_rail_type) this->compatible_railtypes |= GetRailTypeInfo(v->railtype)->compatible_railtypes;
|
||||
}
|
||||
|
||||
bool IsCompatibleRailType(RailType rt)
|
||||
{
|
||||
return HasBit(this->m_compatible_railtypes, rt);
|
||||
return HasBit(this->compatible_railtypes, rt);
|
||||
}
|
||||
|
||||
RailTypes GetCompatibleRailTypes() const
|
||||
{
|
||||
return this->m_compatible_railtypes;
|
||||
return this->compatible_railtypes;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -64,11 +64,11 @@ public:
|
|||
|
||||
/**
|
||||
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::m_estimate
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::estimate
|
||||
*/
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -102,11 +102,11 @@ public:
|
|||
|
||||
/**
|
||||
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::m_estimate.
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::estimate.
|
||||
*/
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -119,10 +119,10 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables
|
||||
|
||||
protected:
|
||||
TileIndex m_destTile;
|
||||
TrackdirBits m_destTrackdirs;
|
||||
StationID m_dest_station_id;
|
||||
bool m_any_depot;
|
||||
TileIndex dest_tile;
|
||||
TrackdirBits dest_trackdirs;
|
||||
StationID dest_station_id;
|
||||
bool any_depot;
|
||||
|
||||
/** to access inherited path finder */
|
||||
Tpf &Yapf()
|
||||
|
@ -133,7 +133,7 @@ protected:
|
|||
public:
|
||||
void SetDestination(const Train *v)
|
||||
{
|
||||
this->m_any_depot = false;
|
||||
this->any_depot = false;
|
||||
switch (v->current_order.GetType()) {
|
||||
case OT_GOTO_WAYPOINT:
|
||||
if (!Waypoint::Get(v->current_order.GetDestination())->IsSingleTile()) {
|
||||
|
@ -147,21 +147,21 @@ public:
|
|||
[[fallthrough]];
|
||||
|
||||
case OT_GOTO_STATION:
|
||||
this->m_destTile = CalcClosestStationTile(v->current_order.GetDestination(), v->tile, v->current_order.IsType(OT_GOTO_STATION) ? STATION_RAIL : STATION_WAYPOINT);
|
||||
this->m_dest_station_id = v->current_order.GetDestination();
|
||||
this->m_destTrackdirs = INVALID_TRACKDIR_BIT;
|
||||
this->dest_tile = CalcClosestStationTile(v->current_order.GetDestination(), v->tile, v->current_order.IsType(OT_GOTO_STATION) ? STATION_RAIL : STATION_WAYPOINT);
|
||||
this->dest_station_id = v->current_order.GetDestination();
|
||||
this->dest_trackdirs = INVALID_TRACKDIR_BIT;
|
||||
break;
|
||||
|
||||
case OT_GOTO_DEPOT:
|
||||
if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
|
||||
this->m_any_depot = true;
|
||||
this->any_depot = true;
|
||||
}
|
||||
[[fallthrough]];
|
||||
|
||||
default:
|
||||
this->m_destTile = v->dest_tile;
|
||||
this->m_dest_station_id = INVALID_STATION;
|
||||
this->m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0));
|
||||
this->dest_tile = v->dest_tile;
|
||||
this->dest_station_id = INVALID_STATION;
|
||||
this->dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0));
|
||||
break;
|
||||
}
|
||||
this->CYapfDestinationRailBase::SetDestination(v);
|
||||
|
@ -176,29 +176,29 @@ public:
|
|||
/** Called by YAPF to detect if node ends in the desired destination */
|
||||
inline bool PfDetectDestination(TileIndex tile, Trackdir td)
|
||||
{
|
||||
if (this->m_dest_station_id != INVALID_STATION) {
|
||||
if (this->dest_station_id != INVALID_STATION) {
|
||||
return HasStationTileRail(tile)
|
||||
&& (GetStationIndex(tile) == this->m_dest_station_id)
|
||||
&& (GetStationIndex(tile) == this->dest_station_id)
|
||||
&& (GetRailStationTrack(tile) == TrackdirToTrack(td));
|
||||
}
|
||||
|
||||
if (this->m_any_depot) {
|
||||
if (this->any_depot) {
|
||||
return IsRailDepotTile(tile);
|
||||
}
|
||||
|
||||
return (tile == this->m_destTile) && HasTrackdir(this->m_destTrackdirs, td);
|
||||
return (tile == this->dest_tile) && HasTrackdir(this->dest_trackdirs, td);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by YAPF to calculate cost estimate. Calculates distance to the destination
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::m_estimate
|
||||
* adds it to the actual cost from origin and stores the sum to the Node::estimate
|
||||
*/
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
|
||||
static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
|
||||
if (this->PfDetectDestination(n)) {
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -206,15 +206,15 @@ public:
|
|||
DiagDirection exitdir = TrackdirToExitdir(n.GetLastTrackdir());
|
||||
int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
|
||||
int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
|
||||
int x2 = 2 * TileX(this->m_destTile);
|
||||
int y2 = 2 * TileY(this->m_destTile);
|
||||
int x2 = 2 * TileX(this->dest_tile);
|
||||
int y2 = 2 * TileY(this->dest_tile);
|
||||
int dx = abs(x1 - x2);
|
||||
int dy = abs(y1 - y2);
|
||||
int dmin = std::min(dx, dy);
|
||||
int dxy = abs(dx - dy);
|
||||
int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
||||
n.m_estimate = n.m_cost + d;
|
||||
assert(n.m_estimate >= n.m_parent->m_estimate);
|
||||
n.estimate = n.cost + d;
|
||||
assert(n.estimate >= n.parent->estimate);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -15,32 +15,32 @@
|
|||
|
||||
/** Yapf Node Key that evaluates hash from (and compares) tile & exit dir. */
|
||||
struct CYapfNodeKeyExitDir {
|
||||
TileIndex m_tile;
|
||||
Trackdir m_td;
|
||||
DiagDirection m_exitdir;
|
||||
TileIndex tile;
|
||||
Trackdir td;
|
||||
DiagDirection exitdir;
|
||||
|
||||
inline void Set(TileIndex tile, Trackdir td)
|
||||
{
|
||||
this->m_tile = tile;
|
||||
this->m_td = td;
|
||||
this->m_exitdir = (this->m_td == INVALID_TRACKDIR) ? INVALID_DIAGDIR : TrackdirToExitdir(this->m_td);
|
||||
this->tile = tile;
|
||||
this->td = td;
|
||||
this->exitdir = (this->td == INVALID_TRACKDIR) ? INVALID_DIAGDIR : TrackdirToExitdir(this->td);
|
||||
}
|
||||
|
||||
inline int CalcHash() const
|
||||
{
|
||||
return this->m_exitdir | (this->m_tile.base() << 2);
|
||||
return this->exitdir | (this->tile.base() << 2);
|
||||
}
|
||||
|
||||
inline bool operator==(const CYapfNodeKeyExitDir &other) const
|
||||
{
|
||||
return this->m_tile == other.m_tile && this->m_exitdir == other.m_exitdir;
|
||||
return this->tile == other.tile && this->exitdir == other.exitdir;
|
||||
}
|
||||
|
||||
void Dump(DumpTarget &dmp) const
|
||||
{
|
||||
dmp.WriteTile("m_tile", this->m_tile);
|
||||
dmp.WriteEnumT("m_td", this->m_td);
|
||||
dmp.WriteEnumT("m_exitdir", this->m_exitdir);
|
||||
dmp.WriteTile("tile", this->tile);
|
||||
dmp.WriteEnumT("td", this->td);
|
||||
dmp.WriteEnumT("exitdir", this->exitdir);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -48,12 +48,12 @@ struct CYapfNodeKeyTrackDir : public CYapfNodeKeyExitDir
|
|||
{
|
||||
inline int CalcHash() const
|
||||
{
|
||||
return this->m_td | (this->m_tile.base() << 4);
|
||||
return this->td | (this->tile.base() << 4);
|
||||
}
|
||||
|
||||
inline bool operator==(const CYapfNodeKeyTrackDir &other) const
|
||||
{
|
||||
return this->m_tile == other.m_tile && this->m_td == other.m_td;
|
||||
return this->tile == other.tile && this->td == other.td;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,74 +63,74 @@ struct CYapfNodeT {
|
|||
typedef Tkey_ Key;
|
||||
typedef Tnode Node;
|
||||
|
||||
Tkey_ m_key;
|
||||
Node *m_hash_next;
|
||||
Node *m_parent;
|
||||
int m_cost;
|
||||
int m_estimate;
|
||||
bool m_is_choice;
|
||||
Tkey_ key;
|
||||
Node *hash_next;
|
||||
Node *parent;
|
||||
int cost;
|
||||
int estimate;
|
||||
bool is_choice;
|
||||
|
||||
inline void Set(Node *parent, TileIndex tile, Trackdir td, bool is_choice)
|
||||
{
|
||||
this->m_key.Set(tile, td);
|
||||
this->m_hash_next = nullptr;
|
||||
this->m_parent = parent;
|
||||
this->m_cost = 0;
|
||||
this->m_estimate = 0;
|
||||
this->m_is_choice = is_choice;
|
||||
this->key.Set(tile, td);
|
||||
this->hash_next = nullptr;
|
||||
this->parent = parent;
|
||||
this->cost = 0;
|
||||
this->estimate = 0;
|
||||
this->is_choice = is_choice;
|
||||
}
|
||||
|
||||
inline Node *GetHashNext()
|
||||
{
|
||||
return this->m_hash_next;
|
||||
return this->hash_next;
|
||||
}
|
||||
|
||||
inline void SetHashNext(Node *pNext)
|
||||
{
|
||||
this->m_hash_next = pNext;
|
||||
this->hash_next = pNext;
|
||||
}
|
||||
|
||||
inline TileIndex GetTile() const
|
||||
{
|
||||
return this->m_key.m_tile;
|
||||
return this->key.tile;
|
||||
}
|
||||
|
||||
inline Trackdir GetTrackdir() const
|
||||
{
|
||||
return this->m_key.m_td;
|
||||
return this->key.td;
|
||||
}
|
||||
|
||||
inline const Tkey_ &GetKey() const
|
||||
{
|
||||
return this->m_key;
|
||||
return this->key;
|
||||
}
|
||||
|
||||
inline int GetCost() const
|
||||
{
|
||||
return this->m_cost;
|
||||
return this->cost;
|
||||
}
|
||||
|
||||
inline int GetCostEstimate() const
|
||||
{
|
||||
return this->m_estimate;
|
||||
return this->estimate;
|
||||
}
|
||||
|
||||
inline bool GetIsChoice() const
|
||||
{
|
||||
return this->m_is_choice;
|
||||
return this->is_choice;
|
||||
}
|
||||
|
||||
inline bool operator<(const Node &other) const
|
||||
{
|
||||
return this->m_estimate < other.m_estimate;
|
||||
return this->estimate < other.estimate;
|
||||
}
|
||||
|
||||
void Dump(DumpTarget &dmp) const
|
||||
{
|
||||
dmp.WriteStructT("m_key", &this->m_key);
|
||||
dmp.WriteStructT("m_parent", this->m_parent);
|
||||
dmp.WriteValue("m_cost", this->m_cost);
|
||||
dmp.WriteValue("m_estimate", this->m_estimate);
|
||||
dmp.WriteStructT("key", &this->key);
|
||||
dmp.WriteStructT("parent", this->parent);
|
||||
dmp.WriteValue("cost", this->cost);
|
||||
dmp.WriteValue("estimate", this->estimate);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
/** key for cached segment cost for rail YAPF */
|
||||
struct CYapfRailSegmentKey
|
||||
{
|
||||
uint32_t m_value;
|
||||
uint32_t value;
|
||||
|
||||
inline CYapfRailSegmentKey(const CYapfNodeKeyTrackDir &node_key)
|
||||
{
|
||||
|
@ -28,32 +28,32 @@ struct CYapfRailSegmentKey
|
|||
|
||||
inline void Set(const CYapfRailSegmentKey &src)
|
||||
{
|
||||
this->m_value = src.m_value;
|
||||
this->value = src.value;
|
||||
}
|
||||
|
||||
inline void Set(const CYapfNodeKeyTrackDir &node_key)
|
||||
{
|
||||
this->m_value = (node_key.m_tile.base() << 4) | node_key.m_td;
|
||||
this->value = (node_key.tile.base() << 4) | node_key.td;
|
||||
}
|
||||
|
||||
inline int32_t CalcHash() const
|
||||
{
|
||||
return this->m_value;
|
||||
return this->value;
|
||||
}
|
||||
|
||||
inline TileIndex GetTile() const
|
||||
{
|
||||
return (TileIndex)(this->m_value >> 4);
|
||||
return (TileIndex)(this->value >> 4);
|
||||
}
|
||||
|
||||
inline Trackdir GetTrackdir() const
|
||||
{
|
||||
return (Trackdir)(this->m_value & 0x0F);
|
||||
return (Trackdir)(this->value & 0x0F);
|
||||
}
|
||||
|
||||
inline bool operator==(const CYapfRailSegmentKey &other) const
|
||||
{
|
||||
return this->m_value == other.m_value;
|
||||
return this->value == other.value;
|
||||
}
|
||||
|
||||
void Dump(DumpTarget &dmp) const
|
||||
|
@ -68,46 +68,46 @@ struct CYapfRailSegment
|
|||
{
|
||||
typedef CYapfRailSegmentKey Key;
|
||||
|
||||
CYapfRailSegmentKey m_key;
|
||||
TileIndex m_last_tile = INVALID_TILE;
|
||||
Trackdir m_last_td = INVALID_TRACKDIR;
|
||||
int m_cost = -1;
|
||||
TileIndex m_last_signal_tile = INVALID_TILE;
|
||||
Trackdir m_last_signal_td = INVALID_TRACKDIR;
|
||||
EndSegmentReasonBits m_end_segment_reason = ESRB_NONE;
|
||||
CYapfRailSegment *m_hash_next = nullptr;
|
||||
CYapfRailSegmentKey key;
|
||||
TileIndex last_tile = INVALID_TILE;
|
||||
Trackdir last_td = INVALID_TRACKDIR;
|
||||
int cost = -1;
|
||||
TileIndex last_signal_tile = INVALID_TILE;
|
||||
Trackdir last_signal_td = INVALID_TRACKDIR;
|
||||
EndSegmentReasonBits end_segment_reason = ESRB_NONE;
|
||||
CYapfRailSegment *hash_next = nullptr;
|
||||
|
||||
inline CYapfRailSegment(const CYapfRailSegmentKey &key) : m_key(key) {}
|
||||
inline CYapfRailSegment(const CYapfRailSegmentKey &key) : key(key) {}
|
||||
|
||||
inline const Key &GetKey() const
|
||||
{
|
||||
return this->m_key;
|
||||
return this->key;
|
||||
}
|
||||
|
||||
inline TileIndex GetTile() const
|
||||
{
|
||||
return this->m_key.GetTile();
|
||||
return this->key.GetTile();
|
||||
}
|
||||
|
||||
inline CYapfRailSegment *GetHashNext()
|
||||
{
|
||||
return this->m_hash_next;
|
||||
return this->hash_next;
|
||||
}
|
||||
|
||||
inline void SetHashNext(CYapfRailSegment *next)
|
||||
{
|
||||
this->m_hash_next = next;
|
||||
this->hash_next = next;
|
||||
}
|
||||
|
||||
void Dump(DumpTarget &dmp) const
|
||||
{
|
||||
dmp.WriteStructT("m_key", &this->m_key);
|
||||
dmp.WriteTile("m_last_tile", this->m_last_tile);
|
||||
dmp.WriteEnumT("m_last_td", this->m_last_td);
|
||||
dmp.WriteValue("m_cost", this->m_cost);
|
||||
dmp.WriteTile("m_last_signal_tile", this->m_last_signal_tile);
|
||||
dmp.WriteEnumT("m_last_signal_td", this->m_last_signal_td);
|
||||
dmp.WriteEnumT("m_end_segment_reason", this->m_end_segment_reason);
|
||||
dmp.WriteStructT("key", &this->key);
|
||||
dmp.WriteTile("last_tile", this->last_tile);
|
||||
dmp.WriteEnumT("last_td", this->last_td);
|
||||
dmp.WriteValue("cost", this->cost);
|
||||
dmp.WriteTile("last_signal_tile", this->last_signal_tile);
|
||||
dmp.WriteEnumT("last_signal_td", this->last_signal_td);
|
||||
dmp.WriteEnumT("end_segment_reason", this->end_segment_reason);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -119,27 +119,27 @@ struct CYapfRailNodeT
|
|||
typedef CYapfNodeT<Tkey_, CYapfRailNodeT<Tkey_> > base;
|
||||
typedef CYapfRailSegment CachedData;
|
||||
|
||||
CYapfRailSegment *m_segment;
|
||||
uint16_t m_num_signals_passed;
|
||||
CYapfRailSegment *segment;
|
||||
uint16_t num_signals_passed;
|
||||
union {
|
||||
uint32_t m_inherited_flags;
|
||||
uint32_t inherited_flags;
|
||||
struct {
|
||||
bool m_targed_seen;
|
||||
bool m_choice_seen;
|
||||
bool m_last_signal_was_red;
|
||||
bool target_seen;
|
||||
bool choice_seen;
|
||||
bool last_signal_was_red;
|
||||
} flags_s;
|
||||
} flags_u;
|
||||
SignalType m_last_red_signal_type;
|
||||
SignalType m_last_signal_type;
|
||||
SignalType last_red_signal_type;
|
||||
SignalType last_signal_type;
|
||||
|
||||
inline void Set(CYapfRailNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
|
||||
{
|
||||
this->base::Set(parent, tile, td, is_choice);
|
||||
this->m_segment = nullptr;
|
||||
this->segment = nullptr;
|
||||
if (parent == nullptr) {
|
||||
this->m_num_signals_passed = 0;
|
||||
this->flags_u.m_inherited_flags = 0;
|
||||
this->m_last_red_signal_type = SIGTYPE_BLOCK;
|
||||
this->num_signals_passed = 0;
|
||||
this->flags_u.inherited_flags = 0;
|
||||
this->last_red_signal_type = SIGTYPE_BLOCK;
|
||||
/* We use PBS as initial signal type because if we are in
|
||||
* a PBS section and need to route, i.e. we're at a safe
|
||||
* waiting point of a station, we need to account for the
|
||||
|
@ -150,33 +150,33 @@ struct CYapfRailNodeT
|
|||
* then avoiding that train with help of the reservation
|
||||
* costs is not a bad thing, actually it would probably
|
||||
* be a good thing to do. */
|
||||
this->m_last_signal_type = SIGTYPE_PBS;
|
||||
this->last_signal_type = SIGTYPE_PBS;
|
||||
} else {
|
||||
this->m_num_signals_passed = parent->m_num_signals_passed;
|
||||
this->flags_u.m_inherited_flags = parent->flags_u.m_inherited_flags;
|
||||
this->m_last_red_signal_type = parent->m_last_red_signal_type;
|
||||
this->m_last_signal_type = parent->m_last_signal_type;
|
||||
this->num_signals_passed = parent->num_signals_passed;
|
||||
this->flags_u.inherited_flags = parent->flags_u.inherited_flags;
|
||||
this->last_red_signal_type = parent->last_red_signal_type;
|
||||
this->last_signal_type = parent->last_signal_type;
|
||||
}
|
||||
this->flags_u.flags_s.m_choice_seen |= is_choice;
|
||||
this->flags_u.flags_s.choice_seen |= is_choice;
|
||||
}
|
||||
|
||||
inline TileIndex GetLastTile() const
|
||||
{
|
||||
assert(this->m_segment != nullptr);
|
||||
return this->m_segment->m_last_tile;
|
||||
assert(this->segment != nullptr);
|
||||
return this->segment->last_tile;
|
||||
}
|
||||
|
||||
inline Trackdir GetLastTrackdir() const
|
||||
{
|
||||
assert(this->m_segment != nullptr);
|
||||
return this->m_segment->m_last_td;
|
||||
assert(this->segment != nullptr);
|
||||
return this->segment->last_td;
|
||||
}
|
||||
|
||||
inline void SetLastTileTrackdir(TileIndex tile, Trackdir td)
|
||||
{
|
||||
assert(this->m_segment != nullptr);
|
||||
this->m_segment->m_last_tile = tile;
|
||||
this->m_segment->m_last_td = td;
|
||||
assert(this->segment != nullptr);
|
||||
this->segment->last_tile = tile;
|
||||
this->segment->last_td = td;
|
||||
}
|
||||
|
||||
template <class Tbase, class Tfunc, class Tpf>
|
||||
|
@ -190,9 +190,9 @@ struct CYapfRailNodeT
|
|||
if (!((obj.*func)(cur, cur_td))) return false;
|
||||
|
||||
if (!ft.Follow(cur, cur_td)) break;
|
||||
cur = ft.m_new_tile;
|
||||
assert(KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE);
|
||||
cur_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
cur = ft.new_tile;
|
||||
assert(KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE);
|
||||
cur_td = FindFirstTrackdir(ft.new_td_bits);
|
||||
}
|
||||
|
||||
return (obj.*func)(cur, cur_td);
|
||||
|
@ -201,12 +201,12 @@ struct CYapfRailNodeT
|
|||
void Dump(DumpTarget &dmp) const
|
||||
{
|
||||
this->base::Dump(dmp);
|
||||
dmp.WriteStructT("m_segment", this->m_segment);
|
||||
dmp.WriteValue("m_num_signals_passed", this->m_num_signals_passed);
|
||||
dmp.WriteValue("m_targed_seen", this->flags_u.flags_s.m_targed_seen ? "Yes" : "No");
|
||||
dmp.WriteValue("m_choice_seen", this->flags_u.flags_s.m_choice_seen ? "Yes" : "No");
|
||||
dmp.WriteValue("m_last_signal_was_red", this->flags_u.flags_s.m_last_signal_was_red ? "Yes" : "No");
|
||||
dmp.WriteEnumT("m_last_red_signal_type", this->m_last_red_signal_type);
|
||||
dmp.WriteStructT("segment", this->segment);
|
||||
dmp.WriteValue("num_signals_passed", this->num_signals_passed);
|
||||
dmp.WriteValue("target_seen", this->flags_u.flags_s.target_seen ? "Yes" : "No");
|
||||
dmp.WriteValue("choice_seen", this->flags_u.flags_s.choice_seen ? "Yes" : "No");
|
||||
dmp.WriteValue("last_signal_was_red", this->flags_u.flags_s.last_signal_was_red ? "Yes" : "No");
|
||||
dmp.WriteEnumT("last_red_signal_type", this->last_red_signal_type);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,14 +20,14 @@ template <class Tkey_>
|
|||
struct CYapfRoadNodeT : CYapfNodeT<Tkey_, CYapfRoadNodeT<Tkey_> > {
|
||||
typedef CYapfNodeT<Tkey_, CYapfRoadNodeT<Tkey_> > base;
|
||||
|
||||
TileIndex m_segment_last_tile;
|
||||
Trackdir m_segment_last_td;
|
||||
TileIndex segment_last_tile;
|
||||
Trackdir segment_last_td;
|
||||
|
||||
void Set(CYapfRoadNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
|
||||
{
|
||||
this->base::Set(parent, tile, td, is_choice);
|
||||
this->m_segment_last_tile = tile;
|
||||
this->m_segment_last_td = td;
|
||||
this->segment_last_tile = tile;
|
||||
this->segment_last_td = td;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -20,14 +20,14 @@ template <class Tkey_>
|
|||
struct CYapfShipNodeT : CYapfNodeT<Tkey_, CYapfShipNodeT<Tkey_> > {
|
||||
typedef CYapfNodeT<Tkey_, CYapfShipNodeT<Tkey_> > base;
|
||||
|
||||
TileIndex m_segment_last_tile;
|
||||
Trackdir m_segment_last_td;
|
||||
TileIndex segment_last_tile;
|
||||
Trackdir segment_last_td;
|
||||
|
||||
void Set(CYapfShipNodeT *parent, TileIndex tile, Trackdir td, bool is_choice)
|
||||
{
|
||||
this->base::Set(parent, tile, td, is_choice);
|
||||
this->m_segment_last_tile = tile;
|
||||
this->m_segment_last_td = td;
|
||||
this->segment_last_tile = tile;
|
||||
this->segment_last_td = td;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -48,20 +48,20 @@ protected:
|
|||
}
|
||||
|
||||
private:
|
||||
TileIndex m_res_dest; ///< The reservation target tile
|
||||
Trackdir m_res_dest_td; ///< The reservation target trackdir
|
||||
Node *m_res_node; ///< The reservation target node
|
||||
TileIndex m_res_fail_tile; ///< The tile where the reservation failed
|
||||
Trackdir m_res_fail_td; ///< The trackdir where the reservation failed
|
||||
TileIndex m_origin_tile; ///< Tile our reservation will originate from
|
||||
TileIndex res_dest_tile; ///< The reservation target tile
|
||||
Trackdir res_dest_td; ///< The reservation target trackdir
|
||||
Node *res_dest_node; ///< The reservation target node
|
||||
TileIndex res_fail_tile; ///< The tile where the reservation failed
|
||||
Trackdir res_fail_td; ///< The trackdir where the reservation failed
|
||||
TileIndex origin_tile; ///< Tile our reservation will originate from
|
||||
|
||||
std::vector<std::pair<TileIndex, Trackdir>> m_signals_set_to_red; ///< List of signals turned red during a path reservation.
|
||||
std::vector<std::pair<TileIndex, Trackdir>> signals_set_to_red; ///< List of signals turned red during a path reservation.
|
||||
|
||||
bool FindSafePositionProc(TileIndex tile, Trackdir td)
|
||||
{
|
||||
if (IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) {
|
||||
this->m_res_dest = tile;
|
||||
this->m_res_dest_td = td;
|
||||
this->res_dest_tile = tile;
|
||||
this->res_dest_td = td;
|
||||
return false; // Stop iterating segment
|
||||
}
|
||||
return true;
|
||||
|
@ -78,7 +78,7 @@ private:
|
|||
SetRailStationReservation(tile, true);
|
||||
MarkTileDirtyByTile(tile);
|
||||
tile = TileAdd(tile, diff);
|
||||
} while (IsCompatibleTrainStationTile(tile, start) && tile != this->m_origin_tile);
|
||||
} while (IsCompatibleTrainStationTile(tile, start) && tile != this->origin_tile);
|
||||
|
||||
TriggerStationRandomisation(nullptr, start, SRT_PATH_RESERVATION);
|
||||
|
||||
|
@ -92,26 +92,26 @@ private:
|
|||
if (IsRailStationTile(tile)) {
|
||||
if (!ReserveRailStationPlatform(tile, TrackdirToExitdir(rev_td))) {
|
||||
/* Platform could not be reserved, undo. */
|
||||
this->m_res_fail_tile = tile;
|
||||
this->m_res_fail_td = td;
|
||||
this->res_fail_tile = tile;
|
||||
this->res_fail_td = td;
|
||||
}
|
||||
} else {
|
||||
if (!TryReserveRailTrack(tile, TrackdirToTrack(td))) {
|
||||
/* Tile couldn't be reserved, undo. */
|
||||
this->m_res_fail_tile = tile;
|
||||
this->m_res_fail_td = td;
|
||||
this->res_fail_tile = tile;
|
||||
this->res_fail_td = td;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Green path signal opposing the path? Turn to red. */
|
||||
if (HasPbsSignalOnTrackdir(tile, rev_td) && GetSignalStateByTrackdir(tile, rev_td) == SIGNAL_STATE_GREEN) {
|
||||
this->m_signals_set_to_red.emplace_back(tile, rev_td);
|
||||
this->signals_set_to_red.emplace_back(tile, rev_td);
|
||||
SetSignalStateByTrackdir(tile, rev_td, SIGNAL_STATE_RED);
|
||||
MarkTileDirtyByTile(tile);
|
||||
}
|
||||
}
|
||||
|
||||
return tile != this->m_res_dest || td != this->m_res_dest_td;
|
||||
return tile != this->res_dest_tile || td != this->res_dest_td;
|
||||
}
|
||||
|
||||
/** Unreserve a single track/platform. Stops when the previous failer is reached. */
|
||||
|
@ -120,68 +120,68 @@ private:
|
|||
if (IsRailStationTile(tile)) {
|
||||
TileIndex start = tile;
|
||||
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(td)));
|
||||
while ((tile != this->m_res_fail_tile || td != this->m_res_fail_td) && IsCompatibleTrainStationTile(tile, start)) {
|
||||
while ((tile != this->res_fail_tile || td != this->res_fail_td) && IsCompatibleTrainStationTile(tile, start)) {
|
||||
SetRailStationReservation(tile, false);
|
||||
tile = TileAdd(tile, diff);
|
||||
}
|
||||
} else if (tile != this->m_res_fail_tile || td != this->m_res_fail_td) {
|
||||
} else if (tile != this->res_fail_tile || td != this->res_fail_td) {
|
||||
UnreserveRailTrack(tile, TrackdirToTrack(td));
|
||||
}
|
||||
return (tile != this->m_res_dest || td != this->m_res_dest_td) && (tile != this->m_res_fail_tile || td != this->m_res_fail_td);
|
||||
return (tile != this->res_dest_tile || td != this->res_dest_td) && (tile != this->res_fail_tile || td != this->res_fail_td);
|
||||
}
|
||||
|
||||
public:
|
||||
/** Set the target to where the reservation should be extended. */
|
||||
inline void SetReservationTarget(Node *node, TileIndex tile, Trackdir td)
|
||||
{
|
||||
this->m_res_node = node;
|
||||
this->m_res_dest = tile;
|
||||
this->m_res_dest_td = td;
|
||||
this->res_dest_node = node;
|
||||
this->res_dest_tile = tile;
|
||||
this->res_dest_td = td;
|
||||
}
|
||||
|
||||
/** Check the node for a possible reservation target. */
|
||||
inline void FindSafePositionOnNode(Node *node)
|
||||
{
|
||||
assert(node->m_parent != nullptr);
|
||||
assert(node->parent != nullptr);
|
||||
|
||||
/* We will never pass more than two signals, no need to check for a safe tile. */
|
||||
if (node->m_parent->m_num_signals_passed >= 2) return;
|
||||
if (node->parent->num_signals_passed >= 2) return;
|
||||
|
||||
if (!node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::FindSafePositionProc)) {
|
||||
this->m_res_node = node;
|
||||
this->res_dest_node = node;
|
||||
}
|
||||
}
|
||||
|
||||
/** Try to reserve the path till the reservation target. */
|
||||
bool TryReservePath(PBSTileInfo *target, TileIndex origin)
|
||||
{
|
||||
this->m_res_fail_tile = INVALID_TILE;
|
||||
this->m_origin_tile = origin;
|
||||
this->res_fail_tile = INVALID_TILE;
|
||||
this->origin_tile = origin;
|
||||
|
||||
if (target != nullptr) {
|
||||
target->tile = this->m_res_dest;
|
||||
target->trackdir = this->m_res_dest_td;
|
||||
target->tile = this->res_dest_tile;
|
||||
target->trackdir = this->res_dest_td;
|
||||
target->okay = false;
|
||||
}
|
||||
|
||||
/* Don't bother if the target is reserved. */
|
||||
if (!IsWaitingPositionFree(Yapf().GetVehicle(), this->m_res_dest, this->m_res_dest_td)) return false;
|
||||
if (!IsWaitingPositionFree(Yapf().GetVehicle(), this->res_dest_tile, this->res_dest_td)) return false;
|
||||
|
||||
this->m_signals_set_to_red.clear();
|
||||
for (Node *node = this->m_res_node; node->m_parent != nullptr; node = node->m_parent) {
|
||||
this->signals_set_to_red.clear();
|
||||
for (Node *node = this->res_dest_node; node->parent != nullptr; node = node->parent) {
|
||||
node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack);
|
||||
if (this->m_res_fail_tile != INVALID_TILE) {
|
||||
if (this->res_fail_tile != INVALID_TILE) {
|
||||
/* Reservation failed, undo. */
|
||||
Node *fail_node = this->m_res_node;
|
||||
TileIndex stop_tile = this->m_res_fail_tile;
|
||||
Node *fail_node = this->res_dest_node;
|
||||
TileIndex stop_tile = this->res_fail_tile;
|
||||
do {
|
||||
/* If this is the node that failed, stop at the failed tile. */
|
||||
this->m_res_fail_tile = fail_node == node ? stop_tile : INVALID_TILE;
|
||||
this->res_fail_tile = fail_node == node ? stop_tile : INVALID_TILE;
|
||||
fail_node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::UnreserveSingleTrack);
|
||||
} while (fail_node != node && (fail_node = fail_node->m_parent) != nullptr);
|
||||
} while (fail_node != node && (fail_node = fail_node->parent) != nullptr);
|
||||
|
||||
/* Re-instate green path signals we turned to red. */
|
||||
for (auto [sig_tile, td] : this->m_signals_set_to_red) {
|
||||
for (auto [sig_tile, td] : this->signals_set_to_red) {
|
||||
SetSignalStateByTrackdir(sig_tile, td, SIGNAL_STATE_GREEN);
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ public:
|
|||
|
||||
if (target != nullptr) target->okay = true;
|
||||
|
||||
if (Yapf().CanUseGlobalCache(*this->m_res_node)) {
|
||||
if (Yapf().CanUseGlobalCache(*this->res_dest_node)) {
|
||||
YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
|
||||
}
|
||||
|
||||
|
@ -280,13 +280,13 @@ public:
|
|||
|
||||
/* walk through the path back to the origin */
|
||||
Node *pNode = n;
|
||||
while (pNode->m_parent != nullptr) {
|
||||
pNode = pNode->m_parent;
|
||||
while (pNode->parent != nullptr) {
|
||||
pNode = pNode->parent;
|
||||
}
|
||||
|
||||
/* if the origin node is our front vehicle tile/Trackdir then we didn't reverse
|
||||
* but we can also look at the cost (== 0 -> not reversed, == reverse_penalty -> reversed) */
|
||||
return FindDepotData(n->GetLastTile(), n->m_cost, pNode->m_cost != 0);
|
||||
return FindDepotData(n->GetLastTile(), n->cost, pNode->cost != 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -362,9 +362,9 @@ public:
|
|||
|
||||
/* Walk through the path back to the origin. */
|
||||
Node *pPrev = nullptr;
|
||||
while (pNode->m_parent != nullptr) {
|
||||
while (pNode->parent != nullptr) {
|
||||
pPrev = pNode;
|
||||
pNode = pNode->m_parent;
|
||||
pNode = pNode->parent;
|
||||
|
||||
this->FindSafePositionOnNode(pPrev);
|
||||
}
|
||||
|
@ -454,9 +454,9 @@ public:
|
|||
/* path was found or at least suggested
|
||||
* walk through the path back to the origin */
|
||||
Node *pPrev = nullptr;
|
||||
while (pNode->m_parent != nullptr) {
|
||||
while (pNode->parent != nullptr) {
|
||||
pPrev = pNode;
|
||||
pNode = pNode->m_parent;
|
||||
pNode = pNode->parent;
|
||||
|
||||
this->FindSafePositionOnNode(pPrev);
|
||||
}
|
||||
|
@ -476,7 +476,7 @@ public:
|
|||
}
|
||||
|
||||
/* Treat the path as found if stopped on the first two way signal(s). */
|
||||
path_found |= Yapf().m_stopped_on_first_two_way_signal;
|
||||
path_found |= Yapf().stopped_on_first_two_way_signal;
|
||||
return next_trackdir;
|
||||
}
|
||||
|
||||
|
@ -513,13 +513,13 @@ public:
|
|||
/* path was found
|
||||
* walk through the path back to the origin */
|
||||
Node *pNode = Yapf().GetBestNode();
|
||||
while (pNode->m_parent != nullptr) {
|
||||
pNode = pNode->m_parent;
|
||||
while (pNode->parent != nullptr) {
|
||||
pNode = pNode->parent;
|
||||
}
|
||||
|
||||
/* check if it was reversed origin */
|
||||
Node &best_org_node = *pNode;
|
||||
bool reversed = (best_org_node.m_cost != 0);
|
||||
bool reversed = (best_org_node.cost != 0);
|
||||
return reversed;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -25,9 +25,9 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables
|
||||
|
||||
protected:
|
||||
int m_max_cost;
|
||||
int max_cost;
|
||||
|
||||
CYapfCostRoadT() : m_max_cost(0) {};
|
||||
CYapfCostRoadT() : max_cost(0) {};
|
||||
|
||||
/** to access inherited path finder */
|
||||
Tpf &Yapf()
|
||||
|
@ -103,7 +103,7 @@ protected:
|
|||
public:
|
||||
inline void SetMaxCost(int max_cost)
|
||||
{
|
||||
this->m_max_cost = max_cost;
|
||||
this->max_cost = max_cost;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,10 +115,10 @@ public:
|
|||
{
|
||||
int segment_cost = 0;
|
||||
uint tiles = 0;
|
||||
/* start at n.m_key.m_tile / n.m_key.m_td and walk to the end of segment */
|
||||
TileIndex tile = n.m_key.m_tile;
|
||||
Trackdir trackdir = n.m_key.m_td;
|
||||
int parent_cost = (n.m_parent != nullptr) ? n.m_parent->m_cost : 0;
|
||||
/* start at n.key.tile / n.key.td and walk to the end of segment */
|
||||
TileIndex tile = n.key.tile;
|
||||
Trackdir trackdir = n.key.td;
|
||||
int parent_cost = (n.parent != nullptr) ? n.parent->cost : 0;
|
||||
|
||||
for (;;) {
|
||||
/* base tile cost depending on distance between edges */
|
||||
|
@ -130,7 +130,7 @@ public:
|
|||
|
||||
/* Finish if we already exceeded the maximum path cost (i.e. when
|
||||
* searching for the nearest depot). */
|
||||
if (this->m_max_cost > 0 && (parent_cost + segment_cost) > this->m_max_cost) {
|
||||
if (this->max_cost > 0 && (parent_cost + segment_cost) > this->max_cost) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -145,39 +145,39 @@ public:
|
|||
if (!F.Follow(tile, trackdir)) break;
|
||||
|
||||
/* if there are more trackdirs available & reachable, we are at the end of segment */
|
||||
if (KillFirstBit(F.m_new_td_bits) != TRACKDIR_BIT_NONE) break;
|
||||
if (KillFirstBit(F.new_td_bits) != TRACKDIR_BIT_NONE) break;
|
||||
|
||||
Trackdir new_td = (Trackdir)FindFirstBit(F.m_new_td_bits);
|
||||
Trackdir new_td = (Trackdir)FindFirstBit(F.new_td_bits);
|
||||
|
||||
/* stop if RV is on simple loop with no junctions */
|
||||
if (F.m_new_tile == n.m_key.m_tile && new_td == n.m_key.m_td) return false;
|
||||
if (F.new_tile == n.key.tile && new_td == n.key.td) return false;
|
||||
|
||||
/* if we skipped some tunnel tiles, add their cost */
|
||||
segment_cost += F.m_tiles_skipped * YAPF_TILE_LENGTH;
|
||||
tiles += F.m_tiles_skipped + 1;
|
||||
segment_cost += F.tiles_skipped * YAPF_TILE_LENGTH;
|
||||
tiles += F.tiles_skipped + 1;
|
||||
|
||||
/* add hilly terrain penalty */
|
||||
segment_cost += Yapf().SlopeCost(tile, F.m_new_tile, trackdir);
|
||||
segment_cost += Yapf().SlopeCost(tile, F.new_tile, trackdir);
|
||||
|
||||
/* add min/max speed penalties */
|
||||
int min_speed = 0;
|
||||
int max_veh_speed = std::min<int>(v->GetDisplayMaxSpeed(), v->current_order.GetMaxSpeed() * 2);
|
||||
int max_speed = F.GetSpeedLimit(&min_speed);
|
||||
if (max_speed < max_veh_speed) segment_cost += YAPF_TILE_LENGTH * (max_veh_speed - max_speed) * (4 + F.m_tiles_skipped) / max_veh_speed;
|
||||
if (max_speed < max_veh_speed) segment_cost += YAPF_TILE_LENGTH * (max_veh_speed - max_speed) * (4 + F.tiles_skipped) / max_veh_speed;
|
||||
if (min_speed > max_veh_speed) segment_cost += YAPF_TILE_LENGTH * (min_speed - max_veh_speed);
|
||||
|
||||
/* move to the next tile */
|
||||
tile = F.m_new_tile;
|
||||
tile = F.new_tile;
|
||||
trackdir = new_td;
|
||||
if (tiles > MAX_MAP_SIZE) break;
|
||||
}
|
||||
|
||||
/* save end of segment back to the node */
|
||||
n.m_segment_last_tile = tile;
|
||||
n.m_segment_last_td = trackdir;
|
||||
n.segment_last_tile = tile;
|
||||
n.segment_last_td = trackdir;
|
||||
|
||||
/* save also tile cost */
|
||||
n.m_cost = parent_cost + segment_cost;
|
||||
n.cost = parent_cost + segment_cost;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -201,7 +201,7 @@ public:
|
|||
/** Called by YAPF to detect if node ends in the desired destination */
|
||||
inline bool PfDetectDestination(Node &n)
|
||||
{
|
||||
return IsRoadDepotTile(n.m_segment_last_tile);
|
||||
return IsRoadDepotTile(n.segment_last_tile);
|
||||
}
|
||||
|
||||
inline bool PfDetectDestinationTile(TileIndex tile, Trackdir)
|
||||
|
@ -215,7 +215,7 @@ public:
|
|||
*/
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -231,37 +231,37 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables
|
||||
|
||||
protected:
|
||||
TileIndex m_destTile;
|
||||
TrackdirBits m_destTrackdirs;
|
||||
StationID m_dest_station;
|
||||
StationType m_station_type;
|
||||
bool m_non_artic;
|
||||
TileIndex dest_tile;
|
||||
TrackdirBits dest_trackdirs;
|
||||
StationID dest_station;
|
||||
StationType station_type;
|
||||
bool non_artic;
|
||||
|
||||
public:
|
||||
void SetDestination(const RoadVehicle *v)
|
||||
{
|
||||
if (v->current_order.IsType(OT_GOTO_STATION)) {
|
||||
this->m_dest_station = v->current_order.GetDestination();
|
||||
this->m_station_type = v->IsBus() ? STATION_BUS : STATION_TRUCK;
|
||||
this->m_destTile = CalcClosestStationTile(this->m_dest_station, v->tile, this->m_station_type);
|
||||
this->m_non_artic = !v->HasArticulatedPart();
|
||||
this->m_destTrackdirs = INVALID_TRACKDIR_BIT;
|
||||
this->dest_station = v->current_order.GetDestination();
|
||||
this->station_type = v->IsBus() ? STATION_BUS : STATION_TRUCK;
|
||||
this->dest_tile = CalcClosestStationTile(this->dest_station, v->tile, this->station_type);
|
||||
this->non_artic = !v->HasArticulatedPart();
|
||||
this->dest_trackdirs = INVALID_TRACKDIR_BIT;
|
||||
} else if (v->current_order.IsType(OT_GOTO_WAYPOINT)) {
|
||||
this->m_dest_station = v->current_order.GetDestination();
|
||||
this->m_station_type = STATION_ROADWAYPOINT;
|
||||
this->m_destTile = CalcClosestStationTile(this->m_dest_station, v->tile, this->m_station_type);
|
||||
this->m_non_artic = !v->HasArticulatedPart();
|
||||
this->m_destTrackdirs = INVALID_TRACKDIR_BIT;
|
||||
this->dest_station = v->current_order.GetDestination();
|
||||
this->station_type = STATION_ROADWAYPOINT;
|
||||
this->dest_tile = CalcClosestStationTile(this->dest_station, v->tile, this->station_type);
|
||||
this->non_artic = !v->HasArticulatedPart();
|
||||
this->dest_trackdirs = INVALID_TRACKDIR_BIT;
|
||||
} else {
|
||||
this->m_dest_station = INVALID_STATION;
|
||||
this->m_destTile = v->dest_tile;
|
||||
this->m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype)));
|
||||
this->dest_station = INVALID_STATION;
|
||||
this->dest_tile = v->dest_tile;
|
||||
this->dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype)));
|
||||
}
|
||||
}
|
||||
|
||||
const Station *GetDestinationStation() const
|
||||
{
|
||||
return this->m_dest_station != INVALID_STATION ? Station::GetIfValid(this->m_dest_station) : nullptr;
|
||||
return this->dest_station != INVALID_STATION ? Station::GetIfValid(this->dest_station) : nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -275,19 +275,19 @@ public:
|
|||
/** Called by YAPF to detect if node ends in the desired destination */
|
||||
inline bool PfDetectDestination(Node &n)
|
||||
{
|
||||
return this->PfDetectDestinationTile(n.m_segment_last_tile, n.m_segment_last_td);
|
||||
return this->PfDetectDestinationTile(n.segment_last_tile, n.segment_last_td);
|
||||
}
|
||||
|
||||
inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
|
||||
{
|
||||
if (this->m_dest_station != INVALID_STATION) {
|
||||
if (this->dest_station != INVALID_STATION) {
|
||||
return IsTileType(tile, MP_STATION) &&
|
||||
GetStationIndex(tile) == this->m_dest_station &&
|
||||
(this->m_station_type == GetStationType(tile)) &&
|
||||
(this->m_non_artic || IsDriveThroughStopTile(tile));
|
||||
GetStationIndex(tile) == this->dest_station &&
|
||||
(this->station_type == GetStationType(tile)) &&
|
||||
(this->non_artic || IsDriveThroughStopTile(tile));
|
||||
}
|
||||
|
||||
return tile == this->m_destTile && HasTrackdir(this->m_destTrackdirs, trackdir);
|
||||
return tile == this->dest_tile && HasTrackdir(this->dest_trackdirs, trackdir);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -299,23 +299,23 @@ public:
|
|||
static const int dg_dir_to_x_offs[] = {-1, 0, 1, 0};
|
||||
static const int dg_dir_to_y_offs[] = {0, 1, 0, -1};
|
||||
if (this->PfDetectDestination(n)) {
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
|
||||
TileIndex tile = n.m_segment_last_tile;
|
||||
DiagDirection exitdir = TrackdirToExitdir(n.m_segment_last_td);
|
||||
TileIndex tile = n.segment_last_tile;
|
||||
DiagDirection exitdir = TrackdirToExitdir(n.segment_last_td);
|
||||
int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
|
||||
int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
|
||||
int x2 = 2 * TileX(this->m_destTile);
|
||||
int y2 = 2 * TileY(this->m_destTile);
|
||||
int x2 = 2 * TileX(this->dest_tile);
|
||||
int y2 = 2 * TileY(this->dest_tile);
|
||||
int dx = abs(x1 - x2);
|
||||
int dy = abs(y1 - y2);
|
||||
int dmin = std::min(dx, dy);
|
||||
int dxy = abs(dx - dy);
|
||||
int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
||||
n.m_estimate = n.m_cost + d;
|
||||
assert(n.m_estimate >= n.m_parent->m_estimate);
|
||||
n.estimate = n.cost + d;
|
||||
assert(n.estimate >= n.parent->estimate);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -348,7 +348,7 @@ public:
|
|||
inline void PfFollowNode(Node &old_node)
|
||||
{
|
||||
TrackFollower F(Yapf().GetVehicle());
|
||||
if (F.Follow(old_node.m_segment_last_tile, old_node.m_segment_last_td)) {
|
||||
if (F.Follow(old_node.segment_last_tile, old_node.segment_last_td)) {
|
||||
Yapf().AddMultipleNodes(&old_node, F);
|
||||
}
|
||||
}
|
||||
|
@ -394,17 +394,17 @@ public:
|
|||
Node *pNode = Yapf().GetBestNode();
|
||||
if (pNode != nullptr) {
|
||||
uint steps = 0;
|
||||
for (Node *n = pNode; n->m_parent != nullptr; n = n->m_parent) steps++;
|
||||
for (Node *n = pNode; n->parent != nullptr; n = n->parent) steps++;
|
||||
|
||||
/* path was found or at least suggested
|
||||
* walk through the path back to its origin */
|
||||
while (pNode->m_parent != nullptr) {
|
||||
while (pNode->parent != nullptr) {
|
||||
steps--;
|
||||
if (pNode->GetIsChoice() && steps < YAPF_ROADVEH_PATH_CACHE_SEGMENTS) {
|
||||
path_cache.td.push_front(pNode->GetTrackdir());
|
||||
path_cache.tile.push_front(pNode->GetTile());
|
||||
}
|
||||
pNode = pNode->m_parent;
|
||||
pNode = pNode->parent;
|
||||
}
|
||||
/* return trackdir from the best origin node (one of start nodes) */
|
||||
Node &best_next_node = *pNode;
|
||||
|
@ -503,7 +503,7 @@ public:
|
|||
|
||||
/* Return the cost of the best path and its depot. */
|
||||
Node *n = Yapf().GetBestNode();
|
||||
return FindDepotData(n->m_segment_last_tile, n->m_cost);
|
||||
return FindDepotData(n->segment_last_tile, n->cost);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -34,33 +34,33 @@ public:
|
|||
typedef typename Node::Key Key; ///< key to hash tables.
|
||||
|
||||
protected:
|
||||
TileIndex m_destTile;
|
||||
TrackdirBits m_destTrackdirs;
|
||||
StationID m_destStation;
|
||||
TileIndex dest_tile;
|
||||
TrackdirBits dest_trackdirs;
|
||||
StationID dest_station;
|
||||
|
||||
bool m_has_intermediate_dest = false;
|
||||
TileIndex m_intermediate_dest_tile;
|
||||
WaterRegionPatchDesc m_intermediate_dest_region_patch;
|
||||
bool has_intermediate_dest = false;
|
||||
TileIndex intermediate_dest_tile;
|
||||
WaterRegionPatchDesc intermediate_dest_region_patch;
|
||||
|
||||
public:
|
||||
void SetDestination(const Ship *v)
|
||||
{
|
||||
if (v->current_order.IsType(OT_GOTO_STATION)) {
|
||||
this->m_destStation = v->current_order.GetDestination();
|
||||
this->m_destTile = CalcClosestStationTile(this->m_destStation, v->tile, STATION_DOCK);
|
||||
this->m_destTrackdirs = INVALID_TRACKDIR_BIT;
|
||||
this->dest_station = v->current_order.GetDestination();
|
||||
this->dest_tile = CalcClosestStationTile(this->dest_station, v->tile, STATION_DOCK);
|
||||
this->dest_trackdirs = INVALID_TRACKDIR_BIT;
|
||||
} else {
|
||||
this->m_destStation = INVALID_STATION;
|
||||
this->m_destTile = v->dest_tile;
|
||||
this->m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0));
|
||||
this->dest_station = INVALID_STATION;
|
||||
this->dest_tile = v->dest_tile;
|
||||
this->dest_trackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_WATER, 0));
|
||||
}
|
||||
}
|
||||
|
||||
void SetIntermediateDestination(const WaterRegionPatchDesc &water_region_patch)
|
||||
{
|
||||
this->m_has_intermediate_dest = true;
|
||||
this->m_intermediate_dest_tile = GetWaterRegionCenterTile(water_region_patch);
|
||||
this->m_intermediate_dest_region_patch = water_region_patch;
|
||||
this->has_intermediate_dest = true;
|
||||
this->intermediate_dest_tile = GetWaterRegionCenterTile(water_region_patch);
|
||||
this->intermediate_dest_region_patch = water_region_patch;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -74,20 +74,20 @@ public:
|
|||
/** Called by YAPF to detect if node ends in the desired destination. */
|
||||
inline bool PfDetectDestination(Node &n)
|
||||
{
|
||||
return this->PfDetectDestinationTile(n.m_segment_last_tile, n.m_segment_last_td);
|
||||
return this->PfDetectDestinationTile(n.segment_last_tile, n.segment_last_td);
|
||||
}
|
||||
|
||||
inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
|
||||
{
|
||||
if (this->m_has_intermediate_dest) {
|
||||
if (this->has_intermediate_dest) {
|
||||
/* GetWaterRegionInfo is much faster than GetWaterRegionPatchInfo so we try that first. */
|
||||
if (GetWaterRegionInfo(tile) != this->m_intermediate_dest_region_patch) return false;
|
||||
return GetWaterRegionPatchInfo(tile) == this->m_intermediate_dest_region_patch;
|
||||
if (GetWaterRegionInfo(tile) != this->intermediate_dest_region_patch) return false;
|
||||
return GetWaterRegionPatchInfo(tile) == this->intermediate_dest_region_patch;
|
||||
}
|
||||
|
||||
if (this->m_destStation != INVALID_STATION) return IsDockingTile(tile) && IsShipDestinationTile(tile, this->m_destStation);
|
||||
if (this->dest_station != INVALID_STATION) return IsDockingTile(tile) && IsShipDestinationTile(tile, this->dest_station);
|
||||
|
||||
return tile == this->m_destTile && ((this->m_destTrackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
|
||||
return tile == this->dest_tile && ((this->dest_trackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,17 +96,17 @@ public:
|
|||
*/
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
const TileIndex destination_tile = this->m_has_intermediate_dest ? this->m_intermediate_dest_tile : this->m_destTile;
|
||||
const TileIndex destination_tile = this->has_intermediate_dest ? this->intermediate_dest_tile : this->dest_tile;
|
||||
|
||||
static const int dg_dir_to_x_offs[] = { -1, 0, 1, 0 };
|
||||
static const int dg_dir_to_y_offs[] = { 0, 1, 0, -1 };
|
||||
if (this->PfDetectDestination(n)) {
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
|
||||
TileIndex tile = n.m_segment_last_tile;
|
||||
DiagDirection exitdir = TrackdirToExitdir(n.m_segment_last_td);
|
||||
TileIndex tile = n.segment_last_tile;
|
||||
DiagDirection exitdir = TrackdirToExitdir(n.segment_last_td);
|
||||
int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
|
||||
int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
|
||||
int x2 = 2 * TileX(destination_tile);
|
||||
|
@ -116,8 +116,8 @@ public:
|
|||
int dmin = std::min(dx, dy);
|
||||
int dxy = abs(dx - dy);
|
||||
int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
|
||||
n.m_estimate = n.m_cost + d;
|
||||
assert(n.m_estimate >= n.m_parent->m_estimate);
|
||||
n.estimate = n.cost + d;
|
||||
assert(n.estimate >= n.parent->estimate);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -139,7 +139,7 @@ protected:
|
|||
return *static_cast<Tpf*>(this);
|
||||
}
|
||||
|
||||
std::vector<WaterRegionDesc> m_water_region_corridor;
|
||||
std::vector<WaterRegionDesc> water_region_corridor;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -150,10 +150,10 @@ public:
|
|||
inline void PfFollowNode(Node &old_node)
|
||||
{
|
||||
TrackFollower F(Yapf().GetVehicle());
|
||||
if (F.Follow(old_node.m_key.m_tile, old_node.m_key.m_td)) {
|
||||
if (this->m_water_region_corridor.empty()
|
||||
|| std::find(this->m_water_region_corridor.begin(), this->m_water_region_corridor.end(),
|
||||
GetWaterRegionInfo(F.m_new_tile)) != this->m_water_region_corridor.end()) {
|
||||
if (F.Follow(old_node.key.tile, old_node.key.td)) {
|
||||
if (this->water_region_corridor.empty()
|
||||
|| std::find(this->water_region_corridor.begin(), this->water_region_corridor.end(),
|
||||
GetWaterRegionInfo(F.new_tile)) != this->water_region_corridor.end()) {
|
||||
Yapf().AddMultipleNodes(&old_node, F);
|
||||
}
|
||||
}
|
||||
|
@ -162,8 +162,8 @@ public:
|
|||
/** Restricts the search by creating corridor or water regions through which the ship is allowed to travel. */
|
||||
inline void RestrictSearch(const std::vector<WaterRegionPatchDesc> &path)
|
||||
{
|
||||
this->m_water_region_corridor.clear();
|
||||
for (const WaterRegionPatchDesc &path_entry : path) this->m_water_region_corridor.push_back(path_entry);
|
||||
this->water_region_corridor.clear();
|
||||
for (const WaterRegionPatchDesc &path_entry : path) this->water_region_corridor.push_back(path_entry);
|
||||
}
|
||||
|
||||
/** Return debug report character to identify the transportation type. */
|
||||
|
@ -185,12 +185,12 @@ public:
|
|||
{
|
||||
TrackFollower follower(v);
|
||||
if (follower.Follow(tile, dir)) {
|
||||
TrackdirBits dirs = follower.m_new_td_bits;
|
||||
TrackdirBits dirs = follower.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;
|
||||
return { follower.m_new_tile, GetRandomTrackdir(dirs) };
|
||||
return { follower.new_tile, GetRandomTrackdir(dirs) };
|
||||
}
|
||||
return { follower.m_new_tile, INVALID_TRACKDIR };
|
||||
return { follower.new_tile, INVALID_TRACKDIR };
|
||||
}
|
||||
|
||||
/** Creates a random path, avoids 90 degree turns. */
|
||||
|
@ -250,7 +250,7 @@ public:
|
|||
const WaterRegionPatchDesc end_water_patch = GetWaterRegionPatchInfo(node->GetTile());
|
||||
assert(GetWaterRegionPatchInfo(tile) == high_level_path.front());
|
||||
const WaterRegionPatchDesc start_water_patch = high_level_path.front();
|
||||
while (node->m_parent) {
|
||||
while (node->parent) {
|
||||
const WaterRegionPatchDesc node_water_patch = GetWaterRegionPatchInfo(node->GetTile());
|
||||
|
||||
const bool node_water_patch_on_high_level_path = std::find(high_level_path.begin(), high_level_path.end(), node_water_patch) != high_level_path.end();
|
||||
|
@ -263,7 +263,7 @@ public:
|
|||
} else {
|
||||
path_cache.clear();
|
||||
}
|
||||
node = node->m_parent;
|
||||
node = node->parent;
|
||||
}
|
||||
assert(node->GetTile() == v->tile);
|
||||
|
||||
|
@ -373,7 +373,7 @@ public:
|
|||
/* Base tile cost depending on distance. */
|
||||
int c = IsDiagonalTrackdir(n.GetTrackdir()) ? YAPF_TILE_LENGTH : YAPF_TILE_CORNER_LENGTH;
|
||||
/* Additional penalty for curves. */
|
||||
c += this->CurveCost(n.m_parent->GetTrackdir(), n.GetTrackdir());
|
||||
c += this->CurveCost(n.parent->GetTrackdir(), n.GetTrackdir());
|
||||
|
||||
if (IsDockingTile(n.GetTile())) {
|
||||
/* Check docking tile for occupancy. */
|
||||
|
@ -383,15 +383,15 @@ public:
|
|||
}
|
||||
|
||||
/* Skipped tile cost for aqueducts. */
|
||||
c += YAPF_TILE_LENGTH * tf->m_tiles_skipped;
|
||||
c += YAPF_TILE_LENGTH * tf->tiles_skipped;
|
||||
|
||||
/* Ocean/canal speed penalty. */
|
||||
const ShipVehicleInfo *svi = ShipVehInfo(Yapf().GetVehicle()->engine_type);
|
||||
uint8_t speed_frac = (GetEffectiveWaterClass(n.GetTile()) == WATER_CLASS_SEA) ? svi->ocean_speed_frac : svi->canal_speed_frac;
|
||||
if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + tf->m_tiles_skipped) * speed_frac / (256 - speed_frac);
|
||||
if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + tf->tiles_skipped) * speed_frac / (256 - speed_frac);
|
||||
|
||||
/* Apply it. */
|
||||
n.m_cost = n.m_parent->m_cost + c;
|
||||
n.cost = n.parent->cost + c;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -420,7 +420,7 @@ struct CYapfShip_TypesT
|
|||
|
||||
struct CYapfShip : CYapfT<CYapfShip_TypesT<CYapfShip, CFollowTrackWater, CShipNodeListExitDir > >
|
||||
{
|
||||
explicit CYapfShip(int max_nodes) { this->m_max_search_nodes = max_nodes; }
|
||||
explicit CYapfShip(int max_nodes) { this->max_search_nodes = max_nodes; }
|
||||
};
|
||||
|
||||
/** Ship controller helper - path finder invoker. */
|
||||
|
|
|
@ -22,20 +22,20 @@ constexpr int MAX_NUMBER_OF_NODES = 65536;
|
|||
|
||||
/** Yapf Node Key that represents a single patch of interconnected water within a water region. */
|
||||
struct CYapfRegionPatchNodeKey {
|
||||
WaterRegionPatchDesc m_water_region_patch;
|
||||
WaterRegionPatchDesc water_region_patch;
|
||||
|
||||
inline void Set(const WaterRegionPatchDesc &water_region_patch)
|
||||
{
|
||||
this->m_water_region_patch = water_region_patch;
|
||||
this->water_region_patch = water_region_patch;
|
||||
}
|
||||
|
||||
inline int CalcHash() const { return CalculateWaterRegionPatchHash(this->m_water_region_patch); }
|
||||
inline int CalcHash() const { return CalculateWaterRegionPatchHash(this->water_region_patch); }
|
||||
inline bool operator==(const CYapfRegionPatchNodeKey &other) const { return this->CalcHash() == other.CalcHash(); }
|
||||
};
|
||||
|
||||
inline uint ManhattanDistance(const CYapfRegionPatchNodeKey &a, const CYapfRegionPatchNodeKey &b)
|
||||
{
|
||||
return (std::abs(a.m_water_region_patch.x - b.m_water_region_patch.x) + std::abs(a.m_water_region_patch.y - b.m_water_region_patch.y)) * DIRECT_NEIGHBOR_COST;
|
||||
return (std::abs(a.water_region_patch.x - b.water_region_patch.x) + std::abs(a.water_region_patch.y - b.water_region_patch.y)) * DIRECT_NEIGHBOR_COST;
|
||||
}
|
||||
|
||||
/** Yapf Node for water regions. */
|
||||
|
@ -44,31 +44,31 @@ struct CYapfRegionNodeT {
|
|||
typedef Tkey_ Key;
|
||||
typedef CYapfRegionNodeT<Tkey_> Node;
|
||||
|
||||
Tkey_ m_key;
|
||||
Node *m_hash_next;
|
||||
Node *m_parent;
|
||||
int m_cost;
|
||||
int m_estimate;
|
||||
Tkey_ key;
|
||||
Node *hash_next;
|
||||
Node *parent;
|
||||
int cost;
|
||||
int estimate;
|
||||
|
||||
inline void Set(Node *parent, const WaterRegionPatchDesc &water_region_patch)
|
||||
{
|
||||
this->m_key.Set(water_region_patch);
|
||||
this->m_hash_next = nullptr;
|
||||
this->m_parent = parent;
|
||||
this->m_cost = 0;
|
||||
this->m_estimate = 0;
|
||||
this->key.Set(water_region_patch);
|
||||
this->hash_next = nullptr;
|
||||
this->parent = parent;
|
||||
this->cost = 0;
|
||||
this->estimate = 0;
|
||||
}
|
||||
|
||||
inline void Set(Node *parent, const Key &key)
|
||||
{
|
||||
this->Set(parent, key.m_water_region_patch);
|
||||
this->Set(parent, key.water_region_patch);
|
||||
}
|
||||
|
||||
DiagDirection GetDiagDirFromParent() const
|
||||
{
|
||||
if (!this->m_parent) return INVALID_DIAGDIR;
|
||||
const int dx = this->m_key.m_water_region_patch.x - this->m_parent->m_key.m_water_region_patch.x;
|
||||
const int dy = this->m_key.m_water_region_patch.y - this->m_parent->m_key.m_water_region_patch.y;
|
||||
if (!this->parent) return INVALID_DIAGDIR;
|
||||
const int dx = this->key.water_region_patch.x - this->parent->key.water_region_patch.x;
|
||||
const int dy = this->key.water_region_patch.y - this->parent->key.water_region_patch.y;
|
||||
if (dx > 0 && dy == 0) return DIAGDIR_SW;
|
||||
if (dx < 0 && dy == 0) return DIAGDIR_NE;
|
||||
if (dx == 0 && dy > 0) return DIAGDIR_SE;
|
||||
|
@ -76,12 +76,12 @@ struct CYapfRegionNodeT {
|
|||
return INVALID_DIAGDIR;
|
||||
}
|
||||
|
||||
inline Node *GetHashNext() { return this->m_hash_next; }
|
||||
inline void SetHashNext(Node *pNext) { this->m_hash_next = pNext; }
|
||||
inline const Tkey_ &GetKey() const { return this->m_key; }
|
||||
inline int GetCost() { return this->m_cost; }
|
||||
inline int GetCostEstimate() { return this->m_estimate; }
|
||||
inline bool operator<(const Node &other) const { return this->m_estimate < other.m_estimate; }
|
||||
inline Node *GetHashNext() { return this->hash_next; }
|
||||
inline void SetHashNext(Node *pNext) { this->hash_next = pNext; }
|
||||
inline const Tkey_ &GetKey() const { return this->key; }
|
||||
inline int GetCost() { return this->cost; }
|
||||
inline int GetCostEstimate() { return this->estimate; }
|
||||
inline bool operator<(const Node &other) const { return this->estimate < other.estimate; }
|
||||
};
|
||||
|
||||
/** YAPF origin for water regions. */
|
||||
|
@ -97,23 +97,23 @@ protected:
|
|||
inline Tpf &Yapf() { return *static_cast<Tpf*>(this); }
|
||||
|
||||
private:
|
||||
std::vector<CYapfRegionPatchNodeKey> m_origin_keys;
|
||||
std::vector<CYapfRegionPatchNodeKey> origin_keys;
|
||||
|
||||
public:
|
||||
void AddOrigin(const WaterRegionPatchDesc &water_region_patch)
|
||||
{
|
||||
if (water_region_patch.label == INVALID_WATER_REGION_PATCH) return;
|
||||
if (!HasOrigin(water_region_patch)) this->m_origin_keys.push_back(CYapfRegionPatchNodeKey{ water_region_patch });
|
||||
if (!HasOrigin(water_region_patch)) this->origin_keys.push_back(CYapfRegionPatchNodeKey{ water_region_patch });
|
||||
}
|
||||
|
||||
bool HasOrigin(const WaterRegionPatchDesc &water_region_patch)
|
||||
{
|
||||
return std::find(this->m_origin_keys.begin(), this->m_origin_keys.end(), CYapfRegionPatchNodeKey{ water_region_patch }) != this->m_origin_keys.end();
|
||||
return std::find(this->origin_keys.begin(), this->origin_keys.end(), CYapfRegionPatchNodeKey{ water_region_patch }) != this->origin_keys.end();
|
||||
}
|
||||
|
||||
void PfSetStartupNodes()
|
||||
{
|
||||
for (const CYapfRegionPatchNodeKey &origin_key : this->m_origin_keys) {
|
||||
for (const CYapfRegionPatchNodeKey &origin_key : this->origin_keys) {
|
||||
Node &node = Yapf().CreateNewNode();
|
||||
node.Set(nullptr, origin_key);
|
||||
Yapf().AddStartupNode(node);
|
||||
|
@ -131,12 +131,12 @@ public:
|
|||
typedef typename Node::Key Key; ///< Key to hash tables.
|
||||
|
||||
protected:
|
||||
Key m_dest;
|
||||
Key dest;
|
||||
|
||||
public:
|
||||
void SetDestination(const WaterRegionPatchDesc &water_region_patch)
|
||||
{
|
||||
this->m_dest.Set(water_region_patch);
|
||||
this->dest.Set(water_region_patch);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -145,17 +145,17 @@ protected:
|
|||
public:
|
||||
inline bool PfDetectDestination(Node &n) const
|
||||
{
|
||||
return n.m_key == this->m_dest;
|
||||
return n.key == this->dest;
|
||||
}
|
||||
|
||||
inline bool PfCalcEstimate(Node &n)
|
||||
{
|
||||
if (this->PfDetectDestination(n)) {
|
||||
n.m_estimate = n.m_cost;
|
||||
n.estimate = n.cost;
|
||||
return true;
|
||||
}
|
||||
|
||||
n.m_estimate = n.m_cost + ManhattanDistance(n.m_key, this->m_dest);
|
||||
n.estimate = n.cost + ManhattanDistance(n.key, this->dest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -183,7 +183,7 @@ public:
|
|||
node.Set(&old_node, water_region_patch);
|
||||
Yapf().AddNewNode(node, TrackFollower{});
|
||||
};
|
||||
VisitWaterRegionPatchNeighbors(old_node.m_key.m_water_region_patch, visitFunc);
|
||||
VisitWaterRegionPatchNeighbors(old_node.key.water_region_patch, visitFunc);
|
||||
}
|
||||
|
||||
inline char TransportTypeChar() const { return '^'; }
|
||||
|
@ -223,8 +223,8 @@ public:
|
|||
Node *node = pf.GetBestNode();
|
||||
for (int i = 0; i < max_returned_path_length - 1; ++i) {
|
||||
if (node != nullptr) {
|
||||
node = node->m_parent;
|
||||
if (node != nullptr) path.push_back(node->m_key.m_water_region_patch);
|
||||
node = node->parent;
|
||||
if (node != nullptr) path.push_back(node->key.water_region_patch);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,13 +255,13 @@ public:
|
|||
*/
|
||||
inline bool PfCalcCost(Node &n, const TrackFollower *)
|
||||
{
|
||||
n.m_cost = n.m_parent->m_cost + ManhattanDistance(n.m_key, n.m_parent->m_key);
|
||||
n.cost = n.parent->cost + ManhattanDistance(n.key, n.parent->key);
|
||||
|
||||
/* Incentivise zigzagging by adding a slight penalty when the search continues in the same direction. */
|
||||
Node *grandparent = n.m_parent->m_parent;
|
||||
Node *grandparent = n.parent->parent;
|
||||
if (grandparent != nullptr) {
|
||||
const DiagDirDiff dir_diff = DiagDirDifference(n.m_parent->GetDiagDirFromParent(), n.GetDiagDirFromParent());
|
||||
if (dir_diff != DIAGDIRDIFF_90LEFT && dir_diff != DIAGDIRDIFF_90RIGHT) n.m_cost += 1;
|
||||
const DiagDirDiff dir_diff = DiagDirDifference(n.parent->GetDiagDirFromParent(), n.GetDiagDirFromParent());
|
||||
if (dir_diff != DIAGDIRDIFF_90LEFT && dir_diff != DIAGDIRDIFF_90RIGHT) n.cost += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -297,7 +297,7 @@ typedef CNodeList_HashTableT<CYapfRegionNodeT<CYapfRegionPatchNodeKey>, 12, 12>
|
|||
|
||||
struct CYapfRegionWater : CYapfT<CYapfRegion_TypesT<CYapfRegionWater, CRegionNodeListWater>>
|
||||
{
|
||||
explicit CYapfRegionWater(int max_nodes) { this->m_max_search_nodes = max_nodes; }
|
||||
explicit CYapfRegionWater(int max_nodes) { this->max_search_nodes = max_nodes; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
42
src/pbs.cpp
42
src/pbs.cpp
|
@ -198,18 +198,18 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
|||
/* Do not disallow 90 deg turns as the setting might have changed between reserving and now. */
|
||||
CFollowTrackRail ft(o, rts);
|
||||
while (ft.Follow(tile, trackdir)) {
|
||||
TrackdirBits reserved = ft.m_new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(ft.m_new_tile));
|
||||
TrackdirBits reserved = ft.new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(ft.new_tile));
|
||||
|
||||
/* No reservation --> path end found */
|
||||
if (reserved == TRACKDIR_BIT_NONE) {
|
||||
if (ft.m_is_station) {
|
||||
if (ft.is_station) {
|
||||
/* Check skipped station tiles as well, maybe our reservation ends inside the station. */
|
||||
TileIndexDiff diff = TileOffsByDiagDir(ft.m_exitdir);
|
||||
while (ft.m_tiles_skipped-- > 0) {
|
||||
ft.m_new_tile -= diff;
|
||||
if (HasStationReservation(ft.m_new_tile)) {
|
||||
tile = ft.m_new_tile;
|
||||
trackdir = DiagDirToDiagTrackdir(ft.m_exitdir);
|
||||
TileIndexDiff diff = TileOffsByDiagDir(ft.exitdir);
|
||||
while (ft.tiles_skipped-- > 0) {
|
||||
ft.new_tile -= diff;
|
||||
if (HasStationReservation(ft.new_tile)) {
|
||||
tile = ft.new_tile;
|
||||
trackdir = DiagDirToDiagTrackdir(ft.exitdir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -222,9 +222,9 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
|
|||
|
||||
/* One-way signal against us. The reservation can't be ours as it is not
|
||||
* a safe position from our direction and we can never pass the signal. */
|
||||
if (!ignore_oneway && HasOnewaySignalBlockingTrackdir(ft.m_new_tile, new_trackdir)) break;
|
||||
if (!ignore_oneway && HasOnewaySignalBlockingTrackdir(ft.new_tile, new_trackdir)) break;
|
||||
|
||||
tile = ft.m_new_tile;
|
||||
tile = ft.new_tile;
|
||||
trackdir = new_trackdir;
|
||||
|
||||
if (first_loop) {
|
||||
|
@ -396,17 +396,17 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo
|
|||
}
|
||||
|
||||
/* Check for reachable tracks. */
|
||||
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile), forbid_90deg)) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) return include_line_end;
|
||||
ft.new_td_bits &= DiagdirReachesTrackdirs(ft.exitdir);
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile), forbid_90deg)) ft.new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||
if (ft.new_td_bits == TRACKDIR_BIT_NONE) return include_line_end;
|
||||
|
||||
if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||
Trackdir td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
if (ft.new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||
Trackdir td = FindFirstTrackdir(ft.new_td_bits);
|
||||
/* PBS signal on next trackdir? Safe position. */
|
||||
if (HasPbsSignalOnTrackdir(ft.m_new_tile, td)) return true;
|
||||
if (HasPbsSignalOnTrackdir(ft.new_tile, td)) return true;
|
||||
/* One-way PBS signal against us? Safe if end-of-line is allowed. */
|
||||
if (IsTileType(ft.m_new_tile, MP_RAILWAY) && HasSignalOnTrackdir(ft.m_new_tile, ReverseTrackdir(td)) &&
|
||||
GetSignalType(ft.m_new_tile, TrackdirToTrack(td)) == SIGTYPE_PBS_ONEWAY) {
|
||||
if (IsTileType(ft.new_tile, MP_RAILWAY) && HasSignalOnTrackdir(ft.new_tile, ReverseTrackdir(td)) &&
|
||||
GetSignalType(ft.new_tile, TrackdirToTrack(td)) == SIGTYPE_PBS_ONEWAY) {
|
||||
return include_line_end;
|
||||
}
|
||||
}
|
||||
|
@ -441,8 +441,8 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
|
|||
if (!ft.Follow(tile, trackdir)) return true;
|
||||
|
||||
/* Check for reachable tracks. */
|
||||
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile), forbid_90deg)) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||
ft.new_td_bits &= DiagdirReachesTrackdirs(ft.exitdir);
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile), forbid_90deg)) ft.new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||
|
||||
return !HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits));
|
||||
return !HasReservedTracks(ft.new_tile, TrackdirBitsToTrackBits(ft.new_td_bits));
|
||||
}
|
||||
|
|
|
@ -2245,16 +2245,16 @@ static void CheckNextTrainTile(Train *v)
|
|||
CFollowTrackRail ft(v);
|
||||
if (!ft.Follow(v->tile, td)) return;
|
||||
|
||||
if (!HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits))) {
|
||||
if (!HasReservedTracks(ft.new_tile, TrackdirBitsToTrackBits(ft.new_td_bits))) {
|
||||
/* Next tile is not reserved. */
|
||||
if (KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||
if (HasPbsSignalOnTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) {
|
||||
if (KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||
if (HasPbsSignalOnTrackdir(ft.new_tile, FindFirstTrackdir(ft.new_td_bits))) {
|
||||
/* If the next tile is a PBS signal, try to make a reservation. */
|
||||
TrackBits tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits);
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) {
|
||||
tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.m_old_td));
|
||||
TrackBits tracks = TrackdirBitsToTrackBits(ft.new_td_bits);
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) {
|
||||
tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.old_td));
|
||||
}
|
||||
ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, nullptr, false);
|
||||
ChooseTrainTrack(v, ft.new_tile, ft.exitdir, tracks, false, nullptr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2410,8 +2410,8 @@ void FreeTrainTrackReservation(const Train *v)
|
|||
|
||||
CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes);
|
||||
while (ft.Follow(tile, td)) {
|
||||
tile = ft.m_new_tile;
|
||||
TrackdirBits bits = ft.m_new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(tile));
|
||||
tile = ft.new_tile;
|
||||
TrackdirBits bits = ft.new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(tile));
|
||||
td = RemoveFirstTrackdir(&bits);
|
||||
assert(bits == TRACKDIR_BIT_NONE);
|
||||
|
||||
|
@ -2441,7 +2441,7 @@ void FreeTrainTrackReservation(const Train *v)
|
|||
}
|
||||
|
||||
/* Don't free first station/bridge/tunnel if we are on it. */
|
||||
if (free_tile || (!(ft.m_is_station && GetStationIndex(ft.m_new_tile) == station_id) && !ft.m_is_tunnel && !ft.m_is_bridge)) ClearPathReservation(v, tile, td);
|
||||
if (free_tile || (!(ft.is_station && GetStationIndex(ft.new_tile) == station_id) && !ft.is_tunnel && !ft.is_bridge)) ClearPathReservation(v, tile, td);
|
||||
|
||||
free_tile = true;
|
||||
}
|
||||
|
@ -2493,39 +2493,39 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
|||
TileIndex tile = origin.tile;
|
||||
Trackdir cur_td = origin.trackdir;
|
||||
while (ft.Follow(tile, cur_td)) {
|
||||
if (KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||
if (KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||
/* Possible signal tile. */
|
||||
if (HasOnewaySignalBlockingTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) break;
|
||||
if (HasOnewaySignalBlockingTrackdir(ft.new_tile, FindFirstTrackdir(ft.new_td_bits))) break;
|
||||
}
|
||||
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) {
|
||||
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td);
|
||||
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) break;
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) {
|
||||
ft.new_td_bits &= ~TrackdirCrossesTrackdirs(ft.old_td);
|
||||
if (ft.new_td_bits == TRACKDIR_BIT_NONE) break;
|
||||
}
|
||||
|
||||
/* Station, depot or waypoint are a possible target. */
|
||||
bool target_seen = ft.m_is_station || (IsTileType(ft.m_new_tile, MP_RAILWAY) && !IsPlainRail(ft.m_new_tile));
|
||||
if (target_seen || KillFirstBit(ft.m_new_td_bits) != TRACKDIR_BIT_NONE) {
|
||||
bool target_seen = ft.is_station || (IsTileType(ft.new_tile, MP_RAILWAY) && !IsPlainRail(ft.new_tile));
|
||||
if (target_seen || KillFirstBit(ft.new_td_bits) != TRACKDIR_BIT_NONE) {
|
||||
/* Choice found or possible target encountered.
|
||||
* On finding a possible target, we need to stop and let the pathfinder handle the
|
||||
* remaining path. This is because we don't know if this target is in one of our
|
||||
* orders, so we might cause pathfinding to fail later on if we find a choice.
|
||||
* This failure would cause a bogous call to TryReserveSafePath which might reserve
|
||||
* a wrong path not leading to our next destination. */
|
||||
if (HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(TrackdirReachesTrackdirs(ft.m_old_td)))) break;
|
||||
if (HasReservedTracks(ft.new_tile, TrackdirBitsToTrackBits(TrackdirReachesTrackdirs(ft.old_td)))) break;
|
||||
|
||||
/* If we did skip some tiles, backtrack to the first skipped tile so the pathfinder
|
||||
* actually starts its search at the first unreserved tile. */
|
||||
if (ft.m_tiles_skipped != 0) ft.m_new_tile -= TileOffsByDiagDir(ft.m_exitdir) * ft.m_tiles_skipped;
|
||||
if (ft.tiles_skipped != 0) ft.new_tile -= TileOffsByDiagDir(ft.exitdir) * ft.tiles_skipped;
|
||||
|
||||
/* Choice found, path valid but not okay. Save info about the choice tile as well. */
|
||||
if (new_tracks != nullptr) *new_tracks = TrackdirBitsToTrackBits(ft.m_new_td_bits);
|
||||
if (enterdir != nullptr) *enterdir = ft.m_exitdir;
|
||||
return PBSTileInfo(ft.m_new_tile, ft.m_old_td, false);
|
||||
if (new_tracks != nullptr) *new_tracks = TrackdirBitsToTrackBits(ft.new_td_bits);
|
||||
if (enterdir != nullptr) *enterdir = ft.exitdir;
|
||||
return PBSTileInfo(ft.new_tile, ft.old_td, false);
|
||||
}
|
||||
|
||||
tile = ft.m_new_tile;
|
||||
cur_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
tile = ft.new_tile;
|
||||
cur_td = FindFirstTrackdir(ft.new_td_bits);
|
||||
|
||||
Trackdir rev_td = ReverseTrackdir(cur_td);
|
||||
if (IsSafeWaitingPosition(v, tile, cur_td, true, _settings_game.pf.forbid_90_deg)) {
|
||||
|
@ -2551,27 +2551,27 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
|
|||
}
|
||||
}
|
||||
|
||||
if (ft.m_err == CFollowTrackRail::EC_OWNER || ft.m_err == CFollowTrackRail::EC_NO_WAY) {
|
||||
if (ft.err == CFollowTrackRail::EC_OWNER || ft.err == CFollowTrackRail::EC_NO_WAY) {
|
||||
/* End of line, path valid and okay. */
|
||||
return PBSTileInfo(ft.m_old_tile, ft.m_old_td, true);
|
||||
return PBSTileInfo(ft.old_tile, ft.old_td, true);
|
||||
}
|
||||
|
||||
/* Sorry, can't reserve path, back out. */
|
||||
tile = origin.tile;
|
||||
cur_td = origin.trackdir;
|
||||
TileIndex stopped = ft.m_old_tile;
|
||||
Trackdir stopped_td = ft.m_old_td;
|
||||
TileIndex stopped = ft.old_tile;
|
||||
Trackdir stopped_td = ft.old_td;
|
||||
while (tile != stopped || cur_td != stopped_td) {
|
||||
if (!ft.Follow(tile, cur_td)) break;
|
||||
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.m_old_tile), GetTileRailType(ft.m_new_tile))) {
|
||||
ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(ft.m_old_td);
|
||||
assert(ft.m_new_td_bits != TRACKDIR_BIT_NONE);
|
||||
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) {
|
||||
ft.new_td_bits &= ~TrackdirCrossesTrackdirs(ft.old_td);
|
||||
assert(ft.new_td_bits != TRACKDIR_BIT_NONE);
|
||||
}
|
||||
assert(KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE);
|
||||
assert(KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE);
|
||||
|
||||
tile = ft.m_new_tile;
|
||||
cur_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||
tile = ft.new_tile;
|
||||
cur_td = FindFirstTrackdir(ft.new_td_bits);
|
||||
|
||||
UnreserveRailTrack(tile, TrackdirToTrack(cur_td));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue