OpenTTD Source  20241120-master-g6d3adc6169
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 
24 static const uint SIG_TBU_SIZE = 64;
25 static const uint SIG_TBD_SIZE = 256;
26 static const uint SIG_GLOB_SIZE = 128;
27 static const uint SIG_GLOB_UPDATE = 64;
28 
29 static_assert(SIG_GLOB_UPDATE <= SIG_GLOB_SIZE);
30 
37 };
38 
45 };
46 
52 template <typename Tdir, uint items>
53 struct SmallSet {
54 private:
55  uint n; // actual number of units
56  bool overflowed; // did we try to overflow the set?
57  const char *name; // name, used for debugging purposes...
58 
60  struct SSdata {
61  TileIndex tile;
62  Tdir dir;
63  } data[items];
64 
65 public:
67  SmallSet(const char *name) : n(0), overflowed(false), name(name) { }
68 
70  void Reset()
71  {
72  this->n = 0;
73  this->overflowed = false;
74  }
75 
80  bool Overflowed()
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 
192 static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
193 {
194  if (v->type != VEH_TRAIN || Train::From(v)->track == TRACK_BIT_DEPOT) return nullptr;
195 
196  return v;
197 }
198 
199 
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 
238 {
239  if (!CheckAddToTodoSet(t1, d1, t2, d2)) return true;
240 
241  return _tbdset.Add(t1, d1);
242 }
243 
244 
246 enum SigFlags {
247  SF_NONE = 0,
248  SF_TRAIN = 1 << 0,
249  SF_EXIT = 1 << 1,
250  SF_EXIT2 = 1 << 2,
251  SF_GREEN = 1 << 3,
252  SF_GREEN2 = 1 << 4,
253  SF_FULL = 1 << 5,
254  SF_PBS = 1 << 6,
255  SF_SPLIT = 1 << 7,
256  SF_ENTER = 1 << 8,
257  SF_ENTER2 = 1 << 9,
258 };
259 
261 
262 
263 
270 {
271  SigFlags flags = SF_NONE;
272 
273  TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
274  DiagDirection enterdir = INVALID_DIAGDIR;
275 
276  while (_tbdset.Get(&tile, &enterdir)) { // tile and enterdir are initialized here, unless I'm mistaken.
277  TileIndex oldtile = tile; // tile we are leaving
278  DiagDirection exitdir = enterdir == INVALID_DIAGDIR ? INVALID_DIAGDIR : ReverseDiagDir(enterdir); // expected new exit direction (for straight line)
279 
280  switch (GetTileType(tile)) {
281  case MP_RAILWAY: {
282  if (GetTileOwner(tile) != owner) continue; // do not propagate signals on others' tiles (remove for tracksharing)
283 
284  if (IsRailDepot(tile)) {
285  if (enterdir == INVALID_DIAGDIR) { // from 'inside' - train just entered or left the depot
286  if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
287  exitdir = GetRailDepotDirection(tile);
288  tile += TileOffsByDiagDir(exitdir);
289  enterdir = ReverseDiagDir(exitdir);
290  break;
291  } else if (enterdir == GetRailDepotDirection(tile)) { // entered a depot
292  if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
293  continue;
294  } else {
295  continue;
296  }
297  }
298 
299  assert(IsValidDiagDirection(enterdir));
300  TrackBits tracks = GetTrackBits(tile); // trackbits of tile
301  TrackBits tracks_masked = (TrackBits)(tracks & _enterdir_to_trackbits[enterdir]); // only incidating trackbits
302 
303  if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one incidating track, no need to check
304  tracks = tracks_masked;
305  /* If no train detected yet, and there is not no train -> there is a train -> set the flag */
306  if (!(flags & SF_TRAIN) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags |= SF_TRAIN;
307  } else {
308  if (tracks_masked == TRACK_BIT_NONE) continue; // no incidating track
309  if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
310  }
311 
312  /* Is this a track merge or split? */
313  if (!HasAtMostOneBit(tracks)) flags |= SF_SPLIT;
314 
315  if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile
316  Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
317  if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir
318  SignalType sig = GetSignalType(tile, track);
319  Trackdir trackdir = (Trackdir)FindFirstBit((tracks * 0x101U) & _enterdir_to_trackdirbits[enterdir]);
320  Trackdir reversedir = ReverseTrackdir(trackdir);
321  /* add (tile, reversetrackdir) to 'to-be-updated' set when there is
322  * ANY conventional signal in REVERSE direction
323  * (if it is a presignal EXIT and it changes, it will be added to 'to-be-done' set later) */
324  if (HasSignalOnTrackdir(tile, reversedir)) {
325  if (IsPbsSignal(sig)) flags |= SF_PBS;
326  if (flags & SF_ENTER) flags |= SF_ENTER2;
327  flags |= SF_ENTER;
328 
329  if (!_tbuset.Add(tile, reversedir)) return flags | SF_FULL;
330  }
331  if (HasSignalOnTrackdir(tile, trackdir) && !IsOnewaySignal(tile, track)) flags |= SF_PBS;
332 
333  /* if it is a presignal EXIT in OUR direction and we haven't found 2 green exits yes, do special check */
334  if (!(flags & SF_GREEN2) && IsPresignalExit(tile, track) && HasSignalOnTrackdir(tile, trackdir)) { // found presignal exit
335  if (flags & SF_EXIT) flags |= SF_EXIT2; // found two (or more) exits
336  flags |= SF_EXIT; // found at least one exit - allow for compiler optimizations
337  if (GetSignalStateByTrackdir(tile, trackdir) == SIGNAL_STATE_GREEN) { // found green presignal exit
338  if (flags & SF_GREEN) flags |= SF_GREEN2;
339  flags |= SF_GREEN;
340  }
341  }
342 
343  continue;
344  }
345  }
346 
347  for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { // test all possible exit directions
348  if (dir != enterdir && (tracks & _enterdir_to_trackbits[dir])) { // any track incidating?
349  TileIndex newtile = tile + TileOffsByDiagDir(dir); // new tile to check
350  DiagDirection newdir = ReverseDiagDir(dir); // direction we are entering from
351  if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SF_FULL;
352  }
353  }
354 
355  continue; // continue the while() loop
356  }
357 
358  case MP_STATION:
359  if (!HasStationRail(tile)) continue;
360  if (GetTileOwner(tile) != owner) continue;
361  if (DiagDirToAxis(enterdir) != GetRailStationAxis(tile)) continue; // different axis
362  if (IsStationTileBlocked(tile)) continue; // 'eye-candy' station tile
363 
364  if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
365  tile += TileOffsByDiagDir(exitdir);
366  break;
367 
368  case MP_ROAD:
369  if (!IsLevelCrossing(tile)) continue;
370  if (GetTileOwner(tile) != owner) continue;
371  if (DiagDirToAxis(enterdir) == GetCrossingRoadAxis(tile)) continue; // different axis
372 
373  if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
374  tile += TileOffsByDiagDir(exitdir);
375  break;
376 
377  case MP_TUNNELBRIDGE: {
378  if (GetTileOwner(tile) != owner) continue;
379  if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue;
381 
382  if (enterdir == INVALID_DIAGDIR) { // incoming from the wormhole
383  if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
384  enterdir = dir;
385  exitdir = ReverseDiagDir(dir);
386  tile += TileOffsByDiagDir(exitdir); // just skip to next tile
387  } else { // NOT incoming from the wormhole!
388  if (ReverseDiagDir(enterdir) != dir) continue;
389  if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, nullptr, &TrainOnTileEnum)) flags |= SF_TRAIN;
390  tile = GetOtherTunnelBridgeEnd(tile); // just skip to exit tile
391  enterdir = INVALID_DIAGDIR;
392  exitdir = INVALID_DIAGDIR;
393  }
394  }
395  break;
396 
397  default:
398  continue; // continue the while() loop
399  }
400 
401  if (!MaybeAddToTodoSet(tile, enterdir, oldtile, exitdir)) return flags | SF_FULL;
402  }
403 
404  return flags;
405 }
406 
407 
414 {
415  TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
416  Trackdir trackdir = INVALID_TRACKDIR;
417 
418  while (_tbuset.Get(&tile, &trackdir)) {
419  assert(HasSignalOnTrackdir(tile, trackdir));
420 
421  Track track = TrackdirToTrack(trackdir);
422  SignalType sig = GetSignalType(tile, track);
423  SignalState newstate = SIGNAL_STATE_GREEN;
424 
425  /* Signal state of reserved path signals is handled by the reserve/unreserve process. */
426  if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue;
427 
428  /* determine whether the new state is red */
429  if (flags & SF_TRAIN) {
430  /* train in the segment */
431  newstate = SIGNAL_STATE_RED;
432  } else if (IsPbsSignal(sig) && (flags & (SF_SPLIT | SF_ENTER2))) {
433  /* Turn path signals red if the segment has a junction or more than one way in. */
434  newstate = SIGNAL_STATE_RED;
435  } else {
436  /* is it a bidir combo? - then do not count its other signal direction as exit */
437  if (sig == SIGTYPE_COMBO && HasSignalOnTrackdir(tile, ReverseTrackdir(trackdir))) {
438  /* at least one more exit */
439  if ((flags & SF_EXIT2) &&
440  /* no green exit */
441  (!(flags & SF_GREEN) ||
442  /* only one green exit, and it is this one - so all other exits are red */
443  (!(flags & SF_GREEN2) && GetSignalStateByTrackdir(tile, ReverseTrackdir(trackdir)) == SIGNAL_STATE_GREEN))) {
444  newstate = SIGNAL_STATE_RED;
445  }
446  } else { // entry, at least one exit, no green exit
447  if (IsPresignalEntry(tile, TrackdirToTrack(trackdir)) && (flags & SF_EXIT) && !(flags & SF_GREEN)) newstate = SIGNAL_STATE_RED;
448  }
449  }
450 
451  /* only when the state changes */
452  if (newstate != GetSignalStateByTrackdir(tile, trackdir)) {
453  if (IsPresignalExit(tile, TrackdirToTrack(trackdir))) {
454  /* for pre-signal exits, add block to the global set */
455  DiagDirection exitdir = TrackdirToExitdir(ReverseTrackdir(trackdir));
456  _globset.Add(tile, exitdir); // do not check for full global set, first update all signals
457  }
458  SetSignalStateByTrackdir(tile, trackdir, newstate);
459  MarkTileDirtyByTile(tile);
460  }
461  }
462 
463 }
464 
465 
467 static inline void ResetSets()
468 {
469  _tbuset.Reset();
470  _tbdset.Reset();
471  _globset.Reset();
472 }
473 
474 
483 {
484  assert(Company::IsValidID(owner));
485 
486  bool first = true; // first block?
487  SigSegState state = SIGSEG_FREE; // value to return
488 
489  TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
491 
492  while (_globset.Get(&tile, &dir)) {
493  assert(_tbuset.IsEmpty());
494  assert(_tbdset.IsEmpty());
495 
496  /* After updating signal, data stored are always MP_RAILWAY with signals.
497  * Other situations happen when data are from outside functions -
498  * modification of railbits (including both rail building and removal),
499  * train entering/leaving block, train leaving depot...
500  */
501  switch (GetTileType(tile)) {
502  case MP_TUNNELBRIDGE:
503  /* 'optimization assert' - do not try to update signals when it is not needed */
505  assert(dir == INVALID_DIAGDIR || dir == ReverseDiagDir(GetTunnelBridgeDirection(tile)));
506  _tbdset.Add(tile, INVALID_DIAGDIR); // we can safely start from wormhole centre
508  break;
509 
510  case MP_RAILWAY:
511  if (IsRailDepot(tile)) {
512  /* 'optimization assert' do not try to update signals in other cases */
513  assert(dir == INVALID_DIAGDIR || dir == GetRailDepotDirection(tile));
514  _tbdset.Add(tile, INVALID_DIAGDIR); // start from depot inside
515  break;
516  }
517  [[fallthrough]];
518 
519  case MP_STATION:
520  case MP_ROAD:
522  /* only add to set when there is some 'interesting' track */
523  _tbdset.Add(tile, dir);
524  _tbdset.Add(tile + TileOffsByDiagDir(dir), ReverseDiagDir(dir));
525  break;
526  }
527  [[fallthrough]];
528 
529  default:
530  /* jump to next tile */
531  tile = tile + TileOffsByDiagDir(dir);
532  dir = ReverseDiagDir(dir);
534  _tbdset.Add(tile, dir);
535  break;
536  }
537  /* happens when removing a rail that wasn't connected at one or both sides */
538  continue; // continue the while() loop
539  }
540 
541  assert(!_tbdset.Overflowed()); // it really shouldn't overflow by these one or two items
542  assert(!_tbdset.IsEmpty()); // it wouldn't hurt anyone, but shouldn't happen too
543 
544  SigFlags flags = ExploreSegment(owner);
545 
546  if (first) {
547  first = false;
548  /* SIGSEG_FREE is set by default */
549  if (flags & SF_PBS) {
550  state = SIGSEG_PBS;
551  } else if ((flags & SF_TRAIN) || ((flags & SF_EXIT) && !(flags & SF_GREEN)) || (flags & SF_FULL)) {
552  state = SIGSEG_FULL;
553  }
554  }
555 
556  /* do not do anything when some buffer was full */
557  if (flags & SF_FULL) {
558  ResetSets(); // free all sets
559  break;
560  }
561 
563  }
564 
565  return state;
566 }
567 
568 
570 
571 
577 {
578  if (!_globset.IsEmpty()) {
580  _last_owner = INVALID_OWNER; // invalidate
581  }
582 }
583 
584 
592 void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner)
593 {
594  static const DiagDirection _search_dir_1[] = {
596  };
597  static const DiagDirection _search_dir_2[] = {
599  };
600 
601  /* do not allow signal updates for two companies in one run */
602  assert(_globset.IsEmpty() || owner == _last_owner);
603 
604  _last_owner = owner;
605 
606  _globset.Add(tile, _search_dir_1[track]);
607  _globset.Add(tile, _search_dir_2[track]);
608 
609  if (_globset.Items() >= SIG_GLOB_UPDATE) {
610  /* too many items, force update */
613  }
614 }
615 
616 
625 {
626  /* do not allow signal updates for two companies in one run */
627  assert(_globset.IsEmpty() || owner == _last_owner);
628 
629  _last_owner = owner;
630 
631  _globset.Add(tile, side);
632 
633  if (_globset.Items() >= SIG_GLOB_UPDATE) {
634  /* too many items, force update */
637  }
638 }
639 
651 {
652  assert(_globset.IsEmpty());
653  _globset.Add(tile, side);
654 
655  return UpdateSignalsInBuffer(owner);
656 }
657 
658 
668 void SetSignalsOnBothDir(TileIndex tile, Track track, Owner owner)
669 {
670  assert(_globset.IsEmpty());
671 
672  AddTrackToSignalBuffer(tile, track, owner);
673  UpdateSignalsInBuffer(owner);
674 }
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.
bool Failed() const
Did this command fail?
Definition: command_type.h:171
Definition of stuff that is very close to a company, like the company struct itself.
DECLARE_ENUM_AS_BIT_SET(GenderEthnicity) enum CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
@ INVALID_OWNER
An invalid owner.
Definition: company_type.h:29
Functions related to debugging.
#define Debug(category, level, format_string,...)
Ouptut 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.
Definition: viewport.cpp:2057
TrackStatus GetTileTrackStatus(TileIndex tile, TransportType mode, uint sub_mode, DiagDirection side)
Returns information about trackdirs and signal states.
Definition: landscape.cpp:554
TileIndexDiff TileOffsByDiagDir(DiagDirection dir)
Convert a DiagDirection to a TileIndexDiff.
Definition: map_func.h:567
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:426
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:449
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:413
bool IsOnewaySignal(Tile t, Track track)
One-way signals can't be passed the 'wrong' way.
Definition: rail_map.h:319
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:438
Axis GetCrossingRoadAxis(Tile t)
Get the road axis of a level crossing.
Definition: road_map.h:325
bool IsLevelCrossing(Tile t)
Return whether a tile is a level crossing.
Definition: road_map.h:85
A number of safeguards to prevent using unsafe methods.
static Owner _last_owner
last owner whose track was put into _globset
Definition: signal.cpp:569
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
static SmallSet< Trackdir, SIG_TBU_SIZE > _tbuset("_tbuset")
set of signals that will be updated
static const TrackdirBits _enterdir_to_trackdirbits[DIAGDIR_END]
incidating trackdirbits with given enterdir
Definition: signal.cpp:40
static SmallSet< DiagDirection, SIG_GLOB_SIZE > _globset("_globset")
set of places to be updated in following runs
static Vehicle * TrainOnTileEnum(Vehicle *v, void *)
Check whether there is a train on rail, not in a depot.
Definition: signal.cpp:192
void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner)
Add track to signal update buffer.
Definition: signal.cpp:592
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:650
static SigSegState UpdateSignalsInBuffer(Owner owner)
Updates blocks in _globset buffer.
Definition: signal.cpp:482
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:624
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:467
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:413
static SmallSet< DiagDirection, SIG_TBD_SIZE > _tbdset("_tbdset")
set of open nodes in current signal block
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:668
SigFlags
Current signal block state flags.
Definition: signal.cpp:246
@ SF_SPLIT
track merge/split found
Definition: signal.cpp:255
@ SF_GREEN2
two or more green exits found
Definition: signal.cpp:252
@ SF_EXIT2
two or more exits found
Definition: signal.cpp:250
@ SF_ENTER2
two or more signals entering the block found
Definition: signal.cpp:257
@ SF_PBS
pbs signal found
Definition: signal.cpp:254
@ SF_GREEN
green exitsignal found
Definition: signal.cpp:251
@ SF_ENTER
signal entering the block found
Definition: signal.cpp:256
@ SF_EXIT
exitsignal found
Definition: signal.cpp:249
@ SF_FULL
some of buffers was full, do not continue
Definition: signal.cpp:253
@ SF_TRAIN
train found in segment
Definition: signal.cpp:248
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:213
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:269
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.
Definition: station_map.h:503
bool IsStationTileBlocked(Tile t)
Is tile t a blocked tile?
Definition: station_map.h:431
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
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:280
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:328
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
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
SmallSet(const char *name)
Constructor - just set default values and 'name'.
Definition: signal.cpp:67
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.
Definition: vehicle_base.h:244
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:67
@ INVALID_TRACKDIR
Flag for an invalid trackdir.
Definition: track_type.h:86
TrackdirBits
Allow incrementing of Trackdir variables.
Definition: track_type.h:98
@ TRACKDIR_BIT_LEFT_S
Track left, direction south.
Definition: track_type.h:104
@ TRACKDIR_BIT_Y_NW
Track y-axis, direction north-west.
Definition: track_type.h:108
@ TRACKDIR_BIT_UPPER_E
Track upper, direction east.
Definition: track_type.h:102
@ TRACKDIR_BIT_X_NE
Track x-axis, direction north-east.
Definition: track_type.h:100
@ TRACKDIR_BIT_LOWER_E
Track lower, direction east.
Definition: track_type.h:103
@ TRACKDIR_BIT_LEFT_N
Track left, direction north.
Definition: track_type.h:111
@ TRACKDIR_BIT_RIGHT_S
Track right, direction south.
Definition: track_type.h:105
@ TRACKDIR_BIT_Y_SE
Track y-axis, direction south-east.
Definition: track_type.h:101
@ TRACKDIR_BIT_RIGHT_N
Track right, direction north.
Definition: track_type.h:112
@ TRACKDIR_BIT_UPPER_W
Track upper, direction west.
Definition: track_type.h:109
@ TRACKDIR_BIT_LOWER_W
Track lower, direction west.
Definition: track_type.h:110
@ TRACKDIR_BIT_X_SW
Track x-axis, direction south-west.
Definition: track_type.h:107
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:608
bool HasVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc)
Checks whether a vehicle is on a specific location.
Definition: vehicle.cpp:520
Functions related to vehicles.
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
Functions related to (drawing on) viewports.