diff --git a/src/economy.cpp b/src/economy.cpp index a5161490c0..4cac152b64 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -485,7 +485,7 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) * because of different owner of crossing and approaching train */ for (const auto tile : Map::Iterate()) { if (IsTileType(tile, TileType::Railway) && IsTileOwner(tile, new_owner) && HasSignals(tile)) { - for (Track track : SetTrackBitIterator(GetTrackBits(tile))) { + for (Track track : GetTrackBits(tile)) { if (IsSignalPresent(tile, SignalOnTrack(track))) AddTrackToSignalBuffer(tile, track, new_owner); } } else if (IsLevelCrossingTile(tile) && IsTileOwner(tile, new_owner)) { diff --git a/src/elrail.cpp b/src/elrail.cpp index 667cda7815..7ca580182f 100644 --- a/src/elrail.cpp +++ b/src/elrail.cpp @@ -87,35 +87,36 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, DiagDirections *override { switch (GetTileType(t)) { case TileType::Railway: - if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE; + if (!HasRailCatenary(GetRailType(t))) return {}; switch (GetRailTileType(t)) { - case RailTileType::Normal: case RailTileType::Signals: + case RailTileType::Normal: + case RailTileType::Signals: return GetTrackBits(t); default: - return TRACK_BIT_NONE; + return {}; } break; case TileType::TunnelBridge: - if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return TRACK_BIT_NONE; - if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE; + if (GetTunnelBridgeTransportType(t) != TRANSPORT_RAIL) return {}; + if (!HasRailCatenary(GetRailType(t))) return {}; if (override != nullptr && (IsTunnel(t) || GetTunnelBridgeLength(t, GetOtherBridgeEnd(t)) > 0)) { *override = GetTunnelBridgeDirection(t); } - return DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)); + return DiagDirToDiagTrack(GetTunnelBridgeDirection(t)); case TileType::Road: - if (!IsLevelCrossing(t)) return TRACK_BIT_NONE; - if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE; - return GetCrossingRailBits(t); + if (!IsLevelCrossing(t)) return {}; + if (!HasRailCatenary(GetRailType(t))) return {}; + return GetCrossingRailTrack(t); case TileType::Station: - if (!HasStationRail(t)) return TRACK_BIT_NONE; - if (!HasRailCatenary(GetRailType(t))) return TRACK_BIT_NONE; - return TrackToTrackBits(GetRailStationTrack(t)); + if (!HasStationRail(t)) return {}; + if (!HasRailCatenary(GetRailType(t))) return {}; + return GetRailStationTrack(t); default: - return TRACK_BIT_NONE; + return {}; } } @@ -128,7 +129,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, DiagDirections *override static TrackBits MaskWireBits(TileIndex t, TrackBits tracks) { /* Single track bits are never masked out. */ - if (HasAtMostOneBit(tracks)) [[likely]] return tracks; + if (tracks.Count() <= 1) [[likely]] return tracks; if (!IsPlainRailTile(t)) return tracks; @@ -141,7 +142,7 @@ static TrackBits MaskWireBits(TileIndex t, TrackBits tracks) TileIndex next_tile = TileAddByDiagDir(t, d); RailType rt = GetTileRailType(next_tile); if (rt == INVALID_RAILTYPE || !HasRailCatenary(rt) || - ((TrackdirBitsToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & DiagdirReachesTracks(d)) == TRACK_BIT_NONE && + (!TrackdirBitsToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Any(DiagdirReachesTracks(d)) && (!HasStationTileRail(next_tile) || GetRailStationAxis(next_tile) != DiagDirToAxis(d) || !CanStationTileHaveWires(next_tile)))) { neighbour_tdb |= DiagdirReachesTrackdirs(ReverseDiagDir(d)); } @@ -154,24 +155,24 @@ 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 = ~(TrackBits)((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_MASK); + mask = static_cast(~((neighbour_tdb & (neighbour_tdb >> 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_MASK) == TRACK_BIT_MASK) mask = ~TrackdirBitsToTrackBits(neighbour_tdb); + if (tracks != TRACK_BIT_CROSS && mask == TRACK_BIT_ALL) mask = TrackdirBitsToTrackBits(neighbour_tdb).Flip(TRACK_BIT_ALL); } else { /* Require only one marked trackdir to mask the track. */ - mask = ~TrackdirBitsToTrackBits(neighbour_tdb); + mask = TrackdirBitsToTrackBits(neighbour_tdb).Flip(TRACK_BIT_ALL); /* If that results in an empty set, require both trackdirs for diagonal track. */ - if ((tracks & mask) == TRACK_BIT_NONE) { - if ((neighbour_tdb & TRACKDIR_BIT_X_NE) == 0 || (neighbour_tdb & TRACKDIR_BIT_X_SW) == 0) mask |= TRACK_BIT_X; - if ((neighbour_tdb & TRACKDIR_BIT_Y_NW) == 0 || (neighbour_tdb & TRACKDIR_BIT_Y_SE) == 0) mask |= TRACK_BIT_Y; + 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 that still is not enough, require both trackdirs for any track. */ - if ((tracks & mask) == TRACK_BIT_NONE) mask = ~(TrackBits)((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_MASK); + if (!tracks.Any(mask)) mask = static_cast(~((neighbour_tdb & (neighbour_tdb >> 8)) & TRACK_BIT_ALL.base())); } } /* Mask the tracks only if at least one track bit would remain. */ - return (tracks & mask) != TRACK_BIT_NONE ? tracks & mask : tracks; + return !tracks.Any(mask) ? tracks & mask : tracks; } /** @@ -302,7 +303,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) track_config[TileSource::Home] = GetRailTrackBitsUniversal(ti->tile, &override_pcp); wire_config[TileSource::Home] = MaskWireBits(ti->tile, track_config[TileSource::Home]); /* If a track bit is present that is not in the main direction, the track is level */ - is_flat[TileSource::Home] = ((track_config[TileSource::Home] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0); + is_flat[TileSource::Home] = track_config[TileSource::Home].Any({Track::Upper, Track::Lower, Track::Left, Track::Right}); AdjustTileh(ti->tile, &tileh[TileSource::Home]); @@ -319,16 +320,16 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) tileh[TileSource::Neighbour] = GetTileSlope(neighbour); track_config[TileSource::Neighbour] = GetRailTrackBitsUniversal(neighbour, nullptr); wire_config[TileSource::Neighbour] = MaskWireBits(neighbour, track_config[TileSource::Neighbour]); - if (IsTunnelTile(neighbour) && i != GetTunnelBridgeDirection(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = TRACK_BIT_NONE; + if (IsTunnelTile(neighbour) && i != GetTunnelBridgeDirection(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = {}; /* Ignore station tiles that allow neither wires nor pylons. */ - if (HasStationTileRail(neighbour) && !CanStationTileHavePylons(neighbour) && !CanStationTileHaveWires(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = TRACK_BIT_NONE; + if (HasStationTileRail(neighbour) && !CanStationTileHavePylons(neighbour) && !CanStationTileHaveWires(neighbour)) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = {}; /* If the neighboured tile does not smoothly connect to the current tile (because of a foundation), * we have to draw all pillars on the current tile. */ - if (elevation != GetPCPElevation(neighbour, ReverseDiagDir(i))) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = TRACK_BIT_NONE; + if (elevation != GetPCPElevation(neighbour, ReverseDiagDir(i))) wire_config[TileSource::Neighbour] = track_config[TileSource::Neighbour] = {}; - is_flat[TileSource::Neighbour] = ((track_config[TileSource::Neighbour] & (TRACK_BIT_HORZ | TRACK_BIT_VERT)) != 0); + is_flat[TileSource::Neighbour] = track_config[TileSource::Neighbour].Any({Track::Upper, Track::Lower, Track::Left, Track::Right}); ppp_preferred[i] = DIRECTIONS_ALL; // We start with preferring everything (end-of-line in any direction) ppp_allowed[i] = _allowed_ppp_on_pcp[i]; @@ -346,7 +347,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) /* We check whether the track in question (k) is present in the tile * (TrackSourceTile) */ DiagDirection pcp_pos = i; - if (HasBit(wire_config[_track_source_tile[i][k]], _tracks_at_pcp[i][k])) { + if (wire_config[_track_source_tile[i][k]].Test(_tracks_at_pcp[i][k])) { /* track found, if track is in the neighbour tile, adjust the number * of the PCP for preferred/allowed determination*/ pcp_pos = (_track_source_tile[i][k] == TileSource::Home) ? i : ReverseDiagDir(i); @@ -354,7 +355,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) ppp_preferred[i] &= _preferred_ppp_of_track_at_pcp[_tracks_at_pcp[i][k]][pcp_pos]; } - if (HasBit(track_config[_track_source_tile[i][k]], _tracks_at_pcp[i][k])) { + if (track_config[_track_source_tile[i][k]].Test(_tracks_at_pcp[i][k])) { ppp_allowed[i].Reset(_disallowed_ppp_of_track_at_pcp[_tracks_at_pcp[i][k]][pcp_pos]); } } @@ -371,7 +372,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) if (IsTileType(neighbour, TileType::Station) || IsTileType(neighbour, TileType::Road)) tileh[TileSource::Neighbour] = SLOPE_FLAT; /* Read the foundations if they are present, and adjust the tileh */ - if (track_config[TileSource::Neighbour] != TRACK_BIT_NONE && IsTileType(neighbour, TileType::Railway) && HasRailCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TileSource::Neighbour], track_config[TileSource::Neighbour]); + if (track_config[TileSource::Neighbour].Any() && IsTileType(neighbour, TileType::Railway) && HasRailCatenary(GetRailType(neighbour))) foundation = GetRailFoundation(tileh[TileSource::Neighbour], track_config[TileSource::Neighbour]); if (IsBridgeTile(neighbour)) { foundation = GetBridgeFoundation(tileh[TileSource::Neighbour], DiagDirToAxis(GetTunnelBridgeDirection(neighbour))); } @@ -423,7 +424,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) /* Don't build the pylon if it would be outside the tile */ if (!_owned_ppp_on_pcp[i].Test(temp)) { /* We have a neighbour that will draw it, bail out */ - if (track_config[TileSource::Neighbour] != TRACK_BIT_NONE) break; + if (track_config[TileSource::Neighbour].Any()) break; continue; // No neighbour, go looking for a better position } @@ -453,15 +454,15 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) SpriteID wire_halftile = (halftile_corner != CORNER_INVALID) ? GetWireBase(ti->tile, TCX_UPPER_HALFTILE) : wire_normal; Track halftile_track; switch (halftile_corner) { - case CORNER_W: halftile_track = TRACK_LEFT; break; - case CORNER_S: halftile_track = TRACK_LOWER; break; - case CORNER_E: halftile_track = TRACK_RIGHT; break; - case CORNER_N: halftile_track = TRACK_UPPER; break; - default: halftile_track = INVALID_TRACK; break; + case CORNER_W: halftile_track = Track::Left; break; + case CORNER_S: halftile_track = Track::Lower; break; + case CORNER_E: halftile_track = Track::Right; break; + case CORNER_N: halftile_track = Track::Upper; break; + default: halftile_track = Track::Invalid; break; } /* Drawing of pylons is finished, now draw the wires */ - for (Track t : SetTrackBitIterator(wire_config[TileSource::Home])) { + for (Track t : wire_config[TileSource::Home]) { SpriteID wire_base = (t == halftile_track) ? wire_halftile : wire_normal; uint8_t pcp_config = pcp_status.Test(_pcp_positions[t][0]) + (pcp_status.Test(_pcp_positions[t][1]) << 1); @@ -469,7 +470,7 @@ static void DrawRailCatenaryRailway(const TileInfo *ti) assert(pcp_config != 0); // We have a pylon on neither end of the wire, that doesn't work (since we have no sprites for that) assert(!IsSteepSlope(tileh[TileSource::Home])); - const SortableSpriteStruct &sss = _rail_catenary_sprite_data[_rail_wires[tileh_selector][t][pcp_config]]; + const SortableSpriteStruct &sss = _rail_catenary_sprite_data[_rail_wires[tileh_selector][to_underlying(t)][pcp_config]]; /* * The "wire"-sprite position is inside the tile, i.e. 0 <= sss->?_offset < TILE_SIZE. diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 7e9900487b..9122c18320 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -920,7 +920,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec case VehicleType::Train: { Train *t = Train::From(v); switch (variable - 0x80) { - case 0x62: return t->track; + case 0x62: return t->track.base(); case 0x66: return t->railtypes.GetNthSetBit(0).value_or(RailType::INVALID_RAILTYPE); case 0x73: return 0x80 + VEHICLE_LENGTH - t->gcache.cached_veh_length; case 0x74: return t->gcache.cached_power; @@ -951,7 +951,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec case VehicleType::Ship: { Ship *s = Ship::From(v); switch (variable - 0x80) { - case 0x62: return s->state; + case 0x62: return s->state.base(); } break; } diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 32c6483115..ccebb19e53 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -222,7 +222,7 @@ static uint32_t GetRailContinuationInfo(TileIndex tile) for (i = 0; i < lengthof(x_dir); i++, dir++, diagdir++) { TileIndex neighbour_tile = tile + TileOffsByDir(*dir); TrackBits trackbits = TrackdirBitsToTrackBits(GetTileTrackStatus(neighbour_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs); - if (trackbits != TRACK_BIT_NONE) { + if (trackbits.Any()) { /* If there is any track on the tile, set the bit in the second byte */ SetBit(res, i + 8); @@ -233,7 +233,7 @@ static uint32_t GetRailContinuationInfo(TileIndex tile) } /* If any track reaches our exit direction, set the bit in the lower byte */ - if (trackbits & DiagdirReachesTracks(*diagdir)) SetBit(res, i); + if (trackbits.Any(DiagdirReachesTracks(*diagdir))) SetBit(res, i); } } diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index 36c80a7576..3b397f1616 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -194,8 +194,8 @@ struct CFollowTrackT { /* Mask already reserved trackdirs. */ this->new_td_bits &= ~TrackBitsToTrackdirBits(reserved); /* Mask out all trackdirs that conflict with the reservation. */ - for (Track t : SetTrackBitIterator(TrackdirBitsToTrackBits(this->new_td_bits))) { - if (TracksOverlap(reserved | TrackToTrackBits(t))) this->new_td_bits &= ~TrackToTrackdirBits(t); + for (Track t : TrackdirBitsToTrackBits(this->new_td_bits)) { + if (TracksOverlap(reserved | t)) this->new_td_bits &= ~TrackToTrackdirBits(t); } if (this->new_td_bits == TRACKDIR_BIT_NONE) { this->err = EC_RESERVED; diff --git a/src/pathfinder/yapf/yapf.h b/src/pathfinder/yapf/yapf.h index d0a8660e76..e93c2ac840 100644 --- a/src/pathfinder/yapf/yapf.h +++ b/src/pathfinder/yapf/yapf.h @@ -23,7 +23,7 @@ * @param tile the tile to find the path from (should be next tile the ship is about to enter) * @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_TRACK if the path could not be found + * @return the best trackdir for next turn or Track::Invalid if the path could not be found */ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipPathCache &path_cache); diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index b08a90e765..b9e85a54ad 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -119,8 +119,8 @@ public: inline int SwitchCost(TileIndex tile1, TileIndex tile2, DiagDirection exitdir) { if (IsPlainRailTile(tile1) && IsPlainRailTile(tile2)) { - bool t1 = KillFirstBit(GetTrackBits(tile1) & DiagdirReachesTracks(ReverseDiagDir(exitdir))) != TRACK_BIT_NONE; - bool t2 = KillFirstBit(GetTrackBits(tile2) & DiagdirReachesTracks(exitdir)) != TRACK_BIT_NONE; + bool t1 = (GetTrackBits(tile1) & DiagdirReachesTracks(ReverseDiagDir(exitdir))).Count() > 1; + bool t2 = (GetTrackBits(tile2) & DiagdirReachesTracks(exitdir)).Count() > 1; if (t1 && t2) return Yapf().PfGetSettings().rail_doubleslip_penalty; } return 0; diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index 6d4e8b66c9..c3a18ac38b 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -227,7 +227,7 @@ public: if (target != nullptr) target->okay = true; if (Yapf().CanUseGlobalCache(*this->res_dest_node)) { - YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK); + YapfNotifyTrackLayoutChange(INVALID_TILE, Track::Invalid); } return true; @@ -628,7 +628,7 @@ bool YapfTrainCheckReverse(const Train *v) } } - if (moving_front->track == TRACK_BIT_WORMHOLE) { + if (moving_front->track == Track::Wormhole) { /* front in tunnel / on bridge */ DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile); @@ -643,7 +643,7 @@ bool YapfTrainCheckReverse(const Train *v) reverse_penalty -= DistanceManhattan(cur_tile, tile) * YAPF_TILE_LENGTH; } - if (moving_back->track == TRACK_BIT_WORMHOLE) { + if (moving_back->track == Track::Wormhole) { /* back in tunnel / on bridge */ DiagDirection dir_into_wormhole = GetTunnelBridgeDirection(tile_rev); diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp index 01413068e6..3e15f099d8 100644 --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -165,7 +165,7 @@ public: } /** - * Returns a random tile/trackdir that can be reached from the current tile/trackdir, or tile/INVALID_TRACK if none is available. + * Returns a random tile/trackdir that can be reached from the current tile/trackdir, or tile/Track::Invalid if none is available. * @param v The ship to get the direction for. * @param tile The start tile. * @param dir the start direction. @@ -440,7 +440,7 @@ Track YapfShipChooseTrack(const Ship *v, TileIndex tile, bool &path_found, ShipP Trackdir best_origin_dir = INVALID_TRACKDIR; 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) : INVALID_TRACK; + return (td_ret != INVALID_TRACKDIR) ? TrackdirToTrack(td_ret) : Track::Invalid; } bool YapfShipCheckReverse(const Ship *v, Trackdir *trackdir) diff --git a/src/pbs.cpp b/src/pbs.cpp index 1f6cbf2c93..00b043b2db 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -18,7 +18,7 @@ /** * Get the reserved trackbits for any tile, regardless of type. * @param t the tile - * @return the reserved trackbits. TRACK_BIT_NONE on nothing reserved or + * @return the reserved trackbits, or empty on nothing reserved or * a tile without rail. */ TrackBits GetReservedTrackbits(TileIndex t) @@ -44,7 +44,7 @@ TrackBits GetReservedTrackbits(TileIndex t) default: break; } - return TRACK_BIT_NONE; + return {}; } /** @@ -79,7 +79,7 @@ void SetRailStationPlatformReservation(TileIndex start, DiagDirection dir, bool */ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) { - assert(HasTrack(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs), t)); + assert(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Test(t)); if (_settings_client.gui.show_track_reservation) { /* show the reserved rail if needed */ @@ -124,7 +124,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) break; case TileType::TunnelBridge: - if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && !GetTunnelBridgeReservationTrackBits(tile)) { + if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL && GetTunnelBridgeReservationTrackBits(tile).None()) { SetTunnelBridgeReservation(tile, true); return true; } @@ -143,7 +143,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t, bool trigger_stations) */ void UnreserveRailTrack(TileIndex tile, Track t) { - assert(HasTrack(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs), t)); + assert(TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Test(t)); if (_settings_client.gui.show_track_reservation) { if (IsBridgeTile(tile)) { @@ -205,7 +205,7 @@ static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Tra /* Start track not reserved? This can happen if two trains * are on the same tile. The reservation on the next tile * is not ours in this case, so exit. */ - if (!HasReservedTracks(tile, TrackToTrackBits(TrackdirToTrack(trackdir)))) return PBSTileInfo(tile, trackdir, false); + if (!HasReservedTracks(tile, TrackdirToTrack(trackdir))) return PBSTileInfo(tile, trackdir, false); /* Do not disallow 90 deg turns as the setting might have changed between reserving and now. */ CFollowTrackRail ft(o, rts); @@ -282,7 +282,7 @@ static void CheckTrainsOnTrack(FindTrainOnTrackInfo &info, TileIndex tile) if (v->type != VehicleType::Train || v->vehstatus.Test(VehState::Crashed)) continue; Train *t = Train::From(v); - if (t->track == TRACK_BIT_WORMHOLE || HasBit(static_cast(t->track), TrackdirToTrack(info.res.trackdir))) { + if (t->track == Track::Wormhole || t->track.Test(TrackdirToTrack(info.res.trackdir))) { t = t->First(); /* ALWAYS return the lowest ID (anti-desync!) */ @@ -307,7 +307,7 @@ PBSTileInfo FollowTrainReservation(const Train *consist, Vehicle **train_on_res) TileIndex tile = moving_front->tile; Trackdir trackdir = moving_front->GetVehicleTrackdir(); - if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) return PBSTileInfo(tile, trackdir, false); + if (IsRailDepotTile(tile) && GetDepotReservationTrackBits(tile).None()) return PBSTileInfo(tile, trackdir, false); FindTrainOnTrackInfo ftoti; ftoti.res = FollowReservation(consist->owner, GetAllCompatibleRailTypes(consist->railtypes), tile, trackdir); @@ -344,7 +344,7 @@ PBSTileInfo FollowTrainReservation(const Train *consist, Vehicle **train_on_res) */ Train *GetTrainForReservation(TileIndex tile, Track track) { - assert(HasReservedTracks(tile, TrackToTrackBits(track))); + assert(HasReservedTracks(tile, track)); Trackdir trackdir = TrackToTrackdir(track); RailTypes rts = GetRailTypeInfo(GetTileRailType(tile))->compatible_railtypes; diff --git a/src/pbs.h b/src/pbs.h index d26ce5232e..921267e27e 100644 --- a/src/pbs.h +++ b/src/pbs.h @@ -57,7 +57,7 @@ Train *GetTrainForReservation(TileIndex tile, Track track); */ inline bool HasReservedTracks(TileIndex tile, TrackBits tracks) { - return (GetReservedTrackbits(tile) & tracks) != TRACK_BIT_NONE; + return GetReservedTrackbits(tile).Any(tracks); } #endif /* PBS_H */ diff --git a/src/rail.h b/src/rail.h index a997b06bc5..9356a65014 100644 --- a/src/rail.h +++ b/src/rail.h @@ -452,7 +452,7 @@ inline Money RailClearCost(RailType railtype) * Calculates the cost of rail conversion * @param from The railtype we are converting from * @param to The railtype we are converting to - * @return Cost per TrackBit + * @return Cost per Track */ inline Money RailConvertCost(RailType from, RailType to) { diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 21db637489..4e708a24ed 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -227,8 +227,7 @@ static const uint8_t _track_sloped_sprites[14] = { */ static CommandCost EnsureNoTrainOnTrack(TileIndex tile, Track track) { - TrackBits rail_bits = TrackToTrackBits(track); - return EnsureNoTrainOnTrackBits(tile, rail_bits); + return EnsureNoTrainOnTrackBits(tile, track); } /** @@ -260,45 +259,45 @@ static CommandCost CheckTrackCombination(TileIndex tile, TrackBits to_build) /** Valid TrackBits on a specific (non-steep)-slope without foundation */ static const TrackBits _valid_tracks_without_foundation[15] = { TRACK_BIT_ALL, - TRACK_BIT_RIGHT, - TRACK_BIT_UPPER, - TRACK_BIT_X, + Track::Right, + Track::Upper, + Track::X, - TRACK_BIT_LEFT, - TRACK_BIT_NONE, - TRACK_BIT_Y, - TRACK_BIT_LOWER, + Track::Left, + {}, + Track::Y, + Track::Lower, - TRACK_BIT_LOWER, - TRACK_BIT_Y, - TRACK_BIT_NONE, - TRACK_BIT_LEFT, + Track::Lower, + Track::Y, + {}, + Track::Left, - TRACK_BIT_X, - TRACK_BIT_UPPER, - TRACK_BIT_RIGHT, + Track::X, + Track::Upper, + Track::Right, }; /** Valid TrackBits on a specific (non-steep)-slope with leveled foundation */ static const TrackBits _valid_tracks_on_leveled_foundation[15] = { - TRACK_BIT_NONE, - TRACK_BIT_LEFT, - TRACK_BIT_LOWER, - TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_LEFT, + {}, + Track::Left, + Track::Lower, + {Track::Y, Track::Lower, Track::Left}, - TRACK_BIT_RIGHT, + Track::Right, TRACK_BIT_ALL, - TRACK_BIT_X | TRACK_BIT_LOWER | TRACK_BIT_RIGHT, + {Track::X, Track::Lower, Track::Right}, TRACK_BIT_ALL, - TRACK_BIT_UPPER, - TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_LEFT, + Track::Upper, + {Track::X, Track::Upper, Track::Left}, TRACK_BIT_ALL, TRACK_BIT_ALL, - TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_RIGHT, + {Track::Y, Track::Upper, Track::Right}, + TRACK_BIT_ALL, TRACK_BIT_ALL, - TRACK_BIT_ALL }; /** @@ -310,12 +309,12 @@ static const TrackBits _valid_tracks_on_leveled_foundation[15] = { */ Foundation GetRailFoundation(Slope tileh, TrackBits bits) { - if (bits == TRACK_BIT_NONE) return Foundation::None; + if (bits.None()) return Foundation::None; if (IsSteepSlope(tileh)) { /* Test for inclined foundations */ - if (bits == TRACK_BIT_X) return Foundation::InclinedX; - if (bits == TRACK_BIT_Y) return Foundation::InclinedY; + if (bits == Track::X) return Foundation::InclinedX; + if (bits == Track::Y) return Foundation::InclinedY; /* Get higher track */ Corner highest_corner = GetHighestSlopeCorner(tileh); @@ -328,34 +327,34 @@ Foundation GetRailFoundation(Slope tileh, TrackBits bits) if (TracksOverlap(bits | higher_track)) return Foundation::Invalid; /* either lower track or both higher and lower track */ - return ((bits & higher_track) != 0 ? Foundation::SteepBoth : Foundation::SteepLower); + return bits.Any(higher_track) ? Foundation::SteepBoth : Foundation::SteepLower; } else { - if ((~_valid_tracks_without_foundation[tileh] & bits) == 0) return Foundation::None; + if (TrackBits{bits}.Reset(_valid_tracks_without_foundation[tileh]).None()) return Foundation::None; - bool valid_on_leveled = ((~_valid_tracks_on_leveled_foundation[tileh] & bits) == 0); + bool valid_on_leveled = TrackBits{bits}.Reset(_valid_tracks_on_leveled_foundation[tileh]).None(); Corner track_corner; - switch (bits) { - case TRACK_BIT_LEFT: track_corner = CORNER_W; break; - case TRACK_BIT_LOWER: track_corner = CORNER_S; break; - case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; - case TRACK_BIT_UPPER: track_corner = CORNER_N; break; + switch (bits.base()) { + case TrackBits{Track::Left}.base(): track_corner = CORNER_W; break; + case TrackBits{Track::Lower}.base(): track_corner = CORNER_S; break; + case TrackBits{Track::Right}.base(): track_corner = CORNER_E; break; + case TrackBits{Track::Upper}.base(): track_corner = CORNER_N; break; - case TRACK_BIT_HORZ: + case TRACK_BIT_HORZ.base(): if (tileh == SLOPE_N) return HalftileFoundation(CORNER_N); if (tileh == SLOPE_S) return HalftileFoundation(CORNER_S); return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid); - case TRACK_BIT_VERT: + case TRACK_BIT_VERT.base(): if (tileh == SLOPE_W) return HalftileFoundation(CORNER_W); if (tileh == SLOPE_E) return HalftileFoundation(CORNER_E); return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid); - case TRACK_BIT_X: + case TrackBits{Track::X}.base(): if (IsSlopeWithOneCornerRaised(tileh)) return Foundation::InclinedX; return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid); - case TRACK_BIT_Y: + case TrackBits{Track::Y}.base(): if (IsSlopeWithOneCornerRaised(tileh)) return Foundation::InclinedY; return (valid_on_leveled ? Foundation::Leveled : Foundation::Invalid); @@ -392,10 +391,10 @@ static CommandCost CheckRailSlope(Slope tileh, TrackBits rail_bits, TrackBits ex { /* don't allow building on the lower side of a coast */ if (GetFloodingBehaviour(tile) != FloodingBehaviour::None) { - if (!IsSteepSlope(tileh) && ((~_valid_tracks_on_leveled_foundation[tileh] & (rail_bits | existing)) != 0)) return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER); + if (!IsSteepSlope(tileh) && TrackBits{rail_bits}.Set(existing).Reset(_valid_tracks_on_leveled_foundation[tileh]).Any()) return CommandCost(STR_ERROR_CAN_T_BUILD_ON_WATER); } - Foundation f_new = GetRailFoundation(tileh, rail_bits | existing); + Foundation f_new = GetRailFoundation(tileh, TrackBits{rail_bits}.Set(existing)); /* check track/slope combination */ if ((f_new == Foundation::Invalid) || @@ -429,7 +428,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra if (!ValParamRailType(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; Slope tileh = GetTileSlope(tile); - TrackBits trackbit = TrackToTrackBits(track); + TrackBits trackbit = track; switch (GetTileType(tile)) { case TileType::Railway: { @@ -448,13 +447,13 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra if (ret.Failed()) return ret; cost.AddCost(ret.GetCost()); - if (HasSignals(tile) && TracksOverlap(GetTrackBits(tile) | TrackToTrackBits(track))) { + if (HasSignals(tile) && TracksOverlap(GetTrackBits(tile) | track)) { /* If adding the new track causes any overlap, all signals must be removed first */ if (!auto_remove_signals) return CommandCost(STR_ERROR_MUST_REMOVE_SIGNALS_FIRST); - for (Track track_it = TRACK_BEGIN; track_it < TRACK_END; track_it++) { - if (HasTrack(tile, track_it) && HasSignalOnTrack(tile, track_it)) { - CommandCost ret_remove_signals = Command::Do(flags, tile, track_it); + for (Track existing_track : GetTrackBits(tile)) { + if (HasSignalOnTrack(tile, existing_track)) { + CommandCost ret_remove_signals = Command::Do(flags, tile, existing_track); if (ret_remove_signals.Failed()) return ret_remove_signals; cost.AddCost(ret_remove_signals.GetCost()); } @@ -479,11 +478,11 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra TrackBits bits = GetTrackBits(tile); SetTrackBits(tile, bits | trackbit); /* Subtract old infrastructure count. */ - uint pieces = CountBits(bits); + uint pieces = bits.Count(); if (TracksOverlap(bits)) pieces *= pieces; Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] -= pieces; /* Add new infrastructure count. */ - pieces = CountBits(bits | trackbit); + pieces = (bits | trackbit).Count(); if (TracksOverlap(bits | trackbit)) pieces *= pieces; Company::Get(GetTileOwner(tile))->infrastructure.rail[GetRailType(tile)] += pieces; DirtyCompanyInfrastructureWindows(GetTileOwner(tile)); @@ -518,8 +517,8 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra RoadBits road = GetRoadBits(tile, RoadTramType::Road); RoadBits tram = GetRoadBits(tile, RoadTramType::Tram); - if ((track == TRACK_X && !(road | tram).Any(ROAD_X)) || - (track == TRACK_Y && !(road | tram).Any(ROAD_Y))) { + if ((track == Track::X && !(road | tram).Any(ROAD_X)) || + (track == Track::Y && !(road | tram).Any(ROAD_Y))) { Owner road_owner = GetRoadOwner(tile, RoadTramType::Road); Owner tram_owner = GetRoadOwner(tile, RoadTramType::Tram); /* Disallow breaking end-of-line of someone else @@ -540,7 +539,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra } if (flags.Test(DoCommandFlag::Execute)) { - MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? Axis::Y : Axis::X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile)); + MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == Track::X ? Axis::Y : Axis::X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile)); UpdateLevelCrossing(tile, false); MarkDirtyAdjacentLevelCrossingTiles(tile, GetCrossingRoadAxis(tile)); Company::Get(_current_company)->infrastructure.rail[railtype] += LEVELCROSSING_TRACKBIT_FACTOR; @@ -558,7 +557,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra } } - if (IsLevelCrossing(tile) && GetCrossingRailBits(tile) == trackbit) { + if (IsLevelCrossing(tile) && GetCrossingRailTrack(tile) == trackbit) { return CommandCost(STR_ERROR_ALREADY_BUILT); } [[fallthrough]]; @@ -568,7 +567,7 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra /* Will there be flat water on the lower halftile? */ bool water_ground = IsTileType(tile, TileType::Water) && IsSlopeWithOneCornerRaised(tileh); - CommandCost ret = CheckRailSlope(tileh, trackbit, TRACK_BIT_NONE, tile); + CommandCost ret = CheckRailSlope(tileh, trackbit, {}, tile); if (ret.Failed()) return ret; cost.AddCost(ret.GetCost()); @@ -617,7 +616,6 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac bool crossing = false; if (!ValParamTrackOrientation(track)) return CMD_ERROR; - TrackBits trackbit = TrackToTrackBits(track); /* Need to read tile owner now because it may change when the rail is removed * Also, in case of floods, _current_company != owner @@ -629,7 +627,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac switch (GetTileType(tile)) { case TileType::Road: { - if (!IsLevelCrossing(tile) || GetCrossingRailBits(tile) != trackbit) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK); + if (!IsLevelCrossing(tile) || GetCrossingRailTrack(tile) != track) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK); if (_current_company != OWNER_WATER) { CommandCost ret = CheckTileOwnership(tile); @@ -646,7 +644,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac if (flags.Test(DoCommandFlag::Execute)) { UpdateAdjacentLevelCrossingTilesOnLevelCrossingRemoval(tile, GetCrossingRoadAxis(tile)); - if (HasReservedTracks(tile, trackbit)) { + if (HasReservedTracks(tile, track)) { v = GetTrainForReservation(tile, track); if (v != nullptr) FreeTrainTrackReservation(v); } @@ -674,8 +672,8 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac if (ret.Failed()) return ret; present = GetTrackBits(tile); - if ((present & trackbit) == 0) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK); - if (present == (TRACK_BIT_X | TRACK_BIT_Y)) crossing = true; + if (!present.Test(track)) return CommandCost(STR_ERROR_THERE_IS_NO_RAILROAD_TRACK); + if (present == TRACK_BIT_CROSS) crossing = true; cost.AddCost(RailClearCost(GetRailType(tile))); @@ -685,7 +683,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac } if (flags.Test(DoCommandFlag::Execute)) { - if (HasReservedTracks(tile, trackbit)) { + if (HasReservedTracks(tile, track)) { v = GetTrainForReservation(tile, track); if (v != nullptr) FreeTrainTrackReservation(v); } @@ -693,17 +691,17 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac owner = GetTileOwner(tile); /* Subtract old infrastructure count. */ - uint pieces = CountBits(present); + uint pieces = present.Count(); if (TracksOverlap(present)) pieces *= pieces; Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= pieces; /* Add new infrastructure count. */ - present ^= trackbit; - pieces = CountBits(present); + present.Flip(track); + pieces = present.Count(); if (TracksOverlap(present)) pieces *= pieces; Company::Get(owner)->infrastructure.rail[GetRailType(tile)] += pieces; DirtyCompanyInfrastructureWindows(owner); - if (present == 0) { + if (present.None()) { Slope tileh = GetTileSlope(tile); /* If there is flat water on the lower halftile, convert the tile to shore so the water remains */ if (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh)) { @@ -735,10 +733,10 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac * are removing one of these pieces, we'll need to update signals for * both directions explicitly, as after the track is removed it won't * 'connect' with the other piece. */ - AddTrackToSignalBuffer(tile, TRACK_X, owner); - AddTrackToSignalBuffer(tile, TRACK_Y, owner); - YapfNotifyTrackLayoutChange(tile, TRACK_X); - YapfNotifyTrackLayoutChange(tile, TRACK_Y); + AddTrackToSignalBuffer(tile, Track::X, owner); + AddTrackToSignalBuffer(tile, Track::Y, owner); + YapfNotifyTrackLayoutChange(tile, Track::X); + YapfNotifyTrackLayoutChange(tile, Track::Y); } else { AddTrackToSignalBuffer(tile, track, owner); YapfNotifyTrackLayoutChange(tile, track); @@ -772,13 +770,13 @@ bool FloodHalftile(TileIndex t) TrackBits lower_track = CornerToTrackBits(OppositeCorner(GetHighestSlopeCorner(tileh))); TrackBits to_remove = lower_track & rail_bits; - if (to_remove != TRACK_BIT_NONE) { + if (to_remove.Any()) { AutoRestoreBackup cur_company(_current_company, OWNER_WATER); flooded = Command::Do(DoCommandFlag::Execute, t, FindFirstTrack(to_remove)).Succeeded(); if (!flooded) return flooded; // not yet floodable - rail_bits = rail_bits & ~to_remove; - if (rail_bits == TRACK_BIT_NONE) { + rail_bits.Reset(to_remove); + if (rail_bits.None()) { MakeShore(t); MarkTileDirtyByTile(t); return flooded; @@ -1111,7 +1109,7 @@ CommandCost CmdBuildSingleSignal(DoCommandFlags flags, TileIndex tile, Track tra /* The new/changed signal could block our path. As this can lead to * stale reservations, we clear the path reservation here and try * to redo it later on. */ - if (HasReservedTracks(tile, TrackToTrackBits(track))) { + if (HasReservedTracks(tile, track)) { v = GetTrainForReservation(tile, track); if (v != nullptr) FreeTrainTrackReservation(v); } @@ -1184,12 +1182,12 @@ CommandCost CmdBuildSingleSignal(DoCommandFlags flags, TileIndex tile, Track tra if (IsPbsSignal(sigtype)) { /* PBS signals should show red unless they are on reserved tiles without a train. */ uint mask = GetPresentSignals(tile) & SignalOnTrack(track); - SetSignalStates(tile, (GetSignalStates(tile) & ~mask) | ((HasBit(GetRailReservationTrackBits(tile), track) && EnsureNoVehicleOnGround(tile).Succeeded() ? UINT_MAX : 0) & mask)); + SetSignalStates(tile, (GetSignalStates(tile) & ~mask) | ((GetRailReservationTrackBits(tile).Test(track) && EnsureNoVehicleOnGround(tile).Succeeded() ? UINT_MAX : 0) & mask)); } MarkTileDirtyByTile(tile); AddTrackToSignalBuffer(tile, track, _current_company); YapfNotifyTrackLayoutChange(tile, track); - if (v != nullptr && v->track != TRACK_BIT_DEPOT) { + if (v != nullptr && v->track != Track::Depot) { Train *moving_front = v->GetMovingFront(); /* Extend the train's path if it's not stopped or loading, or not at a safe position. */ if (!((v->vehstatus.Test(VehState::Stopped) && v->cur_speed == 0) || v->current_order.IsType(OT_LOADING)) || @@ -1482,7 +1480,7 @@ CommandCost CmdRemoveSingleSignal(DoCommandFlags flags, TileIndex tile, Track tr /* Do it? */ if (flags.Test(DoCommandFlag::Execute)) { Train *v = nullptr; - if (HasReservedTracks(tile, TrackToTrackBits(track))) { + if (HasReservedTracks(tile, track)) { v = GetTrainForReservation(tile, track); } else if (IsPbsSignal(GetSignalType(tile, track))) { /* PBS signal, might be the end of a path reservation. */ @@ -1506,7 +1504,7 @@ CommandCost CmdRemoveSingleSignal(DoCommandFlags flags, TileIndex tile, Track tr if (GetPresentSignals(tile) == 0) { SetSignalStates(tile, 0); SetHasSignals(tile, false); - SetSignalVariant(tile, INVALID_TRACK, SignalVariant::Electric); // remove any possible semaphores + SetSignalVariant(tile, Track::Invalid, SignalVariant::Electric); // remove any possible semaphores } AddTrackToSignalBuffer(tile, track, GetTileOwner(tile)); @@ -1608,7 +1606,7 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ } } if (flags.Test(DoCommandFlag::Execute)) { // we can safely convert, too - for (Track track : SetTrackBitIterator(GetReservedTrackbits(tile))) { + for (Track track : GetReservedTrackbits(tile)) { Train *v = GetTrainForReservation(tile, track); if (v != nullptr && !HasPowerOnRail(v->railtypes, totype)) { /* No power on new rail type, reroute. */ @@ -1623,7 +1621,7 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ uint num_pieces = IsLevelCrossingTile(tile) ? LEVELCROSSING_TRACKBIT_FACTOR : 1; if (IsPlainRailTile(tile)) { TrackBits bits = GetTrackBits(tile); - num_pieces = CountBits(bits); + num_pieces = bits.Count(); if (TracksOverlap(bits)) num_pieces *= num_pieces; } c->infrastructure.rail[type] -= num_pieces; @@ -1660,12 +1658,12 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ default: // RailTileType::Normal, RailTileType::Signals if (flags.Test(DoCommandFlag::Execute)) { /* notify YAPF about the track layout change */ - for (Track track : SetTrackBitIterator(GetTrackBits(tile))) { + for (Track track : GetTrackBits(tile)) { YapfNotifyTrackLayoutChange(tile, track); } } found_convertible_track = true; - cost.AddCost(RailConvertCost(type, totype) * CountBits(GetTrackBits(tile))); + cost.AddCost(RailConvertCost(type, totype) * GetTrackBits(tile).Count()); break; } break; @@ -1821,7 +1819,7 @@ static CommandCost ClearTile_Rail(TileIndex tile, DoCommandFlags flags) /* Is there flat water on the lower halftile that gets cleared expensively? */ bool water_ground = (GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(tileh)); - for (Track track : SetTrackBitIterator(GetTrackBits(tile))) { + for (Track track : GetTrackBits(tile)) { CommandCost ret = Command::Do(flags, tile, track); if (ret.Failed()) return ret; cost.AddCost(ret.GetCost()); @@ -1862,10 +1860,10 @@ static CommandCost ClearTile_Rail(TileIndex tile, DoCommandFlags flags) static uint GetSafeSlopeZ(uint x, uint y, Track track) { switch (track) { - case TRACK_UPPER: x &= ~0xF; y &= ~0xF; break; - case TRACK_LOWER: x |= 0xF; y |= 0xF; break; - case TRACK_LEFT: x |= 0xF; y &= ~0xF; break; - case TRACK_RIGHT: x &= ~0xF; y |= 0xF; break; + case Track::Upper: x &= ~0xF; y &= ~0xF; break; + case Track::Lower: x |= 0xF; y |= 0xF; break; + case Track::Left: x |= 0xF; y &= ~0xF; break; + case Track::Right: x &= ~0xF; y |= 0xF; break; default: break; } return GetSlopePixelZ(x, y); @@ -2088,7 +2086,7 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn /* Save halftile corner */ halftile_corner = (f == Foundation::SteepBoth ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f)); /* Draw lower part first */ - track &= ~CornerToTrackBits(halftile_corner); + track.Reset(CornerToTrackBits(halftile_corner)); f = (f == Foundation::SteepBoth ? Foundation::SteepLower : Foundation::None); } @@ -2097,7 +2095,7 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn /* Draw ground */ if (rgt == RailGroundType::HalfTileWater) { - if (track != TRACK_BIT_NONE || IsSteepSlope(ti->tileh)) { + if (track.Any() || IsSteepSlope(ti->tileh)) { /* three-corner-raised slope or steep slope with track on upper part */ DrawShoreTile(ti->tileh); } else { @@ -2121,83 +2119,87 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn bool no_combine = ti->tileh == SLOPE_FLAT && rti->flags.Test(RailTypeFlag::NoSpriteCombine); SpriteID overlay = GetCustomRailSprite(rti, ti->tile, RailSpriteType::Overlay); SpriteID ground = GetCustomRailSprite(rti, ti->tile, no_combine ? RailSpriteType::GroundComplete : RailSpriteType::Ground); - TrackBits pbs = _settings_client.gui.show_track_reservation ? GetRailReservationTrackBits(ti->tile) : TRACK_BIT_NONE; + TrackBits pbs = _settings_client.gui.show_track_reservation ? GetRailReservationTrackBits(ti->tile) : TrackBits{}; - if (track == TRACK_BIT_NONE) { + if (track.None()) { /* Half-tile foundation, no track here? */ } else if (no_combine) { /* Use trackbits as direct index from ground sprite, subtract 1 * because there is no sprite for no bits. */ - DrawGroundSprite(ground + track - 1, PAL_NONE); + DrawGroundSprite(ground + track.base() - 1, PAL_NONE); /* Draw reserved track bits */ - if (pbs & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH); - if (pbs & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH); - if (pbs & TRACK_BIT_UPPER) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N); - if (pbs & TRACK_BIT_LOWER) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S); - if (pbs & TRACK_BIT_RIGHT) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E); - if (pbs & TRACK_BIT_LEFT) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W); - } else if (ti->tileh == SLOPE_NW && track == TRACK_BIT_Y) { + if (pbs.Test(Track::X)) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH); + if (pbs.Test(Track::Y)) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH); + if (pbs.Test(Track::Upper)) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N); + if (pbs.Test(Track::Lower)) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S); + if (pbs.Test(Track::Right)) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E); + if (pbs.Test(Track::Left)) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W); + } else if (ti->tileh == SLOPE_NW && track == Track::Y) { DrawGroundSprite(ground + RTO_SLOPE_NW, PAL_NONE); - if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_NW, PALETTE_CRASH); - } else if (ti->tileh == SLOPE_NE && track == TRACK_BIT_X) { + if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_NW, PALETTE_CRASH); + } else if (ti->tileh == SLOPE_NE && track == Track::X) { DrawGroundSprite(ground + RTO_SLOPE_NE, PAL_NONE); - if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_NE, PALETTE_CRASH); - } else if (ti->tileh == SLOPE_SE && track == TRACK_BIT_Y) { + if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_NE, PALETTE_CRASH); + } else if (ti->tileh == SLOPE_SE && track == Track::Y) { DrawGroundSprite(ground + RTO_SLOPE_SE, PAL_NONE); - if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_SE, PALETTE_CRASH); - } else if (ti->tileh == SLOPE_SW && track == TRACK_BIT_X) { + if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_SE, PALETTE_CRASH); + } else if (ti->tileh == SLOPE_SW && track == Track::X) { DrawGroundSprite(ground + RTO_SLOPE_SW, PAL_NONE); - if (pbs != TRACK_BIT_NONE) DrawGroundSprite(overlay + RTO_SLOPE_SW, PALETTE_CRASH); + if (pbs.Any()) DrawGroundSprite(overlay + RTO_SLOPE_SW, PALETTE_CRASH); } else { - switch (track) { + switch (track.base()) { /* Draw single ground sprite when not overlapping. No track overlay * is necessary for these sprites. */ - case TRACK_BIT_X: DrawGroundSprite(ground + RTO_X, PAL_NONE); break; - case TRACK_BIT_Y: DrawGroundSprite(ground + RTO_Y, PAL_NONE); break; - case TRACK_BIT_UPPER: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); break; - case TRACK_BIT_LOWER: DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break; - case TRACK_BIT_RIGHT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); break; - case TRACK_BIT_LEFT: DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break; - case TRACK_BIT_CROSS: DrawGroundSprite(ground + RTO_CROSSING_XY, PAL_NONE); break; - case TRACK_BIT_HORZ: DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); - DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break; - case TRACK_BIT_VERT: DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); - DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break; + case TrackBits{Track::X}.base(): DrawGroundSprite(ground + RTO_X, PAL_NONE); break; + case TrackBits{Track::Y}.base(): DrawGroundSprite(ground + RTO_Y, PAL_NONE); break; + case TrackBits{Track::Upper}.base(): DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); break; + case TrackBits{Track::Lower}.base(): DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); break; + case TrackBits{Track::Right}.base(): DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); break; + case TrackBits{Track::Left}.base(): DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); break; + case TRACK_BIT_CROSS.base(): DrawGroundSprite(ground + RTO_CROSSING_XY, PAL_NONE); break; + case TRACK_BIT_HORZ.base(): + DrawTrackSprite(ground + RTO_N, PAL_NONE, ti, SLOPE_N); + DrawTrackSprite(ground + RTO_S, PAL_NONE, ti, SLOPE_S); + break; + case TRACK_BIT_VERT.base(): + DrawTrackSprite(ground + RTO_E, PAL_NONE, ti, SLOPE_E); + DrawTrackSprite(ground + RTO_W, PAL_NONE, ti, SLOPE_W); + break; default: /* We're drawing a junction tile */ - if ((track & TRACK_BIT_3WAY_NE) == 0) { + if (!track.Any(TRACK_BIT_3WAY_NE)) { DrawGroundSprite(ground + RTO_JUNCTION_SW, PAL_NONE); - } else if ((track & TRACK_BIT_3WAY_SW) == 0) { + } else if (!track.Any(TRACK_BIT_3WAY_SW)) { DrawGroundSprite(ground + RTO_JUNCTION_NE, PAL_NONE); - } else if ((track & TRACK_BIT_3WAY_NW) == 0) { + } else if (!track.Any(TRACK_BIT_3WAY_NW)) { DrawGroundSprite(ground + RTO_JUNCTION_SE, PAL_NONE); - } else if ((track & TRACK_BIT_3WAY_SE) == 0) { + } else if (!track.Any(TRACK_BIT_3WAY_SE)) { DrawGroundSprite(ground + RTO_JUNCTION_NW, PAL_NONE); } else { DrawGroundSprite(ground + RTO_JUNCTION_NSEW, PAL_NONE); } /* Mask out PBS bits as we shall draw them afterwards anyway. */ - track &= ~pbs; + track.Reset(pbs); /* Draw regular track bits */ - if (track & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PAL_NONE); - if (track & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PAL_NONE); - if (track & TRACK_BIT_UPPER) DrawGroundSprite(overlay + RTO_N, PAL_NONE); - if (track & TRACK_BIT_LOWER) DrawGroundSprite(overlay + RTO_S, PAL_NONE); - if (track & TRACK_BIT_RIGHT) DrawGroundSprite(overlay + RTO_E, PAL_NONE); - if (track & TRACK_BIT_LEFT) DrawGroundSprite(overlay + RTO_W, PAL_NONE); + if (track.Test(Track::X)) DrawGroundSprite(overlay + RTO_X, PAL_NONE); + if (track.Test(Track::Y)) DrawGroundSprite(overlay + RTO_Y, PAL_NONE); + if (track.Test(Track::Upper)) DrawGroundSprite(overlay + RTO_N, PAL_NONE); + if (track.Test(Track::Lower)) DrawGroundSprite(overlay + RTO_S, PAL_NONE); + if (track.Test(Track::Right)) DrawGroundSprite(overlay + RTO_E, PAL_NONE); + if (track.Test(Track::Left)) DrawGroundSprite(overlay + RTO_W, PAL_NONE); } /* Draw reserved track bits */ - if (pbs & TRACK_BIT_X) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH); - if (pbs & TRACK_BIT_Y) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH); - if (pbs & TRACK_BIT_UPPER) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N); - if (pbs & TRACK_BIT_LOWER) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S); - if (pbs & TRACK_BIT_RIGHT) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E); - if (pbs & TRACK_BIT_LEFT) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W); + if (pbs.Test(Track::X)) DrawGroundSprite(overlay + RTO_X, PALETTE_CRASH); + if (pbs.Test(Track::Y)) DrawGroundSprite(overlay + RTO_Y, PALETTE_CRASH); + if (pbs.Test(Track::Upper)) DrawTrackSprite(overlay + RTO_N, PALETTE_CRASH, ti, SLOPE_N); + if (pbs.Test(Track::Lower)) DrawTrackSprite(overlay + RTO_S, PALETTE_CRASH, ti, SLOPE_S); + if (pbs.Test(Track::Right)) DrawTrackSprite(overlay + RTO_E, PALETTE_CRASH, ti, SLOPE_E); + if (pbs.Test(Track::Left)) DrawTrackSprite(overlay + RTO_W, PALETTE_CRASH, ti, SLOPE_W); } if (IsValidCorner(halftile_corner)) { @@ -2223,12 +2225,12 @@ static void DrawTrackBitsOverlay(TileInfo *ti, TrackBits track, const RailTypeIn track = CornerToTrackBits(halftile_corner); int offset; - switch (track) { + switch (FindFirstTrack(track)) { default: NOT_REACHED(); - case TRACK_BIT_UPPER: offset = RTO_N; break; - case TRACK_BIT_LOWER: offset = RTO_S; break; - case TRACK_BIT_RIGHT: offset = RTO_E; break; - case TRACK_BIT_LEFT: offset = RTO_W; break; + case Track::Upper: offset = RTO_N; break; + case Track::Lower: offset = RTO_S; break; + case Track::Right: offset = RTO_E; break; + case Track::Left: offset = RTO_W; break; } DrawTrackSprite(ground + offset, PAL_NONE, ti, fake_slope); @@ -2250,10 +2252,10 @@ static int GetJunctionGroundSpriteOffset(TrackBits track) /* If none of the tracks end up in the NE corner, return the ground sprite * where the NE of the tile is not covered. Repeat for the other directions. * What remains are junctions where all directions are covered. */ - if ((track & TRACK_BIT_3WAY_NE) == 0) return 0; - if ((track & TRACK_BIT_3WAY_SW) == 0) return 1; - if ((track & TRACK_BIT_3WAY_NW) == 0) return 2; - if ((track & TRACK_BIT_3WAY_SE) == 0) return 3; + if (!track.Any(TRACK_BIT_3WAY_NE)) return 0; + if (!track.Any(TRACK_BIT_3WAY_SW)) return 1; + if (!track.Any(TRACK_BIT_3WAY_NW)) return 2; + if (!track.Any(TRACK_BIT_3WAY_SE)) return 3; return 4; } @@ -2279,7 +2281,7 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track) /* Save halftile corner */ halftile_corner = (f == Foundation::SteepBoth ? GetHighestSlopeCorner(ti->tileh) : GetHalftileFoundationCorner(f)); /* Draw lower part first */ - track &= ~CornerToTrackBits(halftile_corner); + track.Reset(CornerToTrackBits(halftile_corner)); f = (f == Foundation::SteepBoth ? Foundation::SteepLower : Foundation::None); } @@ -2292,7 +2294,7 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track) bool junction = false; /* Select the sprite to use. */ - if (track == 0) { + if (track.None()) { /* Clear ground (only track on halftile foundation) */ if (rgt == RailGroundType::HalfTileWater) { if (IsSteepSlope(ti->tileh)) { @@ -2315,19 +2317,19 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track) image = _track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.track_y; } else { /* track on flat ground */ - switch (track) { + switch (track.base()) { /* single track, select combined track + ground sprite*/ - case TRACK_BIT_Y: image = rti->base_sprites.track_y; break; - case TRACK_BIT_X: image = rti->base_sprites.track_y + 1; break; - case TRACK_BIT_UPPER: image = rti->base_sprites.track_y + 2; break; - case TRACK_BIT_LOWER: image = rti->base_sprites.track_y + 3; break; - case TRACK_BIT_RIGHT: image = rti->base_sprites.track_y + 4; break; - case TRACK_BIT_LEFT: image = rti->base_sprites.track_y + 5; break; - case TRACK_BIT_CROSS: image = rti->base_sprites.track_y + 6; break; + case TrackBits{Track::Y}.base(): image = rti->base_sprites.track_y; break; + case TrackBits{Track::X}.base(): image = rti->base_sprites.track_y + 1; break; + case TrackBits{Track::Upper}.base(): image = rti->base_sprites.track_y + 2; break; + case TrackBits{Track::Lower}.base(): image = rti->base_sprites.track_y + 3; break; + case TrackBits{Track::Right}.base(): image = rti->base_sprites.track_y + 4; break; + case TrackBits{Track::Left}.base(): image = rti->base_sprites.track_y + 5; break; + case TRACK_BIT_CROSS.base(): image = rti->base_sprites.track_y + 6; break; /* double diagonal track, select combined track + ground sprite*/ - case TRACK_BIT_HORZ: image = rti->base_sprites.track_ns; break; - case TRACK_BIT_VERT: image = rti->base_sprites.track_ns + 1; break; + case TRACK_BIT_HORZ.base(): image = rti->base_sprites.track_ns; break; + case TRACK_BIT_VERT.base(): image = rti->base_sprites.track_ns + 1; break; /* junction, select only ground sprite, handle track sprite later */ default: @@ -2355,36 +2357,36 @@ static void DrawTrackBits(TileInfo *ti, TrackBits track) /* Draw track pieces individually for junction tiles */ if (junction) { - if (track & TRACK_BIT_X) DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE); - if (track & TRACK_BIT_Y) DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE); - if (track & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE); - if (track & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE); - if (track & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE); - if (track & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE); + if (track.Test(Track::X)) DrawGroundSprite(rti->base_sprites.single_x, PAL_NONE); + if (track.Test(Track::Y)) DrawGroundSprite(rti->base_sprites.single_y, PAL_NONE); + if (track.Test(Track::Upper)) DrawGroundSprite(rti->base_sprites.single_n, PAL_NONE); + if (track.Test(Track::Lower)) DrawGroundSprite(rti->base_sprites.single_s, PAL_NONE); + if (track.Test(Track::Left)) DrawGroundSprite(rti->base_sprites.single_w, PAL_NONE); + if (track.Test(Track::Right)) DrawGroundSprite(rti->base_sprites.single_e, PAL_NONE); } /* PBS debugging, draw reserved tracks darker */ if (_game_mode != GameMode::Menu && _settings_client.gui.show_track_reservation) { /* Get reservation, but mask track on halftile slope */ TrackBits pbs = GetRailReservationTrackBits(ti->tile) & track; - if (pbs & TRACK_BIT_X) { + if (pbs.Test(Track::X)) { if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) { DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH); } else { DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH); } } - if (pbs & TRACK_BIT_Y) { + if (pbs.Test(Track::Y)) { if (ti->tileh == SLOPE_FLAT || ti->tileh == SLOPE_ELEVATED) { DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH); } else { DrawGroundSprite(_track_sloped_sprites[ti->tileh - 1] + rti->base_sprites.single_sloped - 20, PALETTE_CRASH); } } - if (pbs & TRACK_BIT_UPPER) DrawGroundSprite(rti->base_sprites.single_n, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_N ? -(int)TILE_HEIGHT : 0); - if (pbs & TRACK_BIT_LOWER) DrawGroundSprite(rti->base_sprites.single_s, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_S ? -(int)TILE_HEIGHT : 0); - if (pbs & TRACK_BIT_LEFT) DrawGroundSprite(rti->base_sprites.single_w, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_W ? -(int)TILE_HEIGHT : 0); - if (pbs & TRACK_BIT_RIGHT) DrawGroundSprite(rti->base_sprites.single_e, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_E ? -(int)TILE_HEIGHT : 0); + if (pbs.Test(Track::Upper)) DrawGroundSprite(rti->base_sprites.single_n, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_N ? -(int)TILE_HEIGHT : 0); + if (pbs.Test(Track::Lower)) DrawGroundSprite(rti->base_sprites.single_s, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_S ? -(int)TILE_HEIGHT : 0); + if (pbs.Test(Track::Left)) DrawGroundSprite(rti->base_sprites.single_w, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_W ? -(int)TILE_HEIGHT : 0); + if (pbs.Test(Track::Right)) DrawGroundSprite(rti->base_sprites.single_e, PALETTE_CRASH, nullptr, 0, ti->tileh & SLOPE_E ? -(int)TILE_HEIGHT : 0); } if (IsValidCorner(halftile_corner)) { @@ -2415,31 +2417,31 @@ static void DrawSignals(TileIndex tile, TrackBits rails, const RailTypeInfo *rti if (IsSignalPresent(tile, signalbit)) DrawSingleSignal(tile, rti, track, GetSingleSignalState(tile, signalbit), image, pos); }; - if (!(rails & TRACK_BIT_Y)) { - if (!(rails & TRACK_BIT_X)) { - if (rails & TRACK_BIT_LEFT) { - MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTH, 0, TRACK_LEFT); - MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTH, 1, TRACK_LEFT); + if (!rails.Test(Track::Y)) { + if (!rails.Test(Track::X)) { + if (rails.Test(Track::Left)) { + MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTH, 0, Track::Left); + MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTH, 1, Track::Left); } - if (rails & TRACK_BIT_RIGHT) { - MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_NORTH, 2, TRACK_RIGHT); - MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_SOUTH, 3, TRACK_RIGHT); + if (rails.Test(Track::Right)) { + MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_NORTH, 2, Track::Right); + MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_SOUTH, 3, Track::Right); } - if (rails & TRACK_BIT_UPPER) { - MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_WEST, 4, TRACK_UPPER); - MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_EAST, 5, TRACK_UPPER); + if (rails.Test(Track::Upper)) { + MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_WEST, 4, Track::Upper); + MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_EAST, 5, Track::Upper); } - if (rails & TRACK_BIT_LOWER) { - MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_WEST, 6, TRACK_LOWER); - MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_EAST, 7, TRACK_LOWER); + if (rails.Test(Track::Lower)) { + MAYBE_DRAW_SIGNAL(1, SIGNAL_TO_WEST, 6, Track::Lower); + MAYBE_DRAW_SIGNAL(0, SIGNAL_TO_EAST, 7, Track::Lower); } } else { - MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHWEST, 8, TRACK_X); - MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHEAST, 9, TRACK_X); + MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHWEST, 8, Track::X); + MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHEAST, 9, Track::X); } } else { - MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHEAST, 10, TRACK_Y); - MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHWEST, 11, TRACK_Y); + MAYBE_DRAW_SIGNAL(3, SIGNAL_TO_SOUTHEAST, 10, Track::Y); + MAYBE_DRAW_SIGNAL(2, SIGNAL_TO_NORTHWEST, 11, Track::Y); } } @@ -2462,10 +2464,10 @@ static void DrawTile_Rail(TileInfo *ti) if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails, rti); if (IsBridgeAbove(ti->tile)) { - if ((rails & TRACK_BIT_3WAY_NE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNE); - if ((rails & TRACK_BIT_3WAY_SE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSE); - if ((rails & TRACK_BIT_3WAY_SW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSW); - if ((rails & TRACK_BIT_3WAY_NW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNW); + if (rails.Any(TRACK_BIT_3WAY_NE)) blocked_pillars.Set(BridgePillarFlag::EdgeNE); + if (rails.Any(TRACK_BIT_3WAY_SE)) blocked_pillars.Set(BridgePillarFlag::EdgeSE); + if (rails.Any(TRACK_BIT_3WAY_SW)) blocked_pillars.Set(BridgePillarFlag::EdgeSW); + if (rails.Any(TRACK_BIT_3WAY_NW)) blocked_pillars.Set(BridgePillarFlag::EdgeNW); } } else { /* draw depot */ @@ -2718,7 +2720,7 @@ static void TileLoop_Rail(TileIndex tile) static constexpr DiagDirectionIndexArray dir_to_trackbits{TRACK_BIT_3WAY_NE, TRACK_BIT_3WAY_SE, TRACK_BIT_3WAY_SW, TRACK_BIT_3WAY_NW}; /* Track bit on this edge => no fence. */ - if ((rail & dir_to_trackbits[d]) != TRACK_BIT_NONE) continue; + if (rail.Any(dir_to_trackbits[d])) continue; TileIndex tile2 = tile + TileOffsByDiagDir(d); @@ -2759,19 +2761,19 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [ /* Case of half tile slope with water. */ if (mode == TRANSPORT_WATER && IsPlainRail(tile) && GetRailGroundType(tile) == RailGroundType::HalfTileWater && IsSlopeWithOneCornerRaised(GetTileSlope(tile))) { TrackBits tb = GetTrackBits(tile); - switch (tb) { + switch (tb.base()) { default: NOT_REACHED(); - case TRACK_BIT_UPPER: tb = TRACK_BIT_LOWER; break; - case TRACK_BIT_LOWER: tb = TRACK_BIT_UPPER; break; - case TRACK_BIT_LEFT: tb = TRACK_BIT_RIGHT; break; - case TRACK_BIT_RIGHT: tb = TRACK_BIT_LEFT; break; + case TrackBits{Track::Upper}.base(): tb = Track::Lower; break; + case TrackBits{Track::Lower}.base(): tb = Track::Upper; break; + case TrackBits{Track::Left}.base(): tb = Track::Right; break; + case TrackBits{Track::Right}.base(): tb = Track::Left; break; } return {TrackBitsToTrackdirBits(tb), TRACKDIR_BIT_NONE}; } if (mode != TRANSPORT_RAIL) return {}; - TrackBits trackbits = TRACK_BIT_NONE; + TrackBits trackbits{}; TrackdirBits red_signals = TRACKDIR_BIT_NONE; switch (GetRailTileType(tile)) { @@ -2792,8 +2794,8 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [ * the signal type. For signals that are only active from * one side, we set the missing signals explicitly to * `green'. Otherwise, they implicitly become `red'. */ - 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 (!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); @@ -2808,7 +2810,7 @@ static TrackStatus GetTileTrackStatus_Rail(TileIndex tile, TransportType mode, [ if (side != DiagDirection::Invalid && side != dir) break; - trackbits = DiagDirToDiagTrackBits(dir); + trackbits = DiagDirToDiagTrack(dir); break; } } @@ -2891,11 +2893,11 @@ static void GetTileDesc_Rail(TileIndex tile, TileDesc &td) SignalType primary_signal; SignalType secondary_signal; - if (HasSignalOnTrack(tile, TRACK_UPPER)) { - primary_signal = GetSignalType(tile, TRACK_UPPER); - secondary_signal = HasSignalOnTrack(tile, TRACK_LOWER) ? GetSignalType(tile, TRACK_LOWER) : primary_signal; + if (HasSignalOnTrack(tile, Track::Upper)) { + primary_signal = GetSignalType(tile, Track::Upper); + secondary_signal = HasSignalOnTrack(tile, Track::Lower) ? GetSignalType(tile, Track::Lower) : primary_signal; } else { - secondary_signal = primary_signal = GetSignalType(tile, TRACK_LOWER); + secondary_signal = primary_signal = GetSignalType(tile, Track::Lower); } td.str = signal_type[secondary_signal][primary_signal]; @@ -2929,7 +2931,7 @@ static void ChangeTileOwner_Rail(TileIndex tile, Owner old_owner, Owner new_owne uint num_pieces = 1; if (IsPlainRail(tile)) { TrackBits bits = GetTrackBits(tile); - num_pieces = CountBits(bits); + num_pieces = bits.Count(); if (TracksOverlap(bits)) num_pieces *= num_pieces; } RailType rt = GetRailType(tile); @@ -3024,13 +3026,13 @@ static VehicleEnterTileStates VehicleEnterTile_Rail(Vehicle *v, TileIndex tile, /* Leave the depot. */ if ((v = v->GetMovingNext()) != nullptr) { v->vehstatus.Reset(VehState::Hidden); - Train::From(v)->track = AxisToTrackBits(DiagDirToAxis(dir)); + Train::From(v)->track = AxisToTrack(DiagDirToAxis(dir)); } } } else if (_fractcoords_enter[dir] == fract_coord) { /* Entering depot. */ assert(DiagDirToDir(ReverseDiagDir(dir)) == v->GetMovingDirection()); - Train::From(v)->track = TRACK_BIT_DEPOT; + Train::From(v)->track = Track::Depot; v->vehstatus.Set(VehState::Hidden); if (v->GetMovingNext() == nullptr) { Train *consist = Train::From(v)->First(); @@ -3072,18 +3074,18 @@ static CommandCost TestAutoslopeOnRailTile(TileIndex tile, DoCommandFlags flags, if (!_settings_game.construction.build_on_slopes || !AutoslopeEnabled()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK); /* Is the slope-rail_bits combination valid in general? I.e. is it safe to call GetRailFoundation() ? */ - if (CheckRailSlope(tileh_new, rail_bits, TRACK_BIT_NONE, tile).Failed()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK); + if (CheckRailSlope(tileh_new, rail_bits, {}, tile).Failed()) return CommandCost(STR_ERROR_MUST_REMOVE_RAILROAD_TRACK); /* Get the slopes on top of the foundations */ z_old += ApplyFoundationToSlope(GetRailFoundation(tileh_old, rail_bits), tileh_old); z_new += ApplyFoundationToSlope(GetRailFoundation(tileh_new, rail_bits), tileh_new); Corner track_corner; - switch (rail_bits) { - case TRACK_BIT_LEFT: track_corner = CORNER_W; break; - case TRACK_BIT_LOWER: track_corner = CORNER_S; break; - case TRACK_BIT_RIGHT: track_corner = CORNER_E; break; - case TRACK_BIT_UPPER: track_corner = CORNER_N; break; + switch (rail_bits.base()) { + case TrackBits{Track::Left}.base(): track_corner = CORNER_W; break; + case TrackBits{Track::Lower}.base(): track_corner = CORNER_S; break; + case TrackBits{Track::Right}.base(): track_corner = CORNER_E; break; + case TrackBits{Track::Upper}.base(): track_corner = CORNER_N; break; /* Surface slope must not be changed */ default: @@ -3125,11 +3127,11 @@ static CommandCost TerraformTile_Rail(TileIndex tile, DoCommandFlags flags, int /* When there is only a single horizontal/vertical track, one corner can be terraformed. */ Corner allowed_corner; - switch (rail_bits) { - case TRACK_BIT_RIGHT: allowed_corner = CORNER_W; break; - case TRACK_BIT_UPPER: allowed_corner = CORNER_S; break; - case TRACK_BIT_LEFT: allowed_corner = CORNER_E; break; - case TRACK_BIT_LOWER: allowed_corner = CORNER_N; break; + switch (rail_bits.base()) { + case TrackBits{Track::Right}.base(): allowed_corner = CORNER_W; break; + case TrackBits{Track::Upper}.base(): allowed_corner = CORNER_S; break; + case TrackBits{Track::Left}.base(): allowed_corner = CORNER_E; break; + case TrackBits{Track::Lower}.base(): allowed_corner = CORNER_N; break; default: return autoslope_result; } diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 55103bf789..7ee1e37276 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -123,16 +123,16 @@ static void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track) { if (GetRailTileType(tile) == RailTileType::Depot) return; if (GetRailTileType(tile) == RailTileType::Signals && !_settings_client.gui.auto_remove_signals) return; - if ((GetTrackBits(tile) & DiagdirReachesTracks(dir)) == 0) return; + if (!GetTrackBits(tile).Any(DiagdirReachesTracks(dir))) return; Command::Post(tile, _cur_railtype, track, _settings_client.gui.auto_remove_signals); } /** Additional pieces of track to add at the entrance of a depot. */ static constexpr std::array, 3> _place_depot_extra_track{{ - {TRACK_LEFT, TRACK_UPPER, TRACK_UPPER, TRACK_RIGHT}, // First additional track for directions 0..3 - {TRACK_X, TRACK_Y, TRACK_X, TRACK_Y}, // Second additional track - {TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT, TRACK_LOWER}, // Third additional track + {Track::Left, Track::Upper, Track::Upper, Track::Right}, // First additional track for directions 0..3 + {Track::X, Track::Y, Track::X, Track::Y}, // Second additional track + {Track::Lower, Track::Left, Track::Right, Track::Lower}, // Third additional track }}; /** Direction to check for existing track pieces. */ @@ -239,12 +239,12 @@ static void GenericPlaceSignals(TileIndex tile) { TrackBits trackbits = TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs); - if (trackbits & TRACK_BIT_VERT) { // N-S direction - trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? TRACK_BIT_RIGHT : TRACK_BIT_LEFT; + if (trackbits.Any(TRACK_BIT_VERT)) { // N-S direction + trackbits = (_tile_fract_coords.x <= _tile_fract_coords.y) ? Track::Right : Track::Left; } - if (trackbits & TRACK_BIT_HORZ) { // E-W direction - trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? TRACK_BIT_UPPER : TRACK_BIT_LOWER; + if (trackbits.Any(TRACK_BIT_HORZ)) { // E-W direction + trackbits = (_tile_fract_coords.x + _tile_fract_coords.y <= 15) ? Track::Upper : Track::Lower; } Track track = FindFirstTrack(trackbits); @@ -418,7 +418,7 @@ static void HandleAutodirPlacement() */ static void HandleAutoSignalPlacement() { - Track track = (Track)GB(_thd.drawstyle, 0, 3); // 0..5 + Track track = static_cast(_thd.drawstyle & HT_DIR_MASK); // 0..5 if ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT) { // one tile case GenericPlaceSignals(TileVirtXY(_thd.selend.x, _thd.selend.y)); diff --git a/src/rail_map.h b/src/rail_map.h index 31ef57a0e9..d444789de0 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -136,7 +136,7 @@ inline void SetRailType(Tile t, RailType r) inline TrackBits GetTrackBits(Tile tile) { assert(IsPlainRailTile(tile)); - return (TrackBits)GB(tile.m5(), 0, 6); + return static_cast(GB(tile.m5(), 0, 6)); } /** @@ -147,7 +147,7 @@ inline TrackBits GetTrackBits(Tile tile) inline void SetTrackBits(Tile t, TrackBits b) { assert(IsPlainRailTile(t)); - SB(t.m5(), 0, 6, b); + SB(t.m5(), 0, 6, b.base()); } /** @@ -159,7 +159,7 @@ inline void SetTrackBits(Tile t, TrackBits b) */ inline bool HasTrack(Tile tile, Track track) { - return HasBit(GetTrackBits(tile), track); + return GetTrackBits(tile).Test(track); } /** @@ -195,9 +195,9 @@ inline TrackBits GetRailReservationTrackBits(Tile t) { assert(IsPlainRailTile(t)); uint8_t track_b = GB(t.m2(), 8, 3); - Track track = (Track)(track_b - 1); // map array saves Track+1 - if (track_b == 0) return TRACK_BIT_NONE; - return (TrackBits)(TrackToTrackBits(track) | (HasBit(t.m2(), 11) ? TrackToTrackBits(TrackToOppositeTrack(track)) : 0)); + if (track_b == 0) return {}; + Track track = static_cast(track_b - 1); // map array saves Track+1 + return (HasBit(t.m2(), 11) ? TrackToOppositeTrack(track) : TrackBits{}) | track; } /** @@ -212,7 +212,7 @@ inline void SetTrackReservation(Tile t, TrackBits b) assert(!TracksOverlap(b)); Track track = RemoveFirstTrack(&b); SB(t.m2(), 8, 3, IsValidTrack(track) ? to_underlying(track) + 1 : 0); - AssignBit(t.m2(), 11, b != TRACK_BIT_NONE); + AssignBit(t.m2(), 11, b.Any()); } /** @@ -225,10 +225,9 @@ inline void SetTrackReservation(Tile t, TrackBits b) inline bool TryReserveTrack(Tile tile, Track t) { assert(HasTrack(tile, t)); - TrackBits bits = TrackToTrackBits(t); TrackBits res = GetRailReservationTrackBits(tile); - if ((res & bits) != TRACK_BIT_NONE) return false; // already reserved - res |= bits; + if (res.Test(t)) return false; // already reserved + res.Set(t); if (TracksOverlap(res)) return false; // crossing reservation present SetTrackReservation(tile, res); return true; @@ -244,7 +243,7 @@ inline void UnreserveTrack(Tile tile, Track t) { assert(HasTrack(tile, t)); TrackBits res = GetRailReservationTrackBits(tile); - res &= ~TrackToTrackBits(t); + res.Reset(t); SetTrackReservation(tile, res); } @@ -280,7 +279,7 @@ inline void SetDepotReservation(Tile t, bool b) */ inline TrackBits GetDepotReservationTrackBits(Tile t) { - return HasDepotReservation(t) ? TrackToTrackBits(GetRailDepotTrack(t)) : TRACK_BIT_NONE; + return HasDepotReservation(t) ? GetRailDepotTrack(t) : TrackBits{}; } @@ -304,7 +303,7 @@ inline bool IsPbsSignal(SignalType s) inline SignalType GetSignalType(Tile t, Track track) { assert(GetRailTileType(t) == RailTileType::Signals); - uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0; + uint8_t pos = (track == Track::Lower || track == Track::Right) ? 4 : 0; return static_cast(GB(t.m2(), pos, 3)); } @@ -318,7 +317,7 @@ inline SignalType GetSignalType(Tile t, Track track) inline void SetSignalType(Tile t, Track track, SignalType s) { assert(GetRailTileType(t) == RailTileType::Signals); - uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 0; + uint8_t pos = (track == Track::Lower || track == Track::Right) ? 4 : 0; SB(t.m2(), pos, 3, to_underlying(s)); if (!IsValidTrack(track)) SB(t.m2(), 4, 3, to_underlying(s)); } @@ -369,7 +368,7 @@ inline bool IsOnewaySignal(Tile t, Track track) inline void CycleSignalSide(Tile t, Track track) { uint8_t sig; - uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 4 : 6; + uint8_t pos = (track == Track::Lower || track == Track::Right) ? 4 : 6; sig = GB(t.m3(), pos, 2); if (--sig == 0) sig = IsPbsSignal(GetSignalType(t, track)) ? 2 : 3; @@ -385,7 +384,7 @@ inline void CycleSignalSide(Tile t, Track track) */ inline SignalVariant GetSignalVariant(Tile t, Track track) { - uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3; + uint8_t pos = (track == Track::Lower || track == Track::Right) ? 7 : 3; return static_cast(GB(t.m2(), pos, 1)); } @@ -398,7 +397,7 @@ inline SignalVariant GetSignalVariant(Tile t, Track track) */ inline void SetSignalVariant(Tile t, Track track, SignalVariant v) { - uint8_t pos = (track == TRACK_LOWER || track == TRACK_RIGHT) ? 7 : 3; + uint8_t pos = (track == Track::Lower || track == Track::Right) ? 7 : 3; SB(t.m2(), pos, 1, to_underlying(v)); if (!IsValidTrack(track)) SB(t.m2(), 7, 1, to_underlying(v)); } @@ -630,7 +629,7 @@ inline void MakeRailNormal(Tile t, Owner o, TrackBits b, RailType r) t.m2() = 0; t.m3() = 0; t.m4() = 0; - t.m5() = to_underlying(RailTileType::Normal) << 6 | b; + t.m5() = to_underlying(RailTileType::Normal) << 6 | b.base(); SB(t.m6(), 2, 6, 0); t.m7() = 0; t.m8() = r; diff --git a/src/road.cpp b/src/road.cpp index 0632076ea0..a3d56eed42 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -46,7 +46,7 @@ static bool IsPossibleCrossing(const TileIndex tile, Axis ax) { return (IsTileType(tile, TileType::Railway) && GetRailTileType(tile) == RailTileType::Normal && - GetTrackBits(tile) == AxisToTrackBits(OtherAxis(ax)) && + GetTrackBits(tile) == AxisToTrack(OtherAxis(ax)) && std::get(GetFoundationSlope(tile)) == SLOPE_FLAT); } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index f151b84dba..63f00897e1 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -494,12 +494,11 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie /* A full diagonal road tile has two road bits. */ UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2); - Track railtrack = GetCrossingRailTrack(tile); + Track track = GetCrossingRailTrack(tile); if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) { - TrackBits tracks = GetCrossingRailBits(tile); bool reserved = HasCrossingReservation(tile); - MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile)); - if (reserved) SetTrackReservation(tile, tracks); + MakeRailNormal(tile, GetTileOwner(tile), track, GetRailType(tile)); + if (reserved) SetTrackReservation(tile, track); /* Update rail count for level crossings. The plain track should still be accounted * for, so only subtract the difference to the level crossing cost. */ @@ -512,7 +511,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie SetRoadType(tile, rtt, INVALID_ROADTYPE); } MarkTileDirtyByTile(tile); - YapfNotifyTrackLayoutChange(tile, railtrack); + YapfNotifyTrackLayoutChange(tile, track); } return CommandCost(ExpensesType::Construction, RoadClearCost(existing_rt) * 2); } @@ -736,13 +735,13 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, } Axis roaddir; - switch (GetTrackBits(tile)) { - case TRACK_BIT_X: + switch (GetTrackBits(tile).base()) { + case TrackBits{Track::X}.base(): if (pieces.Any(ROAD_X)) goto do_clear; roaddir = Axis::Y; break; - case TRACK_BIT_Y: + case TrackBits{Track::Y}.base(): if (pieces.Any(ROAD_Y)) goto do_clear; roaddir = Axis::X; break; @@ -768,7 +767,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, } /* Always add road to the roadtypes (can't draw without it) */ - bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack); + bool reserved = GetRailReservationTrackBits(tile).Test(railtrack); MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RoadTramType::Road ? rt : INVALID_ROADTYPE, (rtt == RoadTramType::Tram) ? rt : INVALID_ROADTYPE, town_id); SetCrossingReservation(tile, reserved); UpdateLevelCrossing(tile, false); @@ -2121,22 +2120,22 @@ static bool ClickTile_Road(TileIndex tile) /** Converts %RoadBits to %TrackBits. */ static const TrackBits _road_trackbits[16] = { - TRACK_BIT_NONE, // ROAD_NONE - TRACK_BIT_NONE, // RoadBit::NW - TRACK_BIT_NONE, // RoadBit::SW - TRACK_BIT_LEFT, // ROAD_W - TRACK_BIT_NONE, // RoadBit::SE - TRACK_BIT_Y, // ROAD_Y - TRACK_BIT_LOWER, // ROAD_S - TRACK_BIT_LEFT | TRACK_BIT_LOWER | TRACK_BIT_Y, // ROAD_Y | RoadBit::SW - TRACK_BIT_NONE, // RoadBit::NE - TRACK_BIT_UPPER, // ROAD_N - TRACK_BIT_X, // ROAD_X - TRACK_BIT_LEFT | TRACK_BIT_UPPER | TRACK_BIT_X, // ROAD_X | RoadBit::NW - TRACK_BIT_RIGHT, // ROAD_E - TRACK_BIT_RIGHT | TRACK_BIT_UPPER | TRACK_BIT_Y, // ROAD_Y | RoadBit::NE - TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | RoadBit::SE - TRACK_BIT_ALL, // ROAD_ALL + {}, // ROAD_NONE + {}, // RoadBit::NW + {}, // RoadBit::SW + Track::Left, // ROAD_W + {}, // RoadBit::SE + Track::Y, // ROAD_Y + Track::Lower, // ROAD_S + {Track::Left, Track::Lower, Track::Y}, // ROAD_Y | RoadBit::SW + {}, // RoadBit::NE + Track::Upper, // ROAD_N + Track::X, // ROAD_X + {Track::Left, Track::Upper, Track::X}, // ROAD_X | RoadBit::NW + Track::Right, // ROAD_E + {Track::Right, Track::Upper, Track::Y}, // ROAD_Y | RoadBit::NE + {Track::Right, Track::Lower, Track::X}, // ROAD_X | RoadBit::SE + TRACK_BIT_ALL, // ROAD_ALL }; /** @copydoc GetTileTrackStatusProc */ @@ -2146,7 +2145,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R TrackdirBits red_signals = TRACKDIR_BIT_NONE; // crossing barred switch (mode) { case TRANSPORT_RAIL: - if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailBits(tile)); + if (IsLevelCrossing(tile)) trackdirbits = TrackBitsToTrackdirBits(GetCrossingRailTrack(tile)); break; case TRANSPORT_ROAD: { @@ -2161,7 +2160,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R if (side != DiagDirection::Invalid && !DiagDirToRoadBits(side).Any(bits)) break; uint multiplier = drd_to_multiplier[(rtt == RoadTramType::Tram) ? 0 : GetDisallowedRoadDirections(tile).base()]; - if (!HasRoadWorks(tile)) trackdirbits = static_cast(_road_trackbits[bits.base()] * multiplier); + if (!HasRoadWorks(tile)) trackdirbits = static_cast(_road_trackbits[bits.base()].base() * multiplier); break; } @@ -2170,7 +2169,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R if (side != DiagDirection::Invalid && axis != DiagDirToAxis(side)) break; - trackdirbits = TrackBitsToTrackdirBits(AxisToTrackBits(axis)); + trackdirbits = TrackBitsToTrackdirBits(AxisToTrack(axis)); if (IsCrossingBarred(tile)) { red_signals = trackdirbits; if (TrainOnCrossing(tile)) break; @@ -2192,7 +2191,7 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R if (side != DiagDirection::Invalid && side != dir) break; - trackdirbits = TrackBitsToTrackdirBits(DiagDirToDiagTrackBits(dir)); + trackdirbits = TrackBitsToTrackdirBits(DiagDirToDiagTrack(dir)); break; } } diff --git a/src/road_map.h b/src/road_map.h index 38bf29d6bd..4fd455b4d9 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -370,17 +370,6 @@ inline Track GetCrossingRailTrack(Tile tile) return AxisToTrack(GetCrossingRailAxis(tile)); } -/** - * Get the rail track bits of a level crossing. - * @param tile The tile to query. - * @return The rail track bits. - */ -inline TrackBits GetCrossingRailBits(Tile tile) -{ - return AxisToTrackBits(GetCrossingRailAxis(tile)); -} - - /** * Get the reservation state of the rail crossing * @param t the crossing tile @@ -414,7 +403,7 @@ inline void SetCrossingReservation(Tile t, bool b) */ inline TrackBits GetCrossingReservationTrackBits(Tile t) { - return HasCrossingReservation(t) ? GetCrossingRailBits(t) : TRACK_BIT_NONE; + return HasCrossingReservation(t) ? GetCrossingRailTrack(t) : TrackBits{}; } /** diff --git a/src/roadveh.h b/src/roadveh.h index 1472e0ce12..8b5216a890 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -290,7 +290,7 @@ protected: // These functions should not be called outside acceleration code. TrackStatus ts = GetTileTrackStatus(this->tile, TRANSPORT_ROAD, GetRoadTramType(this->roadtype)); TrackBits trackbits = TrackdirBitsToTrackBits(ts.trackdirs); - return trackbits == TRACK_BIT_X || trackbits == TRACK_BIT_Y; + return trackbits == Track::X || trackbits == Track::Y; } /** diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 4acc1342cf..3620c3848a 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -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 & ~TRACK_BIT_CROSS) || (ts.signals != TRACKDIR_BIT_NONE)) return true; + if (!HasBit(ts.trackdirs, od->trackdir) || trackbits.Any({Track::Upper, Track::Lower, Track::Left, Track::Right}) || (ts.signals != TRACKDIR_BIT_NONE)) return true; /* Are there more vehicles on the tile except the two vehicles involved in overtaking */ return HasVehicleOnTile(od->tile, [&](const Vehicle *v) { diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 1bbd2dd888..42a8cc0384 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1235,7 +1235,7 @@ bool AfterLoadGame() MakeRailNormal( t, GetTileOwner(t), - AxisToTrackBits(OtherAxis(axis)), + AxisToTrack(OtherAxis(axis)), GetRailType(t) ); } else { @@ -1297,7 +1297,7 @@ bool AfterLoadGame() continue; } if (v->type == VehicleType::Train) { - Train::From(v)->track = TRACK_BIT_WORMHOLE; + Train::From(v)->track = Track::Wormhole; } else { RoadVehicle::From(v)->state = RVSB_WORMHOLE; } @@ -1439,7 +1439,7 @@ bool AfterLoadGame() } } - YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK); + YapfNotifyTrackLayoutChange(INVALID_TILE, Track::Invalid); if (IsSavegameVersionBefore(SLV_34)) { for (Company *c : Company::Iterate()) ResetCompanyLivery(c); @@ -2026,8 +2026,8 @@ bool AfterLoadGame() case TileType::Railway: if (HasSignals(t)) { /* move the signal variant */ - SetSignalVariant(t, TRACK_UPPER, HasBit(t.m2(), 2) ? SignalVariant::Semaphore : SignalVariant::Electric); - SetSignalVariant(t, TRACK_LOWER, HasBit(t.m2(), 6) ? SignalVariant::Semaphore : SignalVariant::Electric); + SetSignalVariant(t, Track::Upper, HasBit(t.m2(), 2) ? SignalVariant::Semaphore : SignalVariant::Electric); + SetSignalVariant(t, Track::Lower, HasBit(t.m2(), 6) ? SignalVariant::Semaphore : SignalVariant::Electric); ClrBit(t.m2(), 2); ClrBit(t.m2(), 6); } @@ -2036,7 +2036,7 @@ bool AfterLoadGame() if (IsRailDepot(t)) { SetDepotReservation(t, false); } else { - SetTrackReservation(t, TRACK_BIT_NONE); + SetTrackReservation(t, {}); } break; @@ -2672,16 +2672,16 @@ bool AfterLoadGame() v->vehstatus.Set(VehState::Hidden); switch (v->type) { - case VehicleType::Train: Train::From(v)->track = TRACK_BIT_WORMHOLE; break; - case VehicleType::Road: RoadVehicle::From(v)->state = RVSB_WORMHOLE; break; + case VehicleType::Train: Train::From(v)->track = Track::Wormhole; break; + case VehicleType::Road: RoadVehicle::From(v)->state = RVSB_WORMHOLE; break; default: NOT_REACHED(); } } else { v->vehstatus.Reset(VehState::Hidden); switch (v->type) { - case VehicleType::Train: Train::From(v)->track = DiagDirToDiagTrackBits(vdir); break; - case VehicleType::Road: RoadVehicle::From(v)->state = DiagDirToDiagTrackdir(vdir); RoadVehicle::From(v)->frame = frame; break; + 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; default: NOT_REACHED(); } } @@ -2757,7 +2757,7 @@ bool AfterLoadGame() if (t->vehstatus.Test(VehState::Crashed)) break; /* Only X/Y tracks can be sloped. */ - if (t->track != TRACK_BIT_X && t->track != TRACK_BIT_Y) break; + if (t->track != Track::X && t->track != Track::Y) break; t->gv_flags |= FixVehicleInclination(t, t->direction); break; @@ -2776,12 +2776,12 @@ bool AfterLoadGame() TrackBits trackbits = TrackdirBitsToTrackBits(ts.trackdirs); /* Only X/Y tracks can be sloped. */ - if (trackbits != TRACK_BIT_X && trackbits != TRACK_BIT_Y) break; + if (trackbits != Track::X && trackbits != Track::Y) break; Direction dir = rv->direction; /* Test if we are reversing. */ - Axis a = trackbits == TRACK_BIT_X ? Axis::X : Axis::Y; + Axis a = trackbits == Track::X ? Axis::X : Axis::Y; if (AxisToDirection(a) != dir && AxisToDirection(a) != ReverseDir(dir)) { /* When reversing, the road vehicle is on the edge of the tile, @@ -2808,10 +2808,10 @@ bool AfterLoadGame() if (v->type == VehicleType::Train && !v->vehstatus.Test(VehState::Crashed) && v->direction != DiagDirToDir(dir)) { /* If the train has left the bridge, it shouldn't have - * track == TRACK_BIT_WORMHOLE - this could happen + * track == Track::Wormhole - this could happen * when the train was reversed while on the last "tick" * on the ramp before leaving the ramp to the bridge. */ - Train::From(v)->track = DiagDirToDiagTrackBits(dir); + Train::From(v)->track = DiagDirToDiagTrack(dir); } } @@ -2935,10 +2935,10 @@ bool AfterLoadGame() if (!t->IsPrimaryVehicle()) continue; /* Front not in depot -> consist not entering depot */ - if (t->track != TRACK_BIT_DEPOT) continue; + if (t->track != Track::Depot) continue; /* Back in depot -> consist completely in depot */ - if (t->Last()->track == TRACK_BIT_DEPOT) continue; - for (Train *u = t; u->track == TRACK_BIT_DEPOT; u = u->Next()) { + if (t->Last()->track == Track::Depot) continue; + for (Train *u = t; u->track == Track::Depot; u = u->Next()) { u->direction = ReverseDir(u->direction); } } diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 15e51ec1dd..e77789e798 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -144,7 +144,7 @@ void AfterLoadCompanyStats() uint pieces = 1; if (IsPlainRail(tile)) { TrackBits bits = GetTrackBits(tile); - pieces = CountBits(bits); + pieces = bits.Count(); if (TracksOverlap(bits)) pieces *= pieces; } c->infrastructure.rail[GetRailType(tile)] += pieces; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 5edbdc6821..488105dc17 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -574,7 +574,7 @@ void FixupTrainLengths() * so we need to move all vehicles forward to cover the difference to the * old center, otherwise wagon spacing in trains would be broken upon load. */ for (Train *u = Train::From(v); u != nullptr; u = u->Next()) { - if (u->track == TRACK_BIT_DEPOT || u->vehstatus.Test(VehState::Crashed)) continue; + if (u->track == Track::Depot || u->vehstatus.Test(VehState::Crashed)) continue; Train *next = u->Next(); @@ -627,12 +627,12 @@ void FixupTrainLengths() } /* If the next wagon is still in a depot, check if it shouldn't be outside already. */ - if (next != nullptr && next->track == TRACK_BIT_DEPOT) { + if (next != nullptr && next->track == Track::Depot) { int d = TicksToLeaveDepot(u); if (d <= 0) { /* Next vehicle should have left the depot already, show it and pull forward. */ next->vehstatus.Reset(VehState::Hidden); - next->track = TrackToTrackBits(GetRailDepotTrack(next->tile)); + next->track = GetRailDepotTrack(next->tile); for (int i = 0; i >= d; i--) TrainController(next, nullptr); } } diff --git a/src/script/api/script_marine.cpp b/src/script/api/script_marine.cpp index 5251f3a770..537e65b4df 100644 --- a/src/script/api/script_marine.cpp +++ b/src/script/api/script_marine.cpp @@ -68,12 +68,12 @@ /* Determine the reachable tracks from the shared edge */ TrackBits gtts1 = ::TrackdirBitsToTrackBits(::GetTileTrackStatus(t1, TRANSPORT_WATER, RoadTramType::Invalid, ReverseDiagDir(to_other_tile)).trackdirs) & ::DiagdirReachesTracks(to_other_tile); - if (gtts1 == TRACK_BIT_NONE) return false; + if (gtts1.None()) return false; to_other_tile = ReverseDiagDir(to_other_tile); TrackBits gtts2 = ::TrackdirBitsToTrackBits(::GetTileTrackStatus(t2, TRANSPORT_WATER, RoadTramType::Invalid, ReverseDiagDir(to_other_tile)).trackdirs) & ::DiagdirReachesTracks(to_other_tile); - return gtts2 != TRACK_BIT_NONE; + return gtts2.Any(); } /* static */ bool ScriptMarine::BuildWaterDepot(TileIndex tile, TileIndex front) diff --git a/src/script/api/script_rail.cpp b/src/script/api/script_rail.cpp index c249dc85c7..532f604d4a 100644 --- a/src/script/api/script_rail.cpp +++ b/src/script/api/script_rail.cpp @@ -131,7 +131,7 @@ { if (!IsRailStationTile(tile)) return RAILTRACK_INVALID; - return (RailTrack)::GetRailStationTrackBits(tile); + return static_cast(::TrackBits{::GetRailStationTrack(tile)}.base()); } /* static */ bool ScriptRail::BuildRailDepot(TileIndex tile, TileIndex front) @@ -236,10 +236,10 @@ { if (!IsRailTile(tile)) return RAILTRACK_INVALID; - if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile)); - if (IsLevelCrossingTile(tile)) return ::GetCrossingRailBits(tile); - if (IsRailDepotTile(tile)) return ::TRACK_BIT_NONE; - return ::GetTrackBits(tile); + if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackBits{::GetRailStationTrack(tile)}.base(); + if (IsLevelCrossingTile(tile)) return ::TrackBits{::GetCrossingRailTrack(tile)}.base(); + if (IsRailDepotTile(tile)) return {}; + return ::GetTrackBits(tile).base(); } /* static */ bool ScriptRail::BuildRailTrack(TileIndex tile, RailTrack rail_track) @@ -247,7 +247,7 @@ EnforceCompanyModeValid(false); EnforcePrecondition(false, ::IsValidTile(tile)); EnforcePrecondition(false, rail_track != 0); - EnforcePrecondition(false, (static_cast(rail_track) & ~static_cast(::TRACK_BIT_ALL)) == 0); + EnforcePrecondition(false, (static_cast(rail_track) & ~static_cast(::TRACK_BIT_ALL.base())) == 0); EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0); EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType())); @@ -293,18 +293,18 @@ static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to) { int diag_offset = abs(abs((int)::TileX(*to) - (int)::TileX(tile)) - abs((int)::TileY(*to) - (int)::TileY(tile))); - Track track = TRACK_BEGIN; + Track track = Track::Begin; if (::TileY(from) == ::TileY(*to)) { - track = TRACK_X; + track = Track::X; *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1); } else if (::TileX(from) == ::TileX(*to)) { - track = TRACK_Y; + track = Track::Y; *to -= ScriptMap::GetMapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1); } else if (::TileY(from) < ::TileY(tile)) { if (::TileX(*to) < ::TileX(tile)) { - track = TRACK_UPPER; + track = Track::Upper; } else { - track = TRACK_LEFT; + track = Track::Left; } if (diag_offset != 0) { *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1); @@ -313,9 +313,9 @@ static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to) } } else if (::TileY(from) > ::TileY(tile)) { if (::TileX(*to) < ::TileX(tile)) { - track = TRACK_RIGHT; + track = Track::Right; } else { - track = TRACK_LOWER; + track = Track::Lower; } if (diag_offset != 0) { *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1); @@ -324,9 +324,9 @@ static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to) } } else if (::TileX(from) < ::TileX(tile)) { if (::TileY(*to) < ::TileY(tile)) { - track = TRACK_UPPER; + track = Track::Upper; } else { - track = TRACK_RIGHT; + track = Track::Right; } if (diag_offset == 0) { *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1); @@ -335,9 +335,9 @@ static Track SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to) } } else if (::TileX(from) > ::TileX(tile)) { if (::TileY(*to) < ::TileY(tile)) { - track = TRACK_LEFT; + track = Track::Left; } else { - track = TRACK_LOWER; + track = Track::Lower; } if (diag_offset == 0) { *to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1); @@ -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}}, - {{INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, 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, 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}} }; /* static */ ScriptRail::SignalType ScriptRail::GetSignalType(TileIndex tile, TileIndex front) @@ -418,7 +418,7 @@ static const ScriptRailSignalData _possible_trackdirs[5][NUM_TRACK_DIRECTIONS] = for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) { const Track &track = _possible_trackdirs[data_index][i].track; - if (!(::TrackToTrackBits(track) & GetRailTracks(tile))) continue; + if (!static_cast<::TrackBits>(GetRailTracks(tile)).Test(track)) continue; if (!HasSignalOnTrack(tile, track)) continue; if (!HasSignalOnTrackdir(tile, _possible_trackdirs[data_index][i].trackdir)) continue; SignalType st = (SignalType)::GetSignalType(tile, track); @@ -446,13 +446,13 @@ static bool IsValidSignalType(int signal_type) EnforcePrecondition(false, ::IsPlainRailTile(tile)); EnforcePrecondition(false, ::IsValidSignalType(signal)); - Track track = INVALID_TRACK; + Track track = Track::Invalid; uint signal_cycles = 0; int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile)); for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) { const Track &t = _possible_trackdirs[data_index][i].track; - if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue; + if (!static_cast<::TrackBits>(GetRailTracks(tile)).Test(t)) continue; track = t; signal_cycles = _possible_trackdirs[data_index][i].signal_cycles; break; @@ -475,11 +475,11 @@ static bool IsValidSignalType(int signal_type) EnforcePrecondition(false, ScriptMap::DistanceManhattan(tile, front) == 1) EnforcePrecondition(false, GetSignalType(tile, front) != SIGNALTYPE_NONE); - Track track = INVALID_TRACK; + Track track = Track::Invalid; int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile)); for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) { const Track &t = _possible_trackdirs[data_index][i].track; - if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue; + if (!static_cast<::TrackBits>(GetRailTracks(tile)).Test(t)) continue; track = t; break; } diff --git a/src/script/api/script_rail.hpp b/src/script/api/script_rail.hpp index 09794028aa..0f1d76ea24 100644 --- a/src/script/api/script_rail.hpp +++ b/src/script/api/script_rail.hpp @@ -53,12 +53,12 @@ public: */ enum RailTrack { /* Note: these values represent part of the in-game TrackBits enum */ - RAILTRACK_NE_SW = ::TRACK_BIT_X, ///< Track along the x-axis (north-east to south-west). - RAILTRACK_NW_SE = ::TRACK_BIT_Y, ///< Track along the y-axis (north-west to south-east). - RAILTRACK_NW_NE = ::TRACK_BIT_UPPER, ///< Track in the upper corner of the tile (north). - RAILTRACK_SW_SE = ::TRACK_BIT_LOWER, ///< Track in the lower corner of the tile (south). - RAILTRACK_NW_SW = ::TRACK_BIT_LEFT, ///< Track in the left corner of the tile (west). - RAILTRACK_NE_SE = ::TRACK_BIT_RIGHT, ///< Track in the right corner of the tile (east). + RAILTRACK_NE_SW = ::TrackBits{Track::X}.base(), ///< Track along the x-axis (north-east to south-west). + RAILTRACK_NW_SE = ::TrackBits{Track::Y}.base(), ///< Track along the y-axis (north-west to south-east). + RAILTRACK_NW_NE = ::TrackBits{Track::Upper}.base(), ///< Track in the upper corner of the tile (north). + RAILTRACK_SW_SE = ::TrackBits{Track::Lower}.base(), ///< Track in the lower corner of the tile (south). + RAILTRACK_NW_SW = ::TrackBits{Track::Left}.base(), ///< Track in the left corner of the tile (west). + RAILTRACK_NE_SE = ::TrackBits{Track::Right}.base(), ///< Track in the right corner of the tile (east). RAILTRACK_INVALID = 0xFF, ///< Flag for an invalid track. }; diff --git a/src/ship.h b/src/ship.h index 011119f6af..b08b4a144e 100644 --- a/src/ship.h +++ b/src/ship.h @@ -50,7 +50,7 @@ struct Ship final : public SpecializedVehicle { int GetDisplayMaxSpeed() const override { return this->vcache.cached_max_speed / 2; } int GetCurrentMaxSpeed() const override { return std::min(this->vcache.cached_max_speed, this->current_order.GetMaxSpeed() * 2); } Money GetRunningCost() const override; - bool IsInDepot() const override { return this->state == TRACK_BIT_DEPOT; } + bool IsInDepot() const override { return this->state == Track::Depot; } bool Tick() override; void OnNewCalendarDay() override; void OnNewEconomyDay() override; diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 27843c413d..72507cf47e 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -294,7 +294,7 @@ Trackdir Ship::GetVehicleTrackdir() const return DiagDirToDiagTrackdir(GetShipDepotDirection(this->tile)); } - if (this->state == TRACK_BIT_WORMHOLE) { + if (this->state == Track::Wormhole) { /* ship on aqueduct, so just use its direction and assume a diagonal track */ return DiagDirToDiagTrackdir(DirToDiagDir(this->direction)); } @@ -391,7 +391,7 @@ static bool CheckShipStayInDepot(Ship *v) v->direction = DiagDirToDir(TrackdirToExitdir(v->GetVehicleTrackdir())); if (CheckReverseShip(v)) v->direction = ReverseDir(v->direction); - v->state = AxisToTrackBits(GetShipDepotAxis(v->tile)); + v->state = AxisToTrack(GetShipDepotAxis(v->tile)); v->rotation = v->direction; v->vehstatus.Reset(VehState::Hidden); v->cur_speed = 0; @@ -461,7 +461,7 @@ static void ShipArrivesAt(const Vehicle *v, Station *st) * @param v Ship to navigate * @param tile Tile, the ship is about to enter * @param tracks Available track choices on \a tile - * @return Track to choose, or INVALID_TRACK when to reverse. + * @return Track to choose, or Track::Invalid when to reverse. */ static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks) { @@ -472,14 +472,14 @@ static Track ChooseShipTrack(Ship *v, TileIndex tile, TrackBits tracks) /* No destination, don't invoke pathfinder. */ track = TrackBitsToTrack(v->state); if (!IsDiagonalTrack(track)) track = TrackToOppositeTrack(track); - if (!HasBit(tracks, track)) track = FindFirstTrack(tracks); + if (!tracks.Test(track)) track = FindFirstTrack(tracks); path_found = false; } else { /* Attempt to follow cached path. */ if (!v->path.empty()) { track = TrackdirToTrack(v->path.back().trackdir); - if (HasBit(tracks, track)) { + if (tracks.Test(track)) { v->path.pop_back(); /* HandlePathfindResult() is not called here because this is not a new pathfinder result. */ return track; @@ -655,7 +655,7 @@ static void ShipController(Ship *v) if (ShipMoveUpDownOnLock(v)) return; GetNewVehiclePosResult gp = GetNewVehiclePos(v); - if (v->state != TRACK_BIT_WORMHOLE) { + if (v->state != Track::Wormhole) { /* Not on a bridge */ if (gp.old_tile == gp.new_tile) { /* Staying in tile */ @@ -675,7 +675,7 @@ static void ShipController(Ship *v) /* Test if continuing forward would lead to a dead-end, moving into the dock. */ const DiagDirection exitdir = VehicleExitDir(v->direction, v->state); const TileIndex tile = TileAddByDiagDir(v->tile, exitdir); - if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, RoadTramType::Invalid, exitdir).trackdirs) == TRACK_BIT_NONE) return ReverseShip(v); + if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_WATER, RoadTramType::Invalid, exitdir).trackdirs).None()) return ReverseShip(v); } else if (v->dest_tile != INVALID_TILE) { /* We have a target, let's see if we reached it... */ if (v->current_order.IsType(OT_GOTO_WAYPOINT) && @@ -715,7 +715,7 @@ static void ShipController(Ship *v) const DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile); assert(diagdir != DiagDirection::Invalid); const TrackBits tracks = GetAvailShipTracks(gp.new_tile, diagdir); - if (tracks == TRACK_BIT_NONE) { + if (tracks.None()) { Trackdir trackdir = INVALID_TRACKDIR; CheckReverseShip(v, &trackdir); if (trackdir == INVALID_TRACKDIR) return ReverseShip(v); @@ -735,7 +735,7 @@ static void ShipController(Ship *v) if (!vets.Test(VehicleEnterTileState::EnteredWormhole)) { v->tile = gp.new_tile; - v->state = TrackToTrackBits(track); + v->state = track; /* Update ship cache when the water class changes. Aqueducts are always canals. */ if (GetEffectiveWaterClass(gp.old_tile) != GetEffectiveWaterClass(gp.new_tile)) v->UpdateCache(); @@ -853,7 +853,7 @@ CommandCost CmdBuildShip(DoCommandFlags flags, TileIndex tile, const Engine *e, v->reliability_spd_dec = e->reliability_spd_dec; v->max_age = e->GetLifeLengthInDays(); - v->state = TRACK_BIT_DEPOT; + v->state = Track::Depot; v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships); v->date_of_last_service = TimerGameEconomy::date; diff --git a/src/signal.cpp b/src/signal.cpp index 4096758464..9f6779eb87 100644 --- a/src/signal.cpp +++ b/src/signal.cpp @@ -35,7 +35,7 @@ static constexpr DiagDirectionIndexArray _enterdir_to_trackbits{ TRACK_BIT_3WAY_NE, TRACK_BIT_3WAY_SE, TRACK_BIT_3WAY_SW, - TRACK_BIT_3WAY_NW + TRACK_BIT_3WAY_NW, }; /** Accessible TrackdirBits from a given enter direction. */ @@ -200,7 +200,7 @@ static SmallSet _globset("_globset"); ///< set of */ static bool IsTrainAndNotInDepot(const Vehicle *v) { - return v->type == VehicleType::Train && Train::From(v)->track != TRACK_BIT_DEPOT; + return v->type == VehicleType::Train && Train::From(v)->track != Track::Depot; } @@ -302,19 +302,19 @@ static SigFlags ExploreSegment(Owner owner) assert(IsValidDiagDirection(enterdir)); TrackBits tracks = GetTrackBits(tile); // trackbits of tile - TrackBits tracks_masked = static_cast(tracks & _enterdir_to_trackbits[enterdir]); // only accessible trackbits + TrackBits tracks_masked = tracks & _enterdir_to_trackbits[enterdir]; // only accessible trackbits if (tracks == TRACK_BIT_HORZ || tracks == TRACK_BIT_VERT) { // there is exactly one accessible track, no need to check tracks = tracks_masked; /* If no train detected yet, and there is not no train -> there is a train -> set the flag */ if (!flags.Test(SigFlag::Train) && EnsureNoTrainOnTrackBits(tile, tracks).Failed()) flags. Set(SigFlag::Train); } else { - if (tracks_masked == TRACK_BIT_NONE) continue; // no accessible track + if (tracks_masked.None()) continue; // no accessible track if (!flags.Test(SigFlag::Train) && HasVehicleOnTile(tile, IsTrainAndNotInDepot)) flags.Set(SigFlag::Train); } /* Is this a track merge or split? */ - if (!HasAtMostOneBit(tracks)) flags.Set(SigFlag::Split); + if (tracks.Count() > 1) flags.Set(SigFlag::Split); if (HasSignals(tile)) { // there is exactly one track - not zero, because there is exit from this tile Track track = TrackBitsToTrack(tracks_masked); // mask TRACK_BIT_X and Y too @@ -349,7 +349,7 @@ static SigFlags ExploreSegment(Owner owner) } for (DiagDirection dir = DiagDirection::Begin; dir < DiagDirection::End; dir++) { // test all possible exit directions - if (dir != enterdir && (tracks & _enterdir_to_trackbits[dir])) { // any accessible track? + if (dir != enterdir && tracks.Any(_enterdir_to_trackbits[dir])) { // any accessible track? TileIndex newtile = tile + TileOffsByDiagDir(dir); // new tile to check DiagDirection newdir = ReverseDiagDir(dir); // direction we are entering from if (!MaybeAddToTodoSet(newtile, newdir, tile, dir)) return flags | SigFlag::Full; @@ -427,7 +427,7 @@ static void UpdateSignalsAroundSegment(SigFlags flags) SignalState newstate = SignalState::Green; /* Signal state of reserved path signals is handled by the reserve/unreserve process. */ - if (IsPbsSignal(sig) && (GetRailReservationTrackBits(tile) & TrackToTrackBits(track)) != TRACK_BIT_NONE) continue; + if (IsPbsSignal(sig) && GetRailReservationTrackBits(tile).Test(track)) continue; /* determine whether the new state is red */ if (flags.Test(SigFlag::Train)) { @@ -522,7 +522,7 @@ static SigSegState UpdateSignalsInBuffer(Owner owner) case TileType::Station: case TileType::Road: - if ((TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & _enterdir_to_trackbits[dir]) != TRACK_BIT_NONE) { + if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Any(_enterdir_to_trackbits[dir])) { /* only add to set when there is some 'interesting' track */ _tbdset.Add(tile, dir); _tbdset.Add(tile + TileOffsByDiagDir(dir), ReverseDiagDir(dir)); @@ -534,7 +534,7 @@ static SigSegState UpdateSignalsInBuffer(Owner owner) /* jump to next tile */ tile = tile + TileOffsByDiagDir(dir); dir = ReverseDiagDir(dir); - if ((TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & _enterdir_to_trackbits[dir]) != TRACK_BIT_NONE) { + if (TrackdirBitsToTrackBits(GetTileTrackStatus(tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs).Any(_enterdir_to_trackbits[dir])) { _tbdset.Add(tile, dir); break; } @@ -607,8 +607,8 @@ void AddTrackToSignalBuffer(TileIndex tile, Track track, Owner owner) _last_owner = owner; - _globset.Add(tile, _search_dir_1[track]); - _globset.Add(tile, _search_dir_2[track]); + _globset.Add(tile, _search_dir_1[to_underlying(track)]); + _globset.Add(tile, _search_dir_2[to_underlying(track)]); if (_globset.Items() >= SIG_GLOB_UPDATE) { /* too many items, force update */ diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 51c9613d0e..d36f1060e7 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1050,9 +1050,9 @@ static CommandCost CheckFlatLandRailStation(TileIndex tile_cur, TileIndex north_ if (HasPowerOnRail(GetRailType(tile_cur), rt)) { /* The existing track must align with the desired station axis. */ Track track = AxisToTrack(axis); - if (GetTrackBits(tile_cur) == TrackToTrackBits(track)) { + if (GetTrackBits(tile_cur) == track) { /* Check for trains having a reservation for this tile. */ - if (HasBit(GetRailReservationTrackBits(tile_cur), track)) { + if (GetRailReservationTrackBits(tile_cur).Test(track)) { Train *v = GetTrainForReservation(tile_cur, track); if (v != nullptr) { affected_vehicles.push_back(v); @@ -1810,7 +1810,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector &affected_st DoClearSquare(tile); DeleteNewGRFInspectWindow(GrfSpecFeature::Stations, tile.base()); - if (build_rail) MakeRailNormal(tile, owner, TrackToTrackBits(track), rt); + if (build_rail) MakeRailNormal(tile, owner, track, rt); Company::Get(owner)->infrastructure.station--; DirtyCompanyInfrastructureWindows(owner); @@ -3690,12 +3690,12 @@ static void GetTileDesc_Station(TileIndex tile, TileDesc &td) /** @copydoc GetTileTrackStatusProc */ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode, RoadTramType sub_mode, DiagDirection side) { - TrackBits trackbits = TRACK_BIT_NONE; + TrackBits trackbits{}; switch (mode) { case TRANSPORT_RAIL: if (HasStationRail(tile) && !IsStationTileBlocked(tile)) { - trackbits = TrackToTrackBits(GetRailStationTrack(tile)); + trackbits = GetRailStationTrack(tile); } break; @@ -3704,9 +3704,9 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode if (IsBuoy(tile)) { trackbits = TRACK_BIT_ALL; /* remove tracks that connect NE map edge */ - if (TileX(tile) == 0) trackbits &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT); + if (TileX(tile) == 0) trackbits.Reset(TRACK_BIT_3WAY_NE); /* remove tracks that connect NW map edge */ - if (TileY(tile) == 0) trackbits &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER); + if (TileY(tile) == 0) trackbits.Reset({Track::Y, Track::Left, Track::Upper}); } break; @@ -3718,11 +3718,11 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode if (IsBayRoadStopTile(tile)) { DiagDirection dir = GetBayRoadStopDir(tile); if (side != DiagDirection::Invalid && dir != side) break; - trackbits = DiagDirToDiagTrackBits(dir); + trackbits = DiagDirToDiagTrack(dir); } else { Axis axis = GetDriveThroughStopAxis(tile); if (side != DiagDirection::Invalid && axis != DiagDirToAxis(side)) break; - trackbits = AxisToTrackBits(axis); + trackbits = AxisToTrack(axis); } } break; diff --git a/src/station_map.h b/src/station_map.h index fd42960da0..28ea1341a0 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -517,17 +517,6 @@ inline Track GetRailStationTrack(Tile t) return AxisToTrack(GetRailStationAxis(t)); } -/** - * Get the trackbits of a rail station tile. - * @param t Tile to query - * @pre HasStationRail(t) - * @return The trackbits of the rails on tile \a t. - */ -inline TrackBits GetRailStationTrackBits(Tile t) -{ - return AxisToTrackBits(GetRailStationAxis(t)); -} - /** * Check if a tile is a valid continuation to a railstation tile. * The tile \a test_tile is a valid continuation to \a station_tile, if all of the following are true: @@ -582,7 +571,7 @@ inline void SetRailStationReservation(Tile t, bool b) */ inline TrackBits GetStationReservationTrackBits(Tile t) { - return HasStationReservation(t) ? GetRailStationTrackBits(t) : TRACK_BIT_NONE; + return HasStationReservation(t) ? GetRailStationTrack(t) : TrackBits{}; } /** diff --git a/src/table/elrail_data.h b/src/table/elrail_data.h index 4a028e0409..505bbca1db 100644 --- a/src/table/elrail_data.h +++ b/src/table/elrail_data.h @@ -212,10 +212,10 @@ static const TrackIndexArray> _disallowed_pp /** This array stores which track bits can meet at a tile edge. */ static const DiagDirectionIndexArray> _tracks_at_pcp{{{ - {TRACK_X, TRACK_X, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, - {TRACK_Y, TRACK_Y, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, - {TRACK_X, TRACK_X, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, - {TRACK_Y, TRACK_Y, TRACK_UPPER, TRACK_LOWER, TRACK_LEFT, TRACK_RIGHT}, + {Track::X, Track::X, Track::Upper, Track::Lower, Track::Left, Track::Right}, + {Track::Y, Track::Y, Track::Upper, Track::Lower, Track::Left, Track::Right}, + {Track::X, Track::X, Track::Upper, Track::Lower, Track::Left, Track::Right}, + {Track::Y, Track::Y, Track::Upper, Track::Lower, Track::Left, Track::Right}, }}}; /** Takes each of the 6 track bits from the array above and assigns it to the home tile or neighbour tile. */ @@ -493,7 +493,7 @@ enum RailCatenarySprite : uint8_t { * d) both * PCP exists. */ -static const RailCatenarySprite _rail_wires[5][TRACK_END][4] = { +static const RailCatenarySprite _rail_wires[5][to_underlying(Track::End)][4] = { { // Tileh == 0 {INVALID_CATENARY, WIRE_X_FLAT_NE, WIRE_X_FLAT_SW, WIRE_X_FLAT_BOTH}, {INVALID_CATENARY, WIRE_Y_FLAT_SE, WIRE_Y_FLAT_NW, WIRE_Y_FLAT_BOTH}, diff --git a/src/table/track_data.h b/src/table/track_data.h index 924f9c5594..f915dfe5e0 100644 --- a/src/table/track_data.h +++ b/src/table/track_data.h @@ -36,12 +36,12 @@ extern const TrackIndexArray _track_crosses_trackdirs{ /** Maps a track to all tracks that make 90 deg turns with it. */ extern const TrackIndexArray _track_crosses_tracks{ - TRACK_BIT_Y, // TRACK_X - TRACK_BIT_X, // TRACK_Y - TRACK_BIT_VERT, // TRACK_UPPER - TRACK_BIT_VERT, // TRACK_LOWER - TRACK_BIT_HORZ, // TRACK_LEFT - TRACK_BIT_HORZ // TRACK_RIGHT + Track::Y, // Track::X + Track::X, // Track::Y + {Track::Left, Track::Right}, // Track::Upper + {Track::Left, Track::Right}, // Track::Lower + {Track::Upper, Track::Lower}, // Track::Left + {Track::Upper, Track::Lower}, // Track::Right }; /** Maps a trackdir to the (4-way) direction the tile is exited when following that trackdir. */ @@ -87,7 +87,7 @@ extern const DiagDirectionIndexArray _dir_to_diag_trackdir{ /** Maps a single horizontal/vertical trackbit that is in a specific tile corner. */ extern const CornerIndexArray _corner_to_trackbits{ - TRACK_BIT_LEFT, TRACK_BIT_LOWER, TRACK_BIT_RIGHT, TRACK_BIT_UPPER, + Track::Left, Track::Lower, Track::Right, Track::Upper, }; extern const TrackdirBits _uphill_trackdirs[] = { diff --git a/src/track_func.h b/src/track_func.h index c9ea2bd793..8409c0cdc7 100644 --- a/src/track_func.h +++ b/src/track_func.h @@ -15,7 +15,6 @@ #include "direction_func.h" #include "slope_func.h" -using SetTrackBitIterator = SetBitIterator; using SetTrackdirBitIterator = SetBitIterator; /** @@ -27,7 +26,7 @@ using SetTrackdirBitIterator = SetBitIterator; */ inline bool IsValidTrack(Track track) { - return track < TRACK_END; + return track < Track::End; } /** @@ -56,8 +55,8 @@ inline bool IsValidTrackdir(Trackdir trackdir) /** * Convert an Axis to the corresponding Track - * Axis::X -> TRACK_X - * Axis::Y -> TRACK_Y + * Axis::X -> Track::X + * Axis::Y -> Track::Y * Uses the fact that they share the same internal encoding * * @param a the axis to convert @@ -69,27 +68,6 @@ inline Track AxisToTrack(Axis a) return static_cast(to_underlying(a)); } -/** - * Maps a Track to the corresponding TrackBits value - * @param track the track to convert - * @return the converted TrackBits value of the track - */ -inline TrackBits TrackToTrackBits(Track track) -{ - assert(IsValidTrack(track)); - return (TrackBits)(1 << track); -} - -/** - * Maps an Axis to the corresponding TrackBits value - * @param a the axis to convert - * @return the converted TrackBits value of the axis - */ -inline TrackBits AxisToTrackBits(Axis a) -{ - return TrackToTrackBits(AxisToTrack(a)); -} - /** * Returns a single horizontal/vertical trackbit that is in a specific tile corner. * @@ -119,10 +97,10 @@ inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir) * * This function searches for the first bit in the TrackBits, * remove this bit from the parameter and returns the found - * bit as Track value. It returns INVALID_TRACK if the - * parameter was TRACK_BIT_NONE. This - * is basically used in while-loops to get up to 6 possible - * tracks on a tile until the parameter becomes TRACK_BIT_NONE. + * bit as Track value. It returns Track::Invalid if the + * parameter was empty. This is basically used in while-loops + * to get up to 6 possible tracks on a tile until the parameter + * becomes empty. * * @param tracks The value with the TrackBits * @return The first Track from the TrackBits value @@ -130,13 +108,12 @@ inline TrackdirBits TrackdirToTrackdirBits(Trackdir trackdir) */ inline Track RemoveFirstTrack(TrackBits *tracks) { - if (*tracks != TRACK_BIT_NONE) { - assert((*tracks & ~TRACK_BIT_MASK) == TRACK_BIT_NONE); - Track first = (Track)FindFirstBit(*tracks); - ClrBit(*tracks, first); - return first; - } - return INVALID_TRACK; + if (tracks->None()) return Track::Invalid; + + assert(!tracks->Any({Track::Wormhole, Track::Depot})); + Track first = tracks->GetNthSetBit(0).value(); + tracks->Reset(first); + return first; } /** @@ -165,18 +142,18 @@ inline Trackdir RemoveFirstTrackdir(TrackdirBits *trackdirs) } /** - * Returns first Track from TrackBits or INVALID_TRACK + * Returns first Track from TrackBits or Track::Invalid * * This function returns the first Track found in the TrackBits value as Track-value. - * It returns INVALID_TRACK if the parameter is TRACK_BIT_NONE. + * It returns Track::Invalid if the parameter is empty. * * @param tracks The TrackBits value - * @return The first Track found or INVALID_TRACK + * @return The first Track found or Track::Invalid * @see RemoveFirstTrack */ inline Track FindFirstTrack(TrackBits tracks) { - return (tracks != TRACK_BIT_NONE) ? (Track)FindFirstBit(tracks) : INVALID_TRACK; + return tracks.GetNthSetBit(0).value_or(Track::Invalid); } /** @@ -192,8 +169,8 @@ inline Track FindFirstTrack(TrackBits tracks) */ inline Track TrackBitsToTrack(TrackBits tracks) { - assert(tracks != TRACK_BIT_NONE && KillFirstBit(tracks & TRACK_BIT_MASK) == TRACK_BIT_NONE); - return static_cast(FindFirstBit(tracks & TRACK_BIT_MASK)); + assert(tracks.Count() == 1 && !tracks.Any({Track::Wormhole, Track::Depot})); + return FindFirstTrack(tracks); } /** @@ -222,8 +199,8 @@ inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs) /** * Find the opposite track to a given track. * - * TRACK_LOWER -> TRACK_UPPER and vice versa, likewise for left/right. - * TRACK_X is mapped to TRACK_Y and reversed. + * Track::Lower -> Track::Upper and vice versa, likewise for left/right. + * Track::X is mapped to Track::Y and reversed. * * @param t the track to convert * @return the opposite track @@ -231,7 +208,7 @@ inline Trackdir FindFirstTrackdir(TrackdirBits trackdirs) inline Track TrackToOppositeTrack(Track t) { assert(IsValidTrack(t)); - return (Track)(t ^ 1); + return static_cast(to_underlying(t) ^ 1); } /** @@ -262,7 +239,7 @@ inline Trackdir ReverseTrackdir(Trackdir trackdir) inline Track TrackdirToTrack(Trackdir trackdir) { assert(IsValidTrackdir(trackdir)); - return (Track)(trackdir & 0x7); + return static_cast(trackdir & 0x7); } /** @@ -307,7 +284,7 @@ inline TrackdirBits TrackToTrackdirBits(Track track) */ inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits) { - return (TrackBits)((bits | (bits >> 8)) & TRACK_BIT_MASK); + return static_cast((bits | (bits >> 8)) & TRACK_BIT_ALL.base()); } /** @@ -318,19 +295,7 @@ inline TrackBits TrackdirBitsToTrackBits(TrackdirBits bits) */ inline TrackdirBits TrackBitsToTrackdirBits(TrackBits bits) { - return static_cast(bits * 0x101); -} - -/** - * Checks whether a TrackBits has a given Track. - * @param tracks The track bits. - * @param track The track to check. - * @return \c true iff \c track is in \c tracks. - */ -inline bool HasTrack(TrackBits tracks, Track track) -{ - assert(IsValidTrack(track)); - return HasBit(tracks, track); + return static_cast(bits.base() * 0x101); } /** @@ -404,7 +369,7 @@ inline DiagDirection TrackdirToExitdir(Trackdir trackdir) * * For the diagonal tracks the resulting track direction are clear for a given * DiagDirection. It either matches the direction or it returns INVALID_TRACKDIR, - * as a TRACK_X cannot be applied with DIAG_SE. + * 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 * if the DiagDirection is pointing 'away' the track. @@ -430,7 +395,7 @@ inline Trackdir TrackExitdirToTrackdir(Track track, DiagDirection diagdir) * 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 + * 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. * @@ -473,18 +438,6 @@ inline Track DiagDirToDiagTrack(DiagDirection diagdir) return static_cast(to_underlying(diagdir) & 1); } -/** - * Maps a DiagDirection to the associated diagonal TrackBits. - * - * @param diagdir The direction - * @return The resulting TrackBits - */ -inline TrackBits DiagDirToDiagTrackBits(DiagDirection diagdir) -{ - assert(IsValidDiagDirection(diagdir)); - return TrackToTrackBits(DiagDirToDiagTrack(diagdir)); -} - /** * Maps a (4-way) direction to the diagonal trackdir that runs in that * direction. @@ -577,7 +530,7 @@ inline TrackdirBits TrackdirCrossesTrackdirs(Trackdir trackdir) inline bool IsDiagonalTrack(Track track) { assert(IsValidTrack(track)); - return (track == TRACK_X) || (track == TRACK_Y); + return (track == Track::X) || (track == Track::Y); } /** @@ -603,7 +556,7 @@ inline bool IsDiagonalTrackdir(Trackdir trackdir) inline bool TracksOverlap(TrackBits bits) { /* With no, or only one track, there is no overlap */ - if (bits == TRACK_BIT_NONE || KillFirstBit(bits) == TRACK_BIT_NONE) return false; + if (bits.Count() <= 1) return false; /* We know that there are at least two tracks present. When there are more * than 2 tracks, they will surely overlap. When there are two, they will * always overlap unless they are lower & upper or right & left. */ @@ -619,8 +572,8 @@ inline bool TracksOverlap(TrackBits bits) */ inline bool TrackOverlapsTracks(TrackBits tracks, Track track) { - if (HasBit(tracks, track)) return true; - return TracksOverlap(tracks | TrackToTrackBits(track)); + if (tracks.Test(track)) return true; + return TracksOverlap(tracks | track); } /** @@ -671,7 +624,7 @@ inline bool IsUphillTrackdir(Slope slope, Trackdir dir) */ inline DiagDirection VehicleExitDir(Direction direction, TrackBits track) { - static constexpr DiagDirectionIndexArray state_dir_table{TRACK_BIT_RIGHT, TRACK_BIT_LOWER, TRACK_BIT_LEFT, TRACK_BIT_UPPER}; + static const DiagDirectionIndexArray state_dir_table{Track::Right, Track::Lower, Track::Left, Track::Upper}; DiagDirection diagdir = DirToDiagDir(direction); diff --git a/src/track_type.h b/src/track_type.h index 72a316ea9d..42a61bb348 100644 --- a/src/track_type.h +++ b/src/track_type.h @@ -16,50 +16,40 @@ * These are used to specify a single track. * Can be translated to a trackbit with TrackToTrackbit */ -enum Track : uint8_t { - TRACK_BEGIN = 0, ///< Used for iterations - TRACK_X = 0, ///< Track along the x-axis (north-east to south-west) - TRACK_Y = 1, ///< Track along the y-axis (north-west to south-east) - TRACK_UPPER = 2, ///< Track in the upper corner of the tile (north) - TRACK_LOWER = 3, ///< Track in the lower corner of the tile (south) - TRACK_LEFT = 4, ///< Track in the left corner of the tile (west) - TRACK_RIGHT = 5, ///< Track in the right corner of the tile (east) - TRACK_END, ///< Used for iterations - INVALID_TRACK = 0xFF, ///< Flag for an invalid track -}; +enum class Track : uint8_t { + Begin = 0, ///< Used for iterations + X = 0, ///< Track along the x-axis (north-east to south-west) + Y = 1, ///< Track along the y-axis (north-west to south-east) + Upper = 2, ///< Track in the upper corner of the tile (north) + Lower = 3, ///< Track in the lower corner of the tile (south) + Left = 4, ///< Track in the left corner of the tile (west) + Right = 5, ///< Track in the right corner of the tile (east) + End, ///< End marker (of regular track bits) -/** Allow incrementing of Track variables */ -DECLARE_INCREMENT_DECREMENT_OPERATORS(Track) + Wormhole = 6, ///< Special flag indicating vehicle is inside a bridge or tunnel. + Depot = 7, ///< Special flag indicating a vehicle is inside a depot. + + Invalid = 0xFF, ///< Flag for an invalid track +}; /** * Array with \c Track as index. * @tparam T the type contained within the array. */ template -using TrackIndexArray = EnumIndexArray; +using TrackIndexArray = EnumIndexArray; -/** Bitfield corresponding to Track */ -enum TrackBits : uint8_t { - TRACK_BIT_NONE = 0U, ///< No track - TRACK_BIT_X = 1U << TRACK_X, ///< X-axis track - TRACK_BIT_Y = 1U << TRACK_Y, ///< Y-axis track - TRACK_BIT_UPPER = 1U << TRACK_UPPER, ///< Upper track - TRACK_BIT_LOWER = 1U << TRACK_LOWER, ///< Lower track - TRACK_BIT_LEFT = 1U << TRACK_LEFT, ///< Left track - TRACK_BIT_RIGHT = 1U << TRACK_RIGHT, ///< Right track - TRACK_BIT_CROSS = TRACK_BIT_X | TRACK_BIT_Y, ///< X-Y-axis cross - TRACK_BIT_HORZ = TRACK_BIT_UPPER | TRACK_BIT_LOWER, ///< Upper and lower track - TRACK_BIT_VERT = TRACK_BIT_LEFT | TRACK_BIT_RIGHT, ///< Left and right track - TRACK_BIT_3WAY_NE = TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT,///< "Arrow" to the north-east - TRACK_BIT_3WAY_SE = TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_RIGHT,///< "Arrow" to the south-east - TRACK_BIT_3WAY_SW = TRACK_BIT_X | TRACK_BIT_LOWER | TRACK_BIT_LEFT, ///< "Arrow" to the south-west - TRACK_BIT_3WAY_NW = TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_LEFT, ///< "Arrow" to the north-west - TRACK_BIT_ALL = TRACK_BIT_CROSS | TRACK_BIT_HORZ | TRACK_BIT_VERT, ///< All possible tracks - TRACK_BIT_MASK = 0x3FU, ///< Bitmask for the first 6 bits - TRACK_BIT_WORMHOLE = 0x40U, ///< Bitflag for a wormhole (used for tunnels) - TRACK_BIT_DEPOT = 0x80U, ///< Bitflag for a depot -}; -DECLARE_ENUM_AS_BIT_SET(TrackBits) +/** Bitset of \c Track elements. */ +using TrackBits = EnumBitSet; + +static constexpr TrackBits TRACK_BIT_CROSS = {Track::X, Track::Y}; ///< X-Y-axis cross +static constexpr TrackBits TRACK_BIT_HORZ = {Track::Upper, Track::Lower}; ///< Upper and lower track +static constexpr TrackBits TRACK_BIT_VERT = {Track::Left, Track::Right}; ///< Left and right track +static constexpr TrackBits TRACK_BIT_3WAY_NE = {Track::X, Track::Upper, Track::Right}; ///< "Arrow" to the north-east +static constexpr TrackBits TRACK_BIT_3WAY_SE = {Track::Y, Track::Lower, Track::Right}; ///< "Arrow" to the south-east +static constexpr TrackBits TRACK_BIT_3WAY_SW = {Track::X, Track::Lower, Track::Left}; ///< "Arrow" to the south-west +static constexpr TrackBits TRACK_BIT_3WAY_NW = {Track::Y, Track::Upper, Track::Left}; ///< "Arrow" to the north-west +static constexpr TrackBits TRACK_BIT_ALL = {Track::X, Track::Y, Track::Upper, Track::Lower, Track::Left, Track::Right}; ///< All possible tracks /** * Enumeration for tracks and directions. diff --git a/src/train.h b/src/train.h index ea7fe7bfaa..6bfe149176 100644 --- a/src/train.h +++ b/src/train.h @@ -128,7 +128,7 @@ struct Train final : public GroundVehicle { Money GetRunningCost() const override; int GetCursorImageOffset() const; int GetDisplayImageWidth(Point *offset = nullptr) const; - bool IsInDepot() const override { return this->track == TRACK_BIT_DEPOT; } + bool IsInDepot() const override { return this->track == Track::Depot; } bool Tick() override; void OnNewCalendarDay() override; void OnNewEconomyDay() override; @@ -272,7 +272,7 @@ protected: // These functions should not be called outside acceleration code. inline uint8_t GetAirDragArea() const { /* Air drag is higher in tunnels due to the limited cross-section. */ - return (this->track == TRACK_BIT_WORMHOLE && this->vehstatus.Test(VehState::Hidden)) ? 28 : 14; + return (this->track == Track::Wormhole && this->vehstatus.Test(VehState::Hidden)) ? 28 : 14; } /** @@ -348,7 +348,7 @@ protected: // These functions should not be called outside acceleration code. inline bool TileMayHaveSlopedTrack() const { /* Any track that isn't TRACK_BIT_X or TRACK_BIT_Y cannot be sloped. */ - return this->track == TRACK_BIT_X || this->track == TRACK_BIT_Y; + return this->track == Track::X || this->track == Track::Y; } /** diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 9b7fe2e01b..c89ab65757 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -82,10 +82,10 @@ void CheckTrainsLengths() for (const Train *v : Train::Iterate()) { if (v->First() == v && !v->vehstatus.Test(VehState::Crashed)) { for (const Train *u = v->GetMovingFront(), *w = v->GetMovingNext(); w != nullptr; u = w, w = w->GetMovingNext()) { - if (u->track != TRACK_BIT_DEPOT) { - if ((w->track != TRACK_BIT_DEPOT && + if (u->track != Track::Depot) { + if ((w->track != Track::Depot && std::max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->CalcNextVehicleOffset()) || - (w->track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) { + (w->track == Track::Depot && TicksToLeaveDepot(u) <= 0)) { ShowErrorMessage(GetEncodedString(STR_BROKEN_VEHICLE_LENGTH, v->index, v->owner), {}, WarningLevel::Critical); if (!_networking && first) { @@ -417,14 +417,14 @@ int Train::GetCurrentMaxSpeed() const } for (const Train *u = this; u != nullptr; u = u->Next()) { - if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && u->track == TRACK_BIT_DEPOT) { + if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && u->track == Track::Depot) { constexpr int DEPOT_SPEED_LIMIT = 61; max_speed = std::min(max_speed, DEPOT_SPEED_LIMIT); break; } /* Vehicle is on the middle part of a bridge. */ - if (u->track == TRACK_BIT_WORMHOLE && !u->vehstatus.Test(VehState::Hidden)) { + if (u->track == Track::Wormhole && !u->vehstatus.Test(VehState::Hidden)) { max_speed = std::min(max_speed, GetBridgeSpec(GetBridgeType(u->tile))->speed); } } @@ -687,7 +687,7 @@ static CommandCost CmdBuildRailWagon(DoCommandFlags flags, TileIndex tile, const v->y_pos = y; v->z_pos = GetSlopePixelZ(x, y, true); v->owner = _current_company; - v->track = TRACK_BIT_DEPOT; + v->track = Track::Depot; v->vehstatus = {VehState::Hidden, VehState::DefaultPalette}; v->SetWagon(); @@ -762,7 +762,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v) u->x_pos = v->x_pos; u->y_pos = v->y_pos; u->z_pos = v->z_pos; - u->track = TRACK_BIT_DEPOT; + u->track = Track::Depot; u->vehstatus = v->vehstatus; u->vehstatus.Reset(VehState::Stopped); u->spritenum = v->spritenum + 1; @@ -820,7 +820,7 @@ CommandCost CmdBuildRailVehicle(DoCommandFlags flags, TileIndex tile, const Engi v->x_pos = x; v->y_pos = y; v->z_pos = GetSlopePixelZ(x, y, true); - v->track = TRACK_BIT_DEPOT; + v->track = Track::Depot; v->vehstatus = {VehState::Hidden, VehState::Stopped, VehState::DefaultPalette}; v->spritenum = rvi->image_index; v->cargo_type = e->GetDefaultCargoType(); @@ -1652,17 +1652,17 @@ static void UpdateStatusAfterSwap(Train *v, bool reverse = true) if (reverse) v->direction = ReverseDir(v->direction); /* Call the proper EnterTile function unless we are in a wormhole. */ - if (v->track != TRACK_BIT_WORMHOLE) { + if (v->track != Track::Wormhole) { VehicleEnterTile(v, v->tile, v->x_pos, v->y_pos); } else { - /* VehicleEnterTile_TunnelBridge() sets TRACK_BIT_WORMHOLE when the vehicle + /* VehicleEnterTile_TunnelBridge() sets Track::Wormhole when the vehicle * is on the last bit of the bridge head (frame == TILE_SIZE - 1). - * If we were swapped with such a vehicle, we have set TRACK_BIT_WORMHOLE, + * If we were swapped with such a vehicle, we have set Track::Wormhole, * when we shouldn't have. Check if this is the case. */ TileIndex vt = TileVirtXY(v->x_pos, v->y_pos); if (IsTileType(vt, TileType::TunnelBridge)) { VehicleEnterTile(v, vt, v->x_pos, v->y_pos); - if (v->track != TRACK_BIT_WORMHOLE && IsBridgeTile(v->tile)) { + if (v->track != Track::Wormhole && IsBridgeTile(v->tile)) { /* We have just left the wormhole, possibly set the * "goingdown" bit. UpdateInclination() can be used * because we are at the border of the tile. */ @@ -1969,7 +1969,7 @@ static void AdvanceWagonsAfterSwap(Train *moving_front) { /* first of all, fix the situation when the train was entering a depot */ Train *dep = moving_front; // last vehicle in front of just left depot - while (dep->GetMovingNext() != nullptr && (dep->track == TRACK_BIT_DEPOT || dep->GetMovingNext()->track != TRACK_BIT_DEPOT)) { + while (dep->GetMovingNext() != nullptr && (dep->track == Track::Depot || dep->GetMovingNext()->track != Track::Depot)) { dep = dep->GetMovingNext(); // find first vehicle outside of a depot, with next vehicle inside a depot } @@ -1981,7 +1981,7 @@ static void AdvanceWagonsAfterSwap(Train *moving_front) if (d <= 0) { leave->vehstatus.Reset(VehState::Hidden); // move it out of the depot - leave->track = TrackToTrackBits(GetRailDepotTrack(leave->tile)); + leave->track = GetRailDepotTrack(leave->tile); for (int i = 0; i >= d; i--) TrainController(leave, nullptr); // maybe move it, and maybe let another wagon leave } } else { @@ -2021,7 +2021,7 @@ static void AdvanceWagonsAfterSwap(Train *moving_front) static bool IsWholeTrainInsideDepot(const Train *v) { for (const Train *u = v; u != nullptr; u = u->Next()) { - if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return false; + if (u->track != Track::Depot || u->tile != v->tile) return false; } return true; } @@ -2090,7 +2090,7 @@ static void ReverseTrainDirection(Train *consist) if (crossing != INVALID_TILE) MaybeBarCrossingWithSound(crossing); /* If we are inside a depot after reversing, don't bother with path reserving. */ - if (moving_front->track == TRACK_BIT_DEPOT) { + if (moving_front->track == Track::Depot) { /* Can't be stuck here as inside a depot is always a safe tile. */ if (consist->flags.Test(VehicleRailFlag::Stuck)) SetWindowWidgetDirty(WindowClass::VehicleView, consist->index, WID_VV_START_STOP); consist->flags.Reset(VehicleRailFlag::Stuck); @@ -2217,7 +2217,7 @@ static TrainForceProceeding DetermineNextTrainForceProceeding(const Train *t) TileIndex next_tile = TileAddByDiagDir(moving_front->tile, TrackdirToExitdir(moving_front->GetVehicleTrackdir())); if (next_tile == INVALID_TILE || !IsTileType(next_tile, TileType::Railway) || !HasSignals(next_tile)) return TFP_STUCK; TrackBits new_tracks = DiagdirReachesTracks(TrackdirToExitdir(moving_front->GetVehicleTrackdir())) & GetTrackBits(next_tile); - return new_tracks != TRACK_BIT_NONE && HasSignalOnTrack(next_tile, FindFirstTrack(new_tracks)) ? TFP_SIGNAL : TFP_STUCK; + return new_tracks.Any() && HasSignalOnTrack(next_tile, FindFirstTrack(new_tracks)) ? TFP_SIGNAL : TFP_STUCK; } /** @@ -2297,7 +2297,7 @@ static void CheckNextTrainTile(Train *consist) const Train *moving_front = consist->GetMovingFront(); /* Exit if we are inside a depot. */ - if (moving_front->track == TRACK_BIT_DEPOT) return; + if (moving_front->track == Track::Depot) return; switch (consist->current_order.GetType()) { /* Exit if we reached our destination depot. */ @@ -2338,7 +2338,7 @@ static void CheckNextTrainTile(Train *consist) /* If the next tile is a PBS signal, try to make a reservation. */ TrackBits tracks = TrackdirBitsToTrackBits(ft.new_td_bits); if (Rail90DegTurnDisallowed(GetTileRailType(ft.old_tile), GetTileRailType(ft.new_tile))) { - tracks &= ~TrackCrossesTracks(TrackdirToTrack(ft.old_td)); + tracks.Reset(TrackCrossesTracks(TrackdirToTrack(ft.old_td))); } ChooseTrainTrack(consist, ft.new_tile, ft.exitdir, tracks, false, nullptr, false); } @@ -2355,7 +2355,7 @@ static bool CheckTrainStayInDepot(Train *v) { /* bail out if not all wagons are in the same depot or not in a depot at all */ for (const Train *u = v; u != nullptr; u = u->Next()) { - if (u->track != TRACK_BIT_DEPOT || u->tile != v->tile) return false; + if (u->track != Track::Depot || u->tile != v->tile) return false; } /* if the train got no power, then keep it in the depot */ @@ -2412,7 +2412,7 @@ static bool CheckTrainStayInDepot(Train *v) v->PlayLeaveStationSound(); SetWindowClassesDirty(WindowClass::TrainList); - v->track = AxisToTrackBits(DiagDirToAxis(DirToDiagDir(v->direction))); + v->track = AxisToTrack(DiagDirToAxis(DirToDiagDir(v->direction))); v->vehstatus.Reset(VehState::Hidden); v->cur_speed = 0; @@ -2485,14 +2485,14 @@ void FreeTrainTrackReservation(const Train *consist) /* Can't be holding a reservation if we enter a depot. */ if (IsRailDepotTile(tile) && TrackdirToExitdir(td) != GetRailDepotDirection(tile)) return; - if (moving_front->track == TRACK_BIT_DEPOT) { + if (moving_front->track == Track::Depot) { /* Front engine is in a depot. We enter if some part is not in the depot. */ for (const Train *u = consist; u != nullptr; u = u->Next()) { - if (u->track != TRACK_BIT_DEPOT || u->tile != consist->tile) return; + if (u->track != Track::Depot || u->tile != consist->tile) return; } } /* Don't free reservation if it's not ours. */ - if (TracksOverlap(GetReservedTrackbits(tile) | TrackToTrackBits(TrackdirToTrack(td)))) return; + if (TracksOverlap(GetReservedTrackbits(tile) | TrackdirToTrack(td))) return; CFollowTrackRail ft(consist, GetAllCompatibleRailTypes(consist->railtypes)); while (ft.Follow(tile, td)) { @@ -2778,22 +2778,22 @@ public: /* choose a track */ static Track ChooseTrainTrack(Train *consist, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck) { - Track best_track = INVALID_TRACK; + Track best_track = Track::Invalid; bool do_track_reservation = _settings_game.pf.reserve_paths || force_res; bool changed_signal = false; TileIndex final_dest = INVALID_TILE; - assert((tracks & ~TRACK_BIT_MASK) == 0); + assert(tracks == (tracks & TRACK_BIT_ALL)); if (got_reservation != nullptr) *got_reservation = false; /* Don't use tracks here as the setting to forbid 90 deg turns might have been switched between reservation and now. */ - TrackBits res_tracks = (TrackBits)(GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir)); + TrackBits res_tracks = GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir); /* Do we have a suitable reserved track? */ - if (res_tracks != TRACK_BIT_NONE) return FindFirstTrack(res_tracks); + if (res_tracks.Any()) return FindFirstTrack(res_tracks); /* Quick return in case only one possible track is available */ - if (KillFirstBit(tracks) == TRACK_BIT_NONE) { + if (tracks.Count() == 1) { Track track = FindFirstTrack(tracks); /* We need to check for signals only here, as a junction tile can't have signals. */ if (IsValidTrack(track) && HasPbsSignalOnTrackdir(tile, TrackEnterdirToTrackdir(track, enterdir))) { @@ -2897,7 +2897,7 @@ static Track ChooseTrainTrack(Train *consist, TileIndex tile, DiagDirection ente TileIndex next_tile = TileAddByDiagDir(res_dest.tile, exitdir); TrackBits reachable = TrackdirBitsToTrackBits(GetTileTrackStatus(next_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs) & DiagdirReachesTracks(exitdir); if (Rail90DegTurnDisallowed(GetTileRailType(res_dest.tile), GetTileRailType(next_tile))) { - reachable &= ~TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir)); + reachable.Reset(TrackCrossesTracks(TrackdirToTrack(res_dest.trackdir))); } /* Get next order with destination. */ @@ -2959,7 +2959,7 @@ bool TryPathReserve(Train *consist, bool mark_as_stuck, bool first_tile_okay) /* We have to handle depots specially as the track follower won't look * at the depot tile itself but starts from the next tile. If we are still * inside the depot, a depot reservation can never be ours. */ - if (moving_front->track == TRACK_BIT_DEPOT) { + if (moving_front->track == Track::Depot) { if (HasDepotReservation(moving_front->tile)) { if (mark_as_stuck) MarkTrainAsStuck(consist); return false; @@ -2990,7 +2990,7 @@ bool TryPathReserve(Train *consist, bool mark_as_stuck, bool first_tile_okay) } /* If we are in a depot, tentatively reserve the depot. */ - if (moving_front->track == TRACK_BIT_DEPOT) { + if (moving_front->track == Track::Depot) { SetDepotReservation(moving_front->tile, true); if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(moving_front->tile); } @@ -2999,14 +2999,14 @@ bool TryPathReserve(Train *consist, bool mark_as_stuck, bool first_tile_okay) TileIndex new_tile = TileAddByDiagDir(origin.tile, exitdir); TrackBits reachable = TrackdirBitsToTrackBits(GetTileTrackStatus(new_tile, TRANSPORT_RAIL, RoadTramType::Invalid).trackdirs & DiagdirReachesTrackdirs(exitdir)); - if (Rail90DegTurnDisallowed(GetTileRailType(origin.tile), GetTileRailType(new_tile))) reachable &= ~TrackCrossesTracks(TrackdirToTrack(origin.trackdir)); + if (Rail90DegTurnDisallowed(GetTileRailType(origin.tile), GetTileRailType(new_tile))) reachable.Reset(TrackCrossesTracks(TrackdirToTrack(origin.trackdir))); bool res_made = false; ChooseTrainTrack(consist, new_tile, exitdir, reachable, true, &res_made, mark_as_stuck); if (!res_made) { /* Free the depot reservation as well. */ - if (moving_front->track == TRACK_BIT_DEPOT) SetDepotReservation(moving_front->tile, false); + if (moving_front->track == Track::Depot) SetDepotReservation(moving_front->tile, false); return false; } @@ -3027,12 +3027,12 @@ static bool CheckReverseTrain(const Train *consist) { const Train *moving_front = consist->GetMovingFront(); if (_settings_game.difficulty.train_flip_reverse_allowed == TrainFlipReversingAllowed::EndOfLineOnly || - moving_front->track == TRACK_BIT_DEPOT || moving_front->track == TRACK_BIT_WORMHOLE || + moving_front->track == Track::Depot || moving_front->track == Track::Wormhole || !IsDiagonalDirection(moving_front->GetMovingDirection())) { return false; } - assert(moving_front->track != TRACK_BIT_NONE); + assert(moving_front->track.Any()); return YapfTrainCheckReverse(consist); } @@ -3188,11 +3188,11 @@ static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir) void Train::ReserveTrackUnderConsist() const { for (const Train *u = this; u != nullptr; u = u->Next()) { - switch (u->track) { - case TRACK_BIT_WORMHOLE: + switch (u->track.base()) { + case TrackBits{Track::Wormhole}.base(): TryReserveRailTrack(u->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(u->tile))); break; - case TRACK_BIT_DEPOT: + case TrackBits{Track::Depot}.base(): break; default: TryReserveRailTrack(u->tile, TrackBitsToTrack(u->track)); @@ -3277,7 +3277,7 @@ static uint CheckTrainCollision(Vehicle *v, Train *moving_front) if (v->type != VehicleType::Train) return 0; /* We can't crash into trains in a depot. */ - if (Train::From(v)->track == TRACK_BIT_DEPOT) return 0; + if (Train::From(v)->track == Track::Depot) return 0; /* Do not crash into trains of another company. */ if (v->owner != moving_front->First()->owner) return 0; @@ -3319,14 +3319,14 @@ static uint CheckTrainCollision(Vehicle *v, Train *moving_front) static bool CheckTrainCollision(Train *moving_front) { /* can't collide in depot */ - if (moving_front->track == TRACK_BIT_DEPOT) return false; + if (moving_front->track == Track::Depot) return false; - assert(moving_front->track == TRACK_BIT_WORMHOLE || TileVirtXY(moving_front->x_pos, moving_front->y_pos) == moving_front->tile); + assert(moving_front->track == Track::Wormhole || TileVirtXY(moving_front->x_pos, moving_front->y_pos) == moving_front->tile); uint num_victims = 0; /* find colliding vehicles */ - if (moving_front->track == TRACK_BIT_WORMHOLE) { + if (moving_front->track == Track::Wormhole) { for (Vehicle *u : VehiclesOnTile(moving_front->tile)) { num_victims += CheckTrainCollision(u, moving_front); } @@ -3368,11 +3368,11 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) bool update_signals_crossing = false; // will we update signals or crossing state? GetNewVehiclePosResult gp = GetNewVehiclePos(v); - if (v->track != TRACK_BIT_WORMHOLE) { + if (v->track != Track::Wormhole) { /* Not inside tunnel */ if (gp.old_tile == gp.new_tile) { /* Staying in the old tile */ - if (v->track == TRACK_BIT_DEPOT) { + if (v->track == Track::Depot) { /* Inside depot */ gp.x = v->x_pos; gp.y = v->y_pos; @@ -3410,10 +3410,10 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) if (Rail90DegTurnDisallowed(GetTileRailType(gp.old_tile), GetTileRailType(gp.new_tile)) && prev == nullptr) { /* We allow wagons to make 90 deg turns, because forbid_90_deg * can be switched on halfway a turn */ - bits &= ~TrackCrossesTracks(FindFirstTrack(v->track)); + bits.Reset(TrackCrossesTracks(FindFirstTrack(v->track))); } - if (bits == TRACK_BIT_NONE) goto invalid_rail; + if (bits.None()) goto invalid_rail; /* Check if the new tile constrains tracks that are compatible * with the current train, if not, bail out. */ @@ -3423,8 +3423,8 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) if (v->IsMovingFront()) { /* Currently the locomotive is active. Determine which one of the * available tracks to choose */ - chosen_track = TrackToTrackBits(ChooseTrainTrack(first, gp.new_tile, enterdir, bits, false, nullptr, true)); - assert(chosen_track & (bits | GetReservedTrackbits(gp.new_tile))); + chosen_track = ChooseTrainTrack(first, gp.new_tile, enterdir, bits, false, nullptr, true); + assert(chosen_track.Any(bits | GetReservedTrackbits(gp.new_tile))); if (first->force_proceed != TFP_NONE && IsPlainRailTile(gp.new_tile) && HasSignals(gp.new_tile)) { /* For each signal we find decrease the counter by one. @@ -3443,7 +3443,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) } /* Check if it's a red signal and that force proceed is not clicked. */ - if ((red_signals & chosen_track) && first->force_proceed == TFP_NONE) { + if (red_signals.Any(chosen_track) && first->force_proceed == TFP_NONE) { /* In front of a red signal */ Trackdir i = FindFirstTrackdir(trackdirbits); @@ -3471,7 +3471,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) const Train *t = Train::From(u); /* not front engine of a train, inside wormhole or depot, crashed */ - if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return false; + if (!t->IsFrontEngine() || t->track.Any({Track::Wormhole, Track::Depot})) return false; if (t->cur_speed > 5 || VehicleExitDir(t->direction, t->track) != exitdir) return false; @@ -3497,7 +3497,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) /* The wagon is active, simply follow the prev vehicle. */ if (prev->tile == gp.new_tile) { /* Choose the same track as prev */ - if (prev->track == TRACK_BIT_WORMHOLE) { + if (prev->track == Track::Wormhole) { /* Vehicles entering tunnels enter the wormhole earlier than for bridges. * However, just choose the track into the wormhole. */ assert(IsTunnel(prev->tile)); @@ -3514,10 +3514,10 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) * Is also the train just reversing, the wagon inside the tunnel is 'on' the tile of the opposite tunnel entry. */ static const DiagDirectionIndexArray> _connecting_track{{{ - {TRACK_BIT_X, TRACK_BIT_LOWER, TRACK_BIT_NONE, TRACK_BIT_LEFT }, - {TRACK_BIT_UPPER, TRACK_BIT_Y, TRACK_BIT_LEFT, TRACK_BIT_NONE }, - {TRACK_BIT_NONE, TRACK_BIT_RIGHT, TRACK_BIT_X, TRACK_BIT_UPPER}, - {TRACK_BIT_RIGHT, TRACK_BIT_NONE, TRACK_BIT_LOWER, TRACK_BIT_Y } + {{{Track::X, Track::Lower, {}, Track::Left }}}, + {{{Track::Upper, Track::Y, Track::Left, {} }}}, + {{{{}, Track::Right, Track::X, Track::Upper}}}, + {{{Track::Right, {}, Track::Lower, Track::Y }}} }}}; DiagDirection exitdir = DiagdirBetweenTiles(gp.new_tile, prev->tile); assert(IsValidDiagDirection(exitdir)); @@ -3553,7 +3553,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) } v->track = chosen_track; - assert(v->track); + assert(v->track.Any()); } /* We need to update signal status, but after the vehicle position hash @@ -3720,9 +3720,9 @@ static void DeleteLastWagon(Train *v) delete v; v = nullptr; // make sure nobody will try to read 'v' anymore - if (trackbits == TRACK_BIT_WORMHOLE) { + if (trackbits == Track::Wormhole) { /* Vehicle is inside a wormhole, v->track contains no useful value then. */ - trackbits = DiagDirToDiagTrackBits(GetTunnelBridgeDirection(tile)); + trackbits = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile)); } Track track = TrackBitsToTrack(trackbits); @@ -3730,21 +3730,21 @@ static void DeleteLastWagon(Train *v) UnreserveRailTrack(tile, track); /* If there are still crashed vehicles on the tile, give the track reservation to them */ - TrackBits remaining_trackbits = TRACK_BIT_NONE; + TrackBits remaining_trackbits{}; for (const Vehicle *u : VehiclesOnTile(tile)) { if (u->type != VehicleType::Train || !u->vehstatus.Test(VehState::Crashed)) continue; TrackBits train_tbits = Train::From(u)->track; - if (train_tbits == TRACK_BIT_WORMHOLE) { + if (train_tbits == Track::Wormhole) { /* Vehicle is inside a wormhole, u->track contains no useful value then. */ - remaining_trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(u->tile)); - } else if (train_tbits != TRACK_BIT_DEPOT) { - remaining_trackbits |= train_tbits; + remaining_trackbits.Set(DiagDirToDiagTrack(GetTunnelBridgeDirection(u->tile))); + } else if (train_tbits != Track::Depot) { + remaining_trackbits.Set(train_tbits); } } /* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */ - assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1); - for (Track t : SetTrackBitIterator(remaining_trackbits)) TryReserveRailTrack(tile, t); + assert(Track::Begin == Track::X && to_underlying(Track::Y) == to_underlying(Track::Begin) + 1); + for (Track t : remaining_trackbits) TryReserveRailTrack(tile, t); } /* check if the wagon was on a road/rail-crossing */ @@ -3782,7 +3782,7 @@ static void ChangeTrainDirRandomly(Train *v) /* Refrain from updating the z position of the vehicle when on * a bridge, because UpdateInclination() will put the vehicle under * the bridge in that case */ - if (v->track != TRACK_BIT_WORMHOLE) { + if (v->track != Track::Wormhole) { v->UpdatePosition(); v->UpdateInclination(false, true); } else { @@ -3902,7 +3902,7 @@ static bool TrainApproachingLineEnd(Train *moving_front, bool signal, bool rever static bool TrainCanLeaveTile(const Train *moving_front) { /* Exit if inside a tunnel/bridge or a depot */ - if (moving_front->track == TRACK_BIT_WORMHOLE || moving_front->track == TRACK_BIT_DEPOT) return false; + if (moving_front->track == Track::Wormhole || moving_front->track == Track::Depot) return false; TileIndex tile = moving_front->tile; @@ -3990,11 +3990,11 @@ static bool TrainCheckIfLineEnds(Train *moving_front, bool reverse) /* mask unreachable track bits if we are forbidden to do 90deg turns */ TrackBits bits = TrackdirBitsToTrackBits(trackdirbits); if (Rail90DegTurnDisallowed(GetTileRailType(moving_front->tile), GetTileRailType(tile))) { - bits &= ~TrackCrossesTracks(FindFirstTrack(moving_front->track)); + bits.Reset(TrackCrossesTracks(FindFirstTrack(moving_front->track))); } /* no suitable trackbits at all || unusable rail (wrong type or owner) */ - if (bits == TRACK_BIT_NONE || !CheckCompatibleRail(consist, tile, true)) { + if (bits.None() || !CheckCompatibleRail(consist, tile, true)) { return TrainApproachingLineEnd(moving_front, false, reverse); } @@ -4300,12 +4300,12 @@ Trackdir Train::GetVehicleTrackdir() const { if (this->vehstatus.Test(VehState::Crashed)) return INVALID_TRACKDIR; - if (this->track == TRACK_BIT_DEPOT) { + if (this->track == Track::Depot) { /* We'll assume the train is facing outwards */ return DiagDirToDiagTrackdir(GetRailDepotDirection(this->tile)); // Train in depot } - if (this->track == TRACK_BIT_WORMHOLE) { + if (this->track == Track::Wormhole) { /* train in tunnel or on bridge, so just use its direction and assume a diagonal track */ return DiagDirToDiagTrackdir(DirToDiagDir(this->GetMovingDirection())); } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index af1907410e..b8a5e2c25e 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -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(DiagDirToDiagTrackBits(dir)), TRACKDIR_BIT_NONE}; + return {TrackBitsToTrackdirBits(DiagDirToDiagTrack(dir)), TRACKDIR_BIT_NONE}; } /** @copydoc ChangeTileOwnerProc */ @@ -1974,7 +1974,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde if (v->type == VehicleType::Train) { Train *t = Train::From(v); - if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) { + if (t->track != Track::Wormhole && dir == vdir) { if (t->IsMovingFront() && frame == TUNNEL_SOUND_FRAME) { if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == EngineClass::Steam) { SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v); @@ -1983,7 +1983,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde } if (frame == _tunnel_visibility_frame[dir]) { t->tile = tile; - t->track = TRACK_BIT_WORMHOLE; + t->track = Track::Wormhole; t->vehstatus.Set(VehState::Hidden); return VehicleEnterTileState::EnteredWormhole; } @@ -1992,8 +1992,8 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde if (dir == ReverseDiagDir(vdir) && frame == TILE_SIZE - _tunnel_visibility_frame[dir] && z == 0) { /* We're at the tunnel exit ?? */ t->tile = tile; - t->track = DiagDirToDiagTrackBits(vdir); - assert(t->track); + t->track = DiagDirToDiagTrack(vdir); + assert(t->track.Any()); t->vehstatus.Reset(VehState::Hidden); return VehicleEnterTileState::EnteredWormhole; } @@ -2039,7 +2039,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde switch (v->type) { case VehicleType::Train: { Train *t = Train::From(v); - t->track = TRACK_BIT_WORMHOLE; + t->track = Track::Wormhole; PrepareToEnterBridge(t); break; } @@ -2052,7 +2052,7 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde } case VehicleType::Ship: - Ship::From(v)->state = TRACK_BIT_WORMHOLE; + Ship::From(v)->state = Track::Wormhole; break; default: NOT_REACHED(); @@ -2063,8 +2063,8 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde switch (v->type) { case VehicleType::Train: { Train *t = Train::From(v); - if (t->track == TRACK_BIT_WORMHOLE) { - t->track = DiagDirToDiagTrackBits(vdir); + if (t->track == Track::Wormhole) { + t->track = DiagDirToDiagTrack(vdir); return VehicleEnterTileState::EnteredWormhole; } break; @@ -2082,8 +2082,8 @@ static VehicleEnterTileStates VehicleEnterTile_TunnelBridge(Vehicle *v, TileInde case VehicleType::Ship: { Ship *ship = Ship::From(v); - if (ship->state == TRACK_BIT_WORMHOLE) { - ship->state = DiagDirToDiagTrackBits(vdir); + if (ship->state == Track::Wormhole) { + ship->state = DiagDirToDiagTrack(vdir); return VehicleEnterTileState::EnteredWormhole; } break; diff --git a/src/tunnelbridge_map.h b/src/tunnelbridge_map.h index 0fa5af0607..ebdbbffb18 100644 --- a/src/tunnelbridge_map.h +++ b/src/tunnelbridge_map.h @@ -116,7 +116,7 @@ inline void SetTunnelBridgeReservation(Tile t, bool b) */ inline TrackBits GetTunnelBridgeReservationTrackBits(Tile t) { - return HasTunnelBridgeReservation(t) ? DiagDirToDiagTrackBits(GetTunnelBridgeDirection(t)) : TRACK_BIT_NONE; + return HasTunnelBridgeReservation(t) ? DiagDirToDiagTrack(GetTunnelBridgeDirection(t)) : TrackBits{}; } #endif /* TUNNELBRIDGE_MAP_H */ diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 6e4aad2a7f..0698808b7c 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1587,7 +1587,7 @@ void VehicleEnterDepot(Vehicle *v) case VehicleType::Ship: { SetWindowClassesDirty(WindowClass::ShipList); Ship *ship = Ship::From(v); - ship->state = TRACK_BIT_DEPOT; + ship->state = Track::Depot; ship->UpdateCache(); ship->UpdateViewport(true, true); SetWindowDirty(WindowClass::VehicleDepot, v->tile); diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index b370edf89a..5c9ac46466 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -186,7 +186,7 @@ bool IsPossibleDockingTile(Tile t) case TileType::Railway: case TileType::Station: case TileType::TunnelBridge: - return TrackdirBitsToTrackBits(GetTileTrackStatus(t, TRANSPORT_WATER, RoadTramType::Invalid).trackdirs) != TRACK_BIT_NONE; + return TrackdirBitsToTrackBits(GetTileTrackStatus(t, TRANSPORT_WATER, RoadTramType::Invalid).trackdirs).Any(); default: return false; @@ -1254,11 +1254,11 @@ static void DoDryUp(TileIndex tile) assert(GetRailGroundType(tile) == RailGroundType::HalfTileWater); RailGroundType new_ground; - switch (GetTrackBits(tile)) { - case TRACK_BIT_UPPER: new_ground = RailGroundType::FenceHoriz1; break; - case TRACK_BIT_LOWER: new_ground = RailGroundType::FenceHoriz2; break; - case TRACK_BIT_LEFT: new_ground = RailGroundType::FenceVert1; break; - case TRACK_BIT_RIGHT: new_ground = RailGroundType::FenceVert2; break; + switch (TrackBitsToTrack(GetTrackBits(tile))) { + case Track::Upper: new_ground = RailGroundType::FenceHoriz1; break; + case Track::Lower: new_ground = RailGroundType::FenceHoriz2; break; + case Track::Left: new_ground = RailGroundType::FenceVert1; break; + case Track::Right: new_ground = RailGroundType::FenceVert2; break; default: NOT_REACHED(); } SetRailGroundType(tile, new_ground); @@ -1382,27 +1382,26 @@ void ConvertGroundTilesIntoWaterTiles() /** @copydoc GetTileTrackStatusProc */ static TrackStatus GetTileTrackStatus_Water(TileIndex tile, TransportType mode, [[maybe_unused]] RoadTramType sub_mode, [[maybe_unused]] DiagDirection side) { - static const TrackBits coast_tracks[] = {TRACK_BIT_NONE, TRACK_BIT_RIGHT, TRACK_BIT_UPPER, TRACK_BIT_NONE, TRACK_BIT_LEFT, TRACK_BIT_NONE, TRACK_BIT_NONE, - TRACK_BIT_NONE, TRACK_BIT_LOWER, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE, TRACK_BIT_NONE}; + static const TrackBits coast_tracks[] = {{}, Track::Right, Track::Upper, {}, Track::Left, {}, {}, {}, Track::Lower, {}, {}, {}, {}, {}, {}, {}}; TrackBits ts; if (mode != TRANSPORT_WATER) return {}; switch (GetWaterTileType(tile)) { - case WaterTileType::Clear: ts = IsTileFlat(tile) ? TRACK_BIT_ALL : TRACK_BIT_NONE; break; + case WaterTileType::Clear: ts = IsTileFlat(tile) ? TRACK_BIT_ALL : TrackBits{}; break; case WaterTileType::Coast: ts = coast_tracks[GetTileSlope(tile) & 0xF]; break; - case WaterTileType::Lock: ts = DiagDirToDiagTrackBits(GetLockDirection(tile)); break; - case WaterTileType::Depot: ts = AxisToTrackBits(GetShipDepotAxis(tile)); break; + case WaterTileType::Lock: ts = DiagDirToDiagTrack(GetLockDirection(tile)); break; + case WaterTileType::Depot: ts = AxisToTrack(GetShipDepotAxis(tile)); break; default: return {}; } if (TileX(tile) == 0) { /* NE border: remove tracks that connects NE tile edge */ - ts &= ~(TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT); + ts.Reset({Track::X, Track::Upper, Track::Right}); } if (TileY(tile) == 0) { /* NW border: remove tracks that connects NW tile edge */ - ts &= ~(TRACK_BIT_Y | TRACK_BIT_LEFT | TRACK_BIT_UPPER); + ts.Reset({Track::Y, Track::Left, Track::Upper}); } return {TrackBitsToTrackdirBits(ts), TRACKDIR_BIT_NONE}; } diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index c93ae5a248..5f449354fc 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -111,11 +111,10 @@ Axis GetAxisForNewRailWaypoint(TileIndex tile) /* Non-plain rail type, no valid axis for waypoints. */ if (!IsTileType(tile, TileType::Railway) || GetRailTileType(tile) != RailTileType::Normal) return Axis::Invalid; - switch (GetTrackBits(tile)) { - case TRACK_BIT_X: return Axis::X; - case TRACK_BIT_Y: return Axis::Y; - default: return Axis::Invalid; - } + TrackBits bits = GetTrackBits(tile); + if (bits == Track::X) return Axis::X; + if (bits == Track::Y) return Axis::Y; + return Axis::Invalid; } /** @@ -325,7 +324,7 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi uint8_t old_specindex = HasStationTileRail(tile) ? GetCustomStationSpecIndex(tile) : 0; if (!HasStationTileRail(tile)) c->infrastructure.station++; bool reserved = IsTileType(tile, TileType::Railway) ? - HasBit(GetRailReservationTrackBits(tile), AxisToTrack(axis)) : + GetRailReservationTrackBits(tile).Test(AxisToTrack(axis)) : HasStationReservation(tile); MakeRailWaypoint(tile, wp->owner, wp->index, axis, *it, GetRailType(tile)); SetCustomStationSpecIndex(tile, *specindex);