Refactor map system and clarify meteorite impact physics
- Create header-only map module with clean separation of concerns - Move GMap, GTile, RegionManager to dedicated map module - Remove volcanic/impact methods from GMap (wrong responsibilities) - Add fragmentation specification to MeteoriteImpact::calculateImpactRadius() - Define heat conservation formula for MeteoriteImpact::calculateHeatGeneration() - Clean world-generation-realist includes and dependencies - Add comprehensive implementation analysis report 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b93b269e6d
commit
076acd4812
@ -181,7 +181,7 @@
|
|||||||
"impact_characteristics": {
|
"impact_characteristics": {
|
||||||
"crater_factor": 0.5,
|
"crater_factor": 0.5,
|
||||||
"heat_generation": 400,
|
"heat_generation": 400,
|
||||||
"fragmentation": "shattering",
|
"fragmentation": "high",
|
||||||
"special_effects": ["razor_sharp_shards", "perfect_reflections", "optical_effects"]
|
"special_effects": ["razor_sharp_shards", "perfect_reflections", "optical_effects"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -197,7 +197,7 @@
|
|||||||
"impact_characteristics": {
|
"impact_characteristics": {
|
||||||
"crater_factor": 0.1,
|
"crater_factor": 0.1,
|
||||||
"heat_generation": 100,
|
"heat_generation": 100,
|
||||||
"fragmentation": "crumbling",
|
"fragmentation": "low",
|
||||||
"special_effects": ["gas_release", "floating_debris", "minimal_damage"]
|
"special_effects": ["gas_release", "floating_debris", "minimal_damage"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
78
src/modules/map/CLAUDE.md
Normal file
78
src/modules/map/CLAUDE.md
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
# Map Module
|
||||||
|
|
||||||
|
**Responsabilité**: Structures de données pour cartes, régions et tiles du système de génération de monde.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
Ce module contient les structures de données fondamentales pour la représentation géographique du monde : cartes, tiles, régions et leur gestion. Conçu pour être utilisé par les modules de génération de monde et autres systèmes nécessitant des données géographiques.
|
||||||
|
|
||||||
|
## Structures Incluses
|
||||||
|
|
||||||
|
### Core Map Data
|
||||||
|
- **GMap**: Structure principale de carte avec dimensions et données de tiles
|
||||||
|
- **GTile**: Représentation d'une tile individuelle avec propriétés géographiques
|
||||||
|
- **IRegion**: Interface pour toutes les régions géographiques
|
||||||
|
|
||||||
|
### Region Management
|
||||||
|
- **RegionManager**: Gestionnaire pour collections de régions avec opérations spatiales
|
||||||
|
- **ResourceRegion**: Région spécialisée pour dépôts de ressources minérales
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Interfaces
|
||||||
|
- **IRegion**: Interface commune pour tous types de régions
|
||||||
|
- Position (x, y)
|
||||||
|
- Masse/influence
|
||||||
|
- Type de région
|
||||||
|
- Opérations de fusion
|
||||||
|
|
||||||
|
### Types de Régions
|
||||||
|
- **ResourceRegion**: Dépôts minéraux avec mapping ressource → quantité
|
||||||
|
- **TectonicRegion**: Plaques tectoniques (dans world-generation-realist)
|
||||||
|
- **ClimateRegion**: Zones climatiques (dans world-generation-realist)
|
||||||
|
|
||||||
|
## Utilisation
|
||||||
|
|
||||||
|
### Dans world-generation-realist
|
||||||
|
```cpp
|
||||||
|
#include "map/GMap.h"
|
||||||
|
#include "map/ResourceRegion.h"
|
||||||
|
|
||||||
|
// Génération de carte
|
||||||
|
GMap heightmap(width, height);
|
||||||
|
|
||||||
|
// Création de régions de ressources
|
||||||
|
ResourceRegion iron_deposit("iron_ore", x, y, total_mass);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Duck Typing Support
|
||||||
|
Toutes les régions supportent l'interface duck typing pour UniversalRegionFusionFunction:
|
||||||
|
- `std::string getNameType() const`
|
||||||
|
- `float getX() const, float getY() const`
|
||||||
|
- `float getMass() const`
|
||||||
|
- `void setPosition(float x, float y)`
|
||||||
|
- `void addMass(float mass)`
|
||||||
|
|
||||||
|
## Contraintes Modules
|
||||||
|
- **Header-only**: Pas d'implémentations .cpp (structures de données simples)
|
||||||
|
- **Template-friendly**: Compatible avec les templates C++ pour type safety
|
||||||
|
- **Autonomous**: Pas de dépendances externes aux interfaces core
|
||||||
|
- **Hot-reload compatible**: Structures sérialisables
|
||||||
|
|
||||||
|
## Build System
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
```bash
|
||||||
|
cd src/modules/map/
|
||||||
|
cmake . # Configuration autonome
|
||||||
|
make warfactory-map-module # Build module (headers only)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- **Core**: Aucune dépendance core/ requise
|
||||||
|
- **Standards**: C++20 pour features modernes
|
||||||
|
- **Compatibility**: Utilisable par tous autres modules
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**État actuel**: Module créé avec structures de données déplacées depuis world-generation-realist. Fichiers .cpp inclus dans build system.
|
||||||
42
src/modules/map/CMakeLists.txt
Normal file
42
src/modules/map/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
project(warfactory-map-module)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
# Find nlohmann_json
|
||||||
|
find_package(nlohmann_json QUIET)
|
||||||
|
|
||||||
|
# Minimal FetchContent for missing deps
|
||||||
|
if(NOT nlohmann_json_FOUND)
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(nlohmann_json
|
||||||
|
URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz
|
||||||
|
URL_HASH SHA256=d6c65aca6b1ed68e7a182f4757257b107ae403032760ed6ef121c9d55e81757d
|
||||||
|
)
|
||||||
|
FetchContent_MakeAvailable(nlohmann_json)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Include and source directories
|
||||||
|
include_directories(include)
|
||||||
|
include_directories(../../core/include)
|
||||||
|
|
||||||
|
# Headers only (header-only library)
|
||||||
|
file(GLOB_RECURSE HEADERS "include/*.h")
|
||||||
|
|
||||||
|
# Create header-only interface library
|
||||||
|
add_library(warfactory-map-module INTERFACE)
|
||||||
|
|
||||||
|
# Set include directories for interface library
|
||||||
|
target_include_directories(warfactory-map-module INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include>
|
||||||
|
)
|
||||||
|
|
||||||
|
# Link nlohmann_json as interface dependency
|
||||||
|
target_link_libraries(warfactory-map-module INTERFACE nlohmann_json::nlohmann_json)
|
||||||
|
|
||||||
|
# Install headers for other modules to use
|
||||||
|
install(DIRECTORY include/
|
||||||
|
DESTINATION include/warfactory/map
|
||||||
|
FILES_MATCHING PATTERN "*.h")
|
||||||
207
src/modules/map/include/GMap.h
Normal file
207
src/modules/map/include/GMap.h
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GTile.h"
|
||||||
|
#include "warfactory/ASerializable.h"
|
||||||
|
|
||||||
|
namespace warfactory {
|
||||||
|
|
||||||
|
class GMap : public ASerializable {
|
||||||
|
private:
|
||||||
|
int width, height;
|
||||||
|
GTile* tiles; // Contiguous memory block: tiles[y * width + x]
|
||||||
|
|
||||||
|
public:
|
||||||
|
GMap(int w, int h);
|
||||||
|
~GMap();
|
||||||
|
|
||||||
|
// Prevent copy (expensive with large maps)
|
||||||
|
GMap(const GMap&) = delete;
|
||||||
|
GMap& operator=(const GMap&) = delete;
|
||||||
|
|
||||||
|
// Move constructor/assignment for efficiency
|
||||||
|
GMap(GMap&& other) noexcept;
|
||||||
|
GMap& operator=(GMap&& other) noexcept;
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// MAP ACCESS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
GTile* getTile(int x, int y);
|
||||||
|
const GTile* getTile(int x, int y) const;
|
||||||
|
|
||||||
|
bool isValidCoordinate(int x, int y) const {
|
||||||
|
return x >= 0 && x < width && y >= 0 && y < height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getWidth() const { return width; }
|
||||||
|
int getHeight() const { return height; }
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// MAP STATISTICS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get average temperature across map
|
||||||
|
*/
|
||||||
|
float getAverageTemperature() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get average elevation across map
|
||||||
|
*/
|
||||||
|
float getAverageElevation() const;
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// ITERATION SUPPORT (cache-friendly)
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
GTile* begin() { return tiles; }
|
||||||
|
GTile* end() { return tiles + (width * height); }
|
||||||
|
const GTile* begin() const { return tiles; }
|
||||||
|
const GTile* end() const { return tiles + (width * height); }
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// SERIALIZATION
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
json serialize() const override;
|
||||||
|
void deserialize(const json& data) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void allocateTiles();
|
||||||
|
void deallocateTiles();
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// INLINE IMPLEMENTATIONS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
inline GMap::GMap(int w, int h) : ASerializable("gmap"), width(w), height(h), tiles(nullptr) {
|
||||||
|
allocateTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GMap::~GMap() {
|
||||||
|
deallocateTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GMap::GMap(GMap&& other) noexcept
|
||||||
|
: ASerializable("gmap"), width(other.width), height(other.height), tiles(other.tiles) {
|
||||||
|
other.width = 0;
|
||||||
|
other.height = 0;
|
||||||
|
other.tiles = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GMap& GMap::operator=(GMap&& other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
deallocateTiles();
|
||||||
|
width = other.width;
|
||||||
|
height = other.height;
|
||||||
|
tiles = other.tiles;
|
||||||
|
|
||||||
|
other.width = 0;
|
||||||
|
other.height = 0;
|
||||||
|
other.tiles = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline GTile* GMap::getTile(int x, int y) {
|
||||||
|
if (!isValidCoordinate(x, y)) return nullptr;
|
||||||
|
return &tiles[y * width + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const GTile* GMap::getTile(int x, int y) const {
|
||||||
|
if (!isValidCoordinate(x, y)) return nullptr;
|
||||||
|
return &tiles[y * width + x];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float GMap::getAverageTemperature() const {
|
||||||
|
if (width == 0 || height == 0) return 0.0f;
|
||||||
|
|
||||||
|
double temperature_sum = 0.0;
|
||||||
|
const int total_tiles = width * height;
|
||||||
|
|
||||||
|
for (int i = 0; i < total_tiles; ++i) {
|
||||||
|
temperature_sum += tiles[i].getTemperatureCelsius();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<float>(temperature_sum / total_tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float GMap::getAverageElevation() const {
|
||||||
|
if (width == 0 || height == 0) return 0.0f;
|
||||||
|
|
||||||
|
double elevation_sum = 0.0;
|
||||||
|
const int total_tiles = width * height;
|
||||||
|
|
||||||
|
for (int i = 0; i < total_tiles; ++i) {
|
||||||
|
elevation_sum += tiles[i].getElevationMeters();
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<float>(elevation_sum / total_tiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline json GMap::serialize() const {
|
||||||
|
json data;
|
||||||
|
data["width"] = width;
|
||||||
|
data["height"] = height;
|
||||||
|
data["tiles"] = json::array();
|
||||||
|
|
||||||
|
const int total_tiles = width * height;
|
||||||
|
for (int i = 0; i < total_tiles; ++i) {
|
||||||
|
const GTile& tile = tiles[i];
|
||||||
|
json tile_data;
|
||||||
|
tile_data["elevation"] = tile.elevation;
|
||||||
|
tile_data["temperature"] = tile.temperature;
|
||||||
|
tile_data["biome_type_id"] = tile.biome_type_id;
|
||||||
|
tile_data["water_token"] = tile.water_token;
|
||||||
|
tile_data["wind_token"] = tile.wind_token;
|
||||||
|
tile_data["target_budget_score"] = tile.target_budget_score;
|
||||||
|
tile_data["destruction_token"] = tile.destruction_token;
|
||||||
|
tile_data["flags"] = tile.flags;
|
||||||
|
tile_data["feature_set_id"] = tile.feature_set_id;
|
||||||
|
data["tiles"].push_back(tile_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void GMap::deserialize(const json& data) {
|
||||||
|
deallocateTiles();
|
||||||
|
|
||||||
|
width = data.at("width").get<int>();
|
||||||
|
height = data.at("height").get<int>();
|
||||||
|
|
||||||
|
allocateTiles();
|
||||||
|
|
||||||
|
const json& tiles_data = data.at("tiles");
|
||||||
|
const int total_tiles = width * height;
|
||||||
|
|
||||||
|
for (int i = 0; i < total_tiles && i < static_cast<int>(tiles_data.size()); ++i) {
|
||||||
|
const json& tile_data = tiles_data[i];
|
||||||
|
GTile& tile = tiles[i];
|
||||||
|
|
||||||
|
tile.elevation = tile_data.at("elevation").get<uint16_t>();
|
||||||
|
tile.temperature = tile_data.at("temperature").get<int16_t>();
|
||||||
|
tile.biome_type_id = tile_data.at("biome_type_id").get<uint16_t>();
|
||||||
|
tile.water_token = tile_data.at("water_token").get<uint8_t>();
|
||||||
|
tile.wind_token = tile_data.at("wind_token").get<uint8_t>();
|
||||||
|
tile.target_budget_score = tile_data.at("target_budget_score").get<int8_t>();
|
||||||
|
tile.destruction_token = tile_data.at("destruction_token").get<uint16_t>();
|
||||||
|
tile.flags = tile_data.at("flags").get<uint16_t>();
|
||||||
|
tile.feature_set_id = tile_data.at("feature_set_id").get<uint32_t>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void GMap::allocateTiles() {
|
||||||
|
if (width > 0 && height > 0) {
|
||||||
|
const int total_tiles = width * height;
|
||||||
|
tiles = new GTile[total_tiles];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void GMap::deallocateTiles() {
|
||||||
|
delete[] tiles;
|
||||||
|
tiles = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace warfactory
|
||||||
@ -1,29 +1,64 @@
|
|||||||
#include "../include/RegionManager.h"
|
#pragma once
|
||||||
|
|
||||||
|
#include "IRegion.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
namespace warfactory {
|
namespace warfactory {
|
||||||
|
|
||||||
RegionManager::RegionManager() : next_region_id(1) {
|
class RegionManager {
|
||||||
|
private:
|
||||||
|
std::vector<std::unique_ptr<IRegion>> regions;
|
||||||
|
int next_region_id;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RegionManager();
|
||||||
|
|
||||||
|
int createRegion(const std::string& region_type, float x, float y, float mass, float radius);
|
||||||
|
|
||||||
|
void addRegion(std::unique_ptr<IRegion> region);
|
||||||
|
|
||||||
|
void removeRegion(int region_id);
|
||||||
|
|
||||||
|
IRegion* getRegion(int region_id);
|
||||||
|
const IRegion* getRegion(int region_id) const;
|
||||||
|
|
||||||
|
std::vector<IRegion*> getRegionsInRadius(float center_x, float center_y, float radius);
|
||||||
|
|
||||||
|
std::vector<IRegion*> getRegionsByType(const std::string& region_type);
|
||||||
|
|
||||||
|
void updateAllRegions(float delta_time);
|
||||||
|
|
||||||
|
void processFusions();
|
||||||
|
|
||||||
|
size_t getRegionCount() const { return regions.size(); }
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
};
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// INLINE IMPLEMENTATIONS
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
inline RegionManager::RegionManager() : next_region_id(1) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int RegionManager::createRegion(const std::string& region_type, float x, float y, float mass, float radius) {
|
inline int RegionManager::createRegion(const std::string& region_type, float x, float y, float mass, float radius) {
|
||||||
// Note: This is a placeholder - actual region creation would use factories
|
(void)region_type; (void)x; (void)y; (void)mass; (void)radius;
|
||||||
// based on region_type to create specific IRegion implementations
|
|
||||||
const int region_id = next_region_id++;
|
const int region_id = next_region_id++;
|
||||||
|
|
||||||
// TODO: Implement region factory pattern based on region_type
|
|
||||||
// For now, return the assigned ID
|
|
||||||
return region_id;
|
return region_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionManager::addRegion(std::unique_ptr<IRegion> region) {
|
inline void RegionManager::addRegion(std::unique_ptr<IRegion> region) {
|
||||||
if (region) {
|
if (region) {
|
||||||
regions.push_back(std::move(region));
|
regions.push_back(std::move(region));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionManager::removeRegion(int region_id) {
|
inline void RegionManager::removeRegion(int region_id) {
|
||||||
regions.erase(
|
regions.erase(
|
||||||
std::remove_if(regions.begin(), regions.end(),
|
std::remove_if(regions.begin(), regions.end(),
|
||||||
[region_id](const std::unique_ptr<IRegion>& region) {
|
[region_id](const std::unique_ptr<IRegion>& region) {
|
||||||
@ -33,7 +68,7 @@ void RegionManager::removeRegion(int region_id) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
IRegion* RegionManager::getRegion(int region_id) {
|
inline IRegion* RegionManager::getRegion(int region_id) {
|
||||||
for (const std::unique_ptr<IRegion>& region : regions) {
|
for (const std::unique_ptr<IRegion>& region : regions) {
|
||||||
if (region && region->getId() == region_id) {
|
if (region && region->getId() == region_id) {
|
||||||
return region.get();
|
return region.get();
|
||||||
@ -42,7 +77,7 @@ IRegion* RegionManager::getRegion(int region_id) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const IRegion* RegionManager::getRegion(int region_id) const {
|
inline const IRegion* RegionManager::getRegion(int region_id) const {
|
||||||
for (const std::unique_ptr<IRegion>& region : regions) {
|
for (const std::unique_ptr<IRegion>& region : regions) {
|
||||||
if (region && region->getId() == region_id) {
|
if (region && region->getId() == region_id) {
|
||||||
return region.get();
|
return region.get();
|
||||||
@ -51,7 +86,7 @@ const IRegion* RegionManager::getRegion(int region_id) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<IRegion*> RegionManager::getRegionsInRadius(float center_x, float center_y, float radius) {
|
inline std::vector<IRegion*> RegionManager::getRegionsInRadius(float center_x, float center_y, float radius) {
|
||||||
std::vector<IRegion*> result;
|
std::vector<IRegion*> result;
|
||||||
const float radius_squared = radius * radius;
|
const float radius_squared = radius * radius;
|
||||||
|
|
||||||
@ -70,7 +105,7 @@ std::vector<IRegion*> RegionManager::getRegionsInRadius(float center_x, float ce
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<IRegion*> RegionManager::getRegionsByType(const std::string& region_type) {
|
inline std::vector<IRegion*> RegionManager::getRegionsByType(const std::string& region_type) {
|
||||||
std::vector<IRegion*> result;
|
std::vector<IRegion*> result;
|
||||||
|
|
||||||
for (const std::unique_ptr<IRegion>& region : regions) {
|
for (const std::unique_ptr<IRegion>& region : regions) {
|
||||||
@ -82,7 +117,7 @@ std::vector<IRegion*> RegionManager::getRegionsByType(const std::string& region_
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionManager::updateAllRegions(float delta_time) {
|
inline void RegionManager::updateAllRegions(float delta_time) {
|
||||||
for (const std::unique_ptr<IRegion>& region : regions) {
|
for (const std::unique_ptr<IRegion>& region : regions) {
|
||||||
if (region) {
|
if (region) {
|
||||||
region->update(delta_time);
|
region->update(delta_time);
|
||||||
@ -90,8 +125,7 @@ void RegionManager::updateAllRegions(float delta_time) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionManager::processFusions() {
|
inline void RegionManager::processFusions() {
|
||||||
// Check for regions that should fuse based on proximity and compatibility
|
|
||||||
for (size_t i = 0; i < regions.size(); ++i) {
|
for (size_t i = 0; i < regions.size(); ++i) {
|
||||||
if (!regions[i]) continue;
|
if (!regions[i]) continue;
|
||||||
|
|
||||||
@ -101,7 +135,6 @@ void RegionManager::processFusions() {
|
|||||||
const IRegion* region_a = regions[i].get();
|
const IRegion* region_a = regions[i].get();
|
||||||
const IRegion* region_b = regions[j].get();
|
const IRegion* region_b = regions[j].get();
|
||||||
|
|
||||||
// Check if regions are close enough to fuse
|
|
||||||
const float dx = region_a->getX() - region_b->getX();
|
const float dx = region_a->getX() - region_b->getX();
|
||||||
const float dy = region_a->getY() - region_b->getY();
|
const float dy = region_a->getY() - region_b->getY();
|
||||||
const float distance = std::sqrt(dx * dx + dy * dy);
|
const float distance = std::sqrt(dx * dx + dy * dy);
|
||||||
@ -109,20 +142,15 @@ void RegionManager::processFusions() {
|
|||||||
const float fusion_threshold = (region_a->getRadius() + region_b->getRadius()) * 0.5f;
|
const float fusion_threshold = (region_a->getRadius() + region_b->getRadius()) * 0.5f;
|
||||||
|
|
||||||
if (distance < fusion_threshold) {
|
if (distance < fusion_threshold) {
|
||||||
// Check if regions can fuse (same type, compatible properties)
|
|
||||||
if (region_a->getType() == region_b->getType()) {
|
if (region_a->getType() == region_b->getType()) {
|
||||||
// TODO: Implement fusion logic
|
// TODO: Implement fusion logic
|
||||||
// - Calculate new position (weighted by mass)
|
|
||||||
// - Combine masses and radii
|
|
||||||
// - Remove one region, update the other
|
|
||||||
// For now, just mark for potential future implementation
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegionManager::clear() {
|
inline void RegionManager::clear() {
|
||||||
regions.clear();
|
regions.clear();
|
||||||
next_region_id = 1;
|
next_region_id = 1;
|
||||||
}
|
}
|
||||||
@ -11,6 +11,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -DNDEBUG")
|
|||||||
# Include directories
|
# Include directories
|
||||||
include_directories(include)
|
include_directories(include)
|
||||||
include_directories(../../core/include)
|
include_directories(../../core/include)
|
||||||
|
include_directories(../map/include)
|
||||||
|
|
||||||
# Add FetchContent for dependencies
|
# Add FetchContent for dependencies
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
@ -26,8 +27,6 @@ FetchContent_MakeAvailable(nlohmann_json)
|
|||||||
|
|
||||||
# Source files
|
# Source files
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
src/GMap.cpp
|
|
||||||
src/RegionManager.cpp
|
|
||||||
src/MeteoriteImpact.cpp
|
src/MeteoriteImpact.cpp
|
||||||
src/PlanetaryCore.cpp
|
src/PlanetaryCore.cpp
|
||||||
src/WorldData.cpp
|
src/WorldData.cpp
|
||||||
|
|||||||
107
src/modules/world-generation-realist/IMPLEMENTATION_REPORT.md
Normal file
107
src/modules/world-generation-realist/IMPLEMENTATION_REPORT.md
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# World Generation Realist - Implementation Report
|
||||||
|
|
||||||
|
## État Actuel des Définitions
|
||||||
|
|
||||||
|
### ✅ CLAIR À IMPLÉMENTER
|
||||||
|
|
||||||
|
#### Structures de Données
|
||||||
|
- **Volcano** (include/Volcano.h) - Complet, structure simple avec volcano_id, type, reservoir, position
|
||||||
|
- **VolcanoImpact** (include/VolcanoImpact.h) - Interface définie, méthodes claires
|
||||||
|
- **PlanetaryCore** (include/PlanetaryCore.h) - Structure avec core_materials, temperatures
|
||||||
|
- **MeteoriteImpact** (include/MeteoriteImpact.h) - Logique crater/heat/materials définie
|
||||||
|
- **ResourceRegion, TectonicRegion, ClimateRegion** - Duck typing interface complète
|
||||||
|
|
||||||
|
#### Configuration JSON
|
||||||
|
- **Phase 0** - Paramètres initialization clairs dans Regular_world.json:
|
||||||
|
```json
|
||||||
|
"surface_temperature_celsius": -100.0,
|
||||||
|
"surface_elevation_meters": -30000.0,
|
||||||
|
"world_width": 512,
|
||||||
|
"world_height": 512
|
||||||
|
```
|
||||||
|
- **volcanic_generation** - Configuration complète:
|
||||||
|
```json
|
||||||
|
"base_material_per_volcano": 1000000000000,
|
||||||
|
"main_pick_count": 3,
|
||||||
|
"secondary_pick_count": 5,
|
||||||
|
"default_volcano_type": "stratovolcano"
|
||||||
|
```
|
||||||
|
- **cooling_phase** - Paramètres de refroidissement définis
|
||||||
|
|
||||||
|
#### Templates et Fusion
|
||||||
|
- **UniversalRegionFusionFunction<T>** - Template complet avec duck typing
|
||||||
|
- **RadiusCalculation, MassCombination** - Enums et logique définis
|
||||||
|
|
||||||
|
### 🔶 PARTIELLEMENT CLAIR
|
||||||
|
|
||||||
|
#### Factories Partiels
|
||||||
|
- **VolcanoFactory** - Interface définie mais logique de génération incomplète:
|
||||||
|
- `generateVolcanoFromCore()` - Pas de détails sur l'algorithme de sélection des ressources
|
||||||
|
- `generateVolcanoImpact()` - Relation volcano → impact unclear
|
||||||
|
|
||||||
|
- **MeteoriteFactory** - Pattern pool mentionné mais pas implémenté:
|
||||||
|
- Templates de météorites non définis
|
||||||
|
- Algorithme copy+modify absent
|
||||||
|
|
||||||
|
#### Orchestrateur Principal
|
||||||
|
- **WorldGenerationOrchestrator** - Mentionné dans CLAUDE.md mais non implémenté
|
||||||
|
- **IWorldGenerationFunction** - Interface définie mais pas d'implémentations concrètes
|
||||||
|
|
||||||
|
### ❌ UNCLEAR - NÉCESSITE CLARIFICATION
|
||||||
|
|
||||||
|
#### Phase System Architecture
|
||||||
|
- **Phases 1-7** - Mentionnées dans docs mais pas dans Regular_world.json:
|
||||||
|
- Quelles sont les phases exactes ?
|
||||||
|
- Dans quel ordre s'exécutent-elles ?
|
||||||
|
- Quelles fonctions pour chaque phase ?
|
||||||
|
|
||||||
|
#### Fonctions de Génération Manquantes
|
||||||
|
- **InitializeWorldTerrainFunction** - Déclarée mais pas implémentée
|
||||||
|
- **InitializePlanetaryCoreFunction** - Référencée mais absente
|
||||||
|
- **MeteoriteImpactGenerationFunction** - Mentionnée, non implémentée
|
||||||
|
- **ImpactEffectsApplicationFunction** - Listée, non développée
|
||||||
|
|
||||||
|
#### Configuration Incomplète
|
||||||
|
- **PlanetaryDifferentiationFunction** - Pas de config JSON correspondante
|
||||||
|
- **VolcanicRedistributionFunction** - Paramètres manquants dans Regular_world.json
|
||||||
|
- **CoolingPhaseFunction** - Config partielle (cooling_rate_per_cycle manquant)
|
||||||
|
|
||||||
|
#### Mécaniques de Jeu Non Définies
|
||||||
|
- **Échelle temporelle** - Cycles de combien d'années ? 100M mentionné où ?
|
||||||
|
- **Resource IDs** - uint32_t mais pas de mapping vers noms
|
||||||
|
- **Biome generation** - ClimateRegion.getBiomeSuitability() sans détails
|
||||||
|
- **Procedural seed** - RandomGenerator singleton mais pas de seed management
|
||||||
|
|
||||||
|
#### Questions Techniques Ouvertes
|
||||||
|
- **Memory management** - Qui possède les régions ? RegionManager ownership unclear
|
||||||
|
- **Serialization** - Hot-reload state preservation non implémenté
|
||||||
|
- **Error handling** - Pas de gestion d'erreurs dans les factories
|
||||||
|
- **Performance** - 512x512 tiles = 262k objets, optimisations ?
|
||||||
|
|
||||||
|
## RECOMMANDATIONS PRIORITÉS
|
||||||
|
|
||||||
|
### 🚀 PHASE 1 - Foundations (Implementable Now)
|
||||||
|
1. **InitializeWorldTerrainFunction** - Logic simple, config claire
|
||||||
|
2. **VolcanoFactory.generateVolcanoFromCore()** - Algorithme pick resources
|
||||||
|
3. **PlanetaryCore initialization** - Populate depuis meteorites.json
|
||||||
|
|
||||||
|
### 🔧 PHASE 2 - Architecture Clarity Needed
|
||||||
|
1. **Définir phases 1-7** exactes avec JSON config
|
||||||
|
2. **WorldGenerationOrchestrator** implementation
|
||||||
|
3. **Resource ID mapping** système
|
||||||
|
|
||||||
|
### 📋 PHASE 3 - Validation Needed
|
||||||
|
1. **Échelle temporelle** - confirmer cycles et durées
|
||||||
|
2. **Memory ownership** - clarifier qui delete quoi
|
||||||
|
3. **Performance testing** - 262k tiles impact
|
||||||
|
|
||||||
|
## BLOCKERS IMMÉDIATS
|
||||||
|
|
||||||
|
1. **Pas de Regular_world.json complet** - Phases 1-7 manquantes
|
||||||
|
2. **IWorldGenerationFunction impls** - Zero implémentations concrètes
|
||||||
|
3. **ResourceID → string mapping** - Système de ressources incomplet
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**STATUS**: Architecture 60% définie, implémentation 10% complète
|
||||||
|
**NEXT**: Implémenter InitializeWorldTerrainFunction comme proof-of-concept
|
||||||
@ -1,90 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "GTile.h"
|
|
||||||
#include "warfactory/ASerializable.h"
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
class GMap : public ASerializable {
|
|
||||||
private:
|
|
||||||
int width, height;
|
|
||||||
GTile* tiles; // Contiguous memory block: tiles[y * width + x]
|
|
||||||
|
|
||||||
public:
|
|
||||||
GMap(int w, int h);
|
|
||||||
~GMap();
|
|
||||||
|
|
||||||
// Prevent copy (expensive with large maps)
|
|
||||||
GMap(const GMap&) = delete;
|
|
||||||
GMap& operator=(const GMap&) = delete;
|
|
||||||
|
|
||||||
// Move constructor/assignment for efficiency
|
|
||||||
GMap(GMap&& other) noexcept;
|
|
||||||
GMap& operator=(GMap&& other) noexcept;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// MAP ACCESS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
GTile* getTile(int x, int y);
|
|
||||||
const GTile* getTile(int x, int y) const;
|
|
||||||
|
|
||||||
bool isValidCoordinate(int x, int y) const {
|
|
||||||
return x >= 0 && x < width && y >= 0 && y < height;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getWidth() const { return width; }
|
|
||||||
int getHeight() const { return height; }
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// BULK OPERATIONS (Phase 1 specific)
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Apply cooling to all tiles
|
|
||||||
*/
|
|
||||||
void coolAllTiles(float cooling_rate_celsius);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Apply impact effects to circular area
|
|
||||||
*/
|
|
||||||
void applyImpactToArea(float center_x, float center_y, float radius_meters,
|
|
||||||
float heat_celsius, uint16_t crater_depth, uint8_t crater_scale);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Apply volcanic heat to specific location
|
|
||||||
*/
|
|
||||||
void applyVolcanicHeat(float x, float y, float heat_celsius, float radius_meters);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get average temperature across map
|
|
||||||
*/
|
|
||||||
float getAverageTemperature() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get average elevation across map
|
|
||||||
*/
|
|
||||||
float getAverageElevation() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// ITERATION SUPPORT (cache-friendly)
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
GTile* begin() { return tiles; }
|
|
||||||
GTile* end() { return tiles + (width * height); }
|
|
||||||
const GTile* begin() const { return tiles; }
|
|
||||||
const GTile* end() const { return tiles + (width * height); }
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// SERIALIZATION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
json serialize() const override;
|
|
||||||
void deserialize(const json& data) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void allocateTiles();
|
|
||||||
void deallocateTiles();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -3,7 +3,7 @@
|
|||||||
#include "Meteorite.h"
|
#include "Meteorite.h"
|
||||||
#include "WorldData.h"
|
#include "WorldData.h"
|
||||||
#include "PlanetaryCore.h"
|
#include "PlanetaryCore.h"
|
||||||
#include "RegionManager.h"
|
#include "map/RegionManager.h"
|
||||||
|
|
||||||
namespace warfactory {
|
namespace warfactory {
|
||||||
|
|
||||||
@ -27,7 +27,20 @@ public:
|
|||||||
void generateHeat(WorldData& world);
|
void generateHeat(WorldData& world);
|
||||||
|
|
||||||
float calculateKineticEnergy() const;
|
float calculateKineticEnergy() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Calculate impact radius with atmospheric fragmentation
|
||||||
|
*
|
||||||
|
* MUST account for meteorite fragmentation in atmosphere with 4 configurations:
|
||||||
|
* - LOW: Iron meteorites, minimal fragmentation, concentrated impact
|
||||||
|
* - MEDIUM: Stone meteorites, partial fragmentation, main impact + debris field
|
||||||
|
* - HIGH: Ice/carbonaceous meteorites, significant fragmentation, dispersed impacts
|
||||||
|
* - EXPLOSIVE: Volatile-rich meteorites, atmospheric explosion, wide area effect
|
||||||
|
*
|
||||||
|
* Formula should vary based on meteorite_template.getMeteoriteType()
|
||||||
|
*/
|
||||||
float calculateImpactRadius() const;
|
float calculateImpactRadius() const;
|
||||||
|
|
||||||
float calculateHeatGeneration() const;
|
float calculateHeatGeneration() const;
|
||||||
float calculateCraterDepth() const;
|
float calculateCraterDepth() const;
|
||||||
float calculateCraterRadius() const;
|
float calculateCraterRadius() const;
|
||||||
|
|||||||
@ -1,40 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "warfactory/IRegion.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
class RegionManager {
|
|
||||||
private:
|
|
||||||
std::vector<std::unique_ptr<IRegion>> regions;
|
|
||||||
int next_region_id;
|
|
||||||
|
|
||||||
public:
|
|
||||||
RegionManager();
|
|
||||||
|
|
||||||
int createRegion(const std::string& region_type, float x, float y, float mass, float radius);
|
|
||||||
|
|
||||||
void addRegion(std::unique_ptr<IRegion> region);
|
|
||||||
|
|
||||||
void removeRegion(int region_id);
|
|
||||||
|
|
||||||
IRegion* getRegion(int region_id);
|
|
||||||
const IRegion* getRegion(int region_id) const;
|
|
||||||
|
|
||||||
std::vector<IRegion*> getRegionsInRadius(float center_x, float center_y, float radius);
|
|
||||||
|
|
||||||
std::vector<IRegion*> getRegionsByType(const std::string& region_type);
|
|
||||||
|
|
||||||
void updateAllRegions(float delta_time);
|
|
||||||
|
|
||||||
void processFusions();
|
|
||||||
|
|
||||||
size_t getRegionCount() const { return regions.size(); }
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "GMap.h"
|
#include "map/GMap.h"
|
||||||
#include "warfactory/ASerializable.h"
|
#include "warfactory/ASerializable.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "../WorldGenerationFunctions/IWorldGenerationFunction.h"
|
#include "../WorldGenerationFunctions/IWorldGenerationFunction.h"
|
||||||
#include "../WorldData.h"
|
#include "../WorldData.h"
|
||||||
#include "../GMap.h"
|
#include "map/GMap.h"
|
||||||
|
|
||||||
namespace warfactory {
|
namespace warfactory {
|
||||||
|
|
||||||
|
|||||||
@ -1,221 +0,0 @@
|
|||||||
#include "../include/GMap.h"
|
|
||||||
#include <cstring>
|
|
||||||
#include <cmath>
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
GMap::GMap(int w, int h) : ASerializable("gmap"), width(w), height(h), tiles(nullptr) {
|
|
||||||
allocateTiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
GMap::~GMap() {
|
|
||||||
deallocateTiles();
|
|
||||||
}
|
|
||||||
|
|
||||||
GMap::GMap(GMap&& other) noexcept
|
|
||||||
: ASerializable("gmap"), width(other.width), height(other.height), tiles(other.tiles) {
|
|
||||||
other.width = 0;
|
|
||||||
other.height = 0;
|
|
||||||
other.tiles = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
GMap& GMap::operator=(GMap&& other) noexcept {
|
|
||||||
if (this != &other) {
|
|
||||||
deallocateTiles();
|
|
||||||
width = other.width;
|
|
||||||
height = other.height;
|
|
||||||
tiles = other.tiles;
|
|
||||||
|
|
||||||
other.width = 0;
|
|
||||||
other.height = 0;
|
|
||||||
other.tiles = nullptr;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// MAP ACCESS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
GTile* GMap::getTile(int x, int y) {
|
|
||||||
if (!isValidCoordinate(x, y)) return nullptr;
|
|
||||||
return &tiles[y * width + x];
|
|
||||||
}
|
|
||||||
|
|
||||||
const GTile* GMap::getTile(int x, int y) const {
|
|
||||||
if (!isValidCoordinate(x, y)) return nullptr;
|
|
||||||
return &tiles[y * width + x];
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// BULK OPERATIONS (Phase 1 specific)
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
void GMap::coolAllTiles(float cooling_rate_celsius) {
|
|
||||||
const int total_tiles = width * height;
|
|
||||||
for (int i = 0; i < total_tiles; ++i) {
|
|
||||||
tiles[i].coolTile(cooling_rate_celsius);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMap::applyImpactToArea(float center_x, float center_y, float radius_meters,
|
|
||||||
float heat_celsius, uint16_t crater_depth, uint8_t crater_scale) {
|
|
||||||
const float radius_squared = radius_meters * radius_meters;
|
|
||||||
|
|
||||||
// Convert world coordinates to tile indices
|
|
||||||
const int start_x = std::max(0, static_cast<int>(center_x - radius_meters));
|
|
||||||
const int end_x = std::min(width - 1, static_cast<int>(center_x + radius_meters));
|
|
||||||
const int start_y = std::max(0, static_cast<int>(center_y - radius_meters));
|
|
||||||
const int end_y = std::min(height - 1, static_cast<int>(center_y + radius_meters));
|
|
||||||
|
|
||||||
for (int y = start_y; y <= end_y; ++y) {
|
|
||||||
for (int x = start_x; x <= end_x; ++x) {
|
|
||||||
const float dx = x - center_x;
|
|
||||||
const float dy = y - center_y;
|
|
||||||
const float distance_squared = dx * dx + dy * dy;
|
|
||||||
|
|
||||||
if (distance_squared <= radius_squared) {
|
|
||||||
GTile* tile = getTile(x, y);
|
|
||||||
if (tile) {
|
|
||||||
// Apply heat with falloff based on distance
|
|
||||||
const float distance_factor = 1.0f - (distance_squared / radius_squared);
|
|
||||||
const float scaled_heat = heat_celsius * distance_factor;
|
|
||||||
tile->applyImpactHeat(scaled_heat);
|
|
||||||
|
|
||||||
// Apply crater elevation change
|
|
||||||
const float current_elevation = tile->getElevationMeters();
|
|
||||||
const float crater_effect = crater_depth * distance_factor * crater_scale * 0.01f;
|
|
||||||
tile->setElevationMeters(current_elevation - crater_effect);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMap::applyVolcanicHeat(float x, float y, float heat_celsius, float radius_meters) {
|
|
||||||
const float radius_squared = radius_meters * radius_meters;
|
|
||||||
|
|
||||||
const int start_x = std::max(0, static_cast<int>(x - radius_meters));
|
|
||||||
const int end_x = std::min(width - 1, static_cast<int>(x + radius_meters));
|
|
||||||
const int start_y = std::max(0, static_cast<int>(y - radius_meters));
|
|
||||||
const int end_y = std::min(height - 1, static_cast<int>(y + radius_meters));
|
|
||||||
|
|
||||||
for (int tile_y = start_y; tile_y <= end_y; ++tile_y) {
|
|
||||||
for (int tile_x = start_x; tile_x <= end_x; ++tile_x) {
|
|
||||||
const float dx = tile_x - x;
|
|
||||||
const float dy = tile_y - y;
|
|
||||||
const float distance_squared = dx * dx + dy * dy;
|
|
||||||
|
|
||||||
if (distance_squared <= radius_squared) {
|
|
||||||
GTile* tile = getTile(tile_x, tile_y);
|
|
||||||
if (tile) {
|
|
||||||
const float distance_factor = 1.0f - (distance_squared / radius_squared);
|
|
||||||
const float scaled_heat = heat_celsius * distance_factor;
|
|
||||||
tile->applyImpactHeat(scaled_heat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float GMap::getAverageTemperature() const {
|
|
||||||
if (width == 0 || height == 0) return 0.0f;
|
|
||||||
|
|
||||||
double temperature_sum = 0.0;
|
|
||||||
const int total_tiles = width * height;
|
|
||||||
|
|
||||||
for (int i = 0; i < total_tiles; ++i) {
|
|
||||||
temperature_sum += tiles[i].getTemperatureCelsius();
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<float>(temperature_sum / total_tiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
float GMap::getAverageElevation() const {
|
|
||||||
if (width == 0 || height == 0) return 0.0f;
|
|
||||||
|
|
||||||
double elevation_sum = 0.0;
|
|
||||||
const int total_tiles = width * height;
|
|
||||||
|
|
||||||
for (int i = 0; i < total_tiles; ++i) {
|
|
||||||
elevation_sum += tiles[i].getElevationMeters();
|
|
||||||
}
|
|
||||||
|
|
||||||
return static_cast<float>(elevation_sum / total_tiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// SERIALIZATION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
json GMap::serialize() const {
|
|
||||||
json data;
|
|
||||||
data["width"] = width;
|
|
||||||
data["height"] = height;
|
|
||||||
data["tiles"] = json::array();
|
|
||||||
|
|
||||||
const int total_tiles = width * height;
|
|
||||||
for (int i = 0; i < total_tiles; ++i) {
|
|
||||||
const GTile& tile = tiles[i];
|
|
||||||
json tile_data;
|
|
||||||
tile_data["elevation"] = tile.elevation;
|
|
||||||
tile_data["temperature"] = tile.temperature;
|
|
||||||
tile_data["biome_type_id"] = tile.biome_type_id;
|
|
||||||
tile_data["water_token"] = tile.water_token;
|
|
||||||
tile_data["wind_token"] = tile.wind_token;
|
|
||||||
tile_data["target_budget_score"] = tile.target_budget_score;
|
|
||||||
tile_data["destruction_token"] = tile.destruction_token;
|
|
||||||
tile_data["flags"] = tile.flags;
|
|
||||||
tile_data["feature_set_id"] = tile.feature_set_id;
|
|
||||||
data["tiles"].push_back(tile_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMap::deserialize(const json& data) {
|
|
||||||
deallocateTiles();
|
|
||||||
|
|
||||||
width = data.at("width").get<int>();
|
|
||||||
height = data.at("height").get<int>();
|
|
||||||
|
|
||||||
allocateTiles();
|
|
||||||
|
|
||||||
const json& tiles_data = data.at("tiles");
|
|
||||||
const int total_tiles = width * height;
|
|
||||||
|
|
||||||
for (int i = 0; i < total_tiles && i < static_cast<int>(tiles_data.size()); ++i) {
|
|
||||||
const json& tile_data = tiles_data[i];
|
|
||||||
GTile& tile = tiles[i];
|
|
||||||
|
|
||||||
tile.elevation = tile_data.at("elevation").get<uint16_t>();
|
|
||||||
tile.temperature = tile_data.at("temperature").get<int16_t>();
|
|
||||||
tile.biome_type_id = tile_data.at("biome_type_id").get<uint16_t>();
|
|
||||||
tile.water_token = tile_data.at("water_token").get<uint8_t>();
|
|
||||||
tile.wind_token = tile_data.at("wind_token").get<uint8_t>();
|
|
||||||
tile.target_budget_score = tile_data.at("target_budget_score").get<int8_t>();
|
|
||||||
tile.destruction_token = tile_data.at("destruction_token").get<uint16_t>();
|
|
||||||
tile.flags = tile_data.at("flags").get<uint16_t>();
|
|
||||||
tile.feature_set_id = tile_data.at("feature_set_id").get<uint32_t>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// PRIVATE METHODS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
void GMap::allocateTiles() {
|
|
||||||
if (width > 0 && height > 0) {
|
|
||||||
const int total_tiles = width * height;
|
|
||||||
tiles = new GTile[total_tiles];
|
|
||||||
// GTile constructor initializes with default values
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMap::deallocateTiles() {
|
|
||||||
delete[] tiles;
|
|
||||||
tiles = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#include "../include/MeteoriteImpact.h"
|
#include "../include/MeteoriteImpact.h"
|
||||||
#include "../include/GMap.h"
|
#include "map/GMap.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|||||||
@ -1,57 +0,0 @@
|
|||||||
# World Generation Module
|
|
||||||
|
|
||||||
**Responsabilité** : Génération procédurale de la WorldMap avec biomes et features géographiques.
|
|
||||||
|
|
||||||
## Description
|
|
||||||
|
|
||||||
Ce module génère la carte mondiale diplomatique/stratégique en utilisant des algorithmes procéduraux configurables. Il gère les biomes, le terrain, et les features géographiques selon les configurations définies dans gameData/.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Interface
|
|
||||||
- **WorldGenerationModule** : Hérite d'IModule
|
|
||||||
- **GMap** : Structure de données pour stocker la worldmap en mémoire
|
|
||||||
- **Configuration** : Via const IDataNode& depuis gameData/
|
|
||||||
|
|
||||||
### Données de Configuration
|
|
||||||
- `gameData/WorldGeneration/` - Algorithmes et paramètres génération
|
|
||||||
- `gameData/Biomes/` - Définitions des biomes
|
|
||||||
- `gameData/Terrain/` - Types de terrain disponibles
|
|
||||||
- `gameData/MapFeatures/` - Features géographiques (montagnes, rivières, etc.)
|
|
||||||
|
|
||||||
### Format JSON
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"world_map": {
|
|
||||||
"size": {"width": 1000, "height": 1000},
|
|
||||||
"tiles": [
|
|
||||||
{"x": 0, "y": 0, "terrain": "plains", "biome": "temperate", "elevation": 100}
|
|
||||||
],
|
|
||||||
"features": [
|
|
||||||
{"type": "river", "coordinates": [[x1,y1], [x2,y2]]}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contraintes Modules
|
|
||||||
- **200-300 lignes max** pour logique métier
|
|
||||||
- **JSON uniquement** pour communication
|
|
||||||
- **Hot-reload ready** avec getState()/setState()
|
|
||||||
- **Autonome** : `cd src/modules/world-generation/ && cmake .`
|
|
||||||
|
|
||||||
## Build Commands
|
|
||||||
```bash
|
|
||||||
cd src/modules/world-generation/
|
|
||||||
cmake . # Configuration
|
|
||||||
make world-generation # Build .so library
|
|
||||||
make world-generation-test # Build standalone test
|
|
||||||
./build/bin/world-generation-test # Test standalone
|
|
||||||
```
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
- nlohmann/json pour JSON processing
|
|
||||||
- Core interfaces (IModule, IDataNode) depuis ../../core/include
|
|
||||||
|
|
||||||
## Hot-Reload
|
|
||||||
Le module préserve l'état de la map générée à travers les reloads via getState()/setState().
|
|
||||||
@ -1,71 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
|
||||||
project(world-generation VERSION 1.0.0)
|
|
||||||
|
|
||||||
# C++ Standard
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
|
|
||||||
# Defensive programming by default
|
|
||||||
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Build type" FORCE)
|
|
||||||
|
|
||||||
# AddressSanitizer and UndefinedBehaviorSanitizer by default
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined -fno-omit-frame-pointer -g")
|
|
||||||
set(CMAKE_LINKER_FLAGS_DEBUG "${CMAKE_LINKER_FLAGS_DEBUG} -fsanitize=address -fsanitize=undefined")
|
|
||||||
|
|
||||||
# FetchContent for dependencies
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
|
||||||
nlohmann_json
|
|
||||||
GIT_REPOSITORY https://github.com/nlohmann/json.git
|
|
||||||
GIT_TAG v3.11.2
|
|
||||||
)
|
|
||||||
FetchContent_MakeAvailable(nlohmann_json)
|
|
||||||
|
|
||||||
# Include directories
|
|
||||||
target_include_directories(world-generation PRIVATE include)
|
|
||||||
target_include_directories(world-generation PRIVATE ../../core/include)
|
|
||||||
|
|
||||||
# Source files
|
|
||||||
set(SOURCES
|
|
||||||
src/WorldGenerationModule.cpp
|
|
||||||
src/main.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
# Headers
|
|
||||||
set(HEADERS
|
|
||||||
include/WorldGeneration.h
|
|
||||||
include/GMap.h
|
|
||||||
)
|
|
||||||
|
|
||||||
# Create shared library (.so) for hot-reload
|
|
||||||
add_library(world-generation SHARED ${SOURCES} ${HEADERS})
|
|
||||||
|
|
||||||
# Link libraries
|
|
||||||
target_link_libraries(world-generation PRIVATE nlohmann_json::nlohmann_json)
|
|
||||||
|
|
||||||
# Create standalone executable for testing
|
|
||||||
add_executable(world-generation-test ${SOURCES})
|
|
||||||
target_link_libraries(world-generation-test PRIVATE nlohmann_json::nlohmann_json)
|
|
||||||
|
|
||||||
# Include directories for test executable
|
|
||||||
target_include_directories(world-generation-test PRIVATE include)
|
|
||||||
target_include_directories(world-generation-test PRIVATE ../../core/include)
|
|
||||||
|
|
||||||
# Compile definitions for testing
|
|
||||||
target_compile_definitions(world-generation-test PRIVATE TESTING)
|
|
||||||
|
|
||||||
# Build directory
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
|
||||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
|
||||||
|
|
||||||
# Install targets
|
|
||||||
install(TARGETS world-generation DESTINATION lib)
|
|
||||||
install(FILES ${HEADERS} DESTINATION include/world-generation)
|
|
||||||
|
|
||||||
# Apply defensive programming (if available)
|
|
||||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/WarfactoryDefenses.cmake")
|
|
||||||
include(../../../cmake/WarfactoryDefenses.cmake)
|
|
||||||
apply_warfactory_defenses(world-generation)
|
|
||||||
apply_warfactory_defenses(world-generation-test)
|
|
||||||
endif()
|
|
||||||
@ -1,651 +0,0 @@
|
|||||||
# Worldmap Generation System - Technical Analysis Report
|
|
||||||
|
|
||||||
## Executive Summary
|
|
||||||
|
|
||||||
The Warfactory worldmap generation system employs a revolutionary **budget-based procedural generation** approach with **regional influences** to create a realistic, balanced world map. The system uses a **-10 to +10 scoring system** where each tile's features automatically balance risks and rewards, combined with **regional tendencies** that create specialized geographical zones based on real-world geological and historical patterns.
|
|
||||||
|
|
||||||
**Key Innovation**: The budget system ensures automatic risk/reward balancing - valuable resources are naturally accompanied by proportional constraints, while regional influences create coherent geographical specialization.
|
|
||||||
|
|
||||||
## Architecture Overview
|
|
||||||
|
|
||||||
### Core Components
|
|
||||||
|
|
||||||
#### 1. WorldGenerationModule (`WorldGeneration.h`)
|
|
||||||
- **Responsibility**: Global worldmap creation using procedural algorithms
|
|
||||||
- **Output**: Complete world terrain, biomes, elevation data
|
|
||||||
- **Technology**: Noise functions, biome classification, elevation modeling
|
|
||||||
|
|
||||||
#### 2. WorldFeatureModule (`WorldFeature.h`)
|
|
||||||
- **Responsibility**: Placement of 218+ geographical features using budget system
|
|
||||||
- **Output**: Features categorized by type with budget scores (-10 to +10)
|
|
||||||
- **Technology**: Budget scoring, regional probability modifiers, feature suitability analysis
|
|
||||||
|
|
||||||
### Multi-Scale Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
Global World Map (Diplomatic/Strategic Level)
|
|
||||||
├── Terrain Generation (Base)
|
|
||||||
├── Biome Classification (Climate Zones)
|
|
||||||
├── Elevation Modeling (Topographical)
|
|
||||||
└── Feature Placement (Geographical Elements)
|
|
||||||
├── Geological Features
|
|
||||||
├── Aquatic Features
|
|
||||||
├── Terrestrial Features
|
|
||||||
├── Coastal Features
|
|
||||||
├── Industrial Historic Features
|
|
||||||
└── Anomaly Features
|
|
||||||
```
|
|
||||||
|
|
||||||
## Budget Scoring System (-10 to +10)
|
|
||||||
|
|
||||||
### Philosophy
|
|
||||||
Each tile receives a **target score** that determines its overall "potential". The system automatically balances valuable resources with proportional constraints to maintain gameplay equilibrium.
|
|
||||||
|
|
||||||
### Score Distribution Strategy
|
|
||||||
- **30%** of tiles at score 0 (neutral terrain)
|
|
||||||
- **40%** of tiles at scores ±1 to ±3 (common variations)
|
|
||||||
- **20%** of tiles at scores ±4 to ±6 (remarkable zones)
|
|
||||||
- **8%** of tiles at scores ±7 to ±8 (exceptional zones)
|
|
||||||
- **2%** of tiles at scores ±9 to ±10 (legendary zones)
|
|
||||||
|
|
||||||
### Global Geographical Biases
|
|
||||||
- **Mountainous zones**: +1 point (natural mineral concentration)
|
|
||||||
- **Coastal zones**: +0.5 point (access and sediments)
|
|
||||||
- **Historical industrial zones**: -1 point (inherited pollution)
|
|
||||||
|
|
||||||
## Complete Feature Categorization
|
|
||||||
|
|
||||||
### 1. Geological Features
|
|
||||||
|
|
||||||
#### Basic Minerals (+1 point each)
|
|
||||||
- Iron ore deposits
|
|
||||||
- Copper veins
|
|
||||||
- Coal seams
|
|
||||||
- Lead deposits
|
|
||||||
- Sulfur formations
|
|
||||||
- Phosphorus nodes
|
|
||||||
- Natron fields
|
|
||||||
|
|
||||||
#### Precious Minerals
|
|
||||||
- **+2 points**: Bauxite, Tin, Magnesium, Chrome, Antimony, Zinc
|
|
||||||
- **+3 points**: Titanium, Tungsten, Silver, Thorium
|
|
||||||
- **+4 points**: Gold, Lithium
|
|
||||||
- **+5 points**: Platinum, Uranium
|
|
||||||
- **+6 points**: Iridium
|
|
||||||
|
|
||||||
#### Geological Formations
|
|
||||||
- **Caves (+1)**: Natural shelter, hidden resources
|
|
||||||
- **Thermal springs (+1)**: Geothermal energy source
|
|
||||||
- **Salt deposits (+1)**: Chemical resource
|
|
||||||
- **Meteorite impact (+5)**: Concentrated rare metals
|
|
||||||
- **Petrified forest (+2)**: Silica, geological attraction
|
|
||||||
- **Hot water geysers (+2)**: Energy, thermal tourism
|
|
||||||
- **Fairy chimneys (+1)**: Unique erosive formation
|
|
||||||
- **Natural arch (+1)**: Rock bridge, landmark
|
|
||||||
- **Isolated rocky pillar (+1)**: Erosive formation, nesting
|
|
||||||
- **Mesa (+1)**: Isolated plateau, defensive position
|
|
||||||
|
|
||||||
### 2. Aquatic Features
|
|
||||||
|
|
||||||
#### Water Bodies
|
|
||||||
- **Lake (+1)**: Fresh water, transport
|
|
||||||
- **Lake with central island (+2)**: Defensive position, mystery
|
|
||||||
- **Pond (+1)**: Local water resource
|
|
||||||
- **River delta (+2)**: Fertile lands, navigation routes
|
|
||||||
- **Fjord (+1)**: Protected natural port
|
|
||||||
- **Waterfall (+1)**: Hydraulic energy
|
|
||||||
- **River source (+2)**: Pure water, strategic position
|
|
||||||
- **River island (+1)**: Defensive position on waterway
|
|
||||||
- **Archipelago (+3)**: Multiple defensive positions, fishing
|
|
||||||
- **Atoll (+2)**: Protected lagoon, coral reef
|
|
||||||
- **Isolated cove (+2)**: Hidden port, storm protection
|
|
||||||
- **Cove with islet (+3)**: Protected anchorage, mystery
|
|
||||||
- **Skerry (+1)**: Rocky islet, difficult navigation
|
|
||||||
- **Tombolo (+2)**: Island connected by sandbar
|
|
||||||
|
|
||||||
#### Special Aquatic Features
|
|
||||||
- **Marshland (0)**: Resources +2, terrain difficulties -2
|
|
||||||
- **Dried lake (0)**: Salt +2, aridity -2
|
|
||||||
- **Geyser (+2)**: Geothermal energy, attraction
|
|
||||||
- **Mountain oasis (+3)**: Precious water in arid zone +2, strategic position +2, access -1
|
|
||||||
|
|
||||||
### 3. Terrestrial Features
|
|
||||||
|
|
||||||
#### Landforms
|
|
||||||
- **Canyon (0)**: Protection +2, difficult access -2
|
|
||||||
- **Elevated plateau (+1)**: Dominant position, winds
|
|
||||||
- **Enclosed valley (+1)**: Protection, microclimate
|
|
||||||
- **Fertile plain (+2)**: Excellent agriculture
|
|
||||||
- **Steppe (0)**: Pastures +1, aridity -1
|
|
||||||
- **Mobile dunes (-1)**: Terrain instability
|
|
||||||
- **Oasis (+3)**: Precious water in arid zone
|
|
||||||
- **Mountain pass (+1)**: Strategic passage
|
|
||||||
- **Glacial cirque (+1)**: Natural amphitheater
|
|
||||||
- **Gorge (0)**: Narrow passage +1, limited access -1
|
|
||||||
- **Glacier (+1)**: Fresh water reserve, difficult terrain
|
|
||||||
- **Marshy hill (0)**: Elevated position +1, humidity -1
|
|
||||||
- **Caldera (+3)**: Fertile volcanic soil, geothermal
|
|
||||||
- **Isthmus (+2)**: Control of land connection
|
|
||||||
- **Isolated valley (+2)**: Total protection, self-sufficiency
|
|
||||||
- **Isolated mountain (+1)**: Landmark, dominant position
|
|
||||||
- **Giant crater (+4)**: Spectacular formation, minerals
|
|
||||||
- **Desert plateau (0)**: Elevated position +1, aridity -1
|
|
||||||
- **Badlands (-1)**: Severe erosion, poor soil
|
|
||||||
- **Ice oasis (+2)**: Water in arctic zone
|
|
||||||
- **Abyss (-2)**: Natural danger, underground access
|
|
||||||
|
|
||||||
### 4. Coastal Features
|
|
||||||
|
|
||||||
#### Coastal Landforms
|
|
||||||
- **Protected bay (+2)**: Excellent natural port
|
|
||||||
- **Cliffs (0)**: Defense +2, access -2
|
|
||||||
- **Sandy beach (+1)**: Landing, tourism
|
|
||||||
- **Coral reef (+1)**: Natural protection
|
|
||||||
- **Estuary (+2)**: River-maritime commerce
|
|
||||||
- **Peninsula (+1)**: Defensive position
|
|
||||||
- **Strait (+2)**: Control of maritime passage
|
|
||||||
- **Coastal island (+2)**: Maritime outpost, defense
|
|
||||||
- **Coastal cliffs (+1)**: Natural defense, elevated position
|
|
||||||
- **Coastal rift (+1)**: Geological formation, limited access
|
|
||||||
|
|
||||||
### 5. Industrial Historic Features
|
|
||||||
|
|
||||||
#### Historic Industrial Sites
|
|
||||||
- **Terikon (0)**: Pollution -2, scrap +2
|
|
||||||
- **Ghost town (-1)**: Infrastructure +2, dangers -3
|
|
||||||
- **Abandoned textile factory (0)**: Machinery +2, asbestos -2
|
|
||||||
- **Defunct thermal power plant (-1)**: Infrastructure +3, pollution -4
|
|
||||||
- **Steel mill ruins (+1)**: Massive metal scrap +3, contamination -2
|
|
||||||
- **Abandoned refinery (-2)**: Infrastructure +2, toxic pollution -4
|
|
||||||
- **Chemical complex (-3)**: Equipment +3, severe contamination -6
|
|
||||||
- **Industrial mill (+1)**: Machinery +2, hydraulic wheel +1, decay -2
|
|
||||||
- **Abandoned brickyard (+1)**: Local clay +2, furnaces +1, fumes -2
|
|
||||||
- **Glass factory ruins (+1)**: Silica sand +2, equipment +1, debris -2
|
|
||||||
- **Defunct paper mill (0)**: Machinery +2, river pollution -2
|
|
||||||
- **Illegal distillery (+1)**: Copper equipment +2, isolation +1, reputation -2
|
|
||||||
- **Abandoned sawmill (+1)**: Tools +3, stored wood +1, rust -3
|
|
||||||
|
|
||||||
#### Vehicle Graveyards
|
|
||||||
- **Tank graveyard (+2)**: Military metal scrap
|
|
||||||
- **Car cemetery (+1)**: Civil metal scrap
|
|
||||||
- **Aircraft graveyard (+3)**: Rare aviation alloys
|
|
||||||
- **Open-air landfill (-1)**: Pollution -3, scrap +2
|
|
||||||
- **Train wreck (+2)**: Massive steel +3, historical accident -1
|
|
||||||
- **Ship graveyard (+2)**: Naval steel +3, corrosion -1
|
|
||||||
- **Electronic dump (+1)**: Rare metals +3, toxicity -2
|
|
||||||
- **Abandoned gas station (0)**: Underground tanks +1, soil contamination -1
|
|
||||||
|
|
||||||
#### Abandoned Military Sites
|
|
||||||
- **Abandoned Cold War base (+1)**: Bunkers +3, contamination -2
|
|
||||||
- **Ancient war zone (WW1) (0)**: Dangerous munitions -2, scrap +2
|
|
||||||
- **Buried Nazi bunker (+2)**: Fortifications +3, history -1
|
|
||||||
- **Missile launch site (+3)**: Infrastructure +4, contamination -1
|
|
||||||
- **Inactive minefield (-2)**: Residual danger -3, demining +1
|
|
||||||
- **Abandoned naval base (+2)**: Port installations +3, rust -1
|
|
||||||
- **Military airfield (+2)**: Runway +3, hangars +1, residual fuel -2
|
|
||||||
- **Munitions depot (-1)**: Dangerous explosives -4, metals +3
|
|
||||||
- **Abandoned radar (+1)**: Electronic equipment +2, elevated position +1, obsolescence -2
|
|
||||||
|
|
||||||
### 6. Cultural & Natural Sites
|
|
||||||
|
|
||||||
#### Cultural Heritage
|
|
||||||
- **Indigenous tribe (+2)**: Local knowledge, guides
|
|
||||||
- **Abandoned village (0)**: Buildings +1, isolation -1
|
|
||||||
- **Monastery ruins (+1)**: Historical archives, elevated position
|
|
||||||
- **Archaeological site (+2)**: Artifacts, scientific value
|
|
||||||
- **Abandoned lighthouse (+1)**: Strategic coastal position
|
|
||||||
- **Fortress castle (+2)**: Defensive position, cut stone
|
|
||||||
- **Astronomical observatory (+1)**: Precision optics, isolated site
|
|
||||||
- **Historical cemetery (+1)**: Heritage, central position
|
|
||||||
- **Abandoned university (+2)**: Laboratories +3, libraries +1, decay -2
|
|
||||||
- **Hospital ruins (0)**: Medical equipment +2, contamination -2
|
|
||||||
- **Defunct prison (+1)**: Security +3, reputation -2
|
|
||||||
- **Gothic cathedral (+2)**: Architecture +3, tourism +1, maintenance -2
|
|
||||||
- **Historical windmill (+1)**: Ancient mechanics +2, windy position +1, obsolescence -2
|
|
||||||
- **Abandoned collective farm (0)**: Hangars +2, land +1, decay -3
|
|
||||||
|
|
||||||
### 7. Biomes & Ecosystems
|
|
||||||
|
|
||||||
#### Forest Types
|
|
||||||
- **Temperate forest (+1)**: Wood, biodiversity
|
|
||||||
- **Boreal forest (+1)**: Conifers, acidic soils
|
|
||||||
- **Tropical forest (+2)**: Biodiversity, exotic woods
|
|
||||||
- **Mixed forest (+1)**: Wood diversity, ecological balance
|
|
||||||
- **Cloud forest (+2)**: Constant humidity, rare species
|
|
||||||
- **Equatorial jungle (+2)**: Exotic resources +3, accessibility -1
|
|
||||||
|
|
||||||
#### Grasslands & Plains
|
|
||||||
- **Prairie (+1)**: Agriculture, livestock
|
|
||||||
- **Savanna (0)**: Pastures +1, drought -1
|
|
||||||
- **Steppe grassland (0)**: Livestock +1, strong winds -1
|
|
||||||
- **Pampa (+1)**: Fertile lands, constant winds
|
|
||||||
- **Chaparral (0)**: Fire resistance +1, brush -1
|
|
||||||
|
|
||||||
#### Extreme Environments
|
|
||||||
- **Tundra (0)**: Permafrost +0, extreme cold -1, isolation +1
|
|
||||||
- **Taiga (+1)**: Massive wood, furs
|
|
||||||
- **Hot desert (-1)**: Aridity -2, exposed minerals +1
|
|
||||||
- **Cold desert (-1)**: Cold -1, isolation +0
|
|
||||||
- **Salt desert (-1)**: Hostile -3, salt extraction +2
|
|
||||||
- **Ice sheet (-2)**: Extreme isolation -3, arctic fishing +1
|
|
||||||
|
|
||||||
#### Specialized Ecosystems
|
|
||||||
- **Mangrove (+2)**: Coastal protection, unique ecosystem
|
|
||||||
- **Alpine zone (0)**: Elevated position +2, difficult access -2
|
|
||||||
- **Salt marsh (+1)**: Natural salt, terrain difficulties
|
|
||||||
- **Moorland (0)**: Poor soil -1, peat +1
|
|
||||||
- **Mediterranean scrubland (+1)**: Aromatic plants, fires -1
|
|
||||||
- **Wetland (+1)**: Natural filtration, biodiversity
|
|
||||||
- **Floodplain (0)**: Fertility +2, floods -2
|
|
||||||
- **Continental shelf (+1)**: Fishing, maritime position
|
|
||||||
- **Barrier reef (+3)**: Protection +2, marine biodiversity +2, navigation -1
|
|
||||||
- **Glacial valley (+1)**: Fertile soil +2, harsh climate -1
|
|
||||||
|
|
||||||
### 8. Geological Anomalies
|
|
||||||
|
|
||||||
#### Crystal & Mineral Formations
|
|
||||||
- **Crystalline formations (+2)**: Unique minerals
|
|
||||||
- **Rare clay deposits (+2)**: Specialized materials
|
|
||||||
- **Silica sands (+1)**: Glass manufacturing
|
|
||||||
- **Quartz deposits (+2)**: Laser optics
|
|
||||||
- **Diamond veins (+4)**: Precision tools, industrial optics
|
|
||||||
- **Various precious stones (+2)**: Laser technology, electronics
|
|
||||||
- **Amber deposits (+3)**: Fossil resin, scientific inclusions
|
|
||||||
- **Oil shale (+2)**: Unconventional hydrocarbons
|
|
||||||
|
|
||||||
#### Geological Phenomena
|
|
||||||
- **Methane geysers (+2)**: Energy, explosion risk
|
|
||||||
- **Salt dome (+3)**: Underground storage, chemical resource
|
|
||||||
- **Peat bog (+1)**: Organic fuel, preservation
|
|
||||||
- **Ancient lava flow (+2)**: Volcanic rocks, fertile lands
|
|
||||||
- **Impact crater (+4)**: Rare metals, unique geological formation
|
|
||||||
- **Active geological fault (-1)**: Instability +0, exposed minerals +1
|
|
||||||
- **Karst (0)**: Caves +2, collapses -2
|
|
||||||
- **Doline (-1)**: Natural collapse, underground access
|
|
||||||
- **Cave entrance (+2)**: Exploration, natural shelter
|
|
||||||
- **Surface cave (+1)**: Visible shelter, storage
|
|
||||||
- **Hell's pit (-3)**: Deep abyss, dangerous emanations
|
|
||||||
|
|
||||||
### 9. Climate & Meteorological Elements
|
|
||||||
|
|
||||||
#### Weather Phenomena
|
|
||||||
- **Tornado zone (-2)**: Danger -3, wind energy +1
|
|
||||||
- **Wind corridor (+1)**: Constant wind energy
|
|
||||||
- **Fog zone (-1)**: Reduced visibility -2, humidity +1
|
|
||||||
- **Warm microclimate (+1)**: Extended agriculture
|
|
||||||
- **Cold pocket (-1)**: Permanent frost, natural preservation
|
|
||||||
- **Dead calm zone (0)**: Difficult navigation -1, tranquility +1
|
|
||||||
|
|
||||||
### 10. Modern Anthropogenic Elements
|
|
||||||
|
|
||||||
#### Infrastructure
|
|
||||||
- **Abandoned highway (+1)**: Asphalt +2, pollution -1
|
|
||||||
- **Highway bridge (+2)**: Strategic passage +3, maintenance -1
|
|
||||||
- **Railway tunnel (+2)**: Mountain passage +3, maintenance -1
|
|
||||||
- **High-voltage line (+1)**: Electrical infrastructure +2, danger -1
|
|
||||||
- **Broken wind turbine (0)**: Mechanical parts +2, obstruction -2
|
|
||||||
- **Relay antenna (+1)**: Communication +2, elevated position +1, obsolescence -2
|
|
||||||
- **Buried pipeline (+1)**: Infrastructure +2, leak risk -1
|
|
||||||
- **Controlled landfill (-1)**: Recovery +2, pollution -3
|
|
||||||
|
|
||||||
### 11. Mysterious & Rare Elements
|
|
||||||
|
|
||||||
#### Unexplained Phenomena
|
|
||||||
- **Stone circle (+2)**: Historical mystery, landmark
|
|
||||||
- **Isolated monolith (+3)**: Unexplained formation, attraction
|
|
||||||
- **Radio silence zone (-1)**: Unexplained phenomenon -2, isolation +1
|
|
||||||
- **Magnetic anomaly (+2)**: Rare minerals +3, instrument disruption -1
|
|
||||||
- **Natural radioactive source (-2)**: Danger -4, scientific research +2
|
|
||||||
|
|
||||||
## Resource Integration Patterns
|
|
||||||
|
|
||||||
### 1. Integrated vs Standalone Resources
|
|
||||||
|
|
||||||
#### Features with Integrated Resources
|
|
||||||
- **Terikon**: Industrial scrap integrated into feature definition
|
|
||||||
- **Ancient ruins**: Recoverable materials as part of structure
|
|
||||||
- **Industrial complexes**: Machinery and infrastructure as feature elements
|
|
||||||
- **River deltas**: Fertile sediments as inherent property
|
|
||||||
|
|
||||||
#### Standalone Resource Deposits
|
|
||||||
- **Pure mineral patches**: Iron, copper, coal deposits independent of features
|
|
||||||
- **Oil/gas fields**: Energy resource patches with own extraction mechanics
|
|
||||||
- **Precious metal veins**: Gold, platinum as dedicated geological formations
|
|
||||||
|
|
||||||
### 2. Resource-Feature Synergy
|
|
||||||
|
|
||||||
#### Complementary Placement
|
|
||||||
- **Iron near industrial ruins**: Historical mining creates both resources and contamination
|
|
||||||
- **Thermal springs near volcanic minerals**: Geological activity creates multiple benefits
|
|
||||||
- **Clay deposits near abandoned brickworks**: Historical industry aligned with natural resources
|
|
||||||
|
|
||||||
#### Balanced Combinations
|
|
||||||
- **Uranium + contamination**: Valuable resource offset by safety hazards
|
|
||||||
- **Fertile soil + flood risk**: Agricultural potential balanced by natural disasters
|
|
||||||
- **Strategic position + access difficulty**: Military value offset by logistical challenges
|
|
||||||
|
|
||||||
## Regional Influences System
|
|
||||||
|
|
||||||
### 1. Geological Specialization Zones
|
|
||||||
|
|
||||||
#### Petroleum Basins (Persian Gulf, North Sea)
|
|
||||||
- **Petroleum**: probability ×5
|
|
||||||
- **Natural gas**: probability ×3
|
|
||||||
- **Marshy terrain**: ×2
|
|
||||||
- **Natural maritime access**: inherent bonus
|
|
||||||
|
|
||||||
#### Historic Mining Regions (Ruhr, Donbass, Urals)
|
|
||||||
- **Iron and coal**: probability ×3-4
|
|
||||||
- **Terikons**: probability ×8 (highly characteristic)
|
|
||||||
- **Industrial vestiges**: ×2
|
|
||||||
- **Inherited mining pollution**: ×3
|
|
||||||
|
|
||||||
#### Forest/Mountain Regions (Alps, Carpathians, Taiga)
|
|
||||||
- **Dense forest and hunting**: probability ×3-4
|
|
||||||
- **Caves and springs**: ×2-3
|
|
||||||
- **Steep slopes**: ×2
|
|
||||||
- **Geological instability**: ×1.5
|
|
||||||
|
|
||||||
#### Post-Nuclear Zones (Extended Chernobyl, test sites)
|
|
||||||
- **Radioactive pollution**: probability ×10
|
|
||||||
- **Accessible uranium**: ×3
|
|
||||||
- **Abandoned structures**: ×3
|
|
||||||
- **Characteristic mutant vegetation**: special markers
|
|
||||||
|
|
||||||
#### Coastal Regions (Coastlines, deltas)
|
|
||||||
- **Maritime access**: natural bonus
|
|
||||||
- **Sediments and clays**: ×2
|
|
||||||
- **Wetlands**: ×1.5
|
|
||||||
- **Coastal erosion**: specific constraint
|
|
||||||
|
|
||||||
### 2. Transition Zones
|
|
||||||
|
|
||||||
#### Progressive Influence
|
|
||||||
Regional influence diminishes with distance from center, creating realistic mixed zones.
|
|
||||||
|
|
||||||
#### Superposition Effects
|
|
||||||
Multiple influences can combine:
|
|
||||||
- **Mountain + ancient mining basin** = precious metals in difficult terrain
|
|
||||||
- **Coastal + industrial historic** = ports with pollution legacy
|
|
||||||
- **Forest + post-nuclear** = contaminated wilderness areas
|
|
||||||
|
|
||||||
### 3. Fixed Historical Sites
|
|
||||||
|
|
||||||
#### Iconic Locations with Fixed Characteristics
|
|
||||||
- **Chernobyl**: Fixed score -10 (massive radiation, dead zone)
|
|
||||||
- **Persian Gulf**: Fixed score +8 (abundant oil, infrastructure)
|
|
||||||
- **Siberian diamond region**: Fixed score +9 (diamonds + gold + extreme difficulties)
|
|
||||||
- **Atacama Desert**: Fixed score -7 (extreme aridity, rare minerals)
|
|
||||||
- **Ruhr Region**: Fixed score +3 (industrial wealth)
|
|
||||||
|
|
||||||
## Procedural Generation Requirements
|
|
||||||
|
|
||||||
### 1. Core Algorithms
|
|
||||||
|
|
||||||
#### Deterministic Generation
|
|
||||||
```cpp
|
|
||||||
// Seed-based deterministic generation per tile
|
|
||||||
uint32_t tile_seed = global_seed ^ (tile_x << 16) ^ tile_y;
|
|
||||||
// Ensures exact terrain reproduction
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Multi-Layer Noise Functions
|
|
||||||
- **Elevation generation**: Perlin noise for realistic topography
|
|
||||||
- **Climate modeling**: Temperature and humidity gradients
|
|
||||||
- **Resource distribution**: Probability maps based on geological realism
|
|
||||||
- **Feature placement**: Weighted random selection based on budget targets
|
|
||||||
|
|
||||||
### 2. Budget Balancing Algorithm
|
|
||||||
|
|
||||||
#### Target Score Achievement
|
|
||||||
```cpp
|
|
||||||
// Pseudo-algorithm for budget balancing
|
|
||||||
float target_score = calculateTargetScore(x, y, regional_bias);
|
|
||||||
vector<FeatureCombination> combinations = generateCombinations(target_score);
|
|
||||||
FeatureCombination selected = selectBestFit(combinations, terrain_constraints);
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Constraint Satisfaction
|
|
||||||
- **Terrain compatibility**: Features must match geological realism
|
|
||||||
- **Regional probability**: Apply regional influence multipliers
|
|
||||||
- **Mutual exclusion**: Some features cannot coexist
|
|
||||||
- **Spatial distribution**: Avoid over-clustering of similar features
|
|
||||||
|
|
||||||
### 3. Discovery System Architecture
|
|
||||||
|
|
||||||
#### Layered Visibility System
|
|
||||||
|
|
||||||
##### Layer 1: Visible Elements
|
|
||||||
- Terrain relief and rock formations
|
|
||||||
- Waterways and springs
|
|
||||||
- Surface vegetation and forest cover
|
|
||||||
- Surface ruins and structures
|
|
||||||
|
|
||||||
##### Layer 2: Geological Prospecting
|
|
||||||
- **Geological vehicle**: Reveals underground deposits, hydrocarbon reserves, deep water
|
|
||||||
- **Range**: 3×3 chunks from position
|
|
||||||
- **Duration**: 2-5 minutes based on depth
|
|
||||||
|
|
||||||
##### Layer 3: Magnetometric Exploration
|
|
||||||
- **Magnetometric vehicle**: Detects magnetic anomalies, buried metal structures, monoliths
|
|
||||||
- **Range**: 1×1 chunk high precision
|
|
||||||
- **Duration**: 1-3 minutes
|
|
||||||
|
|
||||||
##### Layer 4: CBRN Analysis
|
|
||||||
- **CBRN vehicle**: Reveals invisible contamination, radiation, chemical pollution
|
|
||||||
- **Safety**: Crew protection required
|
|
||||||
- **Duration**: 3-8 minutes based on danger level
|
|
||||||
|
|
||||||
## Technical Implementation Requirements
|
|
||||||
|
|
||||||
### 1. Module Architecture
|
|
||||||
|
|
||||||
#### WorldGenerationModule Responsibilities
|
|
||||||
- **Terrain base generation**: Elevation, basic terrain types
|
|
||||||
- **Biome classification**: Climate-based biome assignment
|
|
||||||
- **Seed management**: Deterministic reproduction
|
|
||||||
- **Configuration loading**: From gameData/ hierarchy
|
|
||||||
|
|
||||||
#### WorldFeatureModule Responsibilities
|
|
||||||
- **Feature placement**: 218+ geographical features using budget system
|
|
||||||
- **Budget calculation**: -10 to +10 scoring for each tile
|
|
||||||
- **Regional influence**: Probability modifiers based on geographical zones
|
|
||||||
- **Discovery system**: Layered visibility and exploration requirements
|
|
||||||
|
|
||||||
### 2. Data Structures
|
|
||||||
|
|
||||||
#### Tile Structure
|
|
||||||
```cpp
|
|
||||||
struct Tile {
|
|
||||||
uint16_t terrain_type; // 2 bytes (65k terrain types possible)
|
|
||||||
uint8_t elevation; // 1 byte (0-255 height)
|
|
||||||
uint16_t building_id; // 2 bytes (ref to building)
|
|
||||||
uint16_t flags; // 2 bytes (passable, destructible, etc.)
|
|
||||||
uint8_t padding; // 1 byte (memory alignment)
|
|
||||||
}; // = 8 bytes per tile
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Feature Structure
|
|
||||||
```cpp
|
|
||||||
struct WorldFeature {
|
|
||||||
string feature_id;
|
|
||||||
string feature_type;
|
|
||||||
FeatureCategory category;
|
|
||||||
int x, y; // World coordinates
|
|
||||||
float budget_score; // -10 to +10 budget scoring
|
|
||||||
json properties; // Feature-specific properties
|
|
||||||
vector<pair<int, int>> affected_tiles; // Tiles covered by feature
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Performance Specifications
|
|
||||||
|
|
||||||
#### Memory Footprint per Chunk (64×64 tiles)
|
|
||||||
- **Terrain**: 32KB (always loaded)
|
|
||||||
- **Resources**: 0-16KB (sparse, on-demand)
|
|
||||||
- **Metadata**: 1-5KB (buildings and features)
|
|
||||||
- **Total**: 33-53KB per chunk (highly reasonable)
|
|
||||||
|
|
||||||
#### Generation Performance
|
|
||||||
- **Streaming generation**: Create chunks on-demand
|
|
||||||
- **Persistent storage**: Save once generated with seed
|
|
||||||
- **Reproduction guarantee**: Same seed = identical terrain
|
|
||||||
- **Hot-reload friendly**: State preservation across module reloads
|
|
||||||
|
|
||||||
### 4. Configuration System
|
|
||||||
|
|
||||||
#### gameData/ Hierarchy
|
|
||||||
```
|
|
||||||
gameData/
|
|
||||||
├── WorldGeneration/ # Generation algorithms and parameters
|
|
||||||
├── Biomes/ # Biome definitions and properties
|
|
||||||
├── Terrain/ # Terrain type definitions
|
|
||||||
├── MapFeatures/ # Geographical features database
|
|
||||||
└── RegionalInfluences/ # Regional probability modifiers
|
|
||||||
```
|
|
||||||
|
|
||||||
#### JSON Configuration Format
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"feature_types": {
|
|
||||||
"terikon": {
|
|
||||||
"category": "INDUSTRIAL_HISTORIC",
|
|
||||||
"budget_score": 0,
|
|
||||||
"components": [
|
|
||||||
{"type": "industrial_waste", "score": 1},
|
|
||||||
{"type": "mining_pollution", "score": -2}
|
|
||||||
],
|
|
||||||
"regional_multipliers": {
|
|
||||||
"mining_historic": 8.0,
|
|
||||||
"industrial_legacy": 3.0
|
|
||||||
},
|
|
||||||
"terrain_requirements": ["flat", "historical_mining"],
|
|
||||||
"mutual_exclusions": ["pristine_nature", "urban_center"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Code Examples & Algorithms
|
|
||||||
|
|
||||||
### 1. Budget Score Calculation
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
float WorldFeatureModule::calculateFeatureBudgetScore(const string& featureType, int x, int y) const {
|
|
||||||
float base_score = feature_definitions[featureType].base_score;
|
|
||||||
float regional_modifier = calculateRegionalInfluence(featureType, x, y);
|
|
||||||
float terrain_modifier = calculateTerrainSuitability(featureType, x, y);
|
|
||||||
|
|
||||||
return base_score * regional_modifier * terrain_modifier;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Regional Influence Application
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
float calculateRegionalInfluence(const string& featureType, int x, int y) const {
|
|
||||||
float influence = 1.0f;
|
|
||||||
|
|
||||||
for (const auto& region : active_regions) {
|
|
||||||
float distance = calculateDistance(x, y, region.center_x, region.center_y);
|
|
||||||
float weight = region.calculateInfluenceWeight(distance);
|
|
||||||
|
|
||||||
if (region.feature_multipliers.count(featureType)) {
|
|
||||||
influence *= (1.0f + (region.feature_multipliers[featureType] - 1.0f) * weight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return influence;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Feature Combination Generation
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
vector<FeatureCombination> generateCombinations(float target_score) {
|
|
||||||
vector<FeatureCombination> combinations;
|
|
||||||
|
|
||||||
// Single feature solutions
|
|
||||||
for (const auto& feature : available_features) {
|
|
||||||
if (abs(feature.score - target_score) < tolerance) {
|
|
||||||
combinations.push_back({feature});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Multi-feature combinations
|
|
||||||
for (int count = 2; count <= max_features_per_tile; count++) {
|
|
||||||
auto multi_combinations = generateMultiFeatureCombinations(target_score, count);
|
|
||||||
combinations.insert(combinations.end(), multi_combinations.begin(), multi_combinations.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
return combinations;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Gameplay Mechanics Integration
|
|
||||||
|
|
||||||
### 1. Economic Specialization
|
|
||||||
- **Petroleum basins** naturally become energy centers
|
|
||||||
- **Historic mining zones** evolve into metallurgical centers
|
|
||||||
- **Forest regions** specialize in wood construction and hunting
|
|
||||||
|
|
||||||
### 2. Strategic Territory Control
|
|
||||||
- **Regional control**: Certain regions become strategically vital
|
|
||||||
- **Targeted exploration**: "Seeking iron → head to historic mining mountains"
|
|
||||||
- **Specialized challenges**: Each region imposes unique technical constraints
|
|
||||||
|
|
||||||
### 3. Risk/Reward Learning
|
|
||||||
- **Visual pattern recognition**: Players learn regional indicators
|
|
||||||
- **Terikons** = probable historic mining zone = iron but pollution
|
|
||||||
- **Abnormal vegetation** = contamination = danger but potential rare resources
|
|
||||||
|
|
||||||
### 4. Temporal Evolution
|
|
||||||
- **Player actions modify scores**: Decontamination, resource depletion, industrial accidents
|
|
||||||
- **Natural processes**: Forest regeneration, contamination erosion, sedimentation
|
|
||||||
- **Dynamic rebalancing**: World evolves based on player activities
|
|
||||||
|
|
||||||
## Implementation Priority & Roadmap
|
|
||||||
|
|
||||||
### Phase 1: Core Generation (Foundation)
|
|
||||||
1. **Basic terrain generation**: Elevation, terrain types, biomes
|
|
||||||
2. **Simple feature placement**: Major geological and aquatic features
|
|
||||||
3. **Budget system framework**: Basic scoring without regional influences
|
|
||||||
4. **Deterministic reproduction**: Seed-based generation
|
|
||||||
|
|
||||||
### Phase 2: Advanced Features (Expansion)
|
|
||||||
1. **Regional influence system**: Geological and historical zone specialization
|
|
||||||
2. **Complete feature catalog**: All 218+ features with proper categorization
|
|
||||||
3. **Discovery system**: Layered visibility and exploration mechanics
|
|
||||||
4. **Advanced balancing**: Complex feature interactions and constraints
|
|
||||||
|
|
||||||
### Phase 3: Integration & Optimization (Polish)
|
|
||||||
1. **Performance optimization**: Streaming, caching, memory management
|
|
||||||
2. **Gameplay integration**: Economic systems, strategic mechanics
|
|
||||||
3. **Temporal evolution**: Dynamic world changes based on player actions
|
|
||||||
4. **Advanced algorithms**: Machine learning for pattern recognition and optimization
|
|
||||||
|
|
||||||
## Development Guidelines
|
|
||||||
|
|
||||||
### Module Constraints
|
|
||||||
- **200-300 lines maximum** per module (strict architectural requirement)
|
|
||||||
- **JSON-only communication** between modules
|
|
||||||
- **Hot-reload compatibility** with state preservation
|
|
||||||
- **Autonomous builds**: `cd src/modules/world-generation/ && cmake .`
|
|
||||||
|
|
||||||
### Testing Strategy
|
|
||||||
- **Deterministic verification**: Same seed produces identical results
|
|
||||||
- **Budget balance validation**: Statistical distribution matches targets
|
|
||||||
- **Regional influence testing**: Probability multipliers work correctly
|
|
||||||
- **Feature placement validation**: No invalid combinations or overlaps
|
|
||||||
|
|
||||||
### Configuration-Driven Development
|
|
||||||
- **External data files**: All features, rules, and parameters in gameData/
|
|
||||||
- **Easy iteration**: Modify JSON configs without code recompilation
|
|
||||||
- **Designer-friendly**: Non-programmers can adjust gameplay balance
|
|
||||||
- **Version control**: Track configuration changes separately from code
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Technical Conclusion**: The Warfactory worldmap generation system represents a sophisticated approach to procedural world creation, combining realistic geological patterns with innovative budget-based balancing. The modular architecture ensures maintainability while the regional influence system creates compelling geographical specialization that emerges naturally from real-world patterns.
|
|
||||||
|
|
||||||
The system successfully bridges the gap between procedural generation flexibility and historical/geographical authenticity, creating a world that feels both familiar and strategically interesting for players to explore and exploit.
|
|
||||||
@ -1,244 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WorldFeature.h"
|
|
||||||
#include "FeatureSet.h"
|
|
||||||
#include "GMap.h"
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Helper for generation algorithms - handles feature placement complexity
|
|
||||||
*
|
|
||||||
* Provides simple interface for generation algorithms while hiding all internal
|
|
||||||
* complexity of feature placement, feature set management, budget calculations,
|
|
||||||
* and resource integration. Does NOT do generation itself - just helps algorithms.
|
|
||||||
*/
|
|
||||||
class FeatureManager {
|
|
||||||
private:
|
|
||||||
GMap* world_map; // Reference to world map (not owned)
|
|
||||||
|
|
||||||
// Configuration cache (loaded once, used repeatedly)
|
|
||||||
std::unordered_map<std::string, json> feature_type_configs; // Feature definitions
|
|
||||||
std::unordered_map<std::string, float> base_budget_scores; // Type -> budget score
|
|
||||||
|
|
||||||
// Feature set optimization cache
|
|
||||||
std::unordered_map<std::vector<uint32_t>, uint32_t> feature_set_cache; // Deduplication
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// INTERNAL COMPLEXITY - Hidden from users
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create WorldFeature from type and position (internal)
|
|
||||||
*/
|
|
||||||
WorldFeature createFeatureInstance(const std::string& feature_type, int center_x, int center_y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Update affected tiles with new feature set (internal)
|
|
||||||
*/
|
|
||||||
void updateAffectedTiles(const WorldFeature& feature);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate budget impact without placing (internal)
|
|
||||||
*/
|
|
||||||
float calculateBudgetImpact(const std::string& feature_type, int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check terrain/biome/elevation compatibility (internal)
|
|
||||||
*/
|
|
||||||
bool checkTerrainCompatibility(const std::string& feature_type, int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate integrated resources for feature (internal)
|
|
||||||
*/
|
|
||||||
void generateIntegratedResources(WorldFeature& feature) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
*/
|
|
||||||
FeatureManager();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor
|
|
||||||
*/
|
|
||||||
~FeatureManager() = default;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// INITIALIZATION - Simple setup
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set reference to world map
|
|
||||||
* @param map Mutable reference to world map
|
|
||||||
*/
|
|
||||||
void setWorldMap(GMap* map);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load feature definitions (call once)
|
|
||||||
* @param feature_configs JSON configuration for all feature types
|
|
||||||
*/
|
|
||||||
void loadFeatureDefinitions(const json& feature_configs);
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CORE INTERFACE - Helper for generation algorithms
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if feature can be placed at location
|
|
||||||
* @param feature_type Feature type name (e.g., "terikon", "scrap_metal")
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
* @return true if feature can be placed (terrain compatible, space available, etc.)
|
|
||||||
*/
|
|
||||||
bool canPlaceFeature(const std::string& feature_type, int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Place single feature at coordinates (handles all complexity)
|
|
||||||
* @param feature_type Feature type name
|
|
||||||
* @param center_x Center X coordinate
|
|
||||||
* @param center_y Center Y coordinate
|
|
||||||
* @return Feature ID if placed successfully, 0 if failed
|
|
||||||
*
|
|
||||||
* Internally handles:
|
|
||||||
* - Creating WorldFeature with resources
|
|
||||||
* - Finding affected tiles
|
|
||||||
* - Creating/updating FeatureSets
|
|
||||||
* - Updating tile feature_set_ids
|
|
||||||
* - Budget score recalculation
|
|
||||||
*/
|
|
||||||
uint32_t placeFeature(const std::string& feature_type, int center_x, int center_y);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove feature from map (handles cleanup)
|
|
||||||
* @param feature_id Feature ID to remove
|
|
||||||
* @return true if feature was removed successfully
|
|
||||||
*
|
|
||||||
* Internally handles:
|
|
||||||
* - Removing from GMap::features
|
|
||||||
* - Updating affected tiles
|
|
||||||
* - Cleaning up unused FeatureSets
|
|
||||||
* - Budget score recalculation
|
|
||||||
*/
|
|
||||||
bool removeFeature(uint32_t feature_id);
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// UTILITY QUERIES - For algorithm decision making
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get budget impact of placing feature (without placing)
|
|
||||||
* @param feature_type Feature type name
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
* @return Budget score impact (positive/negative)
|
|
||||||
*/
|
|
||||||
float getBudgetImpact(const std::string& feature_type, int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if feature type exists in configuration
|
|
||||||
* @param feature_type Feature type name
|
|
||||||
* @return true if feature type is defined
|
|
||||||
*/
|
|
||||||
bool isFeatureTypeValid(const std::string& feature_type) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get feature at specific coordinates
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
* @return Vector of feature IDs at location
|
|
||||||
*/
|
|
||||||
std::vector<uint32_t> getFeaturesAt(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if location has any features
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
* @return true if tile has features
|
|
||||||
*/
|
|
||||||
bool hasFeatures(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get number of features at location
|
|
||||||
* @param x X coordinate
|
|
||||||
* @param y Y coordinate
|
|
||||||
* @return Feature count at tile
|
|
||||||
*/
|
|
||||||
size_t getFeatureCount(int x, int y) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CONFIGURATION QUERIES - For algorithm parameters
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get base budget score for feature type
|
|
||||||
* @param feature_type Feature type name
|
|
||||||
* @return Base budget score (-10 to +10)
|
|
||||||
*/
|
|
||||||
float getBaseBudgetScore(const std::string& feature_type) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get feature category for type
|
|
||||||
* @param feature_type Feature type name
|
|
||||||
* @return Feature category
|
|
||||||
*/
|
|
||||||
FeatureCategory getFeatureCategory(const std::string& feature_type) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get available feature types for category
|
|
||||||
* @param category Feature category
|
|
||||||
* @return Vector of feature type names
|
|
||||||
*/
|
|
||||||
std::vector<std::string> getFeatureTypesForCategory(FeatureCategory category) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// OPTIMIZATION AND MAINTENANCE
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Optimize feature set storage (remove unused sets)
|
|
||||||
* @return Number of feature sets cleaned up
|
|
||||||
*/
|
|
||||||
int optimizeFeatureSets();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get statistics for debugging/monitoring
|
|
||||||
* @return JSON with feature counts, memory usage, etc.
|
|
||||||
*/
|
|
||||||
json getStats() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Validate all features and sets consistency
|
|
||||||
* @return JSON with validation results
|
|
||||||
*/
|
|
||||||
json validateConsistency() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// FEATURE SET MANAGEMENT - Advanced helpers
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Place multiple features as coordinated set
|
|
||||||
* @param feature_types Vector of feature type names
|
|
||||||
* @param center_x Center X coordinate
|
|
||||||
* @param center_y Center Y coordinate
|
|
||||||
* @return Feature set ID if placed successfully, 0 if failed
|
|
||||||
*/
|
|
||||||
uint32_t placeFeatureGroup(const std::vector<std::string>& feature_types, int center_x, int center_y);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if feature group can be placed
|
|
||||||
* @param feature_types Vector of feature type names
|
|
||||||
* @param center_x Center X coordinate
|
|
||||||
* @param center_y Center Y coordinate
|
|
||||||
* @return true if all features in group can be placed
|
|
||||||
*/
|
|
||||||
bool canPlaceFeatureGroup(const std::vector<std::string>& feature_types, int center_x, int center_y) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,210 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
// Forward declarations
|
|
||||||
class GMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Immutable feature set for tile feature collections
|
|
||||||
*
|
|
||||||
* Encapsulates a collection of features with caching and usage tracking.
|
|
||||||
* Once created, the feature collection cannot be modified, ensuring consistency
|
|
||||||
* and enabling aggressive caching optimizations.
|
|
||||||
*/
|
|
||||||
class FeatureSet {
|
|
||||||
private:
|
|
||||||
// ========================================
|
|
||||||
// IMMUTABLE FEATURE DATA
|
|
||||||
// ========================================
|
|
||||||
std::vector<uint32_t> feature_ids; // Feature IDs in this set (immutable)
|
|
||||||
uint32_t primary_feature_id; // Most significant feature (0 = none)
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// USAGE TRACKING (mutable for tracking)
|
|
||||||
// ========================================
|
|
||||||
mutable std::unordered_set<uint32_t> used_by_tiles; // Tile indices using this set
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// PERFORMANCE CACHE (mutable for lazy evaluation)
|
|
||||||
// ========================================
|
|
||||||
mutable float cached_budget_score; // Cached total budget score
|
|
||||||
mutable bool budget_cache_valid; // Cache validity flag
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor - creates immutable feature set
|
|
||||||
* @param features Vector of feature IDs
|
|
||||||
* @param primary_feature Primary feature ID (0 = auto-determine)
|
|
||||||
*/
|
|
||||||
explicit FeatureSet(const std::vector<uint32_t>& features, uint32_t primary_feature = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructor - single feature set
|
|
||||||
* @param feature_id Single feature ID
|
|
||||||
*/
|
|
||||||
explicit FeatureSet(uint32_t feature_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor
|
|
||||||
*/
|
|
||||||
~FeatureSet() = default;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// FEATURE ACCESS - Read-only interface
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get all feature IDs in set
|
|
||||||
* @return Immutable reference to feature vector
|
|
||||||
*/
|
|
||||||
const std::vector<uint32_t>& getFeatureIds() const { return feature_ids; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get primary feature ID
|
|
||||||
* @return Primary feature ID (0 if none)
|
|
||||||
*/
|
|
||||||
uint32_t getPrimaryFeatureId() const { return primary_feature_id; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if set contains specific feature
|
|
||||||
* @param feature_id Feature ID to check
|
|
||||||
* @return true if feature is in set
|
|
||||||
*/
|
|
||||||
bool hasFeature(uint32_t feature_id) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get number of features in set
|
|
||||||
* @return Feature count
|
|
||||||
*/
|
|
||||||
size_t getFeatureCount() const { return feature_ids.size(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if set is empty
|
|
||||||
* @return true if no features
|
|
||||||
*/
|
|
||||||
bool isEmpty() const { return feature_ids.empty(); }
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// BUDGET CALCULATIONS - Cached for performance
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate total budget score for this feature set
|
|
||||||
* @param world_map Reference to world map for feature lookups
|
|
||||||
* @return Total budget contribution (cached after first call)
|
|
||||||
*/
|
|
||||||
float getBudgetScore(const GMap* world_map) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Invalidate budget cache (call when features change globally)
|
|
||||||
*/
|
|
||||||
void invalidateBudgetCache() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// USAGE TRACKING - For memory management
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Mark tile as using this feature set
|
|
||||||
* @param tile_index Tile index that uses this set
|
|
||||||
*/
|
|
||||||
void addUsage(uint32_t tile_index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove tile usage of this feature set
|
|
||||||
* @param tile_index Tile index that no longer uses this set
|
|
||||||
*/
|
|
||||||
void removeUsage(uint32_t tile_index) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get number of tiles using this set
|
|
||||||
* @return Usage count
|
|
||||||
*/
|
|
||||||
size_t getUsageCount() const { return used_by_tiles.size(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if any tiles are using this set
|
|
||||||
* @return true if set is in use
|
|
||||||
*/
|
|
||||||
bool isInUse() const { return !used_by_tiles.empty(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get tiles using this set
|
|
||||||
* @return Set of tile indices
|
|
||||||
*/
|
|
||||||
const std::unordered_set<uint32_t>& getUsedByTiles() const { return used_by_tiles; }
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// COMPARISON AND HASHING - For deduplication
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if two feature sets are identical
|
|
||||||
* @param other Other feature set
|
|
||||||
* @return true if feature collections are identical
|
|
||||||
*/
|
|
||||||
bool operator==(const FeatureSet& other) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if two feature sets are different
|
|
||||||
* @param other Other feature set
|
|
||||||
* @return true if feature collections differ
|
|
||||||
*/
|
|
||||||
bool operator!=(const FeatureSet& other) const { return !(*this == other); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate hash for this feature set
|
|
||||||
* @return Hash value for deduplication
|
|
||||||
*/
|
|
||||||
size_t getHash() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// UTILITIES AND DEBUGGING
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get debug information about this set
|
|
||||||
* @return JSON with set details and usage statistics
|
|
||||||
*/
|
|
||||||
json getDebugInfo() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Validate feature set consistency
|
|
||||||
* @param world_map Reference to world map for validation
|
|
||||||
* @return true if set is valid
|
|
||||||
*/
|
|
||||||
bool validate(const GMap* world_map) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get memory footprint of this set
|
|
||||||
* @return Memory usage in bytes
|
|
||||||
*/
|
|
||||||
size_t getMemoryFootprint() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* @brief Determine primary feature from feature list
|
|
||||||
* @param world_map Reference to world map for feature lookups
|
|
||||||
* @return Feature ID with highest budget score
|
|
||||||
*/
|
|
||||||
uint32_t determinePrimaryFeature(const GMap* world_map) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
|
|
||||||
// Hash function for FeatureSet (enables use in unordered containers)
|
|
||||||
namespace std {
|
|
||||||
template<>
|
|
||||||
struct hash<warfactory::FeatureSet> {
|
|
||||||
size_t operator()(const warfactory::FeatureSet& feature_set) const {
|
|
||||||
return feature_set.getHash();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@ -1,333 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "WorldTile.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
// Forward declarations
|
|
||||||
struct WorldFeature;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Global world map data structure with budget system and regional influences
|
|
||||||
*
|
|
||||||
* Implements the revolutionary budget-based generation system from analysis:
|
|
||||||
* - Automatic risk/reward balancing through -10 to +10 scoring
|
|
||||||
* - Regional influences that create specialized geographical zones
|
|
||||||
* - Separation of terrain (always loaded) and resources (on-demand)
|
|
||||||
* - Support for 218+ feature types with budget integration
|
|
||||||
* - Integration with WorldTile class for encapsulated tile logic
|
|
||||||
*/
|
|
||||||
class GMap {
|
|
||||||
private:
|
|
||||||
int width, height;
|
|
||||||
uint64_t world_seed; // Global generation seed
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// TILE DATA - Optimized 24-byte structure
|
|
||||||
// ========================================
|
|
||||||
std::vector<WorldTileData> tiles; // Linear array: index = y * width + x
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// GLOBAL MAPS - Referenced by tiles
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
// Feature sets - collections of features for tiles
|
|
||||||
std::unordered_map<uint32_t, std::vector<uint32_t>> feature_sets; // set_id -> feature_ids
|
|
||||||
uint32_t next_feature_set_id;
|
|
||||||
|
|
||||||
// Individual features - referenced by feature sets
|
|
||||||
std::unordered_map<uint32_t, WorldFeature> features;
|
|
||||||
uint32_t next_feature_id;
|
|
||||||
|
|
||||||
// Regional influences - complex influence data
|
|
||||||
std::unordered_map<uint32_t, json> regional_influences; // influence_id -> influence_data
|
|
||||||
uint32_t next_regional_influence_id;
|
|
||||||
|
|
||||||
// Feature type definitions (loaded from configuration)
|
|
||||||
std::unordered_map<std::string, json> feature_definitions;
|
|
||||||
|
|
||||||
// Budget scoring metadata
|
|
||||||
std::unordered_map<int, int> budget_score_distribution; // Score -> tile count
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// INTERNAL HELPERS - Data access optimization
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get tile index from coordinates
|
|
||||||
*/
|
|
||||||
uint32_t getTileIndex(int x, int y) const { return y * width + x; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get coordinates from tile index
|
|
||||||
*/
|
|
||||||
std::pair<int, int> getCoordinatesFromIndex(uint32_t index) const {
|
|
||||||
return {index % width, index / width};
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct world map with specified dimensions and seed
|
|
||||||
* @param w Map width in tiles
|
|
||||||
* @param h Map height in tiles
|
|
||||||
* @param seed World generation seed for deterministic results
|
|
||||||
*/
|
|
||||||
GMap(int w, int h, uint64_t seed = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor - ensures proper cleanup
|
|
||||||
*/
|
|
||||||
~GMap();
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// BASIC ACCESSORS
|
|
||||||
// ========================================
|
|
||||||
int getWidth() const { return width; }
|
|
||||||
int getHeight() const { return height; }
|
|
||||||
uint64_t getWorldSeed() const { return world_seed; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get lightweight tile wrapper for easy access
|
|
||||||
*/
|
|
||||||
WorldTile getTile(int x, int y);
|
|
||||||
WorldTile getTile(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if coordinates are valid
|
|
||||||
*/
|
|
||||||
bool isValidCoordinate(int x, int y) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// DIRECT TILE DATA ACCESS - For WorldTile wrapper
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
// Direct access to tile data (used by WorldTile)
|
|
||||||
WorldTileData& getTileData(uint32_t tile_index) { return tiles[tile_index]; }
|
|
||||||
const WorldTileData& getTileData(uint32_t tile_index) const { return tiles[tile_index]; }
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// FEATURE SET MANAGEMENT
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create new feature set
|
|
||||||
* @param feature_ids Vector of feature IDs for this set
|
|
||||||
* @return New feature set ID
|
|
||||||
*/
|
|
||||||
uint32_t createFeatureSet(const std::vector<uint32_t>& feature_ids);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get feature IDs from feature set
|
|
||||||
* @param set_id Feature set ID
|
|
||||||
* @return Vector of feature IDs (empty if set doesn't exist)
|
|
||||||
*/
|
|
||||||
std::vector<uint32_t> getFeatureSet(uint32_t set_id) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if feature set exists
|
|
||||||
*/
|
|
||||||
bool hasFeatureSet(uint32_t set_id) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get or create feature set for feature combination
|
|
||||||
* @param feature_ids Vector of feature IDs
|
|
||||||
* @return Feature set ID (existing or newly created)
|
|
||||||
*/
|
|
||||||
uint32_t getOrCreateFeatureSet(const std::vector<uint32_t>& feature_ids);
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// REGIONAL INFLUENCE MANAGEMENT
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create regional influence
|
|
||||||
* @param influence_data JSON data describing the influence
|
|
||||||
* @return New regional influence ID
|
|
||||||
*/
|
|
||||||
uint32_t createRegionalInfluence(const json& influence_data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get regional influence data
|
|
||||||
* @param influence_id Regional influence ID
|
|
||||||
* @return JSON influence data (null if doesn't exist)
|
|
||||||
*/
|
|
||||||
json getRegionalInfluence(uint32_t influence_id) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// INITIALIZATION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize tiles array (called by constructor)
|
|
||||||
*/
|
|
||||||
void initializeTiles();
|
|
||||||
|
|
||||||
// Budget system methods
|
|
||||||
/**
|
|
||||||
* @brief Set target budget score for a tile
|
|
||||||
*/
|
|
||||||
void setTargetBudgetScore(int x, int y, float target_score);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate actual budget score for a tile (delegates to WorldTile)
|
|
||||||
*/
|
|
||||||
float calculateActualBudgetScore(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Update actual budget scores for all tiles
|
|
||||||
*/
|
|
||||||
void updateAllBudgetScores();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get budget score distribution statistics
|
|
||||||
*/
|
|
||||||
json getBudgetScoreDistribution() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Balance budget for a specific tile
|
|
||||||
*/
|
|
||||||
bool balanceTileBudget(int x, int y);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Balance budgets for entire map
|
|
||||||
*/
|
|
||||||
void balanceAllBudgets();
|
|
||||||
|
|
||||||
// Regional influence methods
|
|
||||||
/**
|
|
||||||
* @brief Add regional influence zone
|
|
||||||
*/
|
|
||||||
void addRegionalInfluence(RegionalInfluence influence, const std::vector<std::pair<int, int>>& area);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get regional influence at coordinates
|
|
||||||
*/
|
|
||||||
RegionalInfluence getRegionalInfluence(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get feature probability modifier for location
|
|
||||||
*/
|
|
||||||
float getFeatureProbabilityModifier(int x, int y, const std::string& feature_type) const;
|
|
||||||
|
|
||||||
// Resource patch methods
|
|
||||||
/**
|
|
||||||
* @brief Add resource patch to the map
|
|
||||||
*/
|
|
||||||
uint32_t addResourcePatch(const ResourcePatch& patch);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get resource patch by ID
|
|
||||||
*/
|
|
||||||
const ResourcePatch* getResourcePatch(uint32_t patch_id) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get mutable resource patch by ID
|
|
||||||
*/
|
|
||||||
ResourcePatch* getResourcePatchMutable(uint32_t patch_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get all resource patches affecting a tile
|
|
||||||
*/
|
|
||||||
std::vector<const ResourcePatch*> getResourcePatchesAt(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove resource patch
|
|
||||||
*/
|
|
||||||
bool removeResourcePatch(uint32_t patch_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get all resource patches
|
|
||||||
*/
|
|
||||||
const std::unordered_map<uint32_t, ResourcePatch>& getResourcePatches() const { return resource_patches; }
|
|
||||||
|
|
||||||
// Feature management methods
|
|
||||||
/**
|
|
||||||
* @brief Add feature to the map
|
|
||||||
*/
|
|
||||||
uint32_t addFeature(const WorldFeature& feature);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get feature by ID
|
|
||||||
*/
|
|
||||||
const WorldFeature* getFeature(uint32_t feature_id) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get mutable feature by ID
|
|
||||||
*/
|
|
||||||
WorldFeature* getFeatureMutable(uint32_t feature_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove feature from map
|
|
||||||
*/
|
|
||||||
bool removeFeature(uint32_t feature_id);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get all features
|
|
||||||
*/
|
|
||||||
const std::unordered_map<uint32_t, WorldFeature>& getFeatures() const { return features; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set feature type definitions
|
|
||||||
*/
|
|
||||||
void setFeatureDefinitions(const std::unordered_map<std::string, json>& definitions);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get feature type definitions
|
|
||||||
*/
|
|
||||||
const std::unordered_map<std::string, json>& getFeatureDefinitions() const { return feature_definitions; }
|
|
||||||
|
|
||||||
// Serialization methods
|
|
||||||
/**
|
|
||||||
* @brief Export entire map to JSON
|
|
||||||
*/
|
|
||||||
json toJson() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Import map from JSON data
|
|
||||||
*/
|
|
||||||
void fromJson(const json& data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Export region to JSON for networking/storage
|
|
||||||
*/
|
|
||||||
json exportRegion(int start_x, int start_y, int region_width, int region_height) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Import region from JSON (for streaming/networking)
|
|
||||||
*/
|
|
||||||
void importRegion(const json& region_data, int start_x, int start_y);
|
|
||||||
|
|
||||||
// Utility methods
|
|
||||||
/**
|
|
||||||
* @brief Clear all data and reset to default state
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate deterministic tile seed for procedural generation
|
|
||||||
*/
|
|
||||||
uint32_t getTileSeed(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Validate map consistency
|
|
||||||
*/
|
|
||||||
bool validate() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get memory usage statistics
|
|
||||||
*/
|
|
||||||
json getMemoryStats() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Optimize memory usage (remove unused patches, compact vectors)
|
|
||||||
*/
|
|
||||||
void optimizeMemory();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,249 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
// Forward declarations
|
|
||||||
class GMap;
|
|
||||||
struct PlanetaryCore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Interface for step-by-step world generation layers
|
|
||||||
*
|
|
||||||
* Enables cycle-by-cycle execution of geological, climate, and resource generation
|
|
||||||
* phases with progress tracking and debugging capabilities.
|
|
||||||
*/
|
|
||||||
class IGenerationLayer {
|
|
||||||
public:
|
|
||||||
virtual ~IGenerationLayer() = default;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// STEP-BY-STEP EXECUTION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Execute one step/cycle of generation
|
|
||||||
* @param map World map to modify
|
|
||||||
* @param core Planetary core for mass conservation
|
|
||||||
* @param config Layer-specific configuration
|
|
||||||
* @return true if layer has more steps to execute
|
|
||||||
*/
|
|
||||||
virtual bool executeStep(GMap& map, PlanetaryCore& core, const json& config) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if layer has more steps to execute
|
|
||||||
* @return true if more steps available
|
|
||||||
*/
|
|
||||||
virtual bool hasMoreSteps() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reset layer to initial state
|
|
||||||
*/
|
|
||||||
virtual void reset() = 0;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// PROGRESS TRACKING
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current step number (0-based)
|
|
||||||
* @return Current step index
|
|
||||||
*/
|
|
||||||
virtual int getCurrentStep() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get total number of steps in this layer
|
|
||||||
* @return Total step count
|
|
||||||
*/
|
|
||||||
virtual int getTotalSteps() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get human-readable description of current step
|
|
||||||
* @return Step description (e.g., "Phase 2 Cycle 15")
|
|
||||||
*/
|
|
||||||
virtual std::string getStepDescription() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get layer completion progress
|
|
||||||
* @return Progress as percentage (0.0-1.0)
|
|
||||||
*/
|
|
||||||
virtual float getProgress() const = 0;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// LAYER METADATA
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get layer name for identification
|
|
||||||
* @return Layer name (e.g., "Geological", "Climate")
|
|
||||||
*/
|
|
||||||
virtual std::string getName() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get estimated time for this layer
|
|
||||||
* @return Estimated seconds for completion
|
|
||||||
*/
|
|
||||||
virtual float getEstimatedDuration() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if layer is currently active
|
|
||||||
* @return true if layer is executing
|
|
||||||
*/
|
|
||||||
virtual bool isActive() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if layer execution is complete
|
|
||||||
* @return true if all steps finished
|
|
||||||
*/
|
|
||||||
virtual bool isComplete() const = 0;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CONFIGURATION AND VALIDATION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Validate configuration before execution
|
|
||||||
* @param config Configuration JSON to validate
|
|
||||||
* @return true if configuration is valid
|
|
||||||
*/
|
|
||||||
virtual bool validateConfig(const json& config) const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get default configuration for this layer
|
|
||||||
* @return Default JSON configuration
|
|
||||||
*/
|
|
||||||
virtual json getDefaultConfig() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get required configuration parameters
|
|
||||||
* @return Vector of required parameter names
|
|
||||||
*/
|
|
||||||
virtual std::vector<std::string> getRequiredConfigParams() const = 0;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// DEBUGGING AND MONITORING
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get detailed status information
|
|
||||||
* @return JSON with current state details
|
|
||||||
*/
|
|
||||||
virtual json getDetailedStatus() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get performance metrics for this layer
|
|
||||||
* @return JSON with timing and performance data
|
|
||||||
*/
|
|
||||||
virtual json getPerformanceMetrics() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enable/disable detailed logging
|
|
||||||
* @param enabled Whether to enable verbose logging
|
|
||||||
*/
|
|
||||||
virtual void setVerboseLogging(bool enabled) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if layer can be paused mid-execution
|
|
||||||
* @return true if pausable
|
|
||||||
*/
|
|
||||||
virtual bool isPausable() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Pause layer execution
|
|
||||||
*/
|
|
||||||
virtual void pause() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Resume layer execution
|
|
||||||
*/
|
|
||||||
virtual void resume() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Base implementation with common functionality
|
|
||||||
*
|
|
||||||
* Provides standard implementations for common layer operations.
|
|
||||||
* Derived layers only need to implement generation-specific logic.
|
|
||||||
*/
|
|
||||||
class GenerationLayerBase : public IGenerationLayer {
|
|
||||||
protected:
|
|
||||||
// State tracking
|
|
||||||
int current_step = 0;
|
|
||||||
int total_steps = 0;
|
|
||||||
bool active = false;
|
|
||||||
bool complete = false;
|
|
||||||
bool paused = false;
|
|
||||||
bool verbose_logging = false;
|
|
||||||
|
|
||||||
// Performance tracking
|
|
||||||
mutable float execution_time = 0.0f;
|
|
||||||
mutable int steps_executed = 0;
|
|
||||||
|
|
||||||
// Layer metadata
|
|
||||||
std::string layer_name;
|
|
||||||
float estimated_duration = 0.0f;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
* @param name Layer name
|
|
||||||
* @param steps Total number of steps
|
|
||||||
* @param duration Estimated duration in seconds
|
|
||||||
*/
|
|
||||||
GenerationLayerBase(const std::string& name, int steps, float duration);
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// COMMON IMPLEMENTATIONS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
float getProgress() const override;
|
|
||||||
std::string getName() const override { return layer_name; }
|
|
||||||
float getEstimatedDuration() const override { return estimated_duration; }
|
|
||||||
bool isActive() const override { return active; }
|
|
||||||
bool isComplete() const override { return complete; }
|
|
||||||
int getCurrentStep() const override { return current_step; }
|
|
||||||
int getTotalSteps() const override { return total_steps; }
|
|
||||||
|
|
||||||
void reset() override;
|
|
||||||
void pause() override { paused = true; }
|
|
||||||
void resume() override { paused = false; }
|
|
||||||
bool isPausable() const override { return true; }
|
|
||||||
void setVerboseLogging(bool enabled) override { verbose_logging = enabled; }
|
|
||||||
|
|
||||||
json getPerformanceMetrics() const override;
|
|
||||||
json getDetailedStatus() const override;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// TO BE IMPLEMENTED BY DERIVED CLASSES
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
virtual bool executeStep(GMap& map, PlanetaryCore& core, const json& config) override = 0;
|
|
||||||
virtual std::string getStepDescription() const override = 0;
|
|
||||||
virtual bool validateConfig(const json& config) const override = 0;
|
|
||||||
virtual json getDefaultConfig() const override = 0;
|
|
||||||
virtual std::vector<std::string> getRequiredConfigParams() const override = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/**
|
|
||||||
* @brief Mark step as complete and advance
|
|
||||||
* @return true if more steps available
|
|
||||||
*/
|
|
||||||
bool advanceStep();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Mark layer as complete
|
|
||||||
*/
|
|
||||||
void markComplete();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Log message if verbose logging enabled
|
|
||||||
* @param message Message to log
|
|
||||||
*/
|
|
||||||
void logVerbose(const std::string& message) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include "warfactory/IDataNode.h"
|
|
||||||
|
|
||||||
class WorldData;
|
|
||||||
class IWorldGenerationStep;
|
|
||||||
|
|
||||||
class IWorldGenerationPhase {
|
|
||||||
public:
|
|
||||||
virtual ~IWorldGenerationPhase() = default;
|
|
||||||
|
|
||||||
virtual std::string getPhaseName() const = 0;
|
|
||||||
|
|
||||||
virtual std::vector<std::unique_ptr<IWorldGenerationStep>> getSteps() const = 0;
|
|
||||||
|
|
||||||
virtual bool execute(WorldData& world, const IDataNode& config) = 0;
|
|
||||||
|
|
||||||
virtual float getProgress() const = 0;
|
|
||||||
|
|
||||||
virtual bool isComplete() const = 0;
|
|
||||||
|
|
||||||
virtual void reset() = 0;
|
|
||||||
|
|
||||||
virtual std::string getPhaseDescription() const = 0;
|
|
||||||
|
|
||||||
virtual int getPhaseNumber() const = 0;
|
|
||||||
};
|
|
||||||
@ -1,31 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "warfactory/IDataNode.h"
|
|
||||||
|
|
||||||
class WorldData;
|
|
||||||
|
|
||||||
class IWorldGenerationStep {
|
|
||||||
public:
|
|
||||||
virtual ~IWorldGenerationStep() = default;
|
|
||||||
|
|
||||||
virtual std::string getStepName() const = 0;
|
|
||||||
|
|
||||||
virtual bool execute(WorldData& world, const IDataNode& config) = 0;
|
|
||||||
|
|
||||||
virtual bool canExecute(const WorldData& world) const = 0;
|
|
||||||
|
|
||||||
virtual float getProgress() const = 0;
|
|
||||||
|
|
||||||
virtual bool isComplete() const = 0;
|
|
||||||
|
|
||||||
virtual void reset() = 0;
|
|
||||||
|
|
||||||
virtual std::string getStepDescription() const = 0;
|
|
||||||
|
|
||||||
virtual float getEstimatedDuration() const = 0;
|
|
||||||
|
|
||||||
virtual std::vector<std::string> getRequiredPreviousSteps() const = 0;
|
|
||||||
|
|
||||||
virtual std::vector<std::string> getProducedData() const = 0;
|
|
||||||
};
|
|
||||||
@ -1,259 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Planetary core system for mass conservation
|
|
||||||
*
|
|
||||||
* Manages planetary mass conservation by accumulating eroded material
|
|
||||||
* and releasing it through volcanic activity when core reaches saturation.
|
|
||||||
*/
|
|
||||||
struct PlanetaryCore {
|
|
||||||
// ========================================
|
|
||||||
// MASS TRACKING
|
|
||||||
// ========================================
|
|
||||||
float core_mass; // Accumulated eroded material (kg)
|
|
||||||
float surface_mass; // Current surface terrain mass (kg)
|
|
||||||
float total_planetary_mass; // Constant after Phase 1 (kg)
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// VOLCANIC SYSTEM
|
|
||||||
// ========================================
|
|
||||||
float max_core_capacity; // Core saturation threshold (kg)
|
|
||||||
float volcanic_overflow_rate; // Rate of material expulsion (0.1-0.3)
|
|
||||||
float pending_volcanic_material; // Material queued for volcanic release (kg)
|
|
||||||
int pending_volcanic_events; // Number of queued eruptions
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CONFIGURATION PARAMETERS
|
|
||||||
// ========================================
|
|
||||||
float volcanic_event_mass_threshold; // Minimum mass per volcanic event (kg)
|
|
||||||
float volcanic_density_factor; // Material density for eruption radius calculation
|
|
||||||
float core_pressure_buildup_rate; // Rate of pressure increase
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// DERIVED VALUES
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get core pressure ratio (0.0-1.0+)
|
|
||||||
* @return core_mass / max_core_capacity
|
|
||||||
*/
|
|
||||||
float getCorePressureRatio() const {
|
|
||||||
return core_mass / max_core_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if core is approaching saturation
|
|
||||||
* @return true if pressure ratio > 0.8
|
|
||||||
*/
|
|
||||||
bool isNearSaturation() const {
|
|
||||||
return getCorePressureRatio() > 0.8f;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if core overflow is occurring
|
|
||||||
* @return true if core_mass > max_core_capacity
|
|
||||||
*/
|
|
||||||
bool isOverflowing() const {
|
|
||||||
return core_mass > max_core_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get overflow amount
|
|
||||||
* @return Amount of mass above capacity (0 if no overflow)
|
|
||||||
*/
|
|
||||||
float getOverflowAmount() const {
|
|
||||||
return std::max(0.0f, core_mass - max_core_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Validate mass conservation
|
|
||||||
* @return true if total mass is conserved
|
|
||||||
*/
|
|
||||||
bool validateMassConservation() const {
|
|
||||||
float total_current = core_mass + surface_mass + pending_volcanic_material;
|
|
||||||
float tolerance = total_planetary_mass * 0.001f; // 0.1% tolerance
|
|
||||||
return std::abs(total_current - total_planetary_mass) < tolerance;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CONSTRUCTION AND INITIALIZATION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default constructor
|
|
||||||
*/
|
|
||||||
PlanetaryCore() :
|
|
||||||
core_mass(0.0f),
|
|
||||||
surface_mass(0.0f),
|
|
||||||
total_planetary_mass(0.0f),
|
|
||||||
max_core_capacity(0.0f),
|
|
||||||
volcanic_overflow_rate(0.2f),
|
|
||||||
pending_volcanic_material(0.0f),
|
|
||||||
pending_volcanic_events(0),
|
|
||||||
volcanic_event_mass_threshold(1000000.0f), // 1M kg per event
|
|
||||||
volcanic_density_factor(100000.0f), // 100k kg/m²
|
|
||||||
core_pressure_buildup_rate(0.1f)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize core for world generation
|
|
||||||
* @param initial_surface_mass Starting surface mass
|
|
||||||
* @param capacity_ratio Core capacity as ratio of total mass (0.3-0.7)
|
|
||||||
*/
|
|
||||||
void initialize(float initial_surface_mass, float capacity_ratio = 0.5f) {
|
|
||||||
surface_mass = initial_surface_mass;
|
|
||||||
total_planetary_mass = initial_surface_mass;
|
|
||||||
core_mass = 0.0f;
|
|
||||||
max_core_capacity = total_planetary_mass * capacity_ratio;
|
|
||||||
pending_volcanic_material = 0.0f;
|
|
||||||
pending_volcanic_events = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// MASS TRANSFER OPERATIONS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Transfer eroded material to core
|
|
||||||
* @param erosion_amount Amount of material eroded (kg)
|
|
||||||
*/
|
|
||||||
void addErodedMaterial(float erosion_amount) {
|
|
||||||
core_mass += erosion_amount;
|
|
||||||
surface_mass -= erosion_amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add meteorite material to system (Phase 1 only)
|
|
||||||
* @param meteorite_mass Mass of meteorite impact (kg)
|
|
||||||
*/
|
|
||||||
void addMeteoriteMaterial(float meteorite_mass) {
|
|
||||||
surface_mass += meteorite_mass;
|
|
||||||
total_planetary_mass += meteorite_mass;
|
|
||||||
|
|
||||||
// Update core capacity proportionally
|
|
||||||
max_core_capacity = total_planetary_mass * (max_core_capacity / (total_planetary_mass - meteorite_mass));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Release volcanic material to surface
|
|
||||||
* @param volcanic_amount Amount of material to release (kg)
|
|
||||||
*/
|
|
||||||
void releaseVolcanicMaterial(float volcanic_amount) {
|
|
||||||
if (volcanic_amount <= pending_volcanic_material) {
|
|
||||||
pending_volcanic_material -= volcanic_amount;
|
|
||||||
surface_mass += volcanic_amount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// VOLCANIC OVERFLOW PROCESSING
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Process core overflow and generate volcanic events
|
|
||||||
*/
|
|
||||||
void processOverflow() {
|
|
||||||
if (!isOverflowing()) return;
|
|
||||||
|
|
||||||
float overflow = getOverflowAmount();
|
|
||||||
float volcanic_expulsion = overflow * volcanic_overflow_rate;
|
|
||||||
|
|
||||||
// Transfer mass from core to pending volcanic events
|
|
||||||
core_mass -= volcanic_expulsion;
|
|
||||||
pending_volcanic_material += volcanic_expulsion;
|
|
||||||
|
|
||||||
// Queue volcanic events proportional to overflow
|
|
||||||
int new_events = static_cast<int>(volcanic_expulsion / volcanic_event_mass_threshold);
|
|
||||||
pending_volcanic_events += new_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get material amount for next volcanic event
|
|
||||||
* @return Material amount per event (kg)
|
|
||||||
*/
|
|
||||||
float getNextVolcanicEventMaterial() const {
|
|
||||||
if (pending_volcanic_events <= 0) return 0.0f;
|
|
||||||
return pending_volcanic_material / pending_volcanic_events;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Consume one volcanic event
|
|
||||||
* @return Material amount released (kg)
|
|
||||||
*/
|
|
||||||
float consumeVolcanicEvent() {
|
|
||||||
if (pending_volcanic_events <= 0) return 0.0f;
|
|
||||||
|
|
||||||
float event_material = getNextVolcanicEventMaterial();
|
|
||||||
pending_volcanic_events--;
|
|
||||||
|
|
||||||
return event_material;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// STATISTICS AND MONITORING
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get core statistics
|
|
||||||
* @return JSON with detailed core information
|
|
||||||
*/
|
|
||||||
json getStatistics() const {
|
|
||||||
return json{
|
|
||||||
{"core_mass", core_mass},
|
|
||||||
{"surface_mass", surface_mass},
|
|
||||||
{"total_planetary_mass", total_planetary_mass},
|
|
||||||
{"max_core_capacity", max_core_capacity},
|
|
||||||
{"pending_volcanic_material", pending_volcanic_material},
|
|
||||||
{"pending_volcanic_events", pending_volcanic_events},
|
|
||||||
{"core_pressure_ratio", getCorePressureRatio()},
|
|
||||||
{"is_near_saturation", isNearSaturation()},
|
|
||||||
{"is_overflowing", isOverflowing()},
|
|
||||||
{"overflow_amount", getOverflowAmount()},
|
|
||||||
{"mass_conservation_valid", validateMassConservation()}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Export core state to JSON
|
|
||||||
* @return JSON representation
|
|
||||||
*/
|
|
||||||
json toJson() const {
|
|
||||||
return json{
|
|
||||||
{"core_mass", core_mass},
|
|
||||||
{"surface_mass", surface_mass},
|
|
||||||
{"total_planetary_mass", total_planetary_mass},
|
|
||||||
{"max_core_capacity", max_core_capacity},
|
|
||||||
{"volcanic_overflow_rate", volcanic_overflow_rate},
|
|
||||||
{"pending_volcanic_material", pending_volcanic_material},
|
|
||||||
{"pending_volcanic_events", pending_volcanic_events},
|
|
||||||
{"volcanic_event_mass_threshold", volcanic_event_mass_threshold},
|
|
||||||
{"volcanic_density_factor", volcanic_density_factor},
|
|
||||||
{"core_pressure_buildup_rate", core_pressure_buildup_rate}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Import core state from JSON
|
|
||||||
* @param data JSON data to import
|
|
||||||
*/
|
|
||||||
void fromJson(const json& data) {
|
|
||||||
core_mass = data.value("core_mass", 0.0f);
|
|
||||||
surface_mass = data.value("surface_mass", 0.0f);
|
|
||||||
total_planetary_mass = data.value("total_planetary_mass", 0.0f);
|
|
||||||
max_core_capacity = data.value("max_core_capacity", 0.0f);
|
|
||||||
volcanic_overflow_rate = data.value("volcanic_overflow_rate", 0.2f);
|
|
||||||
pending_volcanic_material = data.value("pending_volcanic_material", 0.0f);
|
|
||||||
pending_volcanic_events = data.value("pending_volcanic_events", 0);
|
|
||||||
volcanic_event_mass_threshold = data.value("volcanic_event_mass_threshold", 1000000.0f);
|
|
||||||
volcanic_density_factor = data.value("volcanic_density_factor", 100000.0f);
|
|
||||||
core_pressure_buildup_rate = data.value("core_pressure_buildup_rate", 0.1f);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,354 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "IModule.h"
|
|
||||||
#include "GMap.h"
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Feature categories based on WORLDGEN_ANALYSIS.md comprehensive analysis
|
|
||||||
*/
|
|
||||||
enum class FeatureCategory {
|
|
||||||
// Natural geological formations
|
|
||||||
GEOLOGICAL_FORMATIONS, // Caves, thermal springs, salt deposits, meteorites, geysers
|
|
||||||
GEOLOGICAL_RESOURCES, // Basic minerals (iron, copper, coal) and precious (gold, uranium, iridium)
|
|
||||||
|
|
||||||
// Water-related features
|
|
||||||
AQUATIC_NATURAL, // Lakes, ponds, river deltas, fjords, waterfalls, springs
|
|
||||||
AQUATIC_SPECIAL, // Marshlands, dried lakes, geysers, mountain oases
|
|
||||||
|
|
||||||
// Land formations
|
|
||||||
TERRESTRIAL_LANDFORMS, // Canyons, plateaus, valleys, plains, dunes, glaciers
|
|
||||||
TERRESTRIAL_SPECIAL, // Oases, mountain passes, craters, calderas, badlands
|
|
||||||
|
|
||||||
// Coastal and maritime
|
|
||||||
COASTAL_NATURAL, // Protected bays, cliffs, beaches, coral reefs, estuaries
|
|
||||||
COASTAL_FORMATIONS, // Peninsulas, straits, coastal islands, rifts
|
|
||||||
|
|
||||||
// Historical industrial sites
|
|
||||||
INDUSTRIAL_ABANDONED, // Terikons, ghost towns, textile mills, power plants, steelworks
|
|
||||||
INDUSTRIAL_CHEMICAL, // Refineries, chemical complexes, distilleries, glass works
|
|
||||||
|
|
||||||
// Vehicle graveyards and scrap sites
|
|
||||||
VEHICLE_GRAVEYARDS, // Tank, car, plane, train, boat cemeteries, electronic dumps
|
|
||||||
SCRAP_SITES, // Open-air dumps, service stations, electronic waste
|
|
||||||
|
|
||||||
// Abandoned military installations
|
|
||||||
MILITARY_COLD_WAR, // Cold War bases, missile sites, naval bases, airfields
|
|
||||||
MILITARY_HISTORICAL, // WWI sites, Nazi bunkers, inactive minefields, munition depots
|
|
||||||
|
|
||||||
// Cultural and archaeological
|
|
||||||
CULTURAL_ANCIENT, // Ancient ruins, medieval vestiges, archaeological sites
|
|
||||||
CULTURAL_HISTORICAL, // Historical monuments, cultural landmarks
|
|
||||||
|
|
||||||
// Natural ecosystems and biomes
|
|
||||||
BIOMES_FOREST, // Dense forests, boreal forests, tropical rainforests
|
|
||||||
BIOMES_GRASSLAND, // Steppes, pampas, prairies, savannas
|
|
||||||
BIOMES_EXTREME, // Deserts, arctic tundra, volcanic areas, wetlands
|
|
||||||
|
|
||||||
// Geological anomalies and special formations
|
|
||||||
GEOLOGICAL_ANOMALIES, // Magnetic anomalies, monoliths, radio silence zones
|
|
||||||
GEOLOGICAL_EXTREME, // Active fault lines, karst formations, amber deposits
|
|
||||||
|
|
||||||
// Climate and weather phenomena
|
|
||||||
CLIMATE_PHENOMENA, // Cloud forests, chaparral, permafrost zones
|
|
||||||
WEATHER_PATTERNS, // Microclimate zones, wind corridors
|
|
||||||
|
|
||||||
// Modern infrastructure (abandoned or ruins)
|
|
||||||
INFRASTRUCTURE_TRANSPORT, // Abandoned roads, rail lines, bridges, tunnels
|
|
||||||
INFRASTRUCTURE_UTILITY, // Power lines, communication towers, pipelines
|
|
||||||
|
|
||||||
// Mysterious and unexplained phenomena
|
|
||||||
MYSTERIOUS_PHENOMENA, // Unexplained formations, anomalous zones, strange sites
|
|
||||||
|
|
||||||
CATEGORY_COUNT = 18
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Resource integration types within features
|
|
||||||
*/
|
|
||||||
enum class ResourceIntegrationType {
|
|
||||||
STANDALONE_DEPOSIT, // Pure resource patch (iron ore, copper vein)
|
|
||||||
FEATURE_INTEGRATED, // Resource within feature (meteorite metals, scrap in ruins)
|
|
||||||
FEATURE_BYPRODUCT, // Secondary resource from feature (amber inclusions)
|
|
||||||
FEATURE_HIDDEN, // Concealed resource requiring exploration
|
|
||||||
FEATURE_PROCESSING // Resource requiring processing/refinement
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief World feature with integrated resources and budget scoring
|
|
||||||
*/
|
|
||||||
struct WorldFeature {
|
|
||||||
uint32_t feature_id; // Unique feature identifier
|
|
||||||
std::string feature_type; // Specific feature type name
|
|
||||||
FeatureCategory category; // Primary feature category
|
|
||||||
|
|
||||||
// Location and extent
|
|
||||||
int center_x, center_y; // Feature center coordinates
|
|
||||||
std::vector<std::pair<int, int>> affected_tiles; // All tiles covered by feature
|
|
||||||
|
|
||||||
// Budget system integration
|
|
||||||
float base_budget_score; // Base score for this feature type
|
|
||||||
float adjusted_budget_score; // Score adjusted for regional influences
|
|
||||||
float calculated_budget_contribution; // Actual contribution to tile budget
|
|
||||||
|
|
||||||
// Resource integration
|
|
||||||
std::vector<std::pair<uint16_t, ResourceIntegrationType>> integrated_resources;
|
|
||||||
std::unordered_map<uint16_t, uint64_t> resource_quantities; // Resource ID -> quantity
|
|
||||||
|
|
||||||
// Feature properties and metadata
|
|
||||||
json feature_properties; // Feature-specific data
|
|
||||||
json discovery_requirements; // Requirements to discover/access
|
|
||||||
|
|
||||||
// Regional and probability data
|
|
||||||
RegionalInfluence required_influence; // Regional influence that enables this feature
|
|
||||||
float base_probability; // Base generation probability
|
|
||||||
float regional_probability_modifier; // Regional modifier (e.g., 8× for terikons in mining zones)
|
|
||||||
|
|
||||||
// Gameplay mechanics
|
|
||||||
bool requires_exploration; // True if hidden resources/properties exist
|
|
||||||
bool modifies_terrain; // True if feature changes terrain traversability
|
|
||||||
bool provides_strategic_value; // True if feature has military/strategic importance
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert feature to JSON representation
|
|
||||||
*/
|
|
||||||
json toJson() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create feature from JSON data
|
|
||||||
*/
|
|
||||||
static WorldFeature fromJson(const json& data);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate total budget contribution including all resources
|
|
||||||
*/
|
|
||||||
float calculateTotalBudgetContribution() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get resource quantity for specific type
|
|
||||||
*/
|
|
||||||
uint64_t getResourceQuantity(uint16_t resource_type_id) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if feature provides specific resource
|
|
||||||
*/
|
|
||||||
bool providesResource(uint16_t resource_type_id) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief World feature placement and budget balancing module
|
|
||||||
*
|
|
||||||
* Implements the revolutionary budget-based feature generation system from analysis:
|
|
||||||
* - Places 218+ feature types across 18 categories
|
|
||||||
* - Integrates resources directly into features (meteorite metals, scrap in ruins)
|
|
||||||
* - Implements -10 to +10 budget scoring with automatic risk/reward balancing
|
|
||||||
* - Applies regional influences (8× terikon probability in mining zones)
|
|
||||||
* - Manages discovery system with visible/hidden feature properties
|
|
||||||
*
|
|
||||||
* Configuration loaded from gameData/:
|
|
||||||
* - MapFeatures/ - Feature type definitions and properties
|
|
||||||
* - Ressources/ - Resource type definitions and integration patterns
|
|
||||||
* - WorldGeneration/ - Budget scoring rules and regional influences
|
|
||||||
* - Biomes/ - Biome-feature compatibility matrices
|
|
||||||
*/
|
|
||||||
class WorldFeatureModule : public IModule {
|
|
||||||
private:
|
|
||||||
// Feature management
|
|
||||||
std::vector<WorldFeature> placed_features;
|
|
||||||
std::unordered_map<uint32_t, size_t> feature_id_to_index;
|
|
||||||
uint32_t next_feature_id;
|
|
||||||
|
|
||||||
// World reference and generation state
|
|
||||||
GMap* world_map; // Mutable reference for budget modifications
|
|
||||||
uint64_t feature_seed;
|
|
||||||
bool features_generated;
|
|
||||||
bool budget_balanced;
|
|
||||||
|
|
||||||
// Configuration data
|
|
||||||
std::unordered_map<std::string, json> feature_type_definitions;
|
|
||||||
std::unordered_map<uint16_t, json> resource_type_definitions;
|
|
||||||
std::unordered_map<FeatureCategory, std::vector<std::string>> features_by_category;
|
|
||||||
|
|
||||||
// Budget system data
|
|
||||||
std::unordered_map<int, float> target_budget_distribution; // Target % per score
|
|
||||||
std::unordered_map<int, int> actual_budget_distribution; // Actual tile count per score
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load all feature and resource definitions from configuration
|
|
||||||
*/
|
|
||||||
void loadFeatureDefinitions(const IDataNode& config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load resource integration patterns
|
|
||||||
*/
|
|
||||||
void loadResourceIntegrationPatterns(const IDataNode& config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate feature placement probability for location
|
|
||||||
*/
|
|
||||||
float calculateFeaturePlacementProbability(const std::string& feature_type, int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Place features by category with budget balancing
|
|
||||||
*/
|
|
||||||
void placeFeatureCategory(FeatureCategory category);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Attempt to place single feature at location
|
|
||||||
*/
|
|
||||||
bool attemptFeaturePlacement(const std::string& feature_type, int x, int y);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate budget impact of placing feature at location
|
|
||||||
*/
|
|
||||||
float calculateBudgetImpact(const std::string& feature_type, int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Balance tile budgets by adding/removing features
|
|
||||||
*/
|
|
||||||
void balanceRegionBudgets();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check biome-feature compatibility
|
|
||||||
*/
|
|
||||||
bool isFeatureCompatibleWithBiome(const std::string& feature_type, BiomeType biome) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate integrated resources for feature
|
|
||||||
*/
|
|
||||||
void generateIntegratedResources(WorldFeature& feature);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Apply regional probability modifiers
|
|
||||||
*/
|
|
||||||
float applyRegionalModifiers(const std::string& feature_type, int x, int y, float base_probability) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
*/
|
|
||||||
WorldFeatureModule();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor
|
|
||||||
*/
|
|
||||||
virtual ~WorldFeatureModule() = default;
|
|
||||||
|
|
||||||
// IModule interface implementation
|
|
||||||
void setConfiguration(const IDataNode& configNode, IIO* io, ITaskScheduler* scheduler) override;
|
|
||||||
const IDataNode& getConfiguration() override;
|
|
||||||
json process(const json& input) override;
|
|
||||||
void shutdown() override;
|
|
||||||
json getState() override;
|
|
||||||
void setState(const json& state) override;
|
|
||||||
json getHealthStatus() override;
|
|
||||||
std::string getType() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set reference to world map for feature placement
|
|
||||||
* @param map Mutable reference to generated world map
|
|
||||||
*/
|
|
||||||
void setWorldMap(GMap* map);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate and place all features with budget balancing
|
|
||||||
* @return JSON status with budget distribution and feature statistics
|
|
||||||
*/
|
|
||||||
json generateFeaturesWithBudgetBalancing();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Place features for specific category
|
|
||||||
* @param category Feature category to place
|
|
||||||
* @return JSON status of placement for category
|
|
||||||
*/
|
|
||||||
json placeFeaturesForCategory(FeatureCategory category);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get features in region with resource information
|
|
||||||
* @param startX Starting X coordinate
|
|
||||||
* @param startY Starting Y coordinate
|
|
||||||
* @param width Region width
|
|
||||||
* @param height Region height
|
|
||||||
* @param include_hidden Include features requiring exploration
|
|
||||||
* @return JSON array of features with resources
|
|
||||||
*/
|
|
||||||
json getFeaturesInRegion(int startX, int startY, int width, int height, bool include_hidden = false) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get features at specific coordinates
|
|
||||||
* @param x World X coordinate
|
|
||||||
* @param y World Y coordinate
|
|
||||||
* @param include_hidden Include hidden feature properties
|
|
||||||
* @return JSON array of features at location
|
|
||||||
*/
|
|
||||||
json getFeaturesAt(int x, int y, bool include_hidden = false) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get features by category with resource breakdown
|
|
||||||
* @param category Feature category to filter by
|
|
||||||
* @return JSON array of features with integrated resource data
|
|
||||||
*/
|
|
||||||
json getFeaturesByCategory(FeatureCategory category) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current budget score distribution
|
|
||||||
* @return JSON with target vs actual budget distribution
|
|
||||||
*/
|
|
||||||
json getBudgetScoreDistribution() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if budget is balanced according to target distribution
|
|
||||||
* @return true if budget distribution matches targets within tolerance
|
|
||||||
*/
|
|
||||||
bool isBudgetBalanced() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Force budget rebalancing for specific region
|
|
||||||
* @param startX Starting X coordinate
|
|
||||||
* @param startY Starting Y coordinate
|
|
||||||
* @param width Region width
|
|
||||||
* @param height Region height
|
|
||||||
* @return JSON status of rebalancing operation
|
|
||||||
*/
|
|
||||||
json rebalanceRegionBudget(int startX, int startY, int width, int height);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get available feature types by category
|
|
||||||
* @return JSON mapping of categories to available feature types
|
|
||||||
*/
|
|
||||||
json getAvailableFeatureTypes() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get comprehensive feature and resource statistics
|
|
||||||
* @return JSON with feature counts, resource distribution, budget analysis
|
|
||||||
*/
|
|
||||||
json getComprehensiveStats() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set feature generation seed for deterministic results
|
|
||||||
* @param seed New seed value
|
|
||||||
*/
|
|
||||||
void setFeatureSeed(uint64_t seed);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current feature generation seed
|
|
||||||
* @return Current seed value
|
|
||||||
*/
|
|
||||||
uint64_t getFeatureSeed() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if features have been generated and budget balanced
|
|
||||||
* @return true if complete generation finished successfully
|
|
||||||
*/
|
|
||||||
bool isGenerationComplete() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,143 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "IModule.h"
|
|
||||||
#include "GMap.h"
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief World generation module for creating the global world map
|
|
||||||
*
|
|
||||||
* This module generates the complete world map using procedural algorithms.
|
|
||||||
* It handles terrain generation, biome placement, elevation calculation,
|
|
||||||
* and geographical feature placement.
|
|
||||||
*
|
|
||||||
* Configuration is loaded from gameData/:
|
|
||||||
* - WorldGeneration/ - Generation algorithms and parameters
|
|
||||||
* - Biomes/ - Biome definitions and properties
|
|
||||||
* - Terrain/ - Terrain type definitions
|
|
||||||
* - MapFeatures/ - Geographical features
|
|
||||||
*/
|
|
||||||
class WorldGenerationModule : public IModule {
|
|
||||||
private:
|
|
||||||
std::unique_ptr<GMap> worldMap;
|
|
||||||
uint64_t generationSeed;
|
|
||||||
bool isWorldGenerated;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load generation parameters from configuration
|
|
||||||
*/
|
|
||||||
void loadGenerationConfig(const IDataNode& config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate terrain using procedural algorithms
|
|
||||||
*/
|
|
||||||
void generateTerrain();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Apply biomes based on temperature and humidity
|
|
||||||
*/
|
|
||||||
void generateBiomes();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate elevation using noise functions
|
|
||||||
*/
|
|
||||||
void generateElevation();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Place geographical features (rivers, mountains, etc.)
|
|
||||||
*/
|
|
||||||
void generateFeatures();
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
*/
|
|
||||||
WorldGenerationModule();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor
|
|
||||||
*/
|
|
||||||
virtual ~WorldGenerationModule() = default;
|
|
||||||
|
|
||||||
// IModule interface implementation
|
|
||||||
void setConfiguration(const IDataNode& configNode, IIO* io, ITaskScheduler* scheduler) override;
|
|
||||||
const IDataNode& getConfiguration() override;
|
|
||||||
json process(const json& input) override;
|
|
||||||
void shutdown() override;
|
|
||||||
json getState() override;
|
|
||||||
void setState(const json& state) override;
|
|
||||||
json getHealthStatus() override;
|
|
||||||
std::string getType() const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate the complete world map
|
|
||||||
* @return JSON status of generation
|
|
||||||
*/
|
|
||||||
json generateWorldMap();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get terrain type at world coordinates
|
|
||||||
* @param x World X coordinate
|
|
||||||
* @param y World Y coordinate
|
|
||||||
* @return Terrain type string
|
|
||||||
*/
|
|
||||||
std::string getTerrainAt(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get biome type at world coordinates
|
|
||||||
* @param x World X coordinate
|
|
||||||
* @param y World Y coordinate
|
|
||||||
* @return Biome type string
|
|
||||||
*/
|
|
||||||
std::string getBiomeAt(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get elevation at world coordinates
|
|
||||||
* @param x World X coordinate
|
|
||||||
* @param y World Y coordinate
|
|
||||||
* @return Elevation value
|
|
||||||
*/
|
|
||||||
float getElevationAt(int x, int y) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get world map dimensions
|
|
||||||
* @return JSON with width and height
|
|
||||||
*/
|
|
||||||
json getWorldDimensions() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Export region of the world map
|
|
||||||
* @param startX Starting X coordinate
|
|
||||||
* @param startY Starting Y coordinate
|
|
||||||
* @param width Region width
|
|
||||||
* @param height Region height
|
|
||||||
* @return JSON representation of the region
|
|
||||||
*/
|
|
||||||
json exportRegion(int startX, int startY, int width, int height) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set generation seed for deterministic results
|
|
||||||
* @param seed New seed value
|
|
||||||
*/
|
|
||||||
void setSeed(uint64_t seed);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current generation seed
|
|
||||||
* @return Current seed value
|
|
||||||
*/
|
|
||||||
uint64_t getSeed() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if world has been generated
|
|
||||||
* @return true if world is generated, false otherwise
|
|
||||||
*/
|
|
||||||
bool isGenerated() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,385 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "IGenerationLayer.h"
|
|
||||||
#include "GMap.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <memory>
|
|
||||||
#include <chrono>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
// Forward declarations
|
|
||||||
struct PlanetaryCore;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief World generation orchestrator with step-by-step execution
|
|
||||||
*
|
|
||||||
* Manages multiple generation layers and provides cycle-by-cycle execution
|
|
||||||
* with progress tracking, debugging, and configuration management.
|
|
||||||
*/
|
|
||||||
class WorldGenerationModule {
|
|
||||||
private:
|
|
||||||
// ========================================
|
|
||||||
// GENERATION STATE
|
|
||||||
// ========================================
|
|
||||||
std::unique_ptr<GMap> world_map;
|
|
||||||
std::unique_ptr<PlanetaryCore> planetary_core;
|
|
||||||
|
|
||||||
// Layer management
|
|
||||||
std::vector<std::unique_ptr<IGenerationLayer>> layers;
|
|
||||||
int current_layer_index = 0;
|
|
||||||
|
|
||||||
// Configuration
|
|
||||||
json global_config;
|
|
||||||
uint64_t world_seed = 0;
|
|
||||||
|
|
||||||
// Execution state
|
|
||||||
bool generation_active = false;
|
|
||||||
bool generation_complete = false;
|
|
||||||
bool generation_paused = false;
|
|
||||||
|
|
||||||
// Performance tracking
|
|
||||||
std::chrono::steady_clock::time_point start_time;
|
|
||||||
std::chrono::steady_clock::time_point last_step_time;
|
|
||||||
float total_execution_time = 0.0f;
|
|
||||||
int total_steps_executed = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor
|
|
||||||
* @param width World map width
|
|
||||||
* @param height World map height
|
|
||||||
* @param seed World generation seed
|
|
||||||
*/
|
|
||||||
WorldGenerationModule(int width, int height, uint64_t seed = 0);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destructor
|
|
||||||
*/
|
|
||||||
~WorldGenerationModule();
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// LAYER MANAGEMENT
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add generation layer to pipeline
|
|
||||||
* @param layer Layer to add (ownership transferred)
|
|
||||||
*/
|
|
||||||
void addLayer(std::unique_ptr<IGenerationLayer> layer);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove all layers
|
|
||||||
*/
|
|
||||||
void clearLayers();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get number of registered layers
|
|
||||||
* @return Layer count
|
|
||||||
*/
|
|
||||||
size_t getLayerCount() const { return layers.size(); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current active layer
|
|
||||||
* @return Current layer pointer or nullptr
|
|
||||||
*/
|
|
||||||
IGenerationLayer* getCurrentLayer() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get layer by index
|
|
||||||
* @param index Layer index
|
|
||||||
* @return Layer pointer or nullptr if invalid index
|
|
||||||
*/
|
|
||||||
IGenerationLayer* getLayer(size_t index) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// STEP-BY-STEP EXECUTION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Execute next generation step
|
|
||||||
* @return true if more steps available
|
|
||||||
*/
|
|
||||||
bool executeNextStep();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Execute multiple steps
|
|
||||||
* @param step_count Number of steps to execute
|
|
||||||
* @return Number of steps actually executed
|
|
||||||
*/
|
|
||||||
int executeSteps(int step_count);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Execute current layer completely
|
|
||||||
* @return true if layer completed successfully
|
|
||||||
*/
|
|
||||||
bool executeCurrentLayer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Execute all remaining layers
|
|
||||||
* @return true if generation completed successfully
|
|
||||||
*/
|
|
||||||
bool executeAll();
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// EXECUTION CONTROL
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start generation from beginning
|
|
||||||
*/
|
|
||||||
void startGeneration();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Pause generation
|
|
||||||
*/
|
|
||||||
void pauseGeneration();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Resume generation
|
|
||||||
*/
|
|
||||||
void resumeGeneration();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Stop and reset generation
|
|
||||||
*/
|
|
||||||
void stopGeneration();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reset to initial state
|
|
||||||
*/
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// PROGRESS TRACKING
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get overall generation progress
|
|
||||||
* @return Progress percentage (0.0-1.0)
|
|
||||||
*/
|
|
||||||
float getOverallProgress() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current layer progress
|
|
||||||
* @return Progress percentage (0.0-1.0)
|
|
||||||
*/
|
|
||||||
float getCurrentLayerProgress() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current step description
|
|
||||||
* @return Human-readable step description
|
|
||||||
*/
|
|
||||||
std::string getCurrentStepDescription() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get estimated remaining time
|
|
||||||
* @return Estimated seconds remaining
|
|
||||||
*/
|
|
||||||
float getEstimatedRemainingTime() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get total estimated duration
|
|
||||||
* @return Estimated total seconds
|
|
||||||
*/
|
|
||||||
float getTotalEstimatedDuration() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// STATE QUERIES
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
bool isGenerationActive() const { return generation_active; }
|
|
||||||
bool isGenerationComplete() const { return generation_complete; }
|
|
||||||
bool isGenerationPaused() const { return generation_paused; }
|
|
||||||
bool hasMoreSteps() const;
|
|
||||||
|
|
||||||
int getCurrentLayerIndex() const { return current_layer_index; }
|
|
||||||
int getTotalStepsExecuted() const { return total_steps_executed; }
|
|
||||||
float getTotalExecutionTime() const { return total_execution_time; }
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CONFIGURATION
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set global configuration
|
|
||||||
* @param config JSON configuration
|
|
||||||
*/
|
|
||||||
void setConfiguration(const json& config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get current configuration
|
|
||||||
* @return Current JSON configuration
|
|
||||||
*/
|
|
||||||
const json& getConfiguration() const { return global_config; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set world generation seed
|
|
||||||
* @param seed New seed value
|
|
||||||
*/
|
|
||||||
void setWorldSeed(uint64_t seed);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get world generation seed
|
|
||||||
* @return Current seed
|
|
||||||
*/
|
|
||||||
uint64_t getWorldSeed() const { return world_seed; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Validate all layer configurations
|
|
||||||
* @return true if all configurations valid
|
|
||||||
*/
|
|
||||||
bool validateConfigurations() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// WORLD ACCESS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get generated world map
|
|
||||||
* @return World map reference
|
|
||||||
*/
|
|
||||||
const GMap& getWorldMap() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get mutable world map (for testing/debugging)
|
|
||||||
* @return Mutable world map reference
|
|
||||||
*/
|
|
||||||
GMap& getWorldMapMutable();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get planetary core state
|
|
||||||
* @return Planetary core reference
|
|
||||||
*/
|
|
||||||
const PlanetaryCore& getPlanetaryCore() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// DEBUGGING AND MONITORING
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get detailed generation status
|
|
||||||
* @return JSON with complete status information
|
|
||||||
*/
|
|
||||||
json getDetailedStatus() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get performance metrics
|
|
||||||
* @return JSON with performance data
|
|
||||||
*/
|
|
||||||
json getPerformanceMetrics() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Enable verbose logging for all layers
|
|
||||||
* @param enabled Whether to enable verbose output
|
|
||||||
*/
|
|
||||||
void setVerboseLogging(bool enabled);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Export current state for debugging
|
|
||||||
* @return JSON with complete world state
|
|
||||||
*/
|
|
||||||
json exportDebugState() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Import state for debugging/testing
|
|
||||||
* @param state Debug state to import
|
|
||||||
*/
|
|
||||||
void importDebugState(const json& state);
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// CONVENIENCE METHODS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate world with standard layers
|
|
||||||
* @param config Optional configuration override
|
|
||||||
* @return true if generation successful
|
|
||||||
*/
|
|
||||||
bool generateStandardWorld(const json& config = json{});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Generate world step-by-step with callback
|
|
||||||
* @param callback Function called after each step
|
|
||||||
* @return true if generation successful
|
|
||||||
*/
|
|
||||||
bool generateWithCallback(std::function<bool(const WorldGenerationModule&)> callback);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// ========================================
|
|
||||||
// INTERNAL HELPERS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialize planetary core
|
|
||||||
*/
|
|
||||||
void initializePlanetaryCore();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Setup standard generation layers
|
|
||||||
*/
|
|
||||||
void setupStandardLayers();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Update execution timing
|
|
||||||
*/
|
|
||||||
void updateTiming();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Advance to next layer
|
|
||||||
* @return true if more layers available
|
|
||||||
*/
|
|
||||||
bool advanceToNextLayer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Calculate overall progress across all layers
|
|
||||||
* @return Combined progress (0.0-1.0)
|
|
||||||
*/
|
|
||||||
float calculateOverallProgress() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Factory for creating standard layer configurations
|
|
||||||
*/
|
|
||||||
namespace StandardLayers {
|
|
||||||
/**
|
|
||||||
* @brief Create geological generation layer
|
|
||||||
* @return Geological layer with default configuration
|
|
||||||
*/
|
|
||||||
std::unique_ptr<IGenerationLayer> createGeologicalLayer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create climate simulation layer
|
|
||||||
* @return Climate layer with default configuration
|
|
||||||
*/
|
|
||||||
std::unique_ptr<IGenerationLayer> createClimateLayer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create biome classification layer
|
|
||||||
* @return Biome layer with default configuration
|
|
||||||
*/
|
|
||||||
std::unique_ptr<IGenerationLayer> createBiomeLayer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create budget assignment layer
|
|
||||||
* @return Budget layer with default configuration
|
|
||||||
*/
|
|
||||||
std::unique_ptr<IGenerationLayer> createBudgetLayer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create resource generation layer
|
|
||||||
* @return Resource layer with default configuration
|
|
||||||
*/
|
|
||||||
std::unique_ptr<IGenerationLayer> createResourceLayer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create complete standard pipeline
|
|
||||||
* @return Vector of all standard layers
|
|
||||||
*/
|
|
||||||
std::vector<std::unique_ptr<IGenerationLayer>> createStandardPipeline();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,375 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
|
|
||||||
namespace warfactory {
|
|
||||||
|
|
||||||
// Forward declarations
|
|
||||||
struct ResourcePatch;
|
|
||||||
struct WorldFeature;
|
|
||||||
enum class RegionalInfluence;
|
|
||||||
enum class BiomeType;
|
|
||||||
enum class ExplorationLevel;
|
|
||||||
class GMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Optimized tile data structure - 24 bytes per tile
|
|
||||||
*
|
|
||||||
* Compact structure with terrain data and feature set references.
|
|
||||||
* Geological simulation ready with extended ranges for planetary formation.
|
|
||||||
* Features accessed via feature_set_id in global map for memory efficiency.
|
|
||||||
*/
|
|
||||||
struct WorldTileData {
|
|
||||||
// ========================================
|
|
||||||
// TERRAIN DATA (11 bytes) - Always accessed, geological simulation ready
|
|
||||||
// ========================================
|
|
||||||
uint16_t terrain_type_id; // Terrain type (65k possible types)
|
|
||||||
uint16_t biome_type_id; // Biome classification
|
|
||||||
uint16_t elevation; // Elevation: 0-65535 = -11km to +32km (geological range)
|
|
||||||
int16_t temperature; // Temperature: -32768 to +32767 = -3276°C to +3276°C (0.1°C increments)
|
|
||||||
uint8_t humidity; // Humidity: 0-255 = 0-100% (0.4% increments)
|
|
||||||
uint8_t wind_data; // Wind: 4 bits direction (0-15) + 4 bits intensity (0-15)
|
|
||||||
uint8_t water_level; // Accumulated water level (0-255, for river formation)
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// METADATA (21 bytes) - Generation and gameplay
|
|
||||||
// ========================================
|
|
||||||
int8_t target_budget_score; // Target budget score: -10 to +10
|
|
||||||
uint32_t regional_influence_id; // → RegionalInfluenceData in global map
|
|
||||||
uint8_t influence_strength; // Regional influence strength: 0-255
|
|
||||||
uint32_t tile_flags; // Tile properties: PASSABLE, EXPLORED, etc.
|
|
||||||
uint32_t feature_set_id; // → FeatureSet in global map (0 = no features)
|
|
||||||
uint8_t padding2[7]; // Align structure to 32 bytes (11 + 14 + 7 = 32)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Constructor with default values
|
|
||||||
*/
|
|
||||||
WorldTileData();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert tile data to JSON
|
|
||||||
*/
|
|
||||||
json toJson() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Load tile data from JSON
|
|
||||||
*/
|
|
||||||
void fromJson(const json& data);
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// TERRAIN VALUE CONVERSION HELPERS
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert elevation to meters (geological range: -11km to +32km)
|
|
||||||
*/
|
|
||||||
float getElevationMeters() const { return (elevation - 11000.0f) / 1.524f; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set elevation from meters
|
|
||||||
*/
|
|
||||||
void setElevationMeters(float meters) {
|
|
||||||
elevation = static_cast<uint16_t>(std::clamp((meters + 11000.0f) * 1.524f, 0.0f, 65535.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert temperature to Celsius (0.1°C precision, range: -3276°C to +3276°C)
|
|
||||||
*/
|
|
||||||
float getTemperatureCelsius() const { return temperature * 0.1f; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set temperature from Celsius
|
|
||||||
*/
|
|
||||||
void setTemperatureCelsius(float celsius) {
|
|
||||||
temperature = static_cast<int16_t>(std::clamp(celsius * 10.0f, -32768.0f, 32767.0f));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Convert humidity to percentage (0.0-1.0)
|
|
||||||
*/
|
|
||||||
float getHumidityPercent() const { return humidity / 255.0f; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set humidity from percentage (0.0-1.0)
|
|
||||||
*/
|
|
||||||
void setHumidityPercent(float percent) { humidity = static_cast<uint8_t>(std::clamp(percent * 255.0f, 0.0f, 255.0f)); }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get wind direction (0-15, where 0=North, 4=East, 8=South, 12=West)
|
|
||||||
*/
|
|
||||||
uint8_t getWindDirection() const { return (wind_data >> 4) & 0x0F; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set wind direction (0-15)
|
|
||||||
*/
|
|
||||||
void setWindDirection(uint8_t direction) {
|
|
||||||
wind_data = (wind_data & 0x0F) | ((direction & 0x0F) << 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get wind intensity (0-15, where 0=calm, 15=hurricane)
|
|
||||||
*/
|
|
||||||
uint8_t getWindIntensity() const { return wind_data & 0x0F; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set wind intensity (0-15)
|
|
||||||
*/
|
|
||||||
void setWindIntensity(uint8_t intensity) {
|
|
||||||
wind_data = (wind_data & 0xF0) | (intensity & 0x0F);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get wind vector in X,Y components (normalized -1.0 to 1.0)
|
|
||||||
*/
|
|
||||||
std::pair<float, float> getWindVector() const {
|
|
||||||
uint8_t direction = getWindDirection();
|
|
||||||
float intensity = getWindIntensity() / 15.0f;
|
|
||||||
float angle = direction * (2.0f * 3.14159f / 16.0f); // 16 directions
|
|
||||||
return {intensity * sin(angle), intensity * cos(angle)}; // X=East, Y=North
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set wind from vector components
|
|
||||||
*/
|
|
||||||
void setWindVector(float wind_x, float wind_y) {
|
|
||||||
float intensity = sqrt(wind_x * wind_x + wind_y * wind_y);
|
|
||||||
float angle = atan2(wind_x, wind_y); // X=East, Y=North
|
|
||||||
if (angle < 0) angle += 2.0f * 3.14159f;
|
|
||||||
|
|
||||||
uint8_t direction = static_cast<uint8_t>((angle * 16.0f) / (2.0f * 3.14159f)) % 16;
|
|
||||||
uint8_t intensity_value = static_cast<uint8_t>(std::clamp(intensity * 15.0f, 0.0f, 15.0f));
|
|
||||||
|
|
||||||
setWindDirection(direction);
|
|
||||||
setWindIntensity(intensity_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get accumulated water level (0-255, for hydrological simulation)
|
|
||||||
*/
|
|
||||||
uint8_t getWaterLevel() const { return water_level; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set accumulated water level (0-255)
|
|
||||||
*/
|
|
||||||
void setWaterLevel(uint8_t level) { water_level = level; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Add water to current level (with overflow protection)
|
|
||||||
*/
|
|
||||||
void addWater(uint8_t amount) {
|
|
||||||
uint16_t new_level = static_cast<uint16_t>(water_level) + amount;
|
|
||||||
water_level = static_cast<uint8_t>(std::min(new_level, 255u));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Remove water from current level (with underflow protection)
|
|
||||||
*/
|
|
||||||
void removeWater(uint8_t amount) {
|
|
||||||
if (water_level >= amount) {
|
|
||||||
water_level -= amount;
|
|
||||||
} else {
|
|
||||||
water_level = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get effective water surface elevation (elevation + water_level)
|
|
||||||
*/
|
|
||||||
float getWaterSurfaceElevation() const {
|
|
||||||
return getElevationMeters() + (water_level * 10.0f); // 10m per water level unit
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Lightweight tile wrapper with simple interface for world generation
|
|
||||||
*
|
|
||||||
* Provides easy access to tile data through GMap delegation. Acts as a smart wrapper
|
|
||||||
* around tile index with simple methods for terrain, features, and gameplay data.
|
|
||||||
*/
|
|
||||||
class WorldTile {
|
|
||||||
private:
|
|
||||||
uint32_t tile_index; // Linear index in GMap (y * width + x)
|
|
||||||
GMap* parent_map; // Reference to parent map for data access
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Constructor - creates lightweight wrapper
|
|
||||||
* @param index Linear tile index in parent map
|
|
||||||
* @param map Parent GMap reference
|
|
||||||
*/
|
|
||||||
WorldTile(uint32_t index, GMap* map);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Default constructor - invalid tile
|
|
||||||
*/
|
|
||||||
WorldTile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if tile is valid
|
|
||||||
*/
|
|
||||||
bool isValid() const { return parent_map != nullptr; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get tile coordinates
|
|
||||||
*/
|
|
||||||
std::pair<int, int> getCoordinates() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get tile index
|
|
||||||
*/
|
|
||||||
uint32_t getIndex() const { return tile_index; }
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// BASIC TERRAIN ACCESS - Delegate to GMap
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
// Terrain type and biome
|
|
||||||
uint16_t getTerrainTypeId() const;
|
|
||||||
uint16_t getBiomeTypeId() const;
|
|
||||||
void setTerrainTypeId(uint16_t type_id);
|
|
||||||
void setBiomeTypeId(uint16_t biome_id);
|
|
||||||
|
|
||||||
// Elevation (in meters, auto-converted from uint8_t)
|
|
||||||
float getElevation() const;
|
|
||||||
void setElevation(float elevation_meters);
|
|
||||||
|
|
||||||
// Temperature (in Celsius, auto-converted from uint8_t)
|
|
||||||
float getTemperature() const;
|
|
||||||
void setTemperature(float temperature_celsius);
|
|
||||||
|
|
||||||
// Humidity (0.0-1.0, auto-converted from uint8_t)
|
|
||||||
float getHumidity() const;
|
|
||||||
void setHumidity(float humidity_percent);
|
|
||||||
|
|
||||||
// Wind data (direction 0-15, intensity 0-15)
|
|
||||||
uint8_t getWindDirection() const;
|
|
||||||
void setWindDirection(uint8_t direction);
|
|
||||||
uint8_t getWindIntensity() const;
|
|
||||||
void setWindIntensity(uint8_t intensity);
|
|
||||||
std::pair<float, float> getWindVector() const;
|
|
||||||
void setWindVector(float wind_x, float wind_y);
|
|
||||||
|
|
||||||
// Water level (0-255, for hydrological simulation)
|
|
||||||
uint8_t getWaterLevel() const;
|
|
||||||
void setWaterLevel(uint8_t level);
|
|
||||||
void addWater(uint8_t amount);
|
|
||||||
void removeWater(uint8_t amount);
|
|
||||||
float getWaterSurfaceElevation() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// REGIONAL INFLUENCE - Via global maps
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
uint32_t getRegionalInfluenceId() const;
|
|
||||||
void setRegionalInfluenceId(uint32_t influence_id);
|
|
||||||
uint8_t getInfluenceStrength() const;
|
|
||||||
void setInfluenceStrength(uint8_t strength);
|
|
||||||
float getFeatureProbabilityModifier(const std::string& feature_type) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// BUDGET SYSTEM - Simple scoring
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
int8_t getTargetBudgetScore() const;
|
|
||||||
void setTargetBudgetScore(int8_t target_score);
|
|
||||||
float calculateActualBudgetScore() const;
|
|
||||||
bool isBudgetBalanced(int8_t tolerance = 1) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// FEATURE MANAGEMENT - Via feature sets
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
uint32_t getFeatureSetId() const;
|
|
||||||
void setFeatureSetId(uint32_t feature_set_id);
|
|
||||||
std::vector<uint32_t> getFeatureIds() const;
|
|
||||||
bool hasFeature(uint32_t feature_id) const;
|
|
||||||
size_t getFeatureCount() const;
|
|
||||||
|
|
||||||
// Feature compatibility for generation
|
|
||||||
bool canAcceptFeatureType(const std::string& feature_type) const;
|
|
||||||
bool canAcceptFeatureSet(uint32_t feature_set_id) const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// RESOURCE MANAGEMENT - Via features integration
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
// Resources are integrated into features (as per analysis)
|
|
||||||
uint64_t getTotalResourceQuantity(uint16_t resource_type_id) const;
|
|
||||||
bool providesResource(uint16_t resource_type_id) const;
|
|
||||||
std::vector<uint16_t> getAvailableResourceTypes() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// TERRAIN COMPATIBILITY - Generation helpers
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
bool isTerrainCompatible(const std::string& feature_type) const;
|
|
||||||
bool isBiomeCompatible(const std::string& feature_type) const;
|
|
||||||
bool isElevationCompatible(const std::string& feature_type) const;
|
|
||||||
float getTraversability() const;
|
|
||||||
bool isPassable() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// TILE FLAGS - State management
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
void setFlag(uint32_t flag, bool value);
|
|
||||||
bool getFlag(uint32_t flag) const;
|
|
||||||
uint32_t getFlags() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// DISCOVERY SYSTEM - Layered visibility
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
json getVisibleProperties() const;
|
|
||||||
json getDiscoverableProperties(ExplorationLevel level) const;
|
|
||||||
json getHiddenProperties() const;
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// SERIALIZATION & UTILITIES
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
json toJson() const;
|
|
||||||
void fromJson(const json& json_data);
|
|
||||||
json exportForNetwork() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tile flag constants
|
|
||||||
*/
|
|
||||||
namespace TileFlags {
|
|
||||||
const uint32_t PASSABLE = 1 << 0; // Tile allows movement
|
|
||||||
const uint32_t DESTRUCTIBLE = 1 << 1; // Features can be destroyed
|
|
||||||
const uint32_t EXPLORED = 1 << 2; // Tile has been explored
|
|
||||||
const uint32_t GEOLOGICALLY_SURVEYED = 1 << 3; // Geological exploration done
|
|
||||||
const uint32_t MAGNETOMETRICALLY_SURVEYED = 1 << 4; // Magnetic exploration done
|
|
||||||
const uint32_t CBRN_SURVEYED = 1 << 5; // CBRN exploration done
|
|
||||||
const uint32_t CONTAMINATED = 1 << 6; // Tile has contamination
|
|
||||||
const uint32_t STRATEGIC_VALUE = 1 << 7; // Tile has strategic importance
|
|
||||||
const uint32_t WATER_PRESENT = 1 << 8; // Tile has water features
|
|
||||||
const uint32_t RESOURCE_RICH = 1 << 9; // Tile has significant resources
|
|
||||||
const uint32_t FEATURE_RICH = 1 << 10; // Tile has multiple features
|
|
||||||
const uint32_t BUDGET_BALANCED = 1 << 11; // Budget score is balanced
|
|
||||||
const uint32_t REQUIRES_SPECIAL_EQUIPMENT = 1 << 12; // Special vehicles needed
|
|
||||||
const uint32_t HISTORICALLY_SIGNIFICANT = 1 << 13; // Cultural/historical value
|
|
||||||
const uint32_t ENVIRONMENTALLY_PROTECTED = 1 << 14; // Protected area
|
|
||||||
const uint32_t MILITARILY_CONTROLLED = 1 << 15; // Under military control
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Exploration level requirements
|
|
||||||
*/
|
|
||||||
enum class ExplorationLevel {
|
|
||||||
VISUAL = 0, // Standard reconnaissance (visible features)
|
|
||||||
GEOLOGICAL = 1, // Geological vehicle required
|
|
||||||
MAGNETOMETRIC = 2, // Magnetometric vehicle required
|
|
||||||
CBRN = 3, // CBRN vehicle required
|
|
||||||
MAXIMUM = 4 // All exploration completed
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace warfactory
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
#include "WorldGeneration.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
|
||||||
using namespace warfactory;
|
|
||||||
|
|
||||||
#ifdef TESTING
|
|
||||||
/**
|
|
||||||
* @brief Standalone test mode for world-feature module
|
|
||||||
*/
|
|
||||||
int main() {
|
|
||||||
std::cout << "WorldGeneration Module - Standalone Test Mode" << std::endl;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Create module instance
|
|
||||||
WorldGenerationModule worldGeneration;
|
|
||||||
|
|
||||||
// Test basic functionality
|
|
||||||
std::cout << "Module type: " << worldGeneration.getType() << std::endl;
|
|
||||||
|
|
||||||
// Test world generation
|
|
||||||
json generationResult = worldGeneration.generateWorldMap();
|
|
||||||
std::cout << "World generation result: " << generationResult.dump(2) << std::endl;
|
|
||||||
|
|
||||||
// Test coordinate queries
|
|
||||||
if (worldGeneration.isGenerated()) {
|
|
||||||
std::string terrain = worldGeneration.getTerrainAt(100, 100);
|
|
||||||
std::string biome = worldGeneration.getBiomeAt(100, 100);
|
|
||||||
float elevation = worldGeneration.getElevationAt(100, 100);
|
|
||||||
|
|
||||||
std::cout << "At (100,100): terrain=" << terrain
|
|
||||||
<< ", biome=" << biome
|
|
||||||
<< ", elevation=" << elevation << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test health status
|
|
||||||
json health = worldGeneration.getHealthStatus();
|
|
||||||
std::cout << "Health status: " << health.dump(2) << std::endl;
|
|
||||||
|
|
||||||
std::cout << "All tests completed successfully!" << std::endl;
|
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cerr << "Test failed with exception: " << e.what() << std::endl;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
/**
|
|
||||||
* @brief Hot-reload module entry point
|
|
||||||
*
|
|
||||||
* This function is called by the module loader for hot-reload.
|
|
||||||
* It should return a new instance of the module.
|
|
||||||
*/
|
|
||||||
extern "C" {
|
|
||||||
IModule* createModule() {
|
|
||||||
return new WorldGenerationModule();
|
|
||||||
}
|
|
||||||
|
|
||||||
void destroyModule(IModule* module) {
|
|
||||||
delete module;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
Loading…
Reference in New Issue
Block a user