mirror of https://github.com/OpenTTD/OpenTTD
(svn r13940) -Add [YAPP]: YAPF is now able to reserve the found path. (michi_cc)
parent
c91c12adde
commit
abc46b1e86
119
src/pbs.cpp
119
src/pbs.cpp
|
@ -12,6 +12,9 @@
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "direction_func.h"
|
#include "direction_func.h"
|
||||||
#include "settings_type.h"
|
#include "settings_type.h"
|
||||||
|
#include "road_func.h"
|
||||||
|
#include "vehicle_base.h"
|
||||||
|
#include "yapf/follow_track.hpp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the reserved trackbits for any tile, regardless of type.
|
* Get the reserved trackbits for any tile, regardless of type.
|
||||||
|
@ -155,3 +158,119 @@ bool TryReserveRailTrack(TileIndex tile, Track t)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Follow a train reservation to the last tile.
|
||||||
|
*
|
||||||
|
* @param v the vehicle
|
||||||
|
* @returns The last tile of the reservation or the current train tile if no reservation present.
|
||||||
|
*/
|
||||||
|
PBSTileInfo FollowTrainReservation(const Vehicle *v)
|
||||||
|
{
|
||||||
|
assert(v->type == VEH_TRAIN);
|
||||||
|
|
||||||
|
TileIndex tile = v->tile;
|
||||||
|
Trackdir trackdir = GetVehicleTrackdir(v);
|
||||||
|
|
||||||
|
if (IsRailDepotTile(tile) && !GetRailDepotReservation(tile)) return PBSTileInfo(tile, trackdir, false);
|
||||||
|
|
||||||
|
/* Do not disallow 90 deg turns as the setting might have changed between reserving and now. */
|
||||||
|
CFollowTrackRail ft(v, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes);
|
||||||
|
while (ft.Follow(tile, trackdir)) {
|
||||||
|
TrackdirBits reserved = (TrackdirBits)(ft.m_new_td_bits & (GetReservedTrackbits(ft.m_new_tile) * 0x101));
|
||||||
|
|
||||||
|
/* No reservation --> path end found */
|
||||||
|
if (reserved == TRACKDIR_BIT_NONE) break;
|
||||||
|
|
||||||
|
/* Can't have more than one reserved trackdir */
|
||||||
|
Trackdir new_trackdir = FindFirstTrackdir(reserved);
|
||||||
|
|
||||||
|
/* 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 (HasOnewaySignalBlockingTrackdir(ft.m_new_tile, new_trackdir)) break;
|
||||||
|
|
||||||
|
tile = ft.m_new_tile;
|
||||||
|
trackdir = new_trackdir;
|
||||||
|
|
||||||
|
/* Depot tile? Can't continue. */
|
||||||
|
if (IsRailDepotTile(tile)) break;
|
||||||
|
/* Non-pbs signal? Reservation can't continue. */
|
||||||
|
if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PBSTileInfo(tile, trackdir, IsSafeWaitingPosition(v, tile, trackdir, true, _settings_game.pf.forbid_90_deg));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a certain track on a tile is a safe position to end a path.
|
||||||
|
*
|
||||||
|
* @param v the vehicle to test for
|
||||||
|
* @param tile The tile
|
||||||
|
* @param trackdir The trackdir to test
|
||||||
|
* @param include_line_end Should end-of-line tiles be considered safe?
|
||||||
|
* @param forbid_90def Don't allow trains to make 90 degree turns
|
||||||
|
* @return True if it is a safe position
|
||||||
|
*/
|
||||||
|
bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg)
|
||||||
|
{
|
||||||
|
if (IsRailDepotTile(tile)) return true;
|
||||||
|
|
||||||
|
if (IsTileType(tile, MP_RAILWAY)) {
|
||||||
|
/* For non-pbs signals, stop on the signal tile. */
|
||||||
|
if (HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check next tile. For perfomance reasons, we check for 90 degree turns ourself. */
|
||||||
|
CFollowTrackRail ft(v, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes);
|
||||||
|
|
||||||
|
/* End of track? */
|
||||||
|
if (!ft.Follow(tile, trackdir)) {
|
||||||
|
/* Last tile of a terminus station is a safe position. */
|
||||||
|
if (include_line_end) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for reachable tracks. */
|
||||||
|
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
||||||
|
if (ft.m_new_td_bits == TRACKDIR_BIT_NONE) return include_line_end;
|
||||||
|
if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||||
|
|
||||||
|
if (ft.m_new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE) {
|
||||||
|
/* PBS signal on next trackdir? Safe position. */
|
||||||
|
if (HasPbsSignalOnTrackdir(ft.m_new_tile, FindFirstTrackdir(ft.m_new_td_bits))) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a safe position is free.
|
||||||
|
*
|
||||||
|
* @param v the vehicle to test for
|
||||||
|
* @param tile The tile
|
||||||
|
* @param trackdir The trackdir to test
|
||||||
|
* @param forbid_90def Don't allow trains to make 90 degree turns
|
||||||
|
* @return True if the position is free
|
||||||
|
*/
|
||||||
|
bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg)
|
||||||
|
{
|
||||||
|
Track track = TrackdirToTrack(trackdir);
|
||||||
|
TrackBits reserved = GetReservedTrackbits(tile);
|
||||||
|
|
||||||
|
/* Tile reserved? Can never be a free waiting position. */
|
||||||
|
if (TrackOverlapsTracks(reserved, track)) return false;
|
||||||
|
|
||||||
|
/* Not reserved and depot or not a pbs signal -> free. */
|
||||||
|
if (IsRailDepotTile(tile)) return true;
|
||||||
|
if (IsTileType(tile, MP_RAILWAY) && HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, track))) return true;
|
||||||
|
|
||||||
|
/* Check the next tile, if it's a PBS signal, it has to be free as well. */
|
||||||
|
CFollowTrackRail ft(v, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes);
|
||||||
|
|
||||||
|
if (!ft.Follow(tile, trackdir)) return true;
|
||||||
|
|
||||||
|
/* Check for reachable tracks. */
|
||||||
|
ft.m_new_td_bits &= DiagdirReachesTrackdirs(ft.m_exitdir);
|
||||||
|
if (forbid_90deg) ft.m_new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
|
||||||
|
|
||||||
|
return !HasReservedTracks(ft.m_new_tile, TrackdirBitsToTrackBits(ft.m_new_td_bits));
|
||||||
|
}
|
||||||
|
|
15
src/pbs.h
15
src/pbs.h
|
@ -8,6 +8,7 @@
|
||||||
#include "tile_type.h"
|
#include "tile_type.h"
|
||||||
#include "direction_type.h"
|
#include "direction_type.h"
|
||||||
#include "track_type.h"
|
#include "track_type.h"
|
||||||
|
#include "vehicle_type.h"
|
||||||
|
|
||||||
TrackBits GetReservedTrackbits(TileIndex t);
|
TrackBits GetReservedTrackbits(TileIndex t);
|
||||||
|
|
||||||
|
@ -16,6 +17,20 @@ void SetRailwayStationPlatformReservation(TileIndex start, DiagDirection dir, bo
|
||||||
bool TryReserveRailTrack(TileIndex tile, Track t);
|
bool TryReserveRailTrack(TileIndex tile, Track t);
|
||||||
void UnreserveRailTrack(TileIndex tile, Track t);
|
void UnreserveRailTrack(TileIndex tile, Track t);
|
||||||
|
|
||||||
|
/** This struct contains information about the end of a reserved path. */
|
||||||
|
struct PBSTileInfo {
|
||||||
|
TileIndex tile; ///< Tile the path ends, INVALID_TILE if no valid path was found.
|
||||||
|
Trackdir trackdir; ///< The reserved trackdir on the tile.
|
||||||
|
bool okay; ///< True if tile is a safe wairing position, false otherwise.
|
||||||
|
|
||||||
|
PBSTileInfo() : tile(INVALID_TILE), trackdir(INVALID_TRACKDIR), okay(false) {}
|
||||||
|
PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
PBSTileInfo FollowTrainReservation(const Vehicle *v);
|
||||||
|
bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false);
|
||||||
|
bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether some of tracks is reserved on a tile.
|
* Check whether some of tracks is reserved on a tile.
|
||||||
*
|
*
|
||||||
|
|
|
@ -534,6 +534,21 @@ static inline bool HasPbsSignalOnTrackdir(TileIndex tile, Trackdir td)
|
||||||
IsPbsSignal(GetSignalType(tile, TrackdirToTrack(td)));
|
IsPbsSignal(GetSignalType(tile, TrackdirToTrack(td)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is a one-way signal blocking the trackdir? A one-way signal on the
|
||||||
|
* trackdir against will block, but signals on both trackdirs won't.
|
||||||
|
* @param tile the tile to check
|
||||||
|
* @param td the trackdir to check
|
||||||
|
*/
|
||||||
|
static inline bool HasOnewaySignalBlockingTrackdir(TileIndex tile, Trackdir td)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
IsTileType(tile, MP_RAILWAY) &&
|
||||||
|
HasSignalOnTrackdir(tile, ReverseTrackdir(td)) &&
|
||||||
|
!HasSignalOnTrackdir(tile, td) &&
|
||||||
|
IsOnewaySignal(tile, TrackdirToTrack(td));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
|
* Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
#include "../depot_type.h"
|
#include "../depot_type.h"
|
||||||
#include "../direction_type.h"
|
#include "../direction_type.h"
|
||||||
|
#include "../pbs.h"
|
||||||
|
|
||||||
/** Finds the best path for given ship.
|
/** Finds the best path for given ship.
|
||||||
* @param v the ship that needs to find a path
|
* @param v the ship that needs to find a path
|
||||||
|
@ -32,9 +33,11 @@ Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection ent
|
||||||
* @param enterdir diagonal direction which the RV will enter this new tile from
|
* @param enterdir diagonal direction which the RV will enter this new tile from
|
||||||
* @param tracks available trackdirs on the new tile (to choose from)
|
* @param tracks available trackdirs on the new tile (to choose from)
|
||||||
* @param path_not_found [out] true is returned if no path can be found (returned Trackdir is only a 'guess')
|
* @param path_not_found [out] true is returned if no path can be found (returned Trackdir is only a 'guess')
|
||||||
|
* @param reserve_track indicates whether YAPF should try to reserve the found path
|
||||||
|
* @param target [out] the target tile of the reservation, free is set to true if path was reserved
|
||||||
* @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
|
* @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
|
||||||
*/
|
*/
|
||||||
Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found);
|
Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, PBSTileInfo *target);
|
||||||
|
|
||||||
/** Used by RV multistop feature to find the nearest road stop that has a free slot.
|
/** Used by RV multistop feature to find the nearest road stop that has a free slot.
|
||||||
* @param v RV (its current tile will be the origin)
|
* @param v RV (its current tile will be the origin)
|
||||||
|
|
|
@ -177,6 +177,37 @@ struct CYapfRailNodeT
|
||||||
FORCEINLINE Trackdir GetLastTrackdir() const {assert(m_segment != NULL); return m_segment->m_last_td;}
|
FORCEINLINE Trackdir GetLastTrackdir() const {assert(m_segment != NULL); return m_segment->m_last_td;}
|
||||||
FORCEINLINE void SetLastTileTrackdir(TileIndex tile, Trackdir td) {assert(m_segment != NULL); m_segment->m_last_tile = tile; m_segment->m_last_td = td;}
|
FORCEINLINE void SetLastTileTrackdir(TileIndex tile, Trackdir td) {assert(m_segment != NULL); m_segment->m_last_tile = tile; m_segment->m_last_td = td;}
|
||||||
|
|
||||||
|
template <class Tbase, class Tfunc, class Tpf>
|
||||||
|
bool IterateTiles(const Vehicle *v, Tpf &yapf, Tbase &obj, bool (Tfunc::*func)(TileIndex, Trackdir)) const
|
||||||
|
{
|
||||||
|
typename Tbase::TrackFollower ft(v, yapf.GetCompatibleRailTypes());
|
||||||
|
TileIndex cur = base::GetTile();
|
||||||
|
Trackdir cur_td = base::GetTrackdir();
|
||||||
|
|
||||||
|
while (cur != GetLastTile() || cur_td != GetLastTrackdir()) {
|
||||||
|
if (!((obj.*func)(cur, cur_td))) return false;
|
||||||
|
|
||||||
|
ft.Follow(cur, cur_td);
|
||||||
|
cur = ft.m_new_tile;
|
||||||
|
assert(KillFirstBit(ft.m_new_td_bits) == TRACKDIR_BIT_NONE);
|
||||||
|
cur_td = FindFirstTrackdir(ft.m_new_td_bits);
|
||||||
|
|
||||||
|
/* Did we skip tiles because of a station? */
|
||||||
|
if (ft.m_is_station && ft.m_tiles_skipped > 0) {
|
||||||
|
TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(cur_td));
|
||||||
|
TileIndex tile = TILE_ADD(cur, -diff * ft.m_tiles_skipped);
|
||||||
|
|
||||||
|
/* Call func for all tiles in between. */
|
||||||
|
for (int i = 0; i < ft.m_tiles_skipped; ++i) {
|
||||||
|
if (!(obj.*func)(tile, cur_td)) return false;
|
||||||
|
tile = TILE_ADD(tile, diff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (obj.*func)(cur, cur_td);
|
||||||
|
}
|
||||||
|
|
||||||
void Dump(DumpTarget &dmp) const
|
void Dump(DumpTarget &dmp) const
|
||||||
{
|
{
|
||||||
base::Dump(dmp);
|
base::Dump(dmp);
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "yapf_costrail.hpp"
|
#include "yapf_costrail.hpp"
|
||||||
#include "yapf_destrail.hpp"
|
#include "yapf_destrail.hpp"
|
||||||
#include "../vehicle_func.h"
|
#include "../vehicle_func.h"
|
||||||
|
#include "../pbs.h"
|
||||||
|
|
||||||
#define DEBUG_YAPF_CACHE 0
|
#define DEBUG_YAPF_CACHE 0
|
||||||
|
|
||||||
|
@ -16,7 +17,115 @@ int _total_pf_time_us = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <class Types>
|
||||||
|
class CYapfReserveTrack
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
||||||
|
typedef typename Types::TrackFollower TrackFollower;
|
||||||
|
typedef typename Types::NodeList::Titem Node; ///< this will be our node type
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// to access inherited pathfinder
|
||||||
|
FORCEINLINE Tpf& Yapf() {return *static_cast<Tpf*>(this);}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
bool FindSafePositionProc(TileIndex tile, Trackdir td)
|
||||||
|
{
|
||||||
|
if (IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) {
|
||||||
|
m_res_dest = tile;
|
||||||
|
m_res_dest_td = td;
|
||||||
|
return false; // Stop iterating segment
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReserveSingleTrack(TileIndex tile, Trackdir td)
|
||||||
|
{
|
||||||
|
if (!TryReserveRailTrack(tile, TrackdirToTrack(td))) {
|
||||||
|
/* Tile couldn't be reserved, undo. */
|
||||||
|
m_res_fail_tile = tile;
|
||||||
|
m_res_fail_td = td;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* YAPF can sometimes skip parts of a station, so make sure we
|
||||||
|
* always reserve the whole platform. */
|
||||||
|
if (IsRailwayStationTile(tile)) SetRailwayStationPlatformReservation(tile, TrackdirToExitdir(ReverseTrackdir(td)), true);
|
||||||
|
return tile != m_res_dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnreserveSingleTrack(TileIndex tile, Trackdir td)
|
||||||
|
{
|
||||||
|
if (tile != m_res_fail_tile || td != m_res_fail_td) UnreserveRailTrack(tile, TrackdirToTrack(td));
|
||||||
|
return tile != m_res_dest && (tile != m_res_fail_tile || td != m_res_fail_td);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Set the target to where the reservation should be extended. */
|
||||||
|
inline void SetReservationTarget(Node *node, TileIndex tile, Trackdir td)
|
||||||
|
{
|
||||||
|
m_res_node = node;
|
||||||
|
m_res_dest = tile;
|
||||||
|
m_res_dest_td = td;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check the node for a possible reservation target. */
|
||||||
|
inline void FindSafePositionOnNode(Node *node)
|
||||||
|
{
|
||||||
|
assert(node->m_parent != NULL);
|
||||||
|
|
||||||
|
/* 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->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::FindSafePositionProc)) {
|
||||||
|
m_res_node = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Try to reserve the path till the reservation target. */
|
||||||
|
bool TryReservePath(PBSTileInfo *target)
|
||||||
|
{
|
||||||
|
m_res_fail_tile = INVALID_TILE;
|
||||||
|
|
||||||
|
if (target != NULL) {
|
||||||
|
target->tile = m_res_dest;
|
||||||
|
target->trackdir = m_res_dest_td;
|
||||||
|
target->okay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't bother if the target is reserved. */
|
||||||
|
if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false;
|
||||||
|
|
||||||
|
for (Node *node = m_res_node; node->m_parent != NULL; node = node->m_parent) {
|
||||||
|
node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack);
|
||||||
|
if (m_res_fail_tile != INVALID_TILE) {
|
||||||
|
/* Reservation failed, undo. */
|
||||||
|
Node *fail_node = m_res_node;
|
||||||
|
TileIndex stop_tile = m_res_fail_tile;
|
||||||
|
do {
|
||||||
|
/* If this is the node that failed, stop at the failed tile. */
|
||||||
|
m_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) != NULL);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target != NULL) target->okay = true;
|
||||||
|
|
||||||
|
if (Yapf().CanUseGlobalCache(*m_res_node))
|
||||||
|
YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <class Types>
|
template <class Types>
|
||||||
class CYapfFollowAnyDepotRailT
|
class CYapfFollowAnyDepotRailT
|
||||||
|
@ -95,7 +204,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Types>
|
template <class Types>
|
||||||
class CYapfFollowRailT
|
class CYapfFollowRailT : protected CYapfReserveTrack<Types>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class)
|
||||||
|
@ -121,16 +230,18 @@ public:
|
||||||
/// return debug report character to identify the transportation type
|
/// return debug report character to identify the transportation type
|
||||||
FORCEINLINE char TransportTypeChar() const {return 't';}
|
FORCEINLINE char TransportTypeChar() const {return 't';}
|
||||||
|
|
||||||
static Trackdir stChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
|
static Trackdir stChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, PBSTileInfo *target)
|
||||||
{
|
{
|
||||||
// create pathfinder instance
|
// create pathfinder instance
|
||||||
Tpf pf1;
|
Tpf pf1;
|
||||||
Trackdir result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found);
|
#if !DEBUG_YAPF_CACHE
|
||||||
|
Trackdir result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track, target);
|
||||||
|
|
||||||
#if DEBUG_YAPF_CACHE
|
#else
|
||||||
|
Trackdir result1 = pf1.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found, false, NULL);
|
||||||
Tpf pf2;
|
Tpf pf2;
|
||||||
pf2.DisableCache(true);
|
pf2.DisableCache(true);
|
||||||
Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found);
|
Trackdir result2 = pf2.ChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track, target);
|
||||||
if (result1 != result2) {
|
if (result1 != result2) {
|
||||||
DEBUG(yapf, 0, "CACHE ERROR: ChooseRailTrack() = [%d, %d]", result1, result2);
|
DEBUG(yapf, 0, "CACHE ERROR: ChooseRailTrack() = [%d, %d]", result1, result2);
|
||||||
DumpTarget dmp1, dmp2;
|
DumpTarget dmp1, dmp2;
|
||||||
|
@ -148,10 +259,13 @@ public:
|
||||||
return result1;
|
return result1;
|
||||||
}
|
}
|
||||||
|
|
||||||
FORCEINLINE Trackdir ChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
|
FORCEINLINE Trackdir ChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, PBSTileInfo *target)
|
||||||
{
|
{
|
||||||
|
if (target != NULL) target->tile = INVALID_TILE;
|
||||||
|
|
||||||
// set origin and destination nodes
|
// set origin and destination nodes
|
||||||
Yapf().SetOrigin(v->tile, GetVehicleTrackdir(v), INVALID_TILE, INVALID_TRACKDIR, 1, true);
|
PBSTileInfo origin = FollowTrainReservation(v);
|
||||||
|
Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, INVALID_TRACKDIR, 1, true);
|
||||||
Yapf().SetDestination(v);
|
Yapf().SetDestination(v);
|
||||||
|
|
||||||
// find the best path
|
// find the best path
|
||||||
|
@ -166,17 +280,23 @@ public:
|
||||||
Trackdir next_trackdir = INVALID_TRACKDIR;
|
Trackdir next_trackdir = INVALID_TRACKDIR;
|
||||||
Node *pNode = Yapf().GetBestNode();
|
Node *pNode = Yapf().GetBestNode();
|
||||||
if (pNode != NULL) {
|
if (pNode != NULL) {
|
||||||
|
// reserve till end of path
|
||||||
|
this->SetReservationTarget(pNode, pNode->GetLastTile(), pNode->GetLastTrackdir());
|
||||||
|
|
||||||
// path was found or at least suggested
|
// path was found or at least suggested
|
||||||
// walk through the path back to the origin
|
// walk through the path back to the origin
|
||||||
Node* pPrev = NULL;
|
Node* pPrev = NULL;
|
||||||
while (pNode->m_parent != NULL) {
|
while (pNode->m_parent != NULL) {
|
||||||
pPrev = pNode;
|
pPrev = pNode;
|
||||||
pNode = pNode->m_parent;
|
pNode = pNode->m_parent;
|
||||||
|
|
||||||
|
this->FindSafePositionOnNode(pPrev);
|
||||||
}
|
}
|
||||||
// return trackdir from the best origin node (one of start nodes)
|
// return trackdir from the best origin node (one of start nodes)
|
||||||
Node& best_next_node = *pPrev;
|
Node& best_next_node = *pPrev;
|
||||||
assert(best_next_node.GetTile() == tile);
|
|
||||||
next_trackdir = best_next_node.GetTrackdir();
|
next_trackdir = best_next_node.GetTrackdir();
|
||||||
|
|
||||||
|
if (reserve_track && path_found) this->TryReservePath(target);
|
||||||
}
|
}
|
||||||
return next_trackdir;
|
return next_trackdir;
|
||||||
}
|
}
|
||||||
|
@ -247,10 +367,10 @@ struct CYapfAnyDepotRail1 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail1, CFollowT
|
||||||
struct CYapfAnyDepotRail2 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail2, CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
|
struct CYapfAnyDepotRail2 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail2, CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT , CYapfFollowAnyDepotRailT> > {};
|
||||||
|
|
||||||
|
|
||||||
Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
|
Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, PBSTileInfo *target)
|
||||||
{
|
{
|
||||||
// default is YAPF type 2
|
// default is YAPF type 2
|
||||||
typedef Trackdir (*PfnChooseRailTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits, bool*);
|
typedef Trackdir (*PfnChooseRailTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits, bool*, bool, PBSTileInfo*);
|
||||||
PfnChooseRailTrack pfnChooseRailTrack = &CYapfRail1::stChooseRailTrack;
|
PfnChooseRailTrack pfnChooseRailTrack = &CYapfRail1::stChooseRailTrack;
|
||||||
|
|
||||||
// check if non-default YAPF type needed
|
// check if non-default YAPF type needed
|
||||||
|
@ -258,7 +378,7 @@ Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection ent
|
||||||
pfnChooseRailTrack = &CYapfRail2::stChooseRailTrack; // Trackdir, forbid 90-deg
|
pfnChooseRailTrack = &CYapfRail2::stChooseRailTrack; // Trackdir, forbid 90-deg
|
||||||
}
|
}
|
||||||
|
|
||||||
Trackdir td_ret = pfnChooseRailTrack(v, tile, enterdir, tracks, path_not_found);
|
Trackdir td_ret = pfnChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track, target);
|
||||||
|
|
||||||
return td_ret;
|
return td_ret;
|
||||||
}
|
}
|
||||||
|
@ -330,11 +450,8 @@ bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reve
|
||||||
|
|
||||||
const Vehicle *last_veh = GetLastVehicleInChain(v);
|
const Vehicle *last_veh = GetLastVehicleInChain(v);
|
||||||
|
|
||||||
TileIndex tile = v->tile;
|
PBSTileInfo origin = FollowTrainReservation(v);
|
||||||
TileIndex last_tile = last_veh->tile;
|
TileIndex last_tile = last_veh->tile;
|
||||||
|
|
||||||
// their trackdirs
|
|
||||||
Trackdir td = GetVehicleTrackdir(v);
|
|
||||||
Trackdir td_rev = ReverseTrackdir(GetVehicleTrackdir(last_veh));
|
Trackdir td_rev = ReverseTrackdir(GetVehicleTrackdir(last_veh));
|
||||||
|
|
||||||
typedef bool (*PfnFindNearestDepotTwoWay)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
|
typedef bool (*PfnFindNearestDepotTwoWay)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
|
||||||
|
@ -345,7 +462,7 @@ bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reve
|
||||||
pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail2::stFindNearestDepotTwoWay; // Trackdir, forbid 90-deg
|
pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail2::stFindNearestDepotTwoWay; // Trackdir, forbid 90-deg
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ret = pfnFindNearestDepotTwoWay(v, tile, td, last_tile, td_rev, max_distance, reverse_penalty, depot_tile, reversed);
|
bool ret = pfnFindNearestDepotTwoWay(v, origin.tile, origin.trackdir, last_tile, td_rev, max_distance, reverse_penalty, depot_tile, reversed);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue