diff --git a/src/pathfinder/follow_track.hpp b/src/pathfinder/follow_track.hpp index 204917cd01..a8b5038cc6 100644 --- a/src/pathfinder/follow_track.hpp +++ b/src/pathfinder/follow_track.hpp @@ -106,11 +106,11 @@ struct CFollowTrackT { if (IsNormalRoadTile(tile)) { RoadBits rb = GetRoadBits(tile, RoadTramType::Tram); - switch (rb) { - case ROAD_NW: return DIAGDIR_NW; - case ROAD_SW: return DIAGDIR_SW; - case ROAD_SE: return DIAGDIR_SE; - case ROAD_NE: return DIAGDIR_NE; + switch (rb.base()) { + case RoadBits{RoadBit::NW}.base(): return DIAGDIR_NW; + case RoadBits{RoadBit::SW}.base(): return DIAGDIR_SW; + case RoadBits{RoadBit::SE}.base(): return DIAGDIR_SE; + case RoadBits{RoadBit::NE}.base(): return DIAGDIR_NE; default: break; } } diff --git a/src/pathfinder/pathfinder_func.h b/src/pathfinder/pathfinder_func.h index 64593fe246..51ce6da478 100644 --- a/src/pathfinder/pathfinder_func.h +++ b/src/pathfinder/pathfinder_func.h @@ -66,14 +66,14 @@ inline TrackdirBits GetTrackdirBitsForRoad(TileIndex tile, RoadTramType rtt) if (rtt == RoadTramType::Tram && bits == TRACKDIR_BIT_NONE) { if (IsNormalRoadTile(tile)) { RoadBits rb = GetRoadBits(tile, RoadTramType::Tram); - switch (rb) { - case ROAD_NE: - case ROAD_SW: + switch (rb.base()) { + case RoadBits{RoadBit::NE}.base(): + case RoadBits{RoadBit::SW}.base(): bits = TRACKDIR_BIT_X_NE | TRACKDIR_BIT_X_SW; break; - case ROAD_NW: - case ROAD_SE: + case RoadBits{RoadBit::NW}.base(): + case RoadBits{RoadBit::SE}.base(): bits = TRACKDIR_BIT_Y_NW | TRACKDIR_BIT_Y_SE; break; diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 67bd56cee4..eabf620578 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -518,23 +518,23 @@ 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) & ROAD_X) == 0) || - (track == TRACK_Y && ((road | tram) & ROAD_Y) == 0)) { + 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 * so trams can still reverse on this tile. */ - if (Company::IsValidID(tram_owner) && HasExactlyOneBit(tram)) { + if (Company::IsValidID(tram_owner) && tram.Count() == 1) { ret = CheckOwnership(tram_owner); if (ret.Failed()) return ret; } - uint num_new_road_pieces = (road != ROAD_NONE) ? 2 - CountBits(road) : 0; + uint num_new_road_pieces = road.Any() ? 2 - road.Count() : 0; if (num_new_road_pieces > 0) { cost.AddCost(num_new_road_pieces * RoadBuildCost(roadtype_road)); } - uint num_new_tram_pieces = (tram != ROAD_NONE) ? 2 - CountBits(tram) : 0; + uint num_new_tram_pieces = tram.Any() ? 2 - tram.Count() : 0; if (num_new_tram_pieces > 0) { cost.AddCost(num_new_tram_pieces * RoadBuildCost(roadtype_tram)); } diff --git a/src/road.cpp b/src/road.cpp index 6bf808c60d..753a546e7f 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -58,7 +58,7 @@ static bool IsPossibleCrossing(const TileIndex tile, Axis ax) */ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb) { - if (!IsValidTile(tile)) return ROAD_NONE; + if (!IsValidTile(tile)) return {}; for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { const TileIndex neighbour_tile = TileAddByDiagDir(tile, dir); @@ -66,7 +66,7 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb) const RoadBits target_rb = DiagDirToRoadBits(dir); /* If the roadbit is in the current plan */ - if (org_rb & target_rb) { + if (org_rb.Any(target_rb)) { bool connective = false; const RoadBits mirrored_rb = MirrorRoadBits(target_rb); @@ -88,7 +88,7 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb) const RoadBits neighbour_rb = GetAnyRoadBits(neighbour_tile, RoadTramType::Road) | GetAnyRoadBits(neighbour_tile, RoadTramType::Tram); /* Accept only connective tiles */ - connective = (neighbour_rb & mirrored_rb) != ROAD_NONE; + connective = neighbour_rb.Any(mirrored_rb); } break; @@ -107,7 +107,7 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb) } /* If the neighbour tile is inconnective, remove the planned road connection to it */ - if (!connective) org_rb ^= target_rb; + if (!connective) org_rb.Flip(target_rb); } } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 479b682b5f..3f44cadeb4 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -195,48 +195,48 @@ void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count) static const RoadBits _invalid_tileh_slopes_road[2][15] = { /* The inverse of the mixable RoadBits on a leveled slope */ { - ROAD_NONE, // SLOPE_FLAT - ROAD_NE | ROAD_SE, // SLOPE_W - ROAD_NE | ROAD_NW, // SLOPE_S + {}, // SLOPE_FLAT + {RoadBit::NE, RoadBit::SE}, // SLOPE_W + {RoadBit::NE, RoadBit::NW}, // SLOPE_S - ROAD_NE, // SLOPE_SW - ROAD_NW | ROAD_SW, // SLOPE_E - ROAD_NONE, // SLOPE_EW + RoadBit::NE, // SLOPE_SW + {RoadBit::NW, RoadBit::SW}, // SLOPE_E + {}, // SLOPE_EW - ROAD_NW, // SLOPE_SE - ROAD_NONE, // SLOPE_WSE - ROAD_SE | ROAD_SW, // SLOPE_N + RoadBit::NW, // SLOPE_SE + {}, // SLOPE_WSE + {RoadBit::SE, RoadBit::SW}, // SLOPE_N - ROAD_SE, // SLOPE_NW - ROAD_NONE, // SLOPE_NS - ROAD_NONE, // SLOPE_ENW + RoadBit::SE, // SLOPE_NW + {}, // SLOPE_NS + {}, // SLOPE_ENW - ROAD_SW, // SLOPE_NE - ROAD_NONE, // SLOPE_SEN - ROAD_NONE // SLOPE_NWS + RoadBit::SW, // SLOPE_NE + {}, // SLOPE_SEN + {}, // SLOPE_NWS }, /* The inverse of the allowed straight roads on a slope * (with and without a foundation). */ { - ROAD_NONE, // SLOPE_FLAT - ROAD_NONE, // SLOPE_W Foundation - ROAD_NONE, // SLOPE_S Foundation + {}, // SLOPE_FLAT + {}, // SLOPE_W (Foundation) + {}, // SLOPE_S (Foundation) - ROAD_Y, // SLOPE_SW - ROAD_NONE, // SLOPE_E Foundation - ROAD_ALL, // SLOPE_EW + ROAD_Y, // SLOPE_SW + {}, // SLOPE_E (Foundation) + ROAD_ALL, // SLOPE_EW - ROAD_X, // SLOPE_SE - ROAD_ALL, // SLOPE_WSE - ROAD_NONE, // SLOPE_N Foundation + ROAD_X, // SLOPE_SE + ROAD_ALL, // SLOPE_WSE + {}, // SLOPE_N (Foundation) - ROAD_X, // SLOPE_NW - ROAD_ALL, // SLOPE_NS - ROAD_ALL, // SLOPE_ENW + ROAD_X, // SLOPE_NW + ROAD_ALL, // SLOPE_NS + ROAD_ALL, // SLOPE_ENW - ROAD_Y, // SLOPE_NE - ROAD_ALL, // SLOPE_SEN - ROAD_ALL // SLOPE_NW + ROAD_Y, // SLOPE_NE + ROAD_ALL, // SLOPE_SEN + ROAD_ALL, // SLOPE_NW } }; @@ -254,7 +254,7 @@ static Foundation GetRoadFoundation(Slope tileh, RoadBits bits); */ CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, RoadTramType rtt, DoCommandFlags flags, bool town_check) { - if (_game_mode == GM_EDITOR || remove == ROAD_NONE) return CommandCost(); + if (_game_mode == GM_EDITOR || remove.None()) return CommandCost(); /* Water can always flood and towns can always remove "normal" road pieces. * Towns are not be allowed to remove non "normal" road pieces, like tram @@ -283,17 +283,17 @@ CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, R if (ret.Failed()) return ret; /* Get a bitmask of which neighbouring roads has a tile */ - RoadBits n = ROAD_NONE; + RoadBits n{}; RoadBits present = GetAnyRoadBits(tile, rtt); - if ((present & ROAD_NE) && (GetAnyRoadBits(TileAddXY(tile, -1, 0), rtt) & ROAD_SW)) n |= ROAD_NE; - if ((present & ROAD_SE) && (GetAnyRoadBits(TileAddXY(tile, 0, 1), rtt) & ROAD_NW)) n |= ROAD_SE; - if ((present & ROAD_SW) && (GetAnyRoadBits(TileAddXY(tile, 1, 0), rtt) & ROAD_NE)) n |= ROAD_SW; - if ((present & ROAD_NW) && (GetAnyRoadBits(TileAddXY(tile, 0, -1), rtt) & ROAD_SE)) n |= ROAD_NW; + if (present.Test(RoadBit::NE) && GetAnyRoadBits(TileAddXY(tile, -1, 0), rtt).Test(RoadBit::SW)) n.Set(RoadBit::NE); + if (present.Test(RoadBit::SE) && GetAnyRoadBits(TileAddXY(tile, 0, 1), rtt).Test(RoadBit::NW)) n.Set(RoadBit::SE); + if (present.Test(RoadBit::SW) && GetAnyRoadBits(TileAddXY(tile, 1, 0), rtt).Test(RoadBit::NE)) n.Set(RoadBit::SW); + if (present.Test(RoadBit::NW) && GetAnyRoadBits(TileAddXY(tile, 0, -1), rtt).Test(RoadBit::SE)) n.Set(RoadBit::NW); int rating_decrease = RATING_ROAD_DOWN_STEP_EDGE; /* If 0 or 1 bits are set in n, or if no bits that match the bits to remove, * then allow it */ - if (KillFirstBit(n) != ROAD_NONE && (n & remove) != ROAD_NONE) { + if (n.Count() > 1 && n.Any(remove)) { /* you can remove all kind of roads with extra dynamite */ if (!_settings_game.construction.extra_dynamite) { return CommandCostWithParam(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS, t->index); @@ -317,7 +317,7 @@ CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, R */ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pieces, RoadTramType rtt, bool town_check) { - assert(pieces != ROAD_NONE); + assert(pieces.Any()); RoadType existing_rt = MayHaveRoad(tile) ? GetRoadType(tile, rtt) : INVALID_ROADTYPE; /* The tile doesn't have the given road type */ @@ -359,7 +359,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie CommandCost cost(EXPENSES_CONSTRUCTION); if (IsTileType(tile, TileType::TunnelBridge)) { /* Removing any roadbit in the bridge axis removes the roadtype (that's the behaviour remove-long-roads needs) */ - if ((AxisToRoadBits(DiagDirToAxis(GetTunnelBridgeDirection(tile))) & pieces) == ROAD_NONE) return CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD); + if (!AxisToRoadBits(DiagDirToAxis(GetTunnelBridgeDirection(tile))).Any(pieces)) return CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD); TileIndex other_end = GetOtherTunnelBridgeEnd(tile); /* Pay for *every* tile of the bridge or tunnel */ @@ -419,20 +419,20 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie /* Autocomplete to a straight road * @li if the bits of the other roadtypes result in another foundation * @li if build on slopes is disabled */ - if ((IsStraightRoad(other) && (other & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) != ROAD_NONE) || + if ((IsStraightRoad(other) && other.Any(_invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED])) || (tileh != SLOPE_FLAT && !_settings_game.construction.build_on_slopes)) { pieces |= MirrorRoadBits(pieces); } /* limit the bits to delete to the existing bits. */ pieces &= present; - if (pieces == ROAD_NONE) return CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD); + if (pieces.None()) return CommandCost((rtt == RoadTramType::Tram) ? STR_ERROR_THERE_IS_NO_TRAMWAY : STR_ERROR_THERE_IS_NO_ROAD); /* Now set present what it will be after the remove */ - present ^= pieces; + present.Flip(pieces); /* Check for invalid RoadBit combinations on slopes */ - if (tileh != SLOPE_FLAT && present != ROAD_NONE && + if (tileh != SLOPE_FLAT && present.Any() && (present & _invalid_tileh_slopes_road[0][tileh & SLOPE_ELEVATED]) == present) { return CMD_ERROR; } @@ -448,9 +448,9 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie } } - UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)CountBits(pieces)); + UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -static_cast(pieces.Count())); - if (present == ROAD_NONE) { + if (present.None()) { /* No other road type, just clear tile. */ if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) { /* Includes MarkTileDirtyByTile() */ @@ -462,7 +462,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie SetTownIndex(tile, town == nullptr ? TownID::Invalid() : town->index); } if (rtt == RoadTramType::Road) SetDisallowedRoadDirections(tile, DRD_NONE); - SetRoadBits(tile, ROAD_NONE, rtt); + SetRoadBits(tile, {}, rtt); SetRoadType(tile, rtt, INVALID_ROADTYPE); MarkTileDirtyByTile(tile); } @@ -476,7 +476,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie } } - CommandCost cost(EXPENSES_CONSTRUCTION, CountBits(pieces) * RoadClearCost(existing_rt)); + CommandCost cost(EXPENSES_CONSTRUCTION, pieces.Count() * RoadClearCost(existing_rt)); /* If we build a foundation we have to pay for it. */ if (f == FOUNDATION_NONE && GetRoadFoundation(tileh, present) != FOUNDATION_NONE) cost.AddCost(_price[Price::BuildFoundation]); @@ -484,7 +484,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie } case RoadTileType::Crossing: { - if (pieces & ComplementRoadBits(GetCrossingRoadBits(tile))) { + if (pieces.Any(ComplementRoadBits(GetCrossingRoadBits(tile)))) { return CMD_ERROR; } @@ -538,10 +538,10 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existing, RoadBits other) { /* Remove already build pieces */ - *pieces &= ~existing; + pieces->Reset(existing); /* If we can't build anything stop here */ - if (*pieces == ROAD_NONE) return CMD_ERROR; + if (pieces->None()) return CMD_ERROR; /* All RoadBit combos are valid on flat land */ if (tileh == SLOPE_FLAT) return CommandCost(); @@ -555,10 +555,10 @@ static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existi RoadBits type_bits = existing | *pieces; /* Roads on slopes */ - if (_settings_game.construction.build_on_slopes && (_invalid_tileh_slopes_road[0][tileh] & (other | type_bits)) == ROAD_NONE) { + if (_settings_game.construction.build_on_slopes && !_invalid_tileh_slopes_road[0][tileh].Any(other | type_bits)) { /* If we add leveling we've got to pay for it */ - if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]); + if ((other | existing).None()) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]); return CommandCost(); } @@ -568,8 +568,8 @@ static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existi type_bits = existing | *pieces; /* Uphill roads */ - if (IsStraightRoad(type_bits) && (other == type_bits || other == ROAD_NONE) && - (_invalid_tileh_slopes_road[1][tileh] & (other | type_bits)) == ROAD_NONE) { + if (IsStraightRoad(type_bits) && (other == type_bits || other.None()) && + !_invalid_tileh_slopes_road[1][tileh].Any(other | type_bits)) { /* Slopes with foundation ? */ if (IsSlopeWithOneCornerRaised(tileh)) { @@ -578,12 +578,12 @@ static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existi if (_settings_game.construction.build_on_slopes) { /* If we add foundation we've got to pay for it */ - if ((other | existing) == ROAD_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]); + if ((other | existing).None()) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]); return CommandCost(); } } else { - if (HasExactlyOneBit(existing) && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]); + if (existing.Count() == 1 && GetRoadFoundation(tileh, existing) == FOUNDATION_NONE) return CommandCost(EXPENSES_CONSTRUCTION, _price[Price::BuildFoundation]); return CommandCost(); } } @@ -605,8 +605,8 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, CompanyID company = _current_company; CommandCost cost(EXPENSES_CONSTRUCTION); - RoadBits existing = ROAD_NONE; - RoadBits other_bits = ROAD_NONE; + RoadBits existing{}; + RoadBits other_bits{}; /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero * if a non-company is building the road */ @@ -626,7 +626,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, } /* do not allow building 'zero' road bits, code wouldn't handle it */ - if (pieces == ROAD_NONE || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR; + if (pieces.None() || !IsValidRoadBits(pieces) || !IsValidDisallowedRoadDirections(toggle_drd)) return CMD_ERROR; if (!ValParamRoadType(rt)) return CMD_ERROR; Slope tileh = GetTileSlope(tile); @@ -680,7 +680,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, } /* Disallow breaking end-of-line of someone else * so trams can still reverse on this tile. */ - if (rtt == RoadTramType::Tram && HasExactlyOneBit(existing)) { + if (rtt == RoadTramType::Tram && existing.Count() == 1) { Owner owner = GetRoadOwner(tile, rtt); if (Company::IsValidID(owner)) { CommandCost ret = CheckOwnership(owner); @@ -696,7 +696,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, } other_bits = GetCrossingRoadBits(tile); - if (pieces & ComplementRoadBits(other_bits)) goto do_clear; + if (pieces.Any(ComplementRoadBits(other_bits))) goto do_clear; pieces = other_bits; // we need to pay for both roadbits if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT); @@ -738,12 +738,12 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, Axis roaddir; switch (GetTrackBits(tile)) { case TRACK_BIT_X: - if (pieces & ROAD_X) goto do_clear; + if (pieces.Any(ROAD_X)) goto do_clear; roaddir = AXIS_Y; break; case TRACK_BIT_Y: - if (pieces & ROAD_Y) goto do_clear; + if (pieces.Any(ROAD_Y)) goto do_clear; roaddir = AXIS_X; break; @@ -783,7 +783,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, if (!IsDriveThroughStopTile(tile)) goto do_clear; RoadBits curbits = AxisToRoadBits(GetDriveThroughStopAxis(tile)); - if (pieces & ~curbits) goto do_clear; + if (pieces.Any(ComplementRoadBits(curbits))) goto do_clear; pieces = curbits; // we need to pay for both roadbits if (HasTileRoadType(tile, rtt)) return CommandCost(STR_ERROR_ALREADY_BUILT); @@ -828,7 +828,7 @@ do_clear:; if (!need_to_clear) { if (IsTileType(tile, TileType::Road)) { /* Don't put the pieces that already exist */ - pieces &= ComplementRoadBits(existing); + pieces.Reset(existing); /* Check if new road bits will have the same foundation as other existing road types */ if (IsNormalRoad(tile)) { @@ -837,7 +837,7 @@ do_clear:; RoadBits bits = GetRoadBits(tile, OtherRoadTramType(rtt)); /* do not check if there are not road bits of given type */ - if (bits != ROAD_NONE && GetRoadFoundation(slope, bits) != found_new) { + if (bits.Any() && GetRoadFoundation(slope, bits) != found_new) { return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); } } @@ -869,7 +869,7 @@ do_clear:; /* There are 2 pieces on *every* tile of the bridge or tunnel */ 2 * (GetTunnelBridgeLength(GetOtherTunnelBridgeEnd(tile), tile) + 2) : /* Count pieces */ - CountBits(pieces); + pieces.Count(); cost.AddCost(num_pieces * RoadBuildCost(rt)); @@ -877,7 +877,7 @@ do_clear:; switch (GetTileType(tile)) { case TileType::Road: { RoadTileType rttype = GetRoadTileType(tile); - if (existing == ROAD_NONE || rttype == RoadTileType::Crossing) { + if (existing.None() || rttype == RoadTileType::Crossing) { SetRoadType(tile, rtt, rt); SetRoadOwner(tile, rtt, company); if (rtt == RoadTramType::Road) SetTownIndex(tile, town_id); @@ -949,7 +949,7 @@ static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir) if (!HasPowerOnRoad(existing, rt) && !HasPowerOnRoad(rt, existing)) return false; RoadBits bits = GetAnyRoadBits(tile, rtt, false); - return (bits & DiagDirToRoadBits(ReverseDiagDir(dir))) != 0; + return bits.Any(DiagDirToRoadBits(ReverseDiagDir(dir))); } /** @@ -1090,11 +1090,11 @@ std::tuple CmdRemoveLongRoad(DoCommandFlags flags, TileIndex for (;;) { RoadBits bits = AxisToRoadBits(axis); - if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE; - if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW; + if (tile == end_tile && !end_half) bits &= RoadBits{RoadBit::NW, RoadBit::NE}; + if (tile == start_tile && start_half) bits &= RoadBits{RoadBit::SE, RoadBit::SW}; /* try to remove the halves. */ - if (bits != 0) { + if (bits.Any()) { RoadTramType rtt = GetRoadTramType(rt); CommandCost ret = RemoveRoad(tile, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), bits, rtt, true); if (ret.Succeeded()) { @@ -1226,7 +1226,7 @@ static CommandCost ClearTile_Road(TileIndex tile, DoCommandFlags flags) RoadBits b = GetAllRoadBits(tile); /* Clear the road if only one piece is on the tile OR we are not using the DoCommandFlag::Auto flag */ - if ((HasExactlyOneBit(b) && GetRoadBits(tile, RoadTramType::Tram) == ROAD_NONE) || !flags.Test(DoCommandFlag::Auto)) { + if ((b.Count() == 1 && GetRoadBits(tile, RoadTramType::Tram).None()) || !flags.Test(DoCommandFlag::Auto)) { CommandCost ret(EXPENSES_CONSTRUCTION); for (RoadTramType rtt : ROADTRAMTYPES_ALL) { if (!MayHaveRoad(tile) || GetRoadType(tile, rtt) == INVALID_ROADTYPE) continue; @@ -1289,7 +1289,7 @@ struct DrawRoadTileStruct { static Foundation GetRoadFoundation(Slope tileh, RoadBits bits) { /* Flat land and land without a road doesn't require a foundation */ - if (tileh == SLOPE_FLAT || bits == ROAD_NONE) return FOUNDATION_NONE; + if (tileh == SLOPE_FLAT || bits.None()) return FOUNDATION_NONE; /* Steep slopes behave the same as slopes with one corner raised. */ if (IsSteepSlope(tileh)) { @@ -1297,11 +1297,11 @@ static Foundation GetRoadFoundation(Slope tileh, RoadBits bits) } /* Leveled RoadBits on a slope */ - if ((_invalid_tileh_slopes_road[0][tileh] & bits) == ROAD_NONE) return FOUNDATION_LEVELED; + if (!_invalid_tileh_slopes_road[0][tileh].Any(bits)) return FOUNDATION_LEVELED; /* Straight roads without foundation on a slope */ if (!IsSlopeWithOneCornerRaised(tileh) && - (_invalid_tileh_slopes_road[1][tileh] & bits) == ROAD_NONE) + !_invalid_tileh_slopes_road[1][tileh].Any(bits)) return FOUNDATION_NONE; /* Roads on steep Slopes or on Slopes with one corner raised */ @@ -1338,7 +1338,7 @@ static uint GetRoadSpriteOffset(Slope slope, RoadBits bits) 15, 8, 1, 4, 9, 3, 6, 2 }; - return offsets[bits]; + return offsets[bits.base()]; } } @@ -1373,12 +1373,12 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb) if (height <= GetTileMaxZ(ti->tile) + 1) return; } - if (CountBits(rb) > 2) { + if (rb.Count() > 2) { /* On junctions we check whether neighbouring tiles also have catenary, and possibly * do not draw catenary towards those neighbours, which do not have catenary. */ - RoadBits rb_new = ROAD_NONE; + RoadBits rb_new{}; for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) { - if (rb & DiagDirToRoadBits(dir)) { + if (rb.Any(DiagDirToRoadBits(dir))) { TileIndex neighbour = TileAddByDiagDir(ti->tile, dir); if (MayHaveRoad(neighbour)) { RoadType rt_road = GetRoadTypeRoad(neighbour); @@ -1391,7 +1391,7 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb) } } } - if (CountBits(rb_new) >= 2) rb = rb_new; + if (rb_new.Count() >= 2) rb = rb_new; } const RoadTypeInfo *rti = GetRoadTypeInfo(rt); @@ -1405,8 +1405,8 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb) back = SPR_TRAMWAY_BACK_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1]; front = SPR_TRAMWAY_FRONT_WIRES_SLOPED + _road_sloped_sprites[ti->tileh - 1]; } else { - back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb]; - front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb]; + back = SPR_TRAMWAY_BASE + _road_backpole_sprites_1[rb.base()]; + front = SPR_TRAMWAY_BASE + _road_frontwire_sprites_1[rb.base()]; } /* Catenary uses 1st company colour to help identify owner. @@ -1441,8 +1441,8 @@ void DrawRoadTypeCatenary(const TileInfo *ti, RoadType rt, RoadBits rb) */ void DrawRoadCatenary(const TileInfo *ti) { - RoadBits road = ROAD_NONE; - RoadBits tram = ROAD_NONE; + RoadBits road{}; + RoadBits tram{}; if (IsTileType(ti->tile, TileType::Road)) { if (IsNormalRoad(ti->tile)) { @@ -1615,7 +1615,7 @@ void DrawRoadGroundSprites(const TileInfo *ti, RoadBits road, RoadBits tram, con /* Draw baseset underlay */ PaletteID pal = PAL_NONE; - SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road == ROAD_NONE ? tram_offset : road_offset, snow_or_desert, &pal); + SpriteID image = GetRoadGroundSprite(ti, roadside, road_rti, road.None() ? tram_offset : road_offset, snow_or_desert, &pal); DrawGroundSprite(image, pal); DrawRoadOverlays(ti, pal, road_rti, tram_rti, road_offset, tram_offset); @@ -1662,7 +1662,7 @@ static void DrawRoadBits(TileInfo *ti) if (HasRoadWorks(ti->tile)) { /* Road works */ - DrawGroundSprite((road | tram) & ROAD_X ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE); + DrawGroundSprite((road | tram).Any(ROAD_X) ? SPR_EXCAVATION_X : SPR_EXCAVATION_Y, PAL_NONE); return; } @@ -1684,7 +1684,7 @@ static void DrawRoadBits(TileInfo *ti) } /* If there are no road bits, return, as there is nothing left to do */ - if (HasAtMostOneBit(road)) return; + if (road.Count() <= 1) return; /* Do not draw details when invisible. */ if (roadside == Roadside::Trees && IsInvisibilitySet(TO_TREES)) return; @@ -1700,7 +1700,7 @@ static void DrawRoadBits(TileInfo *ti) } /* Draw extra details. */ - for (const DrawRoadTileStruct *drts = _road_display_table[to_underlying(roadside)][road | tram]; drts->image != 0; drts++) { + for (const DrawRoadTileStruct *drts = _road_display_table[to_underlying(roadside)][(road | tram).base()]; drts->image != 0; drts++) { DrawRoadDetail(drts->image, ti, drts->subcoord_x, drts->subcoord_y, 0x10, is_transparent); } } @@ -1715,10 +1715,10 @@ static void DrawTile_Road(TileInfo *ti) if (IsBridgeAbove(ti->tile)) { RoadBits bits = GetAllRoadBits(ti->tile); - if ((bits & ROAD_NE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNE); - if ((bits & ROAD_SE) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSE); - if ((bits & ROAD_SW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeSW); - if ((bits & ROAD_NW) != 0) blocked_pillars.Set(BridgePillarFlag::EdgeNW); + if (bits.Test(RoadBit::NE)) blocked_pillars.Set(BridgePillarFlag::EdgeNE); + if (bits.Test(RoadBit::SE)) blocked_pillars.Set(BridgePillarFlag::EdgeSE); + if (bits.Test(RoadBit::SW)) blocked_pillars.Set(BridgePillarFlag::EdgeSW); + if (bits.Test(RoadBit::NW)) blocked_pillars.Set(BridgePillarFlag::EdgeNW); } break; @@ -2044,7 +2044,7 @@ static void TileLoop_Road(TileIndex tile) /* Show an animation to indicate road work */ if (t->road_build_months != 0 && (DistanceManhattan(t->xy, tile) < 8 || grp != HouseZone::TownEdge) && - IsNormalRoad(tile) && !HasAtMostOneBit(GetAllRoadBits(tile))) { + IsNormalRoad(tile) && GetAllRoadBits(tile).Count() > 1) { if (std::get<0>(GetFoundationSlope(tile)) == SLOPE_FLAT && EnsureNoVehicleOnGround(tile).Succeeded() && Chance16(1, 40)) { StartRoadWorks(tile); @@ -2086,14 +2086,14 @@ static void TileLoop_Road(TileIndex tile) if (_settings_game.economy.mod_road_rebuild) { /* Generate a nicer town surface */ - const RoadBits old_rb = GetAnyRoadBits(tile, RoadTramType::Road); - const RoadBits new_rb = CleanUpRoadBits(tile, old_rb); + RoadBits old_rb = GetAnyRoadBits(tile, RoadTramType::Road); + RoadBits new_rb = CleanUpRoadBits(tile, old_rb); if (old_rb != new_rb) { - RemoveRoad(tile, {DoCommandFlag::Execute, DoCommandFlag::Auto, DoCommandFlag::NoWater}, (old_rb ^ new_rb), RoadTramType::Road, true); + RemoveRoad(tile, {DoCommandFlag::Execute, DoCommandFlag::Auto, DoCommandFlag::NoWater}, old_rb.Flip(new_rb), RoadTramType::Road, true); /* If new_rb is 0, there are now no road pieces left and the tile is no longer a road tile */ - if (new_rb == 0) { + if (new_rb.None()) { MarkTileDirtyByTile(tile); return; } @@ -2124,20 +2124,20 @@ static bool ClickTile_Road(TileIndex tile) /** Converts %RoadBits to %TrackBits. */ static const TrackBits _road_trackbits[16] = { TRACK_BIT_NONE, // ROAD_NONE - TRACK_BIT_NONE, // ROAD_NW - TRACK_BIT_NONE, // ROAD_SW + TRACK_BIT_NONE, // RoadBit::NW + TRACK_BIT_NONE, // RoadBit::SW TRACK_BIT_LEFT, // ROAD_W - TRACK_BIT_NONE, // ROAD_SE + 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 | ROAD_SW - TRACK_BIT_NONE, // ROAD_NE + 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 | ROAD_NW + 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 | ROAD_NE - TRACK_BIT_RIGHT | TRACK_BIT_LOWER | TRACK_BIT_X, // ROAD_X | ROAD_SE + 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 }; @@ -2160,10 +2160,10 @@ static TrackStatus GetTileTrackStatus_Road(TileIndex tile, TransportType mode, R RoadBits bits = GetRoadBits(tile, rtt); /* no roadbit at this side of tile, return 0 */ - if (side != INVALID_DIAGDIR && (DiagDirToRoadBits(side) & bits) == 0) break; + if (side != INVALID_DIAGDIR && !DiagDirToRoadBits(side).Any(bits)) break; uint multiplier = drd_to_multiplier[(rtt == RoadTramType::Tram) ? DRD_NONE : GetDisallowedRoadDirections(tile)]; - if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits] * multiplier); + if (!HasRoadWorks(tile)) trackdirbits = (TrackdirBits)(_road_trackbits[bits.base()] * multiplier); break; } @@ -2351,7 +2351,7 @@ static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owne RoadType rt = GetRoadType(tile, rtt); if (rt != INVALID_ROADTYPE) { /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */ - uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rtt)); + uint num_bits = IsLevelCrossing(tile) ? 2 : GetRoadBits(tile, rtt).Count(); Company::Get(old_owner)->infrastructure.road[rt] -= num_bits; if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits; } @@ -2392,7 +2392,7 @@ static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int RoadBits bits = GetAllRoadBits(tile); RoadBits bits_copy = bits; /* Check if the slope-road_bits combination is valid at all, i.e. it is safe to call GetRoadFoundation(). */ - if (CheckRoadSlope(tileh_new, &bits_copy, ROAD_NONE, ROAD_NONE).Succeeded()) { + if (CheckRoadSlope(tileh_new, &bits_copy, {}, {}).Succeeded()) { /* CheckRoadSlope() sometimes changes the road_bits, if it does not agree with them. */ if (bits == bits_copy) { auto [tileh_old, z_old] = GetTileSlopeZ(tile); @@ -2552,7 +2552,7 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ } } - uint num_pieces = CountBits(GetAnyRoadBits(tile, rtt)); + uint num_pieces = GetAnyRoadBits(tile, rtt).Count(); if (tt == TileType::Station && IsBayRoadStopTile(tile)) { num_pieces *= ROAD_STOP_TRACKBIT_FACTOR; } else if (tt == TileType::Road && IsRoadDepot(tile)) { diff --git a/src/road_func.h b/src/road_func.h index 6c9c6a8343..d459e2333d 100644 --- a/src/road_func.h +++ b/src/road_func.h @@ -22,7 +22,7 @@ */ inline bool IsValidRoadBits(RoadBits r) { - return r < ROAD_END; + return r.Reset(ROAD_ALL).None(); } /** @@ -37,7 +37,7 @@ inline bool IsValidRoadBits(RoadBits r) inline RoadBits ComplementRoadBits(RoadBits r) { assert(IsValidRoadBits(r)); - return (RoadBits)(ROAD_ALL ^ r); + return r.Flip(ROAD_ALL); } /** @@ -51,7 +51,7 @@ inline RoadBits ComplementRoadBits(RoadBits r) inline RoadBits MirrorRoadBits(RoadBits r) { assert(IsValidRoadBits(r)); - return (RoadBits)(GB(r, 0, 2) << 2 | GB(r, 2, 2)); + return static_cast(GB(r.base(), 0, 2) << 2 | GB(r.base(), 2, 2)); } /** @@ -67,7 +67,7 @@ inline RoadBits RotateRoadBits(RoadBits r, DiagDirDiff rot) { assert(IsValidRoadBits(r)); for (; rot > (DiagDirDiff)0; rot--) { - r = (RoadBits)(GB(r, 0, 1) << 3 | GB(r, 1, 3)); + r = static_cast(GB(r.base(), 0, 1) << 3 | GB(r.base(), 1, 3)); } return r; } @@ -96,7 +96,7 @@ inline bool IsStraightRoad(RoadBits r) inline RoadBits DiagDirToRoadBits(DiagDirection d) { assert(IsValidDiagDirection(d)); - return (RoadBits)(ROAD_NW << (3 ^ d)); + return static_cast(RoadBits{RoadBit::NW}.base() << (3 ^ d)); } /** diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 8cc8a37f2e..1801f15c96 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -169,7 +169,7 @@ void ConnectRoadToStructure(TileIndex tile, DiagDirection direction) tile += TileOffsByDiagDir(direction); /* if there is a roadpiece just outside of the station entrance, build a connecting route */ if (IsNormalRoadTile(tile)) { - if (GetRoadBits(tile, GetRoadTramType(_cur_roadtype)) != ROAD_NONE) { + if (GetRoadBits(tile, GetRoadTramType(_cur_roadtype)).Any()) { Command::Post(tile, DiagDirToRoadBits(ReverseDiagDir(direction)), _cur_roadtype, DRD_NONE, TownID::Invalid()); } } diff --git a/src/road_map.cpp b/src/road_map.cpp index 9c337aa74d..e680d99a46 100644 --- a/src/road_map.cpp +++ b/src/road_map.cpp @@ -53,7 +53,7 @@ bool MayHaveRoad(Tile t) */ RoadBits GetAnyRoadBits(Tile tile, RoadTramType rtt, bool straight_tunnel_bridge_entrance) { - if (!MayHaveRoad(tile) || !HasTileRoadType(tile, rtt)) return ROAD_NONE; + if (!MayHaveRoad(tile) || !HasTileRoadType(tile, rtt)) return {}; switch (GetTileType(tile)) { case TileType::Road: @@ -75,6 +75,6 @@ RoadBits GetAnyRoadBits(Tile tile, RoadTramType rtt, bool straight_tunnel_bridge AxisToRoadBits(DiagDirToAxis(GetTunnelBridgeDirection(tile))) : DiagDirToRoadBits(ReverseDiagDir(GetTunnelBridgeDirection(tile))); - default: return ROAD_NONE; + default: return {}; } } diff --git a/src/road_map.h b/src/road_map.h index a2917013aa..a4aefdf10f 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -138,9 +138,9 @@ inline void SetRoadBits(Tile t, RoadBits r, RoadTramType rtt) { assert(IsNormalRoad(t)); // XXX incomplete if (rtt == RoadTramType::Tram) { - SB(t.m3(), 0, 4, r); + SB(t.m3(), 0, 4, r.base()); } else { - SB(t.m5(), 0, 4, r); + SB(t.m5(), 0, 4, r.base()); } } @@ -648,8 +648,8 @@ inline void MakeRoadNormal(Tile t, RoadBits bits, RoadType road_rt, RoadType tra SetTileType(t, TileType::Road); SetTileOwner(t, road); t.m2() = town.base(); - t.m3() = (tram_rt != INVALID_ROADTYPE ? bits : 0); - t.m5() = (road_rt != INVALID_ROADTYPE ? bits : 0) | to_underlying(RoadTileType::Normal) << 6; + t.m3() = (tram_rt != INVALID_ROADTYPE ? bits.base() : 0); + t.m5() = (road_rt != INVALID_ROADTYPE ? bits.base() : 0) | to_underlying(RoadTileType::Normal) << 6; SB(t.m6(), 2, 6, 0); t.m7() = 0; t.m8() = 0; diff --git a/src/road_type.h b/src/road_type.h index 7a301ac984..caa78d7b14 100644 --- a/src/road_type.h +++ b/src/road_type.h @@ -53,25 +53,25 @@ static constexpr RoadTramTypes ROADTRAMTYPES_ALL{RoadTramType::Road, RoadTramTyp * This enumeration defines the possible road parts which * can be build on a tile. */ -enum RoadBits : uint8_t { - ROAD_NONE = 0U, ///< No road-part is build - ROAD_NW = 1U, ///< North-west part - ROAD_SW = 2U, ///< South-west part - ROAD_SE = 4U, ///< South-east part - ROAD_NE = 8U, ///< North-east part - ROAD_X = ROAD_SW | ROAD_NE, ///< Full road along the x-axis (south-west + north-east) - ROAD_Y = ROAD_NW | ROAD_SE, ///< Full road along the y-axis (north-west + south-east) - - ROAD_N = ROAD_NE | ROAD_NW, ///< Road at the two northern edges - ROAD_E = ROAD_NE | ROAD_SE, ///< Road at the two eastern edges - ROAD_S = ROAD_SE | ROAD_SW, ///< Road at the two southern edges - ROAD_W = ROAD_NW | ROAD_SW, ///< Road at the two western edges - - ROAD_ALL = ROAD_X | ROAD_Y, ///< Full 4-way crossing - - ROAD_END = ROAD_ALL + 1, ///< Out-of-range roadbits, used for iterations +enum class RoadBit : uint8_t { + NW = 0, ///< North-west part + SW = 1, ///< South-west part + SE = 2, ///< South-east part + NE = 3, ///< North-east part }; -DECLARE_ENUM_AS_BIT_SET(RoadBits) + +/** Bitset of \c RoadBit elements. */ +using RoadBits = EnumBitSet; + +static constexpr RoadBits ROAD_X{RoadBit::SW, RoadBit::NE}; ///< Full road along the x-axis (south-west + north-east) +static constexpr RoadBits ROAD_Y{RoadBit::NW, RoadBit::SE}; ///< Full road along the y-axis (north-west + south-east) + +static constexpr RoadBits ROAD_N{RoadBit::NE, RoadBit::NW}; ///< Road at the two northern edges +static constexpr RoadBits ROAD_E{RoadBit::NE, RoadBit::SE}; ///< Road at the two eastern edges +static constexpr RoadBits ROAD_S{RoadBit::SE, RoadBit::SW}; ///< Road at the two southern edges +static constexpr RoadBits ROAD_W{RoadBit::NW, RoadBit::SW}; ///< Road at the two western edges + +static constexpr RoadBits ROAD_ALL{RoadBit::NW, RoadBit::SW, RoadBit::SE, RoadBit::NE}; ///< Full 4-way crossing /** Which directions are disallowed ? */ enum DisallowedRoadDirections : uint8_t { diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 0424c6b76f..8d3786c87f 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -950,8 +950,8 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection * trackbits or when it is a valid turning tile (i.e. one roadbit) */ RoadBits rb = GetAnyRoadBits(tile, RoadTramType::Tram); RoadBits straight = AxisToRoadBits(DiagDirToAxis(enterdir)); - reverse = ((rb & straight) == straight) || - (rb == DiagDirToRoadBits(enterdir)); + reverse = rb.All(straight) || + rb == DiagDirToRoadBits(enterdir); } if (reverse) { v->reverse_ctr = 0; @@ -1114,12 +1114,18 @@ static Trackdir FollowPreviousRoadVehicle(const RoadVehicle *v, const RoadVehicl /* Do some sanity checking. */ static const RoadBits required_roadbits[] = { - ROAD_X, ROAD_Y, ROAD_NW | ROAD_NE, ROAD_SW | ROAD_SE, - ROAD_NW | ROAD_SW, ROAD_NE | ROAD_SE, ROAD_X, ROAD_Y + ROAD_X, + ROAD_Y, + {RoadBit::NW, RoadBit::NE}, + {RoadBit::SW, RoadBit::SE}, + {RoadBit::NW, RoadBit::SW}, + {RoadBit::NE, RoadBit::SE}, + ROAD_X, + ROAD_Y, }; RoadBits required = required_roadbits[dir & 0x07]; - if ((required & GetAnyRoadBits(tile, GetRoadTramType(v->roadtype), true)) == ROAD_NONE) { + if (!required.Any(GetAnyRoadBits(tile, GetRoadTramType(v->roadtype), true))) { dir = INVALID_TRACKDIR; } @@ -1232,18 +1238,18 @@ again: if (RoadTypeIsTram(v->roadtype)) { /* Determine the road bits the tram needs to be able to turn around * using the 'big' corner loop. */ - RoadBits needed; + RoadBit needed; switch (dir) { default: NOT_REACHED(); - case TRACKDIR_RVREV_NE: needed = ROAD_SW; break; - case TRACKDIR_RVREV_SE: needed = ROAD_NW; break; - case TRACKDIR_RVREV_SW: needed = ROAD_NE; break; - case TRACKDIR_RVREV_NW: needed = ROAD_SE; break; + case TRACKDIR_RVREV_NE: needed = RoadBit::SW; break; + case TRACKDIR_RVREV_SE: needed = RoadBit::NW; break; + case TRACKDIR_RVREV_SW: needed = RoadBit::NE; break; + case TRACKDIR_RVREV_NW: needed = RoadBit::SE; break; } if ((v->Previous() != nullptr && v->Previous()->tile == tile) || (v->IsFrontEngine() && IsNormalRoadTile(tile) && !HasRoadWorks(tile) && HasTileAnyRoadType(tile, v->compatible_roadtypes) && - (needed & GetRoadBits(tile, RoadTramType::Tram)) != ROAD_NONE)) { + GetRoadBits(tile, RoadTramType::Tram).Test(needed))) { /* * Taking the 'big' corner for trams only happens when: * - The previous vehicle in this (articulated) tram chain is @@ -1254,7 +1260,7 @@ again: * going to cause the tram to split up. * - Or the front of the tram can drive over the next tile. */ - } else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || ((~needed & GetAnyRoadBits(v->tile, RoadTramType::Tram, false)) == ROAD_NONE)) { + } else if (!v->IsFrontEngine() || !CanBuildTramTrackOnTile(v->owner, tile, v->roadtype, needed) || GetAnyRoadBits(v->tile, RoadTramType::Tram, false).Reset(needed).Any()) { /* * Taking the 'small' corner for trams only happens when: * - We are not the from vehicle of an articulated tram. @@ -1365,7 +1371,7 @@ again: Trackdir dir; uint turn_around_start_frame = RVC_TURN_AROUND_START_FRAME; - if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && HasExactlyOneBit(GetAnyRoadBits(v->tile, RoadTramType::Tram, true))) { + if (RoadTypeIsTram(v->roadtype) && !IsRoadDepotTile(v->tile) && GetAnyRoadBits(v->tile, RoadTramType::Tram, true).Count() == 1) { /* * The tram is turning around with one tram 'roadbit'. This means that * it is using the 'big' corner 'drive data'. However, to support the diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index f9d2c82a50..45eabcf1f8 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -457,8 +457,8 @@ static void FixOwnerOfRailTrack(Tile t) /* MakeRoadNormal */ SetTileType(t, TileType::Road); SetTileOwner(t, road); - t.m3() = (hasroad ? bits : 0); - t.m5() = (hastram ? bits : 0) | to_underlying(RoadTileType::Normal) << 6; + t.m3() = (hasroad ? bits.base() : 0); + t.m5() = (hastram ? bits.base() : 0) | to_underlying(RoadTileType::Normal) << 6; SB(t.m6(), 2, 4, 0); SetRoadOwner(t, RoadTramType::Tram, tram); return; @@ -1245,7 +1245,7 @@ bool AfterLoadGame() SetTileType(t, TileType::Road); t.m2() = town.base(); t.m3() = 0; - t.m5() = (axis == AXIS_X ? ROAD_Y : ROAD_X) | to_underlying(RoadTileType::Normal) << 6; + t.m5() = (axis == AXIS_X ? ROAD_Y : ROAD_X).base() | to_underlying(RoadTileType::Normal) << 6; SB(t.m6(), 2, 4, 0); t.m7() = 1 << 6; SetRoadOwner(t, RoadTramType::Tram, OWNER_NONE); diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index d5f025ff4b..5c5d0fb560 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -165,7 +165,7 @@ void AfterLoadCompanyStats() if (rt == INVALID_ROADTYPE) continue; c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rtt)); /* A level crossings and depots have two road bits. */ - if (c != nullptr) c->infrastructure.road[rt] += IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rtt)) : 2; + if (c != nullptr) c->infrastructure.road[rt] += IsNormalRoad(tile) ? GetRoadBits(tile, rtt).Count() : 2; } break; } diff --git a/src/script/api/script_road.cpp b/src/script/api/script_road.cpp index 862f1e08b6..75865579a9 100644 --- a/src/script/api/script_road.cpp +++ b/src/script/api/script_road.cpp @@ -117,12 +117,12 @@ RoadBits r1 = ::GetAnyRoadBits(t1, rtt); // TODO RoadBits r2 = ::GetAnyRoadBits(t2, rtt); // TODO - uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3); - uint dir_2 = 2 ^ dir_1; + RoadBit dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? RoadBit::SE : RoadBit::NW) : (::TileX(t1) < ::TileX(t2) ? RoadBit::SW : RoadBit::NE); + RoadBit dir_2 = static_cast(2 ^ to_underlying(dir_1)); DisallowedRoadDirections drd2 = IsNormalRoadTile(t2) ? GetDisallowedRoadDirections(t2) : DRD_NONE; - return HasBit(r1, dir_1) && HasBit(r2, dir_2) && drd2 != DRD_BOTH && drd2 != (dir_1 > dir_2 ? DRD_SOUTHBOUND : DRD_NORTHBOUND); + return r1.Test(dir_1) && r2.Test(dir_2) && drd2 != DRD_BOTH && drd2 != (dir_1 > dir_2 ? DRD_SOUTHBOUND : DRD_NORTHBOUND); } /* static */ bool ScriptRoad::ConvertRoadType(TileIndex start_tile, TileIndex end_tile, RoadType road_type) @@ -241,10 +241,10 @@ static RoadPartOrientation RotateNeighbour(RoadPartOrientation neighbour) static RoadBits NeighbourToRoadBits(RoadPartOrientation neighbour) { switch (neighbour) { - case RoadPartOrientation::NW: return ROAD_NW; - case RoadPartOrientation::NE: return ROAD_NE; - case RoadPartOrientation::SE: return ROAD_SE; - case RoadPartOrientation::SW: return ROAD_SW; + case RoadPartOrientation::NW: return RoadBit::NW; + case RoadPartOrientation::NE: return RoadBit::NE; + case RoadPartOrientation::SE: return RoadBit::SE; + case RoadPartOrientation::SW: return RoadBit::SW; default: NOT_REACHED(); } } @@ -314,9 +314,9 @@ static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array ToRoadPartOrientation(const TileIndex if (::DistanceManhattan(tile, start) != 1 || ::DistanceManhattan(tile, end) != 1) return -1; const TileIndex neighbours[] = { - ScriptMap::GetTileIndex(0, -1), // ROAD_NW - ScriptMap::GetTileIndex(1, 0), // ROAD_SW - ScriptMap::GetTileIndex(0, 1), // ROAD_SE - ScriptMap::GetTileIndex(-1, 0), // ROAD_NE + ScriptMap::GetTileIndex(0, -1), // RoadBit::NW + ScriptMap::GetTileIndex(1, 0), // RoadBit::SW + ScriptMap::GetTileIndex(0, 1), // RoadBit::SE + ScriptMap::GetTileIndex(-1, 0), // RoadBit::NE }; - ::RoadBits rb = ::ROAD_NONE; + ::RoadBits rb{}; if (::IsNormalRoadTile(tile)) { rb = ::GetAllRoadBits(tile); } else { @@ -446,8 +446,8 @@ static std::optional ToRoadPartOrientation(const TileIndex } Array existing; - for (uint i = 0; i < lengthof(neighbours); i++) { - if (HasBit(rb, i)) existing.emplace_back(neighbours[i]); + for (RoadBit roadbit : rb) { + existing.emplace_back(neighbours[to_underlying(roadbit)]); } return ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::GetSlope(tile), std::move(existing), start - tile, end - tile); diff --git a/src/script/api/script_tile.cpp b/src/script/api/script_tile.cpp index 19d8c26109..90f9ad9863 100644 --- a/src/script/api/script_tile.cpp +++ b/src/script/api/script_tile.cpp @@ -38,7 +38,7 @@ if (::GetRoadTypeTram(tile) != INVALID_ROADTYPE) return false; /* Depots and crossings aren't considered buildable */ if (::GetRoadTileType(tile) != RoadTileType::Normal) return false; - if (!HasExactlyOneBit(::GetRoadBits(tile, RoadTramType::Road))) return false; + if (::GetRoadBits(tile, RoadTramType::Road).Count() != 1) return false; if (::IsRoadOwner(tile, RoadTramType::Road, OWNER_TOWN)) return true; if (::IsRoadOwner(tile, RoadTramType::Road, ScriptObject::GetCompany())) return true; return false; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 597c536398..fd958de605 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1127,10 +1127,10 @@ static CommandCost CheckFlatLandRoadStop(TileIndex cur_tile, int &allowed_z, con } else { bool build_over_road = is_drive_through && IsNormalRoadTile(cur_tile); /* Road bits in the wrong direction. */ - RoadBits rb = IsNormalRoadTile(cur_tile) ? GetAllRoadBits(cur_tile) : ROAD_NONE; - if (build_over_road && (rb & (axis == AXIS_X ? ROAD_Y : ROAD_X)) != 0) { + RoadBits rb = IsNormalRoadTile(cur_tile) ? GetAllRoadBits(cur_tile) : RoadBits{}; + if (build_over_road && rb.Any(axis == AXIS_X ? ROAD_Y : ROAD_X)) { /* Someone was pedantic and *NEEDED* three fracking different error messages. */ - switch (CountBits(rb)) { + switch (rb.Count()) { case 1: return CommandCost(STR_ERROR_DRIVE_THROUGH_DIRECTION); @@ -1154,7 +1154,7 @@ static CommandCost CheckFlatLandRoadStop(TileIndex cur_tile, int &allowed_z, con ret = CheckOwnership(road_owner); if (ret.Failed()) return ret; } - uint num_pieces = CountBits(GetRoadBits(cur_tile, RoadTramType::Road)); + uint num_pieces = GetRoadBits(cur_tile, RoadTramType::Road).Count(); if (rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return CommandCost(STR_ERROR_NO_SUITABLE_ROAD); @@ -1176,11 +1176,11 @@ static CommandCost CheckFlatLandRoadStop(TileIndex cur_tile, int &allowed_z, con (!_settings_game.construction.road_stop_on_competitor_road || /* Disallow breaking end-of-line of someone else * so trams can still reverse on this tile. */ - HasExactlyOneBit(GetRoadBits(cur_tile, RoadTramType::Tram)))) { + GetRoadBits(cur_tile, RoadTramType::Tram).Count() == 1)) { ret = CheckOwnership(tram_owner); if (ret.Failed()) return ret; } - uint num_pieces = CountBits(GetRoadBits(cur_tile, RoadTramType::Tram)); + uint num_pieces = GetRoadBits(cur_tile, RoadTramType::Tram).Count(); if (rt != INVALID_ROADTYPE && RoadTypeIsTram(rt) && !HasPowerOnRoad(rt, tram_rt)) return CommandCost(STR_ERROR_NO_SUITABLE_ROAD); @@ -2206,8 +2206,8 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width /* Update company infrastructure counts. If the current tile is a normal road tile, remove the old * bits first. */ if (IsNormalRoadTile(cur_tile)) { - UpdateCompanyRoadInfrastructure(road_rt, road_owner, -(int)CountBits(GetRoadBits(cur_tile, RoadTramType::Road))); - UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RoadTramType::Tram))); + UpdateCompanyRoadInfrastructure(road_rt, road_owner, -static_cast(GetRoadBits(cur_tile, RoadTramType::Road).Count())); + UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -static_cast(GetRoadBits(cur_tile, RoadTramType::Tram).Count())); } if (road_rt == INVALID_ROADTYPE && RoadTypeIsRoad(rt)) road_rt = rt; @@ -2450,7 +2450,7 @@ static CommandCost RemoveGenericRoadStop(DoCommandFlags flags, const TileArea &r if (!IsTileType(cur_tile, TileType::Station) || !IsAnyRoadStop(cur_tile) || IsRoadWaypoint(cur_tile) != road_waypoint) continue; /* Save information on to-be-restored roads before the stop is removed. */ - RoadBits road_bits = ROAD_NONE; + RoadBits road_bits{}; EnumClassIndexContainer, RoadTramType> road_type{INVALID_ROADTYPE, INVALID_ROADTYPE}; EnumClassIndexContainer, RoadTramType> road_owner{OWNER_NONE, OWNER_NONE}; if (IsDriveThroughStopTile(cur_tile)) { @@ -2483,7 +2483,7 @@ static CommandCost RemoveGenericRoadStop(DoCommandFlags flags, const TileArea &r road_owner[RoadTramType::Road], road_owner[RoadTramType::Tram]); /* Update company infrastructure counts. */ - int count = CountBits(road_bits); + int count = road_bits.Count(); UpdateCompanyRoadInfrastructure(road_type[RoadTramType::Road], road_owner[RoadTramType::Road], count); UpdateCompanyRoadInfrastructure(road_type[RoadTramType::Tram], road_owner[RoadTramType::Tram], count); } @@ -3409,8 +3409,8 @@ static void DrawTile_Station(TileInfo *ti) RoadBits bits = AxisToRoadBits(GetDriveThroughStopAxis(ti->tile)); RoadType road_rt = GetRoadTypeRoad(ti->tile); RoadType tram_rt = GetRoadTypeTram(ti->tile); - RoadBits road = (road_rt != INVALID_ROADTYPE) ? bits : ROAD_NONE; - RoadBits tram = (tram_rt != INVALID_ROADTYPE) ? bits : ROAD_NONE; + RoadBits road = (road_rt != INVALID_ROADTYPE) ? bits : RoadBits{}; + RoadBits tram = (tram_rt != INVALID_ROADTYPE) ? bits : RoadBits{}; const RoadTypeInfo *road_rti = (road_rt != INVALID_ROADTYPE) ? GetRoadTypeInfo(road_rt) : nullptr; const RoadTypeInfo *tram_rti = (tram_rt != INVALID_ROADTYPE) ? GetRoadTypeInfo(tram_rt) : nullptr; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index fdeb77f114..1a754eedde 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -924,7 +924,7 @@ void OnTick_Town() */ static RoadBits GetTownRoadBits(TileIndex tile) { - if (IsRoadDepotTile(tile) || IsBayRoadStopTile(tile)) return ROAD_NONE; + if (IsRoadDepotTile(tile) || IsBayRoadStopTile(tile)) return {}; return GetAnyRoadBits(tile, RoadTramType::Road, true); } @@ -1033,7 +1033,7 @@ static bool IsNeighbourRoadTile(TileIndex tile, const DiagDirection dir, uint di /* Test for roadbit parallel to dir and facing towards the middle axis */ if (IsValidTile(tile + cur) && - GetTownRoadBits(TileAdd(tile, cur)) & DiagDirToRoadBits((pos & 2) ? dir : ReverseDiagDir(dir))) return true; + GetTownRoadBits(TileAdd(tile, cur)).Any(DiagDirToRoadBits((pos & 2) ? dir : ReverseDiagDir(dir)))) return true; } return false; } @@ -1054,7 +1054,7 @@ static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir) if (IsBridgeAbove(tile) && GetBridgeAxis(tile) == DiagDirToAxis(dir)) return false; /* Check if there already is a road at this point? */ - if (GetTownRoadBits(tile) == ROAD_NONE) { + if (GetTownRoadBits(tile).None()) { /* No, try if we are able to build a road piece there. * If that fails clear the land, and if that fails exit. * This is to make sure that we can build a road here later. */ @@ -1127,7 +1127,7 @@ static RoadBits GetTownRoadGridElement(Town *t, TileIndex tile, DiagDirection di { /* align the grid to the downtown */ TileIndexDiffC grid_pos = TileIndexToTileIndexDiffC(t->xy, tile); // Vector from downtown to the tile - RoadBits rcmd = ROAD_NONE; + RoadBits rcmd{}; switch (t->layout) { default: NOT_REACHED(); @@ -1150,24 +1150,24 @@ static RoadBits GetTownRoadGridElement(Town *t, TileIndex tile, DiagDirection di switch (GetTileSlope(tile)) { default: rb_template = ROAD_ALL; break; - case SLOPE_W: rb_template = ROAD_NW | ROAD_SW; break; - case SLOPE_SW: rb_template = ROAD_Y | ROAD_SW; break; - case SLOPE_S: rb_template = ROAD_SW | ROAD_SE; break; - case SLOPE_SE: rb_template = ROAD_X | ROAD_SE; break; - case SLOPE_E: rb_template = ROAD_SE | ROAD_NE; break; - case SLOPE_NE: rb_template = ROAD_Y | ROAD_NE; break; - case SLOPE_N: rb_template = ROAD_NE | ROAD_NW; break; - case SLOPE_NW: rb_template = ROAD_X | ROAD_NW; break; + case SLOPE_W: rb_template = {RoadBit::NW, RoadBit::SW}; break; + case SLOPE_SW: rb_template = ROAD_Y | RoadBit::SW; break; + case SLOPE_S: rb_template = {RoadBit::SW, RoadBit::SE}; break; + case SLOPE_SE: rb_template = ROAD_X | RoadBit::SE; break; + case SLOPE_E: rb_template = {RoadBit::SE, RoadBit::NE}; break; + case SLOPE_NE: rb_template = ROAD_Y | RoadBit::NE; break; + case SLOPE_N: rb_template = {RoadBit::NE, RoadBit::NW}; break; + case SLOPE_NW: rb_template = ROAD_X | RoadBit::NW; break; case SLOPE_STEEP_W: case SLOPE_STEEP_S: case SLOPE_STEEP_E: case SLOPE_STEEP_N: - rb_template = ROAD_NONE; + rb_template = {}; break; } /* Stop if the template is compatible to the growth dir */ - if (DiagDirToRoadBits(ReverseDiagDir(dir)) & rb_template) return rb_template; + if (DiagDirToRoadBits(ReverseDiagDir(dir)).Any(rb_template)) return rb_template; /* If not generate a straight road in the direction of the growth */ return DiagDirToRoadBits(dir) | DiagDirToRoadBits(ReverseDiagDir(dir)); } @@ -1294,7 +1294,7 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi if (slope != SLOPE_FLAT && slope & InclinedSlope(bridge_dir)) return false; /* Assure that the bridge is connectable to the start side */ - if (!(GetTownRoadBits(TileAddByDiagDir(tile, ReverseDiagDir(bridge_dir))) & DiagDirToRoadBits(bridge_dir))) return false; + if (!GetTownRoadBits(TileAddByDiagDir(tile, ReverseDiagDir(bridge_dir))).Any(DiagDirToRoadBits(bridge_dir))) return false; /* We are in the right direction */ uint bridge_length = 0; // This value stores the length of the possible bridge @@ -1381,7 +1381,7 @@ static bool GrowTownWithTunnel(const Town *t, const TileIndex tile, const DiagDi if (slope != InclinedSlope(tunnel_dir)) return false; /* Assure that the tunnel is connectable to the start side */ - if (!(GetTownRoadBits(TileAddByDiagDir(tile, ReverseDiagDir(tunnel_dir))) & DiagDirToRoadBits(tunnel_dir))) return false; + if (!GetTownRoadBits(TileAddByDiagDir(tile, ReverseDiagDir(tunnel_dir))).Any(DiagDirToRoadBits(tunnel_dir))) return false; const TileIndexDiff delta = TileOffsByDiagDir(tunnel_dir); int max_tunnel_length = 0; @@ -1509,12 +1509,12 @@ enum class TownGrowthResult { */ static TownGrowthResult GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, DiagDirection target_dir, Town *t1, TownExpandModes modes) { - RoadBits rcmd = ROAD_NONE; // RoadBits for the road construction command + RoadBits rcmd{}; // RoadBits for the road construction command TileIndex tile = *tile_ptr; // The main tile on which we base our growth assert(tile < Map::Size()); - if (cur_rb == ROAD_NONE) { + if (cur_rb.None()) { /* Tile has no road. * We will return TownGrowthResult::SearchStopped to say that this is the last iteration. */ @@ -1531,7 +1531,7 @@ static TownGrowthResult GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, Dia case TL_3X3_GRID: case TL_2X2_GRID: rcmd = GetTownRoadGridElement(t1, tile, target_dir); - if (rcmd == ROAD_NONE) return TownGrowthResult::SearchStopped; + if (rcmd.None()) return TownGrowthResult::SearchStopped; break; case TL_BETTER_ROADS: @@ -1564,7 +1564,7 @@ static TownGrowthResult GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, Dia break; } - } else if (target_dir < DIAGDIR_END && !(cur_rb & DiagDirToRoadBits(ReverseDiagDir(target_dir)))) { + } else if (target_dir < DIAGDIR_END && !cur_rb.Any(DiagDirToRoadBits(ReverseDiagDir(target_dir)))) { if (!TownCanGrowRoad(tile)) return TownGrowthResult::Continue; if (!TownAllowedToBuildRoads(modes)) return TownGrowthResult::SearchStopped; @@ -1603,7 +1603,7 @@ static TownGrowthResult GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, Dia RoadBits target_rb = DiagDirToRoadBits(target_dir); TileIndex house_tile; // position of a possible house - if (cur_rb & target_rb) { + if (cur_rb.Any(target_rb)) { /* If it's a road turn possibly build a house in a corner. * Use intersection with straight road as an indicator * that we randomised corner house position. @@ -1615,17 +1615,17 @@ static TownGrowthResult GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, Dia /* Check whether it is a turn and if so determine * position of the corner tile */ - switch (cur_rb) { - case ROAD_N: + switch (cur_rb.base()) { + case ROAD_N.base(): house_tile = TileAddByDir(tile, DIR_S); break; - case ROAD_S: + case ROAD_S.base(): house_tile = TileAddByDir(tile, DIR_N); break; - case ROAD_E: + case ROAD_E.base(): house_tile = TileAddByDir(tile, DIR_W); break; - case ROAD_W: + case ROAD_W.base(): house_tile = TileAddByDir(tile, DIR_E); break; default: @@ -1655,7 +1655,7 @@ static TownGrowthResult GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, Dia case TL_2X2_GRID: rcmd = GetTownRoadGridElement(t1, tile, target_dir); - allow_house = (rcmd & target_rb) == ROAD_NONE; + allow_house = !rcmd.Any(target_rb); break; case TL_BETTER_ROADS: // Use original afterwards! @@ -1698,7 +1698,7 @@ static TownGrowthResult GrowTownInTile(TileIndex *tile_ptr, RoadBits cur_rb, Dia /* Make the roads look nicer */ rcmd = CleanUpRoadBits(tile, rcmd); - if (rcmd == ROAD_NONE) return TownGrowthResult::SearchStopped; + if (rcmd.None()) return TownGrowthResult::SearchStopped; /* Only use the target direction for bridges and tunnels to ensure they're connected. * The target_dir is as computed previously according to town layout, so @@ -1735,7 +1735,7 @@ static bool CanFollowRoad(TileIndex tile, DiagDirection dir, TownExpandModes mod /* Check whether a road connection exists or can be build. */ switch (GetTileType(target_tile)) { case TileType::Road: - return target_rb != ROAD_NONE; + return target_rb.Any(); case TileType::Station: return IsDriveThroughStopTile(target_tile); @@ -1756,7 +1756,7 @@ static bool CanFollowRoad(TileIndex tile, DiagDirection dir, TownExpandModes mod /* Check whether a road connection already exists, * and it leads somewhere else. */ RoadBits back_rb = DiagDirToRoadBits(ReverseDiagDir(dir)); - return (target_rb & back_rb) != 0 && (target_rb & ~back_rb) != 0; + return target_rb.Any(back_rb) && target_rb.Reset(back_rb).Any(); } } @@ -1811,8 +1811,8 @@ static bool GrowTownAtRoad(Town *t, TileIndex tile, TownExpandModes modes) /* Exclude the source position from the bitmask * and return if no more road blocks available */ - if (IsValidDiagDirection(target_dir)) cur_rb &= ~DiagDirToRoadBits(ReverseDiagDir(target_dir)); - if (cur_rb == ROAD_NONE) return false; + if (IsValidDiagDirection(target_dir)) cur_rb.Reset(DiagDirToRoadBits(ReverseDiagDir(target_dir))); + if (cur_rb.None()) return false; if (IsTileType(tile, TileType::TunnelBridge)) { /* Only build in the direction away from the tunnel or bridge. */ @@ -1821,13 +1821,13 @@ static bool GrowTownAtRoad(Town *t, TileIndex tile, TownExpandModes modes) /* Select a random bit from the blockmask, walk a step * and continue the search from there. */ do { - if (cur_rb == ROAD_NONE) return false; + if (cur_rb.None()) return false; RoadBits target_bits; do { target_dir = RandomDiagDir(); target_bits = DiagDirToRoadBits(target_dir); - } while (!(cur_rb & target_bits)); - cur_rb &= ~target_bits; + } while (!cur_rb.Any(target_bits)); + cur_rb.Reset(target_bits); } while (!CanFollowRoad(tile, target_dir, modes)); } tile = TileAddByDiagDir(tile, target_dir); @@ -1863,7 +1863,7 @@ static RoadBits GenRandomRoadBits() uint a = GB(r, 0, 2); uint b = GB(r, 8, 2); if (a == b) b ^= 2; - return (RoadBits)((ROAD_NW << a) + (ROAD_NW << b)); + return static_cast((RoadBits{RoadBit::NW}.base() << a) + (RoadBits{RoadBit::NW}.base() << b)); } /** @@ -1897,7 +1897,7 @@ static bool GrowTown(Town *t, TownExpandModes modes) /* Find a road that we can base the construction on. */ for (const auto &ptr : _town_coord_mod) { - if (GetTownRoadBits(tile) != ROAD_NONE) { + if (GetTownRoadBits(tile).Any()) { bool success = GrowTownAtRoad(t, tile, modes); cur_company.Restore(); return success; diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 3c970383eb..64849d0054 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -135,8 +135,8 @@ Axis GetAxisForNewRoadWaypoint(TileIndex tile) RoadBits bits = GetAllRoadBits(tile); - if ((bits & ROAD_Y) == 0) return AXIS_X; - if ((bits & ROAD_X) == 0) return AXIS_Y; + if (!bits.Any(ROAD_Y)) return AXIS_X; + if (!bits.Any(ROAD_X)) return AXIS_Y; return INVALID_AXIS; } @@ -447,8 +447,8 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi /* Update company infrastructure counts. If the current tile is a normal road tile, remove the old * bits first. */ if (IsNormalRoadTile(cur_tile)) { - UpdateCompanyRoadInfrastructure(road_rt, road_owner, -(int)CountBits(GetRoadBits(cur_tile, RoadTramType::Road))); - UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RoadTramType::Tram))); + UpdateCompanyRoadInfrastructure(road_rt, road_owner, -static_cast(GetRoadBits(cur_tile, RoadTramType::Road).Count())); + UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -static_cast(GetRoadBits(cur_tile, RoadTramType::Tram).Count())); } UpdateCompanyRoadInfrastructure(road_rt, road_owner, ROAD_STOP_TRACKBIT_FACTOR);