1
0
Fork 0

Codechange: replace magic numbers with enumeration

pull/13030/head
Rubidium 2024-10-22 18:06:22 +02:00 committed by rubidium42
parent 4a4c77ff04
commit ea6aa4653a
2 changed files with 69 additions and 54 deletions

View File

@ -136,6 +136,32 @@
/* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */ /* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */
/**
* Enumeration or the orientations of road parts.
*
* Technically DiagDirection could be used, but that allows simple conversions to/from integer. In this case that is not wanted.
*/
enum class RoadPartOrientation {
NW, NE, SW, SE
};
/**
* Check whether the two given orientations combined are a straight road.
* @param start The part that should be build first.
* @param end The part that will be build second.
* @return True iff start and end combined describe a straight road (ROAD_X or ROAD_Y).
*/
static bool IsStraight(RoadPartOrientation start, RoadPartOrientation end)
{
switch (start) {
case RoadPartOrientation::NW: return end == RoadPartOrientation::SE;
case RoadPartOrientation::NE: return end == RoadPartOrientation::SW;
case RoadPartOrientation::SW: return end == RoadPartOrientation::NE;
case RoadPartOrientation::SE: return end == RoadPartOrientation::NW;
default: NOT_REACHED();
}
}
/** /**
* Check whether the given existing bits the start and end part can be build. * Check whether the given existing bits the start and end part can be build.
* As the function assumes the bits being build on a slope that does not * As the function assumes the bits being build on a slope that does not
@ -150,9 +176,9 @@
* @param end The part that will be build second. * @param end The part that will be build second.
* @return True if and only if the road bits can be build. * @return True if and only if the road bits can be build.
*/ */
static bool CheckAutoExpandedRoadBits(const Array<> &existing, int32_t start, int32_t end) static bool CheckAutoExpandedRoadBits(const Array<RoadPartOrientation> &existing, RoadPartOrientation start, RoadPartOrientation end)
{ {
return (start + end == 0) && (existing.empty() || existing[0] == start || existing[0] == end); return IsStraight(start, end) && (existing.empty() || existing[0] == start || existing[0] == end);
} }
/** /**
@ -165,7 +191,7 @@ static bool CheckAutoExpandedRoadBits(const Array<> &existing, int32_t start, in
* they are build or 2 when building the first part automatically * they are build or 2 when building the first part automatically
* builds the second part. * builds the second part.
*/ */
static int32_t LookupWithoutBuildOnSlopes(::Slope slope, const Array<> &existing, int32_t start, int32_t end) static int32_t LookupWithoutBuildOnSlopes(::Slope slope, const Array<RoadPartOrientation> &existing, RoadPartOrientation start, RoadPartOrientation end)
{ {
switch (slope) { switch (slope) {
/* Flat slopes can always be build. */ /* Flat slopes can always be build. */
@ -177,9 +203,9 @@ static int32_t LookupWithoutBuildOnSlopes(::Slope slope, const Array<> &existing
* in the game have been changed. * in the game have been changed.
*/ */
case SLOPE_NE: case SLOPE_SW: case SLOPE_NE: case SLOPE_SW:
return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing.empty() ? 2 : 1) : 0; return (CheckAutoExpandedRoadBits(existing, start, end) && (start == RoadPartOrientation::SW || end == RoadPartOrientation::SW)) ? (existing.empty() ? 2 : 1) : 0;
case SLOPE_SE: case SLOPE_NW: case SLOPE_SE: case SLOPE_NW:
return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing.empty() ? 2 : 1) : 0; return (CheckAutoExpandedRoadBits(existing, start, end) && (start != RoadPartOrientation::SW && end != RoadPartOrientation::SW)) ? (existing.empty() ? 2 : 1) : 0;
/* Any other tile cannot be built on. */ /* Any other tile cannot be built on. */
default: default:
@ -192,13 +218,13 @@ static int32_t LookupWithoutBuildOnSlopes(::Slope slope, const Array<> &existing
* @param neighbour The neighbour. * @param neighbour The neighbour.
* @return The rotate neighbour data. * @return The rotate neighbour data.
*/ */
static int32_t RotateNeighbour(int32_t neighbour) static RoadPartOrientation RotateNeighbour(RoadPartOrientation neighbour)
{ {
switch (neighbour) { switch (neighbour) {
case -2: return -1; case RoadPartOrientation::NW: return RoadPartOrientation::NE;
case -1: return 2; case RoadPartOrientation::NE: return RoadPartOrientation::SE;
case 1: return -2; case RoadPartOrientation::SE: return RoadPartOrientation::SW;
case 2: return 1; case RoadPartOrientation::SW: return RoadPartOrientation::NW;
default: NOT_REACHED(); default: NOT_REACHED();
} }
} }
@ -208,13 +234,13 @@ static int32_t RotateNeighbour(int32_t neighbour)
* @param neighbour The neighbour. * @param neighbour The neighbour.
* @return The bits representing the direction. * @return The bits representing the direction.
*/ */
static RoadBits NeighbourToRoadBits(int32_t neighbour) static RoadBits NeighbourToRoadBits(RoadPartOrientation neighbour)
{ {
switch (neighbour) { switch (neighbour) {
case -2: return ROAD_NW; case RoadPartOrientation::NW: return ROAD_NW;
case -1: return ROAD_NE; case RoadPartOrientation::NE: return ROAD_NE;
case 2: return ROAD_SE; case RoadPartOrientation::SE: return ROAD_SE;
case 1: return ROAD_SW; case RoadPartOrientation::SW: return ROAD_SW;
default: NOT_REACHED(); default: NOT_REACHED();
} }
} }
@ -229,7 +255,7 @@ static RoadBits NeighbourToRoadBits(int32_t neighbour)
* they are build or 2 when building the first part automatically * they are build or 2 when building the first part automatically
* builds the second part. * builds the second part.
*/ */
static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<> &existing, int32_t start, int32_t end) static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<RoadPartOrientation> &existing, RoadPartOrientation start, RoadPartOrientation end)
{ {
/* Steep slopes behave the same as slopes with one corner raised. */ /* Steep slopes behave the same as slopes with one corner raised. */
if (IsSteepSlope(slope)) { if (IsSteepSlope(slope)) {
@ -287,7 +313,7 @@ static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<> &existing, i
RoadBits start_roadbits = NeighbourToRoadBits(start); RoadBits start_roadbits = NeighbourToRoadBits(start);
RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end); RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end);
RoadBits existing_roadbits = ROAD_NONE; RoadBits existing_roadbits = ROAD_NONE;
for (int32_t neighbour : existing) { for (RoadPartOrientation neighbour : existing) {
for (int j = 0; j < base_rotate; j++) { for (int j = 0; j < base_rotate; j++) {
neighbour = RotateNeighbour(neighbour); neighbour = RotateNeighbour(neighbour);
} }
@ -356,55 +382,44 @@ static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<> &existing, i
} }
/** /**
* Normalise all input data so we can easily handle it without needing * Normalise all input data (tile indices) so we can easily handle it without needing
* to call the API lots of times or create large if-elseif-elseif-else * to call the API lots of times or create large if-elseif-elseif-else constructs.
* constructs. * @param tile The tile to get the orientation from.
* In this case it means that a TileXY(0, -1) becomes -2 and TileXY(0, 1) * @return The orientation or an empty optional when the input is invalid..
* becomes 2. TileXY(-1, 0) and TileXY(1, 0) stay respectively -1 and 1.
* Any other value means that it is an invalid tile offset.
* @param tile The tile to normalise.
* @return True if and only if the tile offset is valid.
*/ */
static bool NormaliseTileOffset(int32_t *tile) static std::optional<RoadPartOrientation> ToRoadPartOrientation(const TileIndex &tile)
{ {
if (*tile == ScriptMap::GetTileIndex(-1, 0)) { if (tile == ScriptMap::GetTileIndex(0, -1)) return RoadPartOrientation::NW;
*tile = -1; if (tile == ScriptMap::GetTileIndex(1, 0)) return RoadPartOrientation::SW;
return true; if (tile == ScriptMap::GetTileIndex(0, 1)) return RoadPartOrientation::SE;
} if (tile == ScriptMap::GetTileIndex(-1, 0)) return RoadPartOrientation::NE;
if (*tile == ScriptMap::GetTileIndex(1, 0)) { return std::nullopt;
*tile = 1;
return true;
}
if (*tile == ScriptMap::GetTileIndex(0, -1)) {
*tile = -2;
return true;
}
if (*tile == ScriptMap::GetTileIndex(0, 1)) {
*tile = 2;
return true;
}
return false;
} }
/* static */ SQInteger ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::Slope slope_, Array<> &&existing, TileIndex start_, TileIndex end_) /* static */ SQInteger ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::Slope slope_, Array<TileIndex> &&existing, TileIndex start, TileIndex end)
{ {
::Slope slope = (::Slope)slope_; ::Slope slope = (::Slope)slope_;
int32_t start = start_.base();
int32_t end = end_.base();
/* The start tile and end tile cannot be the same tile either. */ /* The start tile and end tile cannot be the same tile either. */
if (start == end) return -1; if (start == end) return -1;
for (size_t i = 0; i < existing.size(); i++) { std::vector<RoadPartOrientation> existing_orientations;
if (!NormaliseTileOffset(&existing[i])) return -1; existing_orientations.reserve(existing.size());
for (const auto &t : existing) {
auto orientation = ToRoadPartOrientation(t);
if (!orientation) return -1;
existing_orientations.push_back(*orientation);
} }
if (!NormaliseTileOffset(&start)) return -1; auto start_orientation = ToRoadPartOrientation(start);
if (!NormaliseTileOffset(&end)) return -1; auto end_orientation = ToRoadPartOrientation(end);
if (!start_orientation || !end_orientation) return -1;
/* Without build on slopes the characteristics are vastly different, so use /* Without build on slopes the characteristics are vastly different, so use
* a different helper function (one that is much simpler). */ * a different helper function (one that is much simpler). */
return _settings_game.construction.build_on_slopes ? LookupWithBuildOnSlopes(slope, existing, start, end) : LookupWithoutBuildOnSlopes(slope, existing, start, end); return _settings_game.construction.build_on_slopes ?
LookupWithBuildOnSlopes(slope, existing_orientations, *start_orientation, *end_orientation) :
LookupWithoutBuildOnSlopes(slope, existing_orientations, *start_orientation, *end_orientation);
} }
/* static */ SQInteger ScriptRoad::CanBuildConnectedRoadPartsHere(TileIndex tile, TileIndex start, TileIndex end) /* static */ SQInteger ScriptRoad::CanBuildConnectedRoadPartsHere(TileIndex tile, TileIndex start, TileIndex end)
@ -426,9 +441,9 @@ static bool NormaliseTileOffset(int32_t *tile)
rb = ::GetAnyRoadBits(tile, RTT_ROAD) | ::GetAnyRoadBits(tile, RTT_TRAM); rb = ::GetAnyRoadBits(tile, RTT_ROAD) | ::GetAnyRoadBits(tile, RTT_TRAM);
} }
Array<> existing; Array<TileIndex> existing;
for (uint i = 0; i < lengthof(neighbours); i++) { for (uint i = 0; i < lengthof(neighbours); i++) {
if (HasBit(rb, i)) existing.emplace_back(neighbours[i].base()); if (HasBit(rb, i)) existing.emplace_back(neighbours[i]);
} }
return ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::GetSlope(tile), std::move(existing), start - tile, end - tile); return ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::GetSlope(tile), std::move(existing), start - tile, end - tile);

View File

@ -248,7 +248,7 @@ public:
* they are build or 2 when building the first part automatically * they are build or 2 when building the first part automatically
* builds the second part. -1 means the preconditions are not met. * builds the second part. -1 means the preconditions are not met.
*/ */
static SQInteger CanBuildConnectedRoadParts(ScriptTile::Slope slope, Array<> &&existing, TileIndex start, TileIndex end); static SQInteger CanBuildConnectedRoadParts(ScriptTile::Slope slope, Array<TileIndex> &&existing, TileIndex start, TileIndex end);
/** /**
* Lookup function for building road parts independent of whether the * Lookup function for building road parts independent of whether the