OpenTTD Source 20260621-master-g720d10536d
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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
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
27template <TransportType Ttr_type_, typename VehicleType, bool T90deg_turns_allowed_ = true, bool Tmask_reserved_tracks = false>
28struct CFollowTrackT {
30 enum class ErrorCode : uint8_t {
32 Owner,
37 };
38
40 Owner veh_owner;
46 bool is_tunnel;
47 bool is_bridge;
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 == ::VehicleType::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;
80 this->new_tile = INVALID_TILE;
81 this->new_td_bits.Reset();
83 this->is_station = false;
84 this->is_bridge = false;
85 this->is_tunnel = false;
86 this->tiles_skipped = 0;
87 this->err = ErrorCode::None;
88 this->railtypes = railtype_override;
89 }
90
91 [[debug_inline]] inline static TransportType TT() { return Ttr_type_; }
92 [[debug_inline]] inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; }
93 [[debug_inline]] inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; }
94 inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(this->veh)->roadtype); }
95 [[debug_inline]] inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; }
96 static inline bool Allow90degTurns() { return T90deg_turns_allowed_; }
97 static inline bool DoTrackMasking() { return Tmask_reserved_tracks; }
98
105 {
106 assert(this->IsTram()); // this function shouldn't be called in other cases
107
108 if (IsNormalRoadTile(tile)) {
110 switch (rb.base()) {
111 case RoadBits{RoadBit::NW}.base(): return DiagDirection::NW;
112 case RoadBits{RoadBit::SW}.base(): return DiagDirection::SW;
113 case RoadBits{RoadBit::SE}.base(): return DiagDirection::SE;
114 case RoadBits{RoadBit::NE}.base(): return DiagDirection::NE;
115 default: break;
116 }
117 }
119 }
120
129 {
130 this->old_tile = old_tile;
131 this->old_td = old_td;
132 this->err = ErrorCode::None;
133
134 assert([&]() {
135 if (this->IsTram() && this->GetSingleTramBit(this->old_tile) != DiagDirection::Invalid) return true; // Skip the check for single tram bits
136 const RoadTramType sub_mode = (IsRoadTT() && this->veh != nullptr) ? (this->IsTram() ? RoadTramType::Tram : RoadTramType::Road) : RoadTramType::Invalid;
137 const TrackdirBits old_tile_valid_dirs = GetTileTrackStatus(this->old_tile, TT(), sub_mode).trackdirs;
138 return old_tile_valid_dirs.Any(TrackdirToTrackdirBits(this->old_td));
139 }());
140
141 this->exitdir = TrackdirToExitdir(this->old_td);
142 if (this->ForcedReverse()) return true;
143 if (!this->CanExitOldTile()) return false;
144 this->FollowTileExit();
145 if (!this->QueryNewTileTrackStatus()) return TryReverse();
146 this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
147 if (this->new_td_bits.None() || !this->CanEnterNewTile()) {
148 /* In case we can't enter the next tile, but are
149 * a normal road vehicle, then we can actually
150 * try to reverse as this is the end of the road.
151 * Trams can only turn on the appropriate bits in
152 * which case reaching this would mean a dead end
153 * near a building and in that case there would
154 * a "false" QueryNewTileTrackStatus result and
155 * as such reversing is already tried. The fact
156 * that function failed can have to do with a
157 * missing road bit, or inability to connect the
158 * different bits due to slopes. */
159 if (IsRoadTT() && !this->IsTram() && this->TryReverse()) return true;
160
161 /* CanEnterNewTile already set a reason.
162 * Do NOT overwrite it (important for example for ErrorCode::RailRoadType).
163 * Only set a reason if CanEnterNewTile was not called */
164 if (this->new_td_bits.None()) this->err = ErrorCode::NoWay;
165
166 return false;
167 }
168 if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(this->old_tile), GetTileRailType(this->new_tile), !Allow90degTurns()))) {
169 this->new_td_bits.Reset(TrackdirCrossesTrackdirs(this->old_td));
170 if (this->new_td_bits.None()) {
171 this->err = ErrorCode::SharpTurn;
172 return false;
173 }
174 }
175 return true;
176 }
177
178 inline bool MaskReservedTracks()
179 {
180 if (!DoTrackMasking()) return true;
181
182 if (this->is_station) {
183 /* Check skipped station tiles as well. */
184 TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
185 for (TileIndex tile = this->new_tile - diff * this->tiles_skipped; tile != this->new_tile; tile += diff) {
186 if (HasStationReservation(tile)) {
187 this->new_td_bits.Reset();
188 this->err = ErrorCode::Reserved;
189 return false;
190 }
191 }
192 }
193
194 TrackBits reserved = GetReservedTrackbits(this->new_tile);
195 /* Mask already reserved trackdirs. */
196 this->new_td_bits.Reset(TrackBitsToTrackdirBits(reserved));
197 /* Mask out all trackdirs that conflict with the reservation. */
198 for (Track t : TrackdirBitsToTrackBits(this->new_td_bits)) {
199 if (TracksOverlap(reserved | t)) this->new_td_bits.Reset(TrackToTrackdirBits(t));
200 }
201 if (this->new_td_bits.None()) {
202 this->err = ErrorCode::Reserved;
203 return false;
204 }
205 return true;
206 }
207
208protected:
210 inline void FollowTileExit()
211 {
212 this->is_station = false;
213 this->is_bridge = false;
214 this->is_tunnel = false;
215 this->tiles_skipped = 0;
216
217 /* extra handling for tunnels and bridges in our direction */
218 if (IsTileType(this->old_tile, TileType::TunnelBridge)) {
219 DiagDirection enterdir = GetTunnelBridgeDirection(this->old_tile);
220 if (enterdir == this->exitdir) {
221 /* we are entering the tunnel / bridge */
222 if (IsTunnel(this->old_tile)) {
223 this->is_tunnel = true;
224 this->new_tile = GetOtherTunnelEnd(this->old_tile);
225 } else { // IsBridge(old_tile)
226 this->is_bridge = true;
227 this->new_tile = GetOtherBridgeEnd(this->old_tile);
228 }
229 this->tiles_skipped = GetTunnelBridgeLength(this->new_tile, this->old_tile);
230 return;
231 }
232 assert(ReverseDiagDir(enterdir) == this->exitdir);
233 }
234
235 /* normal or station tile, do one step */
236 this->new_tile = TileAddByDiagDir(this->old_tile, this->exitdir);
237
238 /* special handling for stations */
239 if (IsRailTT() && HasStationTileRail(this->new_tile)) {
240 this->is_station = true;
241 } else if (IsRoadTT() && IsStationRoadStopTile(this->new_tile)) {
242 this->is_station = true;
243 }
244 }
245
251 {
252 if (IsRailTT() && IsPlainRailTile(this->new_tile)) {
253 this->new_td_bits = TrackBitsToTrackdirBits(GetTrackBits(this->new_tile));
254 } else if (IsRoadTT()) {
255 this->new_td_bits = GetTrackdirBitsForRoad(this->new_tile, this->IsTram() ? RoadTramType::Tram : RoadTramType::Road);
256 } else {
257 this->new_td_bits = GetTileTrackStatus(this->new_tile, TT(), RoadTramType::Invalid).trackdirs;
258 }
259 return this->new_td_bits.Any();
260 }
261
266 inline bool CanExitOldTile()
267 {
268 /* road stop can be left at one direction only unless it's a drive-through stop */
269 if (IsRoadTT() && IsBayRoadStopTile(this->old_tile)) {
270 DiagDirection exitdir = GetBayRoadStopDir(this->old_tile);
271 if (exitdir != this->exitdir) {
272 this->err = ErrorCode::NoWay;
273 return false;
274 }
275 }
276
277 /* single tram bits can only be left in one direction */
278 if (this->IsTram()) {
279 DiagDirection single_tram = GetSingleTramBit(this->old_tile);
280 if (single_tram != DiagDirection::Invalid && single_tram != this->exitdir) {
281 this->err = ErrorCode::NoWay;
282 return false;
283 }
284 }
285
286 /* road depots can be also left in one direction only */
287 if (IsRoadTT() && IsDepotTypeTile(this->old_tile, TT())) {
289 if (exitdir != this->exitdir) {
290 this->err = ErrorCode::NoWay;
291 return false;
292 }
293 }
294 return true;
295 }
296
301 inline bool CanEnterNewTile()
302 {
303 if (IsRoadTT() && IsBayRoadStopTile(this->new_tile)) {
304 /* road stop can be entered from one direction only unless it's a drive-through stop */
305 DiagDirection exitdir = GetBayRoadStopDir(this->new_tile);
306 if (ReverseDiagDir(exitdir) != this->exitdir) {
307 this->err = ErrorCode::NoWay;
308 return false;
309 }
310 }
311
312 /* single tram bits can only be entered from one direction */
313 if (this->IsTram()) {
314 DiagDirection single_tram = this->GetSingleTramBit(this->new_tile);
315 if (single_tram != DiagDirection::Invalid && single_tram != ReverseDiagDir(this->exitdir)) {
316 this->err = ErrorCode::NoWay;
317 return false;
318 }
319 }
320
321 /* road and rail depots can also be entered from one direction only */
322 if (IsRoadTT() && IsDepotTypeTile(this->new_tile, TT())) {
324 if (ReverseDiagDir(exitdir) != this->exitdir) {
325 this->err = ErrorCode::NoWay;
326 return false;
327 }
328 /* don't try to enter other company's depots */
329 if (GetTileOwner(this->new_tile) != this->veh_owner) {
330 this->err = ErrorCode::Owner;
331 return false;
332 }
333 }
334 if (IsRailTT() && IsDepotTypeTile(this->new_tile, TT())) {
336 if (ReverseDiagDir(exitdir) != this->exitdir) {
337 this->err = ErrorCode::NoWay;
338 return false;
339 }
340 }
341
342 /* rail transport is possible only on tiles with the same owner as vehicle */
343 if (IsRailTT() && GetTileOwner(this->new_tile) != this->veh_owner) {
344 /* different owner */
345 this->err = ErrorCode::NoWay;
346 return false;
347 }
348
349 /* rail transport is possible only on compatible rail types */
350 if (IsRailTT() && this->railtypes.Any()) {
351 RailType rail_type = GetTileRailType(this->new_tile);
352 if (!this->railtypes.Test(rail_type)) {
353 /* incompatible rail type */
354 this->err = ErrorCode::RailRoadType;
355 return false;
356 }
357 }
358
359 /* road transport is possible only on compatible road types */
360 if (IsRoadTT()) {
361 const RoadVehicle *v = RoadVehicle::From(this->veh);
362 RoadType roadtype = GetRoadType(this->new_tile, GetRoadTramType(v->roadtype));
363 if (!v->compatible_roadtypes.Test(roadtype)) {
364 /* incompatible road type */
365 this->err = ErrorCode::RailRoadType;
366 return false;
367 }
368 }
369
370 /* tunnel holes and bridge ramps can be entered only from proper direction */
371 if (IsTileType(this->new_tile, TileType::TunnelBridge)) {
372 if (IsTunnel(this->new_tile)) {
373 if (!this->is_tunnel) {
374 DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(this->new_tile);
375 if (tunnel_enterdir != this->exitdir) {
376 this->err = ErrorCode::NoWay;
377 return false;
378 }
379 }
380 } else { // IsBridge(new_tile)
381 if (!this->is_bridge) {
382 DiagDirection ramp_enderdir = GetTunnelBridgeDirection(this->new_tile);
383 if (ramp_enderdir != this->exitdir) {
384 this->err = ErrorCode::NoWay;
385 return false;
386 }
387 }
388 }
389 }
390
391 /* special handling for rail stations - get to the end of platform */
392 if (IsRailTT() && this->is_station) {
393 /* entered railway station
394 * get platform length */
395 uint length = BaseStation::GetByTile(this->new_tile)->GetPlatformLength(this->new_tile, TrackdirToExitdir(this->old_td));
396 /* how big step we must do to get to the last platform tile? */
397 this->tiles_skipped = length - 1;
398 /* move to the platform end */
399 TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
400 diff *= this->tiles_skipped;
401 this->new_tile = TileAdd(this->new_tile, diff);
402 return true;
403 }
404
405 return true;
406 }
407
412 inline bool ForcedReverse()
413 {
414 /* rail and road depots cause reversing */
415 if (!IsWaterTT() && IsDepotTypeTile(this->old_tile, TT())) {
416 DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(this->old_tile) : GetRoadDepotDirection(this->old_tile);
417 if (exitdir != this->exitdir) {
418 /* reverse */
419 this->new_tile = this->old_tile;
420 this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
421 this->exitdir = exitdir;
422 this->tiles_skipped = 0;
423 this->is_tunnel = false;
424 this->is_bridge = false;
425 this->is_station = false;
426 return true;
427 }
428 }
429
430 /* Single tram bits and standard road stops cause reversing. */
431 if (IsRoadTT() && ((this->IsTram() && GetSingleTramBit(this->old_tile) == ReverseDiagDir(this->exitdir)) ||
432 (IsBayRoadStopTile(this->old_tile) && GetBayRoadStopDir(this->old_tile) == ReverseDiagDir(this->exitdir)))) {
433 /* reverse */
434 this->new_tile = this->old_tile;
435 this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
436 this->exitdir = ReverseDiagDir(this->exitdir);
437 this->tiles_skipped = 0;
438 this->is_tunnel = false;
439 this->is_bridge = false;
440 this->is_station = false;
441 return true;
442 }
443
444 return false;
445 }
446
451 inline bool TryReverse()
452 {
453 if (IsRoadTT() && !this->IsTram()) {
454 /* if we reached the end of road, we can reverse the RV and continue moving */
455 this->exitdir = ReverseDiagDir(this->exitdir);
456 /* new tile will be the same as old one */
457 this->new_tile = this->old_tile;
458 /* set new trackdir bits to all reachable trackdirs */
460 this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
461 if (this->new_td_bits.Any()) {
462 /* we have some trackdirs reachable after reversal */
463 return true;
464 }
465 }
466 this->err = ErrorCode::NoWay;
467 return false;
468 }
469
470public:
476 int GetSpeedLimit(int *pmin_speed = nullptr) const
477 {
478 int min_speed = 0;
479 int max_speed = INT_MAX; // no limit
480
481 /* Check for on-bridge speed limit */
482 if (!IsWaterTT() && IsBridgeTile(this->old_tile)) {
483 int spd = GetBridgeSpec(GetBridgeType(this->old_tile))->speed;
484 if (IsRoadTT()) spd *= 2;
485 max_speed = std::min(max_speed, spd);
486 }
487 /* Check for speed limit imposed by railtype */
488 if (IsRailTT()) {
489 uint16_t rail_speed = GetRailTypeInfo(GetRailType(this->old_tile))->max_speed;
490 if (rail_speed > 0) max_speed = std::min<int>(max_speed, rail_speed);
491 }
492 if (IsRoadTT()) {
493 /* max_speed is already in roadvehicle units, no need to further modify (divide by 2) */
494 uint16_t road_speed = GetRoadTypeInfo(GetRoadType(this->old_tile, GetRoadTramType(RoadVehicle::From(this->veh)->roadtype)))->max_speed;
495 if (road_speed > 0) max_speed = std::min<int>(max_speed, road_speed);
496 }
497
498 /* if min speed was requested, return it */
499 if (pmin_speed != nullptr) *pmin_speed = min_speed;
500 return max_speed;
501 }
502};
503
504typedef CFollowTrackT<TRANSPORT_WATER, Ship, true > CFollowTrackWater;
506typedef CFollowTrackT<TRANSPORT_RAIL, Train, true > CFollowTrackRail;
507
508typedef CFollowTrackT<TRANSPORT_RAIL, Train, false> CFollowTrackRailNo90;
509
510typedef CFollowTrackT<TRANSPORT_RAIL, Train, true, true > CFollowTrackFreeRail;
511typedef CFollowTrackT<TRANSPORT_RAIL, Train, false, true > CFollowTrackFreeRailNo90;
512
513#endif /* FOLLOW_TRACK_HPP */
const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition bridge.h:62
TileIndex GetOtherBridgeEnd(TileIndex tile)
Starting at one bridge end finds the other bridge end.
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
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
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.
uint16_t max_speed
Maximum speed for vehicles travelling on this rail type.
Definition rail.h:222
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:118
static constexpr Owner INVALID_OWNER
An invalid owner.
Map related accessors for depots.
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:22
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
DiagDirection
Enumeration for diagonal directions.
@ Invalid
Flag for an invalid DiagDirection.
@ SW
Southwest.
@ NW
Northwest.
@ NE
Northeast, upper right on your monitor.
@ SE
Southeast.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
TileIndex TileAddByDiagDir(TileIndex tile, DiagDirection dir)
Adds a DiagDir to a tile.
Definition map_func.h:615
constexpr TileIndex TileAdd(TileIndex tile, TileIndexDiff offset)
Adds a given offset to a tile.
Definition map_func.h:461
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:574
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(), as for single tram bits GetTileTrackStatus() returns 0.
TrackBits GetReservedTrackbits(TileIndex t)
Get the reserved trackbits for any tile, regardless of type.
Definition pbs.cpp:24
PBS support routines.
RailType GetTileRailType(Tile tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition rail.cpp:39
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:413
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:303
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
static bool IsPlainRailTile(Tile t)
Checks whether the tile is a rail tile or rail tile with signals.
Definition rail_map.h:60
DiagDirection GetRailDepotDirection(Tile t)
Returns the direction the depot is facing to.
Definition rail_map.h:171
EnumBitSet< RailType, uint64_t > RailTypes
Bitset of RailType elements.
Definition rail_type.h:36
RailType
Enumeration for all possible railtypes.
Definition rail_type.h:25
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition road.h:217
RoadBits GetRoadBits(Tile t, RoadTramType rtt)
Get the present road bits for a specific road type.
Definition road_map.h:112
DiagDirection GetRoadDepotDirection(Tile t)
Get the direction of the exit of a road depot.
Definition road_map.h:565
RoadType GetRoadType(Tile t, RoadTramType rtt)
Get the road type for the given RoadTramType.
Definition road_map.h:175
static bool IsNormalRoadTile(Tile t)
Return whether a tile is a normal road tile.
Definition road_map.h:58
EnumBitSet< RoadBit, uint8_t > RoadBits
Bitset of RoadBit elements.
Definition road_type.h:64
@ SW
South-west part.
Definition road_type.h:58
@ NW
North-west part.
Definition road_type.h:57
@ NE
North-east part.
Definition road_type.h:60
@ SE
South-east part.
Definition road_type.h:59
RoadType
The different roadtypes we support.
Definition road_type.h:23
RoadTramType
The different types of road type.
Definition road_type.h:37
@ Invalid
Invalid marker.
Definition road_type.h:41
@ Tram
Tram type.
Definition road_type.h:39
@ Road
Road type.
Definition road_type.h:38
Road vehicle states.
Base classes/functions for stations.
bool IsStationRoadStopTile(Tile t)
Is tile t a road stop station?
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
bool HasStationTileRail(Tile t)
Has this station tile a rail?
bool HasStationReservation(Tile t)
Get the reservation state of the rail station.
DiagDirection GetBayRoadStopDir(Tile t)
Gets the direction the bay road stop entrance points towards.
#define debug_inline
When making a (pure) debug build, the compiler will by default disable inlining of functions.
Definition stdafx.h:222
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:41
Track follower helper template class (can serve pathfinders and vehicle controllers).
bool CanExitOldTile()
Check whether we can leave the old tile.
bool Follow(TileIndex old_tile, Trackdir old_td)
Main follower routine.
bool CanEnterNewTile()
Checks whether we can enter the next tile.
bool QueryNewTileTrackStatus()
Stores track status (available trackdirs) for the new tile into new_td_bits.
bool TryReverse()
Try whether we can reverse our road vehicle.
int GetSpeedLimit(int *pmin_speed=nullptr) const
Helper for pathfinders - get min/max speed on the old_tile/old_td.
bool ForcedReverse()
Are we forced to reverse the vehicle?
void FollowTileExit()
Follow the exitdir from old_tile and fill new_tile and tiles_skipped.
ErrorCode
Errors encountered when attempting to follow tracks.
@ SharpTurn
90 degree turn.
@ RailRoadType
Incompatible rail or road type.
@ Reserved
Path reserved track.
@ NoWay
Tile cannot be entered.
DiagDirection GetSingleTramBit(TileIndex tile)
Tests if a tile is a road tile with a single tramtrack (tram can reverse).
Buses, trucks and trams belong to this class.
Definition roadveh.h:105
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition roadveh.h:117
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition roadveh.h:115
static Train * From(Vehicle *v)
TrackdirBits trackdirs
Trackdirs present on the tile.
Definition track_type.h:106
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
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
@ TunnelBridge
Tunnel entry/exit and bridge heads.
Definition tile_type.h:58
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition track_func.h:292
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:220
bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition track_func.h:540
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
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
Definition track_func.h:86
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition track_func.h:343
TrackdirBits TrackToTrackdirBits(Track track)
Returns a TrackdirBit mask from a given Track.
Definition track_func.h:267
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition track_func.h:281
EnumBitSet< Trackdir, uint16_t > TrackdirBits
Bitset of Trackdir elements.
Definition track_type.h:93
EnumBitSet< Track, uint8_t > TrackBits
Bitset of Track elements.
Definition track_type.h:43
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:63
@ Invalid
Flag for an invalid trackdir.
Definition track_type.h:82
Track
These are used to specify a single track.
Definition track_type.h:19
Base for the train class.
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.
bool IsTunnel(Tile t)
Is this a tunnel (entrance)?
Definition tunnel_map.h:23
Header file for things common for tunnels and bridges.
uint GetTunnelBridgeLength(TileIndex begin, TileIndex end)
Calculates the length of a tunnel or a bridge (without end tiles).
Functions that have tunnels and bridges in common.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
VehicleType
Available vehicle types.
@ Train
Train vehicle type.