Codechange: make RoadBits an EnumBitSet (#15476)

This commit is contained in:
Peter Nelson
2026-04-13 21:23:17 +01:00
committed by GitHub
parent a5a60c8615
commit b33b0d92a0
18 changed files with 268 additions and 262 deletions
+5 -5
View File
@@ -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;
}
}
+5 -5
View File
@@ -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;
+5 -5
View File
@@ -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));
}
+4 -4
View File
@@ -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);
}
}
+111 -111
View File
@@ -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<int>(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<CommandCost, Money> 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)) {
+5 -5
View File
@@ -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<RoadBits>(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<RoadBits>(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>(RoadBits{RoadBit::NW}.base() << (3 ^ d));
}
/**
+1 -1
View File
@@ -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<Commands::BuildRoad>::Post(tile, DiagDirToRoadBits(ReverseDiagDir(direction)), _cur_roadtype, DRD_NONE, TownID::Invalid());
}
}
+2 -2
View File
@@ -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 {};
}
}
+4 -4
View File
@@ -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;
+18 -18
View File
@@ -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<RoadBit, uint8_t>;
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 {
+19 -13
View File
@@ -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
+3 -3
View File
@@ -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);
+1 -1
View File
@@ -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;
}
+31 -31
View File
@@ -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<RoadBit>(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<RoadPartOrient
}
/* Create roadbits out of the data for easier handling. */
RoadBits start_roadbits = NeighbourToRoadBits(start);
RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end);
RoadBits existing_roadbits = ROAD_NONE;
RoadBits start_roadbits = NeighbourToRoadBits(start);
RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end);
RoadBits existing_roadbits{};
for (RoadPartOrientation neighbour : existing) {
for (int j = 0; j < base_rotate; j++) {
neighbour = RotateNeighbour(neighbour);
@@ -327,15 +327,15 @@ static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<RoadPartOrient
switch (slope) {
case SLOPE_W:
/* A slope similar to a SLOPE_W. */
switch (new_roadbits) {
case ROAD_N:
case ROAD_E:
case ROAD_S:
switch (new_roadbits.base()) {
case ROAD_N.base():
case ROAD_E.base():
case ROAD_S.base():
/* Cannot build anything with a turn from the low side. */
return 0;
case ROAD_X:
case ROAD_Y:
case ROAD_X.base():
case ROAD_Y.base():
/* A 'sloped' tile is going to be build. */
if ((existing_roadbits | new_roadbits) != new_roadbits) {
/* There is already a foundation on the tile, or at least
@@ -344,25 +344,25 @@ static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<RoadPartOrient
}
/* If the start is in the low part, it is automatically
* building the second part too. */
return ((start_roadbits & ROAD_E) && !(existing_roadbits & ROAD_W)) ? 2 : 1;
return (start_roadbits.Any(ROAD_E) && !existing_roadbits.Any(ROAD_W)) ? 2 : 1;
default:
/* Roadbits causing a foundation are going to be build.
* When the existing roadbits are slopes (the lower bits
* are used), this cannot be done. */
if ((existing_roadbits | new_roadbits) == new_roadbits) return 1;
return (existing_roadbits & ROAD_E) ? 0 : 1;
return existing_roadbits.Any(ROAD_E) ? 0 : 1;
}
case SLOPE_SW:
/* A slope similar to a SLOPE_SW. */
switch (new_roadbits) {
case ROAD_N:
case ROAD_E:
switch (new_roadbits.base()) {
case ROAD_N.base():
case ROAD_E.base():
/* Cannot build anything with a turn from the low side. */
return 0;
case ROAD_X:
case ROAD_X.base():
/* A 'sloped' tile is going to be build. */
if ((existing_roadbits | new_roadbits) != new_roadbits) {
/* There is already a foundation on the tile, or at least
@@ -371,13 +371,13 @@ static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<RoadPartOrient
}
/* If the start is in the low part, it is automatically
* building the second part too. */
return ((start_roadbits & ROAD_NE) && !(existing_roadbits & ROAD_SW)) ? 2 : 1;
return (start_roadbits.Test(RoadBit::NE) && !existing_roadbits.Test(RoadBit::SW)) ? 2 : 1;
default:
/* Roadbits causing a foundation are going to be build.
* When the existing roadbits are slopes (the lower bits
* are used), this cannot be done. */
return (existing_roadbits & ROAD_NE) ? 0 : 1;
return existing_roadbits.Test(RoadBit::NE) ? 0 : 1;
}
default:
@@ -432,13 +432,13 @@ static std::optional<RoadPartOrientation> 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<RoadPartOrientation> ToRoadPartOrientation(const TileIndex
}
Array<TileIndex> 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);
+1 -1
View File
@@ -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;
+12 -12
View File
@@ -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<int>(GetRoadBits(cur_tile, RoadTramType::Road).Count()));
UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -static_cast<int>(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<std::array<RoadType, to_underlying(RoadTramType::End)>, RoadTramType> road_type{INVALID_ROADTYPE, INVALID_ROADTYPE};
EnumClassIndexContainer<std::array<Owner, to_underlying(RoadTramType::End)>, 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;
+37 -37
View File
@@ -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>((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;
+4 -4
View File
@@ -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<int>(GetRoadBits(cur_tile, RoadTramType::Road).Count()));
UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -static_cast<int>(GetRoadBits(cur_tile, RoadTramType::Tram).Count()));
}
UpdateCompanyRoadInfrastructure(road_rt, road_owner, ROAD_STOP_TRACKBIT_FACTOR);