OpenTTD Source 20260621-master-g720d10536d
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
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;
23
24constexpr int SHIP_LOST_PATH_LENGTH = 8;
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 == INVALID_TILE ? TileIndex{} : v->dest_tile;
53 this->dest_trackdirs = GetTileTrackStatus(this->dest_tile, TRANSPORT_WATER, RoadTramType::Invalid).trackdirs;
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
80 {
81 if (this->has_intermediate_dest) {
82 /* GetWaterRegionInfo is much faster than GetWaterRegionPatchInfo so we try that first. */
83 if (GetWaterRegionInfo(tile) != this->intermediate_dest_region_patch) return false;
84 return GetWaterRegionPatchInfo(tile) == this->intermediate_dest_region_patch;
85 }
86
87 if (this->dest_station != StationID::Invalid()) return IsDockingTile(tile) && IsShipDestinationTile(tile, this->dest_station);
88
89 return tile == this->dest_tile && this->dest_trackdirs.Any(TrackdirToTrackdirBits(td));
90 }
91
93 inline bool PfCalcEstimate(Node &n)
94 {
95 const TileIndex destination_tile = this->has_intermediate_dest ? this->intermediate_dest_tile : this->dest_tile;
96
97 if (this->PfDetectDestination(n)) {
98 n.estimate = n.cost;
99 return true;
100 }
101
102 n.estimate = n.cost + OctileDistanceCost(n.GetTile(), n.GetTrackdir(), destination_tile);
103 assert(n.estimate >= n.parent->estimate);
104 return true;
105 }
106};
107
109template <class Types>
111public:
112 typedef typename Types::Tpf Tpf;
113 typedef typename Types::TrackFollower TrackFollower;
114 typedef typename Types::NodeList::Item Node;
115 typedef typename Node::Key Key;
116
117protected:
119 inline Tpf &Yapf()
120 {
121 return *static_cast<Tpf*>(this);
122 }
123
124 std::vector<WaterRegionDesc> water_region_corridor;
125
126public:
128 inline void PfFollowNode(Node &old_node)
129 {
130 TrackFollower follower{Yapf().GetVehicle()};
131 if (follower.Follow(old_node.key.tile, old_node.key.td)) {
132 if (this->water_region_corridor.empty()
133 || std::ranges::find(this->water_region_corridor, GetWaterRegionInfo(follower.new_tile)) != this->water_region_corridor.end()) {
134 Yapf().AddMultipleNodes(&old_node, follower);
135 }
136 }
137 }
138
143 inline void RestrictSearch(const std::vector<WaterRegionPatchDesc> &path)
144 {
145 this->water_region_corridor.clear();
146 for (const WaterRegionPatchDesc &path_entry : path) this->water_region_corridor.push_back(path_entry);
147 }
148
150 inline char TransportTypeChar() const
151 {
152 return 'w';
153 }
154
161 {
162 return trackdirs.GetNthSetBit(RandomRange(trackdirs.Count())).value_or(Trackdir::Invalid);
163 }
164
172 static std::pair<TileIndex, Trackdir> GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir)
173 {
174 TrackFollower follower{v};
175 if (follower.Follow(tile, dir)) {
176 TrackdirBits dirs = follower.new_td_bits;
177 /* Exclude 90 degree turns unless there are no non-90 turns. */
179 if (dirs.None()) dirs = follower.new_td_bits;
180 return { follower.new_tile, GetRandomTrackdir(dirs) };
181 }
182 return { follower.new_tile, Trackdir::Invalid };
183 }
184
192 static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length)
193 {
194 std::pair<TileIndex, Trackdir> tile_dir = { v->tile, v->GetVehicleTrackdir()};
195 for (int i = 0; i < path_length; ++i) {
196 tile_dir = GetRandomFollowUpTileTrackdir(v, tile_dir.first, tile_dir.second);
197 if (tile_dir.second == Trackdir::Invalid) break;
198 path_cache.push_back(tile_dir.second);
199 }
200
201 if (path_cache.empty()) return Trackdir::Invalid;
202
203 /* Reverse the path so we can take from the end. */
204 std::reverse(std::begin(path_cache), std::end(path_cache));
205
206 const Trackdir result = path_cache.back().trackdir;
207 path_cache.pop_back();
208 return result;
209 }
210
211 static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, TrackdirBits forward_dirs, TrackdirBits reverse_dirs,
212 bool &path_found, ShipPathCache &path_cache, Trackdir &best_origin_dir)
213 {
214 const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
215 if (high_level_path.empty()) {
216 path_found = false;
217 /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
218 return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
219 }
220
221 /* Try one time without restricting the search area, which generally results in better and more natural looking paths.
222 * However the pathfinder can hit the node limit in certain situations such as long aqueducts or maze-like terrain.
223 * If that happens we run the pathfinder again, but restricted only to the regions provided by the region pathfinder. */
224 for (int attempt = 0; attempt < 2; ++attempt) {
226
227 /* Set origin and destination nodes */
228 pf.SetOrigin(v->tile, forward_dirs | reverse_dirs);
229 pf.SetDestination(v);
230 const bool is_intermediate_destination = static_cast<int>(high_level_path.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1;
231 if (is_intermediate_destination) pf.SetIntermediateDestination(high_level_path.back());
232
233 /* Restrict the search area to prevent the low level pathfinder from expanding too many nodes. This can happen
234 * when the terrain is very "maze-like" or when the high level path "teleports" via a very long aqueduct. */
235 if (attempt > 0) pf.RestrictSearch(high_level_path);
236
237 /* Find best path. */
238 path_found = pf.FindPath(v);
239 Node *node = pf.GetBestNode();
240 if (attempt == 0 && !path_found) continue; // Try again with restricted search area.
241
242 /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
243 if (!path_found) return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
244
245 /* Return only the path within the current water region if an intermediate destination was returned. If not, cache the entire path
246 * to the final destination tile. The low-level pathfinder might actually prefer a different docking tile in a nearby region. Without
247 * caching the full path the ship can get stuck in a loop. */
248 const WaterRegionPatchDesc end_water_patch = GetWaterRegionPatchInfo(node->GetTile());
249 assert(GetWaterRegionPatchInfo(tile) == high_level_path.front());
250 const WaterRegionPatchDesc start_water_patch = high_level_path.front();
251 while (node->parent) {
252 const WaterRegionPatchDesc node_water_patch = GetWaterRegionPatchInfo(node->GetTile());
253
254 const bool node_water_patch_on_high_level_path = std::ranges::find(high_level_path, node_water_patch) != high_level_path.end();
255 const bool add_full_path = !is_intermediate_destination && node_water_patch != end_water_patch;
256
257 /* The cached path must always lead to a region patch that's on the high level path.
258 * This is what can happen when that's not the case https://github.com/OpenTTD/OpenTTD/issues/12176. */
259 if (add_full_path || !node_water_patch_on_high_level_path || node_water_patch == start_water_patch) {
260 path_cache.push_back(node->GetTrackdir());
261 } else {
262 path_cache.clear();
263 }
264 node = node->parent;
265 }
266 assert(node->GetTile() == v->tile);
267
268 /* Return Trackdir::Invalid to trigger a ship reversal if that is the best option. */
269 best_origin_dir = node->GetTrackdir();
270 if (!TrackdirToTrackdirBits(best_origin_dir).Any(forward_dirs)) {
271 path_cache.clear();
272 return Trackdir::Invalid;
273 }
274
275 /* A empty path means we are already at the destination. The pathfinder shouldn't have been called at all.
276 * Return a random reachable trackdir to hopefully nudge the ship out of this strange situation. */
277 if (path_cache.empty()) return CreateRandomPath(v, path_cache, 1);
278
279 /* Take out the last trackdir as the result. */
280 const Trackdir result = path_cache.back().trackdir;
281 path_cache.pop_back();
282
283 /* Clear path cache when in final water region patch. This is to allow ships to spread over different docking tiles dynamically. */
284 if (start_water_patch == end_water_patch) path_cache.clear();
285
286 return result;
287 }
288
289 NOT_REACHED();
290 }
291
299 static bool CheckShipReverse(const Ship *v, Trackdir *trackdir)
300 {
301 bool path_found = false;
302 ShipPathCache dummy_cache;
303 Trackdir best_origin_dir = Trackdir::Invalid;
304
305 if (trackdir == nullptr) {
306 /* The normal case, typically called when ships leave a dock. */
307 const Trackdir reverse_dir = ReverseTrackdir(v->GetVehicleTrackdir());
308 const TrackdirBits forward_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
309 const TrackdirBits reverse_dirs = TrackdirToTrackdirBits(reverse_dir);
310 (void)ChooseShipTrack(v, v->tile, forward_dirs, reverse_dirs, path_found, dummy_cache, best_origin_dir);
311 return path_found && best_origin_dir == reverse_dir;
312 } else {
313 /* This gets called when a ship suddenly can't move forward, e.g. due to terraforming. */
316 (void)ChooseShipTrack(v, v->tile, {}, reverse_dirs, path_found, dummy_cache, best_origin_dir);
317 *trackdir = path_found && best_origin_dir != Trackdir::Invalid ? best_origin_dir : GetRandomTrackdir(reverse_dirs);
318 return true;
319 }
320 }
321};
322
324template <class Types>
326public:
327 typedef typename Types::Tpf Tpf;
328 typedef typename Types::TrackFollower TrackFollower;
329 typedef typename Types::NodeList::Item Node;
330 typedef typename Node::Key Key;
331
334 {
335 return *static_cast<Tpf*>(this);
336 }
337
338public:
339 inline int CurveCost(Trackdir td1, Trackdir td2)
340 {
341 assert(IsValidTrackdir(td1));
342 assert(IsValidTrackdir(td2));
343
344 if (TrackdirCrossesTrackdirs(td1).Test(td2)) {
345 /* 90-deg curve penalty. */
346 return Yapf().PfGetSettings().ship_curve90_penalty;
347 } else if (td2 != NextTrackdir(td1)) {
348 /* 45-deg curve penalty. */
349 return Yapf().PfGetSettings().ship_curve45_penalty;
350 }
351 return 0;
352 }
353
360 inline static bool IsPreferredShipDirection(TileIndex tile, Trackdir td)
361 {
362 const bool odd_x = TileX(tile) & 1;
363 const bool odd_y = TileY(tile) & 1;
364 if (td == Trackdir::X_NE) return odd_y;
365 if (td == Trackdir::X_SW) return !odd_y;
366 if (td == Trackdir::Y_NW) return odd_x;
367 if (td == Trackdir::Y_SE) return !odd_x;
369 }
370
372 inline bool PfCalcCost(Node &n, const TrackFollower *follower)
373 {
374 /* Base tile cost depending on distance. */
376 /* Additional penalty for curves. */
377 c += this->CurveCost(n.parent->GetTrackdir(), n.GetTrackdir());
378
379 if (IsDockingTile(n.GetTile())) {
380 /* Check docking tile for occupancy. */
381 uint count = std::ranges::count_if(VehiclesOnTile(n.GetTile()), [](const Vehicle *v) {
382 /* Ignore other vehicles (aircraft) and ships inside depot. */
383 return v->type == VehicleType::Ship && !v->vehstatus.Test(VehState::Hidden);
384 });
385 c += count * 3 * YAPF_TILE_LENGTH;
386 }
387
388 /* Encourage separation between ships traveling in different directions. */
389 if (!IsPreferredShipDirection(n.GetTile(), n.GetTrackdir())) c += YAPF_TILE_LENGTH;
390
391 /* Skipped tile cost for aqueducts. */
392 c += YAPF_TILE_LENGTH * follower->tiles_skipped;
393
394 /* Ocean/canal speed penalty. */
395 const ShipVehicleInfo *svi = ShipVehInfo(Yapf().GetVehicle()->engine_type);
396 uint8_t speed_frac = (GetEffectiveWaterClass(n.GetTile()) == WaterClass::Sea) ? svi->ocean_speed_frac : svi->canal_speed_frac;
397 if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + follower->tiles_skipped) * speed_frac / (256 - speed_frac);
398
399 /* Lock penalty. */
400 if (IsTileType(n.GetTile(), TileType::Water) && IsLock(n.GetTile()) && GetLockPart(n.GetTile()) == LockPart::Middle) {
401 const uint canal_speed = svi->ApplyWaterClassSpeedFrac(svi->max_speed, false);
402 /* Cost is proportional to the vehicle's speed as the vehicle stops in the lock. */
403 c += (TILE_HEIGHT * YAPF_TILE_LENGTH * canal_speed) / 128;
404 }
405
406 /* Apply it. */
407 n.cost = n.parent->cost + c;
408 return true;
409 }
410};
411
416template <class Tpf_>
419 typedef Tpf_ Tpf;
420 typedef CFollowTrackWater TrackFollower;
421 typedef CShipNodeList NodeList;
422 typedef Ship VehicleType;
423
431};
432
433struct CYapfShip : CYapfT<CYapfShip_TypesT<CYapfShip>> {
434 explicit CYapfShip(int max_nodes) { this->max_search_nodes = max_nodes; }
435};
436
437Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
438{
439 Trackdir best_origin_dir = Trackdir::Invalid;
441 const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, {}, path_found, path_cache, best_origin_dir);
442 return (td_ret != Trackdir::Invalid) ? TrackdirToTrack(td_ret) : Track::Invalid;
443}
444
445bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
446{
447 return CYapfShip::CheckShipReverse(v, trackdir);
448}
uint Count() const
Count the number of set bits.
constexpr bool None() const
Test if none of the values are set.
constexpr Timpl & Reset()
Reset all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
std::optional< Tvalue_type > GetNthSetBit(uint n) const
Get the value of the Nth set bit.
CYapfBaseT - A-star type path finder base class.
Definition yapf_base.hpp:48
int max_search_nodes
maximum number of nodes we are allowed to visit before we give up
Cost Provider module of YAPF for ships.
Node::Key Key
key to hash tables.
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.
bool PfCalcCost(Node &n, const TrackFollower *follower)
Called by YAPF to calculate the cost from the origin to the given node.
Tpf & Yapf()
Access the 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:93
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()
Access the inherited path finder.
Definition yapf_ship.cpp:66
bool PfDetectDestinationTile(TileIndex tile, Trackdir td)
Called by YAPF to detect if node ends in the desired destination.
Definition yapf_ship.cpp:79
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()
Access the 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...
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, RoadTramType sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:429
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:419
@ Any
Use first found.
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.
@ Invalid
Invalid marker.
Definition road_type.h:41
A number of safeguards to prevent using unsafe methods.
Base for ships.
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
Definition ship_cmd.cpp:568
WaterClass GetEffectiveWaterClass(TileIndex tile)
Determine the effective WaterClass for a ship travelling on a tile.
Definition ship_cmd.cpp:53
static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
Runs the pathfinder to choose a track to continue along.
Definition ship_cmd.cpp:466
@ Dock
Ship port.
Definition of base types and functions in a cross-platform compatible way.
Config struct of YAPF for ships.
CYapfShip_TypesT< Tpf_ > Types
Shortcut for this struct type.
CYapfDestinationTileWaterT< Types > PfDestination
Destination/distance provider.
CYapfSegmentCostCacheNoneT< Types > PfCache
Segment cost cache provider.
CYapfOriginTileT< Types > PfOrigin
Origin provider.
Tpf_ Tpf
Pathfinder type.
CFollowTrackWater TrackFollower
Track follower helper class.
CYapfFollowShipT< Types > PfFollow
Node follower.
CYapfCostShipT< Types > PfCost
Cost provider.
CYapfBaseT< Types > PfBase
Pathfinder components (modules).
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:100
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:67
Information about a ship vehicle.
Definition engine_type.h:99
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
uint ApplyWaterClassSpeedFrac(uint raw_speed, bool is_ocean) const
Apply ocean/canal speed fraction to a velocity.
uint16_t max_speed
Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h).
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
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
TrackdirBits trackdirs
Trackdirs present on the tile.
Definition track_type.h:106
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.
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > > TileIndex
The index/ID of a Tile.
Definition tile_type.h:92
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:100
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
@ Water
Water tile.
Definition tile_type.h:55
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition track_func.h:235
DiagDirection VehicleExitDir(Direction direction, TrackBits track)
Determine the side in which the vehicle will leave the tile.
Definition track_func.h:609
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:307
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:220
bool IsValidTrackdir(Trackdir trackdir)
Checks if a Trackdir is valid for non-road vehicles.
Definition track_func.h:48
TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
Maps a trackdir to all trackdirs that make 90 deg turns with it.
Definition track_func.h:501
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:450
bool IsDiagonalTrackdir(Trackdir trackdir)
Checks if a given Trackdir is diagonal.
Definition track_func.h:526
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
Definition track_func.h:86
EnumBitSet< Trackdir, uint16_t > TrackdirBits
Bitset of Trackdir elements.
Definition track_type.h:93
static constexpr TrackdirBits INVALID_TRACKDIR_BIT
Marker for an invalid TrackdirBits value.
Definition track_type.h:102
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:63
@ Right_N
Right track and direction to north.
Definition track_type.h:77
@ X_NE
X-axis and direction to north-east.
Definition track_type.h:64
@ Left_S
Left track and direction to south.
Definition track_type.h:68
@ Lower_E
Lower track and direction to east.
Definition track_type.h:67
@ X_SW
X-axis and direction to south-west.
Definition track_type.h:72
@ Invalid
Flag for an invalid trackdir.
Definition track_type.h:82
@ Y_SE
Y-axis and direction to south-east.
Definition track_type.h:65
@ Y_NW
Y-axis and direction to north-west.
Definition track_type.h:73
@ Upper_W
Upper track and direction to west.
Definition track_type.h:74
Track
These are used to specify a single track.
Definition track_type.h:19
@ Invalid
Flag for an invalid track.
Definition track_type.h:32
@ TRANSPORT_WATER
Transport over water.
Functions related to vehicles.
@ 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:375
@ Middle
Middle part of a lock.
Definition water_map.h:66
bool IsLock(Tile t)
Is there a lock on a given water tile?
Definition water_map.h:305
LockPart GetLockPart(Tile t)
Get the part of a lock.
Definition water_map.h:328
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.
Handles dividing the water in the map into regions to assist pathfinding.
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.
constexpr int MAX_SHIP_PF_NODES
4 possible exit dirs per tile.
Definition yapf_ship.cpp:22
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
Returns true if it is better to reverse the ship before leaving depot using YAPF.
constexpr int SHIP_LOST_PATH_LENGTH
The length of the (aimless) path assigned when a ship is lost.
Definition yapf_ship.cpp:24
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
Finds the best path for given ship using YAPF.
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.