KUDr@3900: /* $Id$ */ KUDr@3900: KUDr@3900: #ifndef YAPF_COMMON_HPP KUDr@3900: #define YAPF_COMMON_HPP KUDr@3900: KUDr@3914: /** YAPF origin provider base class - used when origin is one tile / multiple trackdirs */ KUDr@3900: template KUDr@3900: class CYapfOriginTileT KUDr@3900: { KUDr@3900: public: KUDr@3914: typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) KUDr@3900: typedef typename Types::NodeList::Titem Node; ///< this will be our node type KUDr@3914: typedef typename Node::Key Key; ///< key to hash tables KUDr@3900: KUDr@3900: protected: KUDr@3914: TileIndex m_orgTile; ///< origin tile KUDr@3914: TrackdirBits m_orgTrackdirs; ///< origin trackdir mask KUDr@3900: KUDr@3914: /// to access inherited path finder KUDr@3900: FORCEINLINE Tpf& Yapf() {return *static_cast(this);} KUDr@3900: KUDr@3900: public: KUDr@3914: /// Set origin tile / trackdir mask KUDr@3900: void SetOrigin(TileIndex tile, TrackdirBits trackdirs) KUDr@3900: { KUDr@3900: m_orgTile = tile; KUDr@3900: m_orgTrackdirs = trackdirs; KUDr@3900: } KUDr@3900: KUDr@3914: /// Called when YAPF needs to place origin nodes into open list KUDr@3900: void PfSetStartupNodes() KUDr@3900: { KUDr@3978: bool is_choice = (KillFirstBit2x64(m_orgTrackdirs) != 0); KUDr@3900: for (TrackdirBits tdb = m_orgTrackdirs; tdb != TRACKDIR_BIT_NONE; tdb = (TrackdirBits)KillFirstBit2x64(tdb)) { KUDr@3900: Trackdir td = (Trackdir)FindFirstBit2x64(tdb); KUDr@3900: Node& n1 = Yapf().CreateNewNode(); KUDr@3978: n1.Set(NULL, m_orgTile, td, is_choice); KUDr@3900: Yapf().AddStartupNode(n1); KUDr@3900: } KUDr@3900: } KUDr@3900: }; KUDr@3900: KUDr@3914: /** YAPF origin provider base class - used when there are two tile/trackdir origins */ KUDr@3900: template KUDr@3900: class CYapfOriginTileTwoWayT KUDr@3900: { KUDr@3900: public: KUDr@3914: typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) KUDr@3900: typedef typename Types::NodeList::Titem Node; ///< this will be our node type KUDr@3914: typedef typename Node::Key Key; ///< key to hash tables KUDr@3900: KUDr@3900: protected: KUDr@5627: TileIndex m_org_tile; ///< first origin tile KUDr@5627: TrackdirBits m_org_td_bits; ///< first origin trackdirbits KUDr@5627: TileIndex m_rev_tile; ///< second (reversed) origin tile KUDr@5627: TrackdirBits m_rev_td_bits; ///< second (reversed) origin trackdir KUDr@5627: int m_reverse_penalty; ///< penalty to be added for using the reversed origin KUDr@5627: bool m_treat_first_red_two_way_signal_as_eol; ///< in some cases (leaving station) we need to handle first two-way signal differently KUDr@3900: KUDr@3914: /// to access inherited path finder KUDr@3900: FORCEINLINE Tpf& Yapf() {return *static_cast(this);} KUDr@3900: KUDr@3900: public: KUDr@3914: /// set origin (tiles, trackdirs, etc.) KUDr@5627: void SetOrigin(TileIndex tile, TrackdirBits td_bits, TileIndex tiler = INVALID_TILE, TrackdirBits tdr_bits = INVALID_TRACKDIR_BIT, int reverse_penalty = 0, bool treat_first_red_two_way_signal_as_eol = true) KUDr@3900: { KUDr@5627: m_org_tile = tile; KUDr@5627: m_org_td_bits = td_bits; KUDr@5627: m_rev_tile = tiler; KUDr@5627: m_rev_td_bits = tdr_bits; KUDr@3900: m_reverse_penalty = reverse_penalty; KUDr@3900: m_treat_first_red_two_way_signal_as_eol = treat_first_red_two_way_signal_as_eol; KUDr@3900: } KUDr@3900: KUDr@3914: /// Called when YAPF needs to place origin nodes into open list KUDr@3900: void PfSetStartupNodes() KUDr@3900: { KUDr@5627: if (m_org_tile != INVALID_TILE && m_org_td_bits != INVALID_TRACKDIR_BIT) { KUDr@5627: for (TrackdirBits td_bits = m_org_td_bits; td_bits != TRACKDIR_BIT_NONE; td_bits = (TrackdirBits)KillFirstBit2x64(td_bits)) { KUDr@5627: Node& n = Yapf().CreateNewNode(); KUDr@5627: Trackdir td = (Trackdir)FindFirstBit2x64(td_bits); KUDr@5627: n.Set(NULL, m_org_tile, td, false); KUDr@5627: Yapf().AddStartupNode(n); KUDr@5627: } KUDr@3900: } KUDr@5627: if (m_rev_tile != INVALID_TILE && m_rev_td_bits != INVALID_TRACKDIR_BIT) { KUDr@5627: for (TrackdirBits td_bits = m_rev_td_bits; td_bits != TRACKDIR_BIT_NONE; td_bits = (TrackdirBits)KillFirstBit2x64(td_bits)) { KUDr@5627: Node& n = Yapf().CreateNewNode(); KUDr@5627: Trackdir td = (Trackdir)FindFirstBit2x64(td_bits); KUDr@5627: n.Set(NULL, m_rev_tile, td, false); KUDr@5627: n.m_cost = m_reverse_penalty; KUDr@5627: Yapf().AddStartupNode(n); KUDr@5627: } KUDr@3900: } KUDr@3900: } KUDr@3900: KUDr@3914: /// return true if first two-way signal should be treated as dead end KUDr@3900: FORCEINLINE bool TreatFirstRedTwoWaySignalAsEOL() KUDr@3900: { KUDr@3900: return Yapf().PfGetSettings().rail_firstred_twoway_eol && m_treat_first_red_two_way_signal_as_eol; KUDr@3900: } KUDr@3900: }; KUDr@3900: KUDr@3914: /** YAPF destination provider base class - used when destination is single tile / multiple trackdirs */ KUDr@3900: template KUDr@3900: class CYapfDestinationTileT KUDr@3900: { KUDr@3900: public: KUDr@3914: typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) KUDr@3900: typedef typename Types::NodeList::Titem Node; ///< this will be our node type KUDr@3914: typedef typename Node::Key Key; ///< key to hash tables KUDr@3900: KUDr@3900: protected: KUDr@3914: TileIndex m_destTile; ///< destination tile KUDr@3914: TrackdirBits m_destTrackdirs; ///< destination trackdir mask KUDr@3900: KUDr@3900: public: KUDr@3914: /// set the destination tile / more trackdirs KUDr@3900: void SetDestination(TileIndex tile, TrackdirBits trackdirs) KUDr@3900: { KUDr@3900: m_destTile = tile; KUDr@3900: m_destTrackdirs = trackdirs; KUDr@3900: } KUDr@3900: KUDr@3900: protected: KUDr@3914: /// to access inherited path finder KUDr@3900: Tpf& Yapf() {return *static_cast(this);} KUDr@3900: KUDr@3900: public: KUDr@3914: /// Called by YAPF to detect if node ends in the desired destination KUDr@3900: FORCEINLINE bool PfDetectDestination(Node& n) KUDr@3900: { KUDr@3900: bool bDest = (n.m_key.m_tile == m_destTile) && ((m_destTrackdirs & TrackdirToTrackdirBits(n.GetTrackdir())) != TRACKDIR_BIT_NONE); KUDr@3900: return bDest; KUDr@3900: } KUDr@3900: KUDr@3914: /** Called by YAPF to calculate cost estimate. Calculates distance to the destination rubidium@4549: * adds it to the actual cost from origin and stores the sum to the Node::m_estimate */ KUDr@3900: inline bool PfCalcEstimate(Node& n) KUDr@3900: { KUDr@3900: int dx = abs(TileX(n.GetTile()) - TileX(m_destTile)); KUDr@3900: int dy = abs(TileY(n.GetTile()) - TileY(m_destTile)); KUDr@3900: assert(dx >= 0 && dy >= 0); KUDr@3900: int dd = min(dx, dy); KUDr@3900: int dxy = abs(dx - dy); KUDr@3900: int d = 14 * dd + 10 * dxy; KUDr@3900: n.m_estimate = n.m_cost + d /*+ d / 8*/; KUDr@3900: return true; KUDr@3900: } KUDr@3900: }; KUDr@3900: KUDr@3914: /** YAPF template that uses Ttypes template argument to determine all YAPF rubidium@4549: * components (base classes) from which the actual YAPF is composed. rubidium@4549: * For example classes consult: CYapfRail_TypesT template and its instantiations: rubidium@4549: * CYapfRail1, CYapfRail2, CYapfRail3, CYapfAnyDepotRail1, CYapfAnyDepotRail2, CYapfAnyDepotRail3 */ KUDr@3900: template KUDr@3900: class CYapfT KUDr@3914: : public Ttypes::PfBase ///< Instance of CYapfBaseT - main YAPF loop and support base class KUDr@3914: , public Ttypes::PfCost ///< Cost calculation provider base class KUDr@3914: , public Ttypes::PfCache ///< Segment cost cache provider KUDr@3914: , public Ttypes::PfOrigin ///< Origin (tile or two-tile origin) KUDr@3914: , public Ttypes::PfDestination ///< Destination detector and distance (estimate) calculation provider KUDr@3914: , public Ttypes::PfFollow ///< Node follower (stepping provider) KUDr@3900: { KUDr@3900: }; KUDr@3900: KUDr@3900: KUDr@3900: KUDr@3900: #endif /* YAPF_COMMON_HPP */