2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
8 /** @file yapf_destrail.hpp Determining the destination for rail vehicles. */
10 #ifndef YAPF_DESTRAIL_HPP
11 #define YAPF_DESTRAIL_HPP
13 class CYapfDestinationRailBase
{
15 RailTypes m_compatible_railtypes
;
18 void SetDestination(const Train
*v
, bool override_rail_type
= false)
20 m_compatible_railtypes
= v
->compatible_railtypes
;
21 if (override_rail_type
) m_compatible_railtypes
|= GetRailTypeInfo(v
->railtype
)->compatible_railtypes
;
24 bool IsCompatibleRailType(RailType rt
)
26 return HasBit(m_compatible_railtypes
, rt
);
29 RailTypes
GetCompatibleRailTypes() const
31 return m_compatible_railtypes
;
35 template <class Types
>
36 class CYapfDestinationAnyDepotRailT
: public CYapfDestinationRailBase
{
38 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
39 typedef typename
Types::NodeList::Titem Node
; ///< this will be our node type
40 typedef typename
Node::Key Key
; ///< key to hash tables
42 /** to access inherited path finder */
45 return *static_cast<Tpf
*>(this);
48 /** Called by YAPF to detect if node ends in the desired destination */
49 inline bool PfDetectDestination(Node
&n
)
51 return PfDetectDestination(n
.GetLastTile(), n
.GetLastTrackdir());
54 /** Called by YAPF to detect if node ends in the desired destination */
55 inline bool PfDetectDestination(TileIndex tile
, Trackdir td
)
57 bool bDest
= IsRailDepotTile(tile
);
62 * Called by YAPF to calculate cost estimate. Calculates distance to the destination
63 * adds it to the actual cost from origin and stores the sum to the Node::m_estimate
65 inline bool PfCalcEstimate(Node
&n
)
67 n
.m_estimate
= n
.m_cost
;
72 template <class Types
>
73 class CYapfDestinationAnySafeTileRailT
: public CYapfDestinationRailBase
{
75 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
76 typedef typename
Types::NodeList::Titem Node
; ///< this will be our node type
77 typedef typename
Node::Key Key
; ///< key to hash tables
78 typedef typename
Types::TrackFollower TrackFollower
; ///< TrackFollower. Need to typedef for gcc 2.95
80 /** to access inherited path finder */
83 return *static_cast<Tpf
*>(this);
86 /** Called by YAPF to detect if node ends in the desired destination */
87 inline bool PfDetectDestination(Node
&n
)
89 return PfDetectDestination(n
.GetLastTile(), n
.GetLastTrackdir());
92 /** Called by YAPF to detect if node ends in the desired destination */
93 inline bool PfDetectDestination(TileIndex tile
, Trackdir td
)
95 return IsSafeWaitingPosition(Yapf().GetVehicle(), tile
, td
, true, !TrackFollower::Allow90degTurns()) &&
96 IsWaitingPositionFree(Yapf().GetVehicle(), tile
, td
, !TrackFollower::Allow90degTurns());
100 * Called by YAPF to calculate cost estimate. Calculates distance to the destination
101 * adds it to the actual cost from origin and stores the sum to the Node::m_estimate.
103 inline bool PfCalcEstimate(Node
&n
)
105 n
.m_estimate
= n
.m_cost
;
110 template <class Types
>
111 class CYapfDestinationTileOrStationRailT
: public CYapfDestinationRailBase
{
113 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
114 typedef typename
Types::NodeList::Titem Node
; ///< this will be our node type
115 typedef typename
Node::Key Key
; ///< key to hash tables
118 TileIndex m_destTile
;
119 TrackdirBits m_destTrackdirs
;
120 StationID m_dest_station_id
;
122 /** to access inherited path finder */
125 return *static_cast<Tpf
*>(this);
129 void SetDestination(const Train
*v
)
131 switch (v
->current_order
.GetType()) {
132 case OT_GOTO_WAYPOINT
:
133 if (!Waypoint::Get(v
->current_order
.GetDestination())->IsSingleTile()) {
134 /* In case of 'complex' waypoints we need to do a look
135 * ahead. This look ahead messes a bit about, which
136 * means that it 'corrupts' the cache. To prevent this
137 * we disable caching when we're looking for a complex
139 Yapf().DisableCache(true);
143 case OT_GOTO_STATION
:
144 m_destTile
= CalcClosestStationTile(v
->current_order
.GetDestination(), v
->tile
, v
->current_order
.IsType(OT_GOTO_STATION
) ? STATION_RAIL
: STATION_WAYPOINT
);
145 m_dest_station_id
= v
->current_order
.GetDestination();
146 m_destTrackdirs
= INVALID_TRACKDIR_BIT
;
150 m_destTile
= v
->dest_tile
;
151 m_dest_station_id
= INVALID_STATION
;
152 m_destTrackdirs
= TrackStatusToTrackdirBits(GetTileTrackStatus(v
->dest_tile
, TRANSPORT_RAIL
, 0));
155 CYapfDestinationRailBase::SetDestination(v
);
158 /** Called by YAPF to detect if node ends in the desired destination */
159 inline bool PfDetectDestination(Node
&n
)
161 return PfDetectDestination(n
.GetLastTile(), n
.GetLastTrackdir());
164 /** Called by YAPF to detect if node ends in the desired destination */
165 inline bool PfDetectDestination(TileIndex tile
, Trackdir td
)
167 if (m_dest_station_id
!= INVALID_STATION
) {
168 return HasStationTileRail(tile
)
169 && (GetStationIndex(tile
) == m_dest_station_id
)
170 && (GetRailStationTrack(tile
) == TrackdirToTrack(td
));
173 return (tile
== m_destTile
) && HasTrackdir(m_destTrackdirs
, td
);
177 * Called by YAPF to calculate cost estimate. Calculates distance to the destination
178 * adds it to the actual cost from origin and stores the sum to the Node::m_estimate
180 inline bool PfCalcEstimate(Node
&n
)
182 static const int dg_dir_to_x_offs
[] = {-1, 0, 1, 0};
183 static const int dg_dir_to_y_offs
[] = {0, 1, 0, -1};
184 if (PfDetectDestination(n
)) {
185 n
.m_estimate
= n
.m_cost
;
189 TileIndex tile
= n
.GetLastTile();
190 DiagDirection exitdir
= TrackdirToExitdir(n
.GetLastTrackdir());
191 int x1
= 2 * TileX(tile
) + dg_dir_to_x_offs
[(int)exitdir
];
192 int y1
= 2 * TileY(tile
) + dg_dir_to_y_offs
[(int)exitdir
];
193 int x2
= 2 * TileX(m_destTile
);
194 int y2
= 2 * TileY(m_destTile
);
195 int dx
= abs(x1
- x2
);
196 int dy
= abs(y1
- y2
);
197 int dmin
= min(dx
, dy
);
198 int dxy
= abs(dx
- dy
);
199 int d
= dmin
* YAPF_TILE_CORNER_LENGTH
+ (dxy
- 1) * (YAPF_TILE_LENGTH
/ 2);
200 n
.m_estimate
= n
.m_cost
+ d
;
201 assert(n
.m_estimate
>= n
.m_parent
->m_estimate
);
206 #endif /* YAPF_DESTRAIL_HPP */