OpenTTD Source 20260621-master-g720d10536d
track_func.h
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#ifndef TRACK_FUNC_H
11#define TRACK_FUNC_H
12
13#include "track_type.h"
14#include "direction_func.h"
15#include "slope_func.h"
16
24inline bool IsValidTrack(Track track)
25{
26 return track < Track::End;
27}
28
37{
38 return trackdir < Trackdir::End;
39}
40
48inline bool IsValidTrackdir(Trackdir trackdir)
49{
50 return trackdir < Trackdir::End && TRACKDIR_BIT_MASK.Test(trackdir);
51}
52
63{
64 assert(IsValidAxis(a));
65 return static_cast<Track>(to_underlying(a));
66}
67
75{
77 assert(IsValidCorner(corner));
78 return _corner_to_trackbits[corner];
79}
80
87{
88 assert(IsValidTrackdir(trackdir));
89 return trackdir;
90}
91
107{
108 if (tracks.None()) return Track::Invalid;
109
110 assert(!tracks.Any({Track::Wormhole, Track::Depot}));
111 Track first = tracks.GetNthSetBit(0).value();
112 tracks.Reset(first);
113 return first;
114}
115
131{
132 if (trackdirs.None() || trackdirs == INVALID_TRACKDIR_BIT) return Trackdir::Invalid;
133
134 assert(!trackdirs.Any({Trackdir::RvRev_NE, Trackdir::RvRev_SE, Trackdir::RvRev_SW, Trackdir::RvRev_NW}));
135 Trackdir first = trackdirs.GetNthSetBit(0).value();
136 trackdirs.Reset(first);
137 return first;
138}
139
151{
152 return tracks.GetNthSetBit(0).value_or(Track::Invalid);
153}
154
167{
168 assert(tracks.Count() == 1 && !tracks.Any({Track::Wormhole, Track::Depot}));
169 return FindFirstTrack(tracks);
170}
171
185{
186 assert(!trackdirs.Any({Trackdir::RvRev_NE, Trackdir::RvRev_SE, Trackdir::RvRev_SW, Trackdir::RvRev_NW}));
187 return trackdirs.GetNthSetBit(0).value_or(Trackdir::Invalid);
188}
189
190/*
191 * Functions describing logical relations between Tracks, TrackBits, Trackdirs
192 * TrackdirBits, Direction and DiagDirections.
193 */
194
205{
206 assert(IsValidTrack(t));
207 return static_cast<Track>(to_underlying(t) ^ 1);
208}
209
221{
222 assert(IsValidTrackdirForRoadVehicle(trackdir));
223 return static_cast<Trackdir>(to_underlying(trackdir) ^ 8);
224}
225
236{
237 assert(IsValidTrackdir(trackdir));
238 return static_cast<Track>(to_underlying(trackdir) & 0x7);
239}
240
253{
254 assert(IsValidTrack(track));
255 return static_cast<Trackdir>(track);
256}
257
272
282{
283 return static_cast<TrackBits>((bits.base() | (bits.base() >> 8)) & TRACK_BIT_ALL.base());
284}
285
293{
294 return static_cast<TrackdirBits>(bits.base() * 0x101);
295}
296
308{
309 assert(IsValidTrackdir(trackdir));
311 return _next_trackdir[trackdir];
312}
313
325{
326 assert(IsValidTrack(track));
328 return _track_crosses_tracks[track];
329}
330
344{
345 assert(IsValidTrackdirForRoadVehicle(trackdir));
347 return _trackdir_to_exitdir[trackdir];
348}
349
366{
367 assert(IsValidTrack(track));
368 assert(IsValidDiagDirection(diagdir));
370 return _track_exitdir_to_trackdir[track][diagdir];
371}
372
391{
392 assert(IsValidTrack(track));
393 assert(IsValidDiagDirection(diagdir));
395 return _track_enterdir_to_trackdir[track][diagdir];
396}
397
412
420{
421 assert(IsValidDiagDirection(diagdir));
422 return static_cast<Track>(to_underlying(diagdir) & 1);
423}
424
433{
434 assert(IsValidDiagDirection(diagdir));
436 return _dir_to_diag_trackdir[diagdir];
437}
438
456
469
485/* Note that there is no direct table for this function (there used to be),
486 * but it uses two simpler tables to achieve the result */
487
507
514inline bool IsDiagonalTrack(Track track)
515{
516 assert(IsValidTrack(track));
517 return (track == Track::X) || (track == Track::Y);
518}
519
526inline bool IsDiagonalTrackdir(Trackdir trackdir)
527{
528 assert(IsValidTrackdir(trackdir));
529 return IsDiagonalTrack(TrackdirToTrack(trackdir));
530}
531
532
540inline bool TracksOverlap(TrackBits bits)
541{
542 /* With no, or only one track, there is no overlap */
543 if (bits.Count() <= 1) return false;
544 /* We know that there are at least two tracks present. When there are more
545 * than 2 tracks, they will surely overlap. When there are two, they will
546 * always overlap unless they are lower & upper or right & left. */
547 return bits != TRACK_BIT_HORZ && bits != TRACK_BIT_VERT;
548}
549
557inline bool TrackOverlapsTracks(TrackBits tracks, Track track)
558{
559 if (tracks.Test(track)) return true;
560 return TracksOverlap(tracks | track);
561}
562
569{
571 return (to_underlying(dir) & 0x07) >= 6;
572}
573
580{
582 return (to_underlying(dir) & 0x06) == 0;
583}
584
595inline bool IsUphillTrackdir(Slope slope, Trackdir dir)
596{
598 extern const TrackdirBits _uphill_trackdirs[];
599 return _uphill_trackdirs[RemoveHalftileSlope(slope)].Test(dir);
600}
601
610{
612
613 DiagDirection diagdir = DirToDiagDir(direction);
614
615 /* Determine the diagonal direction in which we will exit this tile */
616 if (!IsDiagonalDirection(direction) && track != state_dir_table[diagdir]) {
617 diagdir = ChangeDiagDir(diagdir, DiagDirDiff::Left90);
618 }
619
620 return diagdir;
621}
622
623#endif /* TRACK_FUNC_H */
uint Count() const
Count the number of set bits.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
constexpr bool None() const
Test if none of the values are set.
constexpr Timpl & Reset()
Reset all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
std::optional< Tvalue_type > GetNthSetBit(uint n) const
Get the value of the Nth set bit.
Different functions related to conversions between directions.
bool IsValidAxis(Axis d)
Checks if an integer value is a valid Axis.
bool IsValidDiagDirection(DiagDirection d)
Checks if an integer value is a valid DiagDirection.
DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
Applies a difference on a DiagDirection.
bool IsValidDirection(Direction d)
Checks if an integer value is a valid Direction.
bool IsDiagonalDirection(Direction dir)
Checks if a given Direction is diagonal.
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
EnumIndexArray< T, DiagDirection, DiagDirection::End > DiagDirectionIndexArray
Array with DiagDirection as index.
Direction
Defines the 8 directions on the map.
@ Left90
90 degrees left
Axis
Enumeration for the two axis X and Y.
DiagDirection
Enumeration for diagonal directions.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Definition enum_type.hpp:21
Functions related to slopes.
static constexpr Slope RemoveHalftileSlope(Slope s)
Removes a halftile slope from a slope.
Definition slope_func.h:60
static constexpr bool IsValidCorner(Corner corner)
Rangecheck for Corner enumeration.
Definition slope_func.h:24
Corner
Enumeration of tile corners.
Definition slope_type.h:21
Slope
Enumeration for the slope-type.
Definition slope_type.h:53
EnumIndexArray< T, Corner, CORNER_END > CornerIndexArray
Array with Corner as index.
Definition slope_type.h:35
const TrackIndexArray< DiagDirectionIndexArray< Trackdir > > _track_enterdir_to_trackdir
Maps a track and an (4-way) dir to the trackdir that represents the track with the entry in the given...
const TrackIndexArray< TrackdirBits > _track_crosses_trackdirs
Maps a trackdir to all trackdirs that make 90 deg turns with it.
const DiagDirectionIndexArray< TrackdirBits > _exitdir_reaches_trackdirs
Maps a diagonal direction to the all trackdirs that are connected to any track entering in this direc...
const CornerIndexArray< TrackBits > _corner_to_trackbits
Maps a single horizontal/vertical trackbit that is in a specific tile corner.
const TrackdirIndexArray< DiagDirection > _trackdir_to_exitdir
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
const TrackdirIndexArray< Trackdir > _next_trackdir
Next trackdir to use when moving to a new tile for each current trackdir.
const DiagDirectionIndexArray< Trackdir > _dir_to_diag_trackdir
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
const TrackIndexArray< DirectionIndexArray< Trackdir > > _track_direction_to_trackdir
Maps a track and a full (8-way) direction to the trackdir that represents the track running in the gi...
const TrackIndexArray< TrackBits > _track_crosses_tracks
Maps a track to all tracks that make 90 deg turns with it.
const TrackIndexArray< DiagDirectionIndexArray< Trackdir > > _track_exitdir_to_trackdir
Maps a track and an (4-way) dir to the trackdir that represents the track with the exit in the given ...
Trackdir TrackToTrackdir(Track track)
Returns a Trackdir for the given Track.
Definition track_func.h:252
Track TrackdirToTrack(Trackdir trackdir)
Returns the Track that a given Trackdir represents.
Definition track_func.h:235
Track TrackToOppositeTrack(Track t)
Find the opposite track to a given track.
Definition track_func.h:204
bool TrackOverlapsTracks(TrackBits tracks, Track track)
Check if a given track is contained within or overlaps some other tracks.
Definition track_func.h:557
bool IsUphillTrackdir(Slope slope, Trackdir dir)
Checks whether a trackdir on a specific slope is going uphill.
Definition track_func.h:595
TrackBits CornerToTrackBits(Corner corner)
Returns a single horizontal/vertical trackbit that is in a specific tile corner.
Definition track_func.h:74
bool IsDiagonalTrack(Track track)
Checks if a given Track is diagonal.
Definition track_func.h:514
TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
Converts TrackBits to TrackdirBits while allowing both directions.
Definition track_func.h:292
DiagDirection VehicleExitDir(Direction direction, TrackBits track)
Determine the side in which the vehicle will leave the tile.
Definition track_func.h:609
bool IsReversingRoadTrackdir(Trackdir dir)
Checks whether the trackdir means that we are reversing.
Definition track_func.h:568
Track TrackBitsToTrack(TrackBits tracks)
Converts TrackBits to Track.
Definition track_func.h:166
TrackBits TrackCrossesTracks(Track track)
Maps a track to all tracks that make 90 deg turns with it.
Definition track_func.h:324
Trackdir NextTrackdir(Trackdir trackdir)
Maps a trackdir to the trackdir that you will end up on if you go straight ahead.
Definition track_func.h:307
Trackdir ReverseTrackdir(Trackdir trackdir)
Maps a trackdir to the reverse trackdir.
Definition track_func.h:220
bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition track_func.h:540
Track RemoveFirstTrack(TrackBits &tracks)
Removes first Track from TrackBits and returns it.
Definition track_func.h:106
Trackdir TrackDirectionToTrackdir(Track track, Direction dir)
Maps a track and a full (8-way) direction to the trackdir that represents the track running in the gi...
Definition track_func.h:405
bool IsValidTrackdir(Trackdir trackdir)
Checks if a Trackdir is valid for non-road vehicles.
Definition track_func.h:48
Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
Returns first Trackdir from TrackdirBits or Trackdir::Invalid.
Definition track_func.h:184
bool IsValidTrackdirForRoadVehicle(Trackdir trackdir)
Checks if a Trackdir is valid for road vehicles.
Definition track_func.h:36
TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir)
Maps a trackdir to all trackdirs that make 90 deg turns with it.
Definition track_func.h:501
TrackdirBits TrackdirReachesTrackdirs(Trackdir trackdir)
Maps a trackdir to the trackdirs that can be reached from it (ie, when entering the next tile.
Definition track_func.h:479
TrackdirBits DiagdirReachesTrackdirs(DiagDirection diagdir)
Returns all trackdirs that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:450
bool IsValidTrack(Track track)
Checks if a Track is valid.
Definition track_func.h:24
Track FindFirstTrack(TrackBits tracks)
Returns first Track from TrackBits or Track::Invalid.
Definition track_func.h:150
Trackdir RemoveFirstTrackdir(TrackdirBits &trackdirs)
Removes first Trackdir from TrackdirBits and returns it.
Definition track_func.h:130
Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir)
Maps a track and an (4-way) dir to the trackdir that represents the track with the entry in the given...
Definition track_func.h:390
bool IsDiagonalTrackdir(Trackdir trackdir)
Checks if a given Trackdir is diagonal.
Definition track_func.h:526
TrackBits DiagdirReachesTracks(DiagDirection diagdir)
Returns all tracks that can be reached when entering a tile from a given (diagonal) direction.
Definition track_func.h:468
bool IsStraightRoadTrackdir(Trackdir dir)
Checks whether the given trackdir is a straight road.
Definition track_func.h:579
Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir)
Maps a track and an (4-way) dir to the trackdir that represents the track with the exit in the given ...
Definition track_func.h:365
Trackdir DiagDirToDiagTrackdir(DiagDirection diagdir)
Maps a (4-way) direction to the diagonal trackdir that runs in that direction.
Definition track_func.h:432
TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
Maps a Trackdir to the corresponding TrackdirBits value.
Definition track_func.h:86
Track AxisToTrack(Axis a)
Convert an Axis to the corresponding Track Axis::X -> Track::X Axis::Y -> Track::Y Uses the fact that...
Definition track_func.h:62
DiagDirection TrackdirToExitdir(Trackdir trackdir)
Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir.
Definition track_func.h:343
TrackdirBits TrackToTrackdirBits(Track track)
Returns a TrackdirBit mask from a given Track.
Definition track_func.h:267
Track DiagDirToDiagTrack(DiagDirection diagdir)
Maps a DiagDirection to the associated diagonal Track.
Definition track_func.h:419
TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
Discards all directional information from a TrackdirBits value.
Definition track_func.h:281
All types related to tracks.
EnumIndexArray< T, Track, Track::End > TrackIndexArray
Array with Track as index.
Definition track_type.h:40
static constexpr TrackBits TRACK_BIT_HORZ
Upper and lower track.
Definition track_type.h:46
EnumBitSet< Trackdir, uint16_t > TrackdirBits
Bitset of Trackdir elements.
Definition track_type.h:93
EnumBitSet< Track, uint8_t > TrackBits
Bitset of Track elements.
Definition track_type.h:43
static constexpr TrackBits TRACK_BIT_ALL
All possible tracks.
Definition track_type.h:52
static constexpr TrackdirBits INVALID_TRACKDIR_BIT
Marker for an invalid TrackdirBits value.
Definition track_type.h:102
Trackdir
Enumeration for tracks and directions.
Definition track_type.h:63
@ Invalid
Flag for an invalid trackdir.
Definition track_type.h:82
@ End
End marker.
Definition track_type.h:81
static constexpr TrackBits TRACK_BIT_VERT
Left and right track.
Definition track_type.h:47
static constexpr TrackdirBits TRACKDIR_BIT_MASK
Bitset of valid non-road vehicle trackdirs/.
Definition track_type.h:96
EnumIndexArray< T, Trackdir, Trackdir::End > TrackdirIndexArray
Array with Trackdir as index.
Definition track_type.h:90
Track
These are used to specify a single track.
Definition track_type.h:19
@ X
Track along the x-axis (north-east to south-west).
Definition track_type.h:21
@ Upper
Track in the upper corner of the tile (north).
Definition track_type.h:23
@ Invalid
Flag for an invalid track.
Definition track_type.h:32
@ Y
Track along the y-axis (north-west to south-east).
Definition track_type.h:22
@ End
End marker (of regular track bits).
Definition track_type.h:27
@ Right
Track in the right corner of the tile (east).
Definition track_type.h:26
@ Left
Track in the left corner of the tile (west).
Definition track_type.h:25
@ Lower
Track in the lower corner of the tile (south).
Definition track_type.h:24