OpenTTD Source  20241108-master-g80f628063a
follow_track.hpp
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 #ifndef FOLLOW_TRACK_HPP
11 #define FOLLOW_TRACK_HPP
12 
13 #include "../pbs.h"
14 #include "../roadveh.h"
15 #include "../station_base.h"
16 #include "../train.h"
17 #include "../tunnelbridge.h"
18 #include "../tunnelbridge_map.h"
19 #include "../depot_map.h"
20 #include "pathfinder_func.h"
21 
27 template <TransportType Ttr_type_, typename VehicleType, bool T90deg_turns_allowed_ = true, bool Tmask_reserved_tracks = false>
29 {
30  enum ErrorCode {
31  EC_NONE,
32  EC_OWNER,
33  EC_RAIL_ROAD_TYPE,
34  EC_90DEG,
35  EC_NO_WAY,
36  EC_RESERVED,
37  };
38 
39  const VehicleType *veh;
46  bool is_tunnel;
47  bool is_bridge;
48  bool is_station;
50  ErrorCode err;
51  RailTypes railtypes;
52 
53  inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES)
54  {
55  Init(v, railtype_override);
56  }
57 
58  inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES)
59  {
60  assert(IsRailTT());
61  this->veh = nullptr;
62  Init(o, railtype_override);
63  }
64 
65  inline void Init(const VehicleType *v, RailTypes railtype_override)
66  {
67  assert(!IsRailTT() || (v != nullptr && v->type == VEH_TRAIN));
68  this->veh = v;
69  Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override);
70  }
71 
72  inline void Init(Owner o, RailTypes railtype_override)
73  {
74  assert(!IsRoadTT() || this->veh != nullptr);
75  assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES);
76  this->veh_owner = o;
77  /* don't worry, all is inlined so compiler should remove unnecessary initializations */
78  this->old_tile = INVALID_TILE;
79  this->old_td = INVALID_TRACKDIR;
80  this->new_tile = INVALID_TILE;
81  this->new_td_bits = TRACKDIR_BIT_NONE;
82  this->exitdir = INVALID_DIAGDIR;
83  this->is_station = false;
84  this->is_bridge = false;
85  this->is_tunnel = false;
86  this->tiles_skipped = 0;
87  this->err = EC_NONE;
88  this->railtypes = railtype_override;
89  }
90 
91  debug_inline static TransportType TT() { return Ttr_type_; }
92  debug_inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; }
93  debug_inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; }
94  inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(this->veh)->roadtype); }
95  debug_inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; }
96  inline static bool Allow90degTurns() { return T90deg_turns_allowed_; }
97  inline static bool DoTrackMasking() { return Tmask_reserved_tracks; }
98 
101  {
102  assert(this->IsTram()); // this function shouldn't be called in other cases
103 
104  if (IsNormalRoadTile(tile)) {
105  RoadBits rb = GetRoadBits(tile, RTT_TRAM);
106  switch (rb) {
107  case ROAD_NW: return DIAGDIR_NW;
108  case ROAD_SW: return DIAGDIR_SW;
109  case ROAD_SE: return DIAGDIR_SE;
110  case ROAD_NE: return DIAGDIR_NE;
111  default: break;
112  }
113  }
114  return INVALID_DIAGDIR;
115  }
116 
122  {
123  this->old_tile = old_tile;
124  this->old_td = old_td;
125  this->err = EC_NONE;
126 
127  assert([&]() {
128  if (this->IsTram() && this->GetSingleTramBit(this->old_tile) != INVALID_DIAGDIR) return true; // Skip the check for single tram bits
129  const uint sub_mode = (IsRoadTT() && this->veh != nullptr) ? (this->IsTram() ? RTT_TRAM : RTT_ROAD) : 0;
130  const TrackdirBits old_tile_valid_dirs = TrackStatusToTrackdirBits(GetTileTrackStatus(this->old_tile, TT(), sub_mode));
131  return (old_tile_valid_dirs & TrackdirToTrackdirBits(this->old_td)) != TRACKDIR_BIT_NONE;
132  }());
133 
134  this->exitdir = TrackdirToExitdir(this->old_td);
135  if (this->ForcedReverse()) return true;
136  if (!this->CanExitOldTile()) return false;
137  this->FollowTileExit();
138  if (!this->QueryNewTileTrackStatus()) return TryReverse();
139  this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
140  if (this->new_td_bits == TRACKDIR_BIT_NONE || !this->CanEnterNewTile()) {
141  /* In case we can't enter the next tile, but are
142  * a normal road vehicle, then we can actually
143  * try to reverse as this is the end of the road.
144  * Trams can only turn on the appropriate bits in
145  * which case reaching this would mean a dead end
146  * near a building and in that case there would
147  * a "false" QueryNewTileTrackStatus result and
148  * as such reversing is already tried. The fact
149  * that function failed can have to do with a
150  * missing road bit, or inability to connect the
151  * different bits due to slopes. */
152  if (IsRoadTT() && !this->IsTram() && this->TryReverse()) return true;
153 
154  /* CanEnterNewTile already set a reason.
155  * Do NOT overwrite it (important for example for EC_RAIL_ROAD_TYPE).
156  * Only set a reason if CanEnterNewTile was not called */
157  if (this->new_td_bits == TRACKDIR_BIT_NONE) this->err = EC_NO_WAY;
158 
159  return false;
160  }
161  if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(this->old_tile), GetTileRailType(this->new_tile), !Allow90degTurns()))) {
162  this->new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(this->old_td);
163  if (this->new_td_bits == TRACKDIR_BIT_NONE) {
164  this->err = EC_90DEG;
165  return false;
166  }
167  }
168  return true;
169  }
170 
171  inline bool MaskReservedTracks()
172  {
173  if (!DoTrackMasking()) return true;
174 
175  if (this->is_station) {
176  /* Check skipped station tiles as well. */
177  TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
178  for (TileIndex tile = this->new_tile - diff * this->tiles_skipped; tile != this->new_tile; tile += diff) {
179  if (HasStationReservation(tile)) {
180  this->new_td_bits = TRACKDIR_BIT_NONE;
181  this->err = EC_RESERVED;
182  return false;
183  }
184  }
185  }
186 
187  TrackBits reserved = GetReservedTrackbits(this->new_tile);
188  /* Mask already reserved trackdirs. */
189  this->new_td_bits &= ~TrackBitsToTrackdirBits(reserved);
190  /* Mask out all trackdirs that conflict with the reservation. */
191  for (Track t : SetTrackBitIterator(TrackdirBitsToTrackBits(this->new_td_bits))) {
192  if (TracksOverlap(reserved | TrackToTrackBits(t))) this->new_td_bits &= ~TrackToTrackdirBits(t);
193  }
194  if (this->new_td_bits == TRACKDIR_BIT_NONE) {
195  this->err = EC_RESERVED;
196  return false;
197  }
198  return true;
199  }
200 
201 protected:
203  inline void FollowTileExit()
204  {
205  this->is_station = false;
206  this->is_bridge = false;
207  this->is_tunnel = false;
208  this->tiles_skipped = 0;
209 
210  /* extra handling for tunnels and bridges in our direction */
211  if (IsTileType(this->old_tile, MP_TUNNELBRIDGE)) {
212  DiagDirection enterdir = GetTunnelBridgeDirection(this->old_tile);
213  if (enterdir == this->exitdir) {
214  /* we are entering the tunnel / bridge */
215  if (IsTunnel(this->old_tile)) {
216  this->is_tunnel = true;
217  this->new_tile = GetOtherTunnelEnd(this->old_tile);
218  } else { // IsBridge(old_tile)
219  this->is_bridge = true;
220  this->new_tile = GetOtherBridgeEnd(this->old_tile);
221  }
222  this->tiles_skipped = GetTunnelBridgeLength(this->new_tile, this->old_tile);
223  return;
224  }
225  assert(ReverseDiagDir(enterdir) == this->exitdir);
226  }
227 
228  /* normal or station tile, do one step */
229  this->new_tile = TileAddByDiagDir(this->old_tile, this->exitdir);
230 
231  /* special handling for stations */
232  if (IsRailTT() && HasStationTileRail(this->new_tile)) {
233  this->is_station = true;
234  } else if (IsRoadTT() && IsStationRoadStopTile(this->new_tile)) {
235  this->is_station = true;
236  }
237  }
238 
241  {
242  if (IsRailTT() && IsPlainRailTile(this->new_tile)) {
243  this->new_td_bits = (TrackdirBits)(GetTrackBits(this->new_tile) * 0x101);
244  } else if (IsRoadTT()) {
245  this->new_td_bits = GetTrackdirBitsForRoad(this->new_tile, this->IsTram() ? RTT_TRAM : RTT_ROAD);
246  } else {
247  this->new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(this->new_tile, TT(), 0));
248  }
249  return (this->new_td_bits != TRACKDIR_BIT_NONE);
250  }
251 
253  inline bool CanExitOldTile()
254  {
255  /* road stop can be left at one direction only unless it's a drive-through stop */
256  if (IsRoadTT() && IsBayRoadStopTile(this->old_tile)) {
257  DiagDirection exitdir = GetBayRoadStopDir(this->old_tile);
258  if (exitdir != this->exitdir) {
259  this->err = EC_NO_WAY;
260  return false;
261  }
262  }
263 
264  /* single tram bits can only be left in one direction */
265  if (this->IsTram()) {
266  DiagDirection single_tram = GetSingleTramBit(this->old_tile);
267  if (single_tram != INVALID_DIAGDIR && single_tram != this->exitdir) {
268  this->err = EC_NO_WAY;
269  return false;
270  }
271  }
272 
273  /* road depots can be also left in one direction only */
274  if (IsRoadTT() && IsDepotTypeTile(this->old_tile, TT())) {
275  DiagDirection exitdir = GetRoadDepotDirection(this->old_tile);
276  if (exitdir != this->exitdir) {
277  this->err = EC_NO_WAY;
278  return false;
279  }
280  }
281  return true;
282  }
283 
285  inline bool CanEnterNewTile()
286  {
287  if (IsRoadTT() && IsBayRoadStopTile(this->new_tile)) {
288  /* road stop can be entered from one direction only unless it's a drive-through stop */
289  DiagDirection exitdir = GetBayRoadStopDir(this->new_tile);
290  if (ReverseDiagDir(exitdir) != this->exitdir) {
291  this->err = EC_NO_WAY;
292  return false;
293  }
294  }
295 
296  /* single tram bits can only be entered from one direction */
297  if (this->IsTram()) {
298  DiagDirection single_tram = this->GetSingleTramBit(this->new_tile);
299  if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(this->exitdir)) {
300  this->err = EC_NO_WAY;
301  return false;
302  }
303  }
304 
305  /* road and rail depots can also be entered from one direction only */
306  if (IsRoadTT() && IsDepotTypeTile(this->new_tile, TT())) {
307  DiagDirection exitdir = GetRoadDepotDirection(this->new_tile);
308  if (ReverseDiagDir(exitdir) != this->exitdir) {
309  this->err = EC_NO_WAY;
310  return false;
311  }
312  /* don't try to enter other company's depots */
313  if (GetTileOwner(this->new_tile) != this->veh_owner) {
314  this->err = EC_OWNER;
315  return false;
316  }
317  }
318  if (IsRailTT() && IsDepotTypeTile(this->new_tile, TT())) {
319  DiagDirection exitdir = GetRailDepotDirection(this->new_tile);
320  if (ReverseDiagDir(exitdir) != this->exitdir) {
321  this->err = EC_NO_WAY;
322  return false;
323  }
324  }
325 
326  /* rail transport is possible only on tiles with the same owner as vehicle */
327  if (IsRailTT() && GetTileOwner(this->new_tile) != this->veh_owner) {
328  /* different owner */
329  this->err = EC_NO_WAY;
330  return false;
331  }
332 
333  /* rail transport is possible only on compatible rail types */
334  if (IsRailTT()) {
335  RailType rail_type = GetTileRailType(this->new_tile);
336  if (!HasBit(this->railtypes, rail_type)) {
337  /* incompatible rail type */
338  this->err = EC_RAIL_ROAD_TYPE;
339  return false;
340  }
341  }
342 
343  /* road transport is possible only on compatible road types */
344  if (IsRoadTT()) {
345  const RoadVehicle *v = RoadVehicle::From(this->veh);
346  RoadType roadtype = GetRoadType(this->new_tile, GetRoadTramType(v->roadtype));
347  if (!HasBit(v->compatible_roadtypes, roadtype)) {
348  /* incompatible road type */
349  this->err = EC_RAIL_ROAD_TYPE;
350  return false;
351  }
352  }
353 
354  /* tunnel holes and bridge ramps can be entered only from proper direction */
355  if (IsTileType(this->new_tile, MP_TUNNELBRIDGE)) {
356  if (IsTunnel(this->new_tile)) {
357  if (!this->is_tunnel) {
358  DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(this->new_tile);
359  if (tunnel_enterdir != this->exitdir) {
360  this->err = EC_NO_WAY;
361  return false;
362  }
363  }
364  } else { // IsBridge(new_tile)
365  if (!this->is_bridge) {
366  DiagDirection ramp_enderdir = GetTunnelBridgeDirection(this->new_tile);
367  if (ramp_enderdir != this->exitdir) {
368  this->err = EC_NO_WAY;
369  return false;
370  }
371  }
372  }
373  }
374 
375  /* special handling for rail stations - get to the end of platform */
376  if (IsRailTT() && this->is_station) {
377  /* entered railway station
378  * get platform length */
379  uint length = BaseStation::GetByTile(this->new_tile)->GetPlatformLength(this->new_tile, TrackdirToExitdir(this->old_td));
380  /* how big step we must do to get to the last platform tile? */
381  this->tiles_skipped = length - 1;
382  /* move to the platform end */
383  TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
384  diff *= this->tiles_skipped;
385  this->new_tile = TileAdd(this->new_tile, diff);
386  return true;
387  }
388 
389  return true;
390  }
391 
393  inline bool ForcedReverse()
394  {
395  /* rail and road depots cause reversing */
396  if (!IsWaterTT() && IsDepotTypeTile(this->old_tile, TT())) {
397  DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(this->old_tile) : GetRoadDepotDirection(this->old_tile);
398  if (exitdir != this->exitdir) {
399  /* reverse */
400  this->new_tile = this->old_tile;
401  this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
402  this->exitdir = exitdir;
403  this->tiles_skipped = 0;
404  this->is_tunnel = false;
405  this->is_bridge = false;
406  this->is_station = false;
407  return true;
408  }
409  }
410 
411  /* Single tram bits and standard road stops cause reversing. */
412  if (IsRoadTT() && ((this->IsTram() && GetSingleTramBit(this->old_tile) == ReverseDiagDir(this->exitdir)) ||
413  (IsBayRoadStopTile(this->old_tile) && GetBayRoadStopDir(this->old_tile) == ReverseDiagDir(this->exitdir)))) {
414  /* reverse */
415  this->new_tile = this->old_tile;
416  this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
417  this->exitdir = ReverseDiagDir(this->exitdir);
418  this->tiles_skipped = 0;
419  this->is_tunnel = false;
420  this->is_bridge = false;
421  this->is_station = false;
422  return true;
423  }
424 
425  return false;
426  }
427 
429  inline bool TryReverse()
430  {
431  if (IsRoadTT() && !this->IsTram()) {
432  /* if we reached the end of road, we can reverse the RV and continue moving */
433  this->exitdir = ReverseDiagDir(this->exitdir);
434  /* new tile will be the same as old one */
435  this->new_tile = this->old_tile;
436  /* set new trackdir bits to all reachable trackdirs */
438  this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
439  if (this->new_td_bits != TRACKDIR_BIT_NONE) {
440  /* we have some trackdirs reachable after reversal */
441  return true;
442  }
443  }
444  this->err = EC_NO_WAY;
445  return false;
446  }
447 
448 public:
450  int GetSpeedLimit(int *pmin_speed = nullptr) const
451  {
452  int min_speed = 0;
453  int max_speed = INT_MAX; // no limit
454 
455  /* Check for on-bridge speed limit */
456  if (!IsWaterTT() && IsBridgeTile(this->old_tile)) {
457  int spd = GetBridgeSpec(GetBridgeType(this->old_tile))->speed;
458  if (IsRoadTT()) spd *= 2;
459  max_speed = std::min(max_speed, spd);
460  }
461  /* Check for speed limit imposed by railtype */
462  if (IsRailTT()) {
463  uint16_t rail_speed = GetRailTypeInfo(GetRailType(this->old_tile))->max_speed;
464  if (rail_speed > 0) max_speed = std::min<int>(max_speed, rail_speed);
465  }
466  if (IsRoadTT()) {
467  /* max_speed is already in roadvehicle units, no need to further modify (divide by 2) */
468  uint16_t road_speed = GetRoadTypeInfo(GetRoadType(this->old_tile, GetRoadTramType(RoadVehicle::From(this->veh)->roadtype)))->max_speed;
469  if (road_speed > 0) max_speed = std::min<int>(max_speed, road_speed);
470  }
471 
472  /* if min speed was requested, return it */
473  if (pmin_speed != nullptr) *pmin_speed = min_speed;
474  return max_speed;
475  }
476 };
477 
481 
483 
486 
487 #endif /* FOLLOW_TRACK_HPP */
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition: bridge.h:66
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
Definition: bridge_map.cpp:59
bool IsBridgeTile(Tile t)
checks if there is a bridge on this tile
Definition: bridge_map.h:35
BridgeType GetBridgeType(Tile t)
Determines the type of bridge on a tile.
Definition: bridge_map.h:56
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition: rail.h:231
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition: road.h:142
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ INVALID_OWNER
An invalid owner.
Definition: company_type.h:29
bool IsDepotTypeTile(Tile tile, TransportType type)
Check if a tile is a depot and it is a depot of the given type.
Definition: depot_map.h:18
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
@ DIAGDIR_SW
Southwest.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:554
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition: map_func.h:608
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
Definition: map_func.h:454
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
int32_t TileIndexDiff
An offset value between two tiles.
Definition: map_type.h:23
General functions related to pathfinders.
TrackdirBits GetTrackdirBitsForRoad(TileIndex tile, RoadTramType rtt)
Wrapper around GetTileTrackStatus() and TrackStatusToTrackdirBits(), as for single tram bits GetTileT...
TrackBits GetReservedTrackbits(TileIndex t)
Get the reserved trackbits for any tile, regardless of type.
Definition: pbs.cpp:24
RailType GetTileRailType(Tile tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition: rail.cpp:155
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition: rail.h:307
bool Rail90DegTurnDisallowed(RailType rt1, RailType rt2, bool def=_settings_game.pf.forbid_90_deg)
Test if 90 degree turns are disallowed between two railtypes.
Definition: rail.h:357
RailType GetRailType(Tile t)
Gets the rail type of the given tile.
Definition: rail_map.h:115
TrackBits GetTrackBits(Tile tile)
Gets the track bits of the given tile.
Definition: rail_map.h:136
DiagDirection GetRailDepotDirection(Tile t)
Returns the direction the depot is facing to.
Definition: rail_map.h:171
static debug_inline bool IsPlainRailTile(Tile t)
Checks whether the tile is a rail tile or rail tile with signals.
Definition: rail_map.h:60
RailTypes
Allow incrementing of Track variables.
Definition: rail_type.h:44
@ INVALID_RAILTYPES
Invalid railtypes.
Definition: rail_type.h:50
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:27
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition: road.h:227
static debug_inline bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition: road_map.h:74
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition: road_map.h:128
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition: road_map.h:565
RoadBits
Enumeration for the road parts on a tile.
Definition: road_type.h:52
@ ROAD_SW
South-west part.
Definition: road_type.h:55
@ ROAD_NE
North-east part.
Definition: road_type.h:57
@ ROAD_SE
South-east part.
Definition: road_type.h:56
@ ROAD_NW
North-west part.
Definition: road_type.h:54
RoadType
The different roadtypes we support.
Definition: road_type.h:25
bool IsStationRoadStopTile(Tile t)
Is tile t a road stop station?
Definition: station_map.h:234
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
Definition: station_map.h:266
bool HasStationTileRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
Definition: station_map.h:146
bool HasStationReservation(Tile t)
Get the reservation state of the rail station.
Definition: station_map.h:559
DiagDirection GetBayRoadStopDir(Tile t)
Gets the direction the bay road stop entrance points towards.
Definition: station_map.h:344
virtual uint GetPlatformLength(TileIndex tile) const =0
Obtain the length of a platform.
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
uint16_t speed
maximum travel speed (1 unit = 1/1.6 mph = 1 km-ish/h)
Definition: bridge.h:47
Track follower helper template class (can serve pathfinders and vehicle controllers).
bool CanExitOldTile()
return true if we can leave old_tile in exitdir
bool Follow(TileIndex old_tile, Trackdir old_td)
main follower routine.
bool CanEnterNewTile()
return true if we can enter new_tile from exitdir
bool is_tunnel
last turn passed tunnel
bool QueryNewTileTrackStatus()
stores track status (available trackdirs) for the new tile into new_td_bits
bool TryReverse()
return true if we successfully reversed at end of road/track
bool is_bridge
last turn passed bridge ramp
int GetSpeedLimit(int *pmin_speed=nullptr) const
Helper for pathfinders - get min/max speed on the old_tile/old_td.
const VehicleType * veh
moving vehicle
bool ForcedReverse()
return true if we must reverse (in depots and single tram bits)
int tiles_skipped
number of skipped tunnel or station tiles
DiagDirection exitdir
exit direction (leaving the old tile)
TrackdirBits new_td_bits
the new set of available trackdirs
void FollowTileExit()
Follow the exitdir from old_tile and fill new_tile and tiles_skipped.
TileIndex new_tile
the new tile (the vehicle has entered)
Trackdir old_td
the trackdir (the vehicle was on) before move
bool is_station
last turn passed station
DiagDirection GetSingleTramBit(TileIndex tile)
Tests if a tile is a road tile with a single tramtrack (tram can reverse)
Owner veh_owner
owner of the vehicle
TileIndex old_tile
the origin (vehicle moved from) before move
Buses, trucks and trams belong to this class.
Definition: roadveh.h:106
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition: roadveh.h:118
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition: roadveh.h:116
Iterable ensemble of each set bit in a value.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition: tile_map.h:178
static debug_inline bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition: tile_map.h:150
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:95
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition: tile_type.h:57
TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition: track_func.h:77
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition: track_func.h:319
TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition: track_func.h:352
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition: track_func.h:247
bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition: track_func.h:645
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
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
TrackdirBits TrackToTrackdirBits(Track track)
Returns a TrackdirBit mask from a given Track.
Definition: track_func.h:294
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition: track_func.h:308
TrackBits
Allow incrementing of Track variables.
Definition: track_type.h:35
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
Track
These are used to specify a single track.
Definition: track_type.h:19
TransportType
Available types of transport.
@ TRANSPORT_RAIL
Transport by train.
@ TRANSPORT_ROAD
Transport by road vehicle.
@ TRANSPORT_WATER
Transport over water.
TileIndex GetOtherTunnelEnd(TileIndex tile)
Gets the other end of the tunnel.
Definition: tunnel_map.cpp:22
bool IsTunnel(Tile t)
Is this a tunnel (entrance)?
Definition: tunnel_map.h:23
uint GetTunnelBridgeLength(TileIndex begin, TileIndex end)
Calculates the length of a tunnel or a bridge (without end tiles)
Definition: tunnelbridge.h:25
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24