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(). */
/**
* 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.
* 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.
* @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
* 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) {
/* 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.
*/
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:
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. */
default:
@ -192,13 +218,13 @@ static int32_t LookupWithoutBuildOnSlopes(::Slope slope, const Array<> &existing
* @param neighbour The neighbour.
* @return The rotate neighbour data.
*/
static int32_t RotateNeighbour(int32_t neighbour)
static RoadPartOrientation RotateNeighbour(RoadPartOrientation neighbour)
{
switch (neighbour) {
case -2: return -1;
case -1: return 2;
case 1: return -2;
case 2: return 1;
case RoadPartOrientation::NW: return RoadPartOrientation::NE;
case RoadPartOrientation::NE: return RoadPartOrientation::SE;
case RoadPartOrientation::SE: return RoadPartOrientation::SW;
case RoadPartOrientation::SW: return RoadPartOrientation::NW;
default: NOT_REACHED();
}
}
@ -208,13 +234,13 @@ static int32_t RotateNeighbour(int32_t neighbour)
* @param neighbour The neighbour.
* @return The bits representing the direction.
*/
static RoadBits NeighbourToRoadBits(int32_t neighbour)
static RoadBits NeighbourToRoadBits(RoadPartOrientation neighbour)
{
switch (neighbour) {
case -2: return ROAD_NW;
case -1: return ROAD_NE;
case 2: return ROAD_SE;
case 1: return ROAD_SW;
case RoadPartOrientation::NW: return ROAD_NW;
case RoadPartOrientation::NE: return ROAD_NE;
case RoadPartOrientation::SE: return ROAD_SE;
case RoadPartOrientation::SW: return ROAD_SW;
default: NOT_REACHED();
}
}
@ -229,7 +255,7 @@ static RoadBits NeighbourToRoadBits(int32_t neighbour)
* they are build or 2 when building the first part automatically
* 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. */
if (IsSteepSlope(slope)) {
@ -287,7 +313,7 @@ static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<> &existing, i
RoadBits start_roadbits = NeighbourToRoadBits(start);
RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end);
RoadBits existing_roadbits = ROAD_NONE;
for (int32_t neighbour : existing) {
for (RoadPartOrientation neighbour : existing) {
for (int j = 0; j < base_rotate; j++) {
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
* to call the API lots of times or create large if-elseif-elseif-else
* constructs.
* In this case it means that a TileXY(0, -1) becomes -2 and TileXY(0, 1)
* 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.
* 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 constructs.
* @param tile The tile to get the orientation from.
* @return The orientation or an empty optional when the input is invalid..
*/
static bool NormaliseTileOffset(int32_t *tile)
static std::optional<RoadPartOrientation> ToRoadPartOrientation(const TileIndex &tile)
{
if (*tile == ScriptMap::GetTileIndex(-1, 0)) {
*tile = -1;
return true;
}
if (*tile == ScriptMap::GetTileIndex(1, 0)) {
*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;
if (tile == ScriptMap::GetTileIndex(0, -1)) return RoadPartOrientation::NW;
if (tile == ScriptMap::GetTileIndex(1, 0)) return RoadPartOrientation::SW;
if (tile == ScriptMap::GetTileIndex(0, 1)) return RoadPartOrientation::SE;
if (tile == ScriptMap::GetTileIndex(-1, 0)) return RoadPartOrientation::NE;
return std::nullopt;
}
/* 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_;
int32_t start = start_.base();
int32_t end = end_.base();
/* The start tile and end tile cannot be the same tile either. */
if (start == end) return -1;
for (size_t i = 0; i < existing.size(); i++) {
if (!NormaliseTileOffset(&existing[i])) return -1;
std::vector<RoadPartOrientation> existing_orientations;
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;
if (!NormaliseTileOffset(&end)) return -1;
auto start_orientation = ToRoadPartOrientation(start);
auto end_orientation = ToRoadPartOrientation(end);
if (!start_orientation || !end_orientation) return -1;
/* Without build on slopes the characteristics are vastly different, so use
* 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)
@ -426,9 +441,9 @@ static bool NormaliseTileOffset(int32_t *tile)
rb = ::GetAnyRoadBits(tile, RTT_ROAD) | ::GetAnyRoadBits(tile, RTT_TRAM);
}
Array<> existing;
Array<TileIndex> existing;
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);

View File

@ -248,7 +248,7 @@ public:
* they are build or 2 when building the first part automatically
* 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