Codechange: Update minimum CMake version to 3.16 for all parts. (#13141)
[openttd-github.git] / src / pathfinder / yapf / yapf_destrail.hpp
blob8e72b77176a52d089a1ca0147f2cf4a105b284ea
1 /*
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/>.
6 */
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 {
18 protected:
19 RailTypes compatible_railtypes;
21 public:
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 {
41 public:
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 */
47 Tpf &Yapf()
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);
64 /**
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)
70 n.estimate = n.cost;
71 return true;
75 template <class Types>
76 class CYapfDestinationAnySafeTileRailT : public CYapfDestinationRailBase {
77 public:
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 */
84 Tpf &Yapf()
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)
108 n.estimate = n.cost;
109 return true;
113 template <class Types>
114 class CYapfDestinationTileOrStationRailT : public CYapfDestinationRailBase {
115 public:
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
120 protected:
121 TileIndex dest_tile;
122 TrackdirBits dest_trackdirs;
123 StationID dest_station_id;
124 bool any_depot;
126 /** to access inherited path finder */
127 Tpf &Yapf()
129 return *static_cast<Tpf *>(this);
132 public:
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
143 * waypoint. */
144 Yapf().DisableCache(true);
146 [[fallthrough]];
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;
152 break;
154 case OT_GOTO_DEPOT:
155 if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
156 this->any_depot = true;
158 [[fallthrough]];
160 default:
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));
164 break;
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)) {
200 n.estimate = n.cost;
201 return true;
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);
217 return true;
221 #endif /* YAPF_DESTRAIL_HPP */