diff options
Diffstat (limited to 'src/pathfinder/yapf/yapf_destrail.hpp')
-rw-r--r-- | src/pathfinder/yapf/yapf_destrail.hpp | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/src/pathfinder/yapf/yapf_destrail.hpp b/src/pathfinder/yapf/yapf_destrail.hpp new file mode 100644 index 000000000..acdc68244 --- /dev/null +++ b/src/pathfinder/yapf/yapf_destrail.hpp @@ -0,0 +1,203 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file yapf_destrail.hpp Determining the destination for rail vehicles. */ + +#ifndef YAPF_DESTRAIL_HPP +#define YAPF_DESTRAIL_HPP + +class CYapfDestinationRailBase +{ +protected: + RailTypes m_compatible_railtypes; + +public: + void SetDestination(const Vehicle *v, bool override_rail_type = false) + { + m_compatible_railtypes = Train::From(v)->compatible_railtypes; + if (override_rail_type) m_compatible_railtypes |= GetRailTypeInfo(Train::From(v)->railtype)->compatible_railtypes; + } + + bool IsCompatibleRailType(RailType rt) + { + return HasBit(m_compatible_railtypes, rt); + } + + RailTypes GetCompatibleRailTypes() const + { + return m_compatible_railtypes; + } +}; + +template <class Types> +class CYapfDestinationAnyDepotRailT + : public CYapfDestinationRailBase +{ +public: + typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) + typedef typename Types::NodeList::Titem Node; ///< this will be our node type + typedef typename Node::Key Key; ///< key to hash tables + + /** to access inherited path finder */ + Tpf& Yapf() + { + return *static_cast<Tpf*>(this); + } + + /** Called by YAPF to detect if node ends in the desired destination */ + FORCEINLINE bool PfDetectDestination(Node& n) + { + return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir()); + } + + /** Called by YAPF to detect if node ends in the desired destination */ + FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td) + { + bool bDest = IsRailDepotTile(tile); + return bDest; + } + + /** 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 */ + FORCEINLINE bool PfCalcEstimate(Node& n) + { + n.m_estimate = n.m_cost; + return true; + } +}; + +template <class Types> +class CYapfDestinationAnySafeTileRailT + : public CYapfDestinationRailBase +{ +public: + typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) + typedef typename Types::NodeList::Titem Node; ///< this will be our node type + typedef typename Node::Key Key; ///< key to hash tables + typedef typename Types::TrackFollower TrackFollower; ///< TrackFollower. Need to typedef for gcc 2.95 + + /** to access inherited path finder */ + Tpf& Yapf() + { + return *static_cast<Tpf*>(this); + } + + /** Called by YAPF to detect if node ends in the desired destination */ + FORCEINLINE bool PfDetectDestination(Node& n) + { + return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir()); + } + + /** Called by YAPF to detect if node ends in the desired destination */ + FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td) + { + return + IsSafeWaitingPosition(Train::From(Yapf().GetVehicle()), tile, td, true, !TrackFollower::Allow90degTurns()) && + IsWaitingPositionFree(Train::From(Yapf().GetVehicle()), tile, td, !TrackFollower::Allow90degTurns()); + } + + /** 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. */ + FORCEINLINE bool PfCalcEstimate(Node& n) + { + n.m_estimate = n.m_cost; + return true; + } +}; + +template <class Types> +class CYapfDestinationTileOrStationRailT + : public CYapfDestinationRailBase +{ +public: + typedef typename Types::Tpf Tpf; ///< the pathfinder class (derived from THIS class) + typedef typename Types::NodeList::Titem Node; ///< this will be our node type + typedef typename Node::Key Key; ///< key to hash tables + +protected: + TileIndex m_destTile; + TrackdirBits m_destTrackdirs; + StationID m_dest_station_id; + + /** to access inherited path finder */ + Tpf& Yapf() + { + return *static_cast<Tpf*>(this); + } + +public: + void SetDestination(const Vehicle *v) + { + switch (v->current_order.GetType()) { + case OT_GOTO_STATION: + case OT_GOTO_WAYPOINT: + m_destTile = CalcClosestStationTile(v->current_order.GetDestination(), v->tile); + m_dest_station_id = v->current_order.GetDestination(); + m_destTrackdirs = INVALID_TRACKDIR_BIT; + break; + + default: + m_destTile = v->dest_tile; + m_dest_station_id = INVALID_STATION; + m_destTrackdirs = TrackStatusToTrackdirBits(GetTileTrackStatus(v->dest_tile, TRANSPORT_RAIL, 0)); + break; + } + CYapfDestinationRailBase::SetDestination(v); + } + + /** Called by YAPF to detect if node ends in the desired destination */ + FORCEINLINE bool PfDetectDestination(Node& n) + { + return PfDetectDestination(n.GetLastTile(), n.GetLastTrackdir()); + } + + /** Called by YAPF to detect if node ends in the desired destination */ + FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td) + { + bool bDest; + if (m_dest_station_id != INVALID_STATION) { + bDest = HasStationTileRail(tile) + && (GetStationIndex(tile) == m_dest_station_id) + && (GetRailStationTrack(tile) == TrackdirToTrack(td)); + } else { + bDest = (tile == m_destTile) + && ((m_destTrackdirs & TrackdirToTrackdirBits(td)) != TRACKDIR_BIT_NONE); + } + return bDest; + } + + /** 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 */ + FORCEINLINE 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 (PfDetectDestination(n)) { + n.m_estimate = n.m_cost; + return true; + } + + TileIndex tile = n.GetLastTile(); + 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(m_destTile); + int y2 = 2 * TileY(m_destTile); + int dx = abs(x1 - x2); + int dy = abs(y1 - y2); + int dmin = 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); + return true; + } +}; + +#endif /* YAPF_DESTRAIL_HPP */ |