OpenTTD Source 20250524-master-gc366e6a48e
signal.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 "debug.h"
12#include "station_map.h"
13#include "tunnelbridge_map.h"
14#include "vehicle_func.h"
15#include "viewport_func.h"
16#include "train.h"
17#include "company_base.h"
18#include "pbs.h"
19
20#include "safeguards.h"
21
22
24static const uint SIG_TBU_SIZE = 64;
25static const uint SIG_TBD_SIZE = 256;
26static const uint SIG_GLOB_SIZE = 128;
27static const uint SIG_GLOB_UPDATE = 64;
28
29static_assert(SIG_GLOB_UPDATE <= SIG_GLOB_SIZE);
30
38
46
52template <typename Tdir, uint items>
53struct SmallSet {
54private:
55 uint n = 0; // actual number of units
56 bool overflowed = false; // did we try to overflow the set?
57 const std::string_view name; // name, used for debugging purposes...
58
60 struct SSdata {
61 TileIndex tile;
62 Tdir dir;
63 } data[items];
64
65public:
67 SmallSet(std::string_view name) : name(name) { }
68
70 void Reset()
71 {
72 this->n = 0;
73 this->overflowed = false;
74 }
75
81 {
82 return this->overflowed;
83 }
84
89 bool IsEmpty()
90 {
91 return this->n == 0;
92 }
93
98 bool IsFull()
99 {
100 return this->n == lengthof(data);
101 }
102
107 uint Items()
108 {
109 return this->n;
110 }
111
112
119 bool Remove(TileIndex tile, Tdir dir)
120 {
121 for (uint i = 0; i < this->n; i++) {
122 if (this->data[i].tile == tile && this->data[i].dir == dir) {
123 this->data[i] = this->data[--this->n];
124 return true;
125 }
126 }
127
128 return false;
129 }
130
137 bool IsIn(TileIndex tile, Tdir dir)
138 {
139 for (uint i = 0; i < this->n; i++) {
140 if (this->data[i].tile == tile && this->data[i].dir == dir) return true;
141 }
142
143 return false;
144 }
145
153 bool Add(TileIndex tile, Tdir dir)
154 {
155 if (this->IsFull()) {
156 overflowed = true;
157 Debug(misc, 0, "SignalSegment too complex. Set {} is full (maximum {})", name, items);
158 return false; // set is full
159 }
160
161 this->data[this->n].tile = tile;
162 this->data[this->n].dir = dir;
163 this->n++;
164
165 return true;
166 }
167
174 bool Get(TileIndex *tile, Tdir *dir)
175 {
176 if (this->n == 0) return false;
177
178 this->n--;
179 *tile = this->data[this->n].tile;
180 *dir = this->data[this->n].dir;
181
182 return true;
183 }
184};
185
189
190
192static bool IsTrainAndNotInDepot(const Vehicle *v)
193{
194 return v->type == VEH_TRAIN && Train::From(v)->track != TRACK_BIT_DEPOT;
195}
196
197
212{
213 _globset.Remove(t1, d1); // it can be in Global but not in Todo
214 _globset.Remove(t2, d2); // remove in all cases
215
216 assert(!_tbdset.IsIn(t1, d1)); // it really shouldn't be there already
217
218 return !_tbdset.Remove(t2, d2);
219}
220
221
236{
237 if (!CheckAddToTodoSet(t1, d1, t2, d2)) return true;
238
239 return _tbdset.Add(t1, d1);
240}
241
242
244enum class SigFlag : uint8_t {
245 Train,
246 Exit,
247 MultiExit,
248 Green,
249 MultiGreen,
250 Full,
251 Pbs,
252 Split,
253 Enter,
254 MultiEnter,
255};
257
265{
266 SigFlags flags{};
267
268 TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
270
271 while (_tbdset.Get(&tile, &enterdir)) { // tile and enterdir are initialized here, unless I'm mistaken.
272 TileIndex oldtile = tile; // tile we are leaving
273 DiagDirection exitdir = enterdir == INVALID_DIAGDIR ? INVALID_DIAGDIR : ReverseDiagDir(enterdir); // expected new exit direction (for straight line)
274
275 switch (GetTileType(tile)) {
276 case MP_RAILWAY: {
277 if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing)
278
279 if (IsRailDepot(tile)) {
280 if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
281 if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
282 exitdir = GetRailDepotDirection(tile);
283 tile += TileOffsByDiagDir(exitdir);
284 enterdir = ReverseDiagDir(exitdir);
285 break;
286 } else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot
287 if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
288 continue;
289 } else {
290 continue;
291 }
292 }
293
294 assert(IsValidDiagDirection(enterdir));
295 TrackBits tracks = GetTrackBits(tile); // trackbits of tile
296 TrackBits tracks_masked = (TrackBits)(tracks & _enterdir_to_trackbits[enterdir]); // only incidating trackbits
297
298 if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one incidating track, no need to check
299 tracks = tracks_masked;
300 /* If no train detected yet, and there is not no train -> there is a train -> set the flag */
301 if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train);
302 } else {
303 if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
304 if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
305 }
306
307 /* Is this a track merge or split? */
308 if (!HasAtMostOneBit(tracks)) flags.Set(SigFlag::Split);
309
310 if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
311 Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
312 if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir
313 SignalType sig = GetSignalType(tile, track);
314 Trackdir trackdir = (Trackdir)FindFirstBit((tracks * 0x101U) & _enterdir_to_trackdirbits[enterdir]);
315 Trackdir reversedir = ReverseTrackdir(trackdir);
316 /* add (tile, reversetrackdir) to 'to-be-updated' set when there is
317 * ANY conventional signal in REVERSE direction
318 * (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */
319 if (HasSignalOnTrackdir(tile, reversedir)) {
320 if (IsPbsSignal(sig)) flags.Set(SigFlag::Pbs);
321 if (flags.Test(SigFlag::Enter)) flags.Set(SigFlag::MultiEnter);
322 flags.Set(SigFlag::Enter);
323
324 if (!_tbuset.Add(tile, reversedir)) return flags | SigFlag::Full;
325 }
326 if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags.Set(SigFlag::Pbs);
327
328 /* if it is a presignal EXIT in OUR direction and we haven't found 2 green exits yes, do special check */
329 if (!flags.Test(SigFlag::MultiGreen) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit
330 if (flags.Test(SigFlag::Exit)) flags.Set(SigFlag::MultiExit); // found two (or more) exits
331 flags.Set(SigFlag::Exit); // found at least one exit - allow for compiler optimizations
332 if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { // found green presignal exit
333 if (flags.Test(SigFlag::Green)) flags.Set(SigFlag::MultiGreen);
334 flags.Set(SigFlag::Green);
335 }
336 }
337
338 continue;
339 }
340 }
341
342 for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { // test all possible exit directions
343 if (dir != enterdir && (tracks & _enterdir_to_trackbits[dir])) { // any track incidating?
344 TileIndex newtile = tile + TileOffsByDiagDir(dir); // new tile to check
345 DiagDirection newdir = ReverseDiagDir(dir); // direction we are entering from
346 if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SigFlag::Full;
347 }
348 }
349
350 continue; // continue the while() loop
351 }
352
353 case MP_STATION:
354 if (!HasStationRail(tile)) continue;
355 if (GetTileOwner(tile) != owner) continue;
356 if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
357 if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
358
359 if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
360 tile += TileOffsByDiagDir(exitdir);
361 break;
362
363 case MP_ROAD:
364 if (!IsLevelCrossing(tile)) continue;
365 if (GetTileOwner(tile) != owner) continue;
366 if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
367
368 if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
369 tile += TileOffsByDiagDir(exitdir);
370 break;
371
372 case MP_TUNNELBRIDGE: {
373 if (GetTileOwner(tile) != owner) continue;
374 if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
376
377 if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole
378 if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
379 enterdir = dir;
380 exitdir = ReverseDiagDir(dir);
381 tile += TileOffsByDiagDir(exitdir); // just skip to next tile
382 } else { // NOT incoming from the wormhole!
383 if (ReverseDiagDir(enterdir) != dir) continue;
384 if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train);
385 tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile
386 enterdir = INVALID_DIAGDIR;
387 exitdir = INVALID_DIAGDIR;
388 }
389 }
390 break;
391
392 default:
393 continue; // continue the while() loop
394 }
395
396 if (!MaybeAddToTodoSet(tile, enterdir, oldtile, exitdir)) return flags | SigFlag::Full;
397 }
398
399 return flags;
400}
401
402
409{
410 TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
411 Trackdir trackdir = INVALID_TRACKDIR;
412
413 while (_tbuset.Get(&tile, &trackdir)) {
414 assert(HasSignalOnTrackdir(tile, trackdir));
415
416 Track track = TrackdirToTrack(trackdir);
417 SignalType sig = GetSignalType(tile, track);
419
420 /* Signal state of reserved path signals is handled by the reserve/unreserve process. */
421 if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue;
422
423 /* determine whether the new state is red */
424 if (flags.Test(SigFlag::Train)) {
425 /* train in the segment */
426 newstate = SIGNAL_STATE_RED;
427 } else if (IsPbsSignal(sig) && flags.Any({SigFlag::Split, SigFlag::MultiEnter})) {
428 /* Turn path signals red if the segment has a junction or more than one way in. */
429 newstate = SIGNAL_STATE_RED;
430 } else {
431 /* is it a bidir combo? - then do not count its other signal direction as exit */
432 if (sig == SIGTYPE_COMBO && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
433 /* at least one more exit */
434 if (flags.Test(SigFlag::MultiExit) &&
435 /* no green exit */
436 (!flags.Test(SigFlag::Green) ||
437 /* only one green exit, and it is this one - so all other exits are red */
439 newstate = SIGNAL_STATE_RED;
440 }
441 } else { // entry, at least one exit, no green exit
442 if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && flags.Test(SigFlag::Exit) && !flags.Test(SigFlag::Green)) newstate = SIGNAL_STATE_RED;
443 }
444 }
445
446 /* only when the state changes */
447 if (newstate != GetSignalStateByTrackdir(tile, trackdir)) {
448 if (IsPresignalExit(tile, TrackdirToTrack(trackdir))) {
449 /* for pre-signal exits, add block to the global set */
451 _globset.Add(tile, exitdir); // do not check for full global set, first update all signals
452 }
453 SetSignalStateByTrackdir(tile, trackdir, newstate);
455 }
456 }
457
458}
459
460
462static inline void ResetSets()
463{
464 _tbuset.Reset();
465 _tbdset.Reset();
466 _globset.Reset();
467}
468
469
478{
479 assert(Company::IsValidID(owner));
480
481 bool first = true; // first block?
482 SigSegState state = SIGSEG_FREE; // value to return
483
484 TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
486
487 while (_globset.Get(&tile, &dir)) {
488 assert(_tbuset.IsEmpty());
489 assert(_tbdset.IsEmpty());
490
491 /* After updating signal, data stored are always MP_RAILWAY with signals.
492 * Other situations happen when data are from outside functions -
493 * modification of railbits (including both rail building and removal),
494 * train entering/leaving block, train leaving depot...
495 */
496 switch (GetTileType(tile)) {
497 case MP_TUNNELBRIDGE:
498 /* 'optimization assert' - do not try to update signals when it is not needed */
500 assert(dir == INVALID_DIAGDIR || dir == ReverseDiagDir(GetTunnelBridgeDirection(tile)));
501 _tbdset.Add(tile, INVALID_DIAGDIR); // we can safely start from wormhole centre
503 break;
504
505 case MP_RAILWAY:
506 if (IsRailDepot(tile)) {
507 /* 'optimization assert' do not try to update signals in other cases */
508 assert(dir == INVALID_DIAGDIR || dir == GetRailDepotDirection(tile));
509 _tbdset.Add(tile, INVALID_DIAGDIR); // start from depot inside
510 break;
511 }
512 [[fallthrough]];
513
514 case MP_STATION:
515 case MP_ROAD:
517 /* only add to set when there is some 'interesting' track */
518 _tbdset.Add(tile, dir);
519 _tbdset.Add(tile + TileOffsByDiagDir(dir), ReverseDiagDir(dir));
520 break;
521 }
522 [[fallthrough]];
523
524 default:
525 /* jump to next tile */
526 tile = tile + TileOffsByDiagDir(dir);
527 dir = ReverseDiagDir(dir);
529 _tbdset.Add(tile, dir);
530 break;
531 }
532 /* happens when removing a rail that wasn't connected at one or both sides */
533 continue; // continue the while() loop
534 }
535
536 assert(!_tbdset.Overflowed()); // it really shouldn't overflow by these one or two items
537 assert(!_tbdset.IsEmpty()); // it wouldn't hurt anyone, but shouldn't happen too
538
539 SigFlags flags = ExploreSegment(owner);
540
541 if (first) {
542 first = false;
543 /* SIGSEG_FREE is set by default */
544 if (flags.Test(SigFlag::Pbs)) {
545 state = SIGSEG_PBS;
546 } else if (flags.Test(SigFlag::Train) || (flags.Test(SigFlag::Exit) && !flags.Test(SigFlag::Green)) || flags.Test(SigFlag::Full)) {
547 state = SIGSEG_FULL;
548 }
549 }
550
551 /* do not do anything when some buffer was full */
552 if (flags.Test(SigFlag::Full)) {
553 ResetSets(); // free all sets
554 break;
555 }
556
558 }
559
560 return state;
561}
562
563
565
566
572{
573 if (!_globset.IsEmpty()) {
575 _last_owner = INVALID_OWNER; // invalidate
576 }
577}
578
579
588{
589 static const DiagDirection _search_dir_1[] = {
591 };
592 static const DiagDirection _search_dir_2[] = {
594 };
595
596 /* do not allow signal updates for two companies in one run */
597 assert(_globset.IsEmpty() || owner == _last_owner);
598
599 _last_owner = owner;
600
601 _globset.Add(tile, _search_dir_1[track]);
602 _globset.Add(tile, _search_dir_2[track]);
603
604 if (_globset.Items() >= SIG_GLOB_UPDATE) {
605 /* too many items, force update */
608 }
609}
610
611
620{
621 /* do not allow signal updates for two companies in one run */
622 assert(_globset.IsEmpty() || owner == _last_owner);
623
624 _last_owner = owner;
625
626 _globset.Add(tile, side);
627
628 if (_globset.Items() >= SIG_GLOB_UPDATE) {
629 /* too many items, force update */
632 }
633}
634
646{
647 assert(_globset.IsEmpty());
648 _globset.Add(tile, side);
649
650 return UpdateSignalsInBuffer(owner);
651}
652
653
663void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner)
664{
665 assert(_globset.IsEmpty());
666
667 AddTrackToSignalBuffer(tile, track, owner);
669}
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
bool Failed() const
Did this command fail?
Enum-as-bit-set wrapper.
Definition of stuff that is very close to a company, like the company struct itself.
static constexpr Owner INVALID_OWNER
An invalid owner.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
DiagDirection ReverseDiagDir(DiagDirection d)
Returns the reverse direction of the given DiagDirection.
bool IsValidDiagDirection(DiagDirection d)
Checks if an integer value is a valid DiagDirection.
Axis DiagDirToAxis(DiagDirection d)
Convert a DiagDirection to the axis.
DiagDirection
Enumeration for diagonal directions.
@ DIAGDIR_NE
Northeast, upper right on your monitor.
@ DIAGDIR_NW
Northwest.
@ DIAGDIR_SE
Southeast.
@ DIAGDIR_END
Used for iterations.
@ DIAGDIR_BEGIN
Used for iterations.
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
@ DIAGDIR_SW
Southwest.
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition map_func.h:569
PBS support routines.
bool HasSignalOnTrackdir(Tile tile, Trackdir trackdir)
Checks for the presence of signals along the given trackdir on the given rail tile.
Definition rail_map.h:425
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
void SetSignalStateByTrackdir(Tile tile, Trackdir trackdir, SignalState state)
Sets the state of the signal along the given trackdir.
Definition rail_map.h:448
bool HasSignalOnTrack(Tile tile, Track track)
Checks for the presence of signals (either way) on the given track on the given rail tile.
Definition rail_map.h:412
bool IsOnewaySignal(Tile t, Track track)
One-way signals can't be passed the 'wrong' way.
Definition rail_map.h:318
static debug_inline bool IsRailDepot(Tile t)
Is this rail tile a rail depot?
Definition rail_map.h:95
TrackBits GetRailReservationTrackBits(Tile t)
Returns the reserved track bits of the tile.
Definition rail_map.h:194
bool HasSignals(Tile t)
Checks if a rail tile has signals.
Definition rail_map.h:72
SignalState GetSignalStateByTrackdir(Tile tile, Trackdir trackdir)
Gets the state of the signal along the given trackdir.
Definition rail_map.h:437
Axis GetCrossingRoadAxis(Tile t)
Get the road axis of a level crossing.
Definition road_map.h:309
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition road_map.h:69
A number of safeguards to prevent using unsafe methods.
static bool IsTrainAndNotInDepot(const Vehicle *v)
Check whether there is a train on rail, not in a depot.
Definition signal.cpp:192
static Owner _last_owner
last owner whose track was put into _globset
Definition signal.cpp:564
static bool MaybeAddToTodoSet(TileIndex t1, DiagDirection d1, TileIndex t2, DiagDirection d2)
Perform some operations before adding data into Todo set The new and reverse direction is removed fro...
Definition signal.cpp:235
static const TrackdirBits _enterdir_to_trackdirbits[DIAGDIR_END]
incidating trackdirbits with given enterdir
Definition signal.cpp:40
static SmallSet< Trackdir, SIG_TBU_SIZE > _tbuset("_tbuset")
set of signals that will be updated
static SmallSet< DiagDirection, SIG_GLOB_SIZE > _globset("_globset")
set of places to be updated in following runs
void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner)
Add track to signal update buffer.
Definition signal.cpp:587
SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner)
Update signals, starting at one side of a tile Will check tile next to this at opposite side too.
Definition signal.cpp:645
void UpdateSignalsInBuffer()
Update signals in buffer Called from 'outside'.
Definition signal.cpp:571
static const uint SIG_TBD_SIZE
number of intersections - open nodes in current block
Definition signal.cpp:25
void AddSideToSignalBuffer(TileIndex tile, DiagDirection side, Owner owner)
Add side of tile to signal update buffer.
Definition signal.cpp:619
static const uint SIG_GLOB_SIZE
number of open blocks (block can be opened more times until detected)
Definition signal.cpp:26
static void ResetSets()
Reset all sets after one set overflowed.
Definition signal.cpp:462
SigFlag
Current signal block state flags.
Definition signal.cpp:244
@ MultiGreen
two or more green exits found
@ MultiExit
two or more exits found
@ Pbs
pbs signal found
@ MultiEnter
two or more signals entering the block found
@ Split
track merge/split found
@ Full
some of buffers was full, do not continue
@ Green
green exitsignal found
@ Train
train found in segment
@ Enter
signal entering the block found
@ Exit
exitsignal found
static SmallSet< DiagDirection, SIG_TBD_SIZE > _tbdset("_tbdset")
set of open nodes in current signal block
static const uint SIG_TBU_SIZE
these are the maximums used for updating signal blocks
Definition signal.cpp:24
static void UpdateSignalsAroundSegment(SigFlags flags)
Update signals around segment in _tbuset.
Definition signal.cpp:408
void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner)
Update signals at segments that are at both ends of given (existent or non-existent) track.
Definition signal.cpp:663
static const uint SIG_GLOB_UPDATE
how many items need to be in _globset to force update
Definition signal.cpp:27
static bool CheckAddToTodoSet(TileIndex t1, DiagDirection d1, TileIndex t2, DiagDirection d2)
Perform some operations before adding data into Todo set The new and reverse direction is removed fro...
Definition signal.cpp:211
static const TrackBits _enterdir_to_trackbits[DIAGDIR_END]
incidating trackbits with given enterdir
Definition signal.cpp:32
static SigFlags ExploreSegment(Owner owner)
Search signal block.
Definition signal.cpp:264
SigSegState
State of the signal segment.
Definition signal_func.h:49
@ SIGSEG_PBS
Segment is a PBS segment.
Definition signal_func.h:52
@ SIGSEG_FREE
Free and has no pre-signal exits or at least one green exit.
Definition signal_func.h:50
@ SIGSEG_FULL
Occupied by a train.
Definition signal_func.h:51
SignalType
Type of signal, i.e.
Definition signal_type.h:23
@ SIGTYPE_COMBO
presignal inter-block
Definition signal_type.h:27
SignalState
These are states in which a signal can be.
Definition signal_type.h:42
@ SIGNAL_STATE_RED
The signal is red.
Definition signal_type.h:43
@ SIGNAL_STATE_GREEN
The signal is green.
Definition signal_type.h:44
Maps accessors for stations.
Axis GetRailStationAxis(Tile t)
Get the rail direction of a rail station.
bool IsStationTileBlocked(Tile t)
Is tile t a blocked tile?
bool HasStationRail(Tile t)
Has this station tile a rail? In other words, is this station tile a rail station or rail waypoint?
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
VehicleType type
Type of vehicle.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Element of set.
Definition signal.cpp:60
Set containing 'items' items of 'tile and Tdir' No tree structure is used because it would cause slow...
Definition signal.cpp:53
bool Add(TileIndex tile, Tdir dir)
Adds tile & dir into the set, checks for full set Sets the 'overflowed' flag if the set was full.
Definition signal.cpp:153
SmallSet(std::string_view name)
Constructor - just set default values and 'name'.
Definition signal.cpp:67
bool Overflowed()
Returns value of 'overflowed'.
Definition signal.cpp:80
bool Remove(TileIndex tile, Tdir dir)
Tries to remove first instance of given tile and dir.
Definition signal.cpp:119
bool Get(TileIndex *tile, Tdir *dir)
Reads the last added element into the set.
Definition signal.cpp:174
void Reset()
Reset variables to default values.
Definition signal.cpp:70
uint Items()
Reads the number of items.
Definition signal.cpp:107
bool IsIn(TileIndex tile, Tdir dir)
Tries to find given tile and dir in the set.
Definition signal.cpp:137
bool IsEmpty()
Checks for empty set.
Definition signal.cpp:89
bool IsFull()
Checks for full set.
Definition signal.cpp:98
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Vehicle data structure.
Owner GetTileOwner(Tile tile)
Returns the owner of a tile.
Definition tile_map.h:178
static debug_inline TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
@ MP_ROAD
A tile with road (or tram tracks)
Definition tile_type.h:50
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
@ MP_TUNNELBRIDGE
Tunnel entry/exit and bridge heads.
Definition tile_type.h:57
@ MP_RAILWAY
A railway.
Definition tile_type.h:49
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition track_func.h:262
TrackBits TrackToTrackBits(Track track)
Maps a Track to the corresponding TrackBits value.
Definition track_func.h:77
Track TrackBitsToTrack(TrackBits tracks)
Converts TrackBits to Track.
Definition track_func.h:193
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:247
TrackBits TrackStatusToTrackBits(TrackStatus ts)
Returns the present-track-information of a TrackStatus.
Definition track_func.h:363
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
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
@ TRACK_BIT_DEPOT
Bitflag for a depot.
Definition track_type.h:53
@ TRACK_BIT_HORZ
Upper and lower track.
Definition track_type.h:44
@ TRACK_BIT_NONE
No track.
Definition track_type.h:36
@ TRACK_BIT_3WAY_NW
"Arrow" to the north-west
Definition track_type.h:49
@ TRACK_BIT_3WAY_NE
"Arrow" to the north-east
Definition track_type.h:46
@ TRACK_BIT_3WAY_SW
"Arrow" to the south-west
Definition track_type.h:48
@ TRACK_BIT_VERT
Left and right track.
Definition track_type.h:45
@ TRACK_BIT_3WAY_SE
"Arrow" to the south-east
Definition track_type.h:47
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_LEFT_S
Track left, direction south.
Definition track_type.h:103
@ TRACKDIR_BIT_Y_NW
Track y-axis, direction north-west.
Definition track_type.h:107
@ TRACKDIR_BIT_UPPER_E
Track upper, direction east.
Definition track_type.h:101
@ TRACKDIR_BIT_X_NE
Track x-axis, direction north-east.
Definition track_type.h:99
@ TRACKDIR_BIT_LOWER_E
Track lower, direction east.
Definition track_type.h:102
@ TRACKDIR_BIT_LEFT_N
Track left, direction north.
Definition track_type.h:110
@ TRACKDIR_BIT_RIGHT_S
Track right, direction south.
Definition track_type.h:104
@ TRACKDIR_BIT_Y_SE
Track y-axis, direction south-east.
Definition track_type.h:100
@ TRACKDIR_BIT_RIGHT_N
Track right, direction north.
Definition track_type.h:111
@ TRACKDIR_BIT_UPPER_W
Track upper, direction west.
Definition track_type.h:108
@ TRACKDIR_BIT_LOWER_W
Track lower, direction west.
Definition track_type.h:109
@ TRACKDIR_BIT_X_SW
Track x-axis, direction south-west.
Definition track_type.h:106
Track
These are used to specify a single track.
Definition track_type.h:19
Base for the train class.
@ TRANSPORT_RAIL
Transport by train.
Functions that have tunnels and bridges in common.
DiagDirection GetTunnelBridgeDirection(Tile t)
Get the direction pointing to the other end.
TransportType GetTunnelBridgeTransportType(Tile t)
Tunnel: Get the transport type of the tunnel (road or rail) Bridge: Get the transport type of the bri...
TileIndex GetOtherTunnelBridgeEnd(Tile t)
Determines type of the wormhole and returns its other end.
CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits)
Tests if a vehicle interacts with the specified track bits.
Definition vehicle.cpp:575
Functions related to vehicles.
bool HasVehicleOnTile(TileIndex tile, UnaryPred &&predicate)
Loop over vehicles on a tile, and check whether a predicate is true for any of them.
@ VEH_TRAIN
Train vehicle type.
Functions related to (drawing on) viewports.