Codechange: make Trackdir a scoped enum and TrackdirBits an EnumBitSet (#15696)

This commit is contained in:
Peter Nelson
2026-06-11 14:40:15 +01:00
committed by GitHub
parent 09a475f30a
commit 0149e4a349
37 changed files with 345 additions and 415 deletions
+5 -5
View File
@@ -133,7 +133,7 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
if (!IsPlainRailTile(t)) return tracks;
TrackdirBits neighbour_tdb = TRACKDIR_BIT_NONE;
TrackdirBits neighbour_tdb{};
for (DiagDirection d = DiagDirection::Begin; d < DiagDirection::End; d++) {
/* If the neighbour tile is either not electrified or has no tracks that can be reached
* from this tile, mark all trackdirs that can be reached from the neighbour tile
@@ -155,7 +155,7 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
if (tracks == TRACK_BIT_CROSS || !TracksOverlap(tracks)) {
/* If the tracks form either a diagonal crossing or don't overlap, both
* trackdirs have to be marked to mask the corresponding track bit. */
mask = static_cast<TrackBits>(~((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_ALL.base()));
mask = static_cast<TrackBits>(~((neighbour_tdb.base() & (neighbour_tdb.base() >> 8)) & TRACK_BIT_ALL.base()));
/* If that results in no masked tracks and it is not a diagonal crossing,
* require only one marked trackdir to mask. */
if (tracks != TRACK_BIT_CROSS && mask == TRACK_BIT_ALL) mask = TrackdirBitsToTrackBits(neighbour_tdb).Flip(TRACK_BIT_ALL);
@@ -164,10 +164,10 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks)
mask = TrackdirBitsToTrackBits(neighbour_tdb).Flip(TRACK_BIT_ALL);
/* If that results in an empty set, require both trackdirs for diagonal track. */
if (!tracks.Any(mask)) {
if ((neighbour_tdb & TRACKDIR_BIT_X_NE) == 0 || (neighbour_tdb & TRACKDIR_BIT_X_SW) == 0) mask.Set(Track::X);
if ((neighbour_tdb & TRACKDIR_BIT_Y_NW) == 0 || (neighbour_tdb & TRACKDIR_BIT_Y_SE) == 0) mask.Set(Track::Y);
if (!neighbour_tdb.Test(Trackdir::X_NE) || !neighbour_tdb.Test(Trackdir::X_SW)) mask.Set(Track::X);
if (!neighbour_tdb.Test(Trackdir::Y_NW) || !neighbour_tdb.Test(Trackdir::Y_SE)) mask.Set(Track::Y);
/* If that still is not enough, require both trackdirs for any track. */
if (!tracks.Any(mask)) mask = static_cast<TrackBits>(~((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_ALL.base()));
if (!tracks.Any(mask)) mask = static_cast<TrackBits>(~((neighbour_tdb.base() & (neighbour_tdb.base() >> 8)) & TRACK_BIT_ALL.base()));
}
}
+2 -2
View File
@@ -27,7 +27,7 @@ static const std::string_view trackdir_names[] = {
*/
std::string ValueStr(Trackdir td)
{
return fmt::format("{} ({})", to_underlying(td), ItemAt(td, trackdir_names, "UNK", INVALID_TRACKDIR, "INV"));
return fmt::format("{} ({})", to_underlying(td), ItemAt(td, trackdir_names, "UNK", Trackdir::Invalid, "INV"));
}
/**
@@ -37,7 +37,7 @@ std::string ValueStr(Trackdir td)
*/
std::string ValueStr(TrackdirBits td_bits)
{
return fmt::format("{} ({})", to_underlying(td_bits), ComposeName(td_bits, trackdir_names, "UNK", INVALID_TRACKDIR_BIT, "INV"));
return fmt::format("{} ({})", td_bits.base(), ComposeName(td_bits, trackdir_names, "UNK", INVALID_TRACKDIR_BIT, "INV"));
}
+14 -38
View File
@@ -58,34 +58,21 @@ inline std::string_view ItemAt(E idx, std::span<const std::string_view> names, s
/**
* Helper template function that returns compound bitfield name that is
* concatenation of names of each set bit in the given value
* or invalid_name when index == invalid_index
* or unknown_name when index is out of bounds.
* @param value The bitmask of values.
* @param names Span of names to index.
* @param unknown_name The default value when the index does not exist.
* @param invalid_index The invalid value to consider.
* @param invalid_name The value to output when the invalid value is given.
* @return The composed name.
*/
template <typename E>
inline std::string ComposeName(E value, std::span<const std::string_view> names, std::string_view unknown_name, E invalid_index, std::string_view invalid_name)
template <typename Tbitset>
inline std::string ComposeName(Tbitset value, std::span<const std::string_view> names, std::string_view unknown_name)
{
if (value.None()) return "<none>";
std::string out;
if (value == invalid_index) {
out = invalid_name;
} else if (value == 0) {
out = "<none>";
} else {
for (size_t i = 0; i < std::size(names); i++) {
if ((value & (1 << i)) == 0) continue;
out += (!out.empty() ? "+" : "");
out += names[i];
value &= ~static_cast<E>(1 << i);
}
if (value != 0) {
out += (!out.empty() ? "+" : "");
out += unknown_name;
}
for (auto index : value) {
if (!out.empty()) out += "+";
out += to_underlying(index) < std::size(names) ? names[to_underlying(index)] : unknown_name;
}
return out;
}
@@ -93,31 +80,20 @@ inline std::string ComposeName(E value, std::span<const std::string_view> names,
/**
* Helper template function that returns compound bitfield name that is
* concatenation of names of each set bit in the given value
* or invalid_name when value == invalid_index
* or unknown_name when index is out of bounds.
* @param value The bitmask of values.
* @param names Span of names to index.
* @param unknown_name The default value when the index does not exist.
* @param invalid_value The invalid value to consider.
* @param invalid_name The value to output when the invalid value is given.
* @return The composed name.
*/
template <typename E>
inline std::string ComposeName(E value, std::span<const std::string_view> names, std::string_view unknown_name)
template <typename Tbitset>
inline std::string ComposeName(Tbitset value, std::span<const std::string_view> names, std::string_view unknown_name, Tbitset invalid_value, std::string_view invalid_name)
{
std::string out;
if (value.base() == 0) {
out = "<none>";
} else {
for (size_t i = 0; i < std::size(names); ++i) {
if (!value.Test(static_cast<E::EnumType>(i))) continue;
out += (!out.empty() ? "+" : "");
out += names[i];
value.Reset(static_cast<E::EnumType>(i));
}
if (value.base() != 0) {
out += (!out.empty() ? "+" : "");
out += unknown_name;
}
}
return out;
if (value == invalid_value) return std::string{invalid_name};
return ComposeName(value, names, unknown_name);
}
std::string ValueStr(Trackdir td);
+13 -13
View File
@@ -75,9 +75,9 @@ struct CFollowTrackT {
this->veh_owner = o;
/* don't worry, all is inlined so compiler should remove unnecessary initializations */
this->old_tile = INVALID_TILE;
this->old_td = INVALID_TRACKDIR;
this->old_td = Trackdir::Invalid;
this->new_tile = INVALID_TILE;
this->new_td_bits = TRACKDIR_BIT_NONE;
this->new_td_bits.Reset();
this->exitdir = DiagDirection::Invalid;
this->is_station = false;
this->is_bridge = false;
@@ -134,7 +134,7 @@ struct CFollowTrackT {
if (this->IsTram() && this->GetSingleTramBit(this->old_tile) != DiagDirection::Invalid) return true; // Skip the check for single tram bits
const RoadTramType sub_mode = (IsRoadTT() && this->veh != nullptr) ? (this->IsTram() ? RoadTramType::Tram : RoadTramType::Road) : RoadTramType::Invalid;
const TrackdirBits old_tile_valid_dirs = GetTileTrackStatus(this->old_tile, TT(), sub_mode).trackdirs;
return (old_tile_valid_dirs & TrackdirToTrackdirBits(this->old_td)) != TRACKDIR_BIT_NONE;
return old_tile_valid_dirs.Any(TrackdirToTrackdirBits(this->old_td));
}());
this->exitdir = TrackdirToExitdir(this->old_td);
@@ -143,7 +143,7 @@ struct CFollowTrackT {
this->FollowTileExit();
if (!this->QueryNewTileTrackStatus()) return TryReverse();
this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
if (this->new_td_bits == TRACKDIR_BIT_NONE || !this->CanEnterNewTile()) {
if (this->new_td_bits.None() || !this->CanEnterNewTile()) {
/* In case we can't enter the next tile, but are
* a normal road vehicle, then we can actually
* try to reverse as this is the end of the road.
@@ -160,13 +160,13 @@ struct CFollowTrackT {
/* CanEnterNewTile already set a reason.
* Do NOT overwrite it (important for example for EC_RAIL_ROAD_TYPE).
* Only set a reason if CanEnterNewTile was not called */
if (this->new_td_bits == TRACKDIR_BIT_NONE) this->err = EC_NO_WAY;
if (this->new_td_bits.None()) this->err = EC_NO_WAY;
return false;
}
if ((!IsRailTT() && !Allow90degTurns()) || (IsRailTT() && Rail90DegTurnDisallowed(GetTileRailType(this->old_tile), GetTileRailType(this->new_tile), !Allow90degTurns()))) {
this->new_td_bits &= ~TrackdirCrossesTrackdirs(this->old_td);
if (this->new_td_bits == TRACKDIR_BIT_NONE) {
this->new_td_bits.Reset(TrackdirCrossesTrackdirs(this->old_td));
if (this->new_td_bits.None()) {
this->err = EC_90DEG;
return false;
}
@@ -183,7 +183,7 @@ struct CFollowTrackT {
TileIndexDiff diff = TileOffsByDiagDir(this->exitdir);
for (TileIndex tile = this->new_tile - diff * this->tiles_skipped; tile != this->new_tile; tile += diff) {
if (HasStationReservation(tile)) {
this->new_td_bits = TRACKDIR_BIT_NONE;
this->new_td_bits.Reset();
this->err = EC_RESERVED;
return false;
}
@@ -192,12 +192,12 @@ struct CFollowTrackT {
TrackBits reserved = GetReservedTrackbits(this->new_tile);
/* Mask already reserved trackdirs. */
this->new_td_bits &= ~TrackBitsToTrackdirBits(reserved);
this->new_td_bits.Reset(TrackBitsToTrackdirBits(reserved));
/* Mask out all trackdirs that conflict with the reservation. */
for (Track t : TrackdirBitsToTrackBits(this->new_td_bits)) {
if (TracksOverlap(reserved | t)) this->new_td_bits &= ~TrackToTrackdirBits(t);
if (TracksOverlap(reserved | t)) this->new_td_bits.Reset(TrackToTrackdirBits(t));
}
if (this->new_td_bits == TRACKDIR_BIT_NONE) {
if (this->new_td_bits.None()) {
this->err = EC_RESERVED;
return false;
}
@@ -255,7 +255,7 @@ protected:
} else {
this->new_td_bits = GetTileTrackStatus(this->new_tile, TT(), RoadTramType::Invalid).trackdirs;
}
return (this->new_td_bits != TRACKDIR_BIT_NONE);
return this->new_td_bits.Any();
}
/**
@@ -457,7 +457,7 @@ protected:
/* set new trackdir bits to all reachable trackdirs */
QueryNewTileTrackStatus();
this->new_td_bits &= DiagdirReachesTrackdirs(this->exitdir);
if (this->new_td_bits != TRACKDIR_BIT_NONE) {
if (this->new_td_bits.Any()) {
/* we have some trackdirs reachable after reversal */
return true;
}
+3 -3
View File
@@ -63,18 +63,18 @@ inline TrackdirBits GetTrackdirBitsForRoad(TileIndex tile, RoadTramType rtt)
{
TrackdirBits bits = GetTileTrackStatus(tile, TRANSPORT_ROAD, rtt).trackdirs;
if (rtt == RoadTramType::Tram && bits == TRACKDIR_BIT_NONE) {
if (rtt == RoadTramType::Tram && bits.None()) {
if (IsNormalRoadTile(tile)) {
RoadBits rb = GetRoadBits(tile, RoadTramType::Tram);
switch (rb.base()) {
case RoadBits{RoadBit::NE}.base():
case RoadBits{RoadBit::SW}.base():
bits = TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW;
bits = {Trackdir::X_NE, Trackdir::X_SW};
break;
case RoadBits{RoadBit::NW}.base():
case RoadBits{RoadBit::SE}.base():
bits = TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE;
bits = {Trackdir::Y_NW, Trackdir::Y_SE};
break;
default: break;
+2 -2
View File
@@ -153,7 +153,7 @@ public:
tiles_to_check.pop_back();
const TrackdirBits valid_dirs = TrackBitsToTrackdirBits(GetWaterTracks(tile));
if (valid_dirs == TRACKDIR_BIT_NONE) continue;
if (valid_dirs.None()) continue;
WaterRegionPatchLabel &tile_patch = (*this->data.tile_patch_labels)[this->GetLocalIndex(tile)];
if (tile_patch != INVALID_WATER_REGION_PATCH) continue;
@@ -162,7 +162,7 @@ public:
highest_assigned_label = current_label;
increase_label = true;
for (const Trackdir dir : SetTrackdirBitIterator(valid_dirs)) {
for (Trackdir dir : valid_dirs) {
/* By using a TrackFollower we "play by the same rules" as the actual ship pathfinder */
CFollowTrackWater ft;
if (ft.Follow(tile, dir)) {
+1 -1
View File
@@ -43,7 +43,7 @@ bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir);
* @param trackdirs available trackdirs on the new tile (to choose from)
* @param path_found [out] Whether a path has been found (true) or has been guessed (false)
* @param path_cache Cache of a previously chosen path.
* @return the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
* @return the best trackdir for next turn or Trackdir::Invalid if the path could not be found
*/
Trackdir YapfRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDirection enterdir, TrackdirBits trackdirs, bool &path_found, RoadVehPathCache &path_cache);
+2 -3
View File
@@ -235,9 +235,8 @@ public:
*/
inline void AddMultipleNodes(Node *parent, const TrackFollower &tf)
{
bool is_choice = (KillFirstBit(tf.new_td_bits) != TRACKDIR_BIT_NONE);
for (TrackdirBits rtds = tf.new_td_bits; rtds != TRACKDIR_BIT_NONE; rtds = KillFirstBit(rtds)) {
Trackdir td = (Trackdir)FindFirstBit(rtds);
bool is_choice = tf.new_td_bits.Count() > 1;
for (Trackdir td : tf.new_td_bits) {
Node &n = Yapf().CreateNewNode();
n.Set(parent, tf.new_tile, td, is_choice);
Yapf().AddNewNode(n, tf);
+5 -6
View File
@@ -37,9 +37,8 @@ public:
*/
void SetOrigin(TileIndex tile, TrackdirBits trackdirs)
{
bool is_choice = (KillFirstBit(trackdirs) != TRACKDIR_BIT_NONE);
for (TrackdirBits tdb = trackdirs; tdb != TRACKDIR_BIT_NONE; tdb = KillFirstBit(tdb)) {
Trackdir td = (Trackdir)FindFirstBit(tdb);
bool is_choice = trackdirs.Count() > 1;
for (Trackdir td : trackdirs) {
Node &node = Yapf().CreateNewNode();
node.Set(nullptr, tile, td, is_choice);
Yapf().AddStartupNode(node);
@@ -72,14 +71,14 @@ public:
* @param reverse_penalty The penalty for reversing.
*/
void SetOrigin(TileIndex forward_tile, Trackdir forward_td, TileIndex reverse_tile = INVALID_TILE,
Trackdir reverse_td = INVALID_TRACKDIR, int reverse_penalty = 0)
Trackdir reverse_td = Trackdir::Invalid, int reverse_penalty = 0)
{
if (forward_tile != INVALID_TILE && forward_td != INVALID_TRACKDIR) {
if (forward_tile != INVALID_TILE && forward_td != Trackdir::Invalid) {
Node &node = Yapf().CreateNewNode();
node.Set(nullptr, forward_tile, forward_td, false);
Yapf().AddStartupNode(node);
}
if (reverse_tile != INVALID_TILE && reverse_td != INVALID_TRACKDIR) {
if (reverse_tile != INVALID_TILE && reverse_td != Trackdir::Invalid) {
Node &node = Yapf().CreateNewNode();
node.Set(nullptr, reverse_tile, reverse_td, false);
node.cost = reverse_penalty;
+9 -9
View File
@@ -35,7 +35,7 @@ protected:
TileType tile_type;
RailType rail_type;
TILE() : tile(INVALID_TILE), td(INVALID_TRACKDIR), tile_type(TileType::Void), rail_type(INVALID_RAILTYPE) { }
TILE() : tile(INVALID_TILE), td(Trackdir::Invalid), tile_type(TileType::Void), rail_type(INVALID_RAILTYPE) { }
TILE(TileIndex tile, Trackdir td) : tile(tile), td(td), tile_type(GetTileType(tile)), rail_type(GetTileRailType(tile)) { }
};
@@ -106,7 +106,7 @@ public:
assert(IsValidTrackdir(td2));
int cost = 0;
if (TrackFollower::Allow90degTurns()
&& HasTrackdir(TrackdirCrossesTrackdirs(td1), td2)) {
&& TrackdirCrossesTrackdirs(td1).Test(td2)) {
/* 90-deg curve penalty */
cost += Yapf().PfGetSettings().rail_curve90_penalty;
} else if (td2 != NextTrackdir(td1)) {
@@ -295,7 +295,7 @@ public:
{
assert(!n.flags_u.flags_s.target_seen);
assert(follower->new_tile == n.key.tile);
assert((HasTrackdir(follower->new_td_bits, n.key.td)));
assert(follower->new_td_bits.Test(n.key.td));
/* Does the node have some parent node? */
bool has_parent = (n.parent != nullptr);
@@ -437,14 +437,14 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
t = ft.new_tile;
if (t == cur.tile || --max_tiles == 0) {
/* We looped back on ourself or found another loop, bail out. */
td = INVALID_TRACKDIR;
td = Trackdir::Invalid;
break;
}
if (KillFirstBit(ft.new_td_bits) != TRACKDIR_BIT_NONE) {
if (ft.new_td_bits.Count() > 1) {
/* We encountered a junction; it's going to be too complex to
* handle this perfectly, so just bail out. There is no simple
* free path, so try the other possibilities. */
td = INVALID_TRACKDIR;
td = Trackdir::Invalid;
break;
}
td = RemoveFirstTrackdir(&ft.new_td_bits);
@@ -455,7 +455,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
/* In the case this platform is (possibly) occupied we add penalty so the
* other platforms of this waypoint are evaluated as well, i.e. we assume
* that there is a red signal in the waypoint when it's occupied. */
if (td == INVALID_TRACKDIR ||
if (td == Trackdir::Invalid ||
!IsSafeWaitingPosition(v, t, td, true, _settings_game.pf.forbid_90_deg) ||
!IsWaitingPositionFree(v, t, td, _settings_game.pf.forbid_90_deg)) {
extra_cost += Yapf().PfGetSettings().rail_lastred_penalty;
@@ -521,14 +521,14 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
}
/* Check if the next tile is not a choice. */
if (KillFirstBit(follower_local.new_td_bits) != TRACKDIR_BIT_NONE) {
if (follower_local.new_td_bits.Count() > 1) {
/* More than one segment will follow. Close this one. */
end_segment_reason.Set(EndSegmentReason::ChoiceFollows);
break;
}
/* Gather the next tile/trackdir/tile_type/rail_type. */
TILE next(follower_local.new_tile, (Trackdir)FindFirstBit(follower_local.new_td_bits));
TILE next(follower_local.new_tile, follower_local.new_td_bits.GetNthSetBit(0).value());
if (TrackFollower::DoTrackMasking() && IsTileType(next.tile, TileType::Railway)) {
if (HasSignalOnTrackdir(next.tile, next.td) && IsPbsSignal(GetSignalType(next.tile, TrackdirToTrack(next.td)))) {
+1 -1
View File
@@ -179,7 +179,7 @@ public:
return IsRailDepotTile(tile);
}
return (tile == this->dest_tile) && HasTrackdir(this->dest_trackdirs, td);
return (tile == this->dest_tile) && this->dest_trackdirs.Test(td);
}
/** @copydoc CYapfBaseT::PfCalcEstimateFunc */
+2 -2
View File
@@ -23,7 +23,7 @@ struct CYapfNodeKeyExitDir {
{
this->tile = tile;
this->td = td;
this->exitdir = (this->td == INVALID_TRACKDIR) ? DiagDirection::Invalid : TrackdirToExitdir(this->td);
this->exitdir = (this->td == Trackdir::Invalid) ? DiagDirection::Invalid : TrackdirToExitdir(this->td);
}
inline int CalcHash() const
@@ -47,7 +47,7 @@ struct CYapfNodeKeyExitDir {
struct CYapfNodeKeyTrackDir : public CYapfNodeKeyExitDir {
inline int CalcHash() const
{
return this->td | (this->tile.base() << 4);
return to_underlying(this->td) | (this->tile.base() << 4);
}
inline bool operator==(const CYapfNodeKeyTrackDir &other) const
+5 -5
View File
@@ -32,7 +32,7 @@ struct CYapfRailSegmentKey {
inline void Set(const CYapfNodeKeyTrackDir &node_key)
{
this->value = (node_key.tile.base() << 4) | node_key.td;
this->value = (node_key.tile.base() << 4) | to_underlying(node_key.td);
}
inline int32_t CalcHash() const
@@ -47,7 +47,7 @@ struct CYapfRailSegmentKey {
inline Trackdir GetTrackdir() const
{
return (Trackdir)(this->value & 0x0F);
return static_cast<Trackdir>(this->value & 0x0F);
}
inline bool operator==(const CYapfRailSegmentKey &other) const
@@ -68,10 +68,10 @@ struct CYapfRailSegment {
CYapfRailSegmentKey key;
TileIndex last_tile = INVALID_TILE;
Trackdir last_td = INVALID_TRACKDIR;
Trackdir last_td = Trackdir::Invalid;
int cost = -1;
TileIndex last_signal_tile = INVALID_TILE;
Trackdir last_signal_td = INVALID_TRACKDIR;
Trackdir last_signal_td = Trackdir::Invalid;
EndSegmentReasons end_segment_reason{};
CYapfRailSegment *hash_next = nullptr;
@@ -186,7 +186,7 @@ struct CYapfRailNode : CYapfNodeT<CYapfNodeKeyTrackDir, CYapfRailNode> {
if (!follower.Follow(cur, cur_td)) break;
cur = follower.new_tile;
assert(KillFirstBit(follower.new_td_bits) == TRACKDIR_BIT_NONE);
assert(follower.new_td_bits.Count() == 1);
cur_td = FindFirstTrackdir(follower.new_td_bits);
}
+5 -5
View File
@@ -459,15 +459,15 @@ public:
/* set origin and destination nodes */
PBSTileInfo origin = FollowTrainReservation(v);
Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, INVALID_TRACKDIR, 1);
Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, Trackdir::Invalid, 1);
Yapf().SetTreatFirstRedTwoWaySignalAsEOL(true);
Yapf().SetDestination(v);
/* find the best path */
path_found = Yapf().FindPath(v);
/* if path not found - return INVALID_TRACKDIR */
Trackdir next_trackdir = INVALID_TRACKDIR;
/* if path not found - return Trackdir::Invalid */
Trackdir next_trackdir = Trackdir::Invalid;
Node *node = Yapf().GetBestNode();
if (node != nullptr) {
/* reserve till end of path */
@@ -485,7 +485,7 @@ public:
/* If the best PF node has no parent, then there is no (valid) best next trackdir to return.
* This occurs when the PF is called while the train is already at its destination. */
if (prev == nullptr) return INVALID_TRACKDIR;
if (prev == nullptr) return Trackdir::Invalid;
/* return trackdir from the best origin node (one of start nodes) */
Node &best_next_node = *prev;
@@ -600,7 +600,7 @@ Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdi
? CYapfRailNo90::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest)
: CYapfRail::stChooseRailTrack(v, tile, enterdir, tracks, path_found, reserve_track, target, dest);
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : FindFirstTrack(tracks);
return (td_ret != Trackdir::Invalid) ? TrackdirToTrack(td_ret) : FindFirstTrack(tracks);
}
bool YapfTrainCheckReverse(const Train *v)
+2 -2
View File
@@ -60,7 +60,7 @@ public:
this->end_tile = end_tile;
Node &node = Yapf().CreateNewNode();
node.Set(nullptr, start_tile, INVALID_TRACKDIR, false);
node.Set(nullptr, start_tile, Trackdir::Invalid, false);
Yapf().AddStartupNode(node);
}
@@ -92,7 +92,7 @@ public:
const TileIndex t = old_node.GetTile() + TileOffsByDiagDir(d);
if (IsValidTile(t) && RiverFlowsDown(old_node.GetTile(), t)) {
Node &node = Yapf().CreateNewNode();
node.Set(&old_node, t, INVALID_TRACKDIR, true);
node.Set(&old_node, t, Trackdir::Invalid, true);
Yapf().AddNewNode(node, RiverBuilderFollower{});
}
}
+7 -7
View File
@@ -145,9 +145,9 @@ public:
if (!follower_local.Follow(tile, trackdir)) break;
/* if there are more trackdirs available & reachable, we are at the end of segment */
if (KillFirstBit(follower_local.new_td_bits) != TRACKDIR_BIT_NONE) break;
if (follower_local.new_td_bits.Count() > 1) break;
Trackdir new_td = (Trackdir)FindFirstBit(follower_local.new_td_bits);
Trackdir new_td = follower_local.new_td_bits.GetNthSetBit(0).value();
/* stop if RV is on simple loop with no junctions */
if (follower_local.new_tile == n.key.tile && new_td == n.key.td) return false;
@@ -284,7 +284,7 @@ public:
(this->non_artic || IsDriveThroughStopTile(tile));
}
return tile == this->dest_tile && HasTrackdir(this->dest_trackdirs, td);
return tile == this->dest_tile && this->dest_trackdirs.Test(td);
}
/** @copydoc CYapfBaseT::PfCalcEstimateFunc */
@@ -365,8 +365,8 @@ public:
/* find the best path */
path_found = Yapf().FindPath(v);
/* if path not found - return INVALID_TRACKDIR */
Trackdir next_trackdir = INVALID_TRACKDIR;
/* if path not found - return Trackdir::Invalid */
Trackdir next_trackdir = Trackdir::Invalid;
Node *node = Yapf().GetBestNode();
if (node != nullptr) {
uint steps = 0;
@@ -459,7 +459,7 @@ Trackdir YapfRoadVehicleChooseTrack(const RoadVehicle *v, TileIndex tile, DiagDi
{
Trackdir td_ret = CYapfRoad::stChooseRoadTrack(v, tile, enterdir, path_found, path_cache);
return (td_ret != INVALID_TRACKDIR) ? td_ret : (Trackdir)FindFirstBit(trackdirs);
return (td_ret != Trackdir::Invalid) ? td_ret : trackdirs.GetNthSetBit(0).value();
}
FindDepotData YapfRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_distance)
@@ -467,7 +467,7 @@ FindDepotData YapfRoadVehicleFindNearestDepot(const RoadVehicle *v, int max_dist
TileIndex tile = v->tile;
Trackdir trackdir = v->GetVehicleTrackdir();
if (!HasTrackdir(GetTrackdirBitsForRoad(tile, GetRoadTramType(v->roadtype)), trackdir)) {
if (!GetTrackdirBitsForRoad(tile, GetRoadTramType(v->roadtype)).Test(trackdir)) {
return FindDepotData();
}
+23 -25
View File
@@ -86,7 +86,7 @@ public:
if (this->dest_station != StationID::Invalid()) return IsDockingTile(tile) && IsShipDestinationTile(tile, this->dest_station);
return tile == this->dest_tile && ((this->dest_trackdirs & TrackdirToTrackdirBits(td)) != TRACKDIR_BIT_NONE);
return tile == this->dest_tile && this->dest_trackdirs.Any(TrackdirToTrackdirBits(td));
}
/** @copydoc CYapfBaseT::PfCalcEstimateFunc */
@@ -159,9 +159,7 @@ public:
*/
static Trackdir GetRandomTrackdir(TrackdirBits trackdirs)
{
const int strip_amount = RandomRange(CountBits(trackdirs));
for (int s = 0; s < strip_amount; ++s) RemoveFirstTrackdir(&trackdirs);
return FindFirstTrackdir(trackdirs);
return trackdirs.GetNthSetBit(RandomRange(trackdirs.Count())).value_or(Trackdir::Invalid);
}
/**
@@ -176,11 +174,11 @@ public:
TrackFollower follower{v};
if (follower.Follow(tile, dir)) {
TrackdirBits dirs = follower.new_td_bits;
const TrackdirBits dirs_without_90_degree = dirs & ~TrackdirCrossesTrackdirs(dir);
if (dirs_without_90_degree != TRACKDIR_BIT_NONE) dirs = dirs_without_90_degree;
const TrackdirBits dirs_without_90_degree = dirs.Reset(TrackdirCrossesTrackdirs(dir));
if (dirs_without_90_degree.Any()) dirs = dirs_without_90_degree;
return { follower.new_tile, GetRandomTrackdir(dirs) };
}
return { follower.new_tile, INVALID_TRACKDIR };
return { follower.new_tile, Trackdir::Invalid };
}
/**
@@ -188,18 +186,18 @@ public:
* @param v The ship to create the path for.
* @param[in,out] path_cache Cache of the path for the ship.
* @param path_length The length of the random path to create.
* @return The next track direction to take, or \c INVALID_TRACKDIR when there is no option.
* @return The next track direction to take, or \c Trackdir::Invalid when there is no option.
*/
static Trackdir CreateRandomPath(const Ship *v, ShipPathCache &path_cache, int path_length)
{
std::pair<TileIndex, Trackdir> tile_dir = { v->tile, v->GetVehicleTrackdir()};
for (int i = 0; i < path_length; ++i) {
tile_dir = GetRandomFollowUpTileTrackdir(v, tile_dir.first, tile_dir.second);
if (tile_dir.second == INVALID_TRACKDIR) break;
if (tile_dir.second == Trackdir::Invalid) break;
path_cache.push_back(tile_dir.second);
}
if (path_cache.empty()) return INVALID_TRACKDIR;
if (path_cache.empty()) return Trackdir::Invalid;
/* Reverse the path so we can take from the end. */
std::reverse(std::begin(path_cache), std::end(path_cache));
@@ -266,11 +264,11 @@ public:
}
assert(node->GetTile() == v->tile);
/* Return INVALID_TRACKDIR to trigger a ship reversal if that is the best option. */
/* Return Trackdir::Invalid to trigger a ship reversal if that is the best option. */
best_origin_dir = node->GetTrackdir();
if ((TrackdirToTrackdirBits(best_origin_dir) & forward_dirs) == TRACKDIR_BIT_NONE) {
if (TrackdirToTrackdirBits(best_origin_dir).Any(forward_dirs)) {
path_cache.clear();
return INVALID_TRACKDIR;
return Trackdir::Invalid;
}
/* A empty path means we are already at the destination. The pathfinder shouldn't have been called at all.
@@ -301,7 +299,7 @@ public:
{
bool path_found = false;
ShipPathCache dummy_cache;
Trackdir best_origin_dir = INVALID_TRACKDIR;
Trackdir best_origin_dir = Trackdir::Invalid;
if (trackdir == nullptr) {
/* The normal case, typically called when ships leave a dock. */
@@ -314,8 +312,8 @@ public:
/* This gets called when a ship suddenly can't move forward, e.g. due to terraforming. */
const DiagDirection entry = ReverseDiagDir(VehicleExitDir(v->direction, v->state));
const TrackdirBits reverse_dirs = DiagdirReachesTrackdirs(entry) & GetTileTrackStatus(v->tile, TRANSPORT_WATER, RoadTramType::Invalid, entry).trackdirs;
(void)ChooseShipTrack(v, v->tile, TRACKDIR_BIT_NONE, reverse_dirs, path_found, dummy_cache, best_origin_dir);
*trackdir = path_found && best_origin_dir != INVALID_TRACKDIR ? best_origin_dir : GetRandomTrackdir(reverse_dirs);
(void)ChooseShipTrack(v, v->tile, {}, reverse_dirs, path_found, dummy_cache, best_origin_dir);
*trackdir = path_found && best_origin_dir != Trackdir::Invalid ? best_origin_dir : GetRandomTrackdir(reverse_dirs);
return true;
}
}
@@ -342,7 +340,7 @@ public:
assert(IsValidTrackdir(td1));
assert(IsValidTrackdir(td2));
if (HasTrackdir(TrackdirCrossesTrackdirs(td1), td2)) {
if (TrackdirCrossesTrackdirs(td1).Test(td2)) {
/* 90-deg curve penalty. */
return Yapf().PfGetSettings().ship_curve90_penalty;
} else if (td2 != NextTrackdir(td1)) {
@@ -362,11 +360,11 @@ public:
{
const bool odd_x = TileX(tile) & 1;
const bool odd_y = TileY(tile) & 1;
if (td == TRACKDIR_X_NE) return odd_y;
if (td == TRACKDIR_X_SW) return !odd_y;
if (td == TRACKDIR_Y_NW) return odd_x;
if (td == TRACKDIR_Y_SE) return !odd_x;
return (odd_x ^ odd_y) ^ HasBit(TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_LOWER_E, td);
if (td == Trackdir::X_NE) return odd_y;
if (td == Trackdir::X_SW) return !odd_y;
if (td == Trackdir::Y_NW) return odd_x;
if (td == Trackdir::Y_SE) return !odd_x;
return (odd_x ^ odd_y) ^ TrackdirBits{Trackdir::Right_N, Trackdir::Left_S, Trackdir::Upper_W, Trackdir::Lower_E}.Test(td);
}
/** @copydoc CYapfBaseT::PfCalcCostFunc */
@@ -437,10 +435,10 @@ struct CYapfShip : CYapfT<CYapfShip_TypesT<CYapfShip>> {
Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache)
{
Trackdir best_origin_dir = INVALID_TRACKDIR;
Trackdir best_origin_dir = Trackdir::Invalid;
const TrackdirBits origin_dirs = TrackdirToTrackdirBits(v->GetVehicleTrackdir());
const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, TRACKDIR_BIT_NONE, path_found, path_cache, best_origin_dir);
return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : Track::Invalid;
const Trackdir td_ret = CYapfShip::ChooseShipTrack(v, tile, origin_dirs, {}, path_found, path_cache, best_origin_dir);
return (td_ret != Trackdir::Invalid) ? TrackdirToTrack(td_ret) : Track::Invalid;
}
bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir)
+5 -5
View File
@@ -213,7 +213,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra
TrackdirBits reserved = ft.new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(ft.new_tile));
/* No reservation --> path end found */
if (reserved == TRACKDIR_BIT_NONE) {
if (reserved.None()) {
if (ft.is_station) {
/* Check skipped station tiles as well, maybe our reservation ends inside the station. */
TileIndexDiff diff = TileOffsByDiagDir(ft.exitdir);
@@ -410,10 +410,10 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo
/* Check for reachable tracks. */
ft.new_td_bits &= DiagdirReachesTrackdirs(ft.exitdir);
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile), forbid_90deg)) ft.new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
if (ft.new_td_bits == TRACKDIR_BIT_NONE) return include_line_end;
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile), forbid_90deg)) ft.new_td_bits.Reset(TrackdirCrossesTrackdirs(trackdir));
if (ft.new_td_bits.None()) return include_line_end;
if (ft.new_td_bits != TRACKDIR_BIT_NONE && KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE) {
if (ft.new_td_bits.Count() == 1) {
Trackdir td = FindFirstTrackdir(ft.new_td_bits);
/* PBS signal on next trackdir? Safe position. */
if (HasPbsSignalOnTrackdir(ft.new_tile, td)) return true;
@@ -456,7 +456,7 @@ bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bo
/* Check for reachable tracks. */
ft.new_td_bits &= DiagdirReachesTrackdirs(ft.exitdir);
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile), forbid_90deg)) ft.new_td_bits &= ~TrackdirCrossesTrackdirs(trackdir);
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile), forbid_90deg)) ft.new_td_bits.Reset(TrackdirCrossesTrackdirs(trackdir));
return !HasReservedTracks(ft.new_tile, TrackdirBitsToTrackBits(ft.new_td_bits));
}
+1 -1
View File
@@ -31,7 +31,7 @@ struct PBSTileInfo {
/**
* Create an empty PBSTileInfo.
*/
PBSTileInfo() : tile(INVALID_TILE), trackdir(INVALID_TRACKDIR), okay(false) {}
PBSTileInfo() : tile(INVALID_TILE), trackdir(Trackdir::Invalid), okay(false) {}
/**
* Create a PBSTileInfo with given tile, track direction and safe waiting position information.
+11 -11
View File
@@ -849,8 +849,8 @@ static CommandCost ValidateAutoDrag(Trackdir *trackdir, TileIndex start, TileInd
(trdx >= 0 && dx < 0) ||
(trdy <= 0 && dy > 0) ||
(trdy >= 0 && dy < 0)) {
if (!HasBit(*trackdir, 3)) { // first direction is invalid, try the other
SetBit(*trackdir, 3); // reverse the direction
if (!HasBit(to_underlying(*trackdir), 3)) { // first direction is invalid, try the other
*trackdir = ReverseTrackdir(*trackdir); // reverse the direction
trdx = -trdx;
trdy = -trdy;
} else { // other direction is invalid too, invalid drag
@@ -1215,13 +1215,13 @@ static bool AdvanceSignalAutoFill(TileIndex &tile, Trackdir &trackdir, bool remo
trackdirbits &= TrackdirReachesTrackdirs(trackdir);
/* No track bits, must stop */
if (trackdirbits == TRACKDIR_BIT_NONE) return false;
if (trackdirbits.None()) return false;
/* Get the first track dir */
trackdir = RemoveFirstTrackdir(&trackdirbits);
/* Any left? It's a junction so we stop */
if (trackdirbits != TRACKDIR_BIT_NONE) return false;
if (trackdirbits.Any()) return false;
switch (GetTileType(tile)) {
case TileType::Railway:
@@ -1319,7 +1319,7 @@ static CommandCost CmdSignalTrackHelper(DoCommandFlags flags, TileIndex tile, Ti
int last_used_ctr = -signal_density; // to force signal at first tile
int last_suitable_ctr = 0;
TileIndex last_suitable_tile = INVALID_TILE;
Trackdir last_suitable_trackdir = INVALID_TRACKDIR;
Trackdir last_suitable_trackdir = Trackdir::Invalid;
CommandCost last_error = CMD_ERROR;
bool had_success = false;
auto build_signal = [&](TileIndex tile, Trackdir trackdir, bool test_only) {
@@ -2781,13 +2781,13 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [
case TrackBits{Track::Left}.base(): tb = Track::Right; break;
case TrackBits{Track::Right}.base(): tb = Track::Left; break;
}
return {TrackBitsToTrackdirBits(tb), TRACKDIR_BIT_NONE};
return {TrackBitsToTrackdirBits(tb), {}};
}
if (mode != TRANSPORT_RAIL) return {};
TrackBits trackbits{};
TrackdirBits red_signals = TRACKDIR_BIT_NONE;
TrackdirBits red_signals{};
switch (GetRailTileType(tile)) {
default: NOT_REACHED();
@@ -2810,10 +2810,10 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [
if (!IsOnewaySignal(tile, Track::Upper) || (a & SignalOnTrack(Track::Upper)) == 0) b |= ~a & SignalOnTrack(Track::Upper);
if (!IsOnewaySignal(tile, Track::Lower) || (a & SignalOnTrack(Track::Lower)) == 0) b |= ~a & SignalOnTrack(Track::Lower);
if ((b & 0x8) == 0) red_signals |= (TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E);
if ((b & 0x4) == 0) red_signals |= (TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_UPPER_W);
if ((b & 0x2) == 0) red_signals |= (TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_E);
if ((b & 0x1) == 0) red_signals |= (TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LOWER_W);
if ((b & 0x8) == 0) red_signals.Set({Trackdir::Left_N, Trackdir::X_NE, Trackdir::Y_SE, Trackdir::Upper_E});
if ((b & 0x4) == 0) red_signals.Set({Trackdir::Left_S, Trackdir::X_SW, Trackdir::Y_NW, Trackdir::Upper_W});
if ((b & 0x2) == 0) red_signals.Set({Trackdir::Right_N, Trackdir::Lower_E});
if ((b & 0x1) == 0) red_signals.Set({Trackdir::Right_S, Trackdir::Lower_W});
break;
}
+6 -6
View File
@@ -2141,8 +2141,8 @@ static const TrackBits _road_trackbits[16] = {
/** @copydoc GetTileTrackStatusProc */
static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side)
{
TrackdirBits trackdirbits = TRACKDIR_BIT_NONE;
TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred
TrackdirBits trackdirbits{};
TrackdirBits red_signals{}; // crossing barred
switch (mode) {
case TRANSPORT_RAIL:
if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailTrack(tile));
@@ -2178,9 +2178,9 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R
if (IsLevelCrossingTile(t) && IsCrossingBarred(t)) red_signals &= mask;
};
/* Check for blocked adjacent crossing to south, keep only southbound red signal trackdirs, allow northbound traffic */
mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE);
mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, AxisToDiagDir(axis)), {Trackdir::X_SW, Trackdir::Y_SE});
/* Check for blocked adjacent crossing to north, keep only northbound red signal trackdirs, allow southbound traffic */
mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW);
mask_red_signal_bits_if_crossing_barred(TileAddByDiagDir(tile, ReverseDiagDir(AxisToDiagDir(axis))), {Trackdir::X_NE, Trackdir::Y_NW});
}
break;
}
@@ -2286,7 +2286,7 @@ static void GetTileDesc_Road(TileIndex tile, TileDesc &td)
* vehicle should be travelling in in order to enter the depot.
*/
static constexpr DiagDirectionIndexArray<Trackdir> _roadveh_enter_depot_dir{
TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_X_NE, TRACKDIR_Y_SE
Trackdir::X_SW, Trackdir::Y_NW, Trackdir::X_NE, Trackdir::Y_SE
};
/** @copydoc VehicleEnterTileProc */
@@ -2298,7 +2298,7 @@ static VehicleEnterTileStates VehicleEnterTile_Road(Vehicle *v, TileIndex tile,
RoadVehicle *rv = RoadVehicle::From(v);
if (rv->frame == RVC_DEPOT_STOP_FRAME &&
_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == rv->state) {
_roadveh_enter_depot_dir[GetRoadDepotDirection(tile)] == static_cast<Trackdir>(rv->state)) {
rv->state = RVSB_IN_DEPOT;
rv->vehstatus.Set(VehState::Hidden);
rv->direction = ReverseDir(rv->direction);
+4 -4
View File
@@ -47,9 +47,9 @@ enum RoadVehicleStates : uint8_t {
/* Bit sets of the above specified bits */
RVSB_IN_ROAD_STOP = 1 << RVS_IN_ROAD_STOP, ///< The vehicle is in a road stop
RVSB_IN_ROAD_STOP_END = RVSB_IN_ROAD_STOP + TRACKDIR_END,
RVSB_IN_ROAD_STOP_END = RVSB_IN_ROAD_STOP + to_underlying(Trackdir::End),
RVSB_IN_DT_ROAD_STOP = 1 << RVS_IN_DT_ROAD_STOP, ///< The vehicle is in a drive-through road stop
RVSB_IN_DT_ROAD_STOP_END = RVSB_IN_DT_ROAD_STOP + TRACKDIR_END,
RVSB_IN_DT_ROAD_STOP_END = RVSB_IN_DT_ROAD_STOP + to_underlying(Trackdir::End),
RVSB_DRIVE_SIDE = 1 << RVS_DRIVE_SIDE, ///< The vehicle is at the opposite side of the road
@@ -90,7 +90,7 @@ void GetRoadVehSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs
/** Element of the RoadVehPathCache. */
struct RoadVehPathElement {
Trackdir trackdir = INVALID_TRACKDIR; ///< Trackdir for this element.
Trackdir trackdir = Trackdir::Invalid; ///< Trackdir for this element.
TileIndex tile = INVALID_TILE; ///< Tile for this element.
constexpr RoadVehPathElement() {}
@@ -307,7 +307,7 @@ protected: // These functions should not be called outside acceleration code.
/* Check if this vehicle is in the same direction as the road under.
* We already know it has either GVF_GOINGUP_BIT or GVF_GOINGDOWN_BIT set. */
if (rv->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)rv->state)) {
if (rv->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir(static_cast<Trackdir>(rv->state))) {
/* If the first vehicle is reversing, this vehicle may be reversing too
* (especially if this is the first, and maybe the only, vehicle).*/
return true;
+46 -55
View File
@@ -74,7 +74,7 @@ bool IsValidImageIndex<VehicleType::Road>(uint8_t image_index)
/** Track direction to use when reversing for each diagonal direction. */
static constexpr DiagDirectionIndexArray<Trackdir> _road_reverse_table{
TRACKDIR_RVREV_NE, TRACKDIR_RVREV_SE, TRACKDIR_RVREV_SW, TRACKDIR_RVREV_NW
Trackdir::RvRev_NE, Trackdir::RvRev_SE, Trackdir::RvRev_SW, Trackdir::RvRev_NW
};
/**
@@ -470,7 +470,7 @@ inline int RoadVehicle::GetCurrentMaxSpeed() const
/* Limit speed to 50% while reversing, 75% in curves. */
for (const RoadVehicle *u = this; u != nullptr; u = u->Next()) {
if (_settings_game.vehicle.roadveh_acceleration_model == AM_REALISTIC) {
if (this->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir((Trackdir)this->state)) {
if (this->state <= RVSB_TRACKDIR_MASK && IsReversingRoadTrackdir(static_cast<Trackdir>(this->state))) {
max_speed = this->gcache.cached_max_track_speed / 2;
break;
} else if (!IsDiagonalDirection(u->direction)) {
@@ -796,7 +796,7 @@ static bool CheckRoadBlockedForOvertaking(OvertakeData *od)
TrackBits trackbits = TrackdirBitsToTrackBits(ts.trackdirs);
/* Track does not continue along overtaking direction || track has junction || levelcrossing is barred */
if (!HasBit(ts.trackdirs, od->trackdir) || trackbits.Any({Track::Upper, Track::Lower, Track::Left, Track::Right}) || (ts.signals != TRACKDIR_BIT_NONE)) return true;
if (!ts.trackdirs.Test(od->trackdir) || trackbits.Any({Track::Upper, Track::Lower, Track::Left, Track::Right}) || ts.signals.Any()) return true;
/* Are there more vehicles on the tile except the two vehicles involved in overtaking */
return HasVehicleOnTile(od->tile, [&](const Vehicle *v) {
@@ -824,7 +824,7 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
if (v->direction != u->direction || !IsDiagonalDirection(v->direction)) return;
/* Check if vehicle is in a road stop, depot, tunnel or bridge or not on a straight road */
if (v->state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir((Trackdir)(v->state & RVSB_TRACKDIR_MASK))) return;
if (v->state >= RVSB_IN_ROAD_STOP || !IsStraightRoadTrackdir(static_cast<Trackdir>(v->state & RVSB_TRACKDIR_MASK))) return;
/* Can't overtake a vehicle that is moving faster than us. If the vehicle in front is
* accelerating, take the maximum speed for the comparison, else the current speed.
@@ -868,18 +868,9 @@ static void RoadZPosAffectSpeed(RoadVehicle *v, int old_z)
}
}
static int PickRandomBit(uint bits)
{
uint i;
uint num = RandomRange(CountBits(bits));
for (i = 0; !(bits & 1) || (int)--num >= 0; bits >>= 1, i++) {}
return i;
}
/**
* Returns direction to for a road vehicle to take or
* INVALID_TRACKDIR if the direction is currently blocked
* Trackdir::Invalid if the direction is currently blocked
* @param v the Vehicle to do the pathfinding for
* @param tile the where to start the pathfinding
* @param enterdir the direction the vehicle enters the tile from
@@ -891,36 +882,36 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
TrackStatus ts = GetTileTrackStatus(tile, TRANSPORT_ROAD, GetRoadTramType(v->roadtype));
/* Replaces the given trackdir with INVALID_TRACKDIR when there is red signal for that trackdir. */
/* Replaces the given trackdir with Trackdir::Invalid when there is red signal for that trackdir. */
auto FilterRedSignal = [&ts](Trackdir trackdir) {
if (HasBit(ts.signals, trackdir)) return INVALID_TRACKDIR;
if (ts.signals.Test(trackdir)) return Trackdir::Invalid;
return trackdir;
};
if (IsTileType(tile, TileType::Road)) {
if (IsRoadDepot(tile) && (!IsTileOwner(tile, v->owner) || GetRoadDepotDirection(tile) == enterdir)) {
/* Road depot owned by another company or with the wrong orientation */
ts.trackdirs = TRACKDIR_BIT_NONE;
ts.trackdirs.Reset();
}
} else if (IsTileType(tile, TileType::Station) && IsBayRoadStopTile(tile)) {
/* Standard road stop (drive-through stops are treated as normal road) */
if (!IsTileOwner(tile, v->owner) || GetBayRoadStopDir(tile) == enterdir || v->HasArticulatedPart()) {
/* different station owner or wrong orientation or the vehicle has articulated parts */
ts.trackdirs = TRACKDIR_BIT_NONE;
ts.trackdirs.Reset();
} else {
/* Our station */
RoadStopType rstype = v->IsBus() ? RoadStopType::Bus : RoadStopType::Truck;
if (GetRoadStopType(tile) != rstype) {
/* Wrong station type */
ts.trackdirs = TRACKDIR_BIT_NONE;
ts.trackdirs.Reset();
} else {
/* Proper station type, check if there is free loading bay */
if (!_settings_game.pf.roadveh_queue && IsBayRoadStopTile(tile) &&
!RoadStop::GetByTile(tile, rstype)->HasFreeBay()) {
/* Station is full and RV queuing is off */
ts.trackdirs = TRACKDIR_BIT_NONE;
ts.trackdirs.Reset();
}
}
}
@@ -932,7 +923,7 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
/* Remove tracks unreachable from the enter dir */
ts.trackdirs &= DiagdirReachesTrackdirs(enterdir);
if (ts.trackdirs == TRACKDIR_BIT_NONE) {
if (ts.trackdirs.None()) {
/* If vehicle expected a path, it no longer exists, so invalidate it. */
if (!v->path.empty()) v->path.clear();
/* No reachable tracks, so we'll reverse */
@@ -959,16 +950,16 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
if (v->dest_tile == INVALID_TILE) {
/* We've got no destination, pick a random track */
return FilterRedSignal(static_cast<Trackdir>(PickRandomBit(ts.trackdirs)));
return FilterRedSignal(ts.trackdirs.GetNthSetBit(RandomRange(ts.trackdirs.Count())).value());
}
/* Only one track to choose between? */
if (KillFirstBit(ts.trackdirs) == TRACKDIR_BIT_NONE) {
if (ts.trackdirs.Count() == 1) {
if (!v->path.empty() && v->path.back().tile == tile) {
/* Vehicle expected a choice here, invalidate its path. */
v->path.clear();
}
return FilterRedSignal(static_cast<Trackdir>(FindFirstBit(ts.trackdirs)));
return FilterRedSignal(ts.trackdirs.GetNthSetBit(0).value());
}
/* Attempt to follow cached path. */
@@ -979,7 +970,7 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
} else {
Trackdir trackdir = v->path.back().trackdir;
if (HasBit(ts.trackdirs, trackdir)) {
if (ts.trackdirs.Test(trackdir)) {
v->path.pop_back();
return FilterRedSignal(trackdir);
}
@@ -1013,7 +1004,7 @@ bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
v->direction = DiagDirToDir(dir);
Trackdir tdir = DiagDirToDiagTrackdir(dir);
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(to_underlying(_settings_game.vehicle.road_side) << RVS_DRIVE_SIDE) + tdir];
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(to_underlying(_settings_game.vehicle.road_side) << RVS_DRIVE_SIDE) + to_underlying(tdir)];
int x = TileX(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].x & 0xF);
int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF);
@@ -1037,7 +1028,7 @@ bool RoadVehLeaveDepot(RoadVehicle *v, bool first)
}
v->vehstatus.Reset(VehState::Hidden);
v->state = tdir;
v->state = to_underlying(tdir);
v->frame = RVC_DEPOT_START_FRAME;
v->x_pos = x;
@@ -1070,10 +1061,10 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl
diag_dir = ReverseDiagDir(GetRoadDepotDirection(tile));
}
if (diag_dir == DiagDirection::Invalid) return INVALID_TRACKDIR;
if (diag_dir == DiagDirection::Invalid) return Trackdir::Invalid;
dir = DiagDirToDiagTrackdir(diag_dir);
} else {
if (already_reversed && (prev->tile != tile || (prev_state < TRACKDIR_END && IsReversingRoadTrackdir(static_cast<Trackdir>(prev_state))))) {
if (already_reversed && (prev->tile != tile || (static_cast<Trackdir>(prev_state) < Trackdir::End && IsReversingRoadTrackdir(static_cast<Trackdir>(prev_state))))) {
/*
* The vehicle has reversed, but did not go straight back.
* It immediately turn onto another tile. This means that
@@ -1093,18 +1084,18 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl
if (prev->tile != tile) {
north = prev->tile < tile;
} else {
north = (prev_state == TRACKDIR_RVREV_NW || prev_state == TRACKDIR_RVREV_NE);
north = static_cast<Trackdir>(prev_state) == Trackdir::RvRev_NW || static_cast<Trackdir>(prev_state) == Trackdir::RvRev_NE;
}
static const DiagDirectionIndexArray<Trackdir> reversed_turn_lookup[2] = {
{ TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N, TRACKDIR_UPPER_E },
{ TRACKDIR_RIGHT_S, TRACKDIR_LOWER_W, TRACKDIR_LOWER_E, TRACKDIR_LEFT_S }};
{ Trackdir::Upper_W, Trackdir::Right_N, Trackdir::Left_N, Trackdir::Upper_E },
{ Trackdir::Right_S, Trackdir::Lower_W, Trackdir::Lower_E, Trackdir::Left_S }};
dir = reversed_turn_lookup[north ? 0 : 1][ReverseDiagDir(entry_dir)];
} else if (HasBit(prev_state, RVS_IN_DT_ROAD_STOP)) {
dir = (Trackdir)(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
} else if (prev_state < TRACKDIR_END) {
dir = (Trackdir)prev_state;
dir = static_cast<Trackdir>(prev_state & RVSB_ROAD_STOP_TRACKDIR_MASK);
} else if (static_cast<Trackdir>(prev_state) < Trackdir::End) {
dir = static_cast<Trackdir>(prev_state);
} else {
return INVALID_TRACKDIR;
return Trackdir::Invalid;
}
}
@@ -1119,10 +1110,10 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl
ROAD_X,
ROAD_Y,
};
RoadBits required = required_roadbits[dir & 0x07];
RoadBits required = required_roadbits[to_underlying(dir) & 0x07];
if (!required.Any(GetAnyRoadBits(tile, GetRoadTramType(v->roadtype), true))) {
dir = INVALID_TRACKDIR;
dir = Trackdir::Invalid;
}
return dir;
@@ -1153,7 +1144,7 @@ bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
/* If overtaking just aborts at a random moment, we can have a out-of-bound problem,
* if the vehicle started a corner. To protect that, only allow an abort of
* overtake if we are on straight roads */
if (v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir((Trackdir)v->state)) {
if (v->state < RVSB_IN_ROAD_STOP && IsStraightRoadTrackdir(static_cast<Trackdir>(v->state))) {
v->overtaking = 0;
}
}
@@ -1215,7 +1206,7 @@ bool IndividualRoadVehicleController(RoadVehicle *v, const RoadVehicle *prev)
dir = FollowPreviousRoadVehicle(v, prev, tile, diagdir, false);
}
if (dir == INVALID_TRACKDIR) {
if (dir == Trackdir::Invalid) {
if (!v->IsFrontEngine()) FatalError("Disconnecting road vehicle.");
v->cur_speed = 0;
return false;
@@ -1234,10 +1225,10 @@ again:
RoadBit needed;
switch (dir) {
default: NOT_REACHED();
case TRACKDIR_RVREV_NE: needed = RoadBit::SW; break;
case TRACKDIR_RVREV_SE: needed = RoadBit::NW; break;
case TRACKDIR_RVREV_SW: needed = RoadBit::NE; break;
case TRACKDIR_RVREV_NW: needed = RoadBit::SE; break;
case Trackdir::RvRev_NE: needed = RoadBit::SW; break;
case Trackdir::RvRev_SE: needed = RoadBit::NW; break;
case Trackdir::RvRev_SW: needed = RoadBit::NE; break;
case Trackdir::RvRev_NW: needed = RoadBit::SE; break;
}
if ((v->Previous() != nullptr && v->Previous()->tile == tile) ||
(v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) &&
@@ -1281,7 +1272,7 @@ again:
}
/* Get position data for first frame on the new tile */
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(dir + (to_underlying(_settings_game.vehicle.road_side) << RVS_DRIVE_SIDE)) ^ v->overtaking];
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(to_underlying(dir) + (to_underlying(_settings_game.vehicle.road_side) << RVS_DRIVE_SIDE)) ^ v->overtaking];
int x = TileX(tile) * TILE_SIZE + rdp[start_frame].x;
int y = TileY(tile) * TILE_SIZE + rdp[start_frame].y;
@@ -1327,7 +1318,7 @@ again:
RoadStop::IsDriveThroughRoadStopContinuation(v->tile, tile) &&
v->tile != tile) {
/* So, keep 'our' state */
dir = (Trackdir)v->state;
dir = static_cast<Trackdir>(v->state);
} else if (IsStationRoadStop(v->tile)) {
/* We're not continuing our drive through road stop, so leave. */
RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
@@ -1377,10 +1368,10 @@ again:
turn_around_start_frame = RVC_START_FRAME_AFTER_LONG_TRAM;
switch (static_cast<DiagDirection>(rd.x & 0x3)) {
default: NOT_REACHED();
case DiagDirection::NW: dir = TRACKDIR_RVREV_SE; break;
case DiagDirection::NE: dir = TRACKDIR_RVREV_SW; break;
case DiagDirection::SE: dir = TRACKDIR_RVREV_NW; break;
case DiagDirection::SW: dir = TRACKDIR_RVREV_NE; break;
case DiagDirection::NW: dir = Trackdir::RvRev_SE; break;
case DiagDirection::NE: dir = Trackdir::RvRev_SW; break;
case DiagDirection::SE: dir = Trackdir::RvRev_NW; break;
case DiagDirection::SW: dir = Trackdir::RvRev_NE; break;
}
} else {
if (v->IsFrontEngine()) {
@@ -1391,12 +1382,12 @@ again:
}
}
if (dir == INVALID_TRACKDIR) {
if (dir == Trackdir::Invalid) {
v->cur_speed = 0;
return false;
}
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(to_underlying(_settings_game.vehicle.road_side) << RVS_DRIVE_SIDE) + dir];
const RoadDriveEntry *rdp = _road_drive_data[GetRoadTramType(v->roadtype)][(to_underlying(_settings_game.vehicle.road_side) << RVS_DRIVE_SIDE) + to_underlying(dir)];
int x = TileX(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].x;
int y = TileY(v->tile) * TILE_SIZE + rdp[turn_around_start_frame].y;
@@ -1418,7 +1409,7 @@ again:
return false;
}
v->state = dir;
v->state = to_underlying(dir);
v->frame = turn_around_start_frame;
if (new_dir != v->direction) {
@@ -1750,7 +1741,7 @@ void RoadVehicle::OnNewEconomyDay()
Trackdir RoadVehicle::GetVehicleTrackdir() const
{
if (this->vehstatus.Test(VehState::Crashed)) return INVALID_TRACKDIR;
if (this->vehstatus.Test(VehState::Crashed)) return Trackdir::Invalid;
if (this->IsInDepot()) {
/* We'll assume the road vehicle is facing outwards */
@@ -1767,7 +1758,7 @@ Trackdir RoadVehicle::GetVehicleTrackdir() const
/* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
* otherwise transform it into a valid track direction */
return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->state)) ? (this->state - 6) : this->state);
return static_cast<Trackdir>(IsReversingRoadTrackdir(static_cast<Trackdir>(this->state)) ? (this->state - 6) : this->state);
}
uint16_t RoadVehicle::GetMaxWeight() const
+3 -3
View File
@@ -438,8 +438,8 @@ static void FixOwnerOfRailTrack(Tile t)
/* try to find any connected rail */
for (DiagDirection dd = DiagDirection::Begin; dd < DiagDirection::End; dd++) {
TileIndex tt{t + TileOffsByDiagDir(dd)};
if (GetTileTrackStatus(t, TRANSPORT_RAIL, RoadTramType::Invalid, dd).trackdirs != TRACKDIR_BIT_NONE &&
GetTileTrackStatus(tt, TRANSPORT_RAIL, RoadTramType::Invalid, ReverseDiagDir(dd)).trackdirs != TRACKDIR_BIT_NONE &&
if (GetTileTrackStatus(t, TRANSPORT_RAIL, RoadTramType::Invalid, dd).trackdirs.Any() &&
GetTileTrackStatus(tt, TRANSPORT_RAIL, RoadTramType::Invalid, ReverseDiagDir(dd)).trackdirs.Any() &&
Company::IsValidID(GetTileOwner(tt))) {
SetTileOwner(t, GetTileOwner(tt));
return;
@@ -2681,7 +2681,7 @@ bool AfterLoadGame()
switch (v->type) {
case VehicleType::Train: Train::From(v)->track = DiagDirToDiagTrack(vdir); break;
case VehicleType::Road: RoadVehicle::From(v)->state = DiagDirToDiagTrackdir(vdir); RoadVehicle::From(v)->frame = frame; break;
case VehicleType::Road: RoadVehicle::From(v)->state = to_underlying(DiagDirToDiagTrackdir(vdir)); RoadVehicle::From(v)->frame = frame; break;
default: NOT_REACHED();
}
}
+5 -5
View File
@@ -402,11 +402,11 @@ static const int NUM_TRACK_DIRECTIONS = 3; ///< The number of directions you can
* 2 it added.
*/
static const ScriptRailSignalData _possible_trackdirs[5][NUM_TRACK_DIRECTIONS] = {
{{Track::Upper, TRACKDIR_UPPER_E, 0}, {Track::Y, TRACKDIR_Y_SE, 0}, {Track::Left, TRACKDIR_LEFT_S, 1}},
{{Track::Right, TRACKDIR_RIGHT_S, 1}, {Track::X, TRACKDIR_X_SW, 1}, {Track::Upper, TRACKDIR_UPPER_W, 1}},
{{Track::Invalid, INVALID_TRACKDIR, 0}, {Track::Invalid, INVALID_TRACKDIR, 0}, {Track::Invalid, INVALID_TRACKDIR, 0}},
{{Track::Lower, TRACKDIR_LOWER_E, 0}, {Track::X, TRACKDIR_X_NE, 0}, {Track::Left, TRACKDIR_LEFT_N, 0}},
{{Track::Right, TRACKDIR_RIGHT_N, 0}, {Track::Y, TRACKDIR_Y_NW, 1}, {Track::Lower, TRACKDIR_LOWER_W, 1}}
{{Track::Upper, Trackdir::Upper_E, 0}, {Track::Y, Trackdir::Y_SE, 0}, {Track::Left, Trackdir::Left_S, 1}},
{{Track::Right, Trackdir::Right_S, 1}, {Track::X, Trackdir::X_SW, 1}, {Track::Upper, Trackdir::Upper_W, 1}},
{{Track::Invalid, Trackdir::Invalid, 0}, {Track::Invalid, Trackdir::Invalid, 0}, {Track::Invalid, Trackdir::Invalid, 0}},
{{Track::Lower, Trackdir::Lower_E, 0}, {Track::X, Trackdir::X_NE, 0}, {Track::Left, Trackdir::Left_N, 0}},
{{Track::Right, Trackdir::Right_N, 0}, {Track::Y, Trackdir::Y_NW, 1}, {Track::Lower, Trackdir::Lower_W, 1}}
};
/* static */ ScriptRail::SignalType ScriptRail::GetSignalType(TileIndex tile, TileIndex front)
+3 -3
View File
@@ -219,10 +219,10 @@
if (!::IsValidTile(tile)) return false;
if (transport_type == TRANSPORT_ROAD) {
return ::GetTileTrackStatus(tile, (::TransportType)transport_type, ::RoadTramType::Road).trackdirs != TRACKDIR_BIT_NONE ||
::GetTileTrackStatus(tile, (::TransportType)transport_type, ::RoadTramType::Tram).trackdirs != TRACKDIR_BIT_NONE;
return ::GetTileTrackStatus(tile, (::TransportType)transport_type, ::RoadTramType::Road).trackdirs.Any() ||
::GetTileTrackStatus(tile, (::TransportType)transport_type, ::RoadTramType::Tram).trackdirs.Any();
} else {
return ::GetTileTrackStatus(tile, (::TransportType)transport_type, ::RoadTramType::Invalid).trackdirs != TRACKDIR_BIT_NONE;
return ::GetTileTrackStatus(tile, (::TransportType)transport_type, ::RoadTramType::Invalid).trackdirs.Any();
}
}
+1 -1
View File
@@ -18,7 +18,7 @@ WaterClass GetEffectiveWaterClass(TileIndex tile);
/** Element of the ShipPathCache. */
struct ShipPathElement {
Trackdir trackdir = INVALID_TRACKDIR; ///< Trackdir for this element.
Trackdir trackdir = Trackdir::Invalid; ///< Trackdir for this element.
constexpr ShipPathElement() {}
constexpr ShipPathElement(Trackdir trackdir) : trackdir(trackdir) {}
+4 -4
View File
@@ -287,7 +287,7 @@ void Ship::OnNewEconomyDay()
Trackdir Ship::GetVehicleTrackdir() const
{
if (this->vehstatus.Test(VehState::Crashed)) return INVALID_TRACKDIR;
if (this->vehstatus.Test(VehState::Crashed)) return Trackdir::Invalid;
if (this->IsInDepot()) {
/* We'll assume the ship is facing outwards */
@@ -387,7 +387,7 @@ static bool CheckShipStayInDepot(Ship *v)
return u->type == VehicleType::Ship && u->cur_speed != 0;
})) return true;
assert(v->GetVehicleTrackdir() == TRACKDIR_X_NE || v->GetVehicleTrackdir() == TRACKDIR_Y_NW);
assert(v->GetVehicleTrackdir() == Trackdir::X_NE || v->GetVehicleTrackdir() == Trackdir::Y_NW);
v->direction = DiagDirToDir(TrackdirToExitdir(v->GetVehicleTrackdir()));
if (CheckReverseShip(v)) v->direction = ReverseDir(v->direction);
@@ -716,9 +716,9 @@ static void ShipController(Ship *v)
assert(diagdir != DiagDirection::Invalid);
const TrackBits tracks = GetAvailShipTracks(gp.new_tile, diagdir);
if (tracks.None()) {
Trackdir trackdir = INVALID_TRACKDIR;
Trackdir trackdir = Trackdir::Invalid;
CheckReverseShip(v, &trackdir);
if (trackdir == INVALID_TRACKDIR) return ReverseShip(v);
if (trackdir == Trackdir::Invalid) return ReverseShip(v);
return ReverseShipIntoTrackdir(v, trackdir);
}
+8 -8
View File
@@ -39,12 +39,12 @@ static constexpr DiagDirectionIndexArray<TrackBits> _enterdir_to_trackbits{
};
/** Accessible TrackdirBits from a given enter direction. */
static constexpr DiagDirectionIndexArray<TrackdirBits> _enterdir_to_trackdirbits{
TRACKDIR_BIT_X_SW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_RIGHT_S,
TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_RIGHT_N,
TRACKDIR_BIT_X_NE | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LEFT_N,
TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LEFT_S
};
static constexpr DiagDirectionIndexArray<TrackdirBits> _enterdir_to_trackdirbits{{{
{Trackdir::X_SW, Trackdir::Upper_W, Trackdir::Right_S},
{Trackdir::Y_NW, Trackdir::Lower_W, Trackdir::Right_N},
{Trackdir::X_NE, Trackdir::Lower_E, Trackdir::Left_N},
{Trackdir::Y_SE, Trackdir::Upper_E, Trackdir::Left_S},
}}};
/**
* Set containing 'items' items of 'tile and Tdir'
@@ -320,7 +320,7 @@ static SigFlags ExploreSegment(Owner owner)
Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too
if (HasSignalOnTrack(tile, track)) { // now check whole track, not trackdir
SignalType sig = GetSignalType(tile, track);
Trackdir trackdir = static_cast<Trackdir>(FindFirstBit(TrackBitsToTrackdirBits(tracks) & _enterdir_to_trackdirbits[enterdir]));
Trackdir trackdir = (TrackBitsToTrackdirBits(tracks) & _enterdir_to_trackdirbits[enterdir]).GetNthSetBit(0).value();
Trackdir reversedir = ReverseTrackdir(trackdir);
/* add (tile, reversetrackdir) to 'to-be-updated' set when there is
* ANY conventional signal in REVERSE direction
@@ -417,7 +417,7 @@ static SigFlags ExploreSegment(Owner owner)
static void UpdateSignalsAroundSegment(SigFlags flags)
{
TileIndex tile = INVALID_TILE; // Stop GCC from complaining about a possibly uninitialized variable (issue #8280).
Trackdir trackdir = INVALID_TRACKDIR;
Trackdir trackdir = Trackdir::Invalid;
while (_tbuset.Get(&tile, &trackdir)) {
assert(HasSignalOnTrackdir(tile, trackdir));
+2 -2
View File
@@ -3731,7 +3731,7 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode
break;
}
return {TrackBitsToTrackdirBits(trackbits), TRACKDIR_BIT_NONE};
return {TrackBitsToTrackdirBits(trackbits), {}};
}
@@ -3881,7 +3881,7 @@ static VehicleEnterTileStates VehicleEnterTile_Station(Vehicle *v, TileIndex til
}
} else if (v->type == VehicleType::Road) {
RoadVehicle *rv = RoadVehicle::From(v);
if (rv->state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)rv->state) && rv->frame == 0) {
if (rv->state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir(static_cast<Trackdir>(rv->state)) && rv->frame == 0) {
if (IsStationRoadStop(tile) && rv->IsFrontEngine()) {
/* Attempt to allocate a parking bay in a road stop */
if (RoadStop::GetByTile(tile, GetRoadStopType(tile))->Enter(rv)) return {};
+66 -66
View File
@@ -11,28 +11,28 @@
* Maps a diagonal direction to the all trackdirs that are connected to any
* track entering in this direction (including those making 90 degree turns).
*/
extern const DiagDirectionIndexArray<TrackdirBits> _exitdir_reaches_trackdirs{
TRACKDIR_BIT_X_NE | TRACKDIR_BIT_LOWER_E | TRACKDIR_BIT_LEFT_N, // DiagDirection::NE
TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_LEFT_S | TRACKDIR_BIT_UPPER_E, // DiagDirection::SE
TRACKDIR_BIT_X_SW | TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_RIGHT_S, // DiagDirection::SW
TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_LOWER_W // DiagDirection::NW
};
extern const DiagDirectionIndexArray<TrackdirBits> _exitdir_reaches_trackdirs{{{
{Trackdir::X_NE, Trackdir::Lower_E, Trackdir::Left_N}, // DiagDirection::NE
{Trackdir::Y_SE, Trackdir::Left_S, Trackdir::Upper_E}, // DiagDirection::SE
{Trackdir::X_SW, Trackdir::Upper_W, Trackdir::Right_S}, // DiagDirection::SW
{Trackdir::Y_NW, Trackdir::Right_N, Trackdir::Lower_W}, // DiagDirection::NW
}}};
/** Next trackdir to use when moving to a new tile for each current trackdir. */
extern const TrackdirIndexArray<Trackdir> _next_trackdir{
TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_LOWER_E, TRACKDIR_UPPER_E, TRACKDIR_RIGHT_S, TRACKDIR_LEFT_S, INVALID_TRACKDIR, INVALID_TRACKDIR,
TRACKDIR_X_SW, TRACKDIR_Y_NW, TRACKDIR_LOWER_W, TRACKDIR_UPPER_W, TRACKDIR_RIGHT_N, TRACKDIR_LEFT_N
Trackdir::X_NE, Trackdir::Y_SE, Trackdir::Lower_E, Trackdir::Upper_E, Trackdir::Right_S, Trackdir::Left_S, Trackdir::Invalid, Trackdir::Invalid,
Trackdir::X_SW, Trackdir::Y_NW, Trackdir::Lower_W, Trackdir::Upper_W, Trackdir::Right_N, Trackdir::Left_N
};
/** Maps a trackdir to all trackdirs that make 90 deg turns with it. */
extern const TrackIndexArray<TrackdirBits> _track_crosses_trackdirs{
TRACKDIR_BIT_Y_SE | TRACKDIR_BIT_Y_NW, // TRACK_X
TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW, // TRACK_Y
TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_LEFT_S, // TRACK_UPPER
TRACKDIR_BIT_RIGHT_N | TRACKDIR_BIT_RIGHT_S | TRACKDIR_BIT_LEFT_N | TRACKDIR_BIT_LEFT_S, // TRACK_LOWER
TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_LOWER_E, // TRACK_LEFT
TRACKDIR_BIT_UPPER_W | TRACKDIR_BIT_UPPER_E | TRACKDIR_BIT_LOWER_W | TRACKDIR_BIT_LOWER_E // TRACK_RIGHT
};
extern const TrackIndexArray<TrackdirBits> _track_crosses_trackdirs{{{
{Trackdir::Y_SE, Trackdir::Y_NW}, // TRACK_X
{Trackdir::X_NE, Trackdir::X_SW}, // TRACK_Y
{Trackdir::Right_N, Trackdir::Right_S, Trackdir::Left_N, Trackdir::Left_S}, // TRACK_UPPER
{Trackdir::Right_N, Trackdir::Right_S, Trackdir::Left_N, Trackdir::Left_S}, // TRACK_LOWER
{Trackdir::Upper_W, Trackdir::Upper_E, Trackdir::Lower_W, Trackdir::Lower_E}, // TRACK_LEFT
{Trackdir::Upper_W, Trackdir::Upper_E, Trackdir::Lower_W, Trackdir::Lower_E}, // TRACK_RIGHT
}}};
/** Maps a track to all tracks that make 90 deg turns with it. */
extern const TrackIndexArray<TrackBits> _track_crosses_tracks{
@@ -52,37 +52,37 @@ extern const TrackdirIndexArray<DiagDirection> _trackdir_to_exitdir{
/** Maps a track and an (4-way) dir to the trackdir that represents the track with the exit in the given direction. */
extern const TrackIndexArray<DiagDirectionIndexArray<Trackdir>> _track_exitdir_to_trackdir{{{
{TRACKDIR_X_NE, INVALID_TRACKDIR, TRACKDIR_X_SW, INVALID_TRACKDIR},
{INVALID_TRACKDIR, TRACKDIR_Y_SE, INVALID_TRACKDIR, TRACKDIR_Y_NW},
{TRACKDIR_UPPER_E, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_UPPER_W},
{INVALID_TRACKDIR, TRACKDIR_LOWER_E, TRACKDIR_LOWER_W, INVALID_TRACKDIR},
{INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_LEFT_S, TRACKDIR_LEFT_N},
{TRACKDIR_RIGHT_N, TRACKDIR_RIGHT_S, INVALID_TRACKDIR, INVALID_TRACKDIR}
{Trackdir::X_NE, Trackdir::Invalid, Trackdir::X_SW, Trackdir::Invalid},
{Trackdir::Invalid, Trackdir::Y_SE, Trackdir::Invalid, Trackdir::Y_NW},
{Trackdir::Upper_E, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Upper_W},
{Trackdir::Invalid, Trackdir::Lower_E, Trackdir::Lower_W, Trackdir::Invalid},
{Trackdir::Invalid, Trackdir::Invalid, Trackdir::Left_S, Trackdir::Left_N},
{Trackdir::Right_N, Trackdir::Right_S, Trackdir::Invalid, Trackdir::Invalid}
}}};
/** Maps a track and an (4-way) dir to the trackdir that represents the track with the entry in the given direction. */
extern const TrackIndexArray<DiagDirectionIndexArray<Trackdir>> _track_enterdir_to_trackdir{{{
{TRACKDIR_X_NE, INVALID_TRACKDIR, TRACKDIR_X_SW, INVALID_TRACKDIR},
{INVALID_TRACKDIR, TRACKDIR_Y_SE, INVALID_TRACKDIR, TRACKDIR_Y_NW},
{INVALID_TRACKDIR, TRACKDIR_UPPER_E, TRACKDIR_UPPER_W, INVALID_TRACKDIR},
{TRACKDIR_LOWER_E, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_LOWER_W},
{TRACKDIR_LEFT_N, TRACKDIR_LEFT_S, INVALID_TRACKDIR, INVALID_TRACKDIR},
{INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_RIGHT_S, TRACKDIR_RIGHT_N}
{Trackdir::X_NE, Trackdir::Invalid, Trackdir::X_SW, Trackdir::Invalid},
{Trackdir::Invalid, Trackdir::Y_SE, Trackdir::Invalid, Trackdir::Y_NW},
{Trackdir::Invalid, Trackdir::Upper_E, Trackdir::Upper_W, Trackdir::Invalid},
{Trackdir::Lower_E, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Lower_W},
{Trackdir::Left_N, Trackdir::Left_S, Trackdir::Invalid, Trackdir::Invalid},
{Trackdir::Invalid, Trackdir::Invalid, Trackdir::Right_S, Trackdir::Right_N}
}}};
/** Maps a track and a full (8-way) direction to the trackdir that represents the track running in the given direction. */
extern const TrackIndexArray<DirectionIndexArray<Trackdir>> _track_direction_to_trackdir{{{
{INVALID_TRACKDIR, TRACKDIR_X_NE, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_X_SW, INVALID_TRACKDIR, INVALID_TRACKDIR},
{INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_Y_SE, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_Y_NW},
{INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_UPPER_E, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_UPPER_W, INVALID_TRACKDIR},
{INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_LOWER_E, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_LOWER_W, INVALID_TRACKDIR},
{TRACKDIR_LEFT_N, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_LEFT_S, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR},
{TRACKDIR_RIGHT_N, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR, TRACKDIR_RIGHT_S, INVALID_TRACKDIR, INVALID_TRACKDIR, INVALID_TRACKDIR}
{Trackdir::Invalid, Trackdir::X_NE, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid, Trackdir::X_SW, Trackdir::Invalid, Trackdir::Invalid},
{Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Y_SE, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Y_NW},
{Trackdir::Invalid, Trackdir::Invalid, Trackdir::Upper_E, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Upper_W, Trackdir::Invalid},
{Trackdir::Invalid, Trackdir::Invalid, Trackdir::Lower_E, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Lower_W, Trackdir::Invalid},
{Trackdir::Left_N, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Left_S, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid},
{Trackdir::Right_N, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Right_S, Trackdir::Invalid, Trackdir::Invalid, Trackdir::Invalid}
}}};
/** Maps a (4-way) direction to the diagonal trackdir that runs in that direction. */
extern const DiagDirectionIndexArray<Trackdir> _dir_to_diag_trackdir{
TRACKDIR_X_NE, TRACKDIR_Y_SE, TRACKDIR_X_SW, TRACKDIR_Y_NW,
Trackdir::X_NE, Trackdir::Y_SE, Trackdir::X_SW, Trackdir::Y_NW,
};
/** Maps a single horizontal/vertical trackbit that is in a specific tile corner. */
@@ -91,35 +91,35 @@ extern const CornerIndexArray<TrackBits> _corner_to_trackbits{
};
extern const TrackdirBits _uphill_trackdirs[] = {
TRACKDIR_BIT_NONE , ///< 0 SLOPE_FLAT
TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW, ///< 1 SLOPE_W -> inclined for diagonal track
TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE, ///< 2 SLOPE_S -> inclined for diagonal track
TRACKDIR_BIT_X_SW , ///< 3 SLOPE_SW
TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE, ///< 4 SLOPE_E -> inclined for diagonal track
TRACKDIR_BIT_NONE , ///< 5 SLOPE_EW
TRACKDIR_BIT_Y_SE , ///< 6 SLOPE_SE
TRACKDIR_BIT_NONE , ///< 7 SLOPE_WSE -> leveled
TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW, ///< 8 SLOPE_N -> inclined for diagonal track
TRACKDIR_BIT_Y_NW , ///< 9 SLOPE_NW
TRACKDIR_BIT_NONE , ///< 10 SLOPE_NS
TRACKDIR_BIT_NONE , ///< 11 SLOPE_NWS -> leveled
TRACKDIR_BIT_X_NE , ///< 12 SLOPE_NE
TRACKDIR_BIT_NONE , ///< 13 SLOPE_ENW -> leveled
TRACKDIR_BIT_NONE , ///< 14 SLOPE_SEN -> leveled
TRACKDIR_BIT_NONE , ///< 15 invalid
TRACKDIR_BIT_NONE , ///< 16 invalid
TRACKDIR_BIT_NONE , ///< 17 invalid
TRACKDIR_BIT_NONE , ///< 18 invalid
TRACKDIR_BIT_NONE , ///< 19 invalid
TRACKDIR_BIT_NONE , ///< 20 invalid
TRACKDIR_BIT_NONE , ///< 21 invalid
TRACKDIR_BIT_NONE , ///< 22 invalid
TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_SE, ///< 23 SLOPE_STEEP_S -> inclined for diagonal track
TRACKDIR_BIT_NONE , ///< 24 invalid
TRACKDIR_BIT_NONE , ///< 25 invalid
TRACKDIR_BIT_NONE , ///< 26 invalid
TRACKDIR_BIT_X_SW | TRACKDIR_BIT_Y_NW, ///< 27 SLOPE_STEEP_W -> inclined for diagonal track
TRACKDIR_BIT_NONE , ///< 28 invalid
TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_NW, ///< 29 SLOPE_STEEP_N -> inclined for diagonal track
TRACKDIR_BIT_X_NE | TRACKDIR_BIT_Y_SE, ///< 30 SLOPE_STEEP_E -> inclined for diagonal track
{}, // 0 SLOPE_FLAT
{Trackdir::X_SW, Trackdir::Y_NW}, // 1 SLOPE_W -> inclined for diagonal track
{Trackdir::X_SW, Trackdir::Y_SE}, // 2 SLOPE_S -> inclined for diagonal track
{Trackdir::X_SW}, // 3 SLOPE_SW
{Trackdir::X_NE, Trackdir::Y_SE}, // 4 SLOPE_E -> inclined for diagonal track
{}, // 5 SLOPE_EW
{Trackdir::Y_SE}, // 6 SLOPE_SE
{}, // 7 SLOPE_WSE -> leveled
{Trackdir::X_NE, Trackdir::Y_NW}, // 8 SLOPE_N -> inclined for diagonal track
{Trackdir::Y_NW}, // 9 SLOPE_NW
{}, // 10 SLOPE_NS
{}, // 11 SLOPE_NWS -> leveled
{Trackdir::X_NE}, // 12 SLOPE_NE
{}, // 13 SLOPE_ENW -> leveled
{}, // 14 SLOPE_SEN -> leveled
{}, // 15 invalid
{}, // 16 invalid
{}, // 17 invalid
{}, // 18 invalid
{}, // 19 invalid
{}, // 20 invalid
{}, // 21 invalid
{}, // 22 invalid
{Trackdir::X_SW, Trackdir::Y_SE}, // 23 SLOPE_STEEP_S -> inclined for diagonal track
{}, // 24 invalid
{}, // 25 invalid
{}, // 26 invalid
{Trackdir::X_SW, Trackdir::Y_NW}, // 27 SLOPE_STEEP_W -> inclined for diagonal track
{}, // 28 invalid
{Trackdir::X_NE, Trackdir::Y_NW}, // 29 SLOPE_STEEP_N -> inclined for diagonal track
{Trackdir::X_NE, Trackdir::Y_SE}, // 30 SLOPE_STEEP_E -> inclined for diagonal track
};
+31 -47
View File
@@ -10,13 +10,10 @@
#ifndef TRACK_FUNC_H
#define TRACK_FUNC_H
#include "core/bitmath_func.hpp"
#include "track_type.h"
#include "direction_func.h"
#include "slope_func.h"
using SetTrackdirBitIterator = SetBitIterator<Trackdir, TrackdirBits>;
/**
* Checks if a Track is valid.
*
@@ -38,7 +35,7 @@ inline bool IsValidTrack(Track track)
*/
inline bool IsValidTrackdirForRoadVehicle(Trackdir trackdir)
{
return trackdir < TRACKDIR_END;
return trackdir < Trackdir::End;
}
/**
@@ -50,7 +47,7 @@ inline bool IsValidTrackdirForRoadVehicle(Trackdir trackdir)
*/
inline bool IsValidTrackdir(Trackdir trackdir)
{
return trackdir != INVALID_TRACKDIR && ((1 << trackdir & TRACKDIR_BIT_MASK) != TRACKDIR_BIT_NONE);
return trackdir < Trackdir::End && TRACKDIR_BIT_MASK.Test(trackdir);
}
/**
@@ -89,7 +86,7 @@ inline TrackBits CornerToTrackBits(Corner corner)
inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir)
{
assert(IsValidTrackdir(trackdir));
return static_cast<TrackdirBits>(1 << trackdir);
return trackdir;
}
/**
@@ -121,8 +118,8 @@ inline Track RemoveFirstTrack(TrackBits *tracks)
*
* This function searches for the first bit in the TrackdirBits parameter,
* remove this bit from the parameter and returns the fnound bit as
* Trackdir value. It returns INVALID_TRACKDIR if the trackdirs is
* TRACKDIR_BIT_NONE or INVALID_TRACKDIR_BIT. This is basically used in a
* Trackdir value. It returns Trackdir::Invalid if the trackdirs is
* empty or INVALID_TRACKDIR_BIT. This is basically used in a
* while-loop to get all track-directions step by step until the value
* reaches TRACKDIR_BIT_NONE.
*
@@ -132,13 +129,12 @@ inline Track RemoveFirstTrack(TrackBits *tracks)
*/
inline Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs)
{
if (*trackdirs != TRACKDIR_BIT_NONE && *trackdirs != INVALID_TRACKDIR_BIT) {
assert((*trackdirs & ~TRACKDIR_BIT_MASK) == TRACKDIR_BIT_NONE);
Trackdir first = (Trackdir)FindFirstBit(*trackdirs);
ClrBit(*trackdirs, first);
return first;
}
return INVALID_TRACKDIR;
if (trackdirs->None() || *trackdirs == INVALID_TRACKDIR_BIT) return Trackdir::Invalid;
assert(!trackdirs->Any({Trackdir::RvRev_NE, Trackdir::RvRev_SE, Trackdir::RvRev_SW, Trackdir::RvRev_NW}));
Trackdir first = trackdirs->GetNthSetBit(0).value();
trackdirs->Reset(first);
return first;
}
/**
@@ -174,21 +170,21 @@ inline Track TrackBitsToTrack(TrackBits tracks)
}
/**
* Returns first Trackdir from TrackdirBits or INVALID_TRACKDIR
* Returns first Trackdir from TrackdirBits or Trackdir::Invalid
*
* This function returns the first Trackdir in the given TrackdirBits value or
* INVALID_TRACKDIR if the value is TRACKDIR_BIT_NONE. The TrackdirBits must
* Trackdir::Invalid if the value is empty. The TrackdirBits must
* not be INVALID_TRACKDIR_BIT.
*
* @param trackdirs The TrackdirBits value
* @return The first Trackdir from the TrackdirBits or INVALID_TRACKDIR on TRACKDIR_BIT_NONE.
* @return The first Trackdir from the TrackdirBits or Trackdir::Invalid on empty.
* @pre trackdirs must not be INVALID_TRACKDIR_BIT
* @see RemoveFirstTrackdir
*/
inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs)
{
assert((trackdirs & ~TRACKDIR_BIT_MASK) == TRACKDIR_BIT_NONE);
return (trackdirs != TRACKDIR_BIT_NONE) ? (Trackdir)FindFirstBit(trackdirs) : INVALID_TRACKDIR;
assert(!trackdirs.Any({Trackdir::RvRev_NE, Trackdir::RvRev_SE, Trackdir::RvRev_SW, Trackdir::RvRev_NW}));
return trackdirs.GetNthSetBit(0).value_or(Trackdir::Invalid);
}
/*
@@ -219,12 +215,12 @@ inline Track TrackToOppositeTrack(Track t)
*
* @param trackdir The Trackdir value
* @return The reverse trackdir
* @pre trackdir must not be INVALID_TRACKDIR
* @pre trackdir must not be Trackdir::Invalid
*/
inline Trackdir ReverseTrackdir(Trackdir trackdir)
{
assert(IsValidTrackdirForRoadVehicle(trackdir));
return (Trackdir)(trackdir ^ 8);
return static_cast<Trackdir>(to_underlying(trackdir) ^ 8);
}
/**
@@ -239,7 +235,7 @@ inline Trackdir ReverseTrackdir(Trackdir trackdir)
inline Track TrackdirToTrack(Trackdir trackdir)
{
assert(IsValidTrackdir(trackdir));
return static_cast<Track>(trackdir & 0x7);
return static_cast<Track>(to_underlying(trackdir) & 0x7);
}
/**
@@ -256,7 +252,7 @@ inline Track TrackdirToTrack(Trackdir trackdir)
inline Trackdir TrackToTrackdir(Track track)
{
assert(IsValidTrack(track));
return (Trackdir)track;
return static_cast<Trackdir>(track);
}
/**
@@ -271,7 +267,7 @@ inline Trackdir TrackToTrackdir(Track track)
inline TrackdirBits TrackToTrackdirBits(Track track)
{
Trackdir td = TrackToTrackdir(track);
return static_cast<TrackdirBits>(TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td)));
return TrackdirToTrackdirBits(td) | TrackdirToTrackdirBits(ReverseTrackdir(td));
}
/**
@@ -284,7 +280,7 @@ inline TrackdirBits TrackToTrackdirBits(Track track)
*/
inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits)
{
return static_cast<TrackBits>((bits | (bits >> 8)) & TRACK_BIT_ALL.base());
return static_cast<TrackBits>((bits.base() | (bits.base() >> 8)) & TRACK_BIT_ALL.base());
}
/**
@@ -298,18 +294,6 @@ inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits)
return static_cast<TrackdirBits>(bits.base() * 0x101);
}
/**
* Checks whether a TrackdirBits has a given Trackdir.
* @param trackdirs The trackdir bits.
* @param trackdir The trackdir to check.
* @return \c true iff \c trackdir is in \c trackdirs.
*/
inline bool HasTrackdir(TrackdirBits trackdirs, Trackdir trackdir)
{
assert(IsValidTrackdir(trackdir));
return HasBit(trackdirs, trackdir);
}
/**
* Maps a trackdir to the trackdir that you will end up on if you go straight
* ahead.
@@ -368,15 +352,15 @@ inline DiagDirection TrackdirToExitdir(Trackdir trackdir)
* with the exit in the given direction.
*
* For the diagonal tracks the resulting track direction are clear for a given
* DiagDirection. It either matches the direction or it returns INVALID_TRACKDIR,
* DiagDirection. It either matches the direction or it returns Trackdir::Invalid,
* as a Track::X cannot be applied with DIAG_SE.
* For the straight tracks the resulting track direction will be the
* direction which the DiagDirection is pointing. But this will be INVALID_TRACKDIR
* direction which the DiagDirection is pointing. But this will be Trackdir::Invalid
* if the DiagDirection is pointing 'away' the track.
*
* @param track The track to apply an direction on
* @param diagdir The DiagDirection to apply on
* @return The resulting track direction or INVALID_TRACKDIR if not possible.
* @return The resulting track direction or Trackdir::Invalid if not possible.
*/
inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir)
{
@@ -391,17 +375,17 @@ inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir)
* with the entry in the given direction.
*
* For the diagonal tracks the return value is clear, its either the matching
* track direction or INVALID_TRACKDIR.
* track direction or Trackdir::Invalid.
* For the straight tracks this returns the track direction which results if
* you follow the DiagDirection and then turn by 45 deg left or right on the
* next tile. The new direction on the new track will be the returning Trackdir
* value. If the parameters makes no sense like the track Track::Upper and the
* direction DiagDirection::NE (target track cannot be reached) this function returns
* INVALID_TRACKDIR.
* Trackdir::Invalid.
*
* @param track The target track
* @param diagdir The direction to "come from"
* @return the resulting Trackdir or INVALID_TRACKDIR if not possible.
* @return the resulting Trackdir or Trackdir::Invalid if not possible.
*/
inline Trackdir TrackEnterdirToTrackdir(Track track, DiagDirection diagdir)
{
@@ -584,7 +568,7 @@ inline bool TrackOverlapsTracks(TrackBits tracks, Track track)
inline bool IsReversingRoadTrackdir(Trackdir dir)
{
assert(IsValidTrackdirForRoadVehicle(dir));
return (dir & 0x07) >= 6;
return (to_underlying(dir) & 0x07) >= 6;
}
/**
@@ -595,7 +579,7 @@ inline bool IsReversingRoadTrackdir(Trackdir dir)
inline bool IsStraightRoadTrackdir(Trackdir dir)
{
assert(IsValidTrackdirForRoadVehicle(dir));
return (dir & 0x06) == 0;
return (to_underlying(dir) & 0x06) == 0;
}
/**
@@ -612,7 +596,7 @@ inline bool IsUphillTrackdir(Slope slope, Trackdir dir)
{
assert(IsValidTrackdirForRoadVehicle(dir));
extern const TrackdirBits _uphill_trackdirs[];
return HasBit(_uphill_trackdirs[RemoveHalftileSlope(slope)], dir);
return _uphill_trackdirs[RemoveHalftileSlope(slope)].Test(dir);
}
/**
+31 -48
View File
@@ -60,63 +60,46 @@ static constexpr TrackBits TRACK_BIT_ALL = {Track::X, Track::Y, Track::Upper, Tr
* reversing track dirs are not considered to be 'valid' except in a small
* corner in the road vehicle controller.
*/
enum Trackdir : uint8_t {
TRACKDIR_BEGIN = 0, ///< Used for iterations
TRACKDIR_X_NE = 0, ///< X-axis and direction to north-east
TRACKDIR_Y_SE = 1, ///< Y-axis and direction to south-east
TRACKDIR_UPPER_E = 2, ///< Upper track and direction to east
TRACKDIR_LOWER_E = 3, ///< Lower track and direction to east
TRACKDIR_LEFT_S = 4, ///< Left track and direction to south
TRACKDIR_RIGHT_S = 5, ///< Right track and direction to south
TRACKDIR_RVREV_NE = 6, ///< (Road vehicle) reverse direction north-east
TRACKDIR_RVREV_SE = 7, ///< (Road vehicle) reverse direction south-east
TRACKDIR_X_SW = 8, ///< X-axis and direction to south-west
TRACKDIR_Y_NW = 9, ///< Y-axis and direction to north-west
TRACKDIR_UPPER_W = 10, ///< Upper track and direction to west
TRACKDIR_LOWER_W = 11, ///< Lower track and direction to west
TRACKDIR_LEFT_N = 12, ///< Left track and direction to north
TRACKDIR_RIGHT_N = 13, ///< Right track and direction to north
TRACKDIR_RVREV_SW = 14, ///< (Road vehicle) reverse direction south-west
TRACKDIR_RVREV_NW = 15, ///< (Road vehicle) reverse direction north-west
TRACKDIR_END, ///< Used for iterations
INVALID_TRACKDIR = 0xFF, ///< Flag for an invalid trackdir
};
enum class Trackdir : uint8_t {
X_NE = 0, ///< X-axis and direction to north-east
Y_SE = 1, ///< Y-axis and direction to south-east
Upper_E = 2, ///< Upper track and direction to east
Lower_E = 3, ///< Lower track and direction to east
Left_S = 4, ///< Left track and direction to south
Right_S = 5, ///< Right track and direction to south
RvRev_NE = 6, ///< (Road vehicle) reverse direction north-east
RvRev_SE = 7, ///< (Road vehicle) reverse direction south-east
X_SW = 8, ///< X-axis and direction to south-west
Y_NW = 9, ///< Y-axis and direction to north-west
Upper_W = 10, ///< Upper track and direction to west
Lower_W = 11, ///< Lower track and direction to west
Left_N = 12, ///< Left track and direction to north
Right_N = 13, ///< Right track and direction to north
RvRev_SW = 14, ///< (Road vehicle) reverse direction south-west
RvRev_NW = 15, ///< (Road vehicle) reverse direction north-west
/** Allow incrementing of Trackdir variables */
DECLARE_INCREMENT_DECREMENT_OPERATORS(Trackdir)
End, ///< End marker
Invalid = 0xFF, ///< Flag for an invalid trackdir
};
/**
* Array with \c Trackdir as index.
* @tparam T the type contained within the array.
*/
template <typename T>
using TrackdirIndexArray = EnumIndexArray<T, Trackdir, TRACKDIR_END>;
using TrackdirIndexArray = EnumIndexArray<T, Trackdir, Trackdir::End>;
/**
* Enumeration of bitmasks for the TrackDirs
*
* These are a combination of tracks and directions. Values are 0-5 in one
* direction (corresponding to the Track enum) and 8-13 in the other direction.
*/
enum TrackdirBits : uint16_t {
TRACKDIR_BIT_NONE = 0U, ///< No track build
TRACKDIR_BIT_X_NE = 1U << TRACKDIR_X_NE, ///< Track x-axis, direction north-east
TRACKDIR_BIT_Y_SE = 1U << TRACKDIR_Y_SE, ///< Track y-axis, direction south-east
TRACKDIR_BIT_UPPER_E = 1U << TRACKDIR_UPPER_E, ///< Track upper, direction east
TRACKDIR_BIT_LOWER_E = 1U << TRACKDIR_LOWER_E, ///< Track lower, direction east
TRACKDIR_BIT_LEFT_S = 1U << TRACKDIR_LEFT_S, ///< Track left, direction south
TRACKDIR_BIT_RIGHT_S = 1U << TRACKDIR_RIGHT_S, ///< Track right, direction south
/* Again, note the two missing values here. This enables trackdir -> track conversion by doing (trackdir & 0xFF) */
TRACKDIR_BIT_X_SW = 1U << TRACKDIR_X_SW, ///< Track x-axis, direction south-west
TRACKDIR_BIT_Y_NW = 1U << TRACKDIR_Y_NW, ///< Track y-axis, direction north-west
TRACKDIR_BIT_UPPER_W = 1U << TRACKDIR_UPPER_W, ///< Track upper, direction west
TRACKDIR_BIT_LOWER_W = 1U << TRACKDIR_LOWER_W, ///< Track lower, direction west
TRACKDIR_BIT_LEFT_N = 1U << TRACKDIR_LEFT_N, ///< Track left, direction north
TRACKDIR_BIT_RIGHT_N = 1U << TRACKDIR_RIGHT_N, ///< Track right, direction north
TRACKDIR_BIT_MASK = 0x3F3F, ///< Bitmask for bit-operations
INVALID_TRACKDIR_BIT = 0xFFFF, ///< Flag for an invalid trackdirbit value
/** Bitset of \c Trackdir elements. */
using TrackdirBits = EnumBitSet<Trackdir, uint16_t>;
/** Bitset of valid non-road vehicle trackdirs/ */
static constexpr TrackdirBits TRACKDIR_BIT_MASK{
Trackdir::X_NE, Trackdir::Y_SE, Trackdir::Upper_E, Trackdir::Lower_E, Trackdir::Left_S, Trackdir::Right_S,
Trackdir::X_SW, Trackdir::Y_NW, Trackdir::Upper_W, Trackdir::Lower_W, Trackdir::Left_N, Trackdir::Right_N,
};
DECLARE_ENUM_AS_BIT_SET(TrackdirBits)
/** Marker for an invalid TrackdirBits value. */
static constexpr TrackdirBits INVALID_TRACKDIR_BIT{UINT16_MAX};
/** Track status of a tile. */
struct TrackStatus {
+12 -12
View File
@@ -2333,7 +2333,7 @@ static void CheckNextTrainTile(Train *consist)
if (!HasReservedTracks(ft.new_tile, TrackdirBitsToTrackBits(ft.new_td_bits))) {
/* Next tile is not reserved. */
if (KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE) {
if (ft.new_td_bits.Count() == 1) {
if (HasPbsSignalOnTrackdir(ft.new_tile, FindFirstTrackdir(ft.new_td_bits))) {
/* If the next tile is a PBS signal, try to make a reservation. */
TrackBits tracks = TrackdirBitsToTrackBits(ft.new_td_bits);
@@ -2499,7 +2499,7 @@ void FreeTrainTrackReservation(const Train *consist)
tile = ft.new_tile;
TrackdirBits bits = ft.new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(tile));
td = RemoveFirstTrackdir(&bits);
assert(bits == TRACKDIR_BIT_NONE);
assert(bits.None());
if (!IsValidTrackdir(td)) break;
@@ -2573,19 +2573,19 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
TileIndex tile = origin.tile;
Trackdir cur_td = origin.trackdir;
while (ft.Follow(tile, cur_td)) {
if (KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE) {
if (ft.new_td_bits.Count() == 1) {
/* Possible signal tile. */
if (HasOnewaySignalBlockingTrackdir(ft.new_tile, FindFirstTrackdir(ft.new_td_bits))) break;
}
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) {
ft.new_td_bits &= ~TrackdirCrossesTrackdirs(ft.old_td);
if (ft.new_td_bits == TRACKDIR_BIT_NONE) break;
ft.new_td_bits.Reset(TrackdirCrossesTrackdirs(ft.old_td));
if (ft.new_td_bits.None()) break;
}
/* Station, depot or waypoint are a possible target. */
bool target_seen = ft.is_station || (IsTileType(ft.new_tile, TileType::Railway) && !IsPlainRail(ft.new_tile));
if (target_seen || KillFirstBit(ft.new_td_bits) != TRACKDIR_BIT_NONE) {
if (target_seen || ft.new_td_bits.Count() > 1) {
/* Choice found or possible target encountered.
* On finding a possible target, we need to stop and let the pathfinder handle the
* remaining path. This is because we don't know if this target is in one of our
@@ -2645,10 +2645,10 @@ static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks,
if (!ft.Follow(tile, cur_td)) break;
if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) {
ft.new_td_bits &= ~TrackdirCrossesTrackdirs(ft.old_td);
assert(ft.new_td_bits != TRACKDIR_BIT_NONE);
ft.new_td_bits.Reset(TrackdirCrossesTrackdirs(ft.old_td));
assert(ft.new_td_bits.Any());
}
assert(KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE);
assert(ft.new_td_bits.Count() == 1);
tile = ft.new_tile;
cur_td = FindFirstTrackdir(ft.new_td_bits);
@@ -2808,7 +2808,7 @@ static Track ChooseTrainTrack(Train *consist, TileIndex tile, DiagDirection ente
const Train *moving_front = consist->GetMovingFront();
PBSTileInfo res_dest(tile, INVALID_TRACKDIR, false);
PBSTileInfo res_dest(tile, Trackdir::Invalid, false);
DiagDirection dest_enterdir = enterdir;
if (do_track_reservation) {
res_dest = ExtendTrainReservation(consist, &tracks, &dest_enterdir);
@@ -3999,7 +3999,7 @@ static bool TrainCheckIfLineEnds(Train *moving_front, bool reverse)
}
/* approaching red signal */
if ((trackdirbits & red_signals) != 0) return TrainApproachingLineEnd(moving_front, true, reverse);
if (trackdirbits.Any(red_signals)) return TrainApproachingLineEnd(moving_front, true, reverse);
/* approaching a rail/road crossing? then make it red */
if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile);
@@ -4298,7 +4298,7 @@ void Train::OnNewEconomyDay()
*/
Trackdir Train::GetVehicleTrackdir() const
{
if (this->vehstatus.Test(VehState::Crashed)) return INVALID_TRACKDIR;
if (this->vehstatus.Test(VehState::Crashed)) return Trackdir::Invalid;
if (this->track == Track::Depot) {
/* We'll assume the train is facing outwards */
+3 -3
View File
@@ -1857,7 +1857,7 @@ static TrackStatus GetTileTrackStatus_TunnelBridge(TileIndex tile, TransportType
DiagDirection dir = GetTunnelBridgeDirection(tile);
if (side != DiagDirection::Invalid && side != ReverseDiagDir(dir)) return {};
return {TrackBitsToTrackdirBits(DiagDirToDiagTrack(dir)), TRACKDIR_BIT_NONE};
return {TrackBitsToTrackdirBits(DiagDirToDiagTrack(dir)), {}};
}
/** @copydoc ChangeTileOwnerProc */
@@ -2017,7 +2017,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
/* We're at the tunnel exit ?? */
if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) {
rv->tile = tile;
rv->state = DiagDirToDiagTrackdir(vdir);
rv->state = to_underlying(DiagDirToDiagTrackdir(vdir));
rv->frame = frame;
rv->vehstatus.Reset(VehState::Hidden);
return VehicleEnterTileState::EnteredWormhole;
@@ -2073,7 +2073,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde
case VehicleType::Road: {
RoadVehicle *rv = RoadVehicle::From(v);
if (rv->state == RVSB_WORMHOLE) {
rv->state = DiagDirToDiagTrackdir(vdir);
rv->state = to_underlying(DiagDirToDiagTrackdir(vdir));
rv->frame = 0;
return VehicleEnterTileState::EnteredWormhole;
}
+1 -1
View File
@@ -599,7 +599,7 @@ public:
* in depots), returns 0xFF.
* @return the trackdir of the vehicle
*/
virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
virtual Trackdir GetVehicleTrackdir() const { return Trackdir::Invalid; }
/**
* Gets the running cost of a vehicle that can be sent into string parameters for string processing.
+1 -1
View File
@@ -1403,7 +1403,7 @@ static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode,
/* NW border: remove tracks that connects NW tile edge */
ts.Reset({Track::Y, Track::Left, Track::Upper});
}
return {TrackBitsToTrackdirBits(ts), TRACKDIR_BIT_NONE};
return {TrackBitsToTrackdirBits(ts), {}};
}
/** @copydoc ClickTileProc */