OpenTTD Source 20250911-master-gfe9093df96
yapf_ship.cpp
Go to the documentation of this file.
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 */
7
10#include "../../stdafx.h"
11#include "../../ship.h"
12#include "../../vehicle_func.h"
13
14#include "yapf.hpp"
15#include "yapf_node_ship.hpp"
16#include "yapf_ship_regions.h"
17#include "../water_regions.h"
18
19#include "../../safeguards.h"
20
21constexpr int NUMBER_OR_WATER_REGIONS_LOOKAHEAD = 4;
22constexpr int MAX_SHIP_PF_NODES = (NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1) * WATER_REGION_NUMBER_OF_TILES * 4; // 4 possible exit dirs per tile.
23
24constexpr int SHIP_LOST_PATH_LENGTH = 8; // The length of the (aimless) path assigned when a ship is lost.
25
26template <class Types>
28public:
29 typedef typename Types::Tpf Tpf;
30 typedef typename Types::TrackFollower TrackFollower;
31 typedef typename Types::NodeList::Item Node;
32 typedef typename Node::Key Key;
33
34protected:
35 TileIndex dest_tile;
36 TrackdirBits dest_trackdirs;
37 StationID dest_station;
38
39 bool has_intermediate_dest = false;
40 TileIndex intermediate_dest_tile;
41 WaterRegionPatchDesc intermediate_dest_region_patch;
42
43public:
44 void SetDestination(const Ship *v)
45 {
46 if (v->current_order.IsType(OT_GOTO_STATION)) {
47 this->dest_station = v->current_order.GetDestination().ToStationID();
48 this->dest_tile = CalcClosestStationTile(this->dest_station, v->tile, StationType::Dock);
49 this->dest_trackdirs = INVALID_TRACKDIR_BIT;
50 } else {
51 this->dest_station = StationID::Invalid();
52 this->dest_tile = v->dest_tile;
54 }
55 }
56
57 void SetIntermediateDestination(const WaterRegionPatchDesc &water_region_patch)
58 {
59 this->has_intermediate_dest = true;
60 this->intermediate_dest_tile = GetWaterRegionCenterTile(water_region_patch);
61 this->intermediate_dest_region_patch = water_region_patch;
62 }
63
64protected:
66 inline Tpf& Yapf()
67 {
68 return *static_cast<Tpf*>(this);
69 }
70
71public:
73 inline bool PfDetectDestination(Node &n)
74 {
75 return this->PfDetectDestinationTile(n.GetTile(), n.GetTrackdir());
76 }
77
78 inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
79 {
80 if (this->has_intermediate_dest) {
81 /* GetWaterRegionInfo is much faster than GetWaterRegionPatchInfo so we try that first. */
82 if (GetWaterRegionInfo(tile) != this->intermediate_dest_region_patch) return false;
83 return GetWaterRegionPatchInfo(tile) == this->intermediate_dest_region_patch;
84 }
85
86 if (this->dest_station != StationID::Invalid()) return IsDockingTile(tile) && IsShipDestinationTile(tile, this->dest_station);
87
88 return tile == this->dest_tile && ((this->dest_trackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
89 }
90
95 inline bool PfCalcEstimate(Node &n)
96 {
97 const TileIndex destination_tile = this->has_intermediate_dest ? this->intermediate_dest_tile : this->dest_tile;
98
99 if (this->PfDetectDestination(n)) {
100 n.estimate = n.cost;
101 return true;
102 }
103
104 n.estimate = n.cost + OctileDistanceCost(n.GetTile(), n.GetTrackdir(), destination_tile);
105 assert(n.estimate >= n.parent->estimate);
106 return true;
107 }
108};
109
111template <class Types>
113public:
114 typedef typename Types::Tpf Tpf;
115 typedef typename Types::TrackFollower TrackFollower;
116 typedef typename Types::NodeList::Item Node;
117 typedef typename Node::Key Key;
118
119protected:
121 inline Tpf &Yapf()
122 {
123 return *static_cast<Tpf*>(this);
124 }
125
126 std::vector<WaterRegionDesc> water_region_corridor;
127
128public:
134 inline void PfFollowNode(Node &old_node)
135 {
136 TrackFollower F(Yapf().GetVehicle());
137 if (F.Follow(old_node.key.tile, old_node.key.td)) {
138 if (this->water_region_corridor.empty()
139 || std::ranges::find(this->water_region_corridor, GetWaterRegionInfo(F.new_tile)) != this->water_region_corridor.end()) {
140 Yapf().AddMultipleNodes(&old_node, F);
141 }
142 }
143 }
144
146 inline void RestrictSearch(const std::vector<WaterRegionPatchDesc> &path)
147 {
148 this->water_region_corridor.clear();
149 for (const WaterRegionPatchDesc &path_entry : path) this->water_region_corridor.push_back(path_entry);
150 }
151
153 inline char TransportTypeChar() const
154 {
155 return 'w';
156 }
157
160 {
161 const int strip_amount = RandomRange(CountBits(trackdirs));
162 for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&trackdirs);
163 return FindFirstTrackdir(trackdirs);
164 }
165
167 static std::pair<TileIndex, Trackdir> GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir)
168 {
169 TrackFollower follower(v);
170 if (follower.Follow(tile, dir)) {
171 TrackdirBits dirs = follower.new_td_bits;
172 const TrackdirBits dirs_without_90_degree = dirs & ~TrackdirCrossesTrackdirs(dir);
173 if (dirs_without_90_degree != TRACKDIR_BIT_NONE) dirs = dirs_without_90_degree;
174 return { follower.new_tile, GetRandomTrackdir(dirs) };
175 }
176 return { follower.new_tile, INVALID_TRACKDIR };
177 }
178
180 static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length)
181 {
182 std::pair<TileIndex, Trackdir> tile_dir = { v->tile, v->GetVehicleTrackdir()};
183 for (int i = 0; i < path_length; ++i) {
184 tile_dir = GetRandomFollowUpTileTrackdir(v, tile_dir.first, tile_dir.second);
185 if (tile_dir.second == INVALID_TRACKDIR) break;
186 path_cache.push_back(tile_dir.second);
187 }
188
189 if (path_cache.empty()) return INVALID_TRACKDIR;
190
191 /* Reverse the path so we can take from the end. */
192 std::reverse(std::begin(path_cache), std::end(path_cache));
193
194 const Trackdir result = path_cache.back().trackdir;
195 path_cache.pop_back();
196 return result;
197 }
198
199 static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, TrackdirBits forward_dirs, TrackdirBits reverse_dirs,
200 bool &path_found, ShipPathCache &path_cache, Trackdir &best_origin_dir)
201 {
202 const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
203 if (high_level_path.empty()) {
204 path_found = false;
205 /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
206 return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
207 }
208
209 /* Try one time without restricting the search area, which generally results in better and more natural looking paths.
210 * However the pathfinder can hit the node limit in certain situations such as long aqueducts or maze-like terrain.
211 * If that happens we run the pathfinder again, but restricted only to the regions provided by the region pathfinder. */
212 for (int attempt = 0; attempt < 2; ++attempt) {
213 Tpf pf(MAX_SHIP_PF_NODES);
214
215 /* Set origin and destination nodes */
216 pf.SetOrigin(v->tile, forward_dirs | reverse_dirs);
217 pf.SetDestination(v);
218 const bool is_intermediate_destination = static_cast<int>(high_level_path.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1;
219 if (is_intermediate_destination) pf.SetIntermediateDestination(high_level_path.back());
220
221 /* Restrict the search area to prevent the low level pathfinder from expanding too many nodes. This can happen
222 * when the terrain is very "maze-like" or when the high level path "teleports" via a very long aqueduct. */
223 if (attempt > 0) pf.RestrictSearch(high_level_path);
224
225 /* Find best path. */
226 path_found = pf.FindPath(v);
227 Node *node = pf.GetBestNode();
228 if (attempt == 0 && !path_found) continue; // Try again with restricted search area.
229
230 /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
231 if (!path_found) return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
232
233 /* Return only the path within the current water region if an intermediate destination was returned. If not, cache the entire path
234 * to the final destination tile. The low-level pathfinder might actually prefer a different docking tile in a nearby region. Without
235 * caching the full path the ship can get stuck in a loop. */
236 const WaterRegionPatchDesc end_water_patch = GetWaterRegionPatchInfo(node->GetTile());
237 assert(GetWaterRegionPatchInfo(tile) == high_level_path.front());
238 const WaterRegionPatchDesc start_water_patch = high_level_path.front();
239 while (node->parent) {
240 const WaterRegionPatchDesc node_water_patch = GetWaterRegionPatchInfo(node->GetTile());
241
242 const bool node_water_patch_on_high_level_path = std::ranges::find(high_level_path, node_water_patch) != high_level_path.end();
243 const bool add_full_path = !is_intermediate_destination && node_water_patch != end_water_patch;
244
245 /* The cached path must always lead to a region patch that's on the high level path.
246 * This is what can happen when that's not the case https://github.com/OpenTTD/OpenTTD/issues/12176. */
247 if (add_full_path || !node_water_patch_on_high_level_path || node_water_patch == start_water_patch) {
248 path_cache.push_back(node->GetTrackdir());
249 } else {
250 path_cache.clear();
251 }
252 node = node->parent;
253 }
254 assert(node->GetTile() == v->tile);
255
256 /* Return INVALID_TRACKDIR to trigger a ship reversal if that is the best option. */
257 best_origin_dir = node->GetTrackdir();
258 if ((TrackdirToTrackdirBits(best_origin_dir) & forward_dirs) == TRACKDIR_BIT_NONE) {
259 path_cache.clear();
260 return INVALID_TRACKDIR;
261 }
262
263 /* A empty path means we are already at the destination. The pathfinder shouldn't have been called at all.
264 * Return a random reachable trackdir to hopefully nudge the ship out of this strange situation. */
265 if (path_cache.empty()) return CreateRandomPath(v, path_cache, 1);
266
267 /* Take out the last trackdir as the result. */
268 const Trackdir result = path_cache.back().trackdir;
269 path_cache.pop_back();
270
271 /* Clear path cache when in final water region patch. This is to allow ships to spread over different docking tiles dynamically. */
272 if (start_water_patch == end_water_patch) path_cache.clear();
273
274 return result;
275 }
276
277 NOT_REACHED();
278 }
279
287 static bool CheckShipReverse(const Ship *v, Trackdir *trackdir)
288 {
289 bool path_found = false;
290 ShipPathCache dummy_cache;
291 Trackdir best_origin_dir = INVALID_TRACKDIR;
292
293 if (trackdir == nullptr) {
294 /* The normal case, typically called when ships leave a dock. */
295 const Trackdir reverse_dir = ReverseTrackdir(v->GetVehicleTrackdir());
296 const TrackdirBits forward_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
297 const TrackdirBits reverse_dirs = TrackdirToTrackdirBits(reverse_dir);
298 (void)ChooseShipTrack(v, v->tile, forward_dirs, reverse_dirs, path_found, dummy_cache, best_origin_dir);
299 return path_found && best_origin_dir == reverse_dir;
300 } else {
301 /* This gets called when a ship suddenly can't move forward, e.g. due to terraforming. */
304 (void)ChooseShipTrack(v, v->tile, TRACKDIR_BIT_NONE, reverse_dirs, path_found, dummy_cache, best_origin_dir);
305 *trackdir = path_found && best_origin_dir != INVALID_TRACKDIR ? best_origin_dir : GetRandomTrackdir(reverse_dirs);
306 return true;
307 }
308 }
309};
310
312template <class Types>
314public:
315 typedef typename Types::Tpf Tpf;
316 typedef typename Types::TrackFollower TrackFollower;
317 typedef typename Types::NodeList::Item Node;
318 typedef typename Node::Key Key;
319
322 {
323 return *static_cast<Tpf*>(this);
324 }
325
326public:
327 inline int CurveCost(Trackdir td1, Trackdir td2)
328 {
329 assert(IsValidTrackdir(td1));
330 assert(IsValidTrackdir(td2));
331
332 if (HasTrackdir(TrackdirCrossesTrackdirs(td1), td2)) {
333 /* 90-deg curve penalty. */
334 return Yapf().PfGetSettings().ship_curve90_penalty;
335 } else if (td2 != NextTrackdir(td1)) {
336 /* 45-deg curve penalty. */
337 return Yapf().PfGetSettings().ship_curve45_penalty;
338 }
339 return 0;
340 }
341
348 inline static bool IsPreferredShipDirection(TileIndex tile, Trackdir td)
349 {
350 const bool odd_x = TileX(tile) & 1;
351 const bool odd_y = TileY(tile) & 1;
352 if (td == TRACKDIR_X_NE) return odd_y;
353 if (td == TRACKDIR_X_SW) return !odd_y;
354 if (td == TRACKDIR_Y_NW) return odd_x;
355 if (td == TRACKDIR_Y_SE) return !odd_x;
357 }
358
364 inline bool PfCalcCost(Node &n, const TrackFollower *tf)
365 {
366 /* Base tile cost depending on distance. */
368 /* Additional penalty for curves. */
369 c += this->CurveCost(n.parent->GetTrackdir(), n.GetTrackdir());
370
371 if (IsDockingTile(n.GetTile())) {
372 /* Check docking tile for occupancy. */
373 uint count = std::ranges::count_if(VehiclesOnTile(n.GetTile()), [](const Vehicle *v) {
374 /* Ignore other vehicles (aircraft) and ships inside depot. */
375 return v->type == VEH_SHIP && !v->vehstatus.Test(VehState::Hidden);
376 });
377 c += count * 3 * YAPF_TILE_LENGTH;
378 }
379
380 /* Encourage separation between ships traveling in different directions. */
381 if (!IsPreferredShipDirection(n.GetTile(), n.GetTrackdir())) c += YAPF_TILE_LENGTH;
382
383 /* Skipped tile cost for aqueducts. */
384 c += YAPF_TILE_LENGTH * tf->tiles_skipped;
385
386 /* Ocean/canal speed penalty. */
387 const ShipVehicleInfo *svi = ShipVehInfo(Yapf().GetVehicle()->engine_type);
388 uint8_t speed_frac = (GetEffectiveWaterClass(n.GetTile()) == WATER_CLASS_SEA) ? svi->ocean_speed_frac : svi->canal_speed_frac;
389 if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + tf->tiles_skipped) * speed_frac / (256 - speed_frac);
390
391 /* Apply it. */
392 n.cost = n.parent->cost + c;
393 return true;
394 }
395};
396
401template <class Tpf_, class Ttrack_follower, class Tnode_list>
417
418struct CYapfShip : CYapfT<CYapfShip_TypesT<CYapfShip, CFollowTrackWater, CShipNodeListExitDir>> {
419 explicit CYapfShip(int max_nodes) { this->max_search_nodes = max_nodes; }
420};
421
423Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
424{
425 Trackdir best_origin_dir = INVALID_TRACKDIR;
427 const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, TRACKDIR_BIT_NONE, path_found, path_cache, best_origin_dir);
428 return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
429}
430
431bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
432{
433 return CYapfShip::CheckShipReverse(v, trackdir);
434}
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr uint CountBits(T value)
Counts the number of set bits in a variable.
CYapfBaseT - A-star type path finder base class.
Definition yapf_base.hpp:49
Cost Provider module of YAPF for ships.
Node::Key Key
key to hash tables.
bool PfCalcCost(Node &n, const TrackFollower *tf)
Called by YAPF to calculate the cost from the origin to the given node.
static bool IsPreferredShipDirection(TileIndex tile, Trackdir td)
Whether the provided direction is a preferred direction for a given tile.
Types::NodeList::Item Node
this will be our node type.
Tpf & Yapf()
to access inherited path finder
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
Definition yapf_ship.cpp:29
bool PfCalcEstimate(Node &n)
Called by YAPF to calculate cost estimate.
Definition yapf_ship.cpp:95
Types::NodeList::Item Node
this will be our node type.
Definition yapf_ship.cpp:31
bool PfDetectDestination(Node &n)
Called by YAPF to detect if node ends in the desired destination.
Definition yapf_ship.cpp:73
Node::Key Key
key to hash tables.
Definition yapf_ship.cpp:32
Tpf & Yapf()
To access inherited path finder.
Definition yapf_ship.cpp:66
Node Follower module of YAPF for ships.
static std::pair< TileIndex, Trackdir > GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir)
Returns a random tile/trackdir that can be reached from the current tile/trackdir,...
char TransportTypeChar() const
Return debug report character to identify the transportation type.
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
static Trackdir GetRandomTrackdir(TrackdirBits trackdirs)
Returns a random trackdir out of a set of trackdirs.
Node::Key Key
key to hash tables.
static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length)
Creates a random path, avoids 90 degree turns.
Types::NodeList::Item Node
this will be our node type.
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
void RestrictSearch(const std::vector< WaterRegionPatchDesc > &path)
Restricts the search by creating corridor or water regions through which the ship is allowed to trave...
static bool CheckShipReverse(const Ship *v, Trackdir *trackdir)
Check whether a ship should reverse to reach its destination.
Tpf & Yapf()
to access inherited path finder
YAPF origin provider base class - used when origin is one tile / multiple trackdirs.
CYapfSegmentCostCacheNoneT - the formal only yapf cost cache provider that implements PfNodeCacheFetc...
YAPF template that uses Ttypes template argument to determine all YAPF components (base classes) from...
Hash table based node list multi-container class.
Definition nodelist.hpp:21
Iterate over all vehicles on a tile.
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection
Enumeration for diagonal directions.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:424
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:414
TileIndex CalcClosestStationTile(StationID station, TileIndex tile, StationType station_type)
Calculates the tile of given station that is closest to a given tile for this we assume the station i...
static const int YAPF_TILE_CORNER_LENGTH
Length (penalty) of a corner with YAPF.
static const int YAPF_TILE_LENGTH
Length (penalty) of one tile with YAPF.
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
Definition ship_cmd.cpp:634
WaterClass GetEffectiveWaterClass(TileIndex tile)
Determine the effective WaterClass for a ship travelling on a tile.
Definition ship_cmd.cpp:54
Config struct of YAPF for ships.
CYapfSegmentCostCacheNoneT< Types > PfCache
Segment cost cache provider.
CYapfShip_TypesT< Tpf_, Ttrack_follower, Tnode_list > Types
Shortcut for this struct type.
CYapfFollowShipT< Types > PfFollow
Node follower.
CYapfBaseT< Types > PfBase
Pathfinder components (modules).
CYapfOriginTileT< Types > PfOrigin
Origin provider.
Ttrack_follower TrackFollower
Track follower helper class.
CYapfDestinationTileWaterT< Types > PfDestination
Destination/distance provider.
Tpf_ Tpf
Pathfinder type.
CYapfCostShipT< Types > PfCost
Cost provider.
Node of the link graph.
Definition linkgraph.h:90
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:99
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:66
Information about a ship vehicle.
Definition engine_type.h:72
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
Definition engine_type.h:82
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
Definition engine_type.h:83
All ships have this type.
Definition ship.h:32
TrackBits state
The "track" the ship is following.
Definition ship.h:34
Trackdir GetVehicleTrackdir() const override
Returns the Trackdir on which the vehicle is currently located.
Definition ship_cmd.cpp:288
Vehicle data structure.
Direction direction
facing
Vehicle * first
NOSAVE: pointer to the first vehicle in the chain.
Order current_order
The current order (+ status, like: loading)
TileIndex tile
Current tile index.
TileIndex dest_tile
Heading for this tile.
Describes a single interconnected patch of water within a particular water region.
Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
Removes first Trackdir from TrackdirBits and returns it.
Definition track_func.h:156
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition track_func.h:262
DiagDirection VehicleExitDir(Direction direction, TrackBits track)
Determine the side in which the vehicle will leave the tile.
Definition track_func.h:714
TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition track_func.h:352
Trackdir NextTrackdir(Trackdir trackdir)
Maps a trackdir to the trackdir that you will end up on if you go straight ahead.
Definition track_func.h:403
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:247
bool IsValidTrackdir(Trackdir trackdir)
Checks if a Trackdir is valid for non-road vehicles.
Definition track_func.h:52
Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
Returns first Trackdir from TrackdirBits or INVALID_TRACKDIR.
Definition track_func.h:211
TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
Maps a trackdir to all trackdirs that make 90 deg turns with it.
Definition track_func.h:606
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:555
bool IsDiagonalTrackdir(Trackdir trackdir)
Checks if a given Trackdir is diagonal.
Definition track_func.h:631
bool HasTrackdir(TrackdirBits trackdirs, Trackdir trackdir)
Checks whether a TrackdirBits has a given Trackdir.
Definition track_func.h:340
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
Definition track_func.h:111
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:66
@ TRACKDIR_X_NE
X-axis and direction to north-east.
Definition track_type.h:68
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:85
@ TRACKDIR_Y_SE
Y-axis and direction to south-east.
Definition track_type.h:69
@ TRACKDIR_X_SW
X-axis and direction to south-west.
Definition track_type.h:76
@ TRACKDIR_Y_NW
Y-axis and direction to north-west.
Definition track_type.h:77
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:97
@ TRACKDIR_BIT_LEFT_S
Track left, direction south.
Definition track_type.h:103
@ TRACKDIR_BIT_LOWER_E
Track lower, direction east.
Definition track_type.h:102
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:98
@ TRACKDIR_BIT_RIGHT_N
Track right, direction north.
Definition track_type.h:111
@ TRACKDIR_BIT_UPPER_W
Track upper, direction west.
Definition track_type.h:108
@ INVALID_TRACKDIR_BIT
Flag for an invalid trackdirbit value.
Definition track_type.h:113
Track
These are used to specify a single track.
Definition track_type.h:19
@ INVALID_TRACK
Flag for an invalid track.
Definition track_type.h:28
@ TRANSPORT_WATER
Transport over water.
@ WATER_CLASS_SEA
Sea.
Definition water_map.h:40
bool IsDockingTile(Tile t)
Checks whether the tile is marked as a dockling tile.
Definition water_map.h:373
WaterRegionDesc GetWaterRegionInfo(TileIndex tile)
Returns basic water region information for the provided tile.
WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
Returns basic water region patch information for the provided tile.
TileIndex GetWaterRegionCenterTile(const WaterRegionDesc &water_region)
Returns the center tile of a particular water region.
Base includes/functions for YAPF.
int OctileDistanceCost(TileIndex start_tile, Trackdir start_td, TileIndex destination_tile)
Calculates the octile distance cost between a starting tile / trackdir and a destination tile.
Node tailored for ship pathfinding.
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
Returns true if it is better to reverse the ship before leaving depot using YAPF.
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
Ship controller helper - path finder invoker.
std::vector< WaterRegionPatchDesc > YapfShipFindWaterRegionPath(const Ship *v, TileIndex start_tile, int max_returned_path_length)
Finds a path at the water region level.
Implementation of YAPF for water regions, which are used for finding intermediate ship destinations.