diff --git a/src/core/enum_type.hpp b/src/core/enum_type.hpp index cabefee043..533f734825 100644 --- a/src/core/enum_type.hpp +++ b/src/core/enum_type.hpp @@ -60,4 +60,19 @@ debug_inline constexpr bool HasFlag(const T x, const T y) return (x & y) == y; } +/** + * Toggle a value in a bitset enum. + * @param x The value to change. + * @param y The flag to toggle. + */ +template >> +debug_inline constexpr void ToggleFlag(T &x, const T y) +{ + if (HasFlag(x, y)) { + x &= ~y; + } else { + x |= y; + } +} + #endif /* ENUM_TYPE_HPP */ diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index 1ddd0c916c..31caf9cb14 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -479,11 +479,11 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_RIVER_PULLDOWN: SetDParam(0, _rivers[_settings_newgame.game_creation.amount_of_rivers]); break; case WID_GL_SMOOTHNESS_PULLDOWN: SetDParam(0, _smoothness[_settings_newgame.game_creation.tgen_smoothness]); break; case WID_GL_VARIETY_PULLDOWN: SetDParam(0, _variety[_settings_newgame.game_creation.variety]); break; - case WID_GL_BORDERS_RANDOM: SetDParam(0, (_settings_newgame.game_creation.water_borders == BORDERS_RANDOM) ? STR_MAPGEN_BORDER_RANDOMIZE : STR_MAPGEN_BORDER_MANUAL); break; - case WID_GL_WATER_NE: SetDParam(0, (_settings_newgame.game_creation.water_borders == BORDERS_RANDOM) ? STR_MAPGEN_BORDER_RANDOM : HasBit(_settings_newgame.game_creation.water_borders, BORDER_NE) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; - case WID_GL_WATER_NW: SetDParam(0, (_settings_newgame.game_creation.water_borders == BORDERS_RANDOM) ? STR_MAPGEN_BORDER_RANDOM : HasBit(_settings_newgame.game_creation.water_borders, BORDER_NW) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; - case WID_GL_WATER_SE: SetDParam(0, (_settings_newgame.game_creation.water_borders == BORDERS_RANDOM) ? STR_MAPGEN_BORDER_RANDOM : HasBit(_settings_newgame.game_creation.water_borders, BORDER_SE) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; - case WID_GL_WATER_SW: SetDParam(0, (_settings_newgame.game_creation.water_borders == BORDERS_RANDOM) ? STR_MAPGEN_BORDER_RANDOM : HasBit(_settings_newgame.game_creation.water_borders, BORDER_SW) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; + case WID_GL_BORDERS_RANDOM: SetDParam(0, (_settings_newgame.game_creation.water_borders == Borders::Random) ? STR_MAPGEN_BORDER_RANDOMIZE : STR_MAPGEN_BORDER_MANUAL); break; + case WID_GL_WATER_NE: SetDParam(0, (_settings_newgame.game_creation.water_borders == Borders::Random) ? STR_MAPGEN_BORDER_RANDOM : HasFlag(_settings_newgame.game_creation.water_borders, Borders::NorthEast) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; + case WID_GL_WATER_NW: SetDParam(0, (_settings_newgame.game_creation.water_borders == Borders::Random) ? STR_MAPGEN_BORDER_RANDOM : HasFlag(_settings_newgame.game_creation.water_borders, Borders::NorthWest) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; + case WID_GL_WATER_SE: SetDParam(0, (_settings_newgame.game_creation.water_borders == Borders::Random) ? STR_MAPGEN_BORDER_RANDOM : HasFlag(_settings_newgame.game_creation.water_borders, Borders::SouthEast) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; + case WID_GL_WATER_SW: SetDParam(0, (_settings_newgame.game_creation.water_borders == Borders::Random) ? STR_MAPGEN_BORDER_RANDOM : HasFlag(_settings_newgame.game_creation.water_borders, Borders::SouthWest) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); break; case WID_GL_HEIGHTMAP_ROTATION_PULLDOWN: SetDParam(0, _rotation[_settings_newgame.game_creation.heightmap_rotation]); break; case WID_GL_HEIGHTMAP_SIZE_TEXT: @@ -517,15 +517,15 @@ struct GenerateLandscapeWindow : public Window { this->SetWidgetDisabledState(WID_GL_SMOOTHNESS_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL); this->SetWidgetDisabledState(WID_GL_VARIETY_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL); this->SetWidgetDisabledState(WID_GL_BORDERS_RANDOM, _settings_newgame.game_creation.land_generator == LG_ORIGINAL || !_settings_newgame.construction.freeform_edges); - this->SetWidgetsDisabledState(_settings_newgame.game_creation.land_generator == LG_ORIGINAL || !_settings_newgame.construction.freeform_edges || _settings_newgame.game_creation.water_borders == BORDERS_RANDOM, + this->SetWidgetsDisabledState(_settings_newgame.game_creation.land_generator == LG_ORIGINAL || !_settings_newgame.construction.freeform_edges || _settings_newgame.game_creation.water_borders == Borders::Random, WID_GL_WATER_NW, WID_GL_WATER_NE, WID_GL_WATER_SE, WID_GL_WATER_SW); - this->SetWidgetLoweredState(WID_GL_BORDERS_RANDOM, _settings_newgame.game_creation.water_borders == BORDERS_RANDOM); + this->SetWidgetLoweredState(WID_GL_BORDERS_RANDOM, _settings_newgame.game_creation.water_borders == Borders::Random); - this->SetWidgetLoweredState(WID_GL_WATER_NW, HasBit(_settings_newgame.game_creation.water_borders, BORDER_NW)); - this->SetWidgetLoweredState(WID_GL_WATER_NE, HasBit(_settings_newgame.game_creation.water_borders, BORDER_NE)); - this->SetWidgetLoweredState(WID_GL_WATER_SE, HasBit(_settings_newgame.game_creation.water_borders, BORDER_SE)); - this->SetWidgetLoweredState(WID_GL_WATER_SW, HasBit(_settings_newgame.game_creation.water_borders, BORDER_SW)); + this->SetWidgetLoweredState(WID_GL_WATER_NW, HasFlag(_settings_newgame.game_creation.water_borders, Borders::NorthWest)); + this->SetWidgetLoweredState(WID_GL_WATER_NE, HasFlag(_settings_newgame.game_creation.water_borders, Borders::NorthEast)); + this->SetWidgetLoweredState(WID_GL_WATER_SE, HasFlag(_settings_newgame.game_creation.water_borders, Borders::SouthEast)); + this->SetWidgetLoweredState(WID_GL_WATER_SW, HasFlag(_settings_newgame.game_creation.water_borders, Borders::SouthWest)); this->SetWidgetsDisabledState(_settings_newgame.game_creation.land_generator == LG_ORIGINAL && (_settings_newgame.game_creation.landscape == LT_ARCTIC || _settings_newgame.game_creation.landscape == LT_TROPIC), WID_GL_TERRAIN_PULLDOWN, WID_GL_WATER_PULLDOWN); @@ -829,27 +829,27 @@ struct GenerateLandscapeWindow : public Window { /* Freetype map borders */ case WID_GL_WATER_NW: - _settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_NW); + ToggleFlag(_settings_newgame.game_creation.water_borders, Borders::NorthWest); this->InvalidateData(); break; case WID_GL_WATER_NE: - _settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_NE); + ToggleFlag(_settings_newgame.game_creation.water_borders, Borders::NorthEast); this->InvalidateData(); break; case WID_GL_WATER_SE: - _settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_SE); + ToggleFlag(_settings_newgame.game_creation.water_borders, Borders::SouthEast); this->InvalidateData(); break; case WID_GL_WATER_SW: - _settings_newgame.game_creation.water_borders = ToggleBit(_settings_newgame.game_creation.water_borders, BORDER_SW); + ToggleFlag(_settings_newgame.game_creation.water_borders, Borders::SouthWest); this->InvalidateData(); break; case WID_GL_BORDERS_RANDOM: - _settings_newgame.game_creation.water_borders = (_settings_newgame.game_creation.water_borders == BORDERS_RANDOM) ? 0 : BORDERS_RANDOM; + _settings_newgame.game_creation.water_borders = (_settings_newgame.game_creation.water_borders == Borders::Random) ? Borders::None : Borders::Random; this->InvalidateData(); break; diff --git a/src/landscape_type.h b/src/landscape_type.h index 81bed326e2..602d314d61 100644 --- a/src/landscape_type.h +++ b/src/landscape_type.h @@ -10,6 +10,7 @@ #ifndef LANDSCAPE_TYPE_H #define LANDSCAPE_TYPE_H +#include "core/enum_type.hpp" typedef uint8_t LandscapeID; ///< Landscape type. @see LandscapeType /** Landscape types */ @@ -25,12 +26,15 @@ enum LandscapeType { /** * For storing the water borders which shall be retained. */ -enum Borders { - BORDER_NE = 0, - BORDER_SE = 1, - BORDER_SW = 2, - BORDER_NW = 3, - BORDERS_RANDOM = 16, +enum class Borders : uint8_t { + None = 0, + NorthEast = 1U << 0, ///< Border on North East. + SouthEast = 1U << 1, ///< Border on South East. + SouthWest = 1U << 2, ///< Border on South West. + NorthWest = 1U << 3, ///< Border on North West. + Random = 1U << 4, ///< Randomise borders. + All = NorthEast | SouthEast | SouthWest | NorthWest, ///< Border on all sides. }; +DECLARE_ENUM_AS_BIT_SET(Borders) #endif /* LANDSCAPE_TYPE_H */ diff --git a/src/settings_type.h b/src/settings_type.h index 157bdf6058..b086bc2950 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -366,7 +366,7 @@ struct GameCreationSettings { uint8_t se_flat_world_height; ///< land height a flat world gets in SE uint8_t town_name; ///< the town name generator used for town names uint8_t landscape; ///< the landscape we're currently in - uint8_t water_borders; ///< bitset of the borders that are water + Borders water_borders; ///< bitset of the borders that are water uint16_t custom_town_number; ///< manually entered number of towns uint16_t custom_industry_number; ///< manually entered number of industries uint8_t variety; ///< variety level applied to TGP diff --git a/src/tgp.cpp b/src/tgp.cpp index 1ce32fda86..99f14da30f 100644 --- a/src/tgp.cpp +++ b/src/tgp.cpp @@ -718,7 +718,7 @@ static double perlin_coast_noise_2D(const double x, const double y, const double * Please note that all the small numbers; 53, 101, 167, etc. are small primes * to help give the perlin noise a bit more of a random feel. */ -static void HeightMapCoastLines(uint8_t water_borders) +static void HeightMapCoastLines(Borders water_borders) { int smallest_size = std::min(_settings_game.game_creation.map_x, _settings_game.game_creation.map_y); const int margin = 4; @@ -728,7 +728,7 @@ static void HeightMapCoastLines(uint8_t water_borders) /* Lower to sea level */ for (y = 0; y <= _height_map.size_y; y++) { - if (HasBit(water_borders, BORDER_NE)) { + if (HasFlag(water_borders, Borders::NorthEast)) { /* Top right */ max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.9, 53) + 0.25) * 5 + (perlin_coast_noise_2D(y, y, 0.35, 179) + 1) * 12); max_x = std::max((smallest_size * smallest_size / 64) + max_x, (smallest_size * smallest_size / 64) + margin - max_x); @@ -738,7 +738,7 @@ static void HeightMapCoastLines(uint8_t water_borders) } } - if (HasBit(water_borders, BORDER_SW)) { + if (HasFlag(water_borders, Borders::SouthWest)) { /* Bottom left */ max_x = abs((perlin_coast_noise_2D(_height_map.size_y - y, y, 0.85, 101) + 0.3) * 6 + (perlin_coast_noise_2D(y, y, 0.45, 67) + 0.75) * 8); max_x = std::max((smallest_size * smallest_size / 64) + max_x, (smallest_size * smallest_size / 64) + margin - max_x); @@ -751,7 +751,7 @@ static void HeightMapCoastLines(uint8_t water_borders) /* Lower to sea level */ for (x = 0; x <= _height_map.size_x; x++) { - if (HasBit(water_borders, BORDER_NW)) { + if (HasFlag(water_borders, Borders::NorthWest)) { /* Top left */ max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 2, 0.9, 167) + 0.4) * 5 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.4, 211) + 0.7) * 9); max_y = std::max((smallest_size * smallest_size / 64) + max_y, (smallest_size * smallest_size / 64) + margin - max_y); @@ -761,7 +761,7 @@ static void HeightMapCoastLines(uint8_t water_borders) } } - if (HasBit(water_borders, BORDER_SE)) { + if (HasFlag(water_borders, Borders::SouthEast)) { /* Bottom right */ max_y = abs((perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.85, 71) + 0.25) * 6 + (perlin_coast_noise_2D(x, _height_map.size_y / 3, 0.35, 193) + 0.75) * 12); max_y = std::max((smallest_size * smallest_size / 64) + max_y, (smallest_size * smallest_size / 64) + margin - max_y); @@ -811,18 +811,18 @@ static void HeightMapSmoothCoastInDirection(int org_x, int org_y, int dir_x, int } /** Smooth coasts by modulating height of tiles close to map edges with cosine of distance from edge */ -static void HeightMapSmoothCoasts(uint8_t water_borders) +static void HeightMapSmoothCoasts(Borders water_borders) { int x, y; /* First Smooth NW and SE coasts (y close to 0 and y close to size_y) */ for (x = 0; x < _height_map.size_x; x++) { - if (HasBit(water_borders, BORDER_NW)) HeightMapSmoothCoastInDirection(x, 0, 0, 1); - if (HasBit(water_borders, BORDER_SE)) HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1); + if (HasFlag(water_borders, Borders::NorthWest)) HeightMapSmoothCoastInDirection(x, 0, 0, 1); + if (HasFlag(water_borders, Borders::SouthEast)) HeightMapSmoothCoastInDirection(x, _height_map.size_y - 1, 0, -1); } /* First Smooth NE and SW coasts (x close to 0 and x close to size_x) */ for (y = 0; y < _height_map.size_y; y++) { - if (HasBit(water_borders, BORDER_NE)) HeightMapSmoothCoastInDirection(0, y, 1, 0); - if (HasBit(water_borders, BORDER_SW)) HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0); + if (HasFlag(water_borders, Borders::NorthEast)) HeightMapSmoothCoastInDirection(0, y, 1, 0); + if (HasFlag(water_borders, Borders::SouthWest)) HeightMapSmoothCoastInDirection(_height_map.size_x - 1, y, -1, 0); } } @@ -865,8 +865,8 @@ static void HeightMapNormalize() HeightMapAdjustWaterLevel(water_percent, h_max_new); - uint8_t water_borders = _settings_game.construction.freeform_edges ? _settings_game.game_creation.water_borders : 0xF; - if (water_borders == BORDERS_RANDOM) water_borders = GB(Random(), 0, 4); + Borders water_borders = _settings_game.construction.freeform_edges ? _settings_game.game_creation.water_borders : Borders::All; + if (water_borders == Borders::Random) water_borders = static_cast(GB(Random(), 0, 4)); HeightMapCoastLines(water_borders); HeightMapSmoothSlopes(roughness);