OpenTTD Source: src/signal.cpp Source File

OpenTTD Source 15.3

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