OpenTTD Source 20260421-master-gc2fbc6fdeb
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 {
29 enum ErrorCode : uint8_t {
30 EC_NONE,
31 EC_OWNER,
32 EC_RAIL_ROAD_TYPE,
33 EC_90DEG,
34 EC_NO_WAY,
35 EC_RESERVED,
36 };
37
39 Owner veh_owner;
45 bool is_tunnel;
46 bool is_bridge;
49 ErrorCode err;
50 RailTypes railtypes;
51
52 inline CFollowTrackT(const VehicleType *v = nullptr, RailTypes railtype_override = INVALID_RAILTYPES)
53 {
54 Init(v, railtype_override);
55 }
56
57 inline CFollowTrackT(Owner o, RailTypes railtype_override = INVALID_RAILTYPES)
58 {
59 assert(IsRailTT());
60 this->veh = nullptr;
61 Init(o, railtype_override);
62 }
63
64 inline void Init(const VehicleType *v, RailTypes railtype_override)
65 {
66 assert(!IsRailTT() || (v != nullptr && v->type == VEH_TRAIN));
67 this->veh = v;
68 Init(v != nullptr ? v->owner : INVALID_OWNER, IsRailTT() && railtype_override == INVALID_RAILTYPES ? Train::From(v)->compatible_railtypes : railtype_override);
69 }
70
71 inline void Init(Owner o, RailTypes railtype_override)
72 {
73 assert(!IsRoadTT() || this->veh != nullptr);
74 assert(!IsRailTT() || railtype_override != INVALID_RAILTYPES);
75 this->veh_owner = o;
76 /* don't worry, all is inlined so compiler should remove unnecessary initializations */
77 this->old_tile = INVALID_TILE;
79 this->new_tile = INVALID_TILE;
82 this->is_station = false;
83 this->is_bridge = false;
84 this->is_tunnel = false;
85 this->tiles_skipped = 0;
86 this->err = EC_NONE;
87 this->railtypes = railtype_override;
88 }
89
90 [[debug_inline]] inline static TransportType TT() { return Ttr_type_; }
91 [[debug_inline]] inline static bool IsWaterTT() { return TT() == TRANSPORT_WATER; }
92 [[debug_inline]] inline static bool IsRailTT() { return TT() == TRANSPORT_RAIL; }
93 inline bool IsTram() { return IsRoadTT() && RoadTypeIsTram(RoadVehicle::From(this->veh)->roadtype); }
94 [[debug_inline]] inline static bool IsRoadTT() { return TT() == TRANSPORT_ROAD; }
95 static inline bool Allow90degTurns() { return T90deg_turns_allowed_; }
96 static inline bool DoTrackMasking() { return Tmask_reserved_tracks; }
97
104 {
105 assert(this->IsTram()); // this function shouldn't be called in other cases
106
107 if (IsNormalRoadTile(tile)) {
109 switch (rb.base()) {
110 case RoadBits{RoadBit::NW}.base(): return DIAGDIR_NW;
111 case RoadBits{RoadBit::SW}.base(): return DIAGDIR_SW;
112 case RoadBits{RoadBit::SE}.base(): return DIAGDIR_SE;
113 case RoadBits{RoadBit::NE}.base(): return DIAGDIR_NE;
114 default: break;
115 }
116 }
117 return INVALID_DIAGDIR;
118 }
119
128 {
129 this->old_tile = old_tile;
130 this->old_td = old_td;
131 this->err = EC_NONE;
132
133 assert([&]() {
134 if (this->IsTram() && this->GetSingleTramBit(this->old_tile) != INVALID_DIAGDIR) return true; // Skip the check for single tram bits
135 const RoadTramType sub_mode = (IsRoadTT() && this->veh != nullptr) ? (this->IsTram() ? RoadTramType::Tram : RoadTramType::Road) : RoadTramType::Invalid;
136 const TrackdirBits old_tile_valid_dirs = TrackStatusToTrackdirBits(GetTileTrackStatus(this->old_tile, TT(), sub_mode));
137 return (old_tile_valid_dirs & TrackdirToTrackdirBits(this->old_td)) != TRACKDIR_BIT_NONE;
138 }());
139
140 this->exitdir = TrackdirToExitdir(this->old_td);
141 if (this->ForcedReverse()) return true;
142 if (!this->CanExitOldTile()) return false;
143 this->FollowTileExit();
144 if (!this->QueryNewTileTrackStatus()) return TryReverse();
145 this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
146 if (this->new_td_bits == TRACKDIR_BIT_NONE || !this->CanEnterNewTile()) {
147 /* In case we can't enter the next tile, but are
148 * a normal road vehicle, then we can actually
149 * try to reverse as this is the end of the road.
150 * Trams can only turn on the appropriate bits in
151 * which case reaching this would mean a dead end
152 * near a building and in that case there would
153 * a "false" QueryNewTileTrackStatus result and
154 * as such reversing is already tried. The fact
155 * that function failed can have to do with a
156 * missing road bit, or inability to connect the
157 * different bits due to slopes. */
158 if (IsRoadTT() && !this->IsTram() && this->TryReverse()) return true;
159
160 /* CanEnterNewTile already set a reason.
161 * Do NOT overwrite it (important for example for EC_RAIL_ROAD_TYPE).
162 * Only set a reason if CanEnterNewTile was not called */
163 if (this->new_td_bits == TRACKDIR_BIT_NONE) this->err = EC_NO_WAY;
164
165 return false;
166 }
167 if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(this->old_tile), GetTileRailType(this->new_tile), !Allow90degTurns()))) {
168 this->new_td_bits &= (TrackdirBits)~(int)TrackdirCrossesTrackdirs(this->old_td);
169 if (this->new_td_bits == TRACKDIR_BIT_NONE) {
170 this->err = EC_90DEG;
171 return false;
172 }
173 }
174 return true;
175 }
176
177 inline bool MaskReservedTracks()
178 {
179 if (!DoTrackMasking()) return true;
180
181 if (this->is_station) {
182 /* Check skipped station tiles as well. */
183 TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
184 for (TileIndex tile = this->new_tile - diff * this->tiles_skipped; tile != this->new_tile; tile += diff) {
185 if (HasStationReservation(tile)) {
186 this->new_td_bits = TRACKDIR_BIT_NONE;
187 this->err = EC_RESERVED;
188 return false;
189 }
190 }
191 }
192
193 TrackBits reserved = GetReservedTrackbits(this->new_tile);
194 /* Mask already reserved trackdirs. */
195 this->new_td_bits &= ~TrackBitsToTrackdirBits(reserved);
196 /* Mask out all trackdirs that conflict with the reservation. */
197 for (Track t : SetTrackBitIterator(TrackdirBitsToTrackBits(this->new_td_bits))) {
198 if (TracksOverlap(reserved | TrackToTrackBits(t))) this->new_td_bits &= ~TrackToTrackdirBits(t);
199 }
200 if (this->new_td_bits == TRACKDIR_BIT_NONE) {
201 this->err = EC_RESERVED;
202 return false;
203 }
204 return true;
205 }
206
207protected:
209 inline void FollowTileExit()
210 {
211 this->is_station = false;
212 this->is_bridge = false;
213 this->is_tunnel = false;
214 this->tiles_skipped = 0;
215
216 /* extra handling for tunnels and bridges in our direction */
217 if (IsTileType(this->old_tile, TileType::TunnelBridge)) {
218 DiagDirection enterdir = GetTunnelBridgeDirection(this->old_tile);
219 if (enterdir == this->exitdir) {
220 /* we are entering the tunnel / bridge */
221 if (IsTunnel(this->old_tile)) {
222 this->is_tunnel = true;
223 this->new_tile = GetOtherTunnelEnd(this->old_tile);
224 } else { // IsBridge(old_tile)
225 this->is_bridge = true;
226 this->new_tile = GetOtherBridgeEnd(this->old_tile);
227 }
228 this->tiles_skipped = GetTunnelBridgeLength(this->new_tile, this->old_tile);
229 return;
230 }
231 assert(ReverseDiagDir(enterdir) == this->exitdir);
232 }
233
234 /* normal or station tile, do one step */
235 this->new_tile = TileAddByDiagDir(this->old_tile, this->exitdir);
236
237 /* special handling for stations */
238 if (IsRailTT() && HasStationTileRail(this->new_tile)) {
239 this->is_station = true;
240 } else if (IsRoadTT() && IsStationRoadStopTile(this->new_tile)) {
241 this->is_station = true;
242 }
243 }
244
250 {
251 if (IsRailTT() && IsPlainRailTile(this->new_tile)) {
252 this->new_td_bits = (TrackdirBits)(GetTrackBits(this->new_tile) * 0x101);
253 } else if (IsRoadTT()) {
254 this->new_td_bits = GetTrackdirBitsForRoad(this->new_tile, this->IsTram() ? RoadTramType::Tram : RoadTramType::Road);
255 } else {
256 this->new_td_bits = TrackStatusToTrackdirBits(GetTileTrackStatus(this->new_tile, TT(), RoadTramType::Invalid));
257 }
258 return (this->new_td_bits != TRACKDIR_BIT_NONE);
259 }
260
265 inline bool CanExitOldTile()
266 {
267 /* road stop can be left at one direction only unless it's a drive-through stop */
268 if (IsRoadTT() && IsBayRoadStopTile(this->old_tile)) {
269 DiagDirection exitdir = GetBayRoadStopDir(this->old_tile);
270 if (exitdir != this->exitdir) {
271 this->err = EC_NO_WAY;
272 return false;
273 }
274 }
275
276 /* single tram bits can only be left in one direction */
277 if (this->IsTram()) {
278 DiagDirection single_tram = GetSingleTramBit(this->old_tile);
279 if (single_tram != INVALID_DIAGDIR && single_tram != this->exitdir) {
280 this->err = EC_NO_WAY;
281 return false;
282 }
283 }
284
285 /* road depots can be also left in one direction only */
286 if (IsRoadTT() && IsDepotTypeTile(this->old_tile, TT())) {
288 if (exitdir != this->exitdir) {
289 this->err = EC_NO_WAY;
290 return false;
291 }
292 }
293 return true;
294 }
295
300 inline bool CanEnterNewTile()
301 {
302 if (IsRoadTT() && IsBayRoadStopTile(this->new_tile)) {
303 /* road stop can be entered from one direction only unless it's a drive-through stop */
304 DiagDirection exitdir = GetBayRoadStopDir(this->new_tile);
305 if (ReverseDiagDir(exitdir) != this->exitdir) {
306 this->err = EC_NO_WAY;
307 return false;
308 }
309 }
310
311 /* single tram bits can only be entered from one direction */
312 if (this->IsTram()) {
313 DiagDirection single_tram = this->GetSingleTramBit(this->new_tile);
314 if (single_tram != INVALID_DIAGDIR && single_tram != ReverseDiagDir(this->exitdir)) {
315 this->err = EC_NO_WAY;
316 return false;
317 }
318 }
319
320 /* road and rail depots can also be entered from one direction only */
321 if (IsRoadTT() && IsDepotTypeTile(this->new_tile, TT())) {
323 if (ReverseDiagDir(exitdir) != this->exitdir) {
324 this->err = EC_NO_WAY;
325 return false;
326 }
327 /* don't try to enter other company's depots */
328 if (GetTileOwner(this->new_tile) != this->veh_owner) {
329 this->err = EC_OWNER;
330 return false;
331 }
332 }
333 if (IsRailTT() && IsDepotTypeTile(this->new_tile, TT())) {
335 if (ReverseDiagDir(exitdir) != this->exitdir) {
336 this->err = EC_NO_WAY;
337 return false;
338 }
339 }
340
341 /* rail transport is possible only on tiles with the same owner as vehicle */
342 if (IsRailTT() && GetTileOwner(this->new_tile) != this->veh_owner) {
343 /* different owner */
344 this->err = EC_NO_WAY;
345 return false;
346 }
347
348 /* rail transport is possible only on compatible rail types */
349 if (IsRailTT() && this->railtypes.Any()) {
350 RailType rail_type = GetTileRailType(this->new_tile);
351 if (!this->railtypes.Test(rail_type)) {
352 /* incompatible rail type */
353 this->err = EC_RAIL_ROAD_TYPE;
354 return false;
355 }
356 }
357
358 /* road transport is possible only on compatible road types */
359 if (IsRoadTT()) {
360 const RoadVehicle *v = RoadVehicle::From(this->veh);
361 RoadType roadtype = GetRoadType(this->new_tile, GetRoadTramType(v->roadtype));
362 if (!v->compatible_roadtypes.Test(roadtype)) {
363 /* incompatible road type */
364 this->err = EC_RAIL_ROAD_TYPE;
365 return false;
366 }
367 }
368
369 /* tunnel holes and bridge ramps can be entered only from proper direction */
370 if (IsTileType(this->new_tile, TileType::TunnelBridge)) {
371 if (IsTunnel(this->new_tile)) {
372 if (!this->is_tunnel) {
373 DiagDirection tunnel_enterdir = GetTunnelBridgeDirection(this->new_tile);
374 if (tunnel_enterdir != this->exitdir) {
375 this->err = EC_NO_WAY;
376 return false;
377 }
378 }
379 } else { // IsBridge(new_tile)
380 if (!this->is_bridge) {
381 DiagDirection ramp_enderdir = GetTunnelBridgeDirection(this->new_tile);
382 if (ramp_enderdir != this->exitdir) {
383 this->err = EC_NO_WAY;
384 return false;
385 }
386 }
387 }
388 }
389
390 /* special handling for rail stations - get to the end of platform */
391 if (IsRailTT() && this->is_station) {
392 /* entered railway station
393 * get platform length */
394 uint length = BaseStation::GetByTile(this->new_tile)->GetPlatformLength(this->new_tile, TrackdirToExitdir(this->old_td));
395 /* how big step we must do to get to the last platform tile? */
396 this->tiles_skipped = length - 1;
397 /* move to the platform end */
398 TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
399 diff *= this->tiles_skipped;
400 this->new_tile = TileAdd(this->new_tile, diff);
401 return true;
402 }
403
404 return true;
405 }
406
411 inline bool ForcedReverse()
412 {
413 /* rail and road depots cause reversing */
414 if (!IsWaterTT() && IsDepotTypeTile(this->old_tile, TT())) {
415 DiagDirection exitdir = IsRailTT() ? GetRailDepotDirection(this->old_tile) : GetRoadDepotDirection(this->old_tile);
416 if (exitdir != this->exitdir) {
417 /* reverse */
418 this->new_tile = this->old_tile;
419 this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
420 this->exitdir = exitdir;
421 this->tiles_skipped = 0;
422 this->is_tunnel = false;
423 this->is_bridge = false;
424 this->is_station = false;
425 return true;
426 }
427 }
428
429 /* Single tram bits and standard road stops cause reversing. */
430 if (IsRoadTT() && ((this->IsTram() && GetSingleTramBit(this->old_tile) == ReverseDiagDir(this->exitdir)) ||
431 (IsBayRoadStopTile(this->old_tile) && GetBayRoadStopDir(this->old_tile) == ReverseDiagDir(this->exitdir)))) {
432 /* reverse */
433 this->new_tile = this->old_tile;
434 this->new_td_bits = TrackdirToTrackdirBits(ReverseTrackdir(this->old_td));
435 this->exitdir = ReverseDiagDir(this->exitdir);
436 this->tiles_skipped = 0;
437 this->is_tunnel = false;
438 this->is_bridge = false;
439 this->is_station = false;
440 return true;
441 }
442
443 return false;
444 }
445
450 inline bool TryReverse()
451 {
452 if (IsRoadTT() && !this->IsTram()) {
453 /* if we reached the end of road, we can reverse the RV and continue moving */
454 this->exitdir = ReverseDiagDir(this->exitdir);
455 /* new tile will be the same as old one */
456 this->new_tile = this->old_tile;
457 /* set new trackdir bits to all reachable trackdirs */
459 this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
460 if (this->new_td_bits != TRACKDIR_BIT_NONE) {
461 /* we have some trackdirs reachable after reversal */
462 return true;
463 }
464 }
465 this->err = EC_NO_WAY;
466 return false;
467 }
468
469public:
475 int GetSpeedLimit(int *pmin_speed = nullptr) const
476 {
477 int min_speed = 0;
478 int max_speed = INT_MAX; // no limit
479
480 /* Check for on-bridge speed limit */
481 if (!IsWaterTT() && IsBridgeTile(this->old_tile)) {
482 int spd = GetBridgeSpec(GetBridgeType(this->old_tile))->speed;
483 if (IsRoadTT()) spd *= 2;
484 max_speed = std::min(max_speed, spd);
485 }
486 /* Check for speed limit imposed by railtype */
487 if (IsRailTT()) {
488 uint16_t rail_speed = GetRailTypeInfo(GetRailType(this->old_tile))->max_speed;
489 if (rail_speed > 0) max_speed = std::min<int>(max_speed, rail_speed);
490 }
491 if (IsRoadTT()) {
492 /* max_speed is already in roadvehicle units, no need to further modify (divide by 2) */
493 uint16_t road_speed = GetRoadTypeInfo(GetRoadType(this->old_tile, GetRoadTramType(RoadVehicle::From(this->veh)->roadtype)))->max_speed;
494 if (road_speed > 0) max_speed = std::min<int>(max_speed, road_speed);
495 }
496
497 /* if min speed was requested, return it */
498 if (pmin_speed != nullptr) *pmin_speed = min_speed;
499 return max_speed;
500 }
501};
502
503typedef CFollowTrackT<TRANSPORT_WATER, Ship, true > CFollowTrackWater;
505typedef CFollowTrackT<TRANSPORT_RAIL, Train, true > CFollowTrackRail;
506
507typedef CFollowTrackT<TRANSPORT_RAIL, Train, false> CFollowTrackRailNo90;
508
509typedef CFollowTrackT<TRANSPORT_RAIL, Train, true, true > CFollowTrackFreeRail;
510typedef CFollowTrackT<TRANSPORT_RAIL, Train, false, true > CFollowTrackFreeRailNo90;
511
512#endif /* FOLLOW_TRACK_HPP */
const BridgeSpec * GetBridgeSpec(BridgeType i)
Get the specification of a bridge type.
Definition bridge.h:60
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 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:220
uint16_t max_speed
Maximum speed for vehicles travelling on this road type.
Definition road.h:116
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.
@ 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, 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() 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
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:411
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Definition rail.h:301
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
Allow incrementing of Track variables.
Definition rail_type.h:38
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:215
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:576
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:39
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.
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)
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
TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition track_func.h:77
TrackdirBits TrackStatusToTrackdirBits(TrackStatus ts)
Returns the present-trackdir-information of a TrackStatus.
Definition track_func.h:354
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:650
TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
Maps a trackdir to all trackdirs that make 90 deg turns with it.
Definition track_func.h:611
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:560
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:441
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:66
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition track_type.h:85
TrackdirBits
Allow incrementing of Trackdir variables.
Definition track_type.h:97
@ TRACKDIR_BIT_NONE
No track build.
Definition track_type.h:98
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.
@ VEH_TRAIN
Train vehicle type.