OpenTTD Source  20241108-master-g80f628063a
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 "../../industry.h"
13 #include "../../vehicle_func.h"
14 
15 #include "yapf.hpp"
16 #include "yapf_node_ship.hpp"
17 #include "yapf_ship_regions.h"
18 #include "../water_regions.h"
19 
20 #include "../../safeguards.h"
21 
22 constexpr int NUMBER_OR_WATER_REGIONS_LOOKAHEAD = 4;
23 constexpr int MAX_SHIP_PF_NODES = (NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1) * WATER_REGION_NUMBER_OF_TILES * 4; // 4 possible exit dirs per tile.
24 
25 constexpr int SHIP_LOST_PATH_LENGTH = 8; // The length of the (aimless) path assigned when a ship is lost.
26 
27 template <class Types>
29 {
30 public:
31  typedef typename Types::Tpf Tpf;
32  typedef typename Types::TrackFollower TrackFollower;
33  typedef typename Types::NodeList::Titem Node;
34  typedef typename Node::Key Key;
35 
36 protected:
37  TileIndex dest_tile;
38  TrackdirBits dest_trackdirs;
39  StationID dest_station;
40 
41  bool has_intermediate_dest = false;
42  TileIndex intermediate_dest_tile;
43  WaterRegionPatchDesc intermediate_dest_region_patch;
44 
45 public:
46  void SetDestination(const Ship *v)
47  {
48  if (v->current_order.IsType(OT_GOTO_STATION)) {
49  this->dest_station = v->current_order.GetDestination();
50  this->dest_tile = CalcClosestStationTile(this->dest_station, v->tile, STATION_DOCK);
51  this->dest_trackdirs = INVALID_TRACKDIR_BIT;
52  } else {
53  this->dest_station = INVALID_STATION;
54  this->dest_tile = v->dest_tile;
56  }
57  }
58 
59  void SetIntermediateDestination(const WaterRegionPatchDesc &water_region_patch)
60  {
61  this->has_intermediate_dest = true;
62  this->intermediate_dest_tile = GetWaterRegionCenterTile(water_region_patch);
63  this->intermediate_dest_region_patch = water_region_patch;
64  }
65 
66 protected:
68  inline Tpf& Yapf()
69  {
70  return *static_cast<Tpf*>(this);
71  }
72 
73 public:
75  inline bool PfDetectDestination(Node &n)
76  {
77  return this->PfDetectDestinationTile(n.segment_last_tile, n.segment_last_td);
78  }
79 
80  inline bool PfDetectDestinationTile(TileIndex tile, Trackdir trackdir)
81  {
82  if (this->has_intermediate_dest) {
83  /* GetWaterRegionInfo is much faster than GetWaterRegionPatchInfo so we try that first. */
84  if (GetWaterRegionInfo(tile) != this->intermediate_dest_region_patch) return false;
85  return GetWaterRegionPatchInfo(tile) == this->intermediate_dest_region_patch;
86  }
87 
88  if (this->dest_station != INVALID_STATION) return IsDockingTile(tile) && IsShipDestinationTile(tile, this->dest_station);
89 
90  return tile == this->dest_tile && ((this->dest_trackdirs & TrackdirToTrackdirBits(trackdir)) != TRACKDIR_BIT_NONE);
91  }
92 
97  inline bool PfCalcEstimate(Node &n)
98  {
99  const TileIndex destination_tile = this->has_intermediate_dest ? this->intermediate_dest_tile : this->dest_tile;
100 
101  static const int dg_dir_to_x_offs[] = { -1, 0, 1, 0 };
102  static const int dg_dir_to_y_offs[] = { 0, 1, 0, -1 };
103  if (this->PfDetectDestination(n)) {
104  n.estimate = n.cost;
105  return true;
106  }
107 
108  TileIndex tile = n.segment_last_tile;
109  DiagDirection exitdir = TrackdirToExitdir(n.segment_last_td);
110  int x1 = 2 * TileX(tile) + dg_dir_to_x_offs[(int)exitdir];
111  int y1 = 2 * TileY(tile) + dg_dir_to_y_offs[(int)exitdir];
112  int x2 = 2 * TileX(destination_tile);
113  int y2 = 2 * TileY(destination_tile);
114  int dx = abs(x1 - x2);
115  int dy = abs(y1 - y2);
116  int dmin = std::min(dx, dy);
117  int dxy = abs(dx - dy);
118  int d = dmin * YAPF_TILE_CORNER_LENGTH + (dxy - 1) * (YAPF_TILE_LENGTH / 2);
119  n.estimate = n.cost + d;
120  assert(n.estimate >= n.parent->estimate);
121  return true;
122  }
123 };
124 
126 template <class Types>
128 {
129 public:
130  typedef typename Types::Tpf Tpf;
131  typedef typename Types::TrackFollower TrackFollower;
132  typedef typename Types::NodeList::Titem Node;
133  typedef typename Node::Key Key;
134 
135 protected:
137  inline Tpf &Yapf()
138  {
139  return *static_cast<Tpf*>(this);
140  }
141 
142  std::vector<WaterRegionDesc> water_region_corridor;
143 
144 public:
150  inline void PfFollowNode(Node &old_node)
151  {
152  TrackFollower F(Yapf().GetVehicle());
153  if (F.Follow(old_node.key.tile, old_node.key.td)) {
154  if (this->water_region_corridor.empty()
155  || std::find(this->water_region_corridor.begin(), this->water_region_corridor.end(),
156  GetWaterRegionInfo(F.new_tile)) != this->water_region_corridor.end()) {
157  Yapf().AddMultipleNodes(&old_node, F);
158  }
159  }
160  }
161 
163  inline void RestrictSearch(const std::vector<WaterRegionPatchDesc> &path)
164  {
165  this->water_region_corridor.clear();
166  for (const WaterRegionPatchDesc &path_entry : path) this->water_region_corridor.push_back(path_entry);
167  }
168 
170  inline char TransportTypeChar() const
171  {
172  return 'w';
173  }
174 
177  {
178  const int strip_amount = RandomRange(CountBits(trackdirs));
179  for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&trackdirs);
180  return FindFirstTrackdir(trackdirs);
181  }
182 
184  static std::pair<TileIndex, Trackdir> GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir)
185  {
186  TrackFollower follower(v);
187  if (follower.Follow(tile, dir)) {
188  TrackdirBits dirs = follower.new_td_bits;
189  const TrackdirBits dirs_without_90_degree = dirs & ~TrackdirCrossesTrackdirs(dir);
190  if (dirs_without_90_degree != TRACKDIR_BIT_NONE) dirs = dirs_without_90_degree;
191  return { follower.new_tile, GetRandomTrackdir(dirs) };
192  }
193  return { follower.new_tile, INVALID_TRACKDIR };
194  }
195 
197  static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length)
198  {
199  std::pair<TileIndex, Trackdir> tile_dir = { v->tile, v->GetVehicleTrackdir()};
200  for (int i = 0; i < path_length; ++i) {
201  tile_dir = GetRandomFollowUpTileTrackdir(v, tile_dir.first, tile_dir.second);
202  if (tile_dir.second == INVALID_TRACKDIR) break;
203  path_cache.push_back(tile_dir.second);
204  }
205 
206  if (path_cache.empty()) return INVALID_TRACKDIR;
207 
208  const Trackdir result = path_cache.front();
209  path_cache.pop_front();
210  return result;
211  }
212 
213  static Trackdir ChooseShipTrack(const Ship *v, TileIndex tile, TrackdirBits forward_dirs, TrackdirBits reverse_dirs,
214  bool &path_found, ShipPathCache &path_cache, Trackdir &best_origin_dir)
215  {
216  const std::vector<WaterRegionPatchDesc> high_level_path = YapfShipFindWaterRegionPath(v, tile, NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1);
217  if (high_level_path.empty()) {
218  path_found = false;
219  /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
220  return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
221  }
222 
223  /* Try one time without restricting the search area, which generally results in better and more natural looking paths.
224  * However the pathfinder can hit the node limit in certain situations such as long aqueducts or maze-like terrain.
225  * If that happens we run the pathfinder again, but restricted only to the regions provided by the region pathfinder. */
226  for (int attempt = 0; attempt < 2; ++attempt) {
227  Tpf pf(MAX_SHIP_PF_NODES);
228 
229  /* Set origin and destination nodes */
230  pf.SetOrigin(v->tile, forward_dirs | reverse_dirs);
231  pf.SetDestination(v);
232  const bool is_intermediate_destination = static_cast<int>(high_level_path.size()) >= NUMBER_OR_WATER_REGIONS_LOOKAHEAD + 1;
233  if (is_intermediate_destination) pf.SetIntermediateDestination(high_level_path.back());
234 
235  /* Restrict the search area to prevent the low level pathfinder from expanding too many nodes. This can happen
236  * when the terrain is very "maze-like" or when the high level path "teleports" via a very long aqueduct. */
237  if (attempt > 0) pf.RestrictSearch(high_level_path);
238 
239  /* Find best path. */
240  path_found = pf.FindPath(v);
241  Node *node = pf.GetBestNode();
242  if (attempt == 0 && !path_found) continue; // Try again with restricted search area.
243 
244  /* Make the ship move around aimlessly. This prevents repeated pathfinder calls and clearly indicates that the ship is lost. */
245  if (!path_found) return CreateRandomPath(v, path_cache, SHIP_LOST_PATH_LENGTH);
246 
247  /* Return only the path within the current water region if an intermediate destination was returned. If not, cache the entire path
248  * to the final destination tile. The low-level pathfinder might actually prefer a different docking tile in a nearby region. Without
249  * caching the full path the ship can get stuck in a loop. */
250  const WaterRegionPatchDesc end_water_patch = GetWaterRegionPatchInfo(node->GetTile());
251  assert(GetWaterRegionPatchInfo(tile) == high_level_path.front());
252  const WaterRegionPatchDesc start_water_patch = high_level_path.front();
253  while (node->parent) {
254  const WaterRegionPatchDesc node_water_patch = GetWaterRegionPatchInfo(node->GetTile());
255 
256  const bool node_water_patch_on_high_level_path = std::find(high_level_path.begin(), high_level_path.end(), node_water_patch) != high_level_path.end();
257  const bool add_full_path = !is_intermediate_destination && node_water_patch != end_water_patch;
258 
259  /* The cached path must always lead to a region patch that's on the high level path.
260  * This is what can happen when that's not the case https://github.com/OpenTTD/OpenTTD/issues/12176. */
261  if (add_full_path || !node_water_patch_on_high_level_path || node_water_patch == start_water_patch) {
262  path_cache.push_front(node->GetTrackdir());
263  } else {
264  path_cache.clear();
265  }
266  node = node->parent;
267  }
268  assert(node->GetTile() == v->tile);
269 
270  /* Return INVALID_TRACKDIR to trigger a ship reversal if that is the best option. */
271  best_origin_dir = node->GetTrackdir();
272  if ((TrackdirToTrackdirBits(best_origin_dir) & forward_dirs) == TRACKDIR_BIT_NONE) {
273  path_cache.clear();
274  return INVALID_TRACKDIR;
275  }
276 
277  /* A empty path means we are already at the destination. The pathfinder shouldn't have been called at all.
278  * Return a random reachable trackdir to hopefully nudge the ship out of this strange situation. */
279  if (path_cache.empty()) return CreateRandomPath(v, path_cache, 1);
280 
281  /* Take out the last trackdir as the result. */
282  const Trackdir result = path_cache.front();
283  path_cache.pop_front();
284 
285  /* Clear path cache when in final water region patch. This is to allow ships to spread over different docking tiles dynamically. */
286  if (start_water_patch == end_water_patch) path_cache.clear();
287 
288  return result;
289  }
290 
291  return INVALID_TRACKDIR;
292  }
293 
301  static bool CheckShipReverse(const Ship *v, Trackdir *trackdir)
302  {
303  bool path_found = false;
304  ShipPathCache dummy_cache;
305  Trackdir best_origin_dir = INVALID_TRACKDIR;
306 
307  if (trackdir == nullptr) {
308  /* The normal case, typically called when ships leave a dock. */
309  const Trackdir reverse_dir = ReverseTrackdir(v->GetVehicleTrackdir());
310  const TrackdirBits forward_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
311  const TrackdirBits reverse_dirs = TrackdirToTrackdirBits(reverse_dir);
312  (void)ChooseShipTrack(v, v->tile, forward_dirs, reverse_dirs, path_found, dummy_cache, best_origin_dir);
313  return path_found && best_origin_dir == reverse_dir;
314  } else {
315  /* This gets called when a ship suddenly can't move forward, e.g. due to terraforming. */
318  (void)ChooseShipTrack(v, v->tile, TRACKDIR_BIT_NONE, reverse_dirs, path_found, dummy_cache, best_origin_dir);
319  *trackdir = path_found && best_origin_dir != INVALID_TRACKDIR ? best_origin_dir : GetRandomTrackdir(reverse_dirs);
320  return true;
321  }
322  }
323 };
324 
326 template <class Types>
328 {
329 public:
330  typedef typename Types::Tpf Tpf;
331  typedef typename Types::TrackFollower TrackFollower;
332  typedef typename Types::NodeList::Titem Node;
333  typedef typename Node::Key Key;
334 
337  {
338  return *static_cast<Tpf*>(this);
339  }
340 
341 public:
342  inline int CurveCost(Trackdir td1, Trackdir td2)
343  {
344  assert(IsValidTrackdir(td1));
345  assert(IsValidTrackdir(td2));
346 
347  if (HasTrackdir(TrackdirCrossesTrackdirs(td1), td2)) {
348  /* 90-deg curve penalty. */
349  return Yapf().PfGetSettings().ship_curve90_penalty;
350  } else if (td2 != NextTrackdir(td1)) {
351  /* 45-deg curve penalty. */
352  return Yapf().PfGetSettings().ship_curve45_penalty;
353  }
354  return 0;
355  }
356 
357  static Vehicle *CountShipProc(Vehicle *v, void *data)
358  {
359  uint *count = (uint*)data;
360  /* Ignore other vehicles (aircraft) and ships inside depot. */
361  if (v->type == VEH_SHIP && (v->vehstatus & VS_HIDDEN) == 0) (*count)++;
362 
363  return nullptr;
364  }
365 
371  inline bool PfCalcCost(Node &n, const TrackFollower *tf)
372  {
373  /* Base tile cost depending on distance. */
374  int c = IsDiagonalTrackdir(n.GetTrackdir()) ? YAPF_TILE_LENGTH : YAPF_TILE_CORNER_LENGTH;
375  /* Additional penalty for curves. */
376  c += this->CurveCost(n.parent->GetTrackdir(), n.GetTrackdir());
377 
378  if (IsDockingTile(n.GetTile())) {
379  /* Check docking tile for occupancy. */
380  uint count = 0;
381  HasVehicleOnPos(n.GetTile(), &count, &CountShipProc);
382  c += count * 3 * YAPF_TILE_LENGTH;
383  }
384 
385  /* Skipped tile cost for aqueducts. */
386  c += YAPF_TILE_LENGTH * tf->tiles_skipped;
387 
388  /* Ocean/canal speed penalty. */
389  const ShipVehicleInfo *svi = ShipVehInfo(Yapf().GetVehicle()->engine_type);
390  uint8_t speed_frac = (GetEffectiveWaterClass(n.GetTile()) == WATER_CLASS_SEA) ? svi->ocean_speed_frac : svi->canal_speed_frac;
391  if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + tf->tiles_skipped) * speed_frac / (256 - speed_frac);
392 
393  /* Apply it. */
394  n.cost = n.parent->cost + c;
395  return true;
396  }
397 };
398 
403 template <class Tpf_, class Ttrack_follower, class Tnode_list>
405 {
407  typedef Tpf_ Tpf;
408  typedef Ttrack_follower TrackFollower;
409  typedef Tnode_list NodeList;
410  typedef Ship VehicleType;
411 
419 };
420 
421 struct CYapfShip : CYapfT<CYapfShip_TypesT<CYapfShip, CFollowTrackWater, CShipNodeListExitDir > >
422 {
423  explicit CYapfShip(int max_nodes) { this->max_search_nodes = max_nodes; }
424 };
425 
427 Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
428 {
429  Trackdir best_origin_dir = INVALID_TRACKDIR;
430  const TrackdirBits origin_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
431  const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, TRACKDIR_BIT_NONE, path_found, path_cache, best_origin_dir);
432  return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : INVALID_TRACK;
433 }
434 
435 bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
436 {
437  return CYapfShip::CheckShipReverse(v, trackdir);
438 }
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.
Definition: yapf_ship.cpp:328
Node::Key Key
key to hash tables.
Definition: yapf_ship.cpp:333
bool PfCalcCost(Node &n, const TrackFollower *tf)
Called by YAPF to calculate the cost from the origin to the given node.
Definition: yapf_ship.cpp:371
Types::NodeList::Titem Node
this will be our node type.
Definition: yapf_ship.cpp:332
Tpf & Yapf()
to access inherited path finder
Definition: yapf_ship.cpp:336
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
Definition: yapf_ship.cpp:330
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
Definition: yapf_ship.cpp:31
bool PfCalcEstimate(Node &n)
Called by YAPF to calculate cost estimate.
Definition: yapf_ship.cpp:97
Types::NodeList::Titem Node
this will be our node type.
Definition: yapf_ship.cpp:33
Tpf & Yapf()
To access inherited path finder.
Definition: yapf_ship.cpp:68
bool PfDetectDestination(Node &n)
Called by YAPF to detect if node ends in the desired destination.
Definition: yapf_ship.cpp:75
Node::Key Key
key to hash tables.
Definition: yapf_ship.cpp:34
Node Follower module of YAPF for ships.
Definition: yapf_ship.cpp:128
Types::NodeList::Titem Node
this will be our node type.
Definition: yapf_ship.cpp:132
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,...
Definition: yapf_ship.cpp:184
char TransportTypeChar() const
Return debug report character to identify the transportation type.
Definition: yapf_ship.cpp:170
void PfFollowNode(Node &old_node)
Called by YAPF to move from the given node to the next tile.
Definition: yapf_ship.cpp:150
static Trackdir GetRandomTrackdir(TrackdirBits trackdirs)
Returns a random trackdir out of a set of trackdirs.
Definition: yapf_ship.cpp:176
Node::Key Key
key to hash tables.
Definition: yapf_ship.cpp:133
static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length)
Creates a random path, avoids 90 degree turns.
Definition: yapf_ship.cpp:197
Tpf & Yapf()
to access inherited path finder
Definition: yapf_ship.cpp:137
Types::Tpf Tpf
the pathfinder class (derived from THIS class).
Definition: yapf_ship.cpp:130
void RestrictSearch(const std::vector< WaterRegionPatchDesc > &path)
Restricts the search by creating corridor or water regions through which the ship is allowed to trave...
Definition: yapf_ship.cpp:163
static bool CheckShipReverse(const Ship *v, Trackdir *trackdir)
Check whether a ship should reverse to reach its destination.
Definition: yapf_ship.cpp:301
YAPF origin provider base class - used when origin is one tile / multiple trackdirs.
Definition: yapf_common.hpp:23
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...
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.
Definition: landscape.cpp:554
static debug_inline uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:425
static debug_inline uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:415
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:23
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.
Definition: random_func.hpp:88
bool IsShipDestinationTile(TileIndex tile, StationID station)
Test if a tile is a docking tile for the given station.
Definition: ship_cmd.cpp:647
WaterClass GetEffectiveWaterClass(TileIndex tile)
Determine the effective WaterClass for a ship travelling on a tile.
Definition: ship_cmd.cpp:54
static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks)
Runs the pathfinder to choose a track to continue along.
Definition: ship_cmd.cpp:495
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
Config struct of YAPF for ships.
Definition: yapf_ship.cpp:405
CYapfSegmentCostCacheNoneT< Types > PfCache
Segment cost cache provider.
Definition: yapf_ship.cpp:417
CYapfShip_TypesT< Tpf_, Ttrack_follower, Tnode_list > Types
Shortcut for this struct type.
Definition: yapf_ship.cpp:406
CYapfFollowShipT< Types > PfFollow
Node follower.
Definition: yapf_ship.cpp:414
CYapfBaseT< Types > PfBase
Pathfinder components (modules).
Definition: yapf_ship.cpp:413
CYapfOriginTileT< Types > PfOrigin
Origin provider.
Definition: yapf_ship.cpp:415
Ttrack_follower TrackFollower
Track follower helper class.
Definition: yapf_ship.cpp:408
CYapfDestinationTileWaterT< Types > PfDestination
Destination/distance provider.
Definition: yapf_ship.cpp:416
Tpf_ Tpf
Pathfinder type.
Definition: yapf_ship.cpp:407
CYapfCostShipT< Types > PfCost
Cost provider.
Definition: yapf_ship.cpp:418
Node of the link graph.
Definition: linkgraph.h:90
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:103
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:70
Information about a ship vehicle.
Definition: engine_type.h:67
uint8_t ocean_speed_frac
Fraction of maximum speed for ocean tiles.
Definition: engine_type.h:77
uint8_t canal_speed_frac
Fraction of maximum speed for canal/river tiles.
Definition: engine_type.h:78
All ships have this type.
Definition: ship.h:24
TrackBits state
The "track" the ship is following.
Definition: ship.h:26
Trackdir GetVehicleTrackdir() const override
Returns the Trackdir on which the vehicle is currently located.
Definition: ship_cmd.cpp:288
Vehicle data structure.
Definition: vehicle_base.h:244
Direction direction
facing
Definition: vehicle_base.h:307
Vehicle * first
NOSAVE: pointer to the first vehicle in the chain.
Definition: vehicle_base.h:250
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:356
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
TileIndex dest_tile
Heading for this tile.
Definition: vehicle_base.h:271
Describes a single interconnected patch of water within a particular water region.
Definition: water_regions.h:27
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
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition: track_func.h:439
Trackdir
Enumeration for tracks and directions.
Definition: track_type.h:67
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition: track_type.h:86
TrackdirBits
Allow incrementing of Trackdir variables.
Definition: track_type.h:98
@ TRACKDIR_BIT_NONE
No track build.
Definition: track_type.h:99
@ INVALID_TRACKDIR_BIT
Flag for an invalid trackdirbit value.
Definition: track_type.h:114
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.
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:520
@ VS_HIDDEN
Vehicle is not visible.
Definition: vehicle_base.h:33
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ 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:371
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.
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.
Definition: yapf_ship.cpp:435
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
Ship controller helper - path finder invoker.
Definition: yapf_ship.cpp:427
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.