diff --git a/tilemap/docs/api.md b/tilemap/docs/api.md index 476cc61..2d86609 100644 --- a/tilemap/docs/api.md +++ b/tilemap/docs/api.md @@ -140,8 +140,8 @@ BiomeType determine_biome(double temperature, double humidity); ### Basic Usage ```cpp -#include "tilemap.h" -#include "generation.h" +#include "tilemap/tilemap.h" +#include "tilemap/generation.h" // Create map istd::TileMap tilemap(4); // 4x4 chunks diff --git a/tilemap/examples/biome_demo.cpp b/tilemap/examples/biome_demo.cpp index 364cded..5b90f23 100644 --- a/tilemap/examples/biome_demo.cpp +++ b/tilemap/examples/biome_demo.cpp @@ -1,10 +1,9 @@ #include "bmp.h" -#include "generation.h" -#include "tile.h" -#include "tilemap.h" +#include "tilemap/generation.h" +#include "tilemap/tile.h" +#include "tilemap/tilemap.h" #include #include -#include #include #include diff --git a/tilemap/include/generation.h b/tilemap/include/generation.h deleted file mode 100644 index d28f81d..0000000 --- a/tilemap/include/generation.h +++ /dev/null @@ -1,495 +0,0 @@ -#ifndef TILEMAP_GENERATION_H -#define TILEMAP_GENERATION_H - -#include "biome.h" -#include "chunk.h" -#include "noise.h" -#include "tilemap.h" -#include "xoroshiro.h" -#include -#include - -namespace istd { - -/** - * @brief Configuration parameters for terrain generation - */ -struct GenerationConfig { - Seed seed; - - // Noise parameters - double temperature_scale = 0.05; // Scale for temperature noise - int temperature_octaves = 3; // Number of octaves for temperature noise - double temperature_persistence = 0.4; // Persistence for temperature noise - - double humidity_scale = 0.05; // Scale for humidity noise - int humidity_octaves = 3; // Number of octaves for humidity noise - double humidity_persistence = 0.4; // Persistence for humidity noise - - double base_scale = 0.08; // Scale for base terrain noise - int base_octaves = 3; // Number of octaves for base terrain noise - double base_persistence = 0.5; // Persistence for base terrain noise - - int mountain_smoothen_steps = 2; // Number of steps for mountain smoothing - // cellular automata - std::uint32_t mountain_remove_threshold = 10; // Threshold for mountain - // removal - - int island_smoothen_steps = 8; // Number of steps for island smoothing - // cellular automata - std::uint32_t island_remove_threshold = 8; // Threshold for island removal - - std::uint32_t fill_threshold = 10; // Fill holes smaller than this size - std::uint32_t deepwater_radius = 2; // Radius for deepwater generation - - // Oil generation parameters - std::uint8_t oil_density = 204; // Average oil fields per 255 chunk (~0.8) - std::uint8_t oil_cluster_min_size = 1; // Minimum tiles per oil cluster - std::uint8_t oil_cluster_max_size = 7; // Maximum tiles per oil cluster - // (should be <= 24) - std::uint8_t oil_base_probe = 128; // Biome preference multiplier (out - // of 255) -}; - -class BiomeGenerationPass { -private: - const GenerationConfig &config_; - - UniformPerlinNoise temperature_noise_; - UniformPerlinNoise humidity_noise_; - -public: - /** - * @brief Construct a biome generation pass - * @param config Generation configuration parameters - * @param r1 Random number generator for temperature noise - * @param r2 Random number generator for humidity noise - */ - BiomeGenerationPass( - const GenerationConfig &config, Xoroshiro128PP r1, Xoroshiro128PP r2 - ); - - /** - * @brief Generate biomes for the entire tilemap - * @param tilemap The tilemap to generate biomes into - */ - void operator()(TileMap &tilemap); - -private: - /** - * @brief Get climate values at a global position - * @param global_x Global X coordinate - * @param global_y Global Y coordinate - * @return Pair of (temperature, humidity) in range [0,1] - */ - std::pair get_climate( - double global_x, double global_y - ) const; -}; - -class BaseTileTypeGenerationPass { -private: - const GenerationConfig &config_; - UniformPerlinNoise base_noise_; - -public: - /** - * @brief Construct a base tile type generation pass - * @param config Generation configuration parameters - * @param rng Random number generator for base terrain noise - */ - BaseTileTypeGenerationPass( - const GenerationConfig &config, Xoroshiro128PP rng - ); - - /** - * @brief Generate base tile types for the entire tilemap - * @param tilemap The tilemap to generate base types into - */ - void operator()(TileMap &tilemap); - - /** - * @brief Generate terrain for a single chunk - * @param tilemap The tilemap to modify - * @param chunk_x Chunk X coordinate - * @param chunk_y Chunk Y coordinate - */ - void generate_chunk( - TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y - ); - - /** - * @brief Generate terrain for a sub-chunk with specific biome - * @param tilemap The tilemap to modify - * @param chunk_x Chunk X coordinate - * @param chunk_y Chunk Y coordinate - * @param sub_pos Sub-chunk position within the chunk - * @param biome The biome type for this sub-chunk - */ - void generate_subchunk( - TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y, - SubChunkPos sub_pos, BiomeType biome - ); - - /** - * @brief Determine base terrain type based on noise value and biome - * properties - * @param noise_value Base terrain noise value [0,1] - * @param properties Biome properties to use - * @return The appropriate base tile type - */ - BaseTileType determine_base_type( - double noise_value, const BiomeProperties &properties - ) const; -}; - -class MountainHoleFillPass { -private: - const GenerationConfig &config_; - -public: - /** - * @brief Construct a hole fill pass - * @param config Generation configuration parameters - */ - explicit MountainHoleFillPass(const GenerationConfig &config); - - /** - * @brief Fill small holes in the terrain using BFS - * @param tilemap The tilemap to process - */ - void operator()(TileMap &tilemap); - -private: - /** - * @brief Check if a tile type is passable for BFS - * @param type The base tile type to check - * @return True if the tile is passable (not mountain or at boundary) - */ - bool is_passable(BaseTileType type) const; - - /** - * @brief Perform BFS to find connected component size - * @param tilemap The tilemap to search - * @param start_pos Starting position for BFS - * @param visited 2D array tracking visited tiles - * @param positions Output vector of positions in this component - * @return Size of the connected component - */ - std::uint32_t bfs_component_size( - TileMap &tilemap, TilePos start_pos, - std::vector> &visited, std::vector &positions - ); -}; - -class SmoothenMountainsPass { -private: - const GenerationConfig &config_; - DiscreteRandomNoise noise_; - - /** - * @brief Perform BFS to find connected component size for mountains - * @param tilemap The tilemap to search - * @param start_pos Starting position for BFS - * @param visited 2D array tracking visited tiles - * @param positions Output vector of positions in this component - * @return Size of the connected component - */ - std::uint32_t bfs_component_size( - TileMap &tilemap, TilePos start_pos, - std::vector> &visited, std::vector &positions - ); - - /** - * @brief Replace mountain tiles with terrain types from neighboring areas - * @param tilemap The tilemap to modify - * @param positions Vector of mountain positions to replace - */ - void demountainize(TileMap &tilemap, const std::vector &positions); - - /** - * @brief Remove small mountain components to create smoother terrain - * @param tilemap The tilemap to process - */ - void remove_small_mountain(TileMap &tilemap); - - /** - * @brief Smoothen mountains with cellular automata - * @param tilemap The tilemap to process - */ - void smoothen_mountains(TileMap &tilemap, std::uint32_t step_i); - - void smoothen_mountains_tile( - const TileMap &tilemap, TilePos pos, std::uint32_t step_i, - std::vector> &replacements - ); - -public: - /** - * @brief Construct a mountain smoothing pass - * @param config Generation configuration parameters - * @param rng Random number generator for terrain replacement - */ - SmoothenMountainsPass(const GenerationConfig &config, Xoroshiro128PP rng); - - /** - * @brief Smoothen mountains in the terrain - * @param tilemap The tilemap to process - */ - void operator()(TileMap &tilemap); -}; - -class SmoothenIslandPass { -private: - const GenerationConfig &config_; - DiscreteRandomNoise noise_; - - /** - * @brief Perform BFS to find connected component size for islands - * @param tilemap The tilemap to search - * @param start_pos Starting position for BFS - * @param visited 2D array tracking visited tiles - * @param positions Output vector of positions in this component - * @return Size of the connected component - */ - std::uint32_t bfs_component_size( - TileMap &tilemap, TilePos start_pos, - std::vector> &visited, std::vector &positions - ); - - /** - * @brief Remove small island components to create smoother terrain - * @param tilemap The tilemap to process - */ - void remove_small_island(TileMap &tilemap); - - /** - * @brief Smoothen islands with cellular automata - * @param tilemap The tilemap to process - */ - void smoothen_islands(TileMap &tilemap, std::uint32_t step_i); - - void smoothen_islands_subchunk( - TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y, - SubChunkPos sub_pos, std::uint32_t step_i, - std::vector> &replacements - ); - - struct CACtx { - BiomeType biome; - std::uint8_t rand; - int adj_land, adj_sand, adj_water; // Adjacent tile counts - }; - - Tile ca_tile(TilePos pos, Tile tile, const CACtx &ctx) const; - - /** - * @brief Check if a tile is part of an island (Land or Sand) - * @param tile The tile to check - * @return True if the tile is Land or Sand - */ - bool is_island_tile(const Tile &tile) const; - -public: - /** - * @brief Construct an island smoothing pass - * @param config Generation configuration parameters - * @param rng Random number generator for terrain replacement - */ - SmoothenIslandPass(const GenerationConfig &config, Xoroshiro128PP rng); - - /** - * @brief Smoothen islands in the terrain - * @param tilemap The tilemap to process - */ - void operator()(TileMap &tilemap); -}; - -// Terrain generator class that manages the generation process -class TerrainGenerator { -private: - GenerationConfig config_; - Xoroshiro128PP master_rng_; - -public: - /** - * @brief Construct a terrain generator with the given configuration - * @param config Generation configuration - */ - explicit TerrainGenerator(const GenerationConfig &config); - - /** - * @brief Generate terrain for the entire tilemap - * @param tilemap The tilemap to generate into - */ - void operator()(TileMap &tilemap); - -private: - /** - * @brief Generate biome data for all chunks - * @param tilemap The tilemap to generate biomes into - */ - void biome_pass(TileMap &tilemap); - - /** - * @brief Generate base tile types for all chunks - * @param tilemap The tilemap to generate base types into - */ - void base_tile_type_pass(TileMap &tilemap); - - /** - * @brief Smoothen mountains in the terrain - * @param tilemap The tilemap to process - */ - void smoothen_mountains_pass(TileMap &tilemap); - - /** - * @brief Smoothen islands in the terrain - * @param tilemap The tilemap to process - */ - void smoothen_islands_pass(TileMap &tilemap); - - /** - * @brief Fill small holes in the terrain - * @param tilemap The tilemap to process - */ - void mountain_hole_fill_pass(TileMap &tilemap); - - /** - * @brief Generate deepwater tiles in ocean biomes - * @param tilemap The tilemap to process - */ - void deepwater_pass(TileMap &tilemap); - - /** - * @brief Generate oil clusters on suitable terrain - * @param tilemap The tilemap to process - */ - void oil_pass(TileMap &tilemap); -}; - -class DeepwaterGenerationPass { -private: - std::uint32_t deepwater_radius_; - -public: - /** - * @brief Construct a deepwater generation pass - * @param deepwater_radius Radius to check for water tiles around each water - * tile (default: 1) - */ - explicit DeepwaterGenerationPass(std::uint32_t deepwater_radius); - - /** - * @brief Generate deepwater tiles in ocean biomes - * @param tilemap The tilemap to process - */ - void operator()(TileMap &tilemap); - -private: - /** - * @brief Check if a tile position is within a certain radius and all tiles - * are water - * @param tilemap The tilemap to check - * @param center_pos Center position to check around - * @param radius Radius to check within - * @return True if all tiles within radius are water - */ - -private: - /** - * @brief Process an ocean sub-chunk to generate deepwater tiles - * @param tilemap The tilemap to process - * @param chunk_x Chunk X coordinate - * @param chunk_y Chunk Y coordinate - * @param sub_pos Sub-chunk position within the chunk - */ - void process_ocean_subchunk( - TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y, - SubChunkPos sub_pos - ); - - /** - * @brief Check if a tile position is within a certain radius and all tiles - * are water or deepwater - * @param tilemap The tilemap to check - * @param center_pos Center position to check around - * @param radius Radius to check within - * @return True if all tiles within radius are water or deepwater - */ - bool is_surrounded_by_water( - const TileMap &tilemap, TilePos center_pos, std::uint32_t radius - ) const; -}; - -class OilGenerationPass { -private: - const GenerationConfig &config_; - Xoroshiro128PP rng_; - DiscreteRandomNoise noise_; - -public: - /** - * @brief Construct an oil generation pass - * @param config Generation configuration parameters - * @param rng Random number generator for oil placement - * @param noise_rng Random number generator for noise-based operations - */ - OilGenerationPass( - const GenerationConfig &config, Xoroshiro128PP rng, - Xoroshiro128PP noise_rng - ); - - /** - * @brief Generate oil clusters on the tilemap - * @param tilemap The tilemap to process - */ - void operator()(TileMap &tilemap); - -private: - /** - * @brief Generate oil center positions using Poisson disk sampling - * @param tilemap The tilemap to analyze - * @return Vector of positions where oil clusters should be placed - */ - std::vector generate_oil_centers(const TileMap &tilemap); - - /** - * @brief Generate an oil cluster around a center position - * @param tilemap The tilemap to modify - * @param center Center position for the oil cluster - */ - void generate_oil_cluster(TileMap &tilemap, TilePos center); - - /** - * @brief Check if a tile is suitable for oil placement - * @param tilemap The tilemap to check - * @param pos Position to check - * @return True if oil can be placed at this position - */ - bool is_suitable_for_oil(const TileMap &tilemap, TilePos pos) const; - - /** - * @brief Get biome preference multiplier for oil generation (out of 255) - * @param biome The biome type to check - * @return Preference value (0-255) - */ - std::uint8_t get_biome_oil_preference(BiomeType biome) const; - - /** - * @brief Calculate minimum distance between oil fields based on map size - * @return Minimum distance in tiles - */ - std::uint32_t calculate_min_oil_distance() const; -}; - -/** - * @brief Generate a tilemap using the new biome-based system - * @param tilemap The tilemap to generate into - * @param config Configuration for generation - */ -void map_generate(TileMap &tilemap, const GenerationConfig &config); - -} // namespace istd - -#endif diff --git a/tilemap/include/biome.h b/tilemap/include/tilemap/biome.h similarity index 100% rename from tilemap/include/biome.h rename to tilemap/include/tilemap/biome.h diff --git a/tilemap/include/chunk.h b/tilemap/include/tilemap/chunk.h similarity index 99% rename from tilemap/include/chunk.h rename to tilemap/include/tilemap/chunk.h index be61ac1..1bf89bb 100644 --- a/tilemap/include/chunk.h +++ b/tilemap/include/tilemap/chunk.h @@ -1,6 +1,6 @@ #ifndef ISTD_TILEMAP_CHUNK_H #define ISTD_TILEMAP_CHUNK_H -#include "tile.h" +#include "tilemap/tile.h" #include #include #include diff --git a/tilemap/include/tilemap/generation.h b/tilemap/include/tilemap/generation.h new file mode 100644 index 0000000..421d1f4 --- /dev/null +++ b/tilemap/include/tilemap/generation.h @@ -0,0 +1,121 @@ +#ifndef TILEMAP_GENERATION_H +#define TILEMAP_GENERATION_H + +#include "tilemap/tilemap.h" +#include "tilemap/xoroshiro.h" +#include + +namespace istd { + +/** + * @brief Configuration parameters for terrain generation + */ +struct GenerationConfig { + Seed seed; + + // Noise parameters + double temperature_scale = 0.05; // Scale for temperature noise + int temperature_octaves = 3; // Number of octaves for temperature noise + double temperature_persistence = 0.4; // Persistence for temperature noise + + double humidity_scale = 0.05; // Scale for humidity noise + int humidity_octaves = 3; // Number of octaves for humidity noise + double humidity_persistence = 0.4; // Persistence for humidity noise + + double base_scale = 0.08; // Scale for base terrain noise + int base_octaves = 3; // Number of octaves for base terrain noise + double base_persistence = 0.5; // Persistence for base terrain noise + + int mountain_smoothen_steps = 2; // Number of steps for mountain smoothing + // cellular automata + std::uint32_t mountain_remove_threshold = 10; // Threshold for mountain + // removal + + int island_smoothen_steps = 8; // Number of steps for island smoothing + // cellular automata + std::uint32_t island_remove_threshold = 8; // Threshold for island removal + + std::uint32_t fill_threshold = 10; // Fill holes smaller than this size + std::uint32_t deepwater_radius = 2; // Radius for deepwater generation + + // Oil generation parameters + std::uint8_t oil_density = 204; // Average oil fields per 255 chunk (~0.8) + std::uint8_t oil_cluster_min_size = 1; // Minimum tiles per oil cluster + std::uint8_t oil_cluster_max_size = 7; // Maximum tiles per oil cluster + // (should be <= 24) + std::uint8_t oil_base_probe = 128; // Biome preference multiplier (out + // of 255) +}; + +// Terrain generator class that manages the generation process +class TerrainGenerator { +private: + GenerationConfig config_; + Xoroshiro128PP master_rng_; + +public: + /** + * @brief Construct a terrain generator with the given configuration + * @param config Generation configuration + */ + explicit TerrainGenerator(const GenerationConfig &config); + + /** + * @brief Generate terrain for the entire tilemap + * @param tilemap The tilemap to generate into + */ + void operator()(TileMap &tilemap); + +private: + /** + * @brief Generate biome data for all chunks + * @param tilemap The tilemap to generate biomes into + */ + void biome_pass(TileMap &tilemap); + + /** + * @brief Generate base tile types for all chunks + * @param tilemap The tilemap to generate base types into + */ + void base_tile_type_pass(TileMap &tilemap); + + /** + * @brief Smoothen mountains in the terrain + * @param tilemap The tilemap to process + */ + void smoothen_mountains_pass(TileMap &tilemap); + + /** + * @brief Smoothen islands in the terrain + * @param tilemap The tilemap to process + */ + void smoothen_islands_pass(TileMap &tilemap); + + /** + * @brief Fill small holes in the terrain + * @param tilemap The tilemap to process + */ + void mountain_hole_fill_pass(TileMap &tilemap); + + /** + * @brief Generate deepwater tiles in ocean biomes + * @param tilemap The tilemap to process + */ + void deepwater_pass(TileMap &tilemap); + + /** + * @brief Generate oil clusters on suitable terrain + * @param tilemap The tilemap to process + */ + void oil_pass(TileMap &tilemap); +}; +/** + * @brief Generate a tilemap using the new biome-based system + * @param tilemap The tilemap to generate into + * @param config Configuration for generation + */ +void map_generate(TileMap &tilemap, const GenerationConfig &config); + +} // namespace istd + +#endif diff --git a/tilemap/include/noise.h b/tilemap/include/tilemap/noise.h similarity index 99% rename from tilemap/include/noise.h rename to tilemap/include/tilemap/noise.h index 652a73d..65abaea 100644 --- a/tilemap/include/noise.h +++ b/tilemap/include/tilemap/noise.h @@ -1,7 +1,7 @@ #ifndef ISTD_TILEMAP_NOISE_H #define ISTD_TILEMAP_NOISE_H -#include "xoroshiro.h" +#include "tilemap/xoroshiro.h" #include #include #include diff --git a/tilemap/include/tilemap/pass/base_tile_type.h b/tilemap/include/tilemap/pass/base_tile_type.h new file mode 100644 index 0000000..82b3074 --- /dev/null +++ b/tilemap/include/tilemap/pass/base_tile_type.h @@ -0,0 +1,68 @@ +#ifndef ISTD_TILEMAP_PASS_BASE_TILE_TYPE_H +#define ISTD_TILEMAP_PASS_BASE_TILE_TYPE_H + +#include "tilemap/biome.h" +#include "tilemap/generation.h" +#include "tilemap/noise.h" + +namespace istd { + +class BaseTileTypeGenerationPass { +private: + const GenerationConfig &config_; + UniformPerlinNoise base_noise_; + +public: + /** + * @brief Construct a base tile type generation pass + * @param config Generation configuration parameters + * @param rng Random number generator for base terrain noise + */ + BaseTileTypeGenerationPass( + const GenerationConfig &config, Xoroshiro128PP rng + ); + + /** + * @brief Generate base tile types for the entire tilemap + * @param tilemap The tilemap to generate base types into + */ + void operator()(TileMap &tilemap); + + /** + * @brief Generate terrain for a single chunk + * @param tilemap The tilemap to modify + * @param chunk_x Chunk X coordinate + * @param chunk_y Chunk Y coordinate + */ + void generate_chunk( + TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y + ); + + /** + * @brief Generate terrain for a sub-chunk with specific biome + * @param tilemap The tilemap to modify + * @param chunk_x Chunk X coordinate + * @param chunk_y Chunk Y coordinate + * @param sub_pos Sub-chunk position within the chunk + * @param biome The biome type for this sub-chunk + */ + void generate_subchunk( + TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y, + SubChunkPos sub_pos, BiomeType biome + ); + + /** + * @brief Determine base terrain type based on noise value and biome + * properties + * @param noise_value Base terrain noise value [0,1] + * @param properties Biome properties to use + * @return The appropriate base tile type + */ + BaseTileType determine_base_type( + double noise_value, const BiomeProperties &properties + ) const; +}; + +} // namespace istd + +#endif \ No newline at end of file diff --git a/tilemap/include/tilemap/pass/biome.h b/tilemap/include/tilemap/pass/biome.h new file mode 100644 index 0000000..42363b2 --- /dev/null +++ b/tilemap/include/tilemap/pass/biome.h @@ -0,0 +1,47 @@ +#ifndef ISTD_TILEMAP_PASS_BIOME_H +#define ISTD_TILEMAP_PASS_BIOME_H + +#include "tilemap/generation.h" +#include "tilemap/noise.h" + +namespace istd { + +class BiomeGenerationPass { +private: + const GenerationConfig &config_; + + UniformPerlinNoise temperature_noise_; + UniformPerlinNoise humidity_noise_; + +public: + /** + * @brief Construct a biome generation pass + * @param config Generation configuration parameters + * @param r1 Random number generator for temperature noise + * @param r2 Random number generator for humidity noise + */ + BiomeGenerationPass( + const GenerationConfig &config, Xoroshiro128PP r1, Xoroshiro128PP r2 + ); + + /** + * @brief Generate biomes for the entire tilemap + * @param tilemap The tilemap to generate biomes into + */ + void operator()(TileMap &tilemap); + +private: + /** + * @brief Get climate values at a global position + * @param global_x Global X coordinate + * @param global_y Global Y coordinate + * @return Pair of (temperature, humidity) in range [0,1] + */ + std::pair get_climate( + double global_x, double global_y + ) const; +}; + +} // namespace istd + +#endif diff --git a/tilemap/include/tilemap/pass/deepwater.h b/tilemap/include/tilemap/pass/deepwater.h new file mode 100644 index 0000000..d593e5f --- /dev/null +++ b/tilemap/include/tilemap/pass/deepwater.h @@ -0,0 +1,65 @@ +#ifndef TILEMAP_PASS_DEEPWATER_H +#define TILEMAP_PASS_DEEPWATER_H + +#include "tilemap/tilemap.h" +#include + +namespace istd { + +class DeepwaterGenerationPass { +private: + std::uint32_t deepwater_radius_; + +public: + /** + * @brief Construct a deepwater generation pass + * @param deepwater_radius Radius to check for water tiles around each water + * tile + */ + explicit DeepwaterGenerationPass(std::uint32_t deepwater_radius); + + /** + * @brief Generate deepwater tiles in ocean biomes + * @param tilemap The tilemap to process + */ + void operator()(TileMap &tilemap); + +private: + /** + * @brief Check if a tile position is within a certain radius and all tiles + * are water + * @param tilemap The tilemap to check + * @param center_pos Center position to check around + * @param radius Radius to check within + * @return True if all tiles within radius are water + */ + +private: + /** + * @brief Process an ocean sub-chunk to generate deepwater tiles + * @param tilemap The tilemap to process + * @param chunk_x Chunk X coordinate + * @param chunk_y Chunk Y coordinate + * @param sub_pos Sub-chunk position within the chunk + */ + void process_ocean_subchunk( + TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y, + SubChunkPos sub_pos + ); + + /** + * @brief Check if a tile position is within a certain radius and all tiles + * are water or deepwater + * @param tilemap The tilemap to check + * @param center_pos Center position to check around + * @param radius Radius to check within + * @return True if all tiles within radius are water or deepwater + */ + bool is_surrounded_by_water( + const TileMap &tilemap, TilePos center_pos, std::uint32_t radius + ) const; +}; + +} // namespace istd + +#endif diff --git a/tilemap/include/tilemap/pass/mountain_hole_fill.h b/tilemap/include/tilemap/pass/mountain_hole_fill.h new file mode 100644 index 0000000..728928f --- /dev/null +++ b/tilemap/include/tilemap/pass/mountain_hole_fill.h @@ -0,0 +1,49 @@ +#ifndef ISTD_TILEMAP_PASS_MOUNTAIN_HOLE_FILL_H +#define ISTD_TILEMAP_PASS_MOUNTAIN_HOLE_FILL_H + +#include "tilemap/generation.h" + +namespace istd { + +class MountainHoleFillPass { +private: + const GenerationConfig &config_; + +public: + /** + * @brief Construct a hole fill pass + * @param config Generation configuration parameters + */ + explicit MountainHoleFillPass(const GenerationConfig &config); + + /** + * @brief Fill small holes in the terrain using BFS + * @param tilemap The tilemap to process + */ + void operator()(TileMap &tilemap); + +private: + /** + * @brief Check if a tile type is passable for BFS + * @param type The base tile type to check + * @return True if the tile is passable (not mountain or at boundary) + */ + bool is_passable(BaseTileType type) const; + + /** + * @brief Perform BFS to find connected component size + * @param tilemap The tilemap to search + * @param start_pos Starting position for BFS + * @param visited 2D array tracking visited tiles + * @param positions Output vector of positions in this component + * @return Size of the connected component + */ + std::uint32_t bfs_component_size( + TileMap &tilemap, TilePos start_pos, + std::vector> &visited, std::vector &positions + ); +}; + +} // namespace istd + +#endif diff --git a/tilemap/include/tilemap/pass/oil.h b/tilemap/include/tilemap/pass/oil.h new file mode 100644 index 0000000..ffe6523 --- /dev/null +++ b/tilemap/include/tilemap/pass/oil.h @@ -0,0 +1,72 @@ +#ifndef TILEMAP_PASS_OIL_H +#define TILEMAP_PASS_OIL_H + +#include "tilemap/generation.h" +#include "tilemap/noise.h" + +namespace istd { + +class OilGenerationPass { +private: + const GenerationConfig &config_; + Xoroshiro128PP rng_; + DiscreteRandomNoise noise_; + +public: + /** + * @brief Construct an oil generation pass + * @param config Generation configuration parameters + * @param rng Random number generator for oil placement + * @param noise_rng Random number generator for noise-based operations + */ + OilGenerationPass( + const GenerationConfig &config, Xoroshiro128PP rng, + Xoroshiro128PP noise_rng + ); + + /** + * @brief Generate oil clusters on the tilemap + * @param tilemap The tilemap to process + */ + void operator()(TileMap &tilemap); + +private: + /** + * @brief Generate oil center positions using Poisson disk sampling + * @param tilemap The tilemap to analyze + * @return Vector of positions where oil clusters should be placed + */ + std::vector generate_oil_centers(const TileMap &tilemap); + + /** + * @brief Generate an oil cluster around a center position + * @param tilemap The tilemap to modify + * @param center Center position for the oil cluster + */ + void generate_oil_cluster(TileMap &tilemap, TilePos center); + + /** + * @brief Check if a tile is suitable for oil placement + * @param tilemap The tilemap to check + * @param pos Position to check + * @return True if oil can be placed at this position + */ + bool is_suitable_for_oil(const TileMap &tilemap, TilePos pos) const; + + /** + * @brief Get biome preference multiplier for oil generation (out of 255) + * @param biome The biome type to check + * @return Preference value (0-255) + */ + std::uint8_t get_biome_oil_preference(BiomeType biome) const; + + /** + * @brief Calculate minimum distance between oil fields based on map size + * @return Minimum distance in tiles + */ + std::uint32_t calculate_min_oil_distance() const; +}; + +} // namespace istd + +#endif diff --git a/tilemap/include/tilemap/pass/smoothen_island.h b/tilemap/include/tilemap/pass/smoothen_island.h new file mode 100644 index 0000000..237615b --- /dev/null +++ b/tilemap/include/tilemap/pass/smoothen_island.h @@ -0,0 +1,77 @@ +#ifndef ISTD_TILEMAP_PASS_SMOOTHEN_ISLAND_H +#define ISTD_TILEMAP_PASS_SMOOTHEN_ISLAND_H + +#include "tilemap/generation.h" +#include "tilemap/noise.h" + +namespace istd { + +class SmoothenIslandPass { +private: + const GenerationConfig &config_; + DiscreteRandomNoise noise_; + + /** + * @brief Perform BFS to find connected component size for islands + * @param tilemap The tilemap to search + * @param start_pos Starting position for BFS + * @param visited 2D array tracking visited tiles + * @param positions Output vector of positions in this component + * @return Size of the connected component + */ + std::uint32_t bfs_component_size( + TileMap &tilemap, TilePos start_pos, + std::vector> &visited, std::vector &positions + ); + + /** + * @brief Remove small island components to create smoother terrain + * @param tilemap The tilemap to process + */ + void remove_small_island(TileMap &tilemap); + + /** + * @brief Smoothen islands with cellular automata + * @param tilemap The tilemap to process + */ + void smoothen_islands(TileMap &tilemap, std::uint32_t step_i); + + void smoothen_islands_subchunk( + TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y, + SubChunkPos sub_pos, std::uint32_t step_i, + std::vector> &replacements + ); + + struct CACtx { + BiomeType biome; + std::uint8_t rand; + int adj_land, adj_sand, adj_water; // Adjacent tile counts + }; + + Tile ca_tile(TilePos pos, Tile tile, const CACtx &ctx) const; + + /** + * @brief Check if a tile is part of an island (Land or Sand) + * @param tile The tile to check + * @return True if the tile is Land or Sand + */ + bool is_island_tile(const Tile &tile) const; + +public: + /** + * @brief Construct an island smoothing pass + * @param config Generation configuration parameters + * @param rng Random number generator for terrain replacement + */ + SmoothenIslandPass(const GenerationConfig &config, Xoroshiro128PP rng); + + /** + * @brief Smoothen islands in the terrain + * @param tilemap The tilemap to process + */ + void operator()(TileMap &tilemap); +}; + +} // namespace istd + +#endif diff --git a/tilemap/include/tilemap/pass/smoothen_mountain.h b/tilemap/include/tilemap/pass/smoothen_mountain.h new file mode 100644 index 0000000..56b846c --- /dev/null +++ b/tilemap/include/tilemap/pass/smoothen_mountain.h @@ -0,0 +1,68 @@ +#ifndef ISTD_TILEMAP_PASS_SMOOTHEN_MOUNTAIN_H +#define ISTD_TILEMAP_PASS_SMOOTHEN_MOUNTAIN_H + +#include "tilemap/generation.h" +#include "tilemap/noise.h" + +namespace istd { + +class SmoothenMountainsPass { +private: + const GenerationConfig &config_; + DiscreteRandomNoise noise_; + + /** + * @brief Perform BFS to find connected component size for mountains + * @param tilemap The tilemap to search + * @param start_pos Starting position for BFS + * @param visited 2D array tracking visited tiles + * @param positions Output vector of positions in this component + * @return Size of the connected component + */ + std::uint32_t bfs_component_size( + TileMap &tilemap, TilePos start_pos, + std::vector> &visited, std::vector &positions + ); + + /** + * @brief Replace mountain tiles with terrain types from neighboring areas + * @param tilemap The tilemap to modify + * @param positions Vector of mountain positions to replace + */ + void demountainize(TileMap &tilemap, const std::vector &positions); + + /** + * @brief Remove small mountain components to create smoother terrain + * @param tilemap The tilemap to process + */ + void remove_small_mountain(TileMap &tilemap); + + /** + * @brief Smoothen mountains with cellular automata + * @param tilemap The tilemap to process + */ + void smoothen_mountains(TileMap &tilemap, std::uint32_t step_i); + + void smoothen_mountains_tile( + const TileMap &tilemap, TilePos pos, std::uint32_t step_i, + std::vector> &replacements + ); + +public: + /** + * @brief Construct a mountain smoothing pass + * @param config Generation configuration parameters + * @param rng Random number generator for terrain replacement + */ + SmoothenMountainsPass(const GenerationConfig &config, Xoroshiro128PP rng); + + /** + * @brief Smoothen mountains in the terrain + * @param tilemap The tilemap to process + */ + void operator()(TileMap &tilemap); +}; + +} // namespace istd + +#endif diff --git a/tilemap/include/tile.h b/tilemap/include/tilemap/tile.h similarity index 100% rename from tilemap/include/tile.h rename to tilemap/include/tilemap/tile.h diff --git a/tilemap/include/tilemap.h b/tilemap/include/tilemap/tilemap.h similarity index 98% rename from tilemap/include/tilemap.h rename to tilemap/include/tilemap/tilemap.h index 796ae67..796944b 100644 --- a/tilemap/include/tilemap.h +++ b/tilemap/include/tilemap/tilemap.h @@ -1,7 +1,7 @@ #ifndef ISTD_TILEMAP_TILEMAP_H #define ISTD_TILEMAP_TILEMAP_H -#include "chunk.h" +#include "tilemap/chunk.h" #include #include diff --git a/tilemap/include/xoroshiro.h b/tilemap/include/tilemap/xoroshiro.h similarity index 100% rename from tilemap/include/xoroshiro.h rename to tilemap/include/tilemap/xoroshiro.h diff --git a/tilemap/src/biome.cpp b/tilemap/src/biome.cpp index e0bf84a..01d70a2 100644 --- a/tilemap/src/biome.cpp +++ b/tilemap/src/biome.cpp @@ -1,5 +1,5 @@ -#include "biome.h" -#include "chunk.h" +#include "tilemap/biome.h" +#include "tilemap/chunk.h" #include namespace istd { diff --git a/tilemap/src/chunk.cpp b/tilemap/src/chunk.cpp index d3abae1..ddaa179 100644 --- a/tilemap/src/chunk.cpp +++ b/tilemap/src/chunk.cpp @@ -1,4 +1,4 @@ -#include "chunk.h" +#include "tilemap/chunk.h" #include namespace istd { diff --git a/tilemap/src/generation.cpp b/tilemap/src/generation.cpp index 82a4e1f..f836c23 100644 --- a/tilemap/src/generation.cpp +++ b/tilemap/src/generation.cpp @@ -1,4 +1,4 @@ -#include "generation.h" +#include "tilemap/generation.h" namespace istd { TerrainGenerator::TerrainGenerator(const GenerationConfig &config) diff --git a/tilemap/src/noise.cpp b/tilemap/src/noise.cpp index 6b29a79..594e266 100644 --- a/tilemap/src/noise.cpp +++ b/tilemap/src/noise.cpp @@ -1,4 +1,4 @@ -#include "noise.h" +#include "tilemap/noise.h" #include #include #include diff --git a/tilemap/src/pass/base_tile_type.cpp b/tilemap/src/pass/base_tile_type.cpp index 95acbe5..09891d3 100644 --- a/tilemap/src/pass/base_tile_type.cpp +++ b/tilemap/src/pass/base_tile_type.cpp @@ -1,6 +1,7 @@ -#include "biome.h" -#include "chunk.h" -#include "generation.h" +#include "tilemap/pass/base_tile_type.h" +#include "tilemap/biome.h" +#include "tilemap/chunk.h" +#include "tilemap/generation.h" #include namespace istd { diff --git a/tilemap/src/pass/biome.cpp b/tilemap/src/pass/biome.cpp index 0f89a49..18bc916 100644 --- a/tilemap/src/pass/biome.cpp +++ b/tilemap/src/pass/biome.cpp @@ -1,5 +1,6 @@ -#include "biome.h" -#include "generation.h" +#include "tilemap/biome.h" +#include "tilemap/generation.h" +#include "tilemap/pass/biome.h" namespace istd { diff --git a/tilemap/src/pass/deepwater.cpp b/tilemap/src/pass/deepwater.cpp index b1890c2..32f4f4c 100644 --- a/tilemap/src/pass/deepwater.cpp +++ b/tilemap/src/pass/deepwater.cpp @@ -1,5 +1,6 @@ -#include "biome.h" -#include "generation.h" +#include "tilemap/pass/deepwater.h" +#include "tilemap/biome.h" +#include "tilemap/generation.h" namespace istd { diff --git a/tilemap/src/pass/mountain_hole_fill.cpp b/tilemap/src/pass/mountain_hole_fill.cpp index 59f9fa2..a848779 100644 --- a/tilemap/src/pass/mountain_hole_fill.cpp +++ b/tilemap/src/pass/mountain_hole_fill.cpp @@ -1,4 +1,5 @@ -#include "generation.h" +#include "tilemap/pass/mountain_hole_fill.h" +#include "tilemap/generation.h" #include #include diff --git a/tilemap/src/pass/oil.cpp b/tilemap/src/pass/oil.cpp index ba03cf5..a4fb1dd 100644 --- a/tilemap/src/pass/oil.cpp +++ b/tilemap/src/pass/oil.cpp @@ -1,8 +1,9 @@ -#include "biome.h" -#include "chunk.h" -#include "generation.h" -#include "noise.h" -#include "xoroshiro.h" +#include "tilemap/pass/oil.h" +#include "tilemap/biome.h" +#include "tilemap/chunk.h" +#include "tilemap/generation.h" +#include "tilemap/noise.h" +#include "tilemap/xoroshiro.h" #include #include #include diff --git a/tilemap/src/pass/smoothen_island.cpp b/tilemap/src/pass/smoothen_island.cpp index d5608b2..fc5c6b2 100644 --- a/tilemap/src/pass/smoothen_island.cpp +++ b/tilemap/src/pass/smoothen_island.cpp @@ -1,6 +1,7 @@ -#include "biome.h" -#include "generation.h" -#include "tile.h" +#include "tilemap/pass/smoothen_island.h" +#include "tilemap/biome.h" +#include "tilemap/generation.h" +#include "tilemap/tile.h" #include #include diff --git a/tilemap/src/pass/smoothen_mountain.cpp b/tilemap/src/pass/smoothen_mountain.cpp index ca60ca4..8923aa6 100644 --- a/tilemap/src/pass/smoothen_mountain.cpp +++ b/tilemap/src/pass/smoothen_mountain.cpp @@ -1,4 +1,5 @@ -#include "generation.h" +#include "tilemap/pass/smoothen_mountain.h" +#include "tilemap/generation.h" #include #include #include diff --git a/tilemap/src/tilemap.cpp b/tilemap/src/tilemap.cpp index 20cc62c..ee31995 100644 --- a/tilemap/src/tilemap.cpp +++ b/tilemap/src/tilemap.cpp @@ -1,5 +1,5 @@ -#include "tilemap.h" -#include "chunk.h" +#include "tilemap/tilemap.h" +#include "tilemap/chunk.h" #include namespace istd { diff --git a/tilemap/src/xoroshiro.cpp b/tilemap/src/xoroshiro.cpp index 2a59201..1102de0 100644 --- a/tilemap/src/xoroshiro.cpp +++ b/tilemap/src/xoroshiro.cpp @@ -1,4 +1,4 @@ -#include "xoroshiro.h" +#include "tilemap/xoroshiro.h" #include #include #include @@ -49,8 +49,9 @@ std::uint64_t Xoroshiro128PP::next() { } Xoroshiro128PP Xoroshiro128PP::jump_64() const { - constexpr std::uint64_t JUMP_64[] - = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c}; + constexpr std::uint64_t JUMP_64[] = { + 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c + }; Xoroshiro128PP res{seed}; @@ -68,8 +69,9 @@ Xoroshiro128PP Xoroshiro128PP::jump_64() const { } Xoroshiro128PP Xoroshiro128PP::jump_96() const { - constexpr std::uint64_t JUMP_96[] - = {0x360fd5f2cf8d5d99, 0x9c6e6877736c46e3}; + constexpr std::uint64_t JUMP_96[] = { + 0x360fd5f2cf8d5d99, 0x9c6e6877736c46e3 + }; Xoroshiro128PP res{seed};