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 #include "../../train.h"
14 #include "../pathfinder_func.h"
15 #include "../pathfinder_type.h"
17 class CYapfDestinationRailBase
{
19 RailTypes compatible_railtypes
;
22 void SetDestination(const Train
*v
, bool override_rail_type
= false)
24 this->compatible_railtypes
= v
->compatible_railtypes
;
25 if (override_rail_type
) this->compatible_railtypes
|= GetRailTypeInfo(v
->railtype
)->compatible_railtypes
;
28 bool IsCompatibleRailType(RailType rt
)
30 return HasBit(this->compatible_railtypes
, rt
);
33 RailTypes
GetCompatibleRailTypes() const
35 return this->compatible_railtypes
;
39 template <class Types
>
40 class CYapfDestinationAnyDepotRailT
: public CYapfDestinationRailBase
{
42 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
43 typedef typename
Types::NodeList::Item Node
; ///< this will be our node type
44 typedef typename
Node::Key Key
; ///< key to hash tables
46 /** to access inherited path finder */
49 return *static_cast<Tpf
*>(this);
52 /** Called by YAPF to detect if node ends in the desired destination */
53 inline bool PfDetectDestination(Node
&n
)
55 return this->PfDetectDestination(n
.GetLastTile(), n
.GetLastTrackdir());
58 /** Called by YAPF to detect if node ends in the desired destination */
59 inline bool PfDetectDestination(TileIndex tile
, Trackdir
)
61 return IsRailDepotTile(tile
);
65 * Called by YAPF to calculate cost estimate. Calculates distance to the destination
66 * adds it to the actual cost from origin and stores the sum to the Node::estimate
68 inline bool PfCalcEstimate(Node
&n
)
75 template <class Types
>
76 class CYapfDestinationAnySafeTileRailT
: public CYapfDestinationRailBase
{
78 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
79 typedef typename
Types::NodeList::Item Node
; ///< this will be our node type
80 typedef typename
Node::Key Key
; ///< key to hash tables
81 typedef typename
Types::TrackFollower TrackFollower
; ///< TrackFollower. Need to typedef for gcc 2.95
83 /** to access inherited path finder */
86 return *static_cast<Tpf
*>(this);
89 /** Called by YAPF to detect if node ends in the desired destination */
90 inline bool PfDetectDestination(Node
&n
)
92 return this->PfDetectDestination(n
.GetLastTile(), n
.GetLastTrackdir());
95 /** Called by YAPF to detect if node ends in the desired destination */
96 inline bool PfDetectDestination(TileIndex tile
, Trackdir td
)
98 return IsSafeWaitingPosition(Yapf().GetVehicle(), tile
, td
, true, !TrackFollower::Allow90degTurns()) &&
99 IsWaitingPositionFree(Yapf().GetVehicle(), tile
, td
, !TrackFollower::Allow90degTurns());
103 * Called by YAPF to calculate cost estimate. Calculates distance to the destination
104 * adds it to the actual cost from origin and stores the sum to the Node::estimate.
106 inline bool PfCalcEstimate(Node
&n
)
113 template <class Types
>
114 class CYapfDestinationTileOrStationRailT
: public CYapfDestinationRailBase
{
116 typedef typename
Types::Tpf Tpf
; ///< the pathfinder class (derived from THIS class)
117 typedef typename
Types::NodeList::Item Node
; ///< this will be our node type
118 typedef typename
Node::Key Key
; ///< key to hash tables
122 TrackdirBits dest_trackdirs
;
123 StationID dest_station_id
;
126 /** to access inherited path finder */
129 return *static_cast<Tpf
*>(this);
133 void SetDestination(const Train
*v
)
135 this->any_depot
= false;
136 switch (v
->current_order
.GetType()) {
137 case OT_GOTO_WAYPOINT
:
138 if (!Waypoint::Get(v
->current_order
.GetDestination())->IsSingleTile()) {
139 /* In case of 'complex' waypoints we need to do a look
140 * ahead. This look ahead messes a bit about, which
141 * means that it 'corrupts' the cache. To prevent this
142 * we disable caching when we're looking for a complex
144 Yapf().DisableCache(true);
148 case OT_GOTO_STATION
:
149 this->dest_tile
= CalcClosestStationTile(v
->current_order
.GetDestination(), v
->tile
, v
->current_order
.IsType(OT_GOTO_STATION
) ? STATION_RAIL
: STATION_WAYPOINT
);
150 this->dest_station_id
= v
->current_order
.GetDestination();
151 this->dest_trackdirs
= INVALID_TRACKDIR_BIT
;
155 if (v
->current_order
.GetDepotActionType() & ODATFB_NEAREST_DEPOT
) {
156 this->any_depot
= true;
161 this->dest_tile
= v
->dest_tile
;
162 this->dest_station_id
= INVALID_STATION
;
163 this->dest_trackdirs
= TrackStatusToTrackdirBits(GetTileTrackStatus(v
->dest_tile
, TRANSPORT_RAIL
, 0));
166 this->CYapfDestinationRailBase::SetDestination(v
);
169 /** Called by YAPF to detect if node ends in the desired destination */
170 inline bool PfDetectDestination(Node
&n
)
172 return this->PfDetectDestination(n
.GetLastTile(), n
.GetLastTrackdir());
175 /** Called by YAPF to detect if node ends in the desired destination */
176 inline bool PfDetectDestination(TileIndex tile
, Trackdir td
)
178 if (this->dest_station_id
!= INVALID_STATION
) {
179 return HasStationTileRail(tile
)
180 && (GetStationIndex(tile
) == this->dest_station_id
)
181 && (GetRailStationTrack(tile
) == TrackdirToTrack(td
));
184 if (this->any_depot
) {
185 return IsRailDepotTile(tile
);
188 return (tile
== this->dest_tile
) && HasTrackdir(this->dest_trackdirs
, td
);
192 * Called by YAPF to calculate cost estimate. Calculates distance to the destination
193 * adds it to the actual cost from origin and stores the sum to the Node::estimate
195 inline bool PfCalcEstimate(Node
&n
)
197 static const int dg_dir_to_x_offs
[] = {-1, 0, 1, 0};
198 static const int dg_dir_to_y_offs
[] = {0, 1, 0, -1};
199 if (this->PfDetectDestination(n
)) {
204 TileIndex tile
= n
.GetLastTile();
205 DiagDirection exitdir
= TrackdirToExitdir(n
.GetLastTrackdir());
206 int x1
= 2 * TileX(tile
) + dg_dir_to_x_offs
[(int)exitdir
];
207 int y1
= 2 * TileY(tile
) + dg_dir_to_y_offs
[(int)exitdir
];
208 int x2
= 2 * TileX(this->dest_tile
);
209 int y2
= 2 * TileY(this->dest_tile
);
210 int dx
= abs(x1
- x2
);
211 int dy
= abs(y1
- y2
);
212 int dmin
= std::min(dx
, dy
);
213 int dxy
= abs(dx
- dy
);
214 int d
= dmin
* YAPF_TILE_CORNER_LENGTH
+ (dxy
- 1) * (YAPF_TILE_LENGTH
/ 2);
215 n
.estimate
= n
.cost
+ d
;
216 assert(n
.estimate
>= n
.parent
->estimate
);
221 #endif /* YAPF_DESTRAIL_HPP */