# Tilemap Library Developer Guide ## Project Overview The tilemap library is a C++ terrain generation system that creates tile-based worlds with biome support. It uses a multi-pass generation pipeline to create realistic, balanced terrain. ## Project Structure ``` tilemap/ ├── include/ # Public headers │ ├── tilemap.h # Main map container │ ├── chunk.h # 64x64 tile chunks │ ├── tile.h # Individual tile types │ ├── generation.h # Generation system │ ├── biome.h # Biome system │ ├── noise.h # Noise generators │ └── xoroshiro.h # RNG implementation ├── src/ # Implementation files │ ├── tilemap.cpp # TileMap implementation │ ├── chunk.cpp # Chunk utilities │ ├── generation.cpp # Main generation orchestrator │ ├── biome.cpp # Biome mapping logic │ ├── noise.cpp # Noise implementations │ ├── xoroshiro.cpp # Xoroshiro128++ RNG │ └── pass/ # Generation passes │ ├── biome.cpp # Climate-based biome generation │ ├── base_tile_type.cpp # Base terrain generation │ ├── smoothen_mountain.cpp # Mountain smoothing │ ├── smoothen_island.cpp # Island smoothing │ ├── mountain_hole_fill.cpp # Hole filling │ ├── deepwater.cpp # Deep water placement │ ├── oil.cpp # Oil resource generation │ └── mineral_cluster.cpp # Mineral cluster generation ├── examples/ # Usage examples └── docs/ # Documentation ``` ## Core Architecture ### Data Organization The system uses a hierarchical structure: - **TileMap**: n×n grid of chunks - **Chunk**: 64×64 tiles with biome metadata - **Tile**: Individual terrain cell (1 byte packed) Each chunk also contains a 16×16 grid of sub-chunk biomes, providing efficient biome lookup without per-tile storage. ### Pass-Based Generation Terrain generation uses a multi-pass pipeline for modularity and control: 1. **Biome Pass**: Generates climate data and assigns biomes to sub-chunks 2. **Base Tile Type Pass**: Creates base terrain based on biomes 3. **Mountain Smoothing Pass**: Removes isolated mountain clusters 4. **Island Smoothing Pass**: Smooths island coastlines using cellular automata 5. **Hole Fill Pass**: Fills small terrain holes 6. **Deep Water Pass**: Places deep water areas 7. **Oil Pass**: Generates sparse oil deposits as surface features 8. **Mineral Cluster Pass**: Generates mineral clusters (Hematite, Titanomagnetite, Gibbsite) on mountain edges using cellular automata Each pass operates independently with its own RNG state, ensuring deterministic results. ## Terrain Generation Pipeline ### Climate Generation The biome pass uses dual noise generators for temperature and humidity: - Separate Perlin noise for temperature/humidity at sub-chunk resolution - Climate values mapped to 9 biome types in a 3×3 grid - Sub-chunks store biome data for efficient terrain generation ### Noise System The library addresses Perlin noise distribution issues: - **Problem**: Raw Perlin noise has bell-curve distribution - **Solution**: UniformPerlinNoise calibrates distribution to uniform [0,1] - **Result**: Balanced terrain type ratios according to biome properties ### Terrain Generation Process 1. **Climate Sampling**: Sample temperature/humidity at sub-chunk centers 2. **Biome Assignment**: Map climate values to biome types 3. **Terrain Generation**: Generate tiles based on biome properties and noise 4. **Post-processing**: Apply smoothing and hole-filling algorithms ### Connected Component Analysis Several passes use BFS (Breadth-First Search) for terrain analysis: - **Mountain Smoothing**: Find and remove small mountain components - **Island Smoothing**: Apply cellular automata for natural coastlines - **Hole Filling**: Identify and fill isolated terrain holes - Components touching map boundaries are preserved ### Resource Generation The oil generation pass and mineral generation pass creates sparse resource deposits: - **Poisson Disk Sampling**: Ensures minimum distance between oil fields - **Biome Preference**: Higher probability in desert and plains biomes - **Cluster Growth**: Random walk creates larger tile clusters - **Surface Placement**: Oil appears as surface features on land/sand tiles, Minerals on mountain edges ## Random Number Generation ### Xoroshiro128++ Implementation High-quality PRNG with excellent statistical properties: - 128-bit internal state - Period of 2^128 - 1 - Jump functions for parallel generation - STL-compatible interface ### Seed Management 128-bit seeds provide extensive randomness: - String-based deterministic seed creation - Hardware random seed generation - Independent RNG streams for each generation pass ## Biome System ### Climate Mapping Biomes are determined by temperature/humidity combinations: ``` Dry Moderate Wet Cold Snowy Snowy Frozen Peaks Plains Ocean Temp Plains Forest Ocean Hot Desert Savanna Luke Ocean ``` ### Biome Properties Each biome defines terrain generation ratios: - Water/Ice/Sand/Land ratios - Noise parameters (octaves, persistence) - Used by base terrain generation pass ## Performance Considerations ### Memory Layout - Tiles packed into 1 byte (4 bits base + 4 bits surface) - Chunks use contiguous 64×64 arrays for cache efficiency - Sub-chunk biomes reduce memory overhead vs per-tile storage ### Generation Efficiency - Sub-chunk resolution for biome generation (16×16 vs 64×64) - Single-pass algorithms where possible - Efficient connected component analysis using BFS ### Determinism - Same seed produces identical results - Independent RNG streams prevent cross-pass contamination - Floating-point operations use consistent precision ## Adding New Generation Passes To add a new generation pass: 1. **Create Pass Declaration**: Add a header file in `include/tilemap/pass/`, declaring a Pass class (e.g., `MyCustomPass`) that overloads `void operator()(TileMap &tilemap)`. See existing passes for structure and required members. 2. **Create Pass Implementation**: Add the corresponding implementation file in `src/tilemap/pass/`, implementing the declared class and its methods. 3. **Add to Pipeline**: Update `TerrainGenerator::operator()` to invoke your new pass in the desired order. 4. **RNG Management**: Use jump functions to create an independent RNG stream for your pass, ensuring deterministic results. Pass the RNG to your class constructor as needed. 5. **Configuration**: If your pass requires configuration parameters, add them to `GenerationConfig` and pass them to your class. **Example header (include/tilemap/pass/my_custom_pass.h):** ```cpp class MyCustomPass { public: MyCustomPass(const GenerationConfig &config, Xoroshiro128PP rng); void operator()(TileMap &tilemap); // ...other methods as needed... }; ``` **Example implementation (src/tilemap/pass/my_custom_pass.cpp):** ```cpp MyCustomPass::MyCustomPass(const GenerationConfig &config, Xoroshiro128PP rng) : config_(config), rng_(rng) {} void MyCustomPass::operator()(TileMap &tilemap) { // Process tilemap using config_ and rng_ // ...implementation... } ``` **Pipeline integration:** ```cpp void TerrainGenerator::operator()(TileMap &tilemap) { // ...existing passes... MyCustomPass custom_pass(config_, master_rng_.jump_96()); custom_pass(tilemap); // ...other passes... } ``` Refer to existing passes in `include/tilemap/pass/` and `src/tilemap/pass/` for detailed structure, member variables, and best practices.