mirror of https://github.com/OpenTTD/OpenTTD
Codechange: replace magic numbers with enumeration
parent
4a4c77ff04
commit
ea6aa4653a
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue