feat: add coal generation
Signed-off-by: szdytom <szdytom@qq.com>
This commit is contained in:
parent
1354d9c08a
commit
afc8d8fa1c
@ -4,6 +4,7 @@ cmake_minimum_required(VERSION 3.27)
|
|||||||
set(ISTD_TILEMAP_SRC
|
set(ISTD_TILEMAP_SRC
|
||||||
src/pass/base_tile_type.cpp
|
src/pass/base_tile_type.cpp
|
||||||
src/pass/biome.cpp
|
src/pass/biome.cpp
|
||||||
|
src/pass/coal.cpp
|
||||||
src/pass/deepwater.cpp
|
src/pass/deepwater.cpp
|
||||||
src/pass/mineral_cluster.cpp
|
src/pass/mineral_cluster.cpp
|
||||||
src/pass/mountain_hole_fill.cpp
|
src/pass/mountain_hole_fill.cpp
|
||||||
|
@ -17,7 +17,7 @@ public:
|
|||||||
|
|
||||||
std::uint8_t get_size() const;
|
std::uint8_t get_size() const;
|
||||||
Chunk& get_chunk(std::uint8_t chunk_x, std::uint8_t chunk_y);
|
Chunk& get_chunk(std::uint8_t chunk_x, std::uint8_t chunk_y);
|
||||||
|
|
||||||
Tile& get_tile(TilePos pos);
|
Tile& get_tile(TilePos pos);
|
||||||
const Tile& get_tile(TilePos pos) const;
|
const Tile& get_tile(TilePos pos) const;
|
||||||
void set_tile(TilePos pos, const Tile& tile);
|
void set_tile(TilePos pos, const Tile& tile);
|
||||||
@ -31,10 +31,10 @@ public:
|
|||||||
```cpp
|
```cpp
|
||||||
struct Chunk {
|
struct Chunk {
|
||||||
static constexpr uint8_t size = 64;
|
static constexpr uint8_t size = 64;
|
||||||
|
|
||||||
Tile tiles[size][size];
|
Tile tiles[size][size];
|
||||||
BiomeType biome[16][16]; // Sub-chunk biomes
|
BiomeType biome[16][16]; // Sub-chunk biomes
|
||||||
|
|
||||||
BiomeType& get_biome(SubChunkPos pos);
|
BiomeType& get_biome(SubChunkPos pos);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
@ -62,7 +62,7 @@ struct Tile {
|
|||||||
struct TilePos {
|
struct TilePos {
|
||||||
uint8_t chunk_x, chunk_y; // Chunk coordinates
|
uint8_t chunk_x, chunk_y; // Chunk coordinates
|
||||||
uint8_t local_x, local_y; // Tile within chunk (0-63)
|
uint8_t local_x, local_y; // Tile within chunk (0-63)
|
||||||
|
|
||||||
std::pair<std::uint16_t, std::uint16_t> to_global() const;
|
std::pair<std::uint16_t, std::uint16_t> to_global() const;
|
||||||
static TilePos from_global(std::uint16_t global_x, std::uint16_t global_y);
|
static TilePos from_global(std::uint16_t global_x, std::uint16_t global_y);
|
||||||
};
|
};
|
||||||
@ -81,21 +81,7 @@ Configuration for terrain generation.
|
|||||||
```cpp
|
```cpp
|
||||||
struct GenerationConfig {
|
struct GenerationConfig {
|
||||||
Seed seed;
|
Seed seed;
|
||||||
|
// For more options, see generation.h
|
||||||
// Noise parameters
|
|
||||||
double temperature_scale = 0.05;
|
|
||||||
double humidity_scale = 0.05;
|
|
||||||
double base_scale = 0.08;
|
|
||||||
|
|
||||||
int temperature_octaves = 3;
|
|
||||||
int humidity_octaves = 3;
|
|
||||||
int base_octaves = 3;
|
|
||||||
|
|
||||||
// Oil generation parameters
|
|
||||||
double oil_density = 0.8; // Average oil fields per chunk
|
|
||||||
std::uint32_t oil_cluster_min_size = 2; // Minimum tiles per cluster
|
|
||||||
std::uint32_t oil_cluster_max_size = 6; // Maximum tiles per cluster
|
|
||||||
double oil_biome_preference = 2.0; // Multiplier for preferred biomes
|
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -110,7 +96,7 @@ void map_generate(TileMap& tilemap, const GenerationConfig& config);
|
|||||||
```cpp
|
```cpp
|
||||||
struct Seed {
|
struct Seed {
|
||||||
std::uint64_t s[2];
|
std::uint64_t s[2];
|
||||||
|
|
||||||
static Seed from_string(const char* str);
|
static Seed from_string(const char* str);
|
||||||
static Seed device_random();
|
static Seed device_random();
|
||||||
};
|
};
|
||||||
|
@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.27)
|
|||||||
# Examples for the tilemap library
|
# Examples for the tilemap library
|
||||||
# Each example is built as a separate executable
|
# Each example is built as a separate executable
|
||||||
|
|
||||||
# Biome system demonstration
|
# Tilemap system demonstration
|
||||||
add_executable(tilemap_demo tilemap_demo.cpp)
|
add_executable(tilemap_demo tilemap_demo.cpp)
|
||||||
target_link_libraries(tilemap_demo PRIVATE istd_tilemap)
|
target_link_libraries(tilemap_demo PRIVATE istd_tilemap)
|
||||||
target_include_directories(tilemap_demo PRIVATE ../include)
|
target_include_directories(tilemap_demo PRIVATE ../include)
|
||||||
|
@ -241,6 +241,7 @@ constexpr Color OIL(0, 0, 0); // Black
|
|||||||
constexpr Color HEMATITE(255, 0, 0); // Red
|
constexpr Color HEMATITE(255, 0, 0); // Red
|
||||||
constexpr Color TITANOMAGNETITE(128, 0, 128); // Purple
|
constexpr Color TITANOMAGNETITE(128, 0, 128); // Purple
|
||||||
constexpr Color GIBBSITE(255, 255, 0); // Yellow
|
constexpr Color GIBBSITE(255, 255, 0); // Yellow
|
||||||
|
constexpr Color COAL(64, 64, 64); // Dark gray
|
||||||
} // namespace BmpColors
|
} // namespace BmpColors
|
||||||
|
|
||||||
#endif // BMP_H
|
#endif // BMP_H
|
||||||
|
@ -19,6 +19,8 @@ BmpColors::Color get_tile_color(const istd::Tile &tile) {
|
|||||||
return BmpColors::TITANOMAGNETITE;
|
return BmpColors::TITANOMAGNETITE;
|
||||||
case istd::SurfaceTileType::Gibbsite:
|
case istd::SurfaceTileType::Gibbsite:
|
||||||
return BmpColors::GIBBSITE;
|
return BmpColors::GIBBSITE;
|
||||||
|
case istd::SurfaceTileType::Coal:
|
||||||
|
return BmpColors::COAL;
|
||||||
case istd::SurfaceTileType::Empty:
|
case istd::SurfaceTileType::Empty:
|
||||||
default:
|
default:
|
||||||
break; // Fall through to base tile color
|
break; // Fall through to base tile color
|
||||||
@ -101,6 +103,7 @@ void print_statistics(const istd::TileMap &tilemap) {
|
|||||||
int hematite_count = 0; // Count hematite surface tiles
|
int hematite_count = 0; // Count hematite surface tiles
|
||||||
int titanomagnetite_count = 0; // Count titanomagnetite surface tiles
|
int titanomagnetite_count = 0; // Count titanomagnetite surface tiles
|
||||||
int gibbsite_count = 0; // Count gibbsite surface tiles
|
int gibbsite_count = 0; // Count gibbsite surface tiles
|
||||||
|
int coal_count = 0; // Count coal surface tiles
|
||||||
int mountain_edge_count = 0; // Count mountain edge tiles
|
int mountain_edge_count = 0; // Count mountain edge tiles
|
||||||
const int chunks_per_side = tilemap.get_size();
|
const int chunks_per_side = tilemap.get_size();
|
||||||
const int tiles_per_chunk = istd::Chunk::size;
|
const int tiles_per_chunk = istd::Chunk::size;
|
||||||
@ -128,6 +131,9 @@ void print_statistics(const istd::TileMap &tilemap) {
|
|||||||
case istd::SurfaceTileType::Gibbsite:
|
case istd::SurfaceTileType::Gibbsite:
|
||||||
gibbsite_count++;
|
gibbsite_count++;
|
||||||
break;
|
break;
|
||||||
|
case istd::SurfaceTileType::Coal:
|
||||||
|
coal_count++;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -195,6 +201,7 @@ void print_statistics(const istd::TileMap &tilemap) {
|
|||||||
print_mineral_stats("Hematite", hematite_count);
|
print_mineral_stats("Hematite", hematite_count);
|
||||||
print_mineral_stats("Titanomagnetite", titanomagnetite_count);
|
print_mineral_stats("Titanomagnetite", titanomagnetite_count);
|
||||||
print_mineral_stats("Gibbsite", gibbsite_count);
|
print_mineral_stats("Gibbsite", gibbsite_count);
|
||||||
|
print_mineral_stats("Coal", coal_count);
|
||||||
|
|
||||||
// Mountain edge statistics for mineral context
|
// Mountain edge statistics for mineral context
|
||||||
int mountain_count = tile_counts[static_cast<int>(
|
int mountain_count = tile_counts[static_cast<int>(
|
||||||
|
@ -47,16 +47,24 @@ struct GenerationConfig {
|
|||||||
// of 255)
|
// of 255)
|
||||||
|
|
||||||
// Mineral cluster generation parameters
|
// Mineral cluster generation parameters
|
||||||
std::uint16_t hematite_density = 450; // ~1.8 per chunk (out of 255)
|
std::uint16_t hematite_density = 450; // ~1.8 per chunk (n / 255)
|
||||||
std::uint16_t titanomagnetite_density = 300; // ~1.2 per chunk (out of 255)
|
std::uint16_t titanomagnetite_density = 300; // ~1.2 per chunk (n / 255)
|
||||||
std::uint16_t gibbsite_density = 235; // ~0.9 per chunk (out of 255)
|
std::uint16_t gibbsite_density = 235; // ~0.9 per chunk (n / 255)
|
||||||
|
|
||||||
std::uint8_t mineral_cluster_min_size = 2; // Minimum tiles per mineral
|
std::uint8_t mineral_cluster_min_size = 2; // Minimum tiles per mineral
|
||||||
// cluster
|
// cluster
|
||||||
std::uint8_t mineral_cluster_max_size = 5; // Maximum tiles per mineral
|
std::uint8_t mineral_cluster_max_size = 5; // Maximum tiles per mineral
|
||||||
// cluster
|
// cluster
|
||||||
std::uint8_t mineral_base_probe = 192; // Base probability for mineral
|
std::uint8_t mineral_base_prob = 192; // Base probability for mineral
|
||||||
// placement
|
// placement
|
||||||
|
|
||||||
|
// Coal generation parameters
|
||||||
|
std::uint8_t coal_seeds_per_chunk = 3; // Number of initial coal seeds per
|
||||||
|
// chunk
|
||||||
|
std::uint8_t coal_evolution_steps = 6; // Number of cellular automata
|
||||||
|
// evolution steps
|
||||||
|
std::uint8_t coal_growth_base_prob = 21; // Base probability for coal
|
||||||
|
// growth per neighbor (n / 255)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Terrain generator class that manages the generation process
|
// Terrain generator class that manages the generation process
|
||||||
@ -126,6 +134,12 @@ private:
|
|||||||
* @param tilemap The tilemap to process
|
* @param tilemap The tilemap to process
|
||||||
*/
|
*/
|
||||||
void mineral_cluster_pass(TileMap &tilemap);
|
void mineral_cluster_pass(TileMap &tilemap);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate coal deposits on suitable terrain
|
||||||
|
* @param tilemap The tilemap to process
|
||||||
|
*/
|
||||||
|
void coal_pass(TileMap &tilemap);
|
||||||
};
|
};
|
||||||
/**
|
/**
|
||||||
* @brief Generate a tilemap using the new biome-based system
|
* @brief Generate a tilemap using the new biome-based system
|
||||||
|
86
tilemap/include/tilemap/pass/coal.h
Normal file
86
tilemap/include/tilemap/pass/coal.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#ifndef TILEMAP_PASS_COAL_H
|
||||||
|
#define TILEMAP_PASS_COAL_H
|
||||||
|
|
||||||
|
#include "tilemap/generation.h"
|
||||||
|
#include "tilemap/noise.h"
|
||||||
|
|
||||||
|
namespace istd {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generates coal deposits on suitable terrain using cellular automata
|
||||||
|
*/
|
||||||
|
class CoalGenerationPass {
|
||||||
|
private:
|
||||||
|
const GenerationConfig &config_;
|
||||||
|
Xoroshiro128PP rng_;
|
||||||
|
DiscreteRandomNoise noise_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Construct a coal generation pass
|
||||||
|
* @param config Generation configuration parameters
|
||||||
|
* @param rng Random number generator for coal placement
|
||||||
|
* @param noise_rng Random number generator for noise-based operations
|
||||||
|
*/
|
||||||
|
CoalGenerationPass(
|
||||||
|
const GenerationConfig &config, Xoroshiro128PP rng,
|
||||||
|
Xoroshiro128PP noise_rng
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generate coal deposits using cellular automata
|
||||||
|
* @param tilemap The tilemap to process
|
||||||
|
*/
|
||||||
|
void operator()(TileMap &tilemap);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief Generate initial coal seed points for a chunk
|
||||||
|
* @param tilemap The tilemap to analyze
|
||||||
|
* @param chunk_x Chunk X coordinate
|
||||||
|
* @param chunk_y Chunk Y coordinate
|
||||||
|
* @param seeds Output vector to fill with seed positions
|
||||||
|
*/
|
||||||
|
void chunk_coal_seeds(
|
||||||
|
const TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y,
|
||||||
|
std::vector<TilePos> &seeds
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Evolve coal deposits using cellular automata
|
||||||
|
* @param tilemap The tilemap to modify
|
||||||
|
* @param initial_seeds Initial coal seed positions
|
||||||
|
*/
|
||||||
|
void evolve_coal_deposits(
|
||||||
|
TileMap &tilemap, const std::vector<TilePos> &initial_seeds
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a tile is suitable for coal placement
|
||||||
|
* @param tilemap The tilemap to check
|
||||||
|
* @param pos Position to check
|
||||||
|
* @return True if coal can be placed at this position
|
||||||
|
*/
|
||||||
|
bool is_suitable_for_coal(const TileMap &tilemap, TilePos pos) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the coal growth probability for a specific biome
|
||||||
|
* @param biome The biome type
|
||||||
|
* @return Growth probability multiplier (x / 255)
|
||||||
|
*/
|
||||||
|
std::uint8_t get_biome_coal_growth_probability(BiomeType biome) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Count coal neighbors around a position
|
||||||
|
* @param tilemap The tilemap to check
|
||||||
|
* @param pos Position to check around
|
||||||
|
* @return Number of coal neighbors
|
||||||
|
*/
|
||||||
|
std::uint8_t count_coal_neighbors(
|
||||||
|
const TileMap &tilemap, TilePos pos
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace istd
|
||||||
|
|
||||||
|
#endif // TILEMAP_PASS_COAL_H
|
@ -20,6 +20,7 @@ enum class SurfaceTileType : std::uint8_t {
|
|||||||
Hematite,
|
Hematite,
|
||||||
Titanomagnetite,
|
Titanomagnetite,
|
||||||
Gibbsite,
|
Gibbsite,
|
||||||
|
Coal,
|
||||||
|
|
||||||
// Player built structures
|
// Player built structures
|
||||||
// (not used in generation, but can be placed by player)
|
// (not used in generation, but can be placed by player)
|
||||||
|
@ -13,6 +13,7 @@ void TerrainGenerator::operator()(TileMap &tilemap) {
|
|||||||
deepwater_pass(tilemap);
|
deepwater_pass(tilemap);
|
||||||
oil_pass(tilemap);
|
oil_pass(tilemap);
|
||||||
mineral_cluster_pass(tilemap);
|
mineral_cluster_pass(tilemap);
|
||||||
|
coal_pass(tilemap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_generate(TileMap &tilemap, const GenerationConfig &config) {
|
void map_generate(TileMap &tilemap, const GenerationConfig &config) {
|
||||||
|
207
tilemap/src/pass/coal.cpp
Normal file
207
tilemap/src/pass/coal.cpp
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
#include "tilemap/pass/coal.h"
|
||||||
|
#include "tilemap/biome.h"
|
||||||
|
#include "tilemap/chunk.h"
|
||||||
|
#include "tilemap/generation.h"
|
||||||
|
#include "tilemap/noise.h"
|
||||||
|
#include "tilemap/xoroshiro.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <queue>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace istd {
|
||||||
|
|
||||||
|
CoalGenerationPass::CoalGenerationPass(
|
||||||
|
const GenerationConfig &config, Xoroshiro128PP rng, Xoroshiro128PP noise_rng
|
||||||
|
)
|
||||||
|
: config_(config), rng_(rng), noise_(noise_rng) {}
|
||||||
|
|
||||||
|
void CoalGenerationPass::operator()(TileMap &tilemap) {
|
||||||
|
std::uint8_t map_size = tilemap.get_size();
|
||||||
|
std::vector<TilePos> all_seeds;
|
||||||
|
|
||||||
|
// Generate coal seeds for each chunk
|
||||||
|
for (std::uint8_t chunk_x = 0; chunk_x < map_size; ++chunk_x) {
|
||||||
|
for (std::uint8_t chunk_y = 0; chunk_y < map_size; ++chunk_y) {
|
||||||
|
chunk_coal_seeds(tilemap, chunk_x, chunk_y, all_seeds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evolve coal deposits using cellular automata
|
||||||
|
evolve_coal_deposits(tilemap, all_seeds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoalGenerationPass::chunk_coal_seeds(
|
||||||
|
const TileMap &tilemap, std::uint8_t chunk_x, std::uint8_t chunk_y,
|
||||||
|
std::vector<TilePos> &seeds
|
||||||
|
) {
|
||||||
|
// Use a max heap to keep top N positions by noise value
|
||||||
|
using PosNoisePair = std::pair<std::uint64_t, TilePos>;
|
||||||
|
std::priority_queue<PosNoisePair> heap;
|
||||||
|
|
||||||
|
for (std::uint8_t local_x = 0; local_x < Chunk::size; ++local_x) {
|
||||||
|
for (std::uint8_t local_y = 0; local_y < Chunk::size; ++local_y) {
|
||||||
|
TilePos candidate{chunk_x, chunk_y, local_x, local_y};
|
||||||
|
if (!is_suitable_for_coal(tilemap, candidate)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto [global_x, global_y] = candidate.to_global();
|
||||||
|
auto noise_val = noise_.noise(global_x, global_y, 0x90);
|
||||||
|
|
||||||
|
heap.emplace(noise_val, candidate);
|
||||||
|
if (heap.size() > config_.coal_seeds_per_chunk) {
|
||||||
|
heap.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!heap.empty()) {
|
||||||
|
seeds.push_back(heap.top().second);
|
||||||
|
heap.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CoalGenerationPass::evolve_coal_deposits(
|
||||||
|
TileMap &tilemap, const std::vector<TilePos> &initial_seeds
|
||||||
|
) {
|
||||||
|
// Place initial seeds
|
||||||
|
for (const auto &seed : initial_seeds) {
|
||||||
|
Tile &tile = tilemap.get_tile(seed);
|
||||||
|
if (tile.surface == SurfaceTileType::Empty) {
|
||||||
|
tile.surface = SurfaceTileType::Coal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Evolve using cellular automata
|
||||||
|
for (std::uint8_t step = 1; step <= config_.coal_evolution_steps; ++step) {
|
||||||
|
std::vector<TilePos> new_coal_positions;
|
||||||
|
std::uint8_t map_size = tilemap.get_size();
|
||||||
|
|
||||||
|
// Iterate through all tiles
|
||||||
|
for (std::uint8_t chunk_x = 0; chunk_x < map_size; ++chunk_x) {
|
||||||
|
for (std::uint8_t chunk_y = 0; chunk_y < map_size; ++chunk_y) {
|
||||||
|
const Chunk &chunk = tilemap.get_chunk(chunk_x, chunk_y);
|
||||||
|
|
||||||
|
for (std::uint8_t local_x = 0; local_x < Chunk::size;
|
||||||
|
++local_x) {
|
||||||
|
for (std::uint8_t local_y = 0; local_y < Chunk::size;
|
||||||
|
++local_y) {
|
||||||
|
TilePos pos{chunk_x, chunk_y, local_x, local_y};
|
||||||
|
const Tile &tile = tilemap.get_tile(pos);
|
||||||
|
|
||||||
|
// Skip if not suitable for coal
|
||||||
|
if (!is_suitable_for_coal(tilemap, pos)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip if already has coal
|
||||||
|
if (tile.surface == SurfaceTileType::Coal) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count coal neighbors
|
||||||
|
std::uint8_t coal_neighbors = count_coal_neighbors(
|
||||||
|
tilemap, pos
|
||||||
|
);
|
||||||
|
|
||||||
|
if (coal_neighbors > 0) {
|
||||||
|
// Get biome for this position
|
||||||
|
BiomeType biome = chunk.get_biome(local_x, local_y);
|
||||||
|
auto biome_probability
|
||||||
|
= get_biome_coal_growth_probability(biome);
|
||||||
|
|
||||||
|
// Base probability increases with more coal
|
||||||
|
// neighbors
|
||||||
|
std::uint32_t base_probability = coal_neighbors
|
||||||
|
* config_.coal_growth_base_prob;
|
||||||
|
std::uint8_t final_probability = std::clamp(
|
||||||
|
base_probability * biome_probability / 255, 0u,
|
||||||
|
255u
|
||||||
|
);
|
||||||
|
|
||||||
|
// Use noise to decide whether to grow coal here
|
||||||
|
auto [global_x, global_y] = pos.to_global();
|
||||||
|
std::uint8_t sample = 0xFF
|
||||||
|
& noise_.noise(global_x, global_y, step);
|
||||||
|
|
||||||
|
if (sample < final_probability) {
|
||||||
|
new_coal_positions.push_back(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Place new coal
|
||||||
|
for (const auto &pos : new_coal_positions) {
|
||||||
|
Tile &tile = tilemap.get_tile(pos);
|
||||||
|
if (tile.surface == SurfaceTileType::Empty) {
|
||||||
|
tile.surface = SurfaceTileType::Coal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CoalGenerationPass::is_suitable_for_coal(
|
||||||
|
const TileMap &tilemap, TilePos pos
|
||||||
|
) const {
|
||||||
|
const Tile &tile = tilemap.get_tile(pos);
|
||||||
|
return (tile.base == BaseTileType::Sand || tile.base == BaseTileType::Land)
|
||||||
|
&& tile.surface == SurfaceTileType::Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the coal growth probability for a given biome.
|
||||||
|
// Higher values mean coal is more likely to spread in that biome.
|
||||||
|
std::uint8_t CoalGenerationPass::get_biome_coal_growth_probability(
|
||||||
|
BiomeType biome
|
||||||
|
) const {
|
||||||
|
switch (biome) {
|
||||||
|
case BiomeType::Forest:
|
||||||
|
return 255;
|
||||||
|
case BiomeType::LukeOcean:
|
||||||
|
return 204;
|
||||||
|
case BiomeType::Savanna:
|
||||||
|
return 153;
|
||||||
|
case BiomeType::Plains:
|
||||||
|
return 128;
|
||||||
|
case BiomeType::SnowyPlains:
|
||||||
|
case BiomeType::Ocean:
|
||||||
|
return 102;
|
||||||
|
case BiomeType::SnowyPeeks:
|
||||||
|
return 77;
|
||||||
|
case BiomeType::Desert:
|
||||||
|
return 51;
|
||||||
|
case BiomeType::FrozenOcean:
|
||||||
|
return 26;
|
||||||
|
default:
|
||||||
|
std::unreachable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint8_t CoalGenerationPass::count_coal_neighbors(
|
||||||
|
const TileMap &tilemap, TilePos pos
|
||||||
|
) const {
|
||||||
|
std::uint8_t count = 0;
|
||||||
|
auto neighbors = tilemap.get_neighbors(pos);
|
||||||
|
|
||||||
|
for (const auto neighbor_pos : neighbors) {
|
||||||
|
const Tile &neighbor_tile = tilemap.get_tile(neighbor_pos);
|
||||||
|
if (neighbor_tile.surface == SurfaceTileType::Coal) {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TerrainGenerator::coal_pass(TileMap &tilemap) {
|
||||||
|
auto rng = master_rng_;
|
||||||
|
master_rng_ = master_rng_.jump_96();
|
||||||
|
auto noise_rng = master_rng_;
|
||||||
|
master_rng_ = master_rng_.jump_96();
|
||||||
|
CoalGenerationPass pass(config_, rng, noise_rng);
|
||||||
|
pass(tilemap);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace istd
|
@ -87,7 +87,7 @@ std::vector<TilePos> MineralClusterGenerationPass::generate_mineral_centers(
|
|||||||
mineral_type
|
mineral_type
|
||||||
) // Use mineral type as seed variation
|
) // Use mineral type as seed variation
|
||||||
);
|
);
|
||||||
if (sample < config_.mineral_base_probe) {
|
if (sample < config_.mineral_base_prob) {
|
||||||
centers.push_back(candidate);
|
centers.push_back(candidate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user