Compare commits

...

10 Commits

Author SHA1 Message Date
f393b28d73 Migrate core engine interfaces to GroveEngine repository
Removed core engine infrastructure from warfactoryracine:
- Core interfaces: IEngine, IModule, IModuleSystem, IIO, ITaskScheduler, ICoordinationModule
- Configuration system: IDataTree, IDataNode, DataTreeFactory
- UI system: IUI, IUI_Enums, ImGuiUI (header + implementation)
- Resource management: Resource, ResourceRegistry, SerializationRegistry
- Serialization: ASerializable, ISerializable
- World generation: IWorldGenerationStep (replaced by IWorldGenerationPhase)

These components now live in the GroveEngine repository and are included
via CMake add_subdirectory(../GroveEngine) for reusability across projects.

warfactoryracine remains focused on game-specific logic and content.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-28 00:22:36 +08:00
63a2d251ff Fix world generation interface architecture
- Simplify IWorldGenerationFunction interface (5 required + 4 optional methods)
- Remove over-engineered methods (getProducedData, getRequiredPreviousFunctions, canExecute)
- Correct execute() signature to match implementations: execute(WorldData&, PlanetaryCore&)
- Add UniversalRegionFusionFunctionAdapter wrapper for template compatibility
- Update all 8 Phase 0/1 functions to implement corrected interface
- Delete unnecessary AWorldGenerationFunction abstract class

Phase 0 (2/2): InitializeWorldTerrain, InitializePlanetaryCore
Phase 1 (6/6): MeteoriteImpact, ImpactEffects, PlanetaryDifferentiation,
               VolcanicRedistribution, Cooling, UniversalRegionFusion

All functions now properly inherit from IWorldGenerationFunction with
consistent configure/execute pattern.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-23 10:49:44 +08:00
919b68afd0 Add complete message communication system documentation
- Type-safe message classes with IMessage/AMessage architecture
- Breaking changes versioning strategy (strict, no compatibility)
- AMessage with enforced immutable metadata (timestamp, sender, messageId, partId)
- Automatic fragmentation/defragmentation by IO layer
- Template helper pullMessageAs<T>() for clean type-safe reception
- No ordering guarantees + replaceable messages by default
- Async handling via ITaskScheduler delegation
- Centralized deserialization with factory pattern
- Complete error handling strategy

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-17 11:42:39 +08:00
5e4235889a Add comprehensive AI, diplomacy, and save system documentation
- ai-framework.md: Unified decision framework with scoring system, RL integration, doctrines
- systeme-diplomatique.md: Relations (shared), intentions (bilateral), threat, reliability systems
- calcul-menace.md: Contextual threat calculation with sword & shield mechanics
- systeme-sauvegarde.md: V1 save system with JSON, metachunks, module autonomy
- module-versioning.md: Automatic MAJOR.MINOR.PATCH.BUILD versioning via CMake

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-06 22:39:36 +08:00
076acd4812 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>
2025-09-30 19:00:36 +08:00
b93b269e6d Implement complete world-generation-realist system with volcanic physics and region fusion
- Create volcanic system: Volcano.h, VolcanoFactory.h, VolcanoImpact.h with realistic lifecycle modeling
- Add PlanetaryDifferentiationFunction.h for gravitational material separation (regions → core)
- Implement CoolingPhaseFunction.h with dual influences (core + surface temperature)
- Create UniversalRegionFusionFunction.h as template with duck typing for type-safe fusion
- Add ResourceRegion.h, TectonicRegion.h, ClimateRegion.h with unified fusion interface
- Update Regular_world.json with Phase 0 initialization and volcanic/cooling configurations
- Add melting_point_celsius to all resources for volcanic composition filtering
- Implement ResourceRegistry and RandomGenerator singletons for performance
- Scale system for realistic quantities: uint64_t gameplay, uint128_t planetary core

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-30 14:38:46 +08:00
78e31fc765 Create world-generation-realist module architecture interfaces
Core serialization interfaces:
- ISerializable → ASerializable with auto-registration concept
- SerializationRegistry singleton interface
- Template-based factory system with PhaseRegistry

Shared interfaces (moved to core):
- IAttachedElement for element relationships
- IElementData for polymorphic data
- IRegion interface with attachment capabilities
- Resource interface for gameData integration

World generation interfaces:
- IWorldGenerationPhase and IWorldGenerationStep
- GTile optimized 16-byte structure definition
- GMap interface for contiguous memory layout
- WorldGenerationOrchestrator interface

Phase 1 structure definitions:
- PlanetaryCore interface with composition tracking
- Meteorite data structure
- MeteoriteImpact parameterizable interface
- RegionManager interface

Climate token system design:
- Water/wind tokens for climate simulation
- Destruction tokens (highWind/flood/hurricane) packed design
- Elevation range: -32km to +32km geological scale
- Budget system integration ready

Note: Interfaces and structure definitions only - implementations pending.
Architecture designed for Regular_world.json integration and SIMD optimization.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 23:16:14 +08:00
fd1ec4f503 Implement complete world generation system with geological simulation and resource distribution
## World Generation Pipeline
- Add comprehensive 7-phase geological simulation (4.6 billion years)
- Implement WindRegions-based climate system with ITCZ zones
- Create 18 biome types with scientific classification parameters
- Establish Phase 7 budget assignment and natural feature placement

## Resource System Architecture
- Add 70+ natural features across 8 categories (geological, water, forest, volcanic, etc.)
- Implement complete resource-to-feature mapping for all game materials
- Create individual resource files for metals (iron, copper, gold, uranium, etc.)
- Add comprehensive cross-referencing between features and game resources

## Biome Integration System
- Design scalable blacklist + frequent biomes compatibility system
- Implement mass-based feature selection with geological strength requirements
- Add 5 spatial distribution patterns (concentrated, uniform, ring, clustered, gradient)
- Create region-based feature placement with biome-aware filtering

## Documentation and Architecture
- Add detailed geological and climate simulation system documentation
- Update project overview with world generation achievements
- Establish JSON-driven configuration system for all generation parameters
- Create comprehensive system for Phase 8 integration readiness

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 17:19:01 +08:00
e5ef16742b Add Phase 6: Climate Simulation and Biome Generation to geological system
- Complete physics-based climate simulation with 500 convergence cycles
- Emergent wind patterns from temperature gradients with realistic transport
- Advanced hydrological system with bell-curve erosion for V-shaped valleys
- Automatic river network formation with delta systems and sediment transport
- Comprehensive biome classification (oceans, forests, deserts, grasslands)
- Resource modifiers per biome for industrial suitability mapping
- Forest evolution integration balancing geological history with current climate
- Performance optimized: 5-15 seconds runtime, <120MB memory usage
- Ready for gameplay with environmental challenges and strategic locations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-28 23:04:10 +08:00
ca81062b43 Implement comprehensive configuration system with immutable interfaces
BREAKING CHANGES to IModule interface:
- Replace initialize() with setConfiguration(const IDataNode&)
- Add getConfiguration() returning const IDataNode&
- Change isHealthy() to getHealthStatus() returning JSON

New Core Interfaces:
- IDataTree: Hierarchical configuration container with hot-reload
- IDataNode: Configuration nodes with type-safe property access
- ICoordinationModule: Global system orchestrator for module deployment
- ITaskScheduler: Dedicated file for task delegation interface

System Architecture:
- MainServer → CoordinationModule → IEngine → IModuleSystem → Modules
- gameconfig.json as single source of truth for all configuration
- Configuration immutability via const references
- Module coordination and health monitoring

Documentation Updates:
- Removed references to deprecated "10 engines" architecture
- Added comprehensive technical specifications
- Updated CLAUDE.md with configuration system details
- Created INTEGRATION-MASTER-LIST.md reference

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-27 22:42:32 +08:00
141 changed files with 25828 additions and 2133 deletions

7
.claude/settings.json Normal file
View File

@ -0,0 +1,7 @@
{
"permissions": {
"additionalDirectories": [
"../GroveEngine"
]
}
}

View File

@ -14,11 +14,33 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## 📋 Implementation Status
**ALWAYS CHECK**: `TODO.md` at project root for current implementation roadmap and tasks.
**ALWAYS CHECK**:
- `TODO.md` at project root for current implementation roadmap and high-level phases
- `TASKLIST.md` for detailed task breakdown organized by time investment (Quick Wins, Light Tasks, Medium Tasks, Feature Tasks, Big Tasks)
**Current Phase**: **PRODUCTION-READY** Hot-Reload System - **0.4ms average reload time achieved!**
**Current Phase**: World Generation System - Geological and resource foundation complete
## 🎯 **Recent Major Achievements - UI Interface System**
## 🎯 **Recent Major Achievements - World Generation System**
### ✅ **Complete Geological Simulation (COMPLETED)**
- **7-Phase Pipeline**: 4.6 billion year geological evolution simulation
- **Physics-Based Tectonics**: Collision detection, plate movement, mountain formation
- **Scientific Climate Model**: WindRegions, ITCZ, and realistic weather patterns
- **Biome Classification**: 18 distinct biomes with elevation and generation parameters
### 🗺️ **Resource Distribution System (COMPLETED)**
- **70+ Natural Features**: Geologically accurate formation patterns
- **Smart Biome Integration**: Blacklist + frequent biomes for scalable compatibility
- **Mass-Based Quality**: Region strength determines available resource grades
- **Cross-Referenced Resources**: All features map to actual game resource definitions
### ⚙️ **Spatial Distribution Patterns (COMPLETED)**
- **5 Pattern Types**: Concentrated, uniform, ring, clustered, gradient distributions
- **Random Assignment**: Each region gets unpredictable density patterns
- **Biome-Aware Placement**: Local environment determines compatible features
- **Phase 8 Ready**: System prepared for integration with world generation pipeline
## 🎯 **Previous Major Achievements - UI Interface System**
### ✅ **Complete IUI Interface Architecture (COMPLETED)**
- **Data-Agnostic Design**: Generic `IUI` interface supporting all content types
@ -79,6 +101,7 @@ The project uses a **hierarchical documentation system** in `/docs/`:
- `systeme-militaire.md` - Vehicle design with grid-based component placement
- `economie-logistique.md` - Market simulation, supply chains, pricing
- `map-system.md` - Procedural generation with 218+ elements
- `rendering-system.md` - Sprite composition and entity rendering
- `factory-architecture-post-player.md` - Advanced production architecture
### 🔧 03-implementation/
@ -97,18 +120,43 @@ The project uses a **hierarchical documentation system** in `/docs/`:
## Key Technical Concepts
### Core Interface Architecture (COMPLETED - PHASE 1)
- **Quadruple Interface Pattern**: IEngine, IModuleSystem, IModule, IIO + ITaskScheduler
- **Complete Interface Set**: IEngine, IModuleSystem, IModule, IIO, ITaskScheduler, IDataTree, IDataNode, ICoordinationModule
- **CRITICAL**: **Core interfaces are IMMUTABLE** - Never modify once finalized
- **Configuration System**: IDataTree/IDataNode for hierarchical data-driven development with const references
- **Coordination System**: ICoordinationModule as global orchestrator (first launched, last shutdown)
- **Task Delegation**: ITaskScheduler for module → execution system delegation (multithreading)
- **Autonomous Modules**: Small (200-300 lines) hot-reloadable modules (.so files)
- **Claude Code Optimized**: Each module is a micro-context for AI development
- **Performance Targets**: V1 Client 30+ fps, V2 Client 60+ fps, V1 Server 10+ players, V2 Server 100+ players
### Interface Specifications (NEVER MODIFY THESE)
- **IEngine**: Engine orchestration, module loading, client/coordinator socket management
- **IModuleSystem**: Execution strategy + task scheduling (inherits ITaskScheduler)
- **IModule**: Pure business logic + pub/sub communication + task delegation
- **ICoordinationModule**: Global system orchestrator, gameconfig.json management, module deployment topology
- **IEngine**: Local engine orchestration, module loading, client/coordinator socket management
- **IModuleSystem**: Execution strategy implementation (Sequential → Threaded → Cluster)
- **IModule**: Pure business logic + pub/sub communication (**BREAKING CHANGES** - see below)
- **IIO**: Pull-based pub/sub with low-frequency batching and health monitoring
- **ITaskScheduler**: Task delegation interface for module → execution system
- **ITaskScheduler**: Task delegation interface for module → execution system (multithreading)
- **IDataTree**: Configuration tree container with manual hot-reload capabilities
- **IDataNode**: Hierarchical data nodes with pattern matching and property queries (**const methods**)
### BREAKING CHANGES in IModule Interface
```cpp
// OLD Interface (DEPRECATED)
virtual void initialize(const json& config, IIO* io, ITaskScheduler* scheduler) = 0;
virtual bool isHealthy() = 0;
// NEW Interface (CURRENT)
virtual void setConfiguration(const IDataNode& configNode, IIO* io, ITaskScheduler* scheduler) = 0;
virtual const IDataNode& getConfiguration() = 0;
virtual json getHealthStatus() = 0; // Detailed JSON instead of bool
// initialize() method REMOVED
```
### Configuration Immutability System
- **const IDataNode&** references prevent modules from modifying configuration
- **Single source of truth**: gameconfig.json loaded via IDataTree
- **Hot-reload**: CoordinationModule propagates config changes to all modules
- **Type safety**: All IDataNode getters are const methods
### Module Frequencies & Isolation
- **ProductionModule**: 60Hz (frame-perfect factory operations)
@ -272,7 +320,7 @@ cmake --build build # ALL debugging tools active by default
## Claude Code Development Practices
### Interface Management (ABSOLUTELY CRITICAL)
- **IMMUTABLE INTERFACES**: Core interfaces (IEngine, IModuleSystem, IModule, IIO, ITaskScheduler) are FROZEN
- **IMMUTABLE INTERFACES**: Core interfaces (IEngine, IModuleSystem, IModule, IIO, ITaskScheduler, IDataTree, IDataNode) are FROZEN
- **NEVER MODIFY**: Once interfaces are finalized, they become the architectural foundation
- **Extension Only**: New functionality via new implementations, not interface changes
- **Breaking Changes**: Modifying core interfaces breaks ALL existing modules and systems
@ -344,6 +392,10 @@ The project includes 16 C++ libraries via FetchContent:
3. `03-implementation/testing-strategy.md` - Testing approach
4. `04-reference/INTEGRATION-MASTER-LIST.md` - Complete specifications
### For Task Management
1. `TODO.md` - High-level implementation roadmap and current phases
2. **`TASKLIST.md`** - **DETAILED**: Complete task breakdown by time (Quick Wins < 1h, Light 1-3h, Medium 1-2 days, Feature 3-7 days, Big 1-2 weeks)
### For Technical Reference
1. `04-reference/arbre-technologique.md` - Complete tech tree
2. `04-reference/coherence-problem.md` - Technical analyses
@ -363,4 +415,27 @@ The project includes 16 C++ libraries via FetchContent:
**DEVELOPMENT WORKFLOW**: ✅ **BATTLE-TESTED** - AddressSanitizer + GDB integration for instant bug detection.
**Next Phase**: Integration of IUI system with core modular architecture and hot-reload capabilities.
**CONFIGURATION SYSTEM**: ✅ **INTERFACES COMPLETE** - Comprehensive IDataTree configuration system for data-driven gameplay.
- **GameConfig Source**: Single `gameconfig.json` file containing all game configuration and module deployment topology
- **Hierarchical Data**: Tree structure where each node can have both children AND its own data blob
- **Advanced Querying**: Pattern matching with wildcards, property-based lambda predicates
- **Type-Safe Access**: Getters with defaults for int/double/string/bool properties
- **Hash Validation**: SHA256 hashing for data integrity and synchronization
- **Manual Hot-Reload**: Check for changes and reload on demand with callbacks
- **Module Distribution**: gameconfig.json defines which modules to load and where to deploy them
## 🎯 **Current Status - INTERFACES COMPLETE & CLEAN**
**CORE INTERFACES**: ✅ **ALL COMPLETE** - Complete interface set with proper file organization:
- ✅ **ICoordinationModule.h** - Global orchestrator with detailed startup/shutdown sequences
- ✅ **ITaskScheduler.h** - **NEW FILE** with comprehensive multithreading delegation documentation
- ✅ **IModule.h** - BREAKING CHANGES implemented with const IDataNode& configuration
- ✅ **IDataNode.h** - All methods const for immutability enforcement
- ✅ **IEngine.h, IModuleSystem.h, IIO.h** - Recovered and cleaned from duplications
- ✅ **IDataTree.h, DataTreeFactory.h** - Configuration system foundation
**ARCHITECTURE DOCUMENTED**: ✅ **COMPLETE** - Full system flow and coordination patterns documented
**BREAKING CHANGES**: ✅ **IMPLEMENTED** - IModule interface modernized with configuration immutability
**Next Phase**: Implementation of JSONDataTree concrete classes and example gameconfig.json for testing.

View File

@ -37,6 +37,9 @@ FetchContent_Declare(
FetchContent_MakeAvailable(nlohmann_json imgui)
# Add GroveEngine
add_subdirectory(../GroveEngine GroveEngine_build)
# Create ImGui library with OpenGL/GLFW backends
add_library(imgui_backends
${imgui_SOURCE_DIR}/imgui.cpp
@ -58,16 +61,15 @@ target_link_libraries(imgui_backends PUBLIC glfw OpenGL::GL)
# Test executable
add_executable(test_imgui_ui
test_imgui_ui.cpp
src/core/src/ImGuiUI.cpp
)
target_include_directories(test_imgui_ui PRIVATE
src/core/include
${imgui_SOURCE_DIR}
${imgui_SOURCE_DIR}/backends
)
target_link_libraries(test_imgui_ui
GroveEngine::impl
imgui_backends
nlohmann_json::nlohmann_json
glfw
@ -84,16 +86,15 @@ set_target_properties(test_imgui_ui PROPERTIES
# Test constraints executable
add_executable(test_constraints
test_constraints.cpp
src/core/src/ImGuiUI.cpp
)
target_include_directories(test_constraints PRIVATE
src/core/include
${imgui_SOURCE_DIR}
${imgui_SOURCE_DIR}/backends
)
target_link_libraries(test_constraints
GroveEngine::impl
imgui_backends
nlohmann_json::nlohmann_json
glfw

1723
TASKLIST.md Normal file

File diff suppressed because it is too large Load Diff

View File

@ -422,7 +422,7 @@
---
## Notes
- **Architecture Status**: Transitioning from 10 engines to modular system
- **Architecture Status**: Modular system with complete interface specifications
- **Documentation**: See `docs/01-architecture/architecture-modulaire.md` for complete specification
- **Claude Code Optimization**: Each module = micro-context for AI development
- **Exception**: ProductionModule (Belt+Inserter+Factory) requires 500-800 lines for performance

View File

@ -1,55 +1,266 @@
# Vue d'ensemble du projet
# Warfactory : Vue d'Ensemble du Projet
## Vision et objectifs
## Vision Globale
- **Concept général** : Jeu d'usine avec une composante militaire forte
- **Inspiration** : Factorio-like avec dimension stratégique militaire
- **Principe clé** : L'importance du choix à tous les niveaux
- **Progression** : De PMC vers opérations conventionnelles, impact du joueur grandit avec le temps
**Warfactory** est un RTS/4X révolutionnaire fusionnant la profondeur industrielle de Factorio avec une simulation militaire réaliste et une économie mondiale dynamique. Le projet allie l'hommage moral à l'Ukraine avec une architecture technique modulaire ultra-innovante, optimisée pour le développement assisté par IA.
## Philosophie de design
**Innovation Centrale** : Un système économique où TOUS les acteurs (joueur, IA, États) suivent exactement les mêmes règles économiques, créant une simulation authentique et éducative des marchés mondiaux.
### Clarté et simplicité
- Interface claire avec pictogrammes simples pour éviter la fausse complexité
- Jeu déjà complexe nécessitant une présentation accessible
## Concept de Jeu et Progression
### Aspect usine
- La ligne d'assemblage soit le cœur
- La doctrine militaire que le joueur s'est trouvée indique les besoins industriels
- L'énergie c'est facile à gérer
- L'extraction c'est facile
### De PMC à Géant Industriel
**Progression naturelle** :
- **Phase PMC** : Opérations irrégulières limitées, contrats d'État
- **Phase Industrielle** : Production civile/militaire, expansion géographique
- **Phase Géopolitique** : Influence mondiale, doctrines militaires, crises planétaires
### Aspect militaire
- Le joueur doit se trouver sa propre doctrine et créer son gameplay
- Mettre en avant le concept de doctrine d'emploi
- La contemplation du combat
- IA qui donne du feedback de sa compétence ou de sa médiocrité
- Bien que le contrôle direct soit important, il n'est pas le cœur
**Liberté d'échelle** : Philosophie bac à sable permettant au joueur de rester artisan local ou de défier Lockheed Martin selon ses ambitions.
### Progression militaire
- Dans un premier temps on se cantonner à des opérations irrégulières
- L'impact du joueur grandit avec le temps
### Principe "Skip vs Optimize"
**Design fondamental** : Tous les systèmes peuvent être automatisés ou micro-gérés
- **Skip** : Solutions automatisées, efficacité réduite mais accessibles
- **Optimize** : Contrôle manuel complet, efficacité maximale
- **Hybride** : Mix selon préférences et contexte
### Égalité économique (RÈGLE FONDAMENTALE)
**Principe core** : Le player n'a AUCUN privilège économique artificiel
Exemples concrets :
- **Production** : Usines tout-en-un vs layouts Factorio optimisés
- **Combat** : IA tactique vs commande directe
- **Commerce** : Auto-trade vs négociation manuelle
- **Same rules for all** : Player, AI companies, AI states suivent EXACTEMENT les mêmes règles économiques
- **No artificial advantages** : Aucun bonus coût, aucun discount, aucun traitement spécial
- **Success via insight** : Réussite basée sur compréhension économique réelle, pas privilèges
- **Educational integrity** : Players apprennent vrais principes économiques applicables
- **Competitive fairness** : AI opponents économiquement crédibles et rationnels
## Systèmes Industriels Intégrés
### Architecture Factorio-like Avancée
**Cœur productif** :
- **Production modulaire** : Belts, inserters, factories avec évolution progressive
- **4 phases de complexité** : Mono → Multi-lanes → Bidirectionnel → Full Factorio
- **Qualité d'assemblage** : Placement optimal vs automatique avec pénalités réalistes
**Innovation : Dual Production System** :
- **Production brute** : Transformation ressources primaires (minerai → plaques)
- **Assemblage précis** : Placement composants selon grilles vehicules
### Flexibilité de Reconversion Industrielle
**Mécaniques réalistes** basées sur similarité des processus :
- **Facile** : Tables fer → Blindages (même matériaux, processus similaires)
- **Complexe** : Tables → Canons (précision usinage, alliages spéciaux)
- **Impossible** : Menuiserie → Production hydrogène (zéro overlap technologique)
## Système Militaire Révolutionnaire
### Conception de Véhicules par Grilles
**Innovation gameplay** : Design sur châssis irréguliers avec zones spécialisées
**Interface intuitive** :
- **Pick & Place** : Drag & drop composants avec rotations A/E
- **Snap toggle** : R pour alignement grille
- **Validation temps réel** : Contraintes poids/énergie vérifiées durant placement
**Diversité massive** :
- **Châssis nommés** : "Griffon" (chenillé), "Viper" (modulaire), "Fennec" (ultra-léger)
- **3 layers** : Châssis → Systèmes → Armes & Capteurs
- **1000+ composants** : Formes uniques, jamais carrées ni 1x1
### Système d'Amélioration Générique
**Améliorations universelles** stackables avec rendements décroissants :
- **High ROF** : +20% cadence, +40% chaleur (stack 1), puis +10%/+40% (stack 2)
- **Efficiency** : -20% consommation, -15% performance
- **Reliability** : +30% durabilité, -10% performance
**Coût exponentiel** : 1.25^n per stack avec malus cumulatifs linéaires
## Économie Mondiale Simulée
### Égalité Économique Fondamentale
**RÈGLE NON-NÉGOCIABLE** : Le joueur n'a AUCUN privilège économique artificiel
**Implementation requirement** :
```cpp
// INTERDIT - Player privilege
// INTERDIT - Avantage joueur
if(agent.isPlayer()) order.cost *= 0.9f;
// OBLIGATOIRE - Equal treatment
// OBLIGATOIRE - Traitement égal
float cost = calculateRealTransportCost(order);
agent.processOrder(order, cost);
```
Cette règle est **NON-NÉGOCIABLE** pour l'intégrité de la simulation économique.
**Résultat** : Réussite basée sur compréhension économique réelle, pas sur privilèges artificiels.
## Inspiration Undertale
- S'inspirer d'Undertale pour la partie choix géopolitique
### Système de Companies avec Features
**Chaque IA company** a 2-4 features définissant ses capacités :
- **Domaines** : Metal, Electronic, Tank, Plane, Wood, Food, Engine, Cannon, Missile
- **Modificateurs** : Quality, Quantity, Speed, Cost, Modularity, Innovation
**Exemple** : Company "Metal + Plane + Quantity + Electronic" excelle en avions métalliques de masse avec électronique embarquée, mais manque raffinement vs spécialistes Quality.
### Transport Multi-Modal Réaliste
**Hiérarchie des coûts** (indicative) :
- **Maritime** : ~0.10€/kg (volume massif, ultra-économique)
- **Ferroviaire** : ~0.50€/kg (grandes quantités, infrastructure)
- **Aérien** : ~2.00€/kg (rapide, coûteux)
- **Routier** : ~5.00€/kg (flexible, dernier kilomètre)
**Impact stratégique** : Localisation côtière = avantage économique 50x
### Marchés Segmentés et Restrictions
**Types de marchés** :
- **Nationaux** : Par pays avec politiques douanières
- **Companies privés** : Accords bilatéraux
- **Blocs multinationaux** : UE, OTAN avec préférences
- **Mondial** : Marché libre avec sanctions possibles
**Doubles verrous** : Companies ET États peuvent bloquer accès
## Architecture Technique Révolutionnaire
### Modularité Claude Code Optimisée
**Innovation développement** : Architecture modulaire révolutionnaire pour développement IA
**Contraintes strictes** :
- **200-300 lignes max** par module (EXCEPTION : ProductionModule 500-800)
- **Build autonome** : `cd modules/tank/ && cmake .` - zéro dépendance parent
- **Hot-reload 0.4ms** : Modifications instantanées sans restart
- **Développement parallèle** : 3+ instances Claude Code simultanées
### Interface System IMMUTABLE
**5 interfaces fondamentales** (JAMAIS modifiées une fois finalisées) :
```cpp
ICoordinationModule → Orchestrateur global système
IEngine → Coordination locale (Debug → HighPerf → DataOriented)
IModuleSystem → Stratégie d'exécution (Sequential → Threaded → Cluster)
IModule → Logique métier pure (TankModule.so, EconomyModule.so)
IIO → Communication (IntraIO → LocalIO → NetworkIO)
```
### Évolution Progressive Sans Régression
```cpp
// Phase 1 : Prototype
DebugEngine + SequentialModuleSystem + IntraIO
// Phase 2 : Optimization
DebugEngine + ThreadedModuleSystem + IntraIO
// Phase 3 : Production
HighPerfEngine + MultithreadedModuleSystem + LocalIO
// Phase 4 : MMO Scale
DataOrientedEngine + ClusterModuleSystem + NetworkIO
```
**Avantage révolutionnaire** : Modules métier inchangés à travers toutes les phases !
## Carte et Exploration
### Architecture Multi-Échelles
**2 niveaux discrets** :
- **Large Map** : Carte mondiale éditable, navigation node-based
- **Local Map** : Tiles 1m×1m, chunks 64×64, style Factorio précis
### Génération Procédurale par Budget de Points
**Innovation système** : Chaque tile reçoit score (-10 à +10) équilibrant automatiquement risques/récompenses
**218+ éléments** avec tendances régionales :
- **Bassins pétroliers** : Pétrole ×5 probabilité, terrains marécageux ×2
- **Zones ex-minières** : Fer/charbon ×3-4, teritons ×8, pollution héritée ×3
- **Régions forestières** : Forêt dense ×3-4, grottes ×2-3, pentes abruptes ×2
**Découverte stratifiée** :
- **Visible** : Relief, végétation, structures surface
- **Caché niveau 1** : Prospection géologique (gisements souterrains)
- **Caché niveau 2** : Magnétométrie (anomalies, structures enfouies)
- **Caché niveau 3** : Analyse NRBC (contaminations invisibles)
## Arbre Technologique Massif
### 3000+ Technologies pour Rejouabilité Infinie
**Principe découverte** : Player ne recherche PAS toutes les technologies !
- **Discovery organique** : Breakthrough via gameplay naturel
- **10-50 techs éligibles** simultanément (jamais 3000)
- **Système de passerelles** : Expertise dans un domaine débloque prototypes dans autres
**Exemple passerelles Châssis** :
```
Métallurgie Avancée → [PROTOTYPE] Châssis Composite
Électronique → [PROTOTYPE] Châssis Smart
Moteur → [PROTOTYPE] Châssis Performance
```
## Contexte Narratif et Éthique
### Hommage à l'Ukraine
**Motivation morale fondamentale** : "L'Ukraine parce qu'ils sont des héros, parce qu'ils meurent pour leur liberté et pour la nôtre."
**Intégration authentique** :
- **Géographie réelle** : Ukraine, Europe sur carte mondiale
- **Contexte historique** : Zones post-industrielles, vestiges soviétiques
- **Enjeux géopolitiques** : Résistance démocratique vs autoritarisme
### Crises Endgame
**3 scénarios apocalyptiques** avec mécaniques distinctes :
- **Zombie Apocalypse** : Vitesse de réaction, lignes de défense
- **Invasion ET** : Technologie supérieure aérienne, survie planétaire
- **Demon Portal** : Portails imprévisibles, course contre extermination
## Interface Utilisateur Révolutionnaire
### Système IUI Data-Agnostic
**Architecture générique** supportant tous types de contenu :
- **Enums type-safe** : `DataType::ECONOMY`, `RequestType::GET_PRICES`
- **Windowing hiérarchique** : Parent → Dock → Split → Tab → Window
- **Hybrid Sizing System** : Cibles pourcentage avec contraintes pixels
**Layout professionnel** : Topbar économique + panel companies + carte stratégique + console
## Performance et Scalabilité
### Fréquences Modulaires Optimisées
- **ProductionModule** : 60Hz (frame-perfect factory)
- **TankModule Targeting** : 60Hz (combat réactif)
- **TankModule Movement** : 30Hz (positions)
- **TankModule Tactical** : 1Hz (décisions stratégiques)
- **EconomyModule** : 0.01-0.1Hz (cycles économiques)
### Targets Performance
- **V1 Client** : 30+ fps, 10+ joueurs serveur
- **V2 Client** : 60+ fps, 100+ joueurs serveur avec prédiction locale
## Philosophie de Design Avancée
### "Complexity through Simplicity"
**Complexité AAA** émergeant de modules simples Claude-friendly :
- **Modules 200 lignes** = compréhension IA parfaite
- **Interactions complexes** = gameplay émergent sophistiqué
- **Testing granulaire** = fiabilité et débug facilités
### Configuration vs Modding
**Philosophy YAGNI** : Configuration JSON couvre 90% besoins modding
```json
{
"tank_mk2_custom": {
"health": 150, "speed": 30,
"weapons": ["cannon_105mm", "mg_coaxial"]
},
"aggressive_ai": {
"engagement_range": 1000,
"retreat_threshold": 20
}
}
```
## État Actuel et Roadmap
### PRODUCTION-READY Achievements
- ✅ **Core Interfaces COMPLETE** : Architecture modulaire immutable finalisée
- ✅ **UI System COMPLETE** : IUI + ImGuiUI avec hybrid sizing révolutionnaire
- ✅ **Hot-Reload 0.4ms** : Workflow développement révolutionné
- ✅ **Configuration System** : IDataTree avec validation SHA256
- ✅ **Cross-Platform Pipeline** : Linux dev → Windows .exe automatisé
### Next Phases
1. **Phase 2** : Implémentations concrètes (DebugEngine, JSONDataTree)
2. **Phase 3** : Modules gameplay (ProductionModule, TankModule)
3. **Phase 4** : Integration économique et multijoueur
## Conclusion : Une Vision Révolutionnaire
Warfactory transcende les genres traditionnels en unifiant industrie, stratégie militaire et simulation économique authentique dans une architecture technique révolutionnaire.
Le projet honore l'héroïsme ukrainien tout en repoussant les limites du développement assisté par IA, créant un gameplay émergent d'une profondeur inégalée où chaque choix - industriel, militaire, économique - résonne à travers un système interconnecté d'une complexité et d'un réalisme saisissants.

View File

@ -4,15 +4,17 @@
L'architecture modulaire Warfactory transforme le développement de jeux complexes en utilisant une approche **micro-modules** optimisée pour Claude Code. Chaque module est un micro-contexte de 200-300 lignes de logique métier pure.
## Triple Interface Pattern
## Core Interface Architecture
### Architecture Fondamentale
```cpp
IEngine → Orchestration et coordination
IModuleSystem → Stratégies d'exécution
IModule → Logique métier pure
IIO → Communication et transport
ICoordinationModule → Orchestrateur global système
IEngine → Orchestration locale
IModuleSystem → Stratégies d'exécution
IModule → Logique métier pure
IIO → Communication et transport
ITaskScheduler → Délégation de tâches
```
### IEngine - Orchestration

View File

@ -8,17 +8,35 @@
## Architecture Système
### Triple Interface Pattern (Architecture Révolutionnaire)
### Core Interface Architecture
**NOUVELLE ARCHITECTURE MODULAIRE** - Remplace l'ancienne architecture 10 engines par un système modulaire optimisé pour le développement avec Claude Code.
**ARCHITECTURE MODULAIRE** - Système modulaire optimisé pour le développement avec Claude Code.
#### Les 4 Interfaces Fondamentales
#### Les 5 Interfaces Fondamentales
```cpp
IEngine → Coordination générale (DebugEngine → HighPerfEngine → DataOrientedEngine)
IModuleSystem → Stratégie d'exécution (Sequential → Threaded → Multithread → Cluster)
IModule → Logique métier pure (TankModule.so, EconomyModule.so, FactoryModule.so)
IIO → Communication (IntraIO → LocalIO → NetworkIO)
ICoordinationModule → Orchestrateur global système (MainServer, déploiement, config)
IEngine → Coordination locale (DebugEngine → HighPerfEngine → DataOrientedEngine)
IModuleSystem → Stratégie d'exécution (Sequential → Threaded → Multithread → Cluster)
IModule → Logique métier pure (TankModule.so, EconomyModule.so, FactoryModule.so)
IIO → Communication (IntraIO → LocalIO → NetworkIO)
```
#### Architecture de Déploiement Global
```
MainServer Process:
├── CoordinationModule (Global Orchestrator)
│ ├── Loads gameconfig.json via IDataTree
│ ├── Manages local IEngine + modules
│ └── Launches remote servers + engines
├── Local IEngine (manages local modules)
│ ├── IModuleSystem (Sequential/Threaded/etc.)
│ └── Local Modules (.so files)
└── Remote Servers (launched by coordination)
├── Remote IEngine (manages remote modules)
├── IModuleSystem (execution strategy)
└── Remote Modules (.so files)
```
#### Séparation des Responsabilités
@ -34,12 +52,21 @@ IIO → Communication (IntraIO → LocalIO → NetworkIO)
- MultithreadedModuleSystem : Pool de threads pour tasks
- ClusterModuleSystem : Distribution sur plusieurs machines
**IModule** : Logique métier pure
**ICoordinationModule** : Orchestrateur global système
- Premier module lancé, dernier fermé
- Charge gameconfig.json via IDataTree
- Déploie modules selon topologie (local/distant)
- Synchronise configurations entre tous les modules
**IModule** : Logique métier pure (BREAKING CHANGES)
```cpp
class IModule {
virtual json process(const json& input) = 0; // PURE FUNCTION
virtual void initialize(const json& config) = 0;
virtual void setConfiguration(const IDataNode& configNode, IIO* io, ITaskScheduler* scheduler) = 0; // NEW
virtual const IDataNode& getConfiguration() = 0; // NEW
virtual json getHealthStatus() = 0; // NEW - detailed JSON instead of bool
virtual void shutdown() = 0;
// initialize() method REMOVED
};
```

View File

@ -0,0 +1,488 @@
# Climate Simulation System
**Status**: Designed - Ready for Implementation
**Scope**: Realistic climate patterns through mobile wind regions and convergence zones
**Integration**: Uses existing TectonicRegions framework
## System Overview
Revolutionary climate simulation using **mobile wind regions** that spawn, evolve, and interact to create emergent weather patterns. Solves the "Sahara vs Congo" problem through **Inter-Tropical Convergence Zones (ITCZ)** and **planetary rotation bands** without complex 3D atmospheric physics.
### Key Innovations
- **Mobile WindRegions** with token-based distribution system
- **ITCZ gravitational zones** based on continental mass
- **Planetary rotation bands** for realistic circulation patterns
- **Emergent storm evolution** from simple wind interactions
- **Destruction token system** for persistent terrain effects
## Core Concepts
### WindRegion Mobile Entities
```json
"wind_region": {
"position": [x, y],
"wind_strength": 1.0, // Base intensity (decays over time)
"wetness": 0.0, // Moisture content (gained over ocean)
"velocity": [vx, vy], // Movement vector
"wind_tokens": 100, // Distributed to tiles
"decay_per_move": 0.02, // -2% strength per movement
"decay_per_tile": 0.01 // -1% strength per tile crossed
}
```
### ITCZ Convergence Zones
```json
"itcz_zone": {
"center": [x, y],
"gravitational_range": "sqrt(landmass_area) * 50",
"aspiration_strength": "landmass_mass / distance^2",
"amplification_factor": 3.0, // Wind strength multiplier at center
"latitude_requirement": [0.45, 0.55] // Equatorial band only
}
```
## Simulation Architecture
### Phase 1: Landmass Analysis and ITCZ Generation
**Uses Existing TectonicRegions:**
```cpp
// Analyze continental masses from existing tectonic data
std::vector<Continent> continents = groupTectonicRegions();
// Generate water masses by inverse analysis
std::vector<WaterMass> oceans = detectOceanBasins(continents);
// Place ITCZ zones on qualifying equatorial landmasses
for (auto& continent : continents) {
if (continent.latitude >= 0.45 && continent.latitude <= 0.55 &&
continent.area > MIN_LANDMASS_SIZE) {
createITCZ(continent.center, sqrt(continent.area));
}
}
```
**ITCZ Requirements:**
- **Latitude Band**: 45-55% of map height (equatorial)
- **Minimum Landmass**: 10,000+ tiles
- **Ocean Proximity**: Within 800km for moisture source
- **Continental Heating**: Large thermal mass for convection
### Phase 2: WindRegion Spawning System
**Procedural Spawn Rules:**
```json
"wind_spawn_system": {
"spawn_locations": "ocean_masses_only",
"spawn_frequency": "water_mass_size / 1000",
"initial_strength": "water_temperature * evaporation_factor",
"region_size": "sqrt(water_mass_area) / 10",
"tokens_per_region": "base_tokens * size_factor",
"spawn_distribution": "random_within_water_region_biased_toward_center"
}
```
**Note**: WindRegions spawn aléatoirement dans le rayon de la waterRegion avec une distribution de spawn plutôt vers le centre pour éviter les spawns en bordure systématiques.
**Spawn Distribution:**
- **Large Oceans** (Pacific): Big regions, high frequency
- **Medium Seas** (Mediterranean): Medium regions, moderate frequency
- **Small Bays**: Small regions, low frequency
- **No Land Spawning**: All weather originates from water bodies
### Phase 3: Movement and Planetary Circulation
**Planetary Rotation Bands** (based on real 10hPa atmospheric data):
```json
"planetary_circulation": {
"polar_jet_north": {
"latitude_range": [0.10, 0.25],
"direction": "west_to_east",
"strength": 1.8
},
"calm_transition_1": {
"latitude_range": [0.25, 0.40],
"movement": "chaos_plus_procedural"
},
"equatorial_trades": {
"latitude_range": [0.40, 0.60],
"direction": "east_to_west",
"strength": 1.5
},
"calm_transition_2": {
"latitude_range": [0.60, 0.75],
"movement": "chaos_plus_procedural"
},
"polar_jet_south": {
"latitude_range": [0.75, 0.95],
"direction": "west_to_east",
"strength": 1.8
}
}
```
**Movement Calculation:**
```cpp
Vector2 movement =
planetary_rotation_band * 0.6 + // 60% planetary circulation
equator_to_pole_bias * 0.2 + // 20% thermal circulation
terrain_deflection * 0.1 + // 10% topographic influence
random_variation * 0.1; // 10% chaos
```
### Phase 4: WindRegion Evolution and Interactions
**Dynamic Evolution:**
```cpp
void updateWindRegion(WindRegion& region) {
// Gain moisture over water
if (currentTile.isOcean()) {
region.wetness += OCEAN_MOISTURE_GAIN;
}
// Repulsion from other regions = acceleration
// NOTE: Not physical repulsion - proxy for spatial competition and turbulence
// Prevents region stacking while creating realistic dispersion patterns
// CRITIQUE POINT: May cause "force field" effect around ITCZ zones where regions
// oscillate/scatter instead of converging due to attraction vs repulsion conflict.
// Alternative approaches: density-based drift, no interaction, or collision division.
// TODO: Implement as configurable algorithm options for empirical testing.
float repulsion = calculateRepulsionForce(region, nearbyRegions);
region.wind_strength += repulsion * ACCELERATION_FACTOR;
// Movement decay
region.wind_strength *= (1.0 - DECAY_PER_MOVE);
// Tile crossing cost
region.wind_strength *= (1.0 - DECAY_PER_TILE);
// Die when too weak
if (region.wind_strength < MINIMUM_THRESHOLD) {
destroyRegion(region);
}
}
```
**ITCZ Gravitational Effects:**
```cpp
void applyITCZGravity(WindRegion& region) {
for (auto& itcz : active_itcz_zones) {
float distance = calculateDistance(region.position, itcz.center);
if (distance < itcz.gravitational_range) {
// Attraction force (inverse square law)
// NOTE: "Gravitational" metaphor for influence strength, not literal physics
// Like saying someone has "gravitas" - clear semantic meaning for developers
float attraction = itcz.mass / (distance * distance);
Vector2 pull_direction = normalize(itcz.center - region.position);
// Apply attraction
region.velocity += pull_direction * attraction;
// Amplification effect as region approaches
float proximity = (itcz.range - distance) / itcz.range;
float amplification = 1.0 + (itcz.max_amplification * proximity);
region.wind_strength *= amplification;
region.wetness *= amplification;
}
}
}
```
### Phase 5: Storm Classification and Token Distribution
**Climate Zone Classification:**
```cpp
// Simple thresholds for climate zone determination
const float HIGH_WIND_THRESHOLD = 2.0;
const float FLOOD_THRESHOLD = 1.5;
const float HURRICANE_WIND = 2.5;
const float HURRICANE_RAIN = 2.0;
bool isHighWindZone(const WindRegion& region) {
return region.wind_strength >= HIGH_WIND_THRESHOLD;
}
bool isFloodZone(const WindRegion& region) {
return region.wetness >= FLOOD_THRESHOLD;
}
bool isHurricaneZone(const WindRegion& region) {
return region.wind_strength >= HURRICANE_WIND && region.wetness >= HURRICANE_RAIN;
}
```
**Token Distribution System:**
```cpp
void distributeTokens(WindRegion& region) {
// Basic climate tokens for all regions
int wind_tokens = static_cast<int>(region.wind_strength * 10);
int rain_tokens = static_cast<int>(region.wetness * 10);
WorldTile& tile = world_map.getTile(region.position);
tile.addTokens("wind", wind_tokens);
tile.addTokens("rain", rain_tokens);
// Special climate zone tokens for extreme weather
if (isHighWindZone(region)) {
tile.addTokens("highWind", 1); // Hostile to forests
}
if (isFloodZone(region)) {
tile.addTokens("flood", 1); // Forces wetlands/marshes
}
if (isHurricaneZone(region)) {
tile.addTokens("hurricane", 1); // Specialized hurricane biome
}
// Consume distributed tokens from region
region.wind_tokens -= wind_tokens;
region.rain_tokens -= rain_tokens;
}
```
## Geographic Climate Patterns
### Realistic Climate Formation
**Congo Basin (Rainforest):**
```
1. Large African landmass → Strong ITCZ at equator
2. Atlantic wind regions spawn → Move east via trade winds
3. ITCZ aspiration → Convergence at Congo → Amplification ×3
4. Super-humid storms → Massive rain token distribution
5. Result: Dense rainforest biome
```
**Sahara Desert:**
```
1. Sahara latitude (25-35°N) → Outside ITCZ band
2. No convergence zone → Wind regions pass through
3. Continental distance → Low initial moisture
4. Subtropical high pressure → Air descends (simulated via movement patterns)
5. Result: Minimal rain tokens → Desert biome
```
**Egypt/Algeria Coastal:**
```
1. Mediterranean wind regions → Moderate moisture
2. Coastal proximity → Some rain tokens
3. Sahara interior → Moisture depleted inland
4. Result: Mediterranean coastal climate → Desert interior gradient
```
### Emergent Seasonal Patterns
**ITCZ Strength Variation:**
```json
"seasonal_modulation": {
"itcz_strength_summer": 1.5, // Stronger convection
"itcz_strength_winter": 0.8, // Weaker convection
"spawn_rate_summer": 1.3, // More wind regions
"spawn_rate_winter": 0.7 // Fewer wind regions
}
```
**Results:**
- **Monsoon Seasons**: ITCZ amplification cycles
- **Hurricane Seasons**: Increased spawn rates + ITCZ amplification
- **Dry Seasons**: Reduced ITCZ strength + lower spawn rates
## Climate Zone Effects on Biome Generation
### Token-Based Biome Classification
**Climate Token Usage:**
```cpp
BiomeType classifyBiome(const WorldTile& tile) {
int total_rain = tile.getAccumulatedTokens("rain");
int total_wind = tile.getAccumulatedTokens("wind");
int highWind_tokens = tile.getAccumulatedTokens("highWind");
int flood_tokens = tile.getAccumulatedTokens("flood");
int hurricane_tokens = tile.getAccumulatedTokens("hurricane");
// Special climate zones override normal biome classification
if (hurricane_tokens > 0) {
return BiomeType::HURRICANE_ZONE; // Specialized storm-resistant vegetation
}
if (flood_tokens > FLOOD_THRESHOLD) {
return BiomeType::WETLANDS; // Forced marshes/swamps
}
if (highWind_tokens > STORM_THRESHOLD) {
// High wind prevents forest growth
if (total_rain > 300) {
return BiomeType::STORM_PRAIRIE; // Grasslands that can handle wind
} else {
return BiomeType::BADLANDS; // Sparse, wind-resistant vegetation
}
}
// Normal biome classification using basic rain/wind tokens
if (total_rain > 500) {
return BiomeType::TROPICAL_RAINFOREST;
} else if (total_rain < 50) {
return BiomeType::HOT_DESERT;
}
// ... additional normal biome logic
}
```
**Climate Zone Characteristics:**
- **Hurricane Zones** → Storm-resistant palms, specialized coastal vegetation
- **Flood Zones** → Wetlands, marshes, swamp vegetation mandatory
- **High Wind Zones** → No forests allowed, prairie/badlands only
- **Normal Zones** → Standard biome classification by rain/temperature
## Performance Characteristics
### Computational Complexity
- **Wind Regions**: O(n) for n active regions (~50-200 simultaneously)
- **ITCZ Calculations**: O(m) for m convergence zones (~5-15 globally)
- **Token Distribution**: O(tiles_visited) per region movement
- **Total per cycle**: O(n × average_movement_distance)
### Memory Usage
- **WindRegion**: 32 bytes per region
- **ITCZ Zone**: 24 bytes per zone
- **Token accumulation**: Uses existing tile data structure
- **Estimated total**: <5MB for global weather simulation
### Generation Time
- **Landmass analysis**: 1-2 seconds (one-time setup)
- **Per simulation cycle**: 10-50ms for 100-200 wind regions
- **Full climate stabilization**: 100-500 cycles → 10-30 seconds total
## Integration with Existing Systems
### TectonicRegions Reuse
```cpp
// Leverage existing tectonic analysis
class ClimateSystem {
void initializeFromTectonics(const std::vector<TectonicRegion>& regions) {
auto continents = groupRegionsByProximity(regions);
auto oceans = calculateOceanBasins(continents);
generateITCZFromContinents(continents);
setupWindSpawnFromOceans(oceans);
}
};
```
### RegionalInfluence Framework
```cpp
// Wind regions as mobile regional influences
class WindRegion : public RegionalInfluence {
void applyInfluenceToTile(WorldTile& tile) override {
distributeTokens(tile);
// Create regional influence for persistent effects
if (isStormLevel()) {
createPersistentInfluence(tile, getStormType());
}
}
};
```
### Biome Generation Integration
```cpp
// Use accumulated climate tokens for biome classification
BiomeType classifyBiome(const WorldTile& tile) {
int total_rain = tile.getAccumulatedTokens("rain");
int total_wind = tile.getAccumulatedTokens("wind");
float temperature = tile.getTemperature();
if (total_rain > 500 && temperature > 20.0f) {
return BiomeType::TROPICAL_RAINFOREST;
} else if (total_rain < 50 && temperature > 15.0f) {
return BiomeType::HOT_DESERT;
}
// ... additional biome logic
}
```
## Implementation Priority
### Phase 1: Core Framework (1-2 weeks)
1. WindRegion class and basic movement
2. Token distribution system
3. Simple spawn from ocean detection
4. Basic planetary circulation bands
### Phase 2: ITCZ System (1-2 weeks)
1. Landmass analysis from TectonicRegions
2. ITCZ generation and gravitational effects
3. Wind region amplification mechanics
4. Storm classification system
### Phase 3: Advanced Features (1-2 weeks)
1. Destruction token system and persistent effects
2. Seasonal variation and modulation
3. Performance optimization
4. Integration with biome generation
### Phase 4: Tuning and Validation (1 week)
1. Parameter adjustment for realistic patterns
2. Verification of Congo/Sahara differentiation
3. Performance profiling and optimization
4. Documentation and examples
## Configuration Example
```json
{
"climate_simulation": {
"wind_spawn_system": {
"base_spawn_rate": 0.1,
"ocean_size_factor": 0.001,
"max_concurrent_regions": 200
},
"planetary_circulation": {
"trade_winds_strength": 1.5,
"jet_stream_strength": 1.8,
"calm_zone_chaos": 0.3
},
"itcz_system": {
"latitude_band": [0.45, 0.55],
"min_landmass_size": 10000,
"max_ocean_distance": 800,
"amplification_max": 3.0
},
"storm_thresholds": {
"high_wind_min": 2.0,
"flood_wetness_min": 1.5,
"hurricane_wind_min": 2.5,
"hurricane_rain_min": 2.0
},
"token_distribution": {
"wind_token_factor": 10,
"rain_token_factor": 10,
"climate_zone_rate": 1
}
}
}
```
**Note**: All parameters are hot-reloadable via the modular configuration system. Magic numbers are intentionally externalizable for real-time tuning during development - adjust values, save config, see immediate results without recompilation.
```
## Scientific Accuracy vs Gameplay
### Scientifically Inspired Elements
- ✅ ITCZ formation from continental heating
- ✅ Planetary circulation bands (trade winds, jet streams)
- ✅ Storm formation from wind-moisture interaction
- ✅ Geographic influence on climate patterns
- ✅ Persistent landscape effects from weather
### Gameplay Simplifications
- ⚠️ 2D simulation instead of 3D atmospheric layers
- ⚠️ Simplified storm evolution (no pressure systems)
- ⚠️ Discrete token system instead of continuous fields
- ⚠️ Accelerated timeframes for practical simulation
### Result
**Plausible climate science** that creates **engaging gameplay** with **emergent complexity** from **simple, understandable rules**.
---
**Status**: System designed and ready for implementation. Provides realistic climate differentiation (Sahara vs Congo) through elegant mobile region simulation using existing tectonic framework.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,419 @@
# Message Communication System
## Vue d'ensemble
Le système de communication inter-modules utilise des **classes de messages typées** au lieu de JSON brut pour garantir la fiabilité et la maintenabilité.
## Concept fondamental
**Une classe = un type de message**
**Une instance = un message individuel**
Exemple: La classe `TankMovedMessage` définit le type "mouvement de tank". Chaque fois qu'un tank bouge, on crée une nouvelle instance de cette classe.
## Pourquoi des classes?
### Problème avec JSON brut
- Erreurs découvertes uniquement au runtime
- Pas de validation automatique
- Typos dans les clés non détectées
- Difficile à maintenir et refactoriser
### Solution avec classes
- Validation au compile-time
- Contrat clair entre modules
- IDE autocomplétion et refactoring
- Hot-reload friendly (petites classes isolées)
- Évolutif (ajout de champs sans casser l'existant)
## Architecture
### IMessage - Interface de base
Interface pure définissant le contrat minimal pour tous les messages:
- **Type identification**: Chaque message déclare son type via enum
- **Serialization**: Conversion vers JSON pour transport via IIO
- **Deserialization**: Reconstruction depuis JSON reçu
### AMessage - Classe abstraite avec métadata
Classe abstraite obligatoire fournissant l'implémentation partielle commune à tous les messages.
**Métadata immutables (enforced):**
- `timestamp` - Horodatage de création (const)
- `sender` - Module émetteur (const)
- `messageId` - ID unique pour tracking et reassemblage fragments (const)
- `partId` - ID de fragment pour messages multi-parts (const)
**Caractéristiques:**
- Constructeur protégé force passage par classes enfants
- Métadata initialisées automatiquement à la construction
- Impossible de modifier métadata après création
- Tous messages garantis d'avoir timestamp/sender/messageId
### MessageType - Enum central
Enum listant tous les types de messages du système:
- `TANK_MOVED`, `TANK_FIRED`, `TANK_DESTROYED`
- `PRICE_UPDATED`, `TRADE_EXECUTED`
- `ITEM_PRODUCED`, `BELT_CONGESTION`
- etc.
**Pourquoi enum plutôt que strings?**
- Performance (comparaison d'entiers)
- Type safety (typos détectées au compile)
- Centralisation (tous les types visibles)
### Messages concrets
Chaque type de message est une classe dédiée héritant de `AMessage`:
**TankMovedMessage**: Position, vitesse, ID tank
**PriceUpdatedMessage**: Item, ancien prix, nouveau prix
**ItemProducedMessage**: Item type, quantité, factory ID
Chaque classe:
- Hérite obligatoirement de `AMessage`
- Appelle constructeur `AMessage(senderModule)`
- Stocke ses données spécifiques
- Valide à la construction
- Sérialise/désérialise son propre format
## Flow de communication
### Publication
**Exemple complet:**
```cpp
void TankModule::process(const json& input) {
// 1. Calculer nouvelle position
Vector2 newPos = calculatePosition();
float currentSpeed = getSpeed();
// 2. Créer message (validation automatique à la construction)
TankMovedMessage msg(newPos, currentSpeed, tankId);
// 3. Sérialiser en JSON
json serialized = msg.serialize();
// 4. Publier via IIO
io->publish("tank:" + std::to_string(tankId), serialized);
}
```
**Étapes:**
1. Module crée instance de message (validation à la construction)
2. Message sérialisé en JSON via `serialize()`
3. Publié via `IIO::publish(topic, json)`
4. IIO route vers subscribers du topic
### Réception
**Méthode 1: Type-safe template helper (recommandé)**
```cpp
// Clean syntax avec type safety automatique
auto tankMsg = io->pullMessageAs<TankMovedMessage>();
if (tankMsg) { // nullptr si type mismatch ou queue vide
Vector2 pos = tankMsg->getPosition();
float speed = tankMsg->getSpeed();
}
```
**Méthode 2: Manuelle (si besoin de flexibilité)**
```cpp
// Récupère message brut
Message rawMsg = io->pullMessage();
// Désérialise vers base
std::unique_ptr<IMessage> baseMsg = IMessage::deserialize(rawMsg.data);
// Cast vers type concret
if (TankMovedMessage* tankMsg = dynamic_cast<TankMovedMessage*>(baseMsg.get())) {
// Accès type-safe
}
```
**Template helper implementation:**
```cpp
class IIO {
// Template helper inline (zero overhead)
template<typename T>
std::unique_ptr<T> pullMessageAs() {
if (!hasMessages()) return nullptr;
Message raw = pullMessage();
std::unique_ptr<IMessage> base = IMessage::deserialize(raw.data);
T* casted = dynamic_cast<T*>(base.get());
if (!casted) return nullptr; // Type mismatch
base.release();
return std::unique_ptr<T>(casted);
}
};
```
**Performance:**
- Template inlined = zero function call overhead
- `dynamic_cast` = ~5-10ns (négligeable vs JSON parsing)
- Bottleneck réel = JSON serialization, pas le cast
### Désérialisation centralisée
**Factory pattern avec routing par type:**
```cpp
// IMessage base class
std::unique_ptr<IMessage> IMessage::deserialize(const json& data) {
// Extract type from JSON
int typeInt = data.value("type", -1);
MessageType type = static_cast<MessageType>(typeInt);
// Route to concrete deserializer
switch (type) {
case MessageType::TANK_MOVED:
return TankMovedMessage::deserialize(data);
case MessageType::PRICE_UPDATED:
return PriceUpdatedMessage::deserialize(data);
case MessageType::ITEM_PRODUCED:
return ItemProducedMessage::deserialize(data);
// Add new messages here
default:
return nullptr; // Unknown type
}
}
```
**Chaque message implémente sa propre désérialisation:**
```cpp
class TankMovedMessage : public AMessage {
static std::unique_ptr<TankMovedMessage> deserialize(const json& data) {
try {
Vector2 pos{data["position"]["x"], data["position"]["y"]};
float speed = data["speed"];
int tankId = data["tankId"];
return std::make_unique<TankMovedMessage>(pos, speed, tankId);
} catch (const json::exception& e) {
return nullptr; // Malformed JSON
}
}
};
```
**Gestion des erreurs:**
- JSON malformé → retourne `nullptr`
- Type inconnu → retourne `nullptr`
- Validation échoue → exception à la construction
- Modules doivent vérifier `if (msg != nullptr)`
## Organisation du code
### Location des messages
```
modules/shared/messages/
├── IMessage.h # Interface pure
├── AMessage.h # Classe abstraite avec métadata
├── MessageType.h # Enum des types
├── TankMovedMessage.h
├── PriceUpdatedMessage.h
└── ...
```
**Rationale:**
- Single source of truth (pas de duplication)
- Contrat partagé entre émetteur et récepteur
- Facile à trouver et maintenir
### Validation
**À la construction**: Invariants validés immédiatement
- Vitesse négative → exception
- ID invalide → exception
- Fail fast pour détecter bugs tôt
**À la désérialisation**: Données réseau/externes validées
- JSON malformé → retourne nullptr
- Champs manquants → retourne nullptr
- Protège contre données corrompues
## Décisions de design finalisées
### Versioning - Breaking changes assumées
**Décision:** Types versionnés avec breaking changes strictes
Changement de format = nouveau type + nouvelle classe:
- `TANK_MOVED_V1``TANK_MOVED_V2` = types différents
- Pas de backward compatibility
- Pas de forward compatibility
- Migration forcée de tous les modules
**Rationale:**
- Zéro ambiguïté sur le format attendu
- Pas de logique conditionnelle complexe
- Hot-reload force mise à jour synchronisée
- Détection immédiate des incompatibilités
- Code simple et clair
**Conséquence:**
- Format change → tous modules doivent migrer
- Ancien code ne compile plus → migration manuelle obligatoire
- Breaking changes explicites et visibles
### Message inheritance - AMessage obligatoire
**Décision:** Classe abstraite `AMessage` avec métadata immutables enforced
Architecture:
```
IMessage (interface pure)
AMessage (classe abstraite - métadata immutables)
TankMovedMessage, PriceUpdatedMessage... (classes concrètes)
```
**Enforcement:**
- Constructeur `AMessage` protégé → impossible de créer message sans passer par enfant
- Métadata const → immutables après construction
- Tous messages garantis d'avoir timestamp/sender/messageId
- Format uniforme pour tous messages du système
**Rationale:**
- Pas de duplication (métadata dans AMessage)
- Impossible d'oublier métadata
- Contrat strict et enforced au compile-time
- Simplicité pour messages concrets (métadata automatique)
## Décisions de design finalisées (suite)
### Size limits - Fragmentation automatique par IO
**Décision:** Pas de limite au niveau message, fragmentation automatique par couche transport
**Architecture:**
- **Modules**: Publient/reçoivent messages complets (transparence totale)
- **IIO**: Gère fragmentation/défragmentation automatiquement
- **Transport adaptatif**: Fragmentation si nécessaire selon type IO
**Fragmentation par type:**
- **IntraIO**: Pas de fragmentation (copie mémoire directe)
- **LocalIO**: Fragmentation si > seuil (ex: 64KB chunks)
- **NetworkIO**: Fragmentation si > MTU (~1500 bytes)
**Mécanisme:**
1. Module publie message → sérialisé en JSON
2. IO détecte si taille > seuil transport
3. Si oui: découpe en fragments avec `messageId` + `partId`
4. Transport des fragments
5. IO destination reassemble via `messageId` (collect tous `partId`)
6. Module reçoit message complet via `pullMessage()`
**Robustesse:**
- **Packet loss**: Timeout si fragments incomplets (ex: 30s)
- **Ordering**: `partId` garantit ordre de reassemblage
- **Monitoring**: Log warning si message > 100KB (design smell probable)
**Conséquence:**
- Messages peuvent être arbitrairement gros
- Complexité cachée dans couche IO
- Performance optimisée par type de transport
### Async handling - Délégation au module
**Décision:** Pas de gestion async spéciale au niveau messages
**Rationale:**
- Messages = transport de données uniquement
- `ITaskScheduler` existe déjà pour opérations coûteuses
- Module décide si déléguer ou traiter directement
- Keep messages simple et stupid
**Responsabilité:**
- **Message**: Transport de données (aucune intelligence)
- **Module**: Décide de déléguer opérations coûteuses au scheduler
- **ITaskScheduler**: Gère threading et async
**Exemple:**
```cpp
// Module reçoit message déclenchant opération coûteuse
if (PathfindingRequestMessage* req = dynamic_cast<...>) {
// Module délègue au TaskScheduler
scheduler->scheduleTask(PATHFINDING_TASK, req->serialize());
// Continue traitement autres messages
}
// Plus tard, récupère résultat
if (scheduler->hasCompletedTasks() > 0) {
TaskResult result = scheduler->getCompletedTask();
// Publie résultat via message
}
```
### Message ordering - Pas de garantie + Messages remplaçables
**Décision:** Pas de garantie d'ordre, modules gèrent via timestamp si critique
**Approche:**
- **Pas de FIFO enforced**: Messages peuvent arriver dans ordre arbitraire
- **Messages remplaçables par défaut**: `SubscriptionConfig.replaceable = true` pour majorité
- **Timestamp disponible**: `msg->getTimestamp()` permet tri manuel si nécessaire
- **Utilité questionnable**: Architecture modulaire rend ordre moins critique
**Rationale:**
- Performance maximale (pas de garanties coûteuses)
- Messages remplaçables optimisent bandwidth (garde juste dernier)
- Timestamp dans `AMessage` permet tri si vraiment nécessaire
- Architecture découple les dépendances temporelles
**Exemples d'usage:**
```cpp
// Prix - remplaçable (dernière valeur suffit)
io->subscribeLowFreq("economy:*", {.replaceable = true});
// Tank position - remplaçable (position actuelle suffit)
io->subscribe("tank:*", {.replaceable = true});
// Events critiques - non remplaçable + tri si nécessaire
io->subscribe("combat:*", {.replaceable = false});
// Si ordre vraiment critique (rare)
std::vector<Message> messages = collectAllMessages();
std::sort(messages.begin(), messages.end(),
[](const Message& a, const Message& b) {
return a.getTimestamp() < b.getTimestamp();
});
```
**Conséquence:**
- Modules ne doivent pas assumer ordre de réception
- Messages remplaçables = dernière valeur seulement
- Tri par timestamp disponible mais rarement nécessaire
## Questions ouvertes
Aucune question ouverte restante. Toutes les décisions de design ont été finalisées.
## Statut d'implémentation
**Phase actuelle:** Design et documentation
**Prochaines étapes:**
1. Créer interface `IMessage.h`
2. Créer classe abstraite `AMessage.h` avec métadata immutables
3. Créer enum `MessageType.h`
4. Implémenter 5-10 messages d'exemple
5. Tester avec modules existants
6. Itérer selon usage réel
## Références
- `src/core/include/warfactory/IIO.h` - Couche pub/sub
- `docs/01-architecture/architecture-technique.md` - Patterns de communication
- `docs/03-implementation/CLAUDE-HOT-RELOAD-GUIDE.md` - Impact sur design messages

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,516 @@
# Rendering System - Sprite Composition
## Vue d'ensemble
Le système de rendu graphique de Warfactory utilise une approche de **composition de sprites** inspirée de Rimworld, optimisée pour minimiser le nombre de sprites à dessiner tout en permettant une grande flexibilité visuelle.
**Principe fondamental** : Chaque entité est composée de sprites superposés avec des orientations indépendantes, permettant un rendu dynamique efficace.
## Architecture de composition
### Personnages (Humains)
Un personnage est composé de **3 sprites maximum** :
```
Personnage
├── Corps (sprite de base + vêtements composés)
├── Tête (orientation indépendante - turret behavior)
└── Arme (orientation indépendante - turret behavior)
```
**Optimisation clé** : Les vêtements sont pré-composés avec le corps pour éviter de dessiner chaque couche de vêtement séparément.
#### Exemple de composition
```
Rendu final = Corps_Base + Veste + Pantalon + Tête + Arme
└─────────────────────┘
1 sprite composé
```
Au lieu de dessiner 5 sprites par personnage, on en dessine **3** :
- 1 sprite corps composé (avec tous les vêtements)
- 1 sprite tête
- 1 sprite arme
### Véhicules
Un véhicule suit le même principe avec un nombre variable de tourelles :
```
Véhicule
├── Corps (sprite fixe avec orientation principale)
└── Tourelles[] (orientations indépendantes)
├── Tourelle principale
├── Tourelle secondaire (optionnelle)
└── Tourelle tertiaire (optionnelle)
```
**Exemple** :
- Tank léger : Corps + 1 tourelle = **2 sprites**
- APC : Corps + 1 tourelle principale + 1 mitrailleuse = **3 sprites**
- Véhicule lourd : Corps + 3 tourelles = **4 sprites**
## Pipeline unifiée : Concept Fixe/Mobile
Le système distingue deux types de composants :
### 1. Composants Fixes
**Définition** : Composants dont l'orientation est liée à l'orientation principale de l'entité.
**Caractéristiques** :
- Rotation synchronisée avec l'entité parente
- Pas de calcul d'orientation indépendant
- Exemples : corps de personnage, châssis de véhicule
```cpp
struct FixedComponent {
SpriteID sprite;
Vector2 offset; // Position relative au centre de l'entité
float rotationOffset; // Rotation additionnelle par rapport à l'orientation principale
};
```
### 2. Composants Mobiles (Turret Behavior)
**Définition** : Composants avec orientation indépendante suivant une cible.
**Caractéristiques** :
- Orientation calculée indépendamment
- Cible une position XY (target)
- Contraintes de rotation optionnelles (angle min/max, vitesse de rotation)
- Exemples : tête de personnage, arme, tourelle de véhicule
```cpp
struct MobileComponent {
SpriteID sprite;
Vector2 offset; // Position relative au centre de l'entité
// Turret behavior
Vector2 currentTarget; // Position XY actuelle de la cible
float currentAngle; // Angle actuel du composant
float rotationSpeed; // Vitesse de rotation max (rad/s)
// Contraintes optionnelles
float minAngle; // Angle minimum (par rapport au fixe)
float maxAngle; // Angle maximum (par rapport au fixe)
bool hasConstraints; // Si true, applique les contraintes min/max
};
```
## Pipeline de rendu unifiée
La **même pipeline** gère les têtes, armes et tourelles :
```cpp
class EntityRenderer {
// Composants fixes (corps)
std::vector<FixedComponent> fixedComponents;
// Composants mobiles (têtes, armes, tourelles)
std::vector<MobileComponent> mobileComponents;
void render(Vector2 position, float mainOrientation) {
// 1. Dessiner les composants fixes
for (const FixedComponent& comp : fixedComponents) {
float finalAngle = mainOrientation + comp.rotationOffset;
drawSprite(comp.sprite, position + rotate(comp.offset, mainOrientation), finalAngle);
}
// 2. Dessiner les composants mobiles
for (MobileComponent& comp : mobileComponents) {
// Calculer l'orientation vers la cible
float targetAngle = calculateAngleToTarget(position, comp.offset, comp.currentTarget);
// Appliquer la vitesse de rotation (smooth rotation)
comp.currentAngle = lerpAngle(comp.currentAngle, targetAngle, comp.rotationSpeed * deltaTime);
// Appliquer les contraintes si nécessaire
if (comp.hasConstraints) {
float relativeAngle = comp.currentAngle - mainOrientation;
comp.currentAngle = mainOrientation + clamp(relativeAngle, comp.minAngle, comp.maxAngle);
}
drawSprite(comp.sprite, position + rotate(comp.offset, mainOrientation), comp.currentAngle);
}
}
};
```
## Exemples concrets
### Personnage avec arme
```cpp
EntityRenderer soldier;
// Corps (fixe)
soldier.fixedComponents.push_back({
.sprite = SPRITE_SOLDIER_BODY_COMPOSED,
.offset = {0, 0},
.rotationOffset = 0
});
// Tête (mobile - turret behavior)
soldier.mobileComponents.push_back({
.sprite = SPRITE_HEAD,
.offset = {0, 8}, // 8 pixels au-dessus du centre
.currentTarget = enemyPosition,
.currentAngle = 0,
.rotationSpeed = 5.0f, // rad/s
.minAngle = -PI/2, // Peut regarder 90° à gauche
.maxAngle = PI/2, // Peut regarder 90° à droite
.hasConstraints = true
});
// Arme (mobile - turret behavior)
soldier.mobileComponents.push_back({
.sprite = SPRITE_RIFLE,
.offset = {4, 2}, // Décalage pour la main
.currentTarget = enemyPosition,
.currentAngle = 0,
.rotationSpeed = 3.0f, // Plus lent que la tête
.minAngle = -PI/4, // Contraintes plus strictes
.maxAngle = PI/4,
.hasConstraints = true
});
// Rendu
soldier.render(soldierPosition, soldierOrientation);
```
### Véhicule avec tourelle
```cpp
EntityRenderer tank;
// Châssis (fixe)
tank.fixedComponents.push_back({
.sprite = SPRITE_TANK_HULL,
.offset = {0, 0},
.rotationOffset = 0
});
// Tourelle principale (mobile - rotation 360°)
tank.mobileComponents.push_back({
.sprite = SPRITE_TANK_TURRET,
.offset = {0, 0},
.currentTarget = targetPosition,
.currentAngle = 0,
.rotationSpeed = 2.0f, // Rotation lente (réaliste)
.hasConstraints = false // Rotation complète
});
// Rendu
tank.render(tankPosition, tankOrientation);
```
## Optimisations
### 1. Composition de sprites (Layering)
**Problème** : Dessiner tous les vêtements séparément = beaucoup de draw calls.
**Solution** : Pré-composer les sprites en cache.
```cpp
class SpriteComposer {
std::unordered_map<CompositionKey, SpriteID> compositionCache;
SpriteID getComposedSprite(const std::vector<LayerID>& layers) {
CompositionKey key = hashLayers(layers);
if (compositionCache.contains(key)) {
return compositionCache[key];
}
// Composer les sprites
SpriteID composed = renderToTexture(layers);
compositionCache[key] = composed;
return composed;
}
};
```
**Exemple** :
```cpp
// Composition d'un soldat
std::vector<LayerID> soldierLayers = {
SPRITE_BODY_BASE,
SPRITE_PANTS_CAMO,
SPRITE_JACKET_TACTICAL,
SPRITE_VEST_ARMOR
};
SpriteID composedBody = composer.getComposedSprite(soldierLayers);
```
**Avantages** :
- Réduction massive des draw calls
- Cache persistant entre frames
- Mise à jour uniquement quand les vêtements changent
### 2. Sprite Batching
Grouper les sprites par texture pour minimiser les changements d'état GPU :
```cpp
// Trier par texture avant de dessiner
std::sort(entities.begin(), entities.end(), [](const Entity& a, const Entity& b) {
return a.getTextureID() < b.getTextureID();
});
// Dessiner tous les sprites de la même texture ensemble
for (const Entity& entity : entities) {
entity.render();
}
```
### 3. Culling
Ne dessiner que les entités visibles à l'écran :
```cpp
void renderEntities(const Camera& camera) {
for (Entity& entity : entities) {
if (camera.isVisible(entity.getBounds())) {
entity.render();
}
}
}
```
## Système de couches (Layering)
### Ordre de rendu (Z-order)
Les sprites doivent être dessinés dans un ordre précis pour éviter les problèmes de superposition :
```
Z-Order (du plus bas au plus haut)
├── 0: Corps/Châssis (fixe)
├── 1: Tête/Tourelle (mobile)
└── 2: Arme (mobile)
```
**Implémentation** :
```cpp
struct RenderableComponent {
SpriteID sprite;
Vector2 position;
float rotation;
int zOrder; // Ordre de rendu
};
void renderEntity(const Entity& entity) {
std::vector<RenderableComponent> renderables;
// Collecter tous les composants
collectFixedComponents(entity, renderables);
collectMobileComponents(entity, renderables);
// Trier par Z-order
std::sort(renderables.begin(), renderables.end(),
[](const RenderableComponent& a, const RenderableComponent& b) {
return a.zOrder < b.zOrder;
});
// Dessiner dans l'ordre
for (const RenderableComponent& comp : renderables) {
drawSprite(comp.sprite, comp.position, comp.rotation);
}
}
```
## Gestion des orientations
### Angles et conventions
**Convention** : Angle 0 = direction droite (East), rotation anti-horaire.
```
N (π/2)
|
W (π) --+-- E (0)
|
S (3π/2)
```
### Calcul de l'angle vers une cible
```cpp
float calculateAngleToTarget(Vector2 entityPos, Vector2 componentOffset, Vector2 target) {
// Position mondiale du composant
Vector2 worldPos = entityPos + componentOffset;
// Direction vers la cible
Vector2 direction = target - worldPos;
// Angle en radians
return std::atan2(direction.y, direction.x);
}
```
### Interpolation d'angle (smooth rotation)
Pour éviter les rotations brusques, on interpole vers l'angle cible :
```cpp
float lerpAngle(float current, float target, float speed, float deltaTime) {
// Normaliser les angles entre -π et π
float diff = normalizeAngle(target - current);
// Calculer le changement maximum pour cette frame
float maxChange = speed * deltaTime;
// Appliquer le changement (limité par la vitesse)
float change = std::clamp(diff, -maxChange, maxChange);
return current + change;
}
float normalizeAngle(float angle) {
while (angle > PI) angle -= 2 * PI;
while (angle < -PI) angle += 2 * PI;
return angle;
}
```
## Extensions futures
### 1. Animations
Ajouter un système d'animation pour les sprites :
```cpp
struct AnimatedComponent {
std::vector<SpriteID> frames;
float frameDuration;
float currentTime;
SpriteID getCurrentFrame() {
int frameIndex = (int)(currentTime / frameDuration) % frames.size();
return frames[frameIndex];
}
void update(float deltaTime) {
currentTime += deltaTime;
}
};
```
### 2. Effets visuels
Ajouter des effets visuels aux composants :
```cpp
struct VisualEffect {
Color tint; // Couleur de teinte
float opacity; // Transparence
Vector2 scale; // Échelle
bool flipX, flipY; // Miroirs
};
```
### 3. Attachments dynamiques
Support pour des composants attachés dynamiquement :
```cpp
class AttachmentSystem {
void attachComponent(EntityID entity, MobileComponent component, const std::string& attachPoint);
void detachComponent(EntityID entity, const std::string& attachPoint);
};
// Exemple : attacher une tourelle sur un point de montage
attachments.attachComponent(vehicleID, turretComponent, "mount_point_1");
```
## Performances
### Métriques cibles
- **Entités à l'écran** : 500-1000 personnages/véhicules simultanés
- **Draw calls** : < 100 par frame (via batching)
- **FPS cible** : 60 fps (16.67ms par frame)
- **Temps de rendu** : < 8ms par frame (50% du budget)
### Profiling
Points de mesure critiques :
```cpp
void renderAll() {
PROFILE_SCOPE("Entity Rendering");
{
PROFILE_SCOPE("Sprite Composition");
updateComposedSprites();
}
{
PROFILE_SCOPE("Culling");
cullEntities(camera);
}
{
PROFILE_SCOPE("Sorting");
sortByTexture(visibleEntities);
}
{
PROFILE_SCOPE("Drawing");
drawEntities(visibleEntities);
}
}
```
## Intégration avec les autres systèmes
### Lien avec le système militaire
Le système de rendu est découplé des systèmes de combat :
- **Combat System** calcule les positions, rotations, cibles
- **Rendering System** lit ces données et dessine les sprites
```cpp
// Dans le module Combat
void updateCombat(Entity& entity, float deltaTime) {
// Calculer la cible
Vector2 target = findClosestEnemy(entity.position);
entity.setTarget(target);
// Le rendering system lira cette cible plus tard
}
// Dans le module Rendering
void render(const Entity& entity) {
// Lire la cible depuis l'entité
Vector2 target = entity.getTarget();
// Dessiner avec la cible
entityRenderer.render(entity.position, entity.orientation, target);
}
```
### Lien avec le système de pathfinding
Le système de rendu utilise les positions calculées par le pathfinding :
```cpp
// Pathfinding calcule la position
Vector2 newPosition = pathfinding.getNextPosition(entity);
entity.setPosition(newPosition);
// Rendering dessine à cette position
render(entity);
```
---
**Statut** : ✅ **DESIGN COMPLETE**
**Prochaines étapes** :
1. Implémenter `EntityRenderer` avec la pipeline fixe/mobile
2. Créer `SpriteComposer` pour la composition de sprites
3. Intégrer avec le système de combat pour les cibles
4. Optimiser avec batching et culling

View File

@ -0,0 +1,677 @@
# Module Versioning System
## Vue d'Ensemble
Le système de versioning des modules utilise un format **MAJOR.MINOR.PATCH.BUILD** automatiquement généré par CMake lors de la compilation. Ce système permet de :
- **Tracer les versions** : Identifier précisément quelle version du code a créé une save
- **Détecter incompatibilités** : Alerter si une save utilise une version différente
- **Debugging** : Reproduire bugs avec la version exacte du module
- **Développement** : Versions incrémentales automatiques sans maintenance manuelle
## Format de Version
### Structure : MAJOR.MINOR.PATCH.BUILD
```
0.1.15.3847
│ │ │ │
│ │ │ └─── BUILD : Auto-increment à chaque build (hash sources)
│ │ └────── PATCH : Auto-increment à chaque commit
│ └──────── MINOR : Manuel (fonctionnalités nouvelles)
└────────── MAJOR : Manuel (breaking changes)
```
### Composantes
#### MAJOR (Manuel)
- **Incrémenté** : Breaking changes, incompatibilités majeures
- **Exemples** : Refonte complète architecture, changement format save incompatible
- **Gestion** : Modifié manuellement dans fichier `VERSION`
- **Valeur initiale** : `0` (pré-release), `1` (première version stable)
#### MINOR (Manuel)
- **Incrémenté** : Nouvelles fonctionnalités, ajouts non-breaking
- **Exemples** : Nouveau type de tank, nouveau système économique
- **Gestion** : Modifié manuellement dans fichier `VERSION`
- **Valeur initiale** : `1`
#### PATCH (Automatique)
- **Incrémenté** : À chaque commit Git
- **Calcul** : Nombre de commits depuis le début du projet
- **Exemples** : Bugfixes, optimisations, refactoring mineur
- **Gestion** : Calculé automatiquement par CMake via `git rev-list --count HEAD`
#### BUILD (Automatique)
- **Incrémenté** : À chaque rebuild (si sources modifiées)
- **Calcul** : Hash MD5 des fichiers sources (`.cpp`, `.h`)
- **But** : Distinguer builds de dev avec code non-commité
- **Gestion** : Calculé automatiquement par CMake
### Exemples de Versions
```
0.1.0.0 → Première version dev (MAJOR.MINOR manuel, PATCH/BUILD = 0)
0.1.5.1234 → Après 5 commits, build 1234
0.1.5.1235 → Même commit, sources modifiées → nouveau build
0.1.6.1235 → Nouveau commit, sources identiques → même build (théorique)
0.2.10.3847 → MINOR bump (nouvelle feature) + 10 commits
1.0.0.0 → Release stable, reset PATCH/BUILD
```
## Implémentation CMake
### Fichier VERSION
Chaque module contient un fichier `VERSION` à la racine :
```
modules/tank/VERSION
```
Contenu du fichier :
```
0.1
```
Ce fichier contient uniquement `MAJOR.MINOR`. Les composantes `PATCH.BUILD` sont calculées automatiquement.
### CMakeLists.txt du Module
```cmake
cmake_minimum_required(VERSION 3.20)
project(TankModule)
# ============================================================================
# MODULE VERSIONING
# ============================================================================
# 1. Lire MAJOR.MINOR depuis fichier VERSION
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BASE_VERSION)
string(STRIP "${BASE_VERSION}" BASE_VERSION)
else()
set(BASE_VERSION "0.1")
message(WARNING "No VERSION file found, using default: ${BASE_VERSION}")
endif()
# 2. Calculer PATCH : nombre de commits Git
execute_process(
COMMAND git rev-list --count HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE PATCH_COUNT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
RESULT_VARIABLE GIT_RESULT
)
if(NOT GIT_RESULT EQUAL 0)
set(PATCH_COUNT "0")
message(WARNING "Git not available, PATCH set to 0")
endif()
# 3. Calculer BUILD : hash des fichiers sources
file(GLOB_RECURSE MODULE_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.h"
)
# Concaténer contenu de tous les fichiers
set(SOURCES_CONTENT "")
foreach(SOURCE_FILE ${MODULE_SOURCES})
file(READ ${SOURCE_FILE} FILE_CONTENT)
string(APPEND SOURCES_CONTENT ${FILE_CONTENT})
endforeach()
# Hash MD5 du contenu total
string(MD5 SOURCES_HASH "${SOURCES_CONTENT}")
# Convertir hash hex en nombre décimal (4 premiers caractères)
string(SUBSTRING ${SOURCES_HASH} 0 4 BUILD_HEX)
# Calculer valeur numérique (modulo 10000 pour limiter à 4 chiffres)
math(EXPR BUILD_NUM "0x${BUILD_HEX} % 10000")
# 4. Assembler version complète
set(MODULE_VERSION "${BASE_VERSION}.${PATCH_COUNT}.${BUILD_NUM}")
message(STATUS "Module version: ${MODULE_VERSION}")
message(STATUS " BASE: ${BASE_VERSION} (from VERSION file)")
message(STATUS " PATCH: ${PATCH_COUNT} (git commits)")
message(STATUS " BUILD: ${BUILD_NUM} (sources hash)")
# 5. Définir macro C++ pour accès au runtime
add_definitions(-DMODULE_VERSION="${MODULE_VERSION}")
# ============================================================================
# MODULE BUILD
# ============================================================================
# Inclure sources
file(GLOB_RECURSE TANK_SOURCES src/*.cpp)
# Créer bibliothèque partagée (.so)
add_library(tank-module SHARED ${TANK_SOURCES})
# Configuration compilation
target_include_directories(tank-module PRIVATE include)
target_compile_features(tank-module PRIVATE cxx_std_20)
# Sortie
set_target_properties(tank-module PROPERTIES
OUTPUT_NAME "tank"
PREFIX ""
SUFFIX ".so"
)
message(STATUS "Building TankModule v${MODULE_VERSION}")
```
### Utilisation dans le Code C++
```cpp
// src/TankModule.h
#ifndef MODULE_VERSION
#define MODULE_VERSION "unknown"
#endif
class TankModule : public IModule, public IModuleSave {
public:
std::string getVersion() const override {
return MODULE_VERSION; // Défini par CMake
}
nlohmann::json serialize() override {
json data;
data["module_name"] = "tank";
data["module_version"] = getVersion(); // "0.1.15.3847"
// ... reste de la sérialisation
return data;
}
};
```
### Affichage au Runtime
```cpp
void TankModule::initialize() {
LOG_INFO("TankModule v{} initializing...", getVersion());
}
```
Sortie console :
```
[INFO] TankModule v0.1.15.3847 initializing...
```
## Workflow de Développement
### 1. Création Nouveau Module
```bash
# Créer structure module
mkdir -p modules/new_module/src
cd modules/new_module
# Créer fichier VERSION
echo "0.1" > VERSION
# Créer CMakeLists.txt avec système versioning
# (copier template ci-dessus)
```
**Première compilation** :
```bash
cmake . && make
```
Sortie :
```
-- Module version: 0.1.0.0
-- BASE: 0.1 (from VERSION file)
-- PATCH: 0 (git commits)
-- BUILD: 0 (sources hash)
-- Building NewModule v0.1.0.0
```
### 2. Développement Itératif
**Scénario 1 : Modifier code sans commit**
```bash
# Éditer src/NewModule.cpp
nano src/NewModule.cpp
# Rebuild
make
```
Sortie :
```
-- Module version: 0.1.0.4582
-- PATCH: 0 (aucun commit)
-- BUILD: 4582 (hash sources a changé)
```
**Scénario 2 : Commit modifications**
```bash
git add .
git commit -m "Add feature X"
# Rebuild
make
```
Sortie :
```
-- Module version: 0.1.1.4582
-- PATCH: 1 (nouveau commit)
-- BUILD: 4582 (sources identiques au commit)
```
**Scénario 3 : Rebuild sans modification**
```bash
# Rebuild immédiat
make
```
Sortie :
```
-- Module version: 0.1.1.4582
(version identique, aucun changement)
```
### 3. Release Mineure (Nouvelle Feature)
```bash
# Bump MINOR version
echo "0.2" > VERSION
# Commit
git add VERSION
git commit -m "Bump version to 0.2 (new feature: advanced tactics)"
# Rebuild
cmake . && make
```
Sortie :
```
-- Module version: 0.2.2.5123
-- BASE: 0.2 (nouvelle version)
-- PATCH: 2 (commits depuis début projet)
-- BUILD: 5123 (hash actuel)
```
### 4. Release Majeure (Breaking Change)
```bash
# Bump MAJOR version
echo "1.0" > VERSION
git add VERSION
git commit -m "Release 1.0.0 - Stable API"
cmake . && make
```
Sortie :
```
-- Module version: 1.0.3.5123
-- BASE: 1.0 (version stable)
-- PATCH: 3 (total commits)
-- BUILD: 5123
```
## Comparaison de Versions
### Dans le Système de Save
Lors du chargement d'une save, comparaison des versions :
```cpp
bool SaveSystem::loadModule(const std::string& moduleName) {
auto module = moduleSystem->getModule(moduleName);
json moduleData = readJsonFile(modulePath);
std::string savedVersion = moduleData["module_version"];
std::string currentVersion = module->getVersion();
if (savedVersion != currentVersion) {
LOG_WARN("Module {} version mismatch:", moduleName);
LOG_WARN(" Save version: {}", savedVersion);
LOG_WARN(" Current version: {}", currentVersion);
// Analyser différences
VersionInfo saved = parseVersion(savedVersion);
VersionInfo current = parseVersion(currentVersion);
if (saved.major != current.major) {
LOG_ERROR(" MAJOR version mismatch - likely incompatible!");
return false; // Incompatibilité critique
}
else if (saved.minor != current.minor) {
LOG_WARN(" MINOR version mismatch - some features may differ");
// Continuer avec warning
}
else if (saved.patch != current.patch) {
LOG_INFO(" PATCH version mismatch - minor changes only");
// Sûr, juste bugfixes
}
else {
LOG_DEBUG(" BUILD version mismatch - dev builds differ");
// Totalement sûr
}
}
return module->deserialize(moduleData);
}
```
### Structure VersionInfo
```cpp
struct VersionInfo {
int major;
int minor;
int patch;
int build;
static VersionInfo parse(const std::string& versionStr) {
VersionInfo info;
std::sscanf(versionStr.c_str(), "%d.%d.%d.%d",
&info.major, &info.minor, &info.patch, &info.build);
return info;
}
bool isCompatibleWith(const VersionInfo& other) const {
// Compatible si MAJOR identique
return major == other.major;
}
bool hasBreakingChanges(const VersionInfo& other) const {
return major != other.major;
}
};
```
## Gestion Multi-Modules
### Script CMake Global
Pour centraliser la logique de versioning, créer un fichier CMake réutilisable :
```cmake
# cmake/ModuleVersioning.cmake
function(setup_module_versioning)
# Lire VERSION
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" BASE_VERSION)
string(STRIP "${BASE_VERSION}" BASE_VERSION)
else()
set(BASE_VERSION "0.1")
endif()
# Calculer PATCH
execute_process(
COMMAND git rev-list --count HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE PATCH_COUNT
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
RESULT_VARIABLE GIT_RESULT
)
if(NOT GIT_RESULT EQUAL 0)
set(PATCH_COUNT "0")
endif()
# Calculer BUILD
file(GLOB_RECURSE MODULE_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
"${CMAKE_CURRENT_SOURCE_DIR}/include/*.h"
)
set(SOURCES_CONTENT "")
foreach(SOURCE_FILE ${MODULE_SOURCES})
file(READ ${SOURCE_FILE} FILE_CONTENT)
string(APPEND SOURCES_CONTENT ${FILE_CONTENT})
endforeach()
string(MD5 SOURCES_HASH "${SOURCES_CONTENT}")
string(SUBSTRING ${SOURCES_HASH} 0 4 BUILD_HEX)
math(EXPR BUILD_NUM "0x${BUILD_HEX} % 10000")
# Assembler version
set(MODULE_VERSION "${BASE_VERSION}.${PATCH_COUNT}.${BUILD_NUM}" PARENT_SCOPE)
# Log
message(STATUS "Module version: ${BASE_VERSION}.${PATCH_COUNT}.${BUILD_NUM}")
endfunction()
```
### Utilisation dans Module
```cmake
# modules/tank/CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(TankModule)
# Importer fonction versioning
include(${CMAKE_SOURCE_DIR}/cmake/ModuleVersioning.cmake)
# Setup version automatique
setup_module_versioning()
# Définir macro
add_definitions(-DMODULE_VERSION="${MODULE_VERSION}")
# ... reste du CMakeLists
```
## Best Practices
### 1. Quand Bumper MAJOR ?
**Situations justifiant MAJOR bump** :
- Changement format save incompatible
- Refonte API du module (signatures fonctions changent)
- Suppression de fonctionnalités existantes
- Changement architecture fondamentale
**Exemple** :
```bash
# Avant : TankModule v0.8.x utilise grille 10x10
# Après : TankModule v1.0.0 utilise grille 16x16 (incompatible)
echo "1.0" > VERSION
```
### 2. Quand Bumper MINOR ?
**Situations justifiant MINOR bump** :
- Ajout nouveau type de tank/composant
- Nouvelle fonctionnalité (mode formation, tactiques AI)
- Amélioration significative sans breaking change
**Exemple** :
```bash
# Ajout système de camouflage → 0.1 → 0.2
echo "0.2" > VERSION
```
### 3. PATCH et BUILD sont Automatiques
**Ne jamais modifier manuellement** :
- PATCH suit automatiquement les commits
- BUILD suit automatiquement les modifications code
### 4. Versioning pour Tests
En environnement de test, fixer une version stable :
```cmake
if(DEFINED ENV{CI_BUILD})
# Build CI : version fixe pour reproductibilité
set(MODULE_VERSION "0.0.0.0")
else()
# Build normal : versioning automatique
setup_module_versioning()
endif()
```
### 5. Affichage Version au Démarrage
```cpp
void logModuleVersions() {
LOG_INFO("=== Module Versions ===");
for (auto& module : moduleSystem->getAllModules()) {
LOG_INFO(" {}: v{}", module->getName(), module->getVersion());
}
LOG_INFO("=======================");
}
```
Sortie :
```
[INFO] === Module Versions ===
[INFO] tank: v0.1.15.3847
[INFO] economy: v0.2.8.1203
[INFO] factory: v0.1.20.4512
[INFO] transport: v0.1.5.982
[INFO] =======================
```
## Debugging avec Versions
### Reproduire un Bug
Si un bug est reporté avec une save :
1. **Lire version du module dans la save** :
```bash
cat saves/abc123/server_1/tank.json | grep module_version
# "module_version": "0.1.15.3847"
```
2. **Retrouver commit correspondant** :
```bash
# PATCH = 15 commits
git log --oneline | head -n 15 | tail -n 1
```
3. **Vérifier hash sources** :
```bash
# BUILD = 3847 correspond à un certain hash
# Comparer avec hashes de commits proches
```
4. **Checkout version exacte pour debugging** :
```bash
git checkout <commit_hash>
cmake . && make
# Version devrait matcher ou être proche
```
### Logs de Version
```cpp
void TankModule::initialize() {
LOG_INFO("TankModule v{} initializing", getVersion());
LOG_DEBUG(" Compiled: {} {}", __DATE__, __TIME__);
LOG_DEBUG(" Compiler: {}", __VERSION__);
}
```
## Alternatives et Limitations
### Alternative 1 : Semantic Versioning Manuel
**Avantage** : Contrôle total sur versions
**Inconvénient** : Maintenance manuelle, oublis fréquents
### Alternative 2 : Git Tags Only
```cmake
execute_process(
COMMAND git describe --tags --always
OUTPUT_VARIABLE MODULE_VERSION
)
```
**Avantage** : Simple, suit git
**Inconvénient** : Nécessite tags, pas de granularité build
### Limitation Actuelle : Hash Non-Déterministe
Le hash des sources peut varier selon :
- Ordre de lecture des fichiers (filesystem dépendant)
- Encodage des fichiers
- Whitespace differences
**Solution future** : Hash déterministe avec tri des fichiers et normalisation.
## Migration depuis Système Existant
Si des modules existants utilisent un autre système :
```cmake
# Détecter ancien système
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/version.txt")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/version.txt" OLD_VERSION)
message(WARNING "Found old version.txt, migrating to VERSION file")
# Extraire MAJOR.MINOR
string(REGEX MATCH "^[0-9]+\\.[0-9]+" BASE_VERSION ${OLD_VERSION})
file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" "${BASE_VERSION}")
message(STATUS "Migration complete: ${OLD_VERSION} -> ${BASE_VERSION}.x.x")
endif()
```
## Références Croisées
- `systeme-sauvegarde.md` : Utilisation des versions dans le système de save
- `architecture-modulaire.md` : Interface IModule, contraintes modules
- `claude-code-integration.md` : Optimisation builds pour développement AI
## Exemples Complets
### Module Complet avec Versioning
Voir structure complète dans :
```
modules/tank/
├── VERSION # "0.1"
├── CMakeLists.txt # Setup versioning + build
├── src/
│ ├── TankModule.cpp # Utilise MODULE_VERSION
│ └── Tank.cpp
└── include/
└── TankModule.h # Déclare getVersion()
```
### Test Versioning
```cpp
#ifdef TESTING
#include <cassert>
void testVersioning() {
TankModule module;
std::string version = module.getVersion();
assert(!version.empty());
assert(version != "unknown");
// Parse version
VersionInfo info = VersionInfo::parse(version);
assert(info.major >= 0);
assert(info.minor >= 0);
assert(info.patch >= 0);
assert(info.build >= 0);
std::cout << "Versioning test passed: " << version << std::endl;
}
#endif
```

View File

@ -0,0 +1,395 @@
# INTEGRATION MASTER LIST
Complete technical specifications catalog for the Warfactory project.
## Global Architecture Overview
### System Orchestration Flow
```
MainServer Process:
├── CoordinationModule (Global Orchestrator)
│ ├── Loads gameconfig.json via IDataTree
│ ├── Launches local IEngine + modules
│ └── Launches remote servers + engines
├── Local IEngine (manages local modules)
│ ├── IModuleSystem (execution strategy)
│ └── Local Modules (.so files)
└── Remote Servers (launched by coordination)
├── Remote IEngine (manages remote modules)
├── IModuleSystem (execution strategy)
└── Remote Modules (.so files)
```
### Startup Sequence
1. **MainServer** starts and launches **CoordinationModule**
2. **CoordinationModule** calls `startNewGame("gameconfig.json")`
3. **Config Loading**: IDataTree loads and parses gameconfig.json
4. **Deployment Analysis**: Parse deployment section to determine module topology
5. **Local Deployment**: Deploy modules with `target: "local"` to local IEngine
6. **Remote Deployment**: Launch remote servers and deploy modules with `target: "server:IP"`
7. **Synchronization**: All modules receive their configuration via `setConfiguration()`
8. **Game Ready**: Return control to user interface
### Module Lifecycle with New Configuration System
```cpp
// Old way (DEPRECATED)
module->initialize(json_config, io, scheduler);
// New way (CURRENT)
const IDataNode& config = configTree->getNode("modules/production");
module->setConfiguration(config, io, scheduler); // const ref, no copies
// Health monitoring
json health = module->getHealthStatus();
// Returns: {"status": "healthy", "last_process_time_ms": 1.2, "memory_usage_mb": 45}
```
## Core Interface System
### Engine Interfaces (IMMUTABLE)
- **IEngine**: Engine orchestration, module loading, client/coordinator socket management
- **IModuleSystem**: Execution strategy + task scheduling (inherits ITaskScheduler)
- **IModule**: Pure business logic + pub/sub communication + task delegation (**BREAKING CHANGES**)
- **IIO**: Pull-based pub/sub with low-frequency batching and health monitoring
- **ITaskScheduler**: Task delegation interface for module → execution system
### Configuration System (IMMUTABLE)
- **IDataTree**: Configuration tree container with manual hot-reload capabilities
- **IDataNode**: Hierarchical data nodes with pattern matching and property queries (**const methods**)
- **DataTreeFactory**: Factory pattern for flexible data source creation
### Coordination System (NEW)
- **ICoordinationModule**: Global system orchestrator and main game lifecycle manager
## GameConfig.json Architecture
### Central Configuration System
The entire game system is configured through a single **`gameconfig.json`** file that serves as the master configuration:
```json
{
"game": {
"name": "Warfactory Game Session",
"version": "1.0.0",
"save_path": "./saves/game_001"
},
"deployment": {
"modules": [
{
"id": "production_main",
"type": "ProductionModule",
"path": "./modules/production.so",
"target": "local",
"config_path": "modules/production"
},
{
"id": "economy_central",
"type": "EconomyModule",
"path": "./modules/economy.so",
"target": "server:192.168.1.100:8080",
"config_path": "modules/economy"
},
{
"id": "tank_combat",
"type": "TankModule",
"path": "./modules/tank.so",
"target": "cluster:combat_nodes",
"config_path": "modules/tank"
}
]
},
"modules": {
"production": {
"frequency": "60Hz",
"belt_speed": 2.5,
"inserter_capacity": 12
},
"economy": {
"frequency": "0.1Hz",
"inflation_rate": 0.02,
"market_volatility": 0.15
},
"tank": {
"targeting_frequency": "60Hz",
"movement_frequency": "30Hz",
"tactical_frequency": "1Hz"
}
}
}
```
### Configuration Flow
1. **CoordinationModule** loads `gameconfig.json` via IDataTree
2. **Deployment section** defines module topology and distribution
3. **Modules section** contains hierarchical configuration for each module type
4. **Hot-reload** updates propagated to all deployed modules automatically
### CoordinationModule Deployment Logic
```cpp
// Example deployment process
void CoordinationModule::deployModule(const std::string& moduleInstanceId) {
// 1. Get module configuration from gameconfig.json
const IDataNode& deployConfig = configTree->getNode("deployment/modules");
const IDataNode* moduleConfig = deployConfig.getFirstChildByName(moduleInstanceId);
// 2. Determine deployment target
std::string target = moduleConfig->getString("target");
std::string modulePath = moduleConfig->getString("path");
std::string configPath = moduleConfig->getString("config_path");
// 3. Get module-specific configuration
const IDataNode& moduleSettings = configTree->getNode("modules/" + configPath);
// 4. Deploy based on target
if (target == "local") {
localEngine->getModuleSystem()->loadModule(modulePath, moduleSettings);
} else if (target.startswith("server:")) {
deployToRemoteServer(target, modulePath, moduleSettings);
}
}
```
## IDataTree Configuration System Specifications
### Core Architecture
```cpp
namespace warfactory {
class IDataTree {
// Tree access
virtual std::unique_ptr<IDataNode> getRoot() = 0;
virtual std::unique_ptr<IDataNode> getNode(const std::string& path) = 0;
// Manual hot-reload
virtual bool checkForChanges() = 0;
virtual bool reloadIfChanged() = 0;
virtual void onTreeReloaded(std::function<void()> callback) = 0;
// Metadata
virtual std::string getType() = 0;
};
}
```
### IDataNode Capabilities
```cpp
namespace warfactory {
class IDataNode {
// Tree navigation
virtual std::unique_ptr<IDataNode> getChild(const std::string& name) = 0;
virtual std::vector<std::string> getChildNames() = 0;
virtual bool hasChildren() = 0;
// Exact search in children
virtual std::vector<IDataNode*> getChildrenByName(const std::string& name) = 0;
virtual bool hasChildrenByName(const std::string& name) const = 0;
virtual IDataNode* getFirstChildByName(const std::string& name) = 0;
// Pattern matching search (deep search in whole subtree)
virtual std::vector<IDataNode*> getChildrenByNameMatch(const std::string& pattern) = 0;
virtual bool hasChildrenByNameMatch(const std::string& pattern) const = 0;
virtual IDataNode* getFirstChildByNameMatch(const std::string& pattern) = 0;
// Query by properties
virtual std::vector<IDataNode*> queryByProperty(const std::string& propName,
const std::function<bool(const json&)>& predicate) = 0;
// Node's own data
virtual json getData() = 0;
virtual bool hasData() = 0;
virtual void setData(const json& data) = 0;
// Typed data access by property name
virtual std::string getString(const std::string& name, const std::string& defaultValue = "") = 0;
virtual int getInt(const std::string& name, int defaultValue = 0) = 0;
virtual double getDouble(const std::string& name, double defaultValue = 0.0) = 0;
virtual bool getBool(const std::string& name, bool defaultValue = false) = 0;
virtual bool hasProperty(const std::string& name) = 0;
// Hash system for validation & synchro
virtual std::string getDataHash() = 0;
virtual std::string getTreeHash() = 0;
virtual std::string getSubtreeHash(const std::string& childPath) = 0;
// Metadata
virtual std::string getPath() = 0;
virtual std::string getName() = 0;
virtual std::string getNodeType() = 0;
};
}
```
### Configuration Usage Patterns
#### Hierarchical Data Access
```cpp
// Access nested configuration
std::unique_ptr<IDataTree> tree = DataTreeFactory::create("json", "config/vehicles.json");
std::unique_ptr<IDataNode> tank = tree->getNode("vehicles/tanks/heavy/model5");
// Get properties with type safety
int armor = tank->getInt("armor", 100);
double speed = tank->getDouble("speed", 30.0);
std::string name = tank->getString("display_name", "Unknown Tank");
```
#### Pattern Matching Search
```cpp
// Find all components
std::vector<IDataNode*> components = root->getChildrenByNameMatch("component*");
// Find all heavy variants
std::vector<IDataNode*> heavyUnits = root->getChildrenByNameMatch("*heavy*");
// Find specific models
std::vector<IDataNode*> models = root->getChildrenByNameMatch("model_*");
```
#### Property-Based Queries
```cpp
// Find all tanks with armor > 150
std::vector<IDataNode*> heavyTanks = root->queryByProperty("armor", [](const json& val) {
return val.is_number() && val.get<int>() > 150;
});
// Find all vehicles with specific role
std::vector<IDataNode*> scouts = root->queryByProperty("role", [](const json& val) {
return val.is_string() && val.get<std::string>() == "scout";
});
```
#### Hot-Reload Workflow
```cpp
// Manual hot-reload check
if (tree->checkForChanges()) {
if (tree->reloadIfChanged()) {
// Tree was reloaded - update dependent systems
updateGameContent();
}
}
// Register reload callback
tree->onTreeReloaded([]() {
std::cout << "Configuration reloaded - updating systems\n";
notifyAllModules();
});
```
### Hash-Based Validation
```cpp
// Validate specific data integrity
std::string nodeHash = node->getDataHash();
std::string previousHash = loadStoredHash();
if (nodeHash != previousHash) {
// Data has changed - trigger update
synchronizeWithServer(nodeHash);
}
// Validate entire subtree
std::string treeHash = node->getTreeHash();
if (treeHash != expectedTreeHash) {
// Subtree structure or data has changed
performFullValidation();
}
```
### Factory Pattern Usage
```cpp
// JSON configuration
std::unique_ptr<IDataTree> jsonTree = DataTreeFactory::create("json", "config/vehicles.json");
// Future: Database configuration
std::unique_ptr<IDataTree> dbTree = DataTreeFactory::create("database", "postgresql://config_db");
// Future: Network configuration
std::unique_ptr<IDataTree> netTree = DataTreeFactory::create("network", "https://api.example.com/config");
```
## UI Interface System (COMPLETED)
### IUI Architecture
- **Data-Agnostic Design**: Generic interface supporting all content types
- **Type-Safe Enums**: DataType::ECONOMY, RequestType::GET_PRICES for performance
- **Hierarchical Windowing**: Parent → Dock → Split → Tab → Window structure
- **Hybrid Sizing System**: Percentage targets with absolute pixel constraints
### ImGuiUI Implementation
- **Complete Rendering Pipeline**: All DataType content renderers implemented
- **Interactive Callbacks**: Request/response system with onRequest() + custom events
- **Professional Layout**: Economic topbar + companies panel + strategic map + console
- **State Management**: Window persistence, docking configuration, layout serialization
## Module System Specifications
### BREAKING CHANGES in IModule Interface
```cpp
// OLD Interface (DEPRECATED)
class IModule {
virtual void initialize(const json& config, IIO* io, ITaskScheduler* scheduler) = 0;
virtual bool isHealthy() = 0; // Simple boolean
};
// NEW Interface (CURRENT)
class IModule {
virtual void setConfiguration(const IDataNode& configNode, IIO* io, ITaskScheduler* scheduler) = 0;
virtual const IDataNode& getConfiguration() = 0;
virtual json getHealthStatus() = 0; // Detailed JSON report
// initialize() method REMOVED
};
```
### Configuration Immutability Pattern
```cpp
// Modules receive const references - cannot modify configuration
const IDataNode& config = coordinationModule->getConfigurationTree()->getNode("modules/production");
// All getter methods are const to enforce read-only access
int frequency = config.getInt("frequency", 60); // const method
std::string mode = config.getString("mode", "auto"); // const method
// Modifications only possible through CoordinationModule
coordinationModule->syncConfiguration(); // Reloads entire tree
```
### Module Health Monitoring
```cpp
// Detailed health status example
json healthStatus = {
"status": "healthy|degraded|critical|offline",
"last_process_time_ms": 1.2,
"memory_usage_mb": 45,
"error_count": 0,
"warnings": ["High memory usage detected"],
"details": "All subsystems operational",
"uptime_seconds": 3600,
"processed_messages": 15420
};
```
### Module Frequencies & Isolation
- **ProductionModule**: 60Hz (frame-perfect factory operations)
- **TankModule**: 0.1-60Hz (Targeting 60Hz → Movement 30Hz → Tactical 1Hz → Analytics 0.1Hz)
- **EconomyModule**: 0.01-0.1Hz (economic cycles)
- **War Isolation**: ZERO interaction ProductionModule ↔ WarModule
- **Supply Chain**: Factory → LogisticModule → War (unidirectional flow)
### Performance Targets
- **V1 Client**: 30+ fps
- **V2 Client**: 60+ fps
- **V1 Server**: 10+ players
- **V2 Server**: 100+ players
## Development Constraints
### Code Restrictions
- **AUTO KEYWORD PROHIBITED**: Explicit types required throughout codebase
- **Interface Immutability**: Core interfaces NEVER modified once finalized
- **Module Isolation**: No `#include "../"` or parent directory references
- **PUB/SUB Communication**: Module communication via IIO only
### Build System
- **Autonomous Builds**: Each module builds independently
- **Hot-Reload**: 0.4ms average reload time achieved
- **Cross-Platform**: Linux development → Windows .exe automated
- **Debug Tools**: AddressSanitizer + UndefinedBehaviorSanitizer by default
This document serves as the authoritative reference for all technical specifications in the Warfactory project.

View File

@ -134,6 +134,38 @@ class PsychologicalAntiCheat {
- **Continuité améliorée** : Algorithmes liaison inter-chunks
- **Biomes complexes** : Transitions naturelles entre terrains
### Load Balancing et Distribution Avancée
**Future évolution du CoordinationModule** pour optimisation performance automatique :
#### Distribution Intelligente des Modules
- **CPU Load Monitoring** : Surveillance utilisation processeur par module
- **Network Latency Aware** : Placement modules selon latence réseau
- **Memory Usage Optimization** : Répartition selon consommation mémoire
- **Auto-scaling** : Lancement instances multiples modules haute charge
#### Migration Dynamique
```cpp
class LoadBalancer {
void redistributeModules() {
// Analyse performance metrics
if (economyModule.getCPUUsage() > 80%) {
migrateToLowerLoadServer(economyModule);
}
// Optimisation latence
if (networkLatency(tankModule, productionModule) > 50ms) {
colocateModules(tankModule, productionModule);
}
}
};
```
#### Stratégies de Placement
- **Colocation Intelligente** : Modules communicants sur même serveur
- **Geographic Distribution** : Placement modules selon localisation joueurs
- **Resource Affinity** : Modules CPU-intensifs vs I/O-intensifs
- **Hot-Standby** : Réplication modules critiques pour haute disponibilité
### Autres fonctionnalités à explorer
*À compléter selon l'évolution du projet*

1414
docs/ai-framework.md Normal file

File diff suppressed because it is too large Load Diff

842
docs/calcul-menace.md Normal file
View File

@ -0,0 +1,842 @@
# Calcul de Menace Contextuelle
## Vue d'Ensemble
Le système de calcul de menace évalue la **dangerosité qu'une entité représente pour une autre** en analysant non seulement les forces brutes, mais aussi les capacités défensives, la qualité des équipements, et la production industrielle.
### Principes Fondamentaux
- **Contextuel** : Menace calculée selon capacités **des deux parties**
- **Asymétrique** : A menace B ≠ B menace A
- **Sword & Shield** : Qualité défenses réduit menace, jamais totalement
- **Baseline 20%** : Toute arme reste dangereuse à minimum 20% effectiveness
- **Production** : Capacité industrielle = menace future
- **Multi-domaines** : Terre, air, mer évalués séparément puis agrégés
- **Perte coûteuse** : Perdre unité chère = désastre stratégique même avec victoire
### Distinction Menace vs Victoire Tactique
**CRITIQUE** : La menace mesure la **capacité de nuisance stratégique**, pas l'issue du combat tactique.
**Exemple** : 20 tanks modernes peuvent être détruits par saturation, MAIS avant destruction ils peuvent :
- Percer défenses et atteindre objectifs profonds
- Détruire infrastructure critique (QG, dépôts, ponts)
- Infliger pertes massives
- Forcer mobilisation coûteuse
→ Menace élevée même si tanks finalement détruits
→ Perte d'un Leopard 2A7 (8M€) = toujours désastre stratégique
## Échelle de Menace
**Valeurs** : `0` à `2 000 000+` (pas de maximum strict, type `int32_t`)
**Ordres de grandeur** :
- `0` : Aucune menace
- `100 - 1 000` : PMC petit
- `5 000 - 50 000` : Company moyenne
- `100 000` : État petit
- `500 000` : État moyen (France, UK, Allemagne)
- `900 000` : Superpower (USA, Chine, Russie)
- `1 000 000+` : Menace existentielle
## Architecture Calcul
### Formule Globale
```cpp
int calculateThreat(Entity attacker, Entity defender) {
auto params = attacker.getThreatParams();
// Composantes
int current_military = evaluateCurrentForces(attacker, defender);
int production_capacity = evaluateProduction(attacker, defender, params.projection_months);
// Pondération configurable par entité
return current_military * params.current_weight +
production_capacity * params.production_weight;
}
struct ThreatCalculationParams {
int projection_months = 12; // Horizon projection (défaut 12 mois)
float current_weight = 0.6f; // Poids forces actuelles (60%)
float production_weight = 0.4f; // Poids production (40%)
};
```
**Personnalisation par entité** :
- Company **agressive** : `current: 0.8, production: 0.2` (focus court-terme)
- State **prudent** : `current: 0.4, production: 0.6` (focus long-terme)
- PMC **réactif** : `current: 0.9, production: 0.1` (menace immédiate prioritaire)
## Évaluation Forces Actuelles
### Principe : Sword & Shield avec Effectiveness Float
Pour chaque domaine (terre, air, mer), on évalue :
1. **Sword** (attaquant) : Capacités offensives
2. **Shield** (défenseur) : Capacités défensives
3. **Effectiveness** : Ratio pénétration/armure avec baseline 20% minimum
```cpp
int evaluateCurrentForces(Entity attacker, Entity defender) {
int land_threat = evaluateLandThreat(attacker, defender);
int air_threat = evaluateAirThreat(attacker, defender);
int naval_threat = evaluateNavalThreat(attacker, defender);
return land_threat + air_threat + naval_threat;
}
```
## Système Armor vs Penetration
### Référence de Base
Chaque équipement possède des valeurs mesurables :
```cpp
struct Tank {
float armor_average; // Moyenne armure (mm RHA equivalent)
int combat_value; // Valeur au combat
int quantity;
// Exemple Leopard 2A7:
// - Frontal: 950mm RHA
// - Flancs: 200mm RHA
// - Arrière: 100mm RHA
// - Average (pondéré surface): ~400mm
};
struct ATWeapon {
float penetration; // Pénétration max (mm RHA)
int combat_value;
int quantity;
// Exemples:
// - RPG-7: 260mm
// - Milan Gen2: 530mm
// - Javelin Gen3 (top-attack): 800mm
// - Kornet Gen4+ (tandem): 1200mm
};
```
### Calcul Effectiveness (Float)
**Formule baseline 20%** : Toute arme reste dangereuse (flancs, arrière, chance)
```cpp
float calculateCounterEffectiveness(ATWeapon weapon, Tank tank) {
float pen_ratio = weapon.penetration / tank.armor_average;
// BASELINE 20% : TOUJOURS dangereux
const float BASE_EFFECTIVENESS = 0.20f;
if (pen_ratio >= 1.0f) {
// Arme peut percer : scaling jusqu'à 90% max
float bonus = (pen_ratio - 1.0f) * 0.5f;
return min(0.90f, BASE_EFFECTIVENESS + bonus);
}
else {
// Arme sous-dimensionnée : reste à 20% (flancs, arrière, chance)
return BASE_EFFECTIVENESS;
}
}
```
### Exemples Effectiveness
```cpp
// Leopard 2A7 (armor_avg = 400mm) vs différentes armes
RPG-7 (260mm) :
pen_ratio = 260 / 400 = 0.65
effectiveness = 20%
→ 100 RPG-7 needed = 20 "équivalents kill"
→ Coût: 100 × 500€ = 50k€ vs Leopard 8M€ = 0.625% ratio
→ Menace présente mais faible, économiquement viable en masse
Milan Gen2 (530mm) :
pen_ratio = 530 / 400 = 1.325
effectiveness = 20% + (0.325 × 0.5) = 36.25%
→ ~3 missiles = 1 kill probable
→ Menace sérieuse
Javelin Gen3 (800mm top-attack) :
pen_ratio = 800 / 400 = 2.0
effectiveness = 20% + (1.0 × 0.5) = 70%
→ ~1.5 missiles = 1 kill probable
→ Menace très élevée
Kornet Gen4+ (1200mm tandem) :
pen_ratio = 1200 / 400 = 3.0
effectiveness = 20% + (2.0 × 0.5) = 90% (plafonné)
→ ~1.1 missiles = 1 kill quasi-certain
→ Menace maximale
```
## Évaluation Domaine Terrestre
### Inventaire Forces
**Attaquant** :
```cpp
struct LandForces {
std::vector<Tank> tanks;
std::vector<IFV> ifvs;
std::vector<APC> apcs;
std::vector<Artillery> artillery;
std::vector<Infantry> infantry;
};
```
**Défenseur** :
```cpp
struct LandDefenses {
std::vector<ATSystem> anti_tank; // Systèmes anti-char
std::vector<Tank> counter_tanks; // Tanks défensifs
std::vector<Infantry> anti_tank_inf; // Infanterie AT
std::vector<Fortification> fortifications;
};
```
### Couples Équipement ↔ Contre-mesures
**Principe** : Chaque type d'équipement offensif a des contre-mesures spécifiques.
```cpp
struct EquipmentCounters {
std::map<EquipmentType, std::vector<CounterType>> counters = {
{TANK, {AT_MISSILE, AT_GUN, COUNTER_TANK, AT_INFANTRY}},
{IFV, {AT_MISSILE, AT_GUN, AUTOCANNON}},
{APC, {AUTOCANNON, MACHINE_GUN, RPG}},
{INFANTRY, {MACHINE_GUN, ARTILLERY, AUTOCANNON}},
{ARTILLERY, {COUNTER_BATTERY, AIR_STRIKE}}
};
};
```
### Calcul Defensive Effectiveness
```cpp
float calculateDefensiveEffectiveness(
std::vector<Equipment> swords,
std::vector<Defense> shields
) {
float total_sword_value = 0;
float neutralized_value = 0;
for (auto& sword : swords) {
float sword_value = sword.quantity * sword.combat_value;
total_sword_value += sword_value;
// Trouver défenses applicables
auto applicable_shields = findApplicableDefenses(sword, shields);
// Calculer valeur défensive totale contre ce sword
float shield_value = 0;
for (auto& shield : applicable_shields) {
// ✅ EFFECTIVENESS FLOAT (20%-90%)
float effectiveness = calculateCounterEffectiveness(shield, sword);
shield_value += shield.quantity * shield.combat_value * effectiveness;
}
// Neutralisation proportionnelle
float neutralization = min(1.0f, shield_value / sword_value);
neutralized_value += sword_value * neutralization;
}
return total_sword_value > 0 ? (neutralized_value / total_sword_value) : 0.0f;
}
```
### Score Final avec Menace Résiduelle
```cpp
int evaluateLandThreat(Entity attacker, Entity defender) {
auto swords = attacker.getLandForces();
auto shields = defender.getLandDefenses();
// Menace brute (sans défenses)
int raw_threat = 0;
for (auto& sword : swords) {
raw_threat += sword.quantity * sword.combat_value;
}
// Réduction par défenses
float defensive_effectiveness = calculateDefensiveEffectiveness(swords, shields);
// ✅ MENACE RÉSIDUELLE : Jamais totalement nulle si attaquant existe
float residual_multiplier = max(0.05f, 1.0f - defensive_effectiveness);
int final_threat = raw_threat * residual_multiplier;
return final_threat;
}
```
## Exemples Concrets Terre
### Exemple 1 : Tech Obsolète Viable en Masse
**Attaquant** :
- 20 tanks Gen4 (Leopard 2A7)
- armor_average : 400mm RHA
- combat_value : 1000/tank
- Menace brute : 20 000
- Valeur totale : 20 × 8M€ = 160M€
**Défenseur** :
- 5000 RPG-7 (Gen1, ancien)
- penetration : 260mm
- pen_ratio : 260/400 = 0.65
- effectiveness : 20% (baseline)
- combat_value : 50/RPG
- shield_value : 5000 × 50 × 0.20 = 50 000
- Coût : 5000 × 500€ = 2.5M€
**Résultat** :
```
defensive_effectiveness = min(1.0, 50000 / 20000) = 100%
residual_multiplier = max(0.05, 1.0 - 1.0) = 5%
final_threat = 20000 × 0.05 = 1 000
→ Menace quasi-neutralisée (5% résiduel)
→ Nécessite 5000 RPG-7 (masse logistique)
→ Ratio coût défenseur/attaquant = 2.5M€ / 160M€ = 1.56%
→ Défense économiquement viable ✅
→ MAIS perte Leopard reste désastre (8M€ + prestige + formation)
```
### Exemple 2 : Tech Moderne Efficace
**Attaquant** :
- 20 tanks Gen4 (Leopard 2A7)
- armor_average : 400mm
- Menace brute : 20 000
**Défenseur** :
- 100 missiles Javelin Gen3
- penetration : 800mm (top-attack)
- pen_ratio : 800/400 = 2.0
- effectiveness : 70%
- combat_value : 300/missile
- shield_value : 100 × 300 × 0.70 = 21 000
- Coût : 100 × 200k€ = 20M€
**Résultat** :
```
defensive_effectiveness = min(1.0, 21000 / 20000) = 100%
residual_multiplier = 5%
final_threat = 20000 × 0.05 = 1 000
→ Menace quasi-neutralisée
→ Ratio coût : 20M€ / 160M€ = 12.5%
→ Plus cher que RPG-7 mais logistique simplifiée (100 vs 5000)
```
### Exemple 3 : Défense Insuffisante
**Attaquant** :
- 20 tanks Gen4
- Menace brute : 20 000
**Défenseur** :
- 500 RPG-7
- effectiveness : 20%
- shield_value : 500 × 50 × 0.20 = 5 000
**Résultat** :
```
defensive_effectiveness = 5000 / 20000 = 25%
residual_multiplier = max(0.05, 0.75) = 75%
final_threat = 20000 × 0.75 = 15 000
→ Menace reste élevée (75%)
→ Défense insuffisante
```
### Exemple 4 : Défense Mixte Économique
**Attaquant** :
- 20 tanks Gen4
- Menace brute : 20 000
**Défenseur** :
- 30 Javelin Gen3 : shield = 30 × 300 × 0.70 = 6 300
- 1000 RPG-7 : shield = 1000 × 50 × 0.20 = 10 000
- **Shield total** : 16 300
- **Coût total** : 30 × 200k€ + 1000 × 500€ = 6.5M€
**Résultat** :
```
defensive_effectiveness = 16300 / 20000 = 81.5%
residual_multiplier = max(0.05, 0.185) = 18.5%
final_threat = 20000 × 0.185 = 3 700
→ Menace réduite à 18.5% (acceptable)
→ Défense mixte optimise coût-efficacité
→ Ratio coût : 6.5M€ / 160M€ = 4.06%
```
### Exemple 5 : Système de Conception Modulaire - Retrofit Anti-AT
**Attaquant** :
- 20 tanks Leopard 2A7 **retrofittés Gen5**
- Chassis Gen4 base
- **APS Trophy Gen5** : intercepte 80% missiles avant impact
- **ERA Gen5** : neutralise pénétration Gen2-3
- armor_effective : 400mm × 2.5 (ERA bonus) = 1000mm equivalent
- Menace brute : 20 000
**Défenseur** :
- 1000 missiles Milan Gen2
- penetration : 530mm
- pen_ratio : 530/1000 = 0.53 (sous-dimensionné avec ERA)
- effectiveness : 20% (baseline)
- **APS reduction** : 20% × (1 - 0.80) = 4% effectiveness finale
- shield_value : 1000 × 300 × 0.04 = 12 000
**Résultat** :
```
defensive_effectiveness = 12000 / 20000 = 60%
residual_multiplier = max(0.05, 0.40) = 40%
final_threat = 20000 × 0.40 = 8 000
→ Menace reste significative (40%)
→ APS + ERA réduisent drastiquement effectiveness Gen2
→ Système de conception permet adaptation doctrine
→ Joueur peut designer tanks spécifiquement anti-saturation
```
## Évaluation Domaine Aérien
### Spécificités Air
**Complexité supplémentaire** :
- **Qualité prime** : Furtivité et ECM dominent
- **ECM/ECCM** : Guerre électronique critique
- **Compatibilité stricte** : AA anti-hélicoptère ne touche pas jets
```cpp
struct AirForces {
std::vector<Fighter> fighters;
std::vector<Bomber> bombers;
std::vector<Helicopter> helicopters;
std::vector<Drone> drones;
// Capacités spéciales
bool has_stealth;
bool has_ecm; // Electronic Counter-Measures
int electronic_warfare_level;
};
struct AirDefenses {
std::vector<AAMissile> aa_missiles;
std::vector<AAGun> aa_guns;
std::vector<Fighter> interceptors;
// Capacités
bool has_eccm; // Electronic Counter-Counter-Measures
int radar_quality;
std::map<AASystem, TargetCapability> capabilities;
};
enum TargetCapability {
HELICOPTER_ONLY, // Seulement hélicoptères
LOW_ALTITUDE, // Avions basse altitude
HIGH_ALTITUDE, // Avions haute altitude
ALL_AIRCRAFT // Tous types
};
```
### Effectiveness Air avec Stealth/ECM
```cpp
float calculateAirDefenseEffectiveness(Aircraft aircraft, AASystem aa) {
// Base effectiveness selon pénétration radar vs stealth
float base_eff = calculateCounterEffectiveness(aa, aircraft);
// Multiplicateurs tech
float stealth_reduction = 1.0f;
if (aircraft.has_stealth && !aa.has_advanced_radar) {
stealth_reduction = 1.0f - aircraft.stealth_rating; // Ex: 0.1 si 90% stealth
}
float ecm_reduction = 1.0f;
if (aircraft.has_ecm && !aa.has_eccm) {
ecm_reduction = 1.0f - (aircraft.ecm_power / (aa.radar_quality + 1));
}
// Effectiveness finale (baseline 20% toujours appliqué)
float final_eff = max(0.20f, base_eff * stealth_reduction * ecm_reduction);
return final_eff;
}
```
### Exemple Air : Furtivité + ECM
**Attaquant** :
- 20 jets furtifs Gen4 (F-35)
- stealth_rating : 0.90 (réduit détection 90%)
- ecm_power : 8
- combat_value : 2000/jet
- Menace brute : 40 000
**Défenseur** :
- 1000 missiles AA Gen3 (Patriot)
- radar_quality : 6
- has_eccm : false
- base_effectiveness : 70% (tech Gen3 vs Gen4)
- stealth_reduction : 1.0 - 0.90 = 0.10
- ecm_reduction : 1.0 - (8/7) = -0.14 → 0.0 (plancher)
- final_effectiveness : max(0.20, 0.70 × 0.10 × 0.0) = 20% (baseline)
- shield_value : 1000 × 400 × 0.20 = 80 000
**Résultat** :
```
defensive_effectiveness = min(1.0, 80000 / 40000) = 100%
residual_multiplier = 5%
final_threat = 40000 × 0.05 = 2 000
→ Furtivité + ECM ramènent effectiveness au baseline 20%
→ Nécessite masse importante (1000 missiles) pour compenser
→ F-35 peuvent accomplir raid avant saturation (menace 5% résiduelle)
```
## Évaluation Domaine Naval
**Similaire à terrestre/aérien** mais avec spécificités :
- **Torpilles vs sonars** (submersibles)
- **Anti-ship missiles vs CIWS** (Close-In Weapon Systems)
- **Portée extrême** : Naval combat à 100+ km
Structure identique avec couples spécifiques (penetration vs armor pour missiles anti-navire).
## Évaluation Production
### Principe
La menace ne vient pas seulement des forces actuelles, mais aussi de la **capacité à produire** plus d'équipements.
```cpp
int evaluateProduction(Entity attacker, Entity defender, int projection_months) {
int production_threat = 0;
// Pour chaque type d'équipement
for (auto& equipment_type : all_equipment_types) {
// Taux production attaquant
int attacker_rate = attacker.getProductionRate(equipment_type); // unités/mois
// Taux production défenses défenseur
int defender_rate = defender.getProductionRate(getCounterType(equipment_type));
// Projection future
int attacker_produced = attacker_rate * projection_months;
int defender_produced = defender_rate * projection_months;
// Menace nette production
int net_production = attacker_produced - defender_produced;
if (net_production > 0) {
int equipment_value = getEquipmentValue(equipment_type);
production_threat += net_production * equipment_value;
}
}
return production_threat;
}
```
### Exemple Production
**État A** :
- Production actuelle : 50 tanks/mois
- Projection 12 mois : 600 tanks
- Combat value : 400/tank
- Production threat : 600 × 400 = 240 000
**État B** (défenseur) :
- Production AT : 100 missiles/mois
- Projection 12 mois : 1200 missiles
- Combat value : 300/missile
- Effectiveness moyenne : 40%
- Défense production : 1200 × 300 × 0.40 = 144 000
**Net production threat** :
```
Attacker gain : 240 000
Defender gain : 144 000
Net : 240 000 - 144 000 = 96 000
production_threat = 96 000
→ État A a avantage production malgré défenses
```
## Agrégation Finale
### Formule Complète
```cpp
int calculateThreat(Entity attacker, Entity defender) {
auto params = attacker.getThreatParams();
// Forces actuelles (sword & shield par domaine)
int land_threat = evaluateLandThreat(attacker, defender);
int air_threat = evaluateAirThreat(attacker, defender);
int naval_threat = evaluateNavalThreat(attacker, defender);
int current_military = land_threat + air_threat + naval_threat;
// Production future
int production_threat = evaluateProduction(
attacker,
defender,
params.projection_months
);
// Pondération finale
int total_threat = current_military * params.current_weight +
production_threat * params.production_weight;
return total_threat;
}
```
### Exemples Complets
#### Superpower vs État Moyen
**USA vs France**
**USA forces** :
- Tanks : 8000 (Gen3-4) → 3 200 000
- Aircraft : 2000 (Gen4, furtifs) → 4 000 000
- Naval : 500 ships → 2 500 000
- **Total brut** : 9 700 000
**France défenses** :
- AT systems : 3000 (Gen3, eff 60%) → Shield 60% tanks
- AA systems : 1500 (Gen3, eff 40% vs furtifs) → Shield 40% aircraft
- Naval defenses : 200 (eff 50%) → Shield 50% naval
**Après sword & shield** :
- Land : 3 200 000 × max(0.05, 0.40) = 1 280 000
- Air : 4 000 000 × max(0.05, 0.60) = 2 400 000
- Naval : 2 500 000 × max(0.05, 0.50) = 1 250 000
- **Current threat** : 4 930 000
**Production (12 mois)** :
- USA : +600 tanks, +100 aircraft → 360 000
- France : +100 tanks, +50 aircraft → 70 000
- **Net production** : 290 000
**Total (60% current, 40% prod)** :
```
4 930 000 × 0.6 + 290 000 × 0.4 = 3 074 000
→ Menace colossale, mais France peut tenir avec alliances
```
#### PMC vs Company
**PMC_Alpha vs RheinmetallCorp**
**PMC forces** :
- Infantry : 500 (léger armement)
- Vehicles : 20 APCs
- **Total** : 50 000
**Rheinmetall défenses** :
- Security : 100 guards (effectiveness 30%)
- Fortifications : minimal
- **Shield** : 15%
**Threat** :
```
residual = max(0.05, 1.0 - 0.15) = 85%
final_threat = 50000 × 0.85 = 42 500
→ PMC peut menacer installations Company
```
## Cas Spéciaux
### Menace Économique Pure
Pour Companies sans capacités militaires :
```cpp
int calculateEconomicThreat(Company attacker, Company defender) {
// Part de marché
float market_dominance = attacker.market_share / (defender.market_share + 0.01f);
// Capacité production
float production_ratio = attacker.production_capacity / defender.production_capacity;
// Qualité produits
float quality_advantage = attacker.avg_product_quality / defender.avg_product_quality;
// Menace économique
int economic_threat = (market_dominance * 100000) +
(production_ratio * 80000) +
(quality_advantage * 50000);
return economic_threat;
}
```
### Menace Géographique
Distance géographique module menace :
```cpp
float getGeographicModifier(Entity attacker, Entity defender) {
float distance_km = calculateDistance(attacker.position, defender.position);
// Projection power diminue avec distance
if (distance_km < 500) {
return 1.0f; // Menace pleine
}
else if (distance_km < 2000) {
return 0.7f; // 30% réduction
}
else if (distance_km < 5000) {
return 0.4f; // 60% réduction
}
else {
return 0.1f; // 90% réduction (trop loin)
}
}
```
## Implications Stratégiques
### 1. Coût-Efficacité Défensive
```cpp
struct DefenseCostAnalysis {
float threat_neutralized;
float cost;
float cost_efficiency; // menace neutralisée par €
};
// Neutraliser 20 Leopard 2A7 (160M€ total)
Option A - RPG-7 masse (effectiveness 20%) :
- Quantité nécessaire : 100 RPG × 20 tanks = 2000 RPG
- Coût : 2000 × 500€ = 1M€
- Ratio : 1M€ / 160M€ = 0.625%
- Avantage : Très économique
- Inconvénient : Logistique massive
Option B - Javelin Gen3 (effectiveness 70%) :
- Quantité nécessaire : 1.5 Javelin × 20 tanks = 30 Javelin
- Coût : 30 × 200k€ = 6M€
- Ratio : 6M€ / 160M€ = 3.75%
- Avantage : Logistique légère
- Inconvénient : Plus cher
→ RPG-7 est 6× plus cost-efficient, mais logistique 67× plus lourde
→ Choix stratégique selon capacités logistiques
```
### 2. Perte Asymétrique
```cpp
// Exemple bataille : Menace neutralisée mais pertes coûteuses
Attaquant : 20 Leopard 2A7 (160M€)
Défenseur : 5000 RPG-7 (2.5M€)
Outcome tactique :
- Tous Leopards détruits (saturation)
- 2000 RPG-7 utilisés effectivement
Bilan stratégique :
Attaquant pertes :
- 160M€ équipement
- 20 crews élites (formation coûteuse)
- Prestige international
- Capacités offensives réduites
Défenseur pertes :
- 1M€ munitions consommées (2000 RPG effectifs)
- +Victoire propagande
- +Moral défensif
→ Victoire tactique défenseur = victoire stratégique
→ Système menace reflète cette asymétrie via residual 5%
→ Perdre Leopard = toujours désastre même si menace "neutralisée"
```
## Performance et Optimisation
### Cache Threat
```cpp
class ThreatCache {
private:
struct CachedThreat {
int value;
int timestamp;
int ttl = 3600; // 1 heure
};
std::map<std::pair<EntityId, EntityId>, CachedThreat> cache;
public:
int getThreat(EntityId attacker, EntityId defender) {
auto key = std::make_pair(attacker, defender);
if (cache.contains(key)) {
auto& cached = cache[key];
if (getCurrentTime() - cached.timestamp < cached.ttl) {
return cached.value;
}
}
// Recalculer
int threat = calculateThreat(attacker, defender);
cache[key] = {threat, getCurrentTime()};
return threat;
}
void invalidate(EntityId entity) {
// Invalider tous les caches impliquant cette entité
for (auto it = cache.begin(); it != cache.end();) {
if (it->first.first == entity || it->first.second == entity) {
it = cache.erase(it);
} else {
++it;
}
}
}
};
```
### Invalidation Cache
Événements invalidant cache :
- Production nouvelle unité
- Perte unité au combat
- Nouvelle recherche technologique
- Changement doctrine militaire
- Retrofit/upgrade équipement
### Calcul Lazy
```cpp
// Ne calculer que si demandé par IA
int getThreatOnDemand(EntityId attacker, EntityId defender) {
return threatCache.getThreat(attacker, defender);
}
// Pas de recalcul automatique chaque tick
```
## Références Croisées
- `systeme-diplomatique.md` : Utilisation menace dans relations diplomatiques
- `ai-framework.md` : Menace influence décisions IA (achats, alliances)
- `systeme-militaire.md` : Valeurs combat équipements, générations, système conception modulaire
- `economie-logistique.md` : Production rates, capacités industrielles

1090
docs/systeme-diplomatique.md Normal file

File diff suppressed because it is too large Load Diff

715
docs/systeme-sauvegarde.md Normal file
View File

@ -0,0 +1,715 @@
# Système de Sauvegarde
## Philosophie
Le système de sauvegarde suit la philosophie du projet : **évolution itérative avec versioning des systèmes**. Chaque version améliore progressivement les performances et fonctionnalités tout en maintenant la compatibilité.
Le système est conçu pour être **modulaire et autonome**, chaque module gérant sa propre persistence de manière indépendante.
## Version 1 : Save JSON Local Sans Versioning de Format
### Principes de Base
- **Format** : JSON pur pour lisibilité, debugging et édition manuelle
- **Granularité** : Un fichier par module
- **Distribution** : Chaque serveur sauvegarde localement (multi-serveur ready)
- **Coordination** : Clé de save distribuée par le coordinateur
- **Autonomie** : Chaque module implémente son propre `serialize()` / `deserialize()`
- **Chunks** : Seulement les chunks modifiés (metachunks 512x512)
- **Objectif** : Système fonctionnel et suffisant pour tests et développement
### Architecture de Fichiers
```
saves/
└── abc123_1728226320/ # Clé de save : [id]_[timestamp]
├── save_metadata.json # Métadonnées globales de la save
├── server_1/ # Un dossier par serveur (future-proof)
│ ├── tank.json
│ └── combat.json
├── server_2/
│ ├── economy.json
│ └── factory.json
└── metachunks/
├── 0_0.json # Metachunk coords (x, y) en 512x512
├── 0_1.json
└── ...
```
**Note** : En configuration single-process V1, un seul dossier serveur existe (ex: `server_1/`), mais la structure supporte déjà le multi-serveur.
### Format save_metadata.json
Fichier global décrivant la sauvegarde complète :
```json
{
"save_key": "abc123_1728226320",
"timestamp": "2025-10-06T14:32:00Z",
"game_version": "0.1.0-alpha",
"modules": {
"tank": {
"version": "0.1.15.3847",
"load_status": "ok"
},
"economy": {
"version": "0.2.8.1203",
"load_status": "ok"
},
"factory": {
"version": "0.1.20.4512",
"load_status": "load_pending"
},
"transport": {
"version": "0.1.5.982",
"load_status": "ok"
}
},
"metachunks_count": 42,
"world_seed": 1847293847
}
```
**Champs** :
- `save_key` : Identifiant unique de la save (format : `[id]_[timestamp_unix]`)
- `timestamp` : Date/heure de sauvegarde (ISO 8601)
- `game_version` : Version du jeu ayant créé la save
- `modules` : État de chaque module sauvé
- `version` : Version du module (voir `module-versioning.md`)
- `load_status` : `"ok"`, `"load_pending"`, `"failed"`
- `metachunks_count` : Nombre de metachunks sauvés
- `world_seed` : Seed de génération procédurale
### Format Fichiers Modules
Chaque module implémente `IModuleSave` et définit son propre format JSON.
#### Exemple : tank.json
```json
{
"module_name": "tank",
"module_version": "0.1.15.3847",
"save_timestamp": "2025-10-06T14:32:00Z",
"data": {
"tanks": [
{
"id": "tank_001",
"chassis_type": "m1_abrams",
"position": {"x": 1250.5, "y": 3480.2},
"rotation": 45.0,
"components": [
{
"type": "turret_120mm",
"grid_pos": [2, 3],
"health": 100,
"ammo_loaded": "apfsds"
},
{
"type": "engine_turbine",
"grid_pos": [1, 1],
"health": 85,
"fuel": 0.75
}
],
"inventory": {
"120mm_apfsds": 32,
"120mm_heat": 18
},
"crew_status": "operational"
}
]
}
}
```
#### Exemple : economy.json
```json
{
"module_name": "economy",
"module_version": "0.2.8.1203",
"save_timestamp": "2025-10-06T14:32:00Z",
"data": {
"market_prices": {
"iron_ore": 2.5,
"copper_ore": 3.2,
"steel_plate": 8.0
},
"player_balance": 125000,
"pending_transactions": [
{
"id": "tx_4829",
"type": "buy",
"resource": "steel_plate",
"quantity": 1000,
"price_per_unit": 8.0,
"timestamp": "2025-10-06T14:30:15Z"
}
]
}
}
```
**Convention** : Chaque fichier module contient :
- `module_name` : Nom du module (vérification cohérence)
- `module_version` : Version du module ayant créé la save
- `save_timestamp` : Timestamp de sauvegarde
- `data` : Objet contenant toutes les données spécifiques au module
### Format Metachunks (512x512)
Pour réduire le nombre de fichiers, les chunks 64x64 sont regroupés en **metachunks 512x512** (8x8 chunks par metachunk = 64 chunks).
#### Structure Metachunk
```json
{
"metachunk_coords": {"x": 0, "y": 0},
"metachunk_size": 512,
"chunk_size": 64,
"chunks": {
"0_0": {
"terrain": {
"land_ids_base64": "AQIDBAUGBwg...",
"roof_ids_base64": "CQAKAA..."
},
"buildings": [
{
"id": "building_factory_001",
"type": "assembler_mk1",
"position": {"x": 10, "y": 15},
"recipe": "ammunition_7.62mm",
"progress": 0.45,
"inventory": {
"iron_plate": 50,
"copper_wire": 30
}
}
],
"resources": [
{
"type": "iron_ore",
"patch_id": "iron_patch_042",
"positions": [[5,5], [5,6], [6,5], [6,6]],
"amounts": [1000, 950, 980, 1020]
}
]
},
"0_1": {
"terrain": { "land_ids_base64": "..." },
"buildings": [],
"resources": []
}
}
}
```
**Optimisations** :
- **Base64 compression** : Données terrain denses compressées
- **Sparse storage** : Chunks vides omis du metachunk
- **Dirty tracking** : Seulement metachunks avec chunks modifiés sont sauvés
#### Calcul Coords Metachunk
```cpp
// Chunk 64x64 coords → Metachunk 512x512 coords
MetachunkCoords getMetachunkCoords(int chunkX, int chunkY) {
return {
chunkX / 8, // 512 / 64 = 8 chunks par metachunk
chunkY / 8
};
}
// Coords locales dans le metachunk
ChunkLocalCoords getLocalCoords(int chunkX, int chunkY) {
return {
chunkX % 8,
chunkY % 8
};
}
```
### Interface IModuleSave
Chaque module implémente cette interface pour gérer sa persistence :
```cpp
class IModuleSave {
public:
virtual ~IModuleSave() = default;
// Sérialise l'état complet du module en JSON
virtual nlohmann::json serialize() = 0;
// Restaure l'état du module depuis JSON
// Retourne true si succès, false si erreur (→ load_pending)
virtual bool deserialize(const nlohmann::json& data) = 0;
// Version du module (auto-générée, voir module-versioning.md)
virtual std::string getVersion() const = 0;
};
```
#### Exemple Implémentation
```cpp
class TankModule : public IModule, public IModuleSave {
private:
std::vector<Tank> tanks;
public:
nlohmann::json serialize() override {
json data;
data["module_name"] = "tank";
data["module_version"] = getVersion();
data["save_timestamp"] = getCurrentTimestamp();
json tanksArray = json::array();
for (const auto& tank : tanks) {
tanksArray.push_back(tank.toJson());
}
data["data"]["tanks"] = tanksArray;
return data;
}
bool deserialize(const json& data) override {
try {
// Validation version
if (data["module_name"] != "tank") {
LOG_ERROR("Invalid module name in save file");
return false;
}
// Charge les tanks
tanks.clear();
for (const auto& tankJson : data["data"]["tanks"]) {
tanks.push_back(Tank::fromJson(tankJson));
}
return true;
}
catch (const std::exception& e) {
LOG_ERROR("Deserialization failed: {}", e.what());
return false;
}
}
std::string getVersion() const override {
return MODULE_VERSION; // Défini par CMake
}
};
```
### Workflow de Sauvegarde
#### Déclenchement
**En single-process** :
```cpp
saveSystem->saveGame("abc123");
```
**En multi-serveur** :
Le coordinateur broadcast une clé de save :
```cpp
// Coordinateur
coordinator->broadcastSaveCommand("abc123_1728226320");
// Chaque serveur reçoit et exécute
void Server::onSaveCommand(const std::string& saveKey) {
saveSystem->saveGame(saveKey);
}
```
#### Processus de Sauvegarde
```cpp
void SaveSystem::saveGame(const std::string& saveKey) {
auto startTime = std::chrono::steady_clock::now();
// 1. Créer structure de dossiers
std::string savePath = "saves/" + saveKey + "/";
fs::create_directories(savePath + "server_1/");
fs::create_directories(savePath + "metachunks/");
// 2. Sauvegarder chaque module
json metadata;
metadata["save_key"] = saveKey;
metadata["timestamp"] = getCurrentTimestamp();
metadata["game_version"] = GAME_VERSION;
for (auto& module : moduleSystem->getAllModules()) {
std::string moduleName = module->getName();
try {
// Sérialiser module
json moduleData = module->serialize();
// Écrire fichier
std::string modulePath = savePath + "server_1/" +
moduleName + ".json";
writeJsonFile(modulePath, moduleData);
// Mettre à jour metadata
metadata["modules"][moduleName] = {
{"version", module->getVersion()},
{"load_status", "ok"}
};
LOG_INFO("Module {} saved successfully", moduleName);
}
catch (const std::exception& e) {
LOG_ERROR("Failed to save module {}: {}", moduleName, e.what());
metadata["modules"][moduleName] = {
{"version", module->getVersion()},
{"load_status", "failed"}
};
}
}
// 3. Sauvegarder metachunks modifiés
int metachunkCount = 0;
for (auto& [coords, metachunk] : dirtyMetachunks) {
json metachunkData = metachunk->serialize();
std::string filename = std::to_string(coords.x) + "_" +
std::to_string(coords.y) + ".json";
writeJsonFile(savePath + "metachunks/" + filename, metachunkData);
metachunkCount++;
}
metadata["metachunks_count"] = metachunkCount;
// 4. Écrire metadata
writeJsonFile(savePath + "save_metadata.json", metadata);
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now() - startTime
);
LOG_INFO("Save completed in {}ms: {} modules, {} metachunks",
duration.count(), metadata["modules"].size(), metachunkCount);
}
```
### Workflow de Chargement
```cpp
void SaveSystem::loadGame(const std::string& saveKey) {
std::string savePath = "saves/" + saveKey + "/";
// 1. Charger metadata
json metadata = readJsonFile(savePath + "save_metadata.json");
// Validation game version (warning seulement en V1)
if (metadata["game_version"] != GAME_VERSION) {
LOG_WARN("Save created with different game version: {} vs {}",
metadata["game_version"], GAME_VERSION);
}
// 2. Charger world data (seed, params)
worldGenerator->setSeed(metadata["world_seed"]);
// 3. Charger chaque module
for (auto& module : moduleSystem->getAllModules()) {
std::string moduleName = module->getName();
std::string modulePath = savePath + "server_1/" +
moduleName + ".json";
if (!fs::exists(modulePath)) {
LOG_WARN("No save file for module {}, using defaults", moduleName);
continue;
}
try {
json moduleData = readJsonFile(modulePath);
// Vérification version module
std::string savedVersion = moduleData["module_version"];
std::string currentVersion = module->getVersion();
if (savedVersion != currentVersion) {
LOG_WARN("Module {} version mismatch: save={}, current={}",
moduleName, savedVersion, currentVersion);
}
// Désérialiser
bool success = module->deserialize(moduleData);
if (!success) {
LOG_ERROR("Module {} deserialization failed, marked as load_pending",
moduleName);
metadata["modules"][moduleName]["load_status"] = "load_pending";
}
else {
LOG_INFO("Module {} loaded successfully", moduleName);
}
}
catch (const std::exception& e) {
LOG_ERROR("Failed to load module {}: {}", moduleName, e.what());
metadata["modules"][moduleName]["load_status"] = "load_pending";
}
}
// 4. Metachunks chargés à la demande (streaming)
// Voir Chunk Streaming ci-dessous
LOG_INFO("Save loaded: {}", saveKey);
}
```
### Chunk Streaming
Les metachunks ne sont **pas tous chargés au démarrage** pour économiser la mémoire. Système de chargement à la demande :
```cpp
Chunk* ChunkManager::getChunk(int x, int y) {
ChunkCoords coords{x, y};
// 1. Vérifier si déjà en RAM
if (loadedChunks.contains(coords)) {
return loadedChunks[coords];
}
// 2. Calculer metachunk parent
MetachunkCoords metaCoords = getMetachunkCoords(x, y);
ChunkLocalCoords localCoords = getLocalCoords(x, y);
// 3. Charger metachunk si nécessaire
if (!loadedMetachunks.contains(metaCoords)) {
loadMetachunk(metaCoords);
}
// 4. Extraire chunk du metachunk
Metachunk* metachunk = loadedMetachunks[metaCoords];
Chunk* chunk = metachunk->getChunk(localCoords);
if (chunk) {
loadedChunks[coords] = chunk;
return chunk;
}
// 5. Si chunk n'existe pas dans save → génération procédurale
return generateNewChunk(coords);
}
void ChunkManager::loadMetachunk(MetachunkCoords coords) {
std::string path = "saves/" + currentSave + "/metachunks/" +
std::to_string(coords.x) + "_" +
std::to_string(coords.y) + ".json";
if (!fs::exists(path)) {
// Metachunk pas encore exploré/modifié
loadedMetachunks[coords] = new Metachunk(coords);
return;
}
// Charger et désérialiser metachunk
json metachunkData = readJsonFile(path);
Metachunk* metachunk = new Metachunk(coords);
metachunk->deserialize(metachunkData);
loadedMetachunks[coords] = metachunk;
LOG_DEBUG("Metachunk loaded: ({}, {})", coords.x, coords.y);
}
```
### Gestion des Erreurs : load_pending
Lorsqu'un module échoue à charger (JSON corrompu, incompatibilité version, etc.), il est marqué `load_pending` dans le metadata.
#### Workflow de Récupération
```cpp
// Au chargement, si erreur détectée
if (!module->deserialize(moduleData)) {
metadata["modules"][moduleName]["load_status"] = "load_pending";
// Sauvegarder metadata mis à jour
writeJsonFile(savePath + "save_metadata.json", metadata);
// Continuer le chargement des autres modules
}
```
#### Interface Utilisateur
```cpp
void UI::displayLoadPendingModules() {
for (const auto& [moduleName, info] : metadata["modules"].items()) {
if (info["load_status"] == "load_pending") {
std::cout << "[WARNING] Module '" << moduleName
<< "' failed to load. Check logs and fix JSON file.\n";
std::cout << " File: saves/" << saveKey << "/server_1/"
<< moduleName << ".json\n";
std::cout << " Version: " << info["version"] << "\n\n";
}
}
}
```
#### Retry Manuel
Après avoir corrigé le fichier JSON manuellement :
```cpp
void SaveSystem::retryLoadModule(const std::string& moduleName) {
auto module = moduleSystem->getModule(moduleName);
std::string modulePath = savePath + "server_1/" + moduleName + ".json";
try {
json moduleData = readJsonFile(modulePath);
bool success = module->deserialize(moduleData);
if (success) {
metadata["modules"][moduleName]["load_status"] = "ok";
writeJsonFile(savePath + "save_metadata.json", metadata);
LOG_INFO("Module {} successfully reloaded", moduleName);
}
}
catch (const std::exception& e) {
LOG_ERROR("Retry failed for module {}: {}", moduleName, e.what());
}
}
```
### Dirty Tracking
Seuls les chunks/metachunks **modifiés** sont sauvegardés pour optimiser la taille des saves.
```cpp
class ChunkManager {
private:
std::unordered_set<MetachunkCoords> dirtyMetachunks;
public:
void markChunkDirty(int chunkX, int chunkY) {
MetachunkCoords metaCoords = getMetachunkCoords(chunkX, chunkY);
dirtyMetachunks.insert(metaCoords);
}
void onBuildingPlaced(int x, int y) {
int chunkX = x / 64;
int chunkY = y / 64;
markChunkDirty(chunkX, chunkY);
}
void onResourceMined(int x, int y) {
int chunkX = x / 64;
int chunkY = y / 64;
markChunkDirty(chunkX, chunkY);
}
};
```
### Performance Targets V1
- **Autosave** : < 100ms pause perceptible (background thread recommandé)
- **Save manuelle** : < 500ms acceptable (avec feedback UI)
- **Load game** : < 3 secondes pour metadata + modules
- **Chunk streaming** : < 16ms par metachunk (1 frame @60fps)
- **Taille save** : ~10-50MB pour partie moyenne (dépend exploration)
### Limitations V1
Ces limitations seront résolues dans les versions futures :
1. **Pas de migration format** : Si le format JSON d'un module change, incompatibilité
2. **JSON verbeux** : Fichiers volumineux comparé à format binaire (acceptable pour debug)
3. **Pas de compression** : Taille disque non optimale
4. **Pas de checksums** : Corruption de données détectée tard (au parsing JSON)
5. **Concurrence limitée** : Save/load synchrones (pas de multi-threading)
## Évolution Future
### Version 2 : Compression et Migration
- **Compression LZ4/Zstd** : Réduction 60-80% taille fichiers
- **Format binaire optionnel** : MessagePack ou Protobuf pour données volumineuses
- **Migration automatique** : Système de conversion entre versions de format
- **Checksums** : Validation intégrité (CRC32, SHA256)
- **Async I/O** : Save/load en background threads
### Version 3 : Incremental Saves
- **Delta encoding** : Sauvegardes différentielles (snapshot + journal de changements)
- **Rollback temporel** : Restaurer état à timestamp spécifique
- **Compression inter-saves** : Déduplication entre sauvegardes
- **Hot-save** : Sauvegarde pendant le jeu sans pause
### Version 4 : Cloud et Multiplayer
- **Synchronisation cloud** : Steam Cloud, Google Drive, etc.
- **Save distribué** : Réplication multi-serveur automatique
- **Conflict resolution** : Merge intelligent pour multiplayer
- **Versioning git-like** : Branches, merge, rollback
## Références Croisées
- `module-versioning.md` : Système de versioning automatique des modules
- `architecture-modulaire.md` : Interface IModule, contraintes autonomie
- `systemes-techniques.md` : Architecture chunks multi-échelle
- `map-system.md` : Génération procédurale, resource patches
- `metriques-joueur.md` : Métriques à sauvegarder (3.1GB analytics)
## Exemples Pratiques
### Créer une Nouvelle Save
```cpp
// Single-process
saveSystem->saveGame("my_first_base");
// Multi-serveur
coordinator->broadcastSaveCommand("my_first_base_1728226320");
```
### Charger une Save Existante
```cpp
saveSystem->loadGame("my_first_base_1728226320");
```
### Éditer une Save Manuellement
```bash
# Ouvrir fichier module
nano saves/abc123_1728226320/server_1/economy.json
# Modifier prix du marché
# "iron_ore": 2.5 → "iron_ore": 5.0
# Recharger le module spécifique
saveSystem->retryLoadModule("economy");
```
### Lister les Saves Disponibles
```cpp
std::vector<SaveInfo> SaveSystem::listSaves() {
std::vector<SaveInfo> saves;
for (const auto& entry : fs::directory_iterator("saves/")) {
if (!entry.is_directory()) continue;
std::string metadataPath = entry.path().string() + "/save_metadata.json";
if (!fs::exists(metadataPath)) continue;
json metadata = readJsonFile(metadataPath);
saves.push_back({
.saveKey = metadata["save_key"],
.timestamp = metadata["timestamp"],
.gameVersion = metadata["game_version"],
.moduleCount = metadata["modules"].size(),
.metachunkCount = metadata["metachunks_count"]
});
}
// Trier par timestamp décroissant (plus récent en premier)
std::sort(saves.begin(), saves.end(), [](const auto& a, const auto& b) {
return a.timestamp > b.timestamp;
});
return saves;
}
```

164
gameData/Biomes/alpine.json Normal file
View File

@ -0,0 +1,164 @@
{
"biome_id": "alpine",
"display_name": "Alpine",
"description": "High-altitude mountain regions above treeline with extreme cold, intense UV radiation, and specialized cold-adapted vegetation",
"classification": {
"type": "normal_biome",
"priority": 15,
"token_requirements": {
"temperature": {"max": 0, "condition": "below_freezing"},
"elevation": {"min": 2000, "condition": "high_altitude"}
},
"climate_conditions": {
"extreme_cold": true,
"high_altitude_effects": true,
"intense_uv_radiation": true,
"short_growing_season": true,
"strong_winds": true
},
"elevation_range": {
"minimum": 2000,
"typical_range": [2500, 4000],
"formation_zone": "above_treeline"
},
"generation_notes": {
"formation_process": "Created by combination of cold temperatures (≤0°C) and high elevation (≥2000m)",
"geographic_distribution": "Mountain peaks and high plateaus above treeline",
"rarity": "Uncommon - limited to high mountain areas",
"minimum_area": 25,
"typical_area_range": [50, 300]
}
},
"vegetation": {
"primary": "alpine_specialists",
"secondary": ["alpine_grasses", "cushion_plants", "mountain_wildflowers", "dwarf_conifers"],
"characteristics": [
"extremely_low_growth_forms",
"cold_and_wind_adaptation",
"UV_radiation_protection",
"short_intense_growing_season",
"deep_root_systems"
],
"forest_compatibility": false,
"note": "Above treeline - only specialized alpine plants survive extreme conditions"
},
"environmental_properties": {
"altitude_extremes": 3.0,
"temperature_extremes": 2.8,
"uv_radiation": 2.9,
"wind_exposure": 2.7,
"oxygen_levels": 0.6,
"growing_season": 0.3,
"biodiversity": 0.8
},
"resource_modifiers": {
"mineral_extraction": 2.2,
"rare_earth_elements": 2.0,
"precious_metals": 1.8,
"glacial_water": 1.6,
"wind_energy": 2.1,
"solar_energy": 1.7,
"agriculture": 0.0,
"forestry": 0.0,
"tourism": 1.8,
"research_value": 2.4
},
"industrial_considerations": {
"construction_requirements": [
"extreme_altitude_engineering",
"wind_and_cold_resistance",
"oxygen_supplementation_systems",
"helicopter_or_cable_access"
],
"advantages": [
"rich_mineral_deposits",
"excellent_wind_and_solar_exposure",
"natural_isolation_and_security",
"fresh_water_sources_from_glaciers"
],
"challenges": [
"extreme_construction_costs",
"altitude_sickness_for_workers",
"limited_access_and_logistics",
"equipment_stress_from_conditions"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_fortress": 3.2,
"altitude_advantage": 2.8,
"difficult_approach": 3.0
},
"economic_factors": {
"mining_bonus": 2.2,
"construction_costs": 3.8,
"transportation_costs": 3.5,
"energy_generation_bonus": 1.9
},
"strategic_value": {
"territorial_control": 2.9,
"observation_posts": 3.0,
"resource_monopoly": 2.4
}
},
"altitude_effects": {
"oxygen_reduction": "significant_breathing_difficulty",
"atmospheric_pressure": "reduced_pressure_affects_equipment",
"temperature_lapse": "colder_with_increasing_elevation",
"uv_intensity": "increased_radiation_exposure"
},
"seasonal_extremes": {
"winter": {
"conditions": "extreme_cold_and_snow_cover",
"accessibility": "extremely_limited",
"survival": "life_threatening_conditions"
},
"summer": {
"conditions": "brief_growing_season",
"accessibility": "limited_weather_windows",
"activities": "peak_construction_and_research"
}
},
"wildlife": {
"adapted_species": [
"mountain_goats",
"alpine_birds",
"high_altitude_insects",
"cold_adapted_mammals"
],
"hunting_opportunities": 0.8,
"biodiversity": 0.8,
"conservation_value": "unique_high_altitude_adaptations"
},
"geological_features": {
"exposed_bedrock": "minimal_soil_cover",
"glacial_formations": "cirques_and_moraines",
"talus_slopes": "unstable_rock_debris",
"alpine_lakes": "pristine_high_altitude_water"
},
"mountaineering_aspects": {
"climbing_opportunities": 2.5,
"avalanche_risk": 2.8,
"weather_unpredictability": 3.0,
"rescue_difficulty": 3.2
},
"water_resources": {
"glacial_melt": "seasonal_water_source",
"alpine_springs": "pure_mountain_water",
"snow_accumulation": "winter_water_storage",
"watershed_importance": "supplies_lower_elevations"
},
}

View File

@ -0,0 +1,141 @@
{
"biome_id": "badlands",
"display_name": "Badlands",
"description": "Harsh, wind-scoured regions with minimal vegetation, created by persistent high winds and limited rainfall",
"classification": {
"type": "special_climate_zone",
"priority": 8,
"token_requirements": {
"highWind_tokens": {"min": 2, "condition": "above_storm_threshold"},
"rain_tokens": {"max": 300, "condition": "insufficient_moisture"}
},
"climate_conditions": {
"persistent_high_winds": true,
"limited_rainfall": true,
"extreme_temperature_variations": true,
"severe_erosion": true
},
"elevation_range": {
"minimum": 200,
"maximum": 1500,
"typical_range": [400, 1200],
"formation_zone": "wind_exposed_continental_interiors"
},
"generation_notes": {
"formation_process": "Created by highWind_tokens in areas with insufficient rain_tokens",
"geographic_distribution": "Interior continental areas with extreme wind exposure and low precipitation",
"rarity": "Rare - requires extreme combination of high wind and low rainfall",
"minimum_area": 75,
"typical_area_range": [150, 600]
}
},
"vegetation": {
"primary": "sparse_wind_resistant",
"secondary": ["hardy_cacti", "thorny_shrubs", "rock_lichens", "drought_adapted_grasses"],
"characteristics": [
"extremely_deep_roots",
"water_storage_adaptations",
"minimal_surface_area",
"protective_spines_or_waxy_coatings"
],
"forest_compatibility": false,
"note": "Only the most resilient plants can survive the combination of wind and drought"
},
"environmental_properties": {
"wind_energy": 2.2,
"erosion_rate": 2.8,
"water_scarcity": 2.5,
"temperature_extremes": 2.3,
"soil_quality": 0.3,
"biodiversity": 0.4
},
"resource_modifiers": {
"wind_energy": 2.2,
"mineral_exposure": 1.8,
"rare_earth_elements": 1.4,
"solar_energy": 1.9,
"geothermal_potential": 1.3,
"agriculture": 0.1,
"forestry": 0.0,
"water_resources": 0.2,
"industrial_suitability": 0.8,
"tourism": 0.6
},
"industrial_considerations": {
"construction_requirements": [
"extreme_wind_resistance",
"sandstorm_protection",
"water_importation_systems",
"temperature_resistant_materials"
],
"advantages": [
"exceptional_wind_energy_sites",
"exposed_mineral_deposits",
"excellent_solar_exposure",
"natural_isolation_for_sensitive_operations"
],
"challenges": [
"extreme_construction_conditions",
"constant_erosion_and_sandblasting",
"water_scarcity",
"equipment_maintenance_difficulties"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_fortress": 2.5,
"difficult_terrain": 2.8,
"visibility_reduction": 1.8
},
"economic_factors": {
"construction_costs": 2.8,
"maintenance_costs": 3.2,
"resource_extraction_bonus": 1.6,
"energy_generation_bonus": 2.0
},
"strategic_value": {
"natural_barrier": 2.7,
"hidden_base_potential": 2.2,
"resource_control": 1.9
}
},
"environmental_hazards": {
"sandstorms": {
"frequency": "frequent",
"intensity": "severe",
"effects": "equipment_damage_and_visibility_loss"
},
"flash_floods": {
"frequency": "rare_but_devastating",
"cause": "sudden_rainfall_on_hard_packed_earth",
"effects": "temporary_impassable_terrain"
},
"temperature_extremes": {
"daily_variation": "extreme",
"seasonal_variation": "severe",
"effects": "equipment_stress_and_human_discomfort"
}
},
"geological_features": {
"exposed_rock_formations": "dramatic_geological_history_visible",
"mineral_outcroppings": "rare_elements_accessible_at_surface",
"wind_carved_formations": "unique_landscape_features",
"erosion_patterns": "constantly_changing_topography"
},
"survival_considerations": {
"water_sources": "extremely_rare_and_precious",
"shelter_requirements": "protection_from_wind_and_temperature",
"navigation_challenges": "shifting_landmarks_and_poor_visibility",
"supply_lines": "critical_for_any_operations"
},
}

View File

@ -0,0 +1,215 @@
{
"biome_system_version": "1.0",
"description": "Comprehensive biome definitions for WindRegion-based climate simulation system",
"last_updated": "2024-09-29",
"classification_system": {
"special_climate_zones": {
"description": "Biomes created by extreme weather token accumulation",
"priority_range": [1, 5],
"evaluation_order": "first",
"override_normal_biomes": true
},
"normal_biomes": {
"description": "Standard biomes based on temperature and rainfall patterns",
"priority_range": [10, 20],
"evaluation_order": "second",
"fallback_system": true
}
},
"biome_definitions": {
"special_climate_zones": [
{
"biome_id": "wetlands",
"file": "wetlands.json",
"priority": 1,
"token_requirement": "flood_tokens > flood_threshold",
"description": "Marshes and swamps from recurring flooding patterns"
},
{
"biome_id": "coastal_plain",
"file": "coastal_plain.json",
"priority": 2,
"token_requirement": "rain_tokens >= 150 AND coastal_proximity <= 5",
"description": "Low-lying coastal areas with maritime influence and salt-tolerant vegetation"
},
{
"biome_id": "cliffs",
"file": "cliffs.json",
"priority": 3,
"token_requirement": "elevation >= 50 AND coastal_proximity <= 2",
"description": "Dramatic vertical coastal formations with extreme wind exposure"
},
{
"biome_id": "sandy_coast",
"file": "sandy_coast.json",
"priority": 4,
"token_requirement": "rain_tokens >= 100 AND coastal_proximity <= 3",
"description": "Expansive sandy beaches and dune systems with tourism potential"
},
{
"biome_id": "rocky_shore",
"file": "rocky_shore.json",
"priority": 5,
"token_requirement": "rain_tokens >= 120 AND coastal_proximity <= 2",
"description": "Rugged coastal areas with tidal pools and marine ecosystems"
},
{
"biome_id": "hurricane_zone",
"file": "hurricane_zone.json",
"priority": 6,
"token_requirement": "hurricane_tokens > 0",
"description": "Storm-resistant coastal vegetation in hurricane-prone areas"
},
{
"biome_id": "storm_prairie",
"file": "storm_prairie.json",
"priority": 7,
"token_requirement": "highWind_tokens > storm_threshold AND rain_tokens > 300",
"description": "Wind-resistant grasslands with adequate moisture"
},
{
"biome_id": "badlands",
"file": "badlands.json",
"priority": 8,
"token_requirement": "highWind_tokens > storm_threshold AND rain_tokens <= 300",
"description": "Sparse vegetation in extreme wind and drought conditions"
}
],
"normal_biomes": [
{
"biome_id": "tropical_rainforest",
"file": "tropical_rainforest.json",
"priority": 10,
"requirements": "rain_tokens >= 500 AND temperature >= 25",
"description": "Dense equatorial forests with maximum biodiversity"
},
{
"biome_id": "hot_desert",
"file": "hot_desert.json",
"priority": 11,
"requirements": "rain_tokens <= 50 AND temperature >= 20",
"description": "Arid regions with minimal vegetation and extreme heat"
},
{
"biome_id": "temperate_forest",
"file": "temperate_forest.json",
"priority": 12,
"requirements": "rain_tokens >= 300 AND temperature >= 15 AND temperature <= 25",
"description": "Seasonal forests in moderate climate zones"
},
{
"biome_id": "grassland",
"file": "grassland.json",
"priority": 13,
"requirements": "rain_tokens >= 200 AND temperature >= 10",
"description": "Temperate grasslands ideal for agriculture"
},
{
"biome_id": "tundra",
"file": "tundra.json",
"priority": 14,
"requirements": "temperature <= -10",
"description": "Arctic regions with permafrost and minimal vegetation"
},
{
"biome_id": "alpine",
"file": "alpine.json",
"priority": 15,
"requirements": "temperature <= 0 AND elevation >= 2000",
"description": "High-altitude mountain regions above treeline"
},
{
"biome_id": "cold_desert",
"file": "cold_desert.json",
"priority": 16,
"requirements": "rain_tokens <= 30 AND temperature <= 10",
"description": "High-altitude or high-latitude arid regions with cold temperatures"
},
{
"biome_id": "hills",
"file": "hills.json",
"priority": 17,
"requirements": "elevation >= 500 AND elevation <= 1500 AND rain_tokens >= 150",
"description": "Rolling hill country with diverse microclimates and mixed vegetation"
},
{
"biome_id": "rocky_plateau",
"file": "rocky_plateau.json",
"priority": 18,
"requirements": "elevation >= 800 AND rain_tokens >= 100 AND rain_tokens <= 400",
"description": "Elevated flat-topped terrain with exposed bedrock and hardy vegetation"
},
{
"biome_id": "scrubland",
"file": "scrubland.json",
"priority": 1,
"requirements": "fallback_biome",
"description": "Semi-arid transition zones with sparse vegetation - default fallback biome"
}
]
},
"token_thresholds": {
"climate_zone_tokens": {
"storm_threshold": 2.0,
"flood_threshold": 3.0,
"hurricane_requirement": "wind >= 2.5 AND rain >= 2.0"
},
"normal_biome_tokens": {
"rain_abundant": 500,
"rain_moderate": 300,
"rain_limited": 200,
"rain_minimal": 50,
"rain_very_minimal": 30
},
"temperature_ranges": {
"tropical": 25,
"temperate_warm": 20,
"temperate_cool": 15,
"cold": 10,
"freezing": 0,
"arctic": -10
},
"elevation_thresholds": {
"sea_level": 0,
"hills": 500,
"mountains": 1000,
"high_mountains": 2000,
"alpine_zone": 2500
}
},
"biome_selection_algorithm": {
"step_1": "Check special climate zone tokens (priority 1-5)",
"step_2": "If no special zones match, evaluate normal biomes (priority 10+)",
"step_3": "Use highest priority match, or fallback to 'scrubland' if none match",
"step_4": "Apply forest feature integration for forest-compatible biomes"
},
"integration_notes": {
"climate_system": "Biomes are generated from accumulated tokens from mobile WindRegions",
"congo_vs_sahara": "System designed to create tropical_rainforest (Congo) vs hot_desert (Sahara)",
"token_accumulation": "Permanent climate record from WindRegion movements over 300 cycles",
"special_zones": "Extreme weather creates unique biomes not found in traditional climate models",
"forest_features": "Existing forest features from geological phases influence final biome selection"
},
"validation_patterns": {
"congo_basin": {
"expected_biome": "tropical_rainforest",
"token_pattern": "rain_tokens > 500 from ITCZ convergence",
"latitude": "equatorial (45-55%)"
},
"sahara_desert": {
"expected_biome": "hot_desert",
"token_pattern": "rain_tokens < 50 due to no ITCZ influence",
"latitude": "subtropical (25-35%)"
},
"hurricane_coasts": {
"expected_biome": "hurricane_zone",
"token_pattern": "hurricane_tokens from coastal storm activity"
}
}
}

156
gameData/Biomes/cliffs.json Normal file
View File

@ -0,0 +1,156 @@
{
"biome_id": "cliffs",
"display_name": "Coastal Cliffs",
"description": "Dramatic vertical coastal formations with rugged terrain, seabird colonies and strategic defensive positions",
"classification": {
"type": "special_climate_zone",
"priority": 3,
"token_requirements": {
"elevation": {"min": 50, "condition": "elevated_coastal_terrain"},
"coastal_proximity": {"max": 2, "condition": "immediate_ocean_access"}
},
"climate_conditions": {
"extreme_wind_exposure": true,
"salt_spray_intense": true,
"maritime_influence": true,
"erosion_active": true
},
"elevation_range": {
"minimum": 50,
"maximum": 500,
"typical_range": [100, 300],
"formation_zone": "elevated_coastal_areas_with_vertical_drops"
},
"generation_notes": {
"formation_process": "Created by coastal elevation requirements with immediate ocean access",
"geographic_distribution": "Vertical coastal formations and sea cliffs",
"rarity": "Uncommon - specific geological coastal conditions",
"minimum_area": 50,
"typical_area_range": [100, 400]
}
},
"vegetation": {
"primary": "cliff_adapted_specialists",
"secondary": ["hardy_coastal_shrubs", "cliff_grasses", "maritime_lichens", "wind_sculpted_trees"],
"characteristics": [
"extreme_wind_tolerance",
"salt_spray_resistance",
"cliff_face_adaptation",
"shallow_root_systems",
"low_growth_forms"
],
"forest_compatibility": false,
"note": "Only the most specialized plants survive on exposed cliff faces"
},
"environmental_properties": {
"wind_exposure": 3.0,
"salt_spray": 2.8,
"erosion_activity": 2.6,
"soil_depth": 0.3,
"access_difficulty": 2.9,
"biodiversity": 1.2
},
"resource_modifiers": {
"stone_quarrying": 2.4,
"seabird_guano": 1.8,
"lighthouse_sites": 2.8,
"wind_energy": 2.6,
"defensive_positions": 3.0,
"agriculture": 0.1,
"forestry": 0.0,
"tourism": 2.1,
"industrial_suitability": 0.3,
"research_value": 1.9
},
"industrial_considerations": {
"construction_requirements": [
"extreme_wind_protection",
"cliff_face_stabilization",
"specialized_access_systems",
"salt_spray_corrosion_prevention"
],
"advantages": [
"unparalleled_defensive_position",
"lighthouse_and_navigation_sites",
"stone_quarrying_opportunities",
"extreme_wind_energy_potential"
],
"challenges": [
"extremely_difficult_access",
"continuous_erosion_threats",
"construction_cost_multipliers",
"limited_flat_building_space"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_fortress": 3.2,
"coastal_observation": 3.0,
"amphibious_invasion_prevention": 3.5
},
"economic_factors": {
"construction_costs": 4.2,
"maintenance_costs": 3.8,
"stone_extraction_bonus": 2.4,
"tourism_lighthouse_revenue": 2.1
},
"strategic_value": {
"naval_observation": 3.2,
"coastal_defense": 3.5,
"navigation_control": 2.8
}
},
"survival_challenges": {
"access_limitations": "rope_and_climbing_equipment_required",
"wind_safety": "extreme_weather_poses_constant_danger",
"erosion_instability": "cliff_faces_subject_to_sudden_collapse",
"isolation": "limited_escape_routes_during_emergencies"
},
"wildlife": {
"adapted_species": [
"seabird_colonies",
"cliff_nesting_birds",
"marine_mammals_below",
"specialized_cliff_insects"
],
"hunting_opportunities": 0.8,
"biodiversity": 1.2,
"conservation_value": "critical_seabird_nesting_habitat"
},
"geological_characteristics": {
"rock_type": "resistant_coastal_bedrock",
"stability": "variable_depending_on_rock_type_and_weather",
"erosion_patterns": "continuous_marine_erosion",
"cliff_height": "typically_50_to_300_meters"
},
"maritime_interaction": {
"wave_action": "intense_wave_impact_at_base",
"tidal_influence": "extreme_tidal_variation_exposure",
"storm_impact": "severe_weather_amplification",
"navigation_hazard": "dangerous_waters_for_small_vessels"
},
"research_opportunities": {
"coastal_erosion_studies": 2.4,
"seabird_ecology": 2.2,
"maritime_archaeology": 1.8,
"wind_pattern_analysis": 2.0
},
"historical_significance": {
"lighthouse_heritage": "traditional_navigation_aid_locations",
"defensive_castles": "medieval_coastal_fortification_sites",
"shipwreck_archaeology": "dangerous_waters_with_historical_wrecks",
"smuggling_history": "hidden_coves_and_secret_landing_sites"
}
}

View File

@ -0,0 +1,154 @@
{
"biome_id": "coastal_plain",
"display_name": "Coastal Plain",
"description": "Low-lying areas along coastlines with maritime influence, salt-tolerant vegetation and access to marine resources",
"classification": {
"type": "special_climate_zone",
"priority": 2,
"token_requirements": {
"rain_tokens": {"min": 150, "condition": "moderate_coastal_rainfall"},
"coastal_proximity": {"max": 5, "condition": "near_ocean"}
},
"climate_conditions": {
"maritime_influence": true,
"moderate_temperatures": true,
"salt_spray_exposure": true,
"sea_breeze_circulation": true
},
"elevation_range": {
"minimum": 0,
"maximum": 100,
"typical_range": [0, 50],
"formation_zone": "low_coastal_areas_with_marine_influence"
},
"generation_notes": {
"formation_process": "Created by moderate rainfall with coastal proximity requirements",
"geographic_distribution": "Coastal lowlands with maritime climate influence",
"rarity": "Common - major coastal settlement areas",
"minimum_area": 100,
"typical_area_range": [200, 800]
}
},
"vegetation": {
"primary": "salt_tolerant_coastal_plants",
"secondary": ["sea_grasses", "coastal_shrubs", "salt_marsh_plants", "dune_vegetation"],
"characteristics": [
"salt_tolerance",
"wind_resistance",
"sand_stabilization",
"maritime_adaptation",
"moderate_productivity"
],
"forest_compatibility": "coastal_adapted_trees_only",
"note": "Specialized vegetation adapted to salt spray and coastal conditions"
},
"environmental_properties": {
"salt_tolerance": 2.5,
"wind_exposure": 2.1,
"soil_salinity": 1.8,
"erosion_resistance": 1.4,
"marine_influence": 2.8,
"biodiversity": 1.6
},
"resource_modifiers": {
"fishing": 2.5,
"salt_production": 2.0,
"seaweed_harvest": 1.8,
"maritime_trade": 2.2,
"agriculture": 1.1,
"livestock_grazing": 1.3,
"wind_energy": 1.8,
"tourism": 1.9,
"forestry": 0.4,
"industrial_suitability": 1.2
},
"industrial_considerations": {
"construction_requirements": [
"salt_corrosion_protection",
"wind_resistant_design",
"foundation_drainage_systems",
"storm_surge_preparation"
],
"advantages": [
"excellent_port_access",
"maritime_trade_routes",
"flat_construction_terrain",
"consistent_wind_resources"
],
"challenges": [
"salt_corrosion_issues",
"storm_surge_vulnerability",
"soil_salinity_problems",
"seasonal_tourism_variations"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"amphibious_operations": 2.4,
"naval_support_access": 2.6
},
"economic_factors": {
"maritime_trade_bonus": 2.2,
"fishing_industry_income": 2.5,
"tourism_revenue": 1.9,
"salt_corrosion_costs": 1.8
},
"strategic_value": {
"port_development": 2.8,
"naval_base_suitability": 2.4,
"international_trade": 2.3
}
},
"seasonal_patterns": {
"storm_season": {
"conditions": "increased_wind_and_precipitation_from_ocean_storms",
"challenges": "storm_surge_flooding_and_infrastructure_damage",
"opportunities": "increased_fish_migration_and_wave_energy"
},
"calm_season": {
"conditions": "stable_weather_with_consistent_sea_breezes",
"opportunities": "optimal_fishing_and_maritime_trade_conditions",
"tourism": "peak_visitor_season_with_mild_coastal_climate"
}
},
"wildlife": {
"adapted_species": [
"seabirds",
"coastal_mammals",
"intertidal_species",
"migratory_shorebirds"
],
"hunting_opportunities": 1.4,
"biodiversity": 1.6,
"conservation_value": "important_bird_migration_corridors"
},
"soil_characteristics": {
"soil_type": "sandy_coastal_soils_with_salt_content",
"drainage": "excellent_natural_drainage",
"salinity": "moderate_to_high_salt_content",
"fertility": "moderate_with_marine_nutrient_input"
},
"maritime_features": {
"tidal_influence": "strong_tidal_variations",
"beach_access": "natural_beaches_and_sandy_shores",
"harbor_potential": "excellent_natural_harbors",
"storm_protection": "requires_artificial_breakwaters"
},
"land_use_potential": {
"port_development": "primary_economic_opportunity",
"fishing_industry": "major_coastal_resource_exploitation",
"tourism_development": "beach_and_maritime_recreation",
"salt_farming": "traditional_coastal_industry"
}
}

View File

@ -0,0 +1,184 @@
{
"biome_id": "cold_desert",
"display_name": "Cold Desert",
"description": "High-altitude or high-latitude desert regions with cold temperatures and minimal precipitation, featuring specialized cold-adapted arid vegetation",
"classification": {
"type": "normal_biome",
"priority": 16,
"token_requirements": {
"rain_tokens": {"max": 30, "condition": "very_low_precipitation"},
"temperature": {"max": 10, "condition": "cold_climate"}
},
"climate_conditions": {
"cold_temperatures": true,
"extreme_aridity": true,
"high_altitude_or_latitude": true,
"strong_temperature_variations": true,
"low_humidity": true
},
"elevation_range": {
"minimum": 500,
"maximum": 3000,
"typical_range": [1000, 2500],
"formation_zone": "high_altitude_plateaus_and_polar_deserts"
},
"generation_notes": {
"formation_process": "Created by very low rain_tokens (≤30) combined with cold temperatures (≤10°C)",
"geographic_distribution": "High-altitude plateaus, continental interiors with cold climates, polar deserts",
"rarity": "Uncommon - requires specific combination of cold and extreme aridity",
"minimum_area": 100,
"typical_area_range": [250, 1000]
}
},
"vegetation": {
"primary": "cold_adapted_desert_plants",
"secondary": ["hardy_shrubs", "drought_cold_tolerant_grasses", "alpine_succulents", "cushion_plants"],
"characteristics": [
"dual_stress_adaptation",
"cold_and_drought_tolerance",
"compact_growth_forms",
"deep_root_systems",
"protective_surface_structures"
],
"forest_compatibility": false,
"note": "Must survive both extreme cold and water scarcity simultaneously"
},
"environmental_properties": {
"water_scarcity": 2.9,
"cold_extremes": 2.4,
"temperature_variation": 2.7,
"wind_exposure": 2.3,
"soil_aridity": 2.8,
"growing_season": 0.4,
"biodiversity": 0.4
},
"resource_modifiers": {
"mineral_deposits": 1.9,
"rare_earth_elements": 1.6,
"wind_energy": 1.8,
"solar_energy": 1.4,
"geothermal_potential": 1.5,
"salt_deposits": 1.7,
"agriculture": 0.05,
"forestry": 0.0,
"water_resources": 0.15,
"industrial_suitability": 0.6,
"research_value": 1.8
},
"industrial_considerations": {
"construction_requirements": [
"cold_weather_protection",
"water_conservation_systems",
"wind_and_dust_protection",
"specialized_heating_systems"
],
"advantages": [
"mineral_resource_access",
"low_environmental_impact_restrictions",
"natural_preservation_conditions",
"strategic_isolation"
],
"challenges": [
"dual_environmental_stress",
"water_importation_requirements",
"extreme_temperature_management",
"limited_growing_season"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_barrier": 2.6,
"difficult_logistics": 2.8,
"environmental_protection": 2.4
},
"economic_factors": {
"construction_costs": 2.6,
"heating_costs": 2.8,
"water_importation_costs": 3.2,
"mineral_extraction_bonus": 1.7
},
"strategic_value": {
"resource_control": 2.0,
"territorial_buffer": 2.5,
"research_isolation": 2.2
}
},
"survival_challenges": {
"water_procurement": {
"sources": "snow_melt_and_rare_springs",
"conservation": "critical_water_management",
"quality": "often_high_mineral_content"
},
"temperature_management": {
"heating_requirements": "essential_for_survival",
"insulation_needs": "extreme_cold_protection",
"equipment_protection": "cold_weather_maintenance"
},
"food_procurement": {
"agriculture": "nearly_impossible",
"hunting": "limited_wildlife",
"imports": "critical_supply_dependence"
}
},
"wildlife": {
"adapted_species": [
"cold_desert_lizards",
"hardy_small_mammals",
"migratory_birds",
"specialized_arthropods"
],
"hunting_opportunities": 0.4,
"biodiversity": 0.4,
"conservation_value": "unique_dual_stress_adaptations"
},
"seasonal_patterns": {
"winter": {
"conditions": "extreme_cold_with_minimal_precipitation",
"challenges": "frozen_water_sources_and_heating_demands",
"wildlife": "minimal_activity_and_hibernation"
},
"summer": {
"conditions": "brief_warming_period_with_slight_moisture",
"opportunities": "limited_growing_season_and_construction",
"wildlife": "peak_activity_and_reproduction"
}
},
"geological_characteristics": {
"soil_type": "thin_rocky_soils_with_poor_water_retention",
"rock_formations": "exposed_bedrock_and_scree_slopes",
"mineral_exposure": "weathering_exposes_valuable_deposits",
"erosion_patterns": "wind_and_freeze_thaw_erosion"
},
"water_sources": {
"seasonal_snowmelt": "primary_annual_water_input",
"underground_springs": "rare_but_critical_resources",
"atmospheric_moisture": "dew_and_frost_collection",
"imported_water": "essential_for_human_activities"
},
"research_opportunities": {
"extreme_environment_biology": 2.0,
"cold_arid_adaptations": 1.9,
"climate_change_indicators": 1.8,
"mineral_formation_processes": 1.7
},
"land_use_potential": {
"mining_operations": "primary_economic_activity",
"research_stations": "isolated_study_locations",
"strategic_installations": "remote_monitoring_posts",
"renewable_energy": "wind_and_limited_solar"
},
}

View File

@ -0,0 +1,153 @@
{
"biome_id": "grassland",
"display_name": "Grassland",
"description": "Temperate grasslands with moderate rainfall and temperature, ideal for agriculture and grazing, featuring vast open plains",
"classification": {
"type": "normal_biome",
"priority": 13,
"token_requirements": {
"rain_tokens": {"min": 200, "condition": "moderate_rainfall"},
"temperature": {"min": 10, "condition": "temperate_climate"}
},
"climate_conditions": {
"moderate_temperatures": true,
"adequate_rainfall": true,
"seasonal_variation": true,
"insufficient_for_forest_growth": true
},
"elevation_range": {
"minimum": 0,
"maximum": 800,
"typical_range": [100, 600],
"formation_zone": "continental_interiors_with_moderate_precipitation"
},
"generation_notes": {
"formation_process": "Created by moderate rain_tokens (200+) with temperate temperatures but insufficient for forests",
"geographic_distribution": "Continental interiors with moderate precipitation",
"rarity": "Common - major agricultural regions worldwide",
"minimum_area": 200,
"typical_area_range": [500, 2500]
}
},
"vegetation": {
"primary": "perennial_grasses",
"secondary": ["prairie_grasses", "wildflowers", "scattered_shrubs"],
"characteristics": [
"deep_root_systems",
"drought_tolerance",
"fire_adaptation",
"seasonal_growth_cycles",
"high_productivity"
],
"forest_compatibility": "scattered_trees_only",
"note": "Natural grassland ecosystem with high agricultural potential"
},
"environmental_properties": {
"agricultural_potential": 2.5,
"soil_quality": 2.2,
"carbon_storage": 1.8,
"erosion_resistance": 1.6,
"fire_resilience": 2.0,
"biodiversity": 1.4
},
"resource_modifiers": {
"agriculture": 1.8,
"livestock_grazing": 2.2,
"grain_production": 2.0,
"hay_and_forage": 2.5,
"wild_game": 1.6,
"wind_energy": 1.4,
"forestry": 0.2,
"industrial_suitability": 0.9,
"recreation": 1.3
},
"industrial_considerations": {
"construction_requirements": [
"minimal_ground_preparation",
"wind_exposure_considerations",
"seasonal_weather_protection"
],
"advantages": [
"excellent_agricultural_land",
"easy_construction_conditions",
"flat_terrain_for_development",
"good_transportation_routes"
],
"challenges": [
"limited_natural_windbreaks",
"fire_risk_management",
"soil_conservation_needs",
"seasonal_weather_extremes"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"open_terrain_visibility": 2.2,
"cavalry_advantage": 2.0
},
"economic_factors": {
"agricultural_productivity": 2.2,
"low_development_costs": 1.5,
"food_security_bonus": 2.0
},
"strategic_value": {
"food_production_hub": 2.5,
"population_support": 2.2,
"transportation_network": 1.8
}
},
"agricultural_systems": {
"crop_rotation": "sustainable_soil_management",
"livestock_integration": "mixed_farming_systems",
"irrigation_potential": "moderate_water_requirements",
"mechanization": "ideal_for_large_scale_farming"
},
"wildlife": {
"grassland_species": [
"prairie_dogs",
"ground_nesting_birds",
"grazing_mammals",
"raptors"
],
"hunting_opportunities": 1.6,
"biodiversity": 1.4,
"migration_routes": "important_corridors_for_many_species"
},
"seasonal_patterns": {
"growing_season": "spring_through_early_autumn",
"dormancy_period": "winter_with_possible_snow_cover",
"fire_season": "late_summer_natural_fire_cycles",
"grazing_patterns": "seasonal_animal_movement"
},
"soil_characteristics": {
"soil_type": "deep_fertile_prairie_soils",
"organic_matter": "high_due_to_grass_root_systems",
"drainage": "generally_well_drained",
"erosion_risk": "moderate_without_ground_cover"
},
"fire_ecology": {
"natural_fire_frequency": "every_3_10_years",
"fire_benefits": "removes_woody_plants_and_stimulates_grass_growth",
"fire_management": "controlled_burns_for_ecosystem_health",
"fire_prevention": "firebreaks_and_early_detection"
},
"land_use_patterns": {
"agriculture": "crop_production_and_livestock",
"urban_development": "preferred_sites_for_cities",
"transportation": "ideal_for_roads_and_railways",
"energy_production": "wind_farms_and_solar_installations"
},
}

180
gameData/Biomes/hills.json Normal file
View File

@ -0,0 +1,180 @@
{
"biome_id": "hills",
"display_name": "Hills",
"description": "Rolling hill country with moderate elevation, diverse microclimates, and mixed vegetation creating natural terraced landscapes",
"classification": {
"type": "normal_biome",
"priority": 17,
"token_requirements": {
"elevation": {"min": 500, "max": 1500, "condition": "moderate_altitude"},
"rain_tokens": {"min": 150, "condition": "adequate_moisture"}
},
"climate_conditions": {
"moderate_elevation_effects": true,
"varied_microclimates": true,
"good_drainage": true,
"wind_exposure_variation": true
},
"elevation_range": {
"minimum": 500,
"maximum": 1500,
"typical_range": [600, 1200],
"formation_zone": "transition_between_plains_and_mountains"
},
"generation_notes": {
"formation_process": "Created by moderate elevation (500-1500m) with adequate moisture (≥150 rain_tokens)",
"geographic_distribution": "Transition zones between plains and mountains",
"rarity": "Common - natural intermediate terrain",
"minimum_area": 100,
"typical_area_range": [200, 800]
}
},
"vegetation": {
"primary": "mixed_elevation_adapted",
"secondary": ["hill_grasslands", "scattered_woodlands", "shrublands", "valley_forests"],
"characteristics": [
"elevation_gradient_adaptation",
"diverse_microhabitats",
"slope_aspect_variation",
"mixed_vegetation_types",
"erosion_resistance"
],
"forest_compatibility": "partial_woodlands",
"note": "Diverse vegetation zones based on slope orientation and elevation"
},
"environmental_properties": {
"topographic_diversity": 2.5,
"drainage_quality": 2.2,
"microclimate_variation": 2.3,
"erosion_control": 1.8,
"scenic_value": 2.4,
"biodiversity": 1.6
},
"resource_modifiers": {
"mixed_agriculture": 1.4,
"livestock_grazing": 1.8,
"forestry": 1.2,
"stone_quarrying": 1.6,
"wind_energy": 1.3,
"water_sources": 1.5,
"tourism": 1.9,
"industrial_suitability": 1.1,
"transportation": 0.8,
"recreation": 2.1
},
"industrial_considerations": {
"construction_requirements": [
"slope_stabilization",
"terraced_construction",
"drainage_management",
"access_road_engineering"
],
"advantages": [
"natural_defensive_positions",
"diverse_resource_access",
"good_water_drainage",
"scenic_development_potential"
],
"challenges": [
"uneven_terrain_costs",
"erosion_management",
"transportation_complexity",
"varying_soil_conditions"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"elevated_positions": 1.8,
"natural_fortification": 1.6,
"observation_advantage": 2.0
},
"economic_factors": {
"construction_costs": 1.4,
"agricultural_diversity": 1.6,
"tourism_income": 1.8,
"transportation_costs": 1.3
},
"strategic_value": {
"tactical_advantage": 1.9,
"resource_diversity": 1.7,
"settlement_desirability": 1.8
}
},
"topographic_features": {
"rolling_terrain": "gentle_to_moderate_slopes",
"valley_systems": "natural_drainage_and_shelter",
"ridge_lines": "elevated_transportation_routes",
"natural_terraces": "stepped_landscape_features"
},
"agricultural_potential": {
"terraced_farming": "slope_agriculture_adaptation",
"mixed_land_use": "crops_pasture_and_woodland",
"orchard_suitability": "fruit_trees_on_slopes",
"vineyard_potential": "wine_production_terrain"
},
"water_systems": {
"spring_sources": "hillside_water_emergence",
"creek_systems": "valley_drainage_networks",
"pond_potential": "natural_water_collection",
"watershed_management": "erosion_and_runoff_control"
},
"wildlife": {
"habitat_diversity": [
"valley_woodland_species",
"grassland_animals",
"edge_habitat_specialists",
"slope_adapted_plants"
],
"hunting_opportunities": 1.6,
"biodiversity": 1.6,
"wildlife_corridors": "natural_movement_pathways"
},
"settlement_patterns": {
"hilltop_settlements": "defensive_and_scenic_locations",
"valley_villages": "water_access_and_shelter",
"slope_farming": "terraced_agricultural_communities",
"ridge_transportation": "natural_road_corridors"
},
"seasonal_characteristics": {
"spring": "varied_blooming_times_by_elevation",
"summer": "diverse_microclimates_and_activities",
"autumn": "spectacular_color_displays",
"winter": "snow_variation_by_elevation_and_aspect"
},
"recreational_opportunities": {
"hiking_trails": 2.2,
"scenic_driving": 2.0,
"mountain_biking": 1.9,
"photography": 2.1,
"camping": 1.7,
"nature_education": 1.8
},
"microclimate_zones": {
"south_facing_slopes": "warmer_and_drier_conditions",
"north_facing_slopes": "cooler_and_moister_conditions",
"valley_bottoms": "protected_and_humid_microclimates",
"ridge_tops": "exposed_and_windy_conditions"
},
"soil_characteristics": {
"slope_variation": "thinner_soils_on_slopes_deeper_in_valleys",
"drainage_quality": "generally_good_with_slope_advantage",
"erosion_potential": "managed_through_vegetation_cover",
"fertility_variation": "nutrient_accumulation_in_lower_areas"
},
}

View File

@ -0,0 +1,165 @@
{
"biome_id": "hot_desert",
"display_name": "Hot Desert",
"description": "Arid regions with high temperatures and minimal rainfall, featuring specialized drought-adapted vegetation and extreme environmental conditions",
"classification": {
"type": "normal_biome",
"priority": 11,
"token_requirements": {
"rain_tokens": {"max": 50, "condition": "minimal_rainfall"},
"temperature": {"min": 20, "condition": "hot_climate"}
},
"climate_conditions": {
"extreme_aridity": true,
"high_daytime_temperatures": true,
"cold_nighttime_temperatures": true,
"irregular_precipitation": true
},
"elevation_range": {
"minimum": 0,
"maximum": 1200,
"typical_range": [200, 800],
"formation_zone": "continental_interiors_and_subtropical_zones"
},
"generation_notes": {
"formation_process": "Created by minimal rain_tokens (≤50) combined with hot temperatures (≥20°C)",
"geographic_distribution": "Continental interiors and subtropical high-pressure zones without ITCZ influence",
"rarity": "Common - represents Sahara success pattern",
"minimum_area": 300,
"typical_area_range": [800, 3000],
"formation_priority": "High - represents successful Congo vs Sahara differentiation"
}
},
"vegetation": {
"primary": "drought_adapted_specialists",
"secondary": ["cacti", "succulents", "drought_deciduous_shrubs", "ephemeral_annuals"],
"characteristics": [
"water_storage_organs",
"reduced_leaf_surface_area",
"waxy_protective_coatings",
"deep_tap_roots",
"CAM_photosynthesis"
],
"forest_compatibility": false,
"note": "Only highly specialized plants can survive extreme water scarcity"
},
"environmental_properties": {
"water_scarcity": 2.8,
"solar_exposure": 3.0,
"temperature_extremes": 2.5,
"wind_exposure": 1.8,
"soil_aridity": 2.9,
"biodiversity": 0.3
},
"resource_modifiers": {
"solar_energy": 2.5,
"mineral_deposits": 1.8,
"rare_earth_elements": 1.5,
"salt_deposits": 2.0,
"geothermal_energy": 1.4,
"agriculture": 0.1,
"forestry": 0.0,
"water_resources": 0.1,
"industrial_suitability": 1.2,
"tourism": 1.0
},
"industrial_considerations": {
"construction_requirements": [
"extreme_heat_resistance",
"sand_and_dust_protection",
"water_conservation_systems",
"thermal_insulation"
],
"advantages": [
"excellent_solar_energy_potential",
"exposed_mineral_resources",
"vast_open_spaces",
"minimal_environmental_constraints"
],
"challenges": [
"extreme_water_scarcity",
"temperature_stress_on_equipment",
"sandstorm_damage",
"worker_health_and_safety"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_barrier": 2.0,
"difficult_logistics": 2.5,
"heat_exhaustion_advantage": 2.2
},
"economic_factors": {
"solar_farm_efficiency": 2.8,
"mineral_extraction_bonus": 1.7,
"water_importation_costs": 3.0,
"construction_heat_costs": 1.8
},
"strategic_value": {
"renewable_energy_hub": 2.7,
"resource_control": 1.9,
"natural_isolation": 2.3
}
},
"survival_adaptations": {
"water_sources": [
"rare_oases",
"underground_aquifers",
"seasonal_water_holes",
"dew_collection"
],
"temperature_management": [
"underground_shelter",
"thermal_mass_utilization",
"reflective_surfaces",
"shade_structures"
],
"navigation_challenges": [
"shifting_sand_dunes",
"heat_mirages",
"sandstorm_visibility",
"landmark_scarcity"
]
},
"wildlife": {
"adapted_species": [
"desert_reptiles",
"nocturnal_mammals",
"water_conserving_birds",
"specialized_insects"
],
"hunting_opportunities": 0.3,
"biodiversity": 0.3,
"conservation_value": "specialized_endemic_species"
},
"climatic_patterns": {
"daily_temperature_cycle": "extreme_day_night_variation",
"seasonal_patterns": "hot_dry_vs_less_hot_dry",
"precipitation_events": "rare_but_intense_flash_floods",
"wind_patterns": "dust_storms_and_thermal_circulation"
},
"geological_features": {
"sand_dunes": "shifting_landscape_features",
"rock_outcroppings": "rare_shelter_and_navigation_points",
"salt_flats": "remnants_of_ancient_lakes",
"mineral_exposures": "valuable_surface_deposits"
},
"water_economy": {
"conservation_priority": "critical",
"sources": "extremely_limited_and_precious",
"management": "every_drop_must_be_utilized",
"technology": "advanced_conservation_required"
},
}

View File

@ -0,0 +1,100 @@
{
"biome_id": "hurricane_zone",
"display_name": "Hurricane Zone",
"description": "Coastal regions subjected to frequent hurricane activity, featuring storm-resistant vegetation and specialized ecosystems",
"classification": {
"type": "special_climate_zone",
"priority": 6,
"token_requirements": {
"hurricane_tokens": {"min": 1, "condition": "greater_than_zero"}
},
"climate_conditions": {
"high_wind_exposure": true,
"frequent_storm_activity": true,
"salt_spray_tolerance_required": true,
"coastal_proximity": true
},
"elevation_range": {
"minimum": 0,
"maximum": 100,
"typical_range": [0, 50],
"formation_zone": "coastal_areas_near_sea_level"
},
"generation_notes": {
"formation_process": "Created by hurricane_tokens from WindRegions with high wind_strength + high wetness",
"geographic_distribution": "Coastal areas in hurricane-prone latitudes",
"rarity": "Moderate - found along storm-prone coastlines",
"minimum_area": 50,
"typical_area_range": [100, 500]
}
},
"vegetation": {
"primary": "storm_resistant_palms",
"secondary": ["coastal_grasses", "mangrove_species", "salt_tolerant_shrubs"],
"characteristics": [
"deep_root_systems",
"flexible_trunks",
"salt_tolerance",
"rapid_recovery_after_storms"
],
"forest_compatibility": false,
"note": "Traditional forests cannot survive the frequent high-wind disturbances"
},
"environmental_properties": {
"storm_resistance": 3.0,
"coastal_access": 2.0,
"wind_energy_potential": 2.5,
"biodiversity": 1.2,
"soil_stability": 0.6,
"water_drainage": 1.8
},
"resource_modifiers": {
"wind_energy": 2.5,
"seafood": 1.8,
"storm_resistant_materials": 2.0,
"agriculture": 0.4,
"forestry": 0.1,
"industrial_suitability": 0.6,
"tourism_potential": 1.4
},
"industrial_considerations": {
"construction_requirements": [
"hurricane_resistant_buildings",
"elevated_foundations",
"storm_surge_protection"
],
"advantages": [
"excellent_wind_energy_sites",
"natural_harbors_from_storm_carving",
"unique_marine_resources"
],
"challenges": [
"seasonal_evacuation_needs",
"infrastructure_maintenance_costs",
"limited_agricultural_productivity"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"coastal_fortification_bonus": 1.5,
"storm_shelter_effectiveness": 2.0
},
"economic_factors": {
"insurance_costs": 2.5,
"reconstruction_frequency": "seasonal",
"specialized_industry_bonus": 1.3
},
"strategic_value": {
"naval_base_suitability": 1.8,
"early_warning_systems": 2.0,
"hurricane_tracking_advantage": true
}
},
}

View File

@ -0,0 +1,194 @@
{
"biome_id": "rocky_plateau",
"display_name": "Rocky Plateau",
"description": "Elevated flat-topped landforms with exposed bedrock, thin soils, and hardy vegetation adapted to wind exposure and rocky terrain",
"classification": {
"type": "normal_biome",
"priority": 18,
"token_requirements": {
"elevation": {"min": 800, "condition": "elevated_terrain"},
"rain_tokens": {"min": 100, "max": 400, "condition": "moderate_to_low_moisture"}
},
"climate_conditions": {
"elevated_exposure": true,
"strong_winds": true,
"thin_soils": true,
"temperature_extremes": true,
"good_drainage": true
},
"elevation_range": {
"minimum": 800,
"typical_range": [1000, 2500],
"formation_zone": "elevated_flat_topped_terrain"
},
"generation_notes": {
"formation_process": "Created by elevated terrain (≥800m) with moderate to low moisture (100-400 rain_tokens)",
"geographic_distribution": "Elevated areas with resistant geology and moderate precipitation",
"rarity": "Uncommon - requires specific geological and climatic conditions",
"minimum_area": 75,
"typical_area_range": [150, 600]
}
},
"vegetation": {
"primary": "rocky_terrain_specialists",
"secondary": ["plateau_grasses", "hardy_shrubs", "rock_garden_plants", "windswept_trees"],
"characteristics": [
"rock_crevice_adaptation",
"wind_resistance",
"drought_tolerance",
"shallow_root_systems",
"hardy_constitution"
],
"forest_compatibility": "stunted_woodlands_only",
"note": "Vegetation limited by thin soils and wind exposure"
},
"environmental_properties": {
"rock_exposure": 2.8,
"wind_exposure": 2.6,
"soil_depth": 0.4,
"drainage_quality": 2.9,
"temperature_variation": 2.3,
"erosion_resistance": 2.5,
"biodiversity": 0.9
},
"resource_modifiers": {
"stone_quarrying": 2.5,
"mineral_extraction": 2.2,
"wind_energy": 2.3,
"solar_energy": 1.9,
"water_collection": 1.4,
"grazing_land": 0.6,
"agriculture": 0.3,
"forestry": 0.4,
"tourism": 1.7,
"industrial_suitability": 1.3
},
"industrial_considerations": {
"construction_requirements": [
"rock_drilling_and_blasting",
"wind_resistant_structures",
"water_importation_systems",
"specialized_foundation_work"
],
"advantages": [
"excellent_building_stone_access",
"stable_geological_foundation",
"commanding_views_and_positions",
"wind_and_solar_energy_potential"
],
"challenges": [
"limited_water_sources",
"difficult_excavation",
"extreme_wind_exposure",
"thin_soil_for_agriculture"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_fortress": 2.8,
"observation_advantage": 2.9,
"difficult_approach": 2.4
},
"economic_factors": {
"quarrying_income": 2.4,
"construction_costs": 2.2,
"water_importation_costs": 2.6,
"energy_generation_bonus": 2.1
},
"strategic_value": {
"territorial_control": 2.7,
"communication_advantage": 2.8,
"resource_monopoly": 2.3
}
},
"geological_features": {
"bedrock_exposure": "extensive_rock_outcroppings",
"flat_topped_terrain": "erosion_resistant_caprock",
"cliff_edges": "dramatic_escarpments",
"joint_and_fracture_systems": "natural_stone_quarrying_sites"
},
"water_systems": {
"surface_runoff": "rapid_drainage_with_minimal_retention",
"rock_pools": "temporary_water_collection_in_depressions",
"spring_emergence": "water_sources_at_plateau_edges",
"cistern_potential": "artificial_water_storage_in_rock"
},
"wildlife": {
"adapted_species": [
"cliff_dwelling_birds",
"rock_crevice_mammals",
"hardy_reptiles",
"wind_dispersed_plants"
],
"hunting_opportunities": 0.8,
"biodiversity": 0.9,
"conservation_value": "specialized_rocky_habitat_species"
},
"wind_patterns": {
"exposure_effects": "constant_wind_stress_on_vegetation",
"wind_channeling": "increased_velocity_over_flat_surfaces",
"turbulence_zones": "complex_airflow_around_edges",
"energy_potential": "excellent_wind_farm_locations"
},
"agricultural_limitations": {
"soil_depth": "insufficient_for_most_crops",
"water_scarcity": "irrigation_challenges",
"wind_damage": "crop_protection_difficulties",
"specialized_techniques": "rock_garden_and_terrace_farming"
},
"construction_opportunities": {
"castle_and_fort_sites": "natural_defensive_positions",
"observation_towers": "communication_and_surveillance",
"wind_farms": "optimal_renewable_energy_sites",
"quarry_operations": "building_stone_extraction"
},
"seasonal_characteristics": {
"winter": "extreme_wind_chill_and_ice_formation",
"spring": "brief_flowering_in_protected_crevices",
"summer": "intense_heat_reflection_from_rock",
"autumn": "dramatic_temperature_swings"
},
"erosion_patterns": {
"differential_weathering": "harder_rocks_form_resistant_caps",
"joint_widening": "freeze_thaw_processes",
"surface_scaling": "temperature_expansion_effects",
"chemical_weathering": "slow_soil_formation_processes"
},
"recreational_uses": {
"rock_climbing": 2.2,
"hiking_and_exploration": 1.8,
"photography": 2.0,
"astronomical_observation": 2.3,
"paragliding_launch": 2.1
},
"microhabitats": {
"rock_crevices": "protected_growing_spaces",
"lee_slopes": "wind_protection_zones",
"water_collection_areas": "temporary_moist_zones",
"exposed_surfaces": "extreme_environment_specialists"
},
"formation_requirements": {
"geological_stability": "resistant_caprock_preservation",
"elevation_maintenance": "ongoing_uplift_or_erosion_resistance",
"climate_balance": "enough_moisture_for_some_vegetation",
"time_scale": "long_term_landscape_evolution"
},
}

View File

@ -0,0 +1,110 @@
{
"biome_id": "rocky_shore",
"display_name": "Rocky Shore",
"description": "Rugged coastal areas with exposed bedrock, tidal pools and rich marine ecosystems",
"classification": {
"type": "special_climate_zone",
"priority": 5,
"token_requirements": {
"rain_tokens": {"min": 120, "condition": "moderate_coastal_precipitation"},
"coastal_proximity": {"max": 2, "condition": "immediate_ocean_access"},
"rock_exposure": {"min": 1, "condition": "bedrock_substrate"}
},
"climate_conditions": {
"intense_salt_spray": true,
"tidal_variation_extreme": true,
"wave_action_strong": true,
"maritime_influence": true
},
"elevation_range": {
"minimum": 0,
"maximum": 25,
"typical_range": [0, 10],
"formation_zone": "low_rocky_coastal_areas_with_tidal_exposure"
},
"generation_notes": {
"formation_process": "Created by moderate rainfall with rocky coastal proximity",
"geographic_distribution": "Rocky coastlines with exposed bedrock and tidal zones",
"rarity": "Common - many temperate and cold coastlines",
"minimum_area": 60,
"typical_area_range": [120, 400]
}
},
"vegetation": {
"primary": "rock_crevice_specialists",
"secondary": ["maritime_lichens", "salt_marsh_edges", "cliff_grasses", "seaweed_beds"],
"characteristics": [
"extreme_salt_tolerance",
"tidal_submersion_resistance",
"rock_crevice_growth",
"wave_impact_tolerance",
"minimal_soil_requirements"
],
"forest_compatibility": false,
"note": "Highly specialized flora adapted to harsh intertidal conditions"
},
"environmental_properties": {
"salt_exposure": 3.0,
"wave_impact": 2.8,
"tidal_variation": 2.9,
"rock_weathering": 2.2,
"marine_productivity": 2.6,
"biodiversity": 1.8
},
"resource_modifiers": {
"marine_biology": 2.4,
"shellfish_harvesting": 2.6,
"seaweed_collection": 2.2,
"tidal_energy": 2.0,
"stone_quarrying": 1.8,
"research_value": 2.2,
"fishing": 2.0,
"tourism": 1.6,
"agriculture": 0.1,
"forestry": 0.0,
"industrial_suitability": 0.5
},
"industrial_considerations": {
"construction_requirements": [
"extreme_salt_corrosion_protection",
"wave_impact_resistant_design",
"tidal_flood_management",
"rock_anchor_foundation_systems"
],
"advantages": [
"solid_bedrock_foundations",
"natural_wave_barriers",
"rich_marine_resource_access",
"tidal_energy_potential"
],
"challenges": [
"extreme_corrosion_environment",
"limited_flat_construction_space",
"tidal_flooding_issues",
"harsh_working_conditions"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_barriers": 2.4,
"amphibious_defense": 2.6
},
"economic_factors": {
"marine_harvesting_bonus": 2.4,
"extreme_maintenance_costs": 2.8,
"research_station_value": 2.2,
"tidal_energy_income": 2.0
},
"strategic_value": {
"marine_resource_control": 2.4,
"coastal_observation": 2.0,
"scientific_research": 2.2
}
}
}

View File

@ -0,0 +1,109 @@
{
"biome_id": "sandy_coast",
"display_name": "Sandy Coast",
"description": "Expansive sandy beaches and dune systems with dynamic coastal environment and tourism potential",
"classification": {
"type": "special_climate_zone",
"priority": 4,
"token_requirements": {
"rain_tokens": {"min": 100, "condition": "moderate_coastal_precipitation"},
"coastal_proximity": {"max": 3, "condition": "close_ocean_access"},
"sediment_availability": {"min": 1, "condition": "sandy_substrate"}
},
"climate_conditions": {
"maritime_influence": true,
"sand_mobility": true,
"moderate_salt_exposure": true,
"dune_formation_active": true
},
"elevation_range": {
"minimum": 0,
"maximum": 30,
"typical_range": [0, 15],
"formation_zone": "low_coastal_areas_with_sandy_substrate"
},
"generation_notes": {
"formation_process": "Created by moderate rainfall with sandy coastal proximity",
"geographic_distribution": "Sandy beaches, dune systems, barrier islands",
"rarity": "Common - major tourist and recreational coastlines",
"minimum_area": 80,
"typical_area_range": [150, 600]
}
},
"vegetation": {
"primary": "dune_stabilizing_plants",
"secondary": ["beach_grasses", "salt_tolerant_shrubs", "coastal_pines", "dune_flowers"],
"characteristics": [
"sand_stabilization",
"salt_spray_tolerance",
"deep_root_systems",
"wind_resistance",
"seasonal_adaptation"
],
"forest_compatibility": "coastal_pine_forests_only",
"note": "Specialized vegetation for mobile sand environments"
},
"environmental_properties": {
"sand_mobility": 2.4,
"salt_tolerance": 2.2,
"wind_exposure": 2.0,
"erosion_variability": 2.3,
"tourism_appeal": 2.8,
"biodiversity": 1.4
},
"resource_modifiers": {
"tourism": 2.8,
"recreation": 2.6,
"fishing": 1.8,
"sand_extraction": 2.2,
"wind_energy": 1.6,
"salt_production": 1.4,
"agriculture": 0.4,
"forestry": 0.6,
"industrial_suitability": 0.8,
"coastal_development": 2.4
},
"industrial_considerations": {
"construction_requirements": [
"sand_stabilization_systems",
"hurricane_storm_surge_protection",
"seasonal_erosion_management",
"foundation_sand_compaction"
],
"advantages": [
"excellent_tourism_development",
"recreational_beach_access",
"sand_construction_materials",
"flat_development_terrain"
],
"challenges": [
"seasonal_storm_damage",
"sand_erosion_and_mobility",
"limited_freshwater_access",
"environmental_protection_regulations"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"amphibious_landing_zones": 1.8,
"coastal_monitoring": 1.6
},
"economic_factors": {
"tourism_revenue": 2.8,
"seasonal_income_variation": 2.2,
"beach_maintenance_costs": 1.6,
"sand_resource_income": 2.2
},
"strategic_value": {
"recreational_development": 2.8,
"coastal_access": 2.4,
"tourism_infrastructure": 2.6
}
}
}

View File

@ -0,0 +1,158 @@
{
"biome_id": "scrubland",
"display_name": "Scrubland",
"description": "Semi-arid transition zones with sparse vegetation, scattered shrubs and bushes, serving as fallback biome for indeterminate climate conditions",
"classification": {
"type": "normal_biome",
"priority": 1,
"token_requirements": {
"_comment": "Fallback biome - no specific requirements, catches all unmatched areas"
},
"climate_conditions": {
"moderate_aridity": true,
"variable_temperatures": true,
"irregular_precipitation": true,
"transitional_zone": true
},
"elevation_range": {
"minimum": 0,
"maximum": 1500,
"typical_range": [200, 800],
"formation_zone": "transition_areas_between_major_biomes"
},
"generation_notes": {
"formation_process": "Default fallback biome for areas not matching specific climate criteria",
"geographic_distribution": "Transition zones, climate boundaries, indeterminate areas",
"rarity": "Common - appears where other biomes don't fit",
"minimum_area": 50,
"typical_area_range": [100, 500]
}
},
"vegetation": {
"primary": "mixed_shrubs_and_bushes",
"secondary": ["drought_tolerant_shrubs", "hardy_grasses", "scattered_small_trees", "thorny_bushes"],
"characteristics": [
"sparse_vegetation_cover",
"drought_adaptation",
"mixed_growth_patterns",
"seasonal_variation",
"opportunistic_growth"
],
"forest_compatibility": "scattered_trees_only",
"note": "Adaptable vegetation that survives in variable conditions"
},
"environmental_properties": {
"vegetation_density": 1.2,
"soil_stability": 1.4,
"erosion_resistance": 1.1,
"water_retention": 1.0,
"fire_risk": 1.6,
"biodiversity": 1.1
},
"resource_modifiers": {
"agriculture": 0.7,
"livestock_grazing": 1.4,
"small_game_hunting": 1.2,
"medicinal_plants": 1.3,
"thorny_wood": 1.1,
"wind_energy": 1.2,
"solar_energy": 1.3,
"forestry": 0.3,
"industrial_suitability": 0.8,
"tourism": 0.6
},
"industrial_considerations": {
"construction_requirements": [
"basic_ground_preparation",
"seasonal_weather_adaptation",
"dust_and_wind_protection"
],
"advantages": [
"low_environmental_restrictions",
"moderate_construction_costs",
"good_solar_exposure",
"reasonable_access_routes"
],
"challenges": [
"limited_water_availability",
"variable_soil_conditions",
"fire_risk_management",
"dust_storm_considerations"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"moderate_concealment": 1.2,
"irregular_terrain_advantage": 1.1
},
"economic_factors": {
"low_development_costs": 1.3,
"moderate_maintenance_costs": 1.1,
"grazing_income": 1.4
},
"strategic_value": {
"transition_zone_control": 1.2,
"buffer_territory": 1.3,
"fallback_settlement": 1.1
}
},
"seasonal_patterns": {
"wet_season": {
"conditions": "increased_vegetation_growth_and_temporary_blooming",
"opportunities": "grazing_improvement_and_limited_agriculture",
"wildlife": "increased_activity_and_breeding"
},
"dry_season": {
"conditions": "vegetation_dormancy_and_increased_fire_risk",
"challenges": "water_scarcity_and_livestock_stress",
"wildlife": "reduced_activity_and_migration"
}
},
"wildlife": {
"adapted_species": [
"small_mammals",
"ground_birds",
"reptiles",
"hardy_insects"
],
"hunting_opportunities": 1.2,
"biodiversity": 1.1,
"conservation_value": "moderate_ecosystem_diversity"
},
"soil_characteristics": {
"soil_type": "variable_sandy_clay_soils",
"organic_matter": "moderate_due_to_mixed_vegetation",
"drainage": "generally_well_drained_with_seasonal_variation",
"erosion_risk": "moderate_especially_during_dry_periods"
},
"land_use_potential": {
"extensive_grazing": "primary_economic_use",
"limited_agriculture": "drought_resistant_crops_only",
"renewable_energy": "good_solar_and_wind_potential",
"rural_settlements": "viable_with_water_management"
},
"water_management": {
"water_sources": "seasonal_streams_and_groundwater",
"conservation_needs": "essential_for_any_development",
"irrigation_potential": "limited_but_possible_with_investment",
"drought_resilience": "moderate_natural_adaptation"
},
"fire_ecology": {
"natural_fire_frequency": "irregular_seasonal_fires",
"fire_adaptation": "mixed_vegetation_recovery_rates",
"fire_management": "controlled_burns_for_grazing_improvement",
"fire_prevention": "firebreaks_and_early_warning_systems"
}
}

View File

@ -0,0 +1,131 @@
{
"biome_id": "storm_prairie",
"display_name": "Storm Prairie",
"description": "Windswept grasslands in high-wind zones with sufficient rainfall, featuring wind-resistant vegetation but hostile to forest growth",
"classification": {
"type": "special_climate_zone",
"priority": 7,
"token_requirements": {
"highWind_tokens": {"min": 2, "condition": "above_storm_threshold"},
"rain_tokens": {"min": 300, "condition": "sufficient_moisture"}
},
"climate_conditions": {
"frequent_high_winds": true,
"adequate_rainfall": true,
"temperature_suitable_for_growth": true,
"forest_growth_prevented": true
},
"elevation_range": {
"minimum": 100,
"maximum": 1000,
"typical_range": [200, 800],
"formation_zone": "interior_continental_areas_with_wind_exposure"
},
"generation_notes": {
"formation_process": "Created by highWind_tokens in areas with sufficient rain_tokens but prevented forest growth",
"geographic_distribution": "Interior continental areas with strong wind patterns",
"rarity": "Uncommon - requires specific combination of high wind and adequate rainfall",
"minimum_area": 100,
"typical_area_range": [200, 800]
}
},
"vegetation": {
"primary": "wind_resistant_grasslands",
"secondary": ["hardy_shrubs", "low_bushes", "wind_adapted_wildflowers"],
"characteristics": [
"deep_root_systems",
"flexible_stems",
"low_profile_growth",
"rapid_regrowth_after_damage"
],
"forest_compatibility": false,
"note": "High winds prevent tree establishment and growth"
},
"environmental_properties": {
"wind_energy": 2.0,
"grassland_productivity": 1.6,
"soil_conservation": 1.4,
"wildfire_resilience": 1.8,
"erosion_resistance": 1.3,
"carbon_storage": 1.2
},
"resource_modifiers": {
"wind_energy": 2.0,
"grazing_land": 1.8,
"wild_game": 1.4,
"medicinal_herbs": 1.3,
"honey_production": 1.6,
"agriculture": 0.7,
"forestry": 0.0,
"industrial_suitability": 1.1,
"recreation": 1.2
},
"industrial_considerations": {
"construction_requirements": [
"wind_resistant_building_design",
"deep_foundations",
"aerodynamic_structures",
"flexible_infrastructure"
],
"advantages": [
"excellent_wind_energy_potential",
"wide_open_spaces_for_development",
"good_soil_for_adapted_agriculture",
"natural_firebreaks"
],
"challenges": [
"constant_wind_stress_on_structures",
"limited_natural_windbreaks",
"difficulty_establishing_trees",
"seasonal_wind_variations"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"open_terrain_visibility": 2.0,
"difficult_approach": 1.3
},
"economic_factors": {
"wind_farm_efficiency": 2.2,
"livestock_grazing_bonus": 1.5,
"construction_wind_resistance_costs": 1.4
},
"strategic_value": {
"renewable_energy_hub": 2.5,
"cavalry_and_vehicle_advantage": 1.8,
"early_warning_systems": 1.9
}
},
"seasonal_variations": {
"growing_season": {
"grass_growth_peak": "spring_and_early_summer",
"wildflower_blooms": "creating_temporary_beauty",
"wildlife_activity": "peak_grazing_and_nesting"
},
"wind_patterns": {
"storm_season": "maximum_wind_intensity",
"calm_periods": "rare_opportunities_for_maintenance",
"seasonal_wind_direction_changes": "affecting_energy_generation"
}
},
"wildlife": {
"adapted_species": [
"prairie_dogs",
"wind_resistant_birds",
"grazing_herbivores",
"burrowing_mammals"
],
"hunting_opportunities": 1.4,
"biodiversity": 1.1,
"migration_routes": "important_stopover_for_wind_dispersed_species"
},
}

View File

@ -0,0 +1,157 @@
{
"biome_id": "temperate_forest",
"display_name": "Temperate Forest",
"description": "Deciduous and mixed forests in moderate climate zones with seasonal variations, balanced temperature and moderate rainfall",
"classification": {
"type": "normal_biome",
"priority": 12,
"token_requirements": {
"rain_tokens": {"min": 300, "condition": "moderate_rainfall"},
"temperature": {"min": 15, "max": 25, "condition": "temperate_climate"}
},
"climate_conditions": {
"moderate_temperatures": true,
"seasonal_variation": true,
"adequate_rainfall": true,
"winter_dormancy_period": true
},
"elevation_range": {
"minimum": 0,
"maximum": 1200,
"typical_range": [100, 800],
"formation_zone": "mid_latitude_regions_with_seasonal_climate"
},
"generation_notes": {
"formation_process": "Created by moderate rain_tokens (300+) with temperate temperatures (15-25°C)",
"geographic_distribution": "Mid-latitude regions with seasonal climate patterns",
"rarity": "Common - standard forest biome in temperate zones",
"minimum_area": 150,
"typical_area_range": [300, 1200]
}
},
"vegetation": {
"primary": "deciduous_and_mixed_forests",
"secondary": ["oak_maple_forests", "beech_birch_woodlands", "mixed_coniferous_deciduous"],
"characteristics": [
"seasonal_leaf_drop",
"cold_adaptation",
"moderate_growth_rates",
"diverse_understory",
"autumn_color_displays"
],
"forest_compatibility": true,
"note": "Classic forest ecosystem with seasonal adaptations"
},
"environmental_properties": {
"biodiversity": 1.8,
"carbon_storage": 1.9,
"seasonal_beauty": 2.5,
"soil_quality": 2.0,
"water_regulation": 1.7,
"wildlife_habitat": 2.2
},
"resource_modifiers": {
"wood": 1.5,
"paper_products": 1.8,
"maple_syrup": 2.0,
"nuts_and_berries": 1.6,
"mushrooms": 1.7,
"wildlife": 1.8,
"agriculture": 1.2,
"industrial_suitability": 0.7,
"tourism": 2.0,
"recreation": 2.2
},
"industrial_considerations": {
"construction_requirements": [
"seasonal_weather_protection",
"foundation_frost_protection",
"moderate_humidity_control"
],
"advantages": [
"sustainable_timber_production",
"good_construction_conditions",
"reliable_water_sources",
"moderate_climate_for_workers"
],
"challenges": [
"seasonal_access_limitations",
"winter_construction_delays",
"forest_clearing_requirements",
"environmental_protection_laws"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_concealment": 1.8,
"seasonal_tactical_variation": 1.6
},
"economic_factors": {
"sustainable_resource_income": 1.8,
"seasonal_tourism_peaks": 2.0,
"moderate_construction_costs": 1.0
},
"strategic_value": {
"resource_sustainability": 2.0,
"population_support": 1.8,
"defensive_terrain": 1.6
}
},
"seasonal_cycle": {
"spring": {
"characteristics": "leaf_emergence_and_flowering",
"activities": "planting_and_early_harvesting",
"wildlife": "breeding_and_migration"
},
"summer": {
"characteristics": "full_canopy_and_peak_growth",
"activities": "maximum_productivity_period",
"wildlife": "peak_activity_and_abundance"
},
"autumn": {
"characteristics": "leaf_color_change_and_fall",
"activities": "harvest_and_preparation",
"wildlife": "migration_and_preparation"
},
"winter": {
"characteristics": "dormancy_and_snow_cover",
"activities": "planning_and_indoor_work",
"wildlife": "hibernation_and_adaptation"
}
},
"wildlife": {
"diversity_index": 1.8,
"game_animals": [
"deer",
"wild_boar",
"small_mammals",
"forest_birds"
],
"hunting_opportunities": 1.8,
"conservation_value": "moderate_biodiversity_and_ecosystem_services"
},
"forest_management": {
"sustainable_harvesting": "selective_cutting_and_rotation",
"regeneration": "natural_and_assisted_forest_renewal",
"fire_management": "controlled_burns_and_fire_prevention",
"pest_control": "integrated_pest_management"
},
"recreation_opportunities": {
"hiking_and_trails": 2.0,
"camping": 1.8,
"wildlife_watching": 1.9,
"autumn_foliage_tourism": 2.5,
"hunting_and_fishing": 1.7
},
}

View File

@ -0,0 +1,147 @@
{
"biome_id": "tropical_rainforest",
"display_name": "Tropical Rainforest",
"description": "Dense, high-biodiversity forests in equatorial regions with high temperature and abundant rainfall, representing peak terrestrial biodiversity",
"classification": {
"type": "normal_biome",
"priority": 10,
"token_requirements": {
"rain_tokens": {"min": 500, "condition": "abundant_rainfall"},
"temperature": {"min": 25, "condition": "tropical_heat"}
},
"climate_conditions": {
"high_temperature": true,
"abundant_rainfall": true,
"high_humidity": true,
"minimal_seasonal_variation": true
},
"elevation_range": {
"minimum": 0,
"maximum": 1500,
"typical_range": [0, 800],
"formation_zone": "equatorial_lowlands_and_foothills"
},
"generation_notes": {
"formation_process": "Created by high rain_tokens (500+) combined with tropical temperatures (25°C+)",
"geographic_distribution": "Equatorial regions with ITCZ influence and abundant moisture",
"rarity": "Moderate - requires specific combination of heat and extreme moisture",
"minimum_area": 200,
"typical_area_range": [500, 2000],
"formation_priority": "High - represents Congo Basin success pattern"
}
},
"vegetation": {
"primary": "multi_layered_forest_canopy",
"secondary": ["emergent_trees", "canopy_layer", "understory", "forest_floor"],
"characteristics": [
"extreme_biodiversity",
"rapid_nutrient_cycling",
"vertical_stratification",
"epiphytic_communities",
"buttress_root_systems"
],
"forest_compatibility": true,
"note": "Peak forest development with maximum biomass and species diversity"
},
"environmental_properties": {
"biodiversity": 3.0,
"carbon_storage": 2.8,
"oxygen_production": 2.5,
"water_regulation": 2.2,
"soil_protection": 2.0,
"climate_regulation": 2.3
},
"resource_modifiers": {
"wood": 2.0,
"biodiversity": 3.0,
"medicinal_plants": 2.8,
"exotic_fruits": 2.5,
"rubber_and_latex": 2.2,
"spices": 2.0,
"agriculture": 0.8,
"industrial_suitability": 0.3,
"tourism": 2.4,
"research_value": 3.0
},
"industrial_considerations": {
"construction_requirements": [
"humidity_resistant_materials",
"elevated_foundations",
"pest_control_systems",
"climate_controlled_storage"
],
"advantages": [
"abundant_biological_resources",
"natural_pharmaceuticals",
"eco_tourism_potential",
"carbon_credit_opportunities"
],
"challenges": [
"extremely_difficult_construction",
"high_maintenance_costs",
"disease_and_pest_pressure",
"environmental_protection_requirements"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_concealment": 2.5,
"difficult_terrain": 2.0,
"guerrilla_warfare_advantage": 2.8
},
"economic_factors": {
"construction_costs": 2.5,
"maintenance_difficulty": 2.3,
"biological_resource_income": 2.8,
"environmental_services_value": 3.0
},
"strategic_value": {
"natural_fortress": 2.2,
"resource_monopoly": 2.6,
"environmental_importance": 3.0
}
},
"ecosystem_services": {
"climate_regulation": "global_carbon_cycling_and_oxygen_production",
"water_cycle": "rainfall_generation_and_watershed_protection",
"biodiversity_conservation": "highest_species_diversity_on_planet",
"soil_conservation": "preventing_erosion_and_maintaining_fertility"
},
"wildlife": {
"diversity_index": 3.0,
"endemic_species": "extremely_high",
"hunting_opportunities": 1.8,
"conservation_priority": "critical",
"research_opportunities": 3.0
},
"layered_structure": {
"emergent_layer": "tallest_trees_reaching_60m_plus",
"canopy_layer": "main_photosynthetic_layer_30_45m",
"understory": "shade_adapted_plants_5_25m",
"forest_floor": "decomposition_and_nutrient_cycling"
},
"seasonal_patterns": {
"wet_season": "peak_growth_and_reproduction",
"dry_season": "minimal_but_still_adequate_rainfall",
"temperature_variation": "minimal_seasonal_change",
"biological_activity": "year_round_high_activity"
},
"formation_requirements": {
"temperature_stability": "consistent_warm_temperatures",
"rainfall_consistency": "year_round_abundant_water",
"soil_drainage": "well_drained_but_water_retentive",
"minimal_disturbance": "requires_stable_conditions_for_development"
},
}

156
gameData/Biomes/tundra.json Normal file
View File

@ -0,0 +1,156 @@
{
"biome_id": "tundra",
"display_name": "Tundra",
"description": "Arctic and alpine regions with extremely cold temperatures, permafrost, and minimal vegetation adapted to harsh conditions",
"classification": {
"type": "normal_biome",
"priority": 14,
"token_requirements": {
"temperature": {"max": -10, "condition": "extremely_cold"}
},
"climate_conditions": {
"extremely_cold_temperatures": true,
"permafrost_layer": true,
"short_growing_season": true,
"low_precipitation": true
},
"elevation_range": {
"minimum": 0,
"maximum": 2000,
"typical_range": [0, 500],
"formation_zone": "arctic_regions_and_high_mountain_areas"
},
"generation_notes": {
"formation_process": "Created by extremely cold temperatures (≤-10°C) regardless of precipitation",
"geographic_distribution": "Arctic regions and high mountain areas",
"rarity": "Uncommon - limited to polar and high-altitude zones",
"minimum_area": 100,
"typical_area_range": [300, 1500]
}
},
"vegetation": {
"primary": "cold_adapted_specialists",
"secondary": ["mosses", "lichens", "dwarf_shrubs", "sedges"],
"characteristics": [
"extremely_low_growth_forms",
"cold_tolerance",
"short_growing_season_adaptation",
"permafrost_root_systems",
"UV_radiation_protection"
],
"forest_compatibility": false,
"note": "Only the most cold-adapted plants can survive permafrost conditions"
},
"environmental_properties": {
"permafrost_depth": 2.8,
"cold_extremes": 3.0,
"growing_season_length": 0.2,
"solar_radiation_extremes": 2.5,
"wind_exposure": 2.2,
"biodiversity": 0.3
},
"resource_modifiers": {
"mineral_extraction": 1.6,
"oil_and_gas": 1.8,
"rare_earth_elements": 1.4,
"ice_and_freshwater": 2.0,
"wildlife_fur": 1.5,
"agriculture": 0.0,
"forestry": 0.0,
"renewable_energy": 0.8,
"industrial_suitability": 0.4,
"research_value": 2.2
},
"industrial_considerations": {
"construction_requirements": [
"permafrost_foundation_systems",
"extreme_cold_protection",
"heating_system_redundancy",
"ice_road_transportation"
],
"advantages": [
"mineral_and_energy_resources",
"natural_refrigeration",
"strategic_location_value",
"minimal_environmental_constraints"
],
"challenges": [
"extreme_construction_costs",
"permafrost_instability",
"transportation_difficulties",
"worker_safety_and_health"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"extreme_weather_advantage": 3.0,
"natural_fortress": 2.8,
"supply_line_difficulty": 3.2
},
"economic_factors": {
"extraction_bonus": 1.8,
"construction_costs": 4.0,
"heating_and_energy_costs": 3.5,
"specialized_equipment_requirements": 3.0
},
"strategic_value": {
"resource_control": 2.2,
"territorial_claims": 2.5,
"climate_research": 2.8
}
},
"survival_challenges": {
"temperature_management": "critical_for_survival",
"food_scarcity": "hunting_and_imported_supplies",
"isolation": "extreme_remoteness_and_communication",
"equipment_failure": "catastrophic_in_cold_conditions"
},
"wildlife": {
"adapted_species": [
"arctic_foxes",
"caribou_and_reindeer",
"polar_bears",
"migratory_birds"
],
"hunting_opportunities": 1.5,
"biodiversity": 0.3,
"conservation_value": "unique_cold_adapted_species"
},
"seasonal_extremes": {
"polar_night": "months_of_darkness",
"midnight_sun": "months_of_continuous_daylight",
"temperature_variation": "extreme_seasonal_differences",
"ice_cycles": "freeze_thaw_permafrost_dynamics"
},
"permafrost_dynamics": {
"active_layer": "seasonal_thaw_zone",
"permafrost_table": "permanently_frozen_layer",
"thermokarst": "ground_collapse_from_thawing",
"frost_heave": "ground_expansion_from_freezing"
},
"research_opportunities": {
"climate_change_studies": 2.8,
"permafrost_research": 2.5,
"cold_adaptation_biology": 2.2,
"ice_core_paleoclimatology": 2.0
},
"transportation": {
"ice_roads": "seasonal_transportation_corridors",
"aircraft_dependency": "primary_year_round_access",
"specialized_vehicles": "cold_weather_equipment_required",
"fuel_logistics": "critical_supply_chain_management"
},
}

View File

@ -0,0 +1,124 @@
{
"biome_id": "wetlands",
"display_name": "Wetlands",
"description": "Marshy regions formed by recurring flood patterns, creating specialized aquatic ecosystems with high biodiversity",
"classification": {
"type": "special_climate_zone",
"priority": 1,
"token_requirements": {
"flood_tokens": {"min": 3, "condition": "above_flood_threshold"}
},
"climate_conditions": {
"frequent_flooding": true,
"high_water_table": true,
"poor_drainage": true,
"seasonal_water_variation": true
},
"elevation_range": {
"minimum": -10,
"maximum": 200,
"typical_range": [0, 100],
"formation_zone": "low_lying_areas_with_poor_drainage"
},
"generation_notes": {
"formation_process": "Created by flood_tokens from WindRegions with high wetness concentrations",
"geographic_distribution": "Low-lying areas with poor drainage and frequent flooding",
"rarity": "Common in flood-prone river deltas and coastal plains",
"minimum_area": 25,
"typical_area_range": [50, 300]
}
},
"vegetation": {
"primary": "marshes_and_swamps",
"secondary": ["cattails", "water_lilies", "cypress_trees", "bog_plants"],
"characteristics": [
"water_adapted_root_systems",
"flood_tolerance",
"nutrient_cycling_specialists",
"methane_production"
],
"forest_compatibility": "specialized_swamp_forests_only",
"note": "Only specialized flood-tolerant tree species can survive"
},
"environmental_properties": {
"water_resources": 2.5,
"biodiversity": 1.8,
"carbon_sequestration": 2.2,
"flood_control": 2.0,
"water_filtration": 2.3,
"methane_production": 1.6
},
"resource_modifiers": {
"freshwater": 2.0,
"fish_and_waterfowl": 2.5,
"medicinal_plants": 1.7,
"peat": 2.8,
"natural_gas": 1.4,
"agriculture": 0.3,
"forestry": 0.5,
"industrial_suitability": 0.2,
"recreation": 1.6
},
"industrial_considerations": {
"construction_requirements": [
"pile_foundations",
"waterproof_construction",
"elevated_roads_and_platforms",
"specialized_drainage_systems"
],
"advantages": [
"natural_water_treatment",
"flood_protection_for_surrounding_areas",
"unique_ecosystem_services",
"peat_energy_source"
],
"challenges": [
"extremely_difficult_construction",
"seasonal_accessibility_issues",
"methane_emission_management",
"environmental_protection_requirements"
]
},
"gameplay_effects": {
"defensive_bonuses": {
"natural_barrier": 1.8,
"difficult_terrain_advantage": 2.2
},
"economic_factors": {
"construction_costs": 3.0,
"maintenance_difficulty": 2.5,
"environmental_services_value": 2.0
},
"strategic_value": {
"natural_fortress": 1.9,
"water_control": 2.1,
"ecosystem_services": 2.3
}
},
"special_features": {
"seasonal_variations": {
"wet_season": "maximum_biodiversity_and_inaccessibility",
"dry_season": "limited_access_for_construction_and_harvesting"
},
"ecosystem_services": [
"flood_control",
"water_purification",
"carbon_storage",
"wildlife_habitat"
],
"environmental_hazards": [
"methane_accumulation",
"disease_vectors",
"unstable_ground",
"toxic_plant_species"
]
},
}

View File

@ -0,0 +1,40 @@
{
"aluminum_resources": {
"bauxite_deposit": {
"display_name": "Bauxite Deposit",
"description": "Primary aluminum ore with high aluminum oxide content ideal for smelting",
"formation_type": "tropical_laterite_weathering",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"laterite_aluminum": {
"display_name": "Laterite Aluminum",
"description": "Weathered aluminum-rich soil formed in tropical climates",
"formation_type": "tropical_soil_weathering",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"nepheline_syenite": {
"display_name": "Nepheline Syenite",
"description": "Igneous rock with aluminum silicate minerals suitable for aluminum extraction",
"formation_type": "alkaline_igneous_intrusion",
"extraction_difficulty": "hard",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"clay_aluminum": {
"display_name": "Aluminum Clay",
"description": "Clay deposits with elevated aluminum content requiring advanced processing",
"formation_type": "sedimentary_aluminum_concentration",
"extraction_difficulty": "very_hard",
"budget_impact": 2,
"resource_yield": "high",
"quality": "low"
}
}
}

View File

@ -0,0 +1,40 @@
{
"anomalies": {
"magnetic_anomaly": {
"display_name": "Magnetic Anomaly",
"description": "Area with unusual magnetic properties affecting instruments and containing rare metals",
"formation_type": "magnetic_field",
"budget_impact": 2
},
"radio_silence_zone": {
"display_name": "Radio Silence Zone",
"description": "Mysterious area where radio communications are disrupted",
"formation_type": "electromagnetic",
"budget_impact": -1
},
"meteorite_impact": {
"display_name": "Meteorite Impact",
"description": "Site of ancient meteorite strike with rare metals and unique minerals",
"formation_type": "extraterrestrial",
"budget_impact": 5
},
"crystalline_formation": {
"display_name": "Crystalline Formation",
"description": "Natural crystal deposits with technological and commercial value",
"formation_type": "mineral_crystal",
"budget_impact": 2
},
"thermal_vent": {
"display_name": "Thermal Vent",
"description": "Underground heat source with geothermal energy potential",
"formation_type": "geothermal",
"budget_impact": 2
},
"unstable_ground": {
"display_name": "Unstable Ground",
"description": "Geologically unstable area prone to landslides and collapse",
"formation_type": "geological_instability",
"budget_impact": -3
}
}
}

View File

@ -0,0 +1,58 @@
{
"base_metal_resources": {
"tin_placer": {
"display_name": "Tin Placer",
"description": "Cassiterite deposits concentrated in alluvial gravels and beach sands",
"formation_type": "alluvial_tin_concentration",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"tin_lode": {
"display_name": "Tin Lode",
"description": "Primary cassiterite ore in granite-related veins and greisen",
"formation_type": "granitic_tin_mineralization",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"lead_galena": {
"display_name": "Lead Galena",
"description": "Primary lead sulfide ore often associated with silver and zinc",
"formation_type": "sulfide_mineralization",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "high",
"quality": "standard"
},
"lead_carbonate": {
"display_name": "Lead Carbonate",
"description": "Weathered lead ore with cerussite and anglesite minerals",
"formation_type": "lead_oxidation_zone",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "medium",
"quality": "standard"
},
"nickel_laterite": {
"display_name": "Nickel Laterite",
"description": "Tropical weathering deposit with garnierite and limonite nickel ores",
"formation_type": "laterite_nickel_weathering",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "high",
"quality": "standard"
},
"nickel_sulfide": {
"display_name": "Nickel Sulfide",
"description": "Primary nickel ore with pentlandite in mafic intrusions",
"formation_type": "magmatic_sulfide_segregation",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "medium",
"quality": "premium"
}
}
}

View File

@ -0,0 +1,58 @@
{
"coal_resources": {
"rich_coal_seam": {
"display_name": "Rich Coal Seam",
"description": "High-quality coal deposit with excellent heating value and low impurities",
"formation_type": "compressed_carboniferous_forest",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"coal_seam": {
"display_name": "Coal Seam",
"description": "Standard coal deposit suitable for industrial and heating applications",
"formation_type": "compressed_carboniferous_forest",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"coal_outcrop": {
"display_name": "Coal Outcrop",
"description": "Surface-exposed coal formation easy to access but lower quality",
"formation_type": "exposed_carboniferous_forest",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "medium",
"quality": "standard"
},
"surface_coal": {
"display_name": "Surface Coal",
"description": "Weathered coal deposits scattered on surface with minimal extraction requirements",
"formation_type": "eroded_coal_seam",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"resource_yield": "low",
"quality": "low"
},
"peat_bog": {
"display_name": "Peat Bog",
"description": "Early-stage coal formation providing low-grade fuel and soil amendment",
"formation_type": "partially_decomposed_organic_matter",
"extraction_difficulty": "easy",
"budget_impact": 1,
"resource_yield": "low",
"quality": "low"
},
"lignite_deposit": {
"display_name": "Lignite Deposit",
"description": "Brown coal with moderate heating value, intermediate between peat and bituminous coal",
"formation_type": "intermediate_carboniferous_compression",
"extraction_difficulty": "medium",
"budget_impact": 2,
"resource_yield": "medium",
"quality": "medium"
}
}
}

View File

@ -0,0 +1,52 @@
{
"coastal_features": {
"sea_cave": {
"display_name": "Sea Cave",
"description": "Ocean-carved cavern accessible at low tide with marine ecosystems",
"formation_type": "marine_erosion",
"budget_impact": 2
},
"tidal_pool": {
"display_name": "Tidal Pool",
"description": "Rock depressions filled with seawater hosting unique marine life",
"formation_type": "tidal_formation",
"budget_impact": 1
},
"natural_harbor": {
"display_name": "Natural Harbor",
"description": "Sheltered coastal bay perfect for maritime activities and ports",
"formation_type": "coastal_geography",
"budget_impact": 3
},
"coral_reef": {
"display_name": "Coral Reef",
"description": "Living reef structure providing marine biodiversity and coastal protection",
"formation_type": "biological_formation",
"budget_impact": 2
},
"sea_stack": {
"display_name": "Sea Stack",
"description": "Isolated rocky pillar standing in shallow coastal waters",
"formation_type": "marine_erosion",
"budget_impact": 1
},
"beach_dunes": {
"display_name": "Beach Dunes",
"description": "Sand formations shaped by wind providing coastal protection",
"formation_type": "aeolian_formation",
"budget_impact": 1
},
"estuary": {
"display_name": "Estuary",
"description": "River mouth where freshwater meets saltwater creating rich ecosystems",
"formation_type": "fluvial_marine",
"budget_impact": 2
},
"blowhole": {
"display_name": "Blowhole",
"description": "Coastal rock formation that shoots water sprays during high waves",
"formation_type": "marine_erosion",
"budget_impact": 1
}
}
}

View File

@ -0,0 +1,58 @@
{
"copper_resources": {
"porphyry_copper": {
"display_name": "Porphyry Copper",
"description": "Large-scale copper deposit in igneous intrusion with molybdenum traces",
"formation_type": "igneous_hydrothermal_intrusion",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "very_high",
"quality": "premium"
},
"copper_vein": {
"display_name": "Copper Vein",
"description": "High-grade copper ore in hydrothermal veins with excellent purity",
"formation_type": "hydrothermal_vein_formation",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"chalcopyrite_deposit": {
"display_name": "Chalcopyrite Deposit",
"description": "Standard copper sulfide ore suitable for flotation processing",
"formation_type": "sulfide_mineralization",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"malachite_outcrop": {
"display_name": "Malachite Outcrop",
"description": "Green copper carbonate formation indicating deeper copper deposits",
"formation_type": "copper_oxidation_zone",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "medium",
"quality": "standard"
},
"native_copper": {
"display_name": "Native Copper",
"description": "Pure metallic copper deposits requiring minimal processing",
"formation_type": "basalt_flow_copper_precipitation",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "low",
"quality": "premium"
},
"copper_shale": {
"display_name": "Copper Shale",
"description": "Sedimentary copper deposit with low grade but large extent",
"formation_type": "sedimentary_copper_precipitation",
"extraction_difficulty": "very_hard",
"budget_impact": 2,
"resource_yield": "high",
"quality": "low"
}
}
}

View File

@ -0,0 +1,40 @@
{
"cultural_sites": {
"ancient_ruins": {
"display_name": "Ancient Ruins",
"description": "Archaeological remains from past civilizations with historical value",
"formation_type": "archaeological",
"budget_impact": 1
},
"abandoned_village": {
"display_name": "Abandoned Village",
"description": "Deserted rural settlement with basic infrastructure",
"formation_type": "abandoned_settlement",
"budget_impact": 0
},
"old_monastery": {
"display_name": "Old Monastery",
"description": "Historic religious complex with stone architecture and strategic position",
"formation_type": "religious_heritage",
"budget_impact": 1
},
"castle_ruins": {
"display_name": "Castle Ruins",
"description": "Remains of medieval fortress with defensive advantages and stone materials",
"formation_type": "military_heritage",
"budget_impact": 2
},
"lighthouse": {
"display_name": "Lighthouse",
"description": "Coastal navigation aid with strategic maritime position",
"formation_type": "maritime_infrastructure",
"budget_impact": 1
},
"historical_cemetery": {
"display_name": "Historical Cemetery",
"description": "Old burial ground with cultural significance and central location",
"formation_type": "cultural_heritage",
"budget_impact": 1
}
}
}

View File

@ -0,0 +1,45 @@
{
"feature_system_version": "1.0",
"description": "Map features catalog for procedural world generation",
"last_updated": "2024-09-29",
"feature_categories": {
"geological_formations": {
"file": "geological_formations.json",
"description": "Natural rock and terrain formations",
"count": 10
},
"natural_landmarks": {
"file": "natural_landmarks.json",
"description": "Distinctive natural monuments and formations",
"count": 6
},
"water_features": {
"file": "water_features.json",
"description": "Lakes, rivers, springs and wetlands",
"count": 8
},
"industrial_ruins": {
"file": "industrial_ruins.json",
"description": "Abandoned industrial and military sites",
"count": 8
},
"anomalies": {
"file": "anomalies.json",
"description": "Unusual geological and electromagnetic phenomena",
"count": 6
},
"cultural_sites": {
"file": "cultural_sites.json",
"description": "Historical and archaeological locations",
"count": 6
}
},
"generation_parameters": {
"placement_probability": 0.05,
"max_features_per_tile": 1,
"biome_filtering": true,
"budget_impact_range": [-3, 5]
}
}

View File

@ -0,0 +1,52 @@
{
"forest_features": {
"ancient_grove": {
"display_name": "Ancient Grove",
"description": "Stand of extremely old trees with rare wood and spiritual significance",
"formation_type": "old_growth_forest",
"budget_impact": 3
},
"forest_clearing": {
"display_name": "Forest Clearing",
"description": "Natural open space within forest perfect for settlements",
"formation_type": "natural_opening",
"budget_impact": 1
},
"giant_tree": {
"display_name": "Giant Tree",
"description": "Massive individual tree suitable for treehouse construction",
"formation_type": "exceptional_growth",
"budget_impact": 2
},
"bamboo_grove": {
"display_name": "Bamboo Grove",
"description": "Dense bamboo forest with rapid growth and construction materials",
"formation_type": "bamboo_ecosystem",
"budget_impact": 1
},
"fruit_orchard": {
"display_name": "Wild Fruit Orchard",
"description": "Natural grove of fruit-bearing trees providing food resources",
"formation_type": "fruit_tree_cluster",
"budget_impact": 2
},
"medicinal_grove": {
"display_name": "Medicinal Grove",
"description": "Forest area rich in plants with pharmaceutical properties",
"formation_type": "medicinal_ecosystem",
"budget_impact": 2
},
"mushroom_grove": {
"display_name": "Mushroom Grove",
"description": "Forest area with abundant fungal growth and rare mushroom species",
"formation_type": "fungal_ecosystem",
"budget_impact": 1
},
"carboniferous_forest": {
"display_name": "Carboniferous Forest",
"description": "Ancient forest remnant with giant ferns and primitive trees, containing coal seams",
"formation_type": "paleozoic_relic",
"budget_impact": 4
}
}
}

View File

@ -0,0 +1,64 @@
{
"geological_formations": {
"cave": {
"display_name": "Cave",
"description": "Natural underground cavern providing shelter and potential hidden resources",
"formation_type": "erosion",
"budget_impact": 1
},
"hot_spring": {
"display_name": "Hot Spring",
"description": "Geothermally heated groundwater emerging at surface",
"formation_type": "geothermal",
"budget_impact": 1
},
"canyon": {
"display_name": "Canyon",
"description": "Deep gorge carved by water erosion providing natural barriers",
"formation_type": "erosion",
"budget_impact": 0
},
"plateau": {
"display_name": "Plateau",
"description": "Elevated flat-topped landform with commanding views",
"formation_type": "erosion_resistant",
"budget_impact": 1
},
"geyser": {
"display_name": "Geyser",
"description": "Periodic eruption of heated groundwater and steam",
"formation_type": "geothermal",
"budget_impact": 2
},
"cliff": {
"display_name": "Cliff",
"description": "Steep vertical rock face formed by erosion or faulting",
"formation_type": "erosion_faulting",
"budget_impact": 0
},
"gorge": {
"display_name": "Gorge",
"description": "Narrow valley with steep rocky walls carved by water flow",
"formation_type": "water_erosion",
"budget_impact": 0
},
"natural_bridge": {
"display_name": "Natural Bridge",
"description": "Rock arch formation spanning across valleys or rivers",
"formation_type": "erosion_arch",
"budget_impact": 1
},
"sinkhole": {
"display_name": "Sinkhole",
"description": "Circular depression formed by underground water dissolution",
"formation_type": "karst_dissolution",
"budget_impact": -1
},
"spring": {
"display_name": "Spring",
"description": "Natural emergence of groundwater at surface",
"formation_type": "groundwater_emergence",
"budget_impact": 1
}
}
}

View File

@ -0,0 +1,58 @@
{
"gold_resources": {
"gold_lode": {
"display_name": "Gold Lode",
"description": "Primary gold deposit in quartz veins with high-grade ore concentrations",
"formation_type": "hydrothermal_quartz_vein",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "medium",
"quality": "premium"
},
"placer_gold": {
"display_name": "Placer Gold",
"description": "Alluvial gold deposits concentrated in river gravels and ancient streambeds",
"formation_type": "alluvial_gold_concentration",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "premium"
},
"epithermal_gold": {
"display_name": "Epithermal Gold",
"description": "Shallow gold deposit formed by hot springs with silver associations",
"formation_type": "epithermal_mineralization",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"residual_gold": {
"display_name": "Residual Gold",
"description": "Weathered gold deposits concentrated by erosion of primary sources",
"formation_type": "weathering_concentration",
"extraction_difficulty": "very_easy",
"budget_impact": 2,
"resource_yield": "low",
"quality": "premium"
},
"conglomerate_gold": {
"display_name": "Conglomerate Gold",
"description": "Ancient gold deposits in fossil river conglomerates with uranium traces",
"formation_type": "paleozoic_conglomerate",
"extraction_difficulty": "very_hard",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"sulfide_gold": {
"display_name": "Sulfide Gold",
"description": "Gold associated with sulfide minerals requiring complex processing",
"formation_type": "sulfide_mineralization",
"extraction_difficulty": "very_hard",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
}
}
}

View File

@ -0,0 +1,52 @@
{
"industrial_ruins": {
"terikon": {
"display_name": "Terikon",
"description": "Artificial hill of mining waste with recoverable materials but pollution",
"formation_type": "mining_waste",
"budget_impact": 0
},
"abandoned_factory": {
"display_name": "Abandoned Factory",
"description": "Derelict industrial facility with scrap metal and machinery",
"formation_type": "industrial_ruin",
"budget_impact": 1
},
"ghost_town": {
"display_name": "Ghost Town",
"description": "Deserted settlement with infrastructure but potential dangers",
"formation_type": "abandoned_settlement",
"budget_impact": -1
},
"tank_graveyard": {
"display_name": "Tank Graveyard",
"description": "Collection of abandoned military vehicles with valuable scrap metal",
"formation_type": "military_scrap",
"budget_impact": 2
},
"car_cemetery": {
"display_name": "Car Cemetery",
"description": "Abandoned vehicles providing civilian scrap metal",
"formation_type": "civilian_scrap",
"budget_impact": 1
},
"plane_wreckage": {
"display_name": "Plane Wreckage",
"description": "Crashed aircraft with rare aviation alloys and components",
"formation_type": "aviation_scrap",
"budget_impact": 3
},
"abandoned_mine": {
"display_name": "Abandoned Mine",
"description": "Old mining facility with potential resources but structural dangers",
"formation_type": "extraction_ruin",
"budget_impact": 0
},
"derelict_refinery": {
"display_name": "Derelict Refinery",
"description": "Abandoned oil processing facility with infrastructure but contamination",
"formation_type": "chemical_ruin",
"budget_impact": -2
}
}
}

View File

@ -0,0 +1,67 @@
{
"iron_resources": {
"rich_iron_ore": {
"display_name": "Rich Iron Ore",
"description": "High-grade iron ore deposit with excellent purity and minimal processing requirements",
"formation_type": "banded_iron_formation",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "very_high",
"quality": "premium"
},
"iron_ore_vein": {
"display_name": "Iron Ore Vein",
"description": "Standard iron ore deposit suitable for industrial steel production",
"formation_type": "hydrothermal_iron_precipitation",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "high",
"quality": "standard"
},
"magnetite_deposit": {
"display_name": "Magnetite Deposit",
"description": "Magnetic iron ore with high iron content and easy magnetic separation",
"formation_type": "metamorphic_iron_concentration",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "high",
"quality": "premium"
},
"hematite_outcrop": {
"display_name": "Hematite Outcrop",
"description": "Surface-exposed iron oxide formation with moderate iron content",
"formation_type": "weathered_iron_oxidation",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "medium",
"quality": "standard"
},
"bog_iron": {
"display_name": "Bog Iron",
"description": "Iron deposits formed in wetlands through bacterial precipitation",
"formation_type": "biological_iron_precipitation",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"resource_yield": "low",
"quality": "low"
},
"laterite_iron": {
"display_name": "Laterite Iron",
"description": "Tropical weathering iron deposit with mixed aluminum and iron content",
"formation_type": "tropical_weathering_concentration",
"extraction_difficulty": "hard",
"budget_impact": 2,
"resource_yield": "medium",
"quality": "medium"
},
"taconite": {
"display_name": "Taconite",
"description": "Low-grade iron ore requiring beneficiation but with massive reserves",
"formation_type": "precambrian_banded_iron",
"extraction_difficulty": "hard",
"budget_impact": 2,
"resource_yield": "very_high",
"quality": "low"
}
}
}

View File

@ -0,0 +1,40 @@
{
"natural_landmarks": {
"natural_arch": {
"display_name": "Natural Arch",
"description": "Spectacular stone arch formation created by selective erosion",
"formation_type": "erosion_arch",
"budget_impact": 1
},
"monolith": {
"display_name": "Monolith",
"description": "Large isolated stone pillar standing prominently in landscape",
"formation_type": "erosion_resistant",
"budget_impact": 3
},
"rock_spire": {
"display_name": "Rock Spire",
"description": "Tall needle-like rock formation pointing skyward",
"formation_type": "erosion_pillar",
"budget_impact": 1
},
"mesa": {
"display_name": "Mesa",
"description": "Flat-topped mountain with steep cliff sides",
"formation_type": "erosion_resistant",
"budget_impact": 1
},
"hoodoo": {
"display_name": "Hoodoo",
"description": "Tall thin spire of rock formed by differential erosion",
"formation_type": "erosion_pillar",
"budget_impact": 1
},
"crater": {
"display_name": "Crater",
"description": "Large circular depression from ancient impact or volcanic activity",
"formation_type": "impact_volcanic",
"budget_impact": 4
}
}
}

View File

@ -0,0 +1,67 @@
{
"oil_resources": {
"major_oil_field": {
"display_name": "Major Oil Field",
"description": "Large petroleum reservoir with high pressure and excellent crude quality",
"formation_type": "deep_carboniferous_compression_with_geological_trap",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "very_high",
"quality": "premium"
},
"oil_well": {
"display_name": "Oil Well",
"description": "Standard petroleum deposit accessible through drilling operations",
"formation_type": "carboniferous_compression_with_geological_trap",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "high",
"quality": "standard"
},
"shallow_oil_pocket": {
"display_name": "Shallow Oil Pocket",
"description": "Surface-near petroleum deposit with easier access but lower pressure",
"formation_type": "shallow_carboniferous_trap",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"oil_seep": {
"display_name": "Oil Seep",
"description": "Natural petroleum surface emergence indicating deeper reserves",
"formation_type": "surface_petroleum_migration",
"extraction_difficulty": "very_easy",
"budget_impact": 2,
"resource_yield": "low",
"quality": "medium"
},
"tar_sands": {
"display_name": "Tar Sands",
"description": "Heavy oil mixed with sand requiring specialized extraction methods",
"formation_type": "degraded_petroleum_in_sandstone",
"extraction_difficulty": "very_hard",
"budget_impact": 3,
"resource_yield": "high",
"quality": "low"
},
"offshore_oil": {
"display_name": "Offshore Oil",
"description": "Underwater petroleum reservoir requiring marine drilling platforms",
"formation_type": "submerged_carboniferous_compression",
"extraction_difficulty": "very_hard",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"shale_oil": {
"display_name": "Shale Oil",
"description": "Oil trapped in shale rock formations requiring hydraulic fracturing",
"formation_type": "carboniferous_matter_in_shale",
"extraction_difficulty": "very_hard",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "medium"
}
}
}

View File

@ -0,0 +1,40 @@
{
"platinum_resources": {
"pge_reef": {
"display_name": "PGE Reef",
"description": "Platinum group elements concentrated in layered igneous intrusions",
"formation_type": "layered_igneous_intrusion",
"extraction_difficulty": "very_hard",
"budget_impact": 6,
"resource_yield": "medium",
"quality": "premium"
},
"platinum_placer": {
"display_name": "Platinum Placer",
"description": "Alluvial platinum deposits concentrated in river systems from eroded sources",
"formation_type": "alluvial_pge_concentration",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "low",
"quality": "premium"
},
"sperrylite_deposit": {
"display_name": "Sperrylite Deposit",
"description": "Platinum arsenide ore associated with copper-nickel sulfides",
"formation_type": "magmatic_sulfide_segregation",
"extraction_difficulty": "very_hard",
"budget_impact": 5,
"resource_yield": "medium",
"quality": "premium"
},
"cooperite_vein": {
"display_name": "Cooperite Vein",
"description": "Platinum sulfide mineral in hydrothermal veins with palladium content",
"formation_type": "hydrothermal_pge_precipitation",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "low",
"quality": "premium"
}
}
}

View File

@ -0,0 +1,76 @@
{
"rare_metal_resources": {
"tungsten_vein": {
"display_name": "Tungsten Vein",
"description": "High-grade tungsten ore in quartz veins with scheelite and wolframite",
"formation_type": "hydrothermal_tungsten_precipitation",
"extraction_difficulty": "very_hard",
"budget_impact": 6,
"resource_yield": "medium",
"quality": "premium"
},
"molybdenum_porphyry": {
"display_name": "Molybdenum Porphyry",
"description": "Molybdenum sulfide in large porphyry copper systems",
"formation_type": "porphyry_molybdenum_system",
"extraction_difficulty": "very_hard",
"budget_impact": 5,
"resource_yield": "medium",
"quality": "premium"
},
"chromite_deposit": {
"display_name": "Chromite Deposit",
"description": "Chromium-iron oxide ore in layered mafic intrusions",
"formation_type": "layered_mafic_intrusion",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "high",
"quality": "standard"
},
"antimony_vein": {
"display_name": "Antimony Vein",
"description": "Stibnite ore in hydrothermal veins with mercury associations",
"formation_type": "epithermal_antimony_vein",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"cobalt_arsenide": {
"display_name": "Cobalt Arsenide",
"description": "Cobalt-arsenic minerals in hydrothermal deposits with silver traces",
"formation_type": "hydrothermal_cobalt_precipitation",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "low",
"quality": "premium"
},
"iridium_placer": {
"display_name": "Iridium Placer",
"description": "Ultra-rare platinum group metal in alluvial concentrations",
"formation_type": "alluvial_pge_concentration",
"extraction_difficulty": "very_hard",
"budget_impact": 7,
"resource_yield": "very_low",
"quality": "premium"
},
"lithium_pegmatite": {
"display_name": "Lithium Pegmatite",
"description": "Spodumene-bearing granite pegmatite with lithium silicate minerals",
"formation_type": "granitic_pegmatite",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "medium",
"quality": "premium"
},
"lithium_brine": {
"display_name": "Lithium Brine",
"description": "Salt lake brines with concentrated lithium chloride solutions",
"formation_type": "evaporite_lithium_concentration",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "high",
"quality": "standard"
}
}
}

View File

@ -0,0 +1,49 @@
{
"silver_resources": {
"silver_vein": {
"display_name": "Silver Vein",
"description": "High-grade silver ore in hydrothermal veins with excellent purity",
"formation_type": "hydrothermal_precious_metal_vein",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "medium",
"quality": "premium"
},
"galena_silver": {
"display_name": "Galena Silver",
"description": "Silver-bearing lead sulfide ore requiring lead-silver separation",
"formation_type": "sulfide_mineralization",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "high",
"quality": "standard"
},
"argentite_deposit": {
"display_name": "Argentite Deposit",
"description": "Silver sulfide mineral with high silver content and moderate processing",
"formation_type": "sulfide_precipitation",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "medium",
"quality": "premium"
},
"native_silver": {
"display_name": "Native Silver",
"description": "Pure metallic silver deposits requiring minimal processing",
"formation_type": "hydrothermal_metal_precipitation",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "low",
"quality": "premium"
},
"silver_placer": {
"display_name": "Silver Placer",
"description": "Alluvial silver deposits concentrated in ancient river systems",
"formation_type": "alluvial_precious_metal_concentration",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "low",
"quality": "premium"
}
}
}

View File

@ -0,0 +1,103 @@
{
"stone_resources": {
"stone_quarry": {
"display_name": "Stone Quarry",
"description": "Generic rock outcrop suitable for basic construction materials",
"formation_type": "surface_rock_exposure",
"extraction_difficulty": "medium",
"budget_impact": 2,
"resource_yield": "very_high",
"quality": "standard"
},
"granite_quarry": {
"display_name": "Granite Quarry",
"description": "High-quality igneous rock perfect for construction and monuments",
"formation_type": "plutonic_igneous_intrusion",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "very_high",
"quality": "premium"
},
"limestone_quarry": {
"display_name": "Limestone Quarry",
"description": "Sedimentary rock ideal for cement production and building materials",
"formation_type": "marine_carbonate_precipitation",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "very_high",
"quality": "standard"
},
"sandstone_quarry": {
"display_name": "Sandstone Quarry",
"description": "Layered sedimentary rock suitable for construction blocks and aggregate",
"formation_type": "clastic_sedimentary_formation",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "very_high",
"quality": "standard"
},
"marble_deposit": {
"display_name": "Marble Deposit",
"description": "Metamorphic limestone with excellent carving properties and durability",
"formation_type": "limestone_metamorphism",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "high",
"quality": "premium"
},
"clay_pit": {
"display_name": "Clay Pit",
"description": "Fine sedimentary material essential for ceramics and construction",
"formation_type": "weathering_accumulation",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"resource_yield": "very_high",
"quality": "standard"
},
"sand_deposit": {
"display_name": "Sand Deposit",
"description": "Fine granular material perfect for concrete and glass production",
"formation_type": "weathering_erosion_accumulation",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"resource_yield": "very_high",
"quality": "standard"
},
"gravel_pit": {
"display_name": "Gravel Pit",
"description": "Mixed rock fragments perfect for concrete aggregate and road base",
"formation_type": "fluvial_glacial_accumulation",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"resource_yield": "very_high",
"quality": "standard"
},
"slate_deposit": {
"display_name": "Slate Deposit",
"description": "Fine-grained metamorphic rock perfect for roofing and flooring",
"formation_type": "shale_metamorphism",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "high",
"quality": "premium"
},
"quartzite_deposit": {
"display_name": "Quartzite Deposit",
"description": "Hard metamorphic quartz rock with excellent abrasive properties",
"formation_type": "sandstone_metamorphism",
"extraction_difficulty": "hard",
"budget_impact": 3,
"resource_yield": "high",
"quality": "premium"
},
"gneiss_outcrop": {
"display_name": "Gneiss Outcrop",
"description": "Banded metamorphic rock suitable for decorative construction",
"formation_type": "high_grade_metamorphism",
"extraction_difficulty": "hard",
"budget_impact": 3,
"resource_yield": "high",
"quality": "standard"
}
}
}

View File

@ -0,0 +1,31 @@
{
"thorium_resources": {
"monazite_placer": {
"display_name": "Monazite Placer",
"description": "Heavy mineral sand deposit with thorium-bearing rare earth phosphates",
"formation_type": "beach_placer_concentration",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "medium",
"quality": "premium"
},
"thorite_vein": {
"display_name": "Thorite Vein",
"description": "Primary thorium silicate mineral in granite pegmatites",
"formation_type": "granitic_pegmatite",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "low",
"quality": "premium"
},
"thorium_granite": {
"display_name": "Thorium Granite",
"description": "Radioactive granite with elevated thorium content requiring bulk processing",
"formation_type": "radioactive_granite_intrusion",
"extraction_difficulty": "very_hard",
"budget_impact": 3,
"resource_yield": "high",
"quality": "low"
}
}
}

View File

@ -0,0 +1,40 @@
{
"titanium_resources": {
"ilmenite_deposit": {
"display_name": "Ilmenite Deposit",
"description": "Primary titanium-iron oxide ore with excellent titanium content",
"formation_type": "magmatic_oxide_segregation",
"extraction_difficulty": "hard",
"budget_impact": 5,
"resource_yield": "high",
"quality": "premium"
},
"rutile_placer": {
"display_name": "Rutile Placer",
"description": "Heavy mineral sand deposit concentrated by wave action with pure titanium dioxide",
"formation_type": "beach_placer_concentration",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "medium",
"quality": "premium"
},
"anatase_vein": {
"display_name": "Anatase Vein",
"description": "Crystalline titanium dioxide in hydrothermal veins with high purity",
"formation_type": "hydrothermal_oxide_precipitation",
"extraction_difficulty": "medium",
"budget_impact": 4,
"resource_yield": "low",
"quality": "premium"
},
"titaniferous_magnetite": {
"display_name": "Titaniferous Magnetite",
"description": "Iron-titanium oxide requiring separation processing for both metals",
"formation_type": "layered_igneous_intrusion",
"extraction_difficulty": "very_hard",
"budget_impact": 4,
"resource_yield": "high",
"quality": "standard"
}
}
}

View File

@ -0,0 +1,40 @@
{
"underground_features": {
"cave_network": {
"display_name": "Cave Network",
"description": "Interconnected underground cavern system with multiple entrances",
"formation_type": "limestone_dissolution",
"budget_impact": 2
},
"underground_lake": {
"display_name": "Underground Lake",
"description": "Subterranean water body accessible through cave systems",
"formation_type": "groundwater_accumulation",
"budget_impact": 3
},
"crystal_cavern": {
"display_name": "Crystal Cavern",
"description": "Underground chamber with natural crystal formations",
"formation_type": "mineral_crystallization",
"budget_impact": 4
},
"bat_cave": {
"display_name": "Bat Cave",
"description": "Large cave system inhabited by bat colonies with guano deposits",
"formation_type": "biological_cave",
"budget_impact": 1
},
"underground_river": {
"display_name": "Underground River",
"description": "Subterranean watercourse flowing through cave systems",
"formation_type": "groundwater_flow",
"budget_impact": 2
},
"deep_cavern": {
"display_name": "Deep Cavern",
"description": "Extremely deep cave system reaching significant depths",
"formation_type": "tectonic_cave",
"budget_impact": 3
}
}
}

View File

@ -0,0 +1,49 @@
{
"uranium_resources": {
"pitchblende_vein": {
"display_name": "Pitchblende Vein",
"description": "High-grade uranium ore in hydrothermal veins with exceptional uranium content",
"formation_type": "hydrothermal_uranium_concentration",
"extraction_difficulty": "very_hard",
"budget_impact": 6,
"resource_yield": "high",
"quality": "premium"
},
"uranium_roll_front": {
"display_name": "Uranium Roll Front",
"description": "Crescent-shaped uranium deposit formed by groundwater flow in sandstone",
"formation_type": "groundwater_uranium_precipitation",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "medium",
"quality": "standard"
},
"carnotite_deposit": {
"display_name": "Carnotite Deposit",
"description": "Uranium-vanadium ore in sedimentary formations with yellow coloration",
"formation_type": "sedimentary_uranium_vanadium",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"uraninite_placer": {
"display_name": "Uraninite Placer",
"description": "Detrital uranium deposits concentrated in ancient river channels",
"formation_type": "alluvial_uranium_concentration",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "low",
"quality": "premium"
},
"phosphate_uranium": {
"display_name": "Phosphate Uranium",
"description": "Low-grade uranium associated with phosphate rock formations",
"formation_type": "phosphate_uranium_association",
"extraction_difficulty": "very_hard",
"budget_impact": 2,
"resource_yield": "very_high",
"quality": "low"
}
}
}

View File

@ -0,0 +1,67 @@
{
"volcanic_resources": {
"sulfur_fumarole": {
"display_name": "Sulfur Fumarole",
"description": "Volcanic vent depositing pure sulfur crystals from gas emissions",
"formation_type": "volcanic_gas_precipitation",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "premium"
},
"obsidian_flow": {
"display_name": "Obsidian Flow",
"description": "Volcanic glass formation suitable for cutting tools and decoration",
"formation_type": "rapid_lava_cooling",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "high",
"quality": "premium"
},
"basalt_flow": {
"display_name": "Basalt Flow",
"description": "Dense volcanic rock excellent for construction and road aggregate",
"formation_type": "mafic_lava_flow",
"extraction_difficulty": "hard",
"budget_impact": 3,
"resource_yield": "very_high",
"quality": "standard"
},
"pumice_deposit": {
"display_name": "Pumice Deposit",
"description": "Lightweight volcanic rock perfect for construction and abrasives",
"formation_type": "explosive_volcanic_eruption",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"resource_yield": "very_high",
"quality": "standard"
},
"volcanic_ash": {
"display_name": "Volcanic Ash",
"description": "Fine volcanic material excellent for cement production and soil amendment",
"formation_type": "pyroclastic_fallout",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"resource_yield": "very_high",
"quality": "standard"
},
"perlite_deposit": {
"display_name": "Perlite Deposit",
"description": "Volcanic glass that expands when heated, used for insulation",
"formation_type": "hydrated_volcanic_glass",
"extraction_difficulty": "easy",
"budget_impact": 2,
"resource_yield": "high",
"quality": "standard"
},
"zeolite_formation": {
"display_name": "Zeolite Formation",
"description": "Crystalline volcanic minerals with molecular sieve properties",
"formation_type": "volcanic_glass_alteration",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "premium"
}
}
}

View File

@ -0,0 +1,40 @@
{
"volcanic_features": {
"volcano": {
"display_name": "Volcano",
"description": "Active or dormant volcanic cone with potential geothermal energy",
"formation_type": "volcanic_activity",
"budget_impact": 3
},
"lava_field": {
"display_name": "Lava Field",
"description": "Solidified lava flows creating rough terrain with mineral deposits",
"formation_type": "volcanic_flow",
"budget_impact": 1
},
"volcanic_vent": {
"display_name": "Volcanic Vent",
"description": "Secondary volcanic opening with gas emissions and sulfur deposits",
"formation_type": "volcanic_secondary",
"budget_impact": 2
},
"caldera": {
"display_name": "Caldera",
"description": "Large volcanic depression with fertile soils and geothermal activity",
"formation_type": "volcanic_collapse",
"budget_impact": 4
},
"fumarole": {
"display_name": "Fumarole",
"description": "Volcanic gas vent with sulfur deposits and geothermal potential",
"formation_type": "volcanic_gas",
"budget_impact": 1
},
"obsidian_field": {
"display_name": "Obsidian Field",
"description": "Natural volcanic glass deposits valuable for precision tools",
"formation_type": "volcanic_glass",
"budget_impact": 2
}
}
}

View File

@ -0,0 +1,64 @@
{
"water_features": {
"lake": {
"display_name": "Lake",
"description": "Large body of fresh water surrounded by land",
"formation_type": "water_accumulation",
"budget_impact": 1
},
"pond": {
"display_name": "Pond",
"description": "Small body of still fresh water",
"formation_type": "water_accumulation",
"budget_impact": 1
},
"waterfall": {
"display_name": "Waterfall",
"description": "Water cascading down from height with hydroelectric potential",
"formation_type": "water_erosion",
"budget_impact": 1
},
"marsh": {
"display_name": "Marsh",
"description": "Wetland area with standing water and specialized vegetation",
"formation_type": "water_saturation",
"budget_impact": 0
},
"central_hill_swamp": {
"display_name": "Central Hill Swamp",
"description": "Marshy wetland with elevated central hill providing strategic position",
"formation_type": "water_saturation_with_elevation",
"budget_impact": 1
},
"islands_swamp": {
"display_name": "Islands Swamp",
"description": "Swampland dotted with multiple small dry islands and complex waterways",
"formation_type": "fragmented_water_saturation",
"budget_impact": 1
},
"hilly_swampy": {
"display_name": "Hilly Swampy",
"description": "Rolling terrain with marshy valleys and elevated dry ridges",
"formation_type": "terrain_drainage_pattern",
"budget_impact": 0
},
"river_source": {
"display_name": "River Source",
"description": "Origin point of a major river with strategic importance",
"formation_type": "groundwater_emergence",
"budget_impact": 2
},
"delta": {
"display_name": "River Delta",
"description": "Fertile river mouth area with rich sediment deposits",
"formation_type": "sediment_deposit",
"budget_impact": 2
},
"oasis": {
"display_name": "Oasis",
"description": "Isolated fertile spot in desert with precious water source",
"formation_type": "groundwater_emergence",
"budget_impact": 3
}
}
}

View File

@ -0,0 +1,40 @@
{
"zinc_resources": {
"sphalerite_deposit": {
"display_name": "Sphalerite Deposit",
"description": "Primary zinc sulfide ore with high zinc content and lead associations",
"formation_type": "sulfide_mineralization",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "high",
"quality": "standard"
},
"zinc_carbonate": {
"display_name": "Zinc Carbonate",
"description": "Oxidized zinc ore formed by weathering of sulfide deposits",
"formation_type": "zinc_oxidation_zone",
"extraction_difficulty": "easy",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
},
"franklinite_ore": {
"display_name": "Franklinite Ore",
"description": "Zinc-iron-manganese oxide mineral in metamorphic formations",
"formation_type": "metamorphic_oxide_formation",
"extraction_difficulty": "hard",
"budget_impact": 4,
"resource_yield": "medium",
"quality": "premium"
},
"willemite_deposit": {
"display_name": "Willemite Deposit",
"description": "Zinc silicate mineral with fluorescent properties under UV light",
"formation_type": "silicate_mineralization",
"extraction_difficulty": "medium",
"budget_impact": 3,
"resource_yield": "medium",
"quality": "standard"
}
}
}

View File

@ -0,0 +1,81 @@
{
"region_system_v3": {
"description": "Scalable blacklist + frequent biomes system with mass requirements",
"version": "3.0",
"revolutionary_simplification": {
"problem_solved": "Exponential complexity of biome compatibility (20 biomes × 50 features = 1000 combinations)",
"old_system": "compatible_biomes + incompatible_biomes + probability (redundant and massive)",
"new_system": "incompatible_biomes (blacklist) + frequent_biomes (priority) - NO probability"
},
"core_logic": {
"default_behavior": "All features available everywhere by default",
"blacklist_filtering": "incompatible_biomes = hard exclusions (geological impossibility)",
"priority_system": "frequent_biomes = higher priority/likelihood in these environments",
"mass_gating": "minimum_region_mass = geological strength requirements",
"selection_method": "Filter by mass + blacklist, then prioritize frequent biomes"
},
"workflow_example": {
"scenario": "Iron region (mass=200) placing feature in 'alpine' biome",
"step_1": "Filter by mass: rich_iron_ore (≥150✅), iron_ore_vein (≥75✅), bog_iron (≥10✅), etc.",
"step_2": "Filter by blacklist: remove bog_iron (alpine incompatible), keep rich_iron_ore + iron_ore_vein",
"step_3": "Check frequent biomes: rich_iron_ore has alpine in frequent_biomes → HIGH PRIORITY",
"step_4": "Result: rich_iron_ore selected (mass ok, not blacklisted, frequent in alpine)"
},
"scalability_advantages": {
"new_biome_addition": "Automatically compatible with all features except explicit blacklists",
"maintenance_load": "~3 blacklist entries per feature vs ~15+ whitelist entries",
"geological_logic": "Blacklist = impossible formations, frequent = optimal conditions",
"no_probability_management": "Eliminates probability balancing and normalization complexity"
},
"feature_examples": {
"rich_iron_ore": {
"incompatible_biomes": ["tropical_rainforest", "wetlands"],
"frequent_biomes": ["hills", "rocky_plateau", "alpine"],
"explanation": "Cannot form in tropical/wetland conditions, optimal in mountain/hill tectonics"
},
"laterite_iron": {
"incompatible_biomes": ["alpine", "cold_desert", "tundra", "hot_desert"],
"frequent_biomes": ["tropical_rainforest"],
"explanation": "Requires tropical weathering, impossible in cold/dry conditions"
},
"peat_bog": {
"incompatible_biomes": ["hot_desert", "cold_desert", "alpine", "rocky_plateau"],
"frequent_biomes": ["wetlands"],
"explanation": "Needs wetland accumulation, impossible in dry/rocky conditions"
}
},
"files_updated": {
"iron_regions.json": "7 features with blacklist+frequent system",
"copper_regions.json": "6 features with blacklist+frequent system",
"coal_regions.json": "6 features with blacklist+frequent system",
"oil_regions.json": "7 features with blacklist+frequent system",
"spatial_distribution_patterns.json": "5 random density patterns for regions"
},
"implementation_ready": {
"phase_8_integration": "System ready for world generation Phase 8",
"algorithm": [
"1. Region assigned random pattern (concentrated/uniform/ring/clustered/gradient)",
"2. Pattern determines density distribution within region radius",
"3. For each feature placement:",
"4. - Check region.mass >= feature.minimum_region_mass",
"5. - Check local_biome NOT IN feature.incompatible_biomes",
"6. - Prioritize features where local_biome IN feature.frequent_biomes",
"7. - Select from available features",
"8. - Place according to region density pattern"
]
},
"maintenance_metrics": {
"old_system": "1000+ compatibility combinations to maintain",
"new_system": "~200 blacklist entries total across all features",
"reduction_factor": "5x less maintenance, infinite scalability for new biomes"
}
}
}

View File

@ -0,0 +1,90 @@
{
"coal_region_system": {
"resource_type": "coal",
"description": "Coal feature selection based on region mass and biome compatibility",
"features": {
"rich_coal_seam": {
"display_name": "Rich Coal Seam",
"incompatible_biomes": ["hot_desert", "cold_desert", "alpine", "wetlands"],
"frequent_biomes": ["temperate_forest", "hills"],
"minimum_region_mass": 100,
"quality_base": "premium",
"extraction_difficulty": "medium",
"budget_impact": 4,
"description": "High-quality coal requiring substantial geological compression"
},
"coal_seam": {
"display_name": "Coal Seam",
"incompatible_biomes": ["hot_desert", "cold_desert", "alpine"],
"frequent_biomes": ["temperate_forest", "grassland", "hills"],
"minimum_region_mass": 50,
"quality_base": "standard",
"extraction_difficulty": "medium",
"budget_impact": 3,
"description": "Standard coal in medium-strength regions"
},
"coal_outcrop": {
"display_name": "Coal Outcrop",
"incompatible_biomes": ["hot_desert", "alpine", "tropical_rainforest"],
"frequent_biomes": ["temperate_forest", "grassland", "hills", "scrubland"],
"minimum_region_mass": 25,
"quality_base": "standard",
"extraction_difficulty": "easy",
"budget_impact": 2,
"description": "Surface coal accessible in small regions"
},
"surface_coal": {
"display_name": "Surface Coal",
"incompatible_biomes": ["hot_desert", "cold_desert", "alpine", "wetlands"],
"frequent_biomes": ["temperate_forest", "grassland", "scrubland"],
"minimum_region_mass": 15,
"quality_base": "low",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"description": "Weathered coal in small regions"
},
"lignite_deposit": {
"display_name": "Lignite Deposit",
"incompatible_biomes": ["hot_desert", "cold_desert", "alpine", "rocky_plateau"],
"frequent_biomes": ["temperate_forest", "grassland"],
"minimum_region_mass": 75,
"quality_base": "medium",
"extraction_difficulty": "medium",
"budget_impact": 2,
"description": "Brown coal in medium sedimentary regions"
},
"peat_bog": {
"display_name": "Peat Bog",
"incompatible_biomes": ["hot_desert", "cold_desert", "alpine", "rocky_plateau"],
"frequent_biomes": ["wetlands"],
"minimum_region_mass": 10,
"quality_base": "low",
"extraction_difficulty": "easy",
"budget_impact": 1,
"description": "Early coal formation in wetland environments"
}
},
"selection_logic": {
"step_1": "Check region mass against minimum_region_mass",
"step_2": "Filter out features with incompatible biomes",
"step_3": "Prioritize features with frequent biomes for this location",
"step_4": "Select from available features",
"fallback": "If no features available, place generic coal"
},
"mass_categories": {
"tiny_region": {"mass_range": [10, 25], "typical_features": ["peat_bog", "surface_coal"]},
"small_region": {"mass_range": [25, 50], "typical_features": ["coal_outcrop", "surface_coal"]},
"medium_region": {"mass_range": [50, 100], "typical_features": ["coal_seam", "lignite_deposit"]},
"large_region": {"mass_range": [100, 300], "typical_features": ["rich_coal_seam", "coal_seam"]},
"huge_region": {"mass_range": [300, 1000], "typical_features": ["rich_coal_seam"]}
}
}
}

View File

@ -0,0 +1,89 @@
{
"copper_region_system": {
"resource_type": "copper_ore",
"description": "Copper feature selection based on region mass and biome compatibility",
"features": {
"porphyry_copper": {
"display_name": "Porphyry Copper",
"incompatible_biomes": ["wetlands", "coastal_plain"],
"frequent_biomes": ["hills", "rocky_plateau", "alpine"],
"minimum_region_mass": 200,
"quality_base": "premium",
"extraction_difficulty": "hard",
"budget_impact": 5,
"description": "Large-scale copper system requiring massive geological activity"
},
"copper_vein": {
"display_name": "Copper Vein",
"incompatible_biomes": ["wetlands"],
"frequent_biomes": ["hills", "rocky_plateau", "alpine"],
"minimum_region_mass": 75,
"quality_base": "premium",
"extraction_difficulty": "medium",
"budget_impact": 4,
"description": "High-grade copper veins in medium-strength regions"
},
"chalcopyrite_deposit": {
"display_name": "Chalcopyrite Deposit",
"incompatible_biomes": ["wetlands", "tropical_rainforest"],
"frequent_biomes": ["hills", "temperate_forest", "grassland", "scrubland"],
"minimum_region_mass": 50,
"quality_base": "standard",
"extraction_difficulty": "medium",
"budget_impact": 3,
"description": "Standard copper sulfide in moderate regions"
},
"malachite_outcrop": {
"display_name": "Malachite Outcrop",
"incompatible_biomes": ["wetlands", "tropical_rainforest"],
"frequent_biomes": ["hills", "scrubland", "grassland"],
"minimum_region_mass": 30,
"quality_base": "standard",
"extraction_difficulty": "easy",
"budget_impact": 2,
"description": "Surface copper ore in small to medium regions"
},
"native_copper": {
"display_name": "Native Copper",
"incompatible_biomes": ["wetlands", "tropical_rainforest", "hot_desert"],
"frequent_biomes": ["rocky_plateau", "hills", "alpine"],
"minimum_region_mass": 100,
"quality_base": "premium",
"extraction_difficulty": "easy",
"budget_impact": 3,
"description": "Pure copper requiring specific geological conditions"
},
"copper_shale": {
"display_name": "Copper Shale",
"incompatible_biomes": ["wetlands", "alpine", "rocky_plateau"],
"frequent_biomes": ["grassland", "temperate_forest", "scrubland"],
"minimum_region_mass": 150,
"quality_base": "low",
"extraction_difficulty": "very_hard",
"budget_impact": 2,
"description": "Low-grade copper in large sedimentary regions"
}
},
"selection_logic": {
"step_1": "Check region mass against minimum_region_mass",
"step_2": "Filter out features with incompatible biomes",
"step_3": "Prioritize features with frequent biomes for this location",
"step_4": "Select from available features",
"fallback": "If no features available, place generic copper_ore"
},
"mass_categories": {
"small_region": {"mass_range": [30, 75], "typical_features": ["malachite_outcrop", "chalcopyrite_deposit"]},
"medium_region": {"mass_range": [75, 150], "typical_features": ["copper_vein", "chalcopyrite_deposit"]},
"large_region": {"mass_range": [150, 300], "typical_features": ["porphyry_copper", "copper_shale", "native_copper"]},
"huge_region": {"mass_range": [300, 1000], "typical_features": ["porphyry_copper", "copper_shale"]}
}
}
}

View File

@ -0,0 +1,80 @@
{
"gold_region_system": {
"resource_type": "gold_ore",
"description": "Gold deposit regions with biome-compatible feature selection",
"features": {
"gold_lode": {
"display_name": "Gold Lode",
"compatible_biomes": ["hills", "rocky_plateau", "alpine"],
"incompatible_biomes": ["wetlands", "coastal_plain"],
"pattern": "concentrated",
"probability": 0.25,
"quality_base": "premium",
"extraction_difficulty": "hard",
"budget_impact": 5,
"geological_requirements": ["hydrothermal_quartz_vein"]
},
"placer_gold": {
"display_name": "Placer Gold",
"compatible_biomes": ["temperate_forest", "grassland", "coastal_plain"],
"incompatible_biomes": ["alpine", "rocky_plateau", "hot_desert"],
"pattern": "clustered",
"probability": 0.30,
"quality_base": "premium",
"extraction_difficulty": "easy",
"budget_impact": 3,
"geological_requirements": ["alluvial_gold_concentration"]
},
"epithermal_gold": {
"display_name": "Epithermal Gold",
"compatible_biomes": ["hills", "scrubland", "temperate_forest"],
"incompatible_biomes": ["wetlands", "cold_desert"],
"pattern": "ring",
"probability": 0.20,
"quality_base": "premium",
"extraction_difficulty": "medium",
"budget_impact": 4,
"geological_requirements": ["epithermal_mineralization"]
},
"residual_gold": {
"display_name": "Residual Gold",
"compatible_biomes": ["hills", "scrubland", "grassland"],
"incompatible_biomes": ["wetlands", "alpine"],
"pattern": "gradient",
"probability": 0.15,
"quality_base": "premium",
"extraction_difficulty": "very_easy",
"budget_impact": 2,
"geological_requirements": ["weathering_concentration"]
},
"conglomerate_gold": {
"display_name": "Conglomerate Gold",
"compatible_biomes": ["hills", "rocky_plateau"],
"incompatible_biomes": ["wetlands", "coastal_plain", "tropical_rainforest"],
"pattern": "uniform",
"probability": 0.08,
"quality_base": "premium",
"extraction_difficulty": "very_hard",
"budget_impact": 4,
"geological_requirements": ["paleozoic_conglomerate"]
},
"sulfide_gold": {
"display_name": "Sulfide Gold",
"compatible_biomes": ["hills", "rocky_plateau", "alpine"],
"incompatible_biomes": ["wetlands", "coastal_plain"],
"pattern": "concentrated",
"probability": 0.02,
"quality_base": "standard",
"extraction_difficulty": "very_hard",
"budget_impact": 3,
"geological_requirements": ["sulfide_mineralization"]
}
}
}
}

View File

@ -0,0 +1,101 @@
{
"iron_region_system": {
"resource_type": "iron_ore",
"description": "Iron feature selection based on region mass and biome compatibility",
"features": {
"rich_iron_ore": {
"display_name": "Rich Iron Ore",
"incompatible_biomes": ["tropical_rainforest", "wetlands"],
"frequent_biomes": ["hills", "rocky_plateau", "alpine"],
"minimum_region_mass": 150,
"quality_base": "premium",
"extraction_difficulty": "medium",
"budget_impact": 4,
"description": "High-grade iron ore requiring strong geological activity"
},
"iron_ore_vein": {
"display_name": "Iron Ore Vein",
"incompatible_biomes": ["tropical_rainforest", "wetlands"],
"frequent_biomes": ["hills", "rocky_plateau", "alpine", "temperate_forest"],
"minimum_region_mass": 75,
"quality_base": "standard",
"extraction_difficulty": "medium",
"budget_impact": 3,
"description": "Standard iron ore in medium-strength regions"
},
"magnetite_deposit": {
"display_name": "Magnetite Deposit",
"incompatible_biomes": ["wetlands", "hot_desert"],
"frequent_biomes": ["hills", "rocky_plateau", "alpine"],
"minimum_region_mass": 50,
"quality_base": "premium",
"extraction_difficulty": "easy",
"budget_impact": 3,
"description": "Magnetic iron ore accessible in moderate regions"
},
"hematite_outcrop": {
"display_name": "Hematite Outcrop",
"incompatible_biomes": ["tropical_rainforest", "wetlands"],
"frequent_biomes": ["hills", "rocky_plateau", "grassland", "scrubland"],
"minimum_region_mass": 25,
"quality_base": "standard",
"extraction_difficulty": "easy",
"budget_impact": 2,
"description": "Surface iron ore available in small regions"
},
"laterite_iron": {
"display_name": "Laterite Iron",
"incompatible_biomes": ["alpine", "cold_desert", "tundra", "hot_desert"],
"frequent_biomes": ["tropical_rainforest"],
"minimum_region_mass": 30,
"quality_base": "medium",
"extraction_difficulty": "hard",
"budget_impact": 2,
"description": "Tropical weathering iron, specialized formation"
},
"bog_iron": {
"display_name": "Bog Iron",
"incompatible_biomes": ["hot_desert", "cold_desert", "alpine", "rocky_plateau"],
"frequent_biomes": ["wetlands"],
"minimum_region_mass": 10,
"quality_base": "low",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"description": "Low-grade iron in wetland environments"
},
"taconite": {
"display_name": "Taconite",
"incompatible_biomes": ["tropical_rainforest", "wetlands", "hot_desert"],
"frequent_biomes": ["hills", "rocky_plateau", "grassland"],
"minimum_region_mass": 200,
"quality_base": "low",
"extraction_difficulty": "hard",
"budget_impact": 2,
"description": "Low-grade iron requiring very large, stable regions"
}
},
"selection_logic": {
"step_1": "Check region mass against minimum_region_mass",
"step_2": "Filter out features with incompatible biomes",
"step_3": "Prioritize features with frequent biomes for this location",
"step_4": "Select from available features",
"fallback": "If no features available, place generic iron_ore"
},
"mass_categories": {
"tiny_region": {"mass_range": [10, 30], "typical_features": ["bog_iron", "laterite_iron"]},
"small_region": {"mass_range": [30, 75], "typical_features": ["hematite_outcrop", "magnetite_deposit"]},
"medium_region": {"mass_range": [75, 150], "typical_features": ["iron_ore_vein", "magnetite_deposit"]},
"large_region": {"mass_range": [150, 300], "typical_features": ["rich_iron_ore", "iron_ore_vein"]},
"huge_region": {"mass_range": [300, 1000], "typical_features": ["rich_iron_ore", "taconite"]}
}
}
}

View File

@ -0,0 +1,101 @@
{
"oil_region_system": {
"resource_type": "crude_oil",
"description": "Oil feature selection based on region mass and biome compatibility",
"features": {
"major_oil_field": {
"display_name": "Major Oil Field",
"incompatible_biomes": ["alpine", "rocky_plateau", "wetlands"],
"frequent_biomes": ["grassland", "scrubland", "hot_desert"],
"minimum_region_mass": 250,
"quality_base": "premium",
"extraction_difficulty": "hard",
"budget_impact": 5,
"description": "Large oil reservoirs requiring massive sedimentary basins"
},
"oil_well": {
"display_name": "Oil Well",
"incompatible_biomes": ["alpine", "wetlands"],
"frequent_biomes": ["grassland", "temperate_forest", "scrubland"],
"minimum_region_mass": 75,
"quality_base": "standard",
"extraction_difficulty": "medium",
"budget_impact": 4,
"description": "Standard oil deposits in medium regions"
},
"shallow_oil_pocket": {
"display_name": "Shallow Oil Pocket",
"incompatible_biomes": ["alpine", "wetlands"],
"frequent_biomes": ["grassland", "temperate_forest", "scrubland", "hills"],
"minimum_region_mass": 30,
"quality_base": "standard",
"extraction_difficulty": "easy",
"budget_impact": 3,
"description": "Surface-near oil accessible in small regions"
},
"oil_seep": {
"display_name": "Oil Seep",
"incompatible_biomes": ["alpine", "cold_desert", "wetlands"],
"frequent_biomes": ["grassland", "scrubland", "temperate_forest"],
"minimum_region_mass": 15,
"quality_base": "medium",
"extraction_difficulty": "very_easy",
"budget_impact": 2,
"description": "Natural oil emergence in tiny regions"
},
"offshore_oil": {
"display_name": "Offshore Oil",
"incompatible_biomes": ["hills", "rocky_plateau", "alpine", "hot_desert"],
"frequent_biomes": ["coastal_plain"],
"minimum_region_mass": 150,
"quality_base": "premium",
"extraction_difficulty": "very_hard",
"budget_impact": 4,
"description": "Marine oil deposits in coastal regions"
},
"tar_sands": {
"display_name": "Tar Sands",
"incompatible_biomes": ["alpine", "hot_desert", "wetlands"],
"frequent_biomes": ["grassland", "temperate_forest"],
"minimum_region_mass": 200,
"quality_base": "low",
"extraction_difficulty": "very_hard",
"budget_impact": 3,
"description": "Heavy oil requiring large sedimentary systems"
},
"shale_oil": {
"display_name": "Shale Oil",
"incompatible_biomes": ["alpine", "wetlands", "tropical_rainforest"],
"frequent_biomes": ["grassland", "scrubland"],
"minimum_region_mass": 100,
"quality_base": "medium",
"extraction_difficulty": "very_hard",
"budget_impact": 3,
"description": "Unconventional oil in shale formations"
}
},
"selection_logic": {
"step_1": "Check region mass against minimum_region_mass",
"step_2": "Filter out features with incompatible biomes",
"step_3": "Prioritize features with frequent biomes for this location",
"step_4": "Select from available features",
"fallback": "If no features available, place generic oil_seep"
},
"mass_categories": {
"tiny_region": {"mass_range": [15, 30], "typical_features": ["oil_seep"]},
"small_region": {"mass_range": [30, 75], "typical_features": ["shallow_oil_pocket", "oil_seep"]},
"medium_region": {"mass_range": [75, 150], "typical_features": ["oil_well", "shale_oil"]},
"large_region": {"mass_range": [150, 300], "typical_features": ["major_oil_field", "offshore_oil", "tar_sands"]},
"huge_region": {"mass_range": [300, 1000], "typical_features": ["major_oil_field", "tar_sands"]}
}
}
}

View File

@ -0,0 +1,73 @@
{
"region_density_patterns": {
"version": "2.0",
"description": "Density distribution patterns within resource regions - randomly assigned per region",
"available_patterns": [
"concentrated",
"uniform",
"ring",
"clustered",
"gradient"
],
"pattern_definitions": {
"concentrated": {
"description": "High feature density near region center, low at edges",
"density_center": 1.0,
"density_edge": 0.2,
"effective_radius_percent": 50,
"use_cases": "Rich ore bodies, primary deposits"
},
"uniform": {
"description": "Equal feature density throughout entire region",
"density_center": 1.0,
"density_edge": 1.0,
"effective_radius_percent": 100,
"use_cases": "Sedimentary layers, widespread deposits"
},
"ring": {
"description": "Feature density concentrated in annular zone",
"density_center": 0.1,
"density_ring_start": 0.6,
"density_ring_peak": 1.0,
"density_edge": 0.3,
"use_cases": "Contact metamorphism, intrusion margins"
},
"clustered": {
"description": "Multiple high-density sub-zones within region",
"cluster_count": {"min": 2, "max": 4},
"density_in_cluster": 1.0,
"density_between_clusters": 0.2,
"use_cases": "Pod formations, scattered deposits"
},
"gradient": {
"description": "Smooth density decrease from center to edge",
"density_center": 1.0,
"density_edge": 0.4,
"gradient_function": "logarithmic",
"use_cases": "Diffusion halos, weathering profiles"
}
},
"pattern_assignment": {
"method": "random_selection",
"equal_probability": true,
"description": "Each region gets a random pattern from available_patterns"
},
"feature_placement_workflow": {
"1": "Region created with random pattern",
"2": "Pattern determines density distribution within region",
"3": "For each tile needing feature placement:",
"4": " - Check region mass (strength)",
"5": " - Check local biome",
"6": " - Select compatible feature based on mass + biome",
"7": " - Place feature if density allows"
}
}
}

View File

@ -0,0 +1,92 @@
{
"stone_region_system": {
"resource_type": "construction_materials",
"description": "Construction stone regions with biome-compatible feature selection",
"features": {
"granite_quarry": {
"display_name": "Granite Quarry",
"compatible_biomes": ["hills", "rocky_plateau", "alpine"],
"incompatible_biomes": ["wetlands", "coastal_plain"],
"pattern": "concentrated",
"probability": 0.20,
"quality_base": "premium",
"extraction_difficulty": "hard",
"budget_impact": 4,
"geological_requirements": ["plutonic_igneous_intrusion"]
},
"limestone_quarry": {
"display_name": "Limestone Quarry",
"compatible_biomes": ["hills", "grassland", "temperate_forest"],
"incompatible_biomes": ["alpine", "hot_desert"],
"pattern": "uniform",
"probability": 0.25,
"quality_base": "standard",
"extraction_difficulty": "medium",
"budget_impact": 3,
"geological_requirements": ["marine_carbonate_precipitation"]
},
"sandstone_quarry": {
"display_name": "Sandstone Quarry",
"compatible_biomes": ["grassland", "scrubland", "temperate_forest"],
"incompatible_biomes": ["alpine", "wetlands"],
"pattern": "uniform",
"probability": 0.20,
"quality_base": "standard",
"extraction_difficulty": "easy",
"budget_impact": 2,
"geological_requirements": ["clastic_sedimentary_formation"]
},
"marble_deposit": {
"display_name": "Marble Deposit",
"compatible_biomes": ["hills", "rocky_plateau"],
"incompatible_biomes": ["wetlands", "coastal_plain", "hot_desert"],
"pattern": "concentrated",
"probability": 0.10,
"quality_base": "premium",
"extraction_difficulty": "hard",
"budget_impact": 4,
"geological_requirements": ["limestone_metamorphism"]
},
"clay_pit": {
"display_name": "Clay Pit",
"compatible_biomes": ["temperate_forest", "grassland", "coastal_plain"],
"incompatible_biomes": ["alpine", "rocky_plateau", "hot_desert"],
"pattern": "uniform",
"probability": 0.15,
"quality_base": "standard",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"geological_requirements": ["weathering_accumulation"]
},
"sand_deposit": {
"display_name": "Sand Deposit",
"compatible_biomes": ["coastal_plain", "grassland", "scrubland"],
"incompatible_biomes": ["alpine", "rocky_plateau"],
"pattern": "uniform",
"probability": 0.08,
"quality_base": "standard",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"geological_requirements": ["weathering_erosion_accumulation"]
},
"gravel_pit": {
"display_name": "Gravel Pit",
"compatible_biomes": ["temperate_forest", "grassland", "hills"],
"incompatible_biomes": ["hot_desert", "wetlands"],
"pattern": "clustered",
"probability": 0.02,
"quality_base": "standard",
"extraction_difficulty": "very_easy",
"budget_impact": 1,
"geological_requirements": ["fluvial_glacial_accumulation"]
}
}
}
}

View File

@ -0,0 +1,68 @@
{
"uranium_region_system": {
"resource_type": "uranium_ore",
"description": "Uranium deposit regions with biome-compatible feature selection",
"features": {
"pitchblende_vein": {
"display_name": "Pitchblende Vein",
"compatible_biomes": ["hills", "rocky_plateau", "cold_desert"],
"incompatible_biomes": ["wetlands", "tropical_rainforest", "coastal_plain"],
"pattern": "concentrated",
"probability": 0.25,
"quality_base": "premium",
"extraction_difficulty": "very_hard",
"budget_impact": 6,
"geological_requirements": ["hydrothermal_uranium_concentration"]
},
"uranium_roll_front": {
"display_name": "Uranium Roll Front",
"compatible_biomes": ["grassland", "scrubland", "cold_desert"],
"incompatible_biomes": ["wetlands", "alpine", "tropical_rainforest"],
"pattern": "ring",
"probability": 0.30,
"quality_base": "standard",
"extraction_difficulty": "hard",
"budget_impact": 4,
"geological_requirements": ["groundwater_uranium_precipitation"]
},
"carnotite_deposit": {
"display_name": "Carnotite Deposit",
"compatible_biomes": ["scrubland", "cold_desert", "grassland"],
"incompatible_biomes": ["wetlands", "tropical_rainforest", "temperate_forest"],
"pattern": "uniform",
"probability": 0.25,
"quality_base": "standard",
"extraction_difficulty": "medium",
"budget_impact": 3,
"geological_requirements": ["sedimentary_uranium_vanadium"]
},
"uraninite_placer": {
"display_name": "Uraninite Placer",
"compatible_biomes": ["grassland", "scrubland"],
"incompatible_biomes": ["wetlands", "alpine", "tropical_rainforest"],
"pattern": "clustered",
"probability": 0.15,
"quality_base": "premium",
"extraction_difficulty": "medium",
"budget_impact": 3,
"geological_requirements": ["alluvial_uranium_concentration"]
},
"phosphate_uranium": {
"display_name": "Phosphate Uranium",
"compatible_biomes": ["grassland", "scrubland", "coastal_plain"],
"incompatible_biomes": ["alpine", "rocky_plateau"],
"pattern": "uniform",
"probability": 0.05,
"quality_base": "low",
"extraction_difficulty": "very_hard",
"budget_impact": 2,
"geological_requirements": ["phosphate_uranium_association"]
}
}
}
}

View File

@ -0,0 +1,86 @@
{
"sulfur": {
"name": "Sulfur",
"category": "basic_chemical",
"logistic_category": "resource",
"density": 2.1,
"stack_size": 100,
"container_type": "chemical_powder",
"ui": {
"icon": "sulfur.png",
"color": "#FFFF00",
"map_color": "#FFD700",
"particle_effect": "sulfur_dust"
}
},
"phosphorus": {
"name": "Phosphorus",
"category": "reactive_chemical",
"logistic_category": "resource",
"density": 1.8,
"stack_size": 50,
"container_type": "reactive_chemical",
"ui": {
"icon": "phosphorus.png",
"color": "#FF4500",
"map_color": "#FF6347",
"particle_effect": "phosphorus_glow"
}
},
"potassium": {
"name": "Potassium",
"category": "alkali_metal",
"logistic_category": "resource",
"density": 0.9,
"stack_size": 25,
"container_type": "reactive_metal",
"ui": {
"icon": "potassium.png",
"color": "#C0C0C0",
"map_color": "#A9A9A9",
"particle_effect": "metallic_shine"
}
},
"sodium": {
"name": "Sodium",
"category": "alkali_metal",
"logistic_category": "resource",
"density": 1.0,
"stack_size": 25,
"container_type": "reactive_metal",
"ui": {
"icon": "sodium.png",
"color": "#D3D3D3",
"map_color": "#DCDCDC",
"particle_effect": "sodium_shine"
}
},
"magnesium": {
"name": "Magnesium",
"category": "alkaline_earth_metal",
"logistic_category": "resource",
"density": 1.7,
"stack_size": 50,
"container_type": "light_metal",
"ui": {
"icon": "magnesium.png",
"color": "#F5F5F5",
"map_color": "#E0E0E0",
"particle_effect": "bright_metallic_dust"
}
},
"calcium": {
"name": "Calcium",
"category": "alkaline_earth_metal",
"logistic_category": "resource",
"density": 1.5,
"stack_size": 50,
"container_type": "reactive_metal",
"ui": {
"icon": "calcium.png",
"color": "#FFFAF0",
"map_color": "#F0F8FF",
"particle_effect": "calcium_dust"
}
}
}

View File

@ -0,0 +1,82 @@
{
"quartz_crystal": {
"name": "Quartz Crystal",
"category": "silicon_crystal",
"logistic_category": "resource",
"density": 2.6,
"stack_size": 25,
"container_type": "crystal_material",
"hardness_mohs": 7,
"processing_note": "Essential for electronics and optics",
"ui": {
"icon": "quartz_crystal.png",
"color": "#F5F5F5",
"map_color": "#E0E0E0",
"particle_effect": "crystal_sparkle"
}
},
"micro_diamonds": {
"name": "Micro Diamonds",
"category": "precious_crystal",
"logistic_category": "resource",
"density": 3.5,
"stack_size": 5,
"container_type": "precious_material",
"hardness_mohs": 10,
"processing_note": "Industrial grade diamonds for cutting tools",
"ui": {
"icon": "micro_diamonds.png",
"color": "#E0E0E0",
"map_color": "#FFFFFF",
"particle_effect": "diamond_sparkle"
}
},
"volcanic_glass": {
"name": "Volcanic Glass",
"category": "natural_glass",
"logistic_category": "resource",
"density": 2.4,
"stack_size": 25,
"container_type": "glass_material",
"hardness_mohs": 5.5,
"processing_note": "Natural glass formed by rapid cooling",
"ui": {
"icon": "volcanic_glass.png",
"color": "#000000",
"map_color": "#2F2F2F",
"particle_effect": "glass_reflection"
}
},
"magnetite": {
"name": "Magnetite",
"category": "magnetic_mineral",
"logistic_category": "resource",
"density": 5.2,
"stack_size": 50,
"container_type": "magnetic_ore",
"magnetic_strength": "strong_natural",
"processing_note": "Naturally magnetic iron oxide",
"ui": {
"icon": "magnetite.png",
"color": "#2F4F4F",
"map_color": "#708090",
"particle_effect": "magnetic_field"
}
},
"rare_earth_magnets": {
"name": "Rare Earth Magnets",
"category": "advanced_magnetic",
"logistic_category": "resource",
"density": 8.1,
"stack_size": 10,
"container_type": "magnetic_material",
"magnetic_strength": "extremely_strong",
"processing_note": "Neodymium-iron-boron permanent magnets",
"ui": {
"icon": "rare_earth_magnets.png",
"color": "#4169E1",
"map_color": "#0000FF",
"particle_effect": "strong_magnetic_field"
}
}
}

View File

@ -0,0 +1,108 @@
{
"coal": {
"name": "Coal",
"category": "fossil_fuel",
"logistic_category": "resource",
"density": 1.3,
"stack_size": 100,
"container_type": "bulk_fuel",
"energy_content_mj": 25,
"ui": {
"icon": "coal.png",
"color": "#2F2F2F",
"map_color": "#1C1C1C",
"particle_effect": "coal_dust"
}
},
"crude_oil": {
"name": "Crude Oil",
"category": "liquid_fuel",
"logistic_category": "fluid",
"density": 0.85,
"stack_size": 0,
"container_type": "liquid_fuel",
"energy_content_mj": 42,
"ui": {
"icon": "crude_oil.png",
"color": "#2F2F2F",
"map_color": "#000000",
"particle_effect": "oil_drops"
}
},
"natural_gas": {
"name": "Natural Gas",
"category": "gaseous_fuel",
"logistic_category": "fluid",
"density": 0.0007,
"stack_size": 0,
"container_type": "pressurized_gas",
"energy_content_mj": 55,
"ui": {
"icon": "natural_gas.png",
"color": "#B0E0E6",
"map_color": "#87CEEB",
"particle_effect": "gas_wisps"
}
},
"uranium_235": {
"name": "Uranium-235",
"category": "fissile_fuel",
"logistic_category": "resource",
"density": 19.1,
"stack_size": 1,
"container_type": "fissile_material",
"energy_content_mj": 80000000,
"ui": {
"icon": "uranium_235.png",
"color": "#00FF00",
"map_color": "#32CD32",
"particle_effect": "uranium_glow"
}
},
"uranium_ore": {
"name": "Uranium Ore",
"category": "radioactive_ore",
"logistic_category": "resource",
"density": 19.1,
"stack_size": 10,
"container_type": "radioactive_ore",
"processing_note": "Requires enrichment to produce Uranium-235",
"ui": {
"icon": "uranium_ore.png",
"color": "#FFFF00",
"map_color": "#FFD700",
"particle_effect": "uranium_glow"
}
},
"thorium_ore": {
"name": "Thorium Ore",
"category": "radioactive_ore",
"logistic_category": "resource",
"density": 11.7,
"stack_size": 15,
"container_type": "radioactive_ore",
"processing_note": "Alternative nuclear fuel, requires breeder reactor",
"ui": {
"icon": "thorium_ore.png",
"color": "#C0C0C0",
"map_color": "#A9A9A9",
"particle_effect": "thorium_radiation"
}
},
"plutonium": {
"name": "Plutonium",
"category": "fissile_material",
"logistic_category": "resource",
"density": 19.8,
"stack_size": 1,
"container_type": "fissile_material",
"energy_content_mj": 87000000,
"processing_note": "Weapons-grade nuclear material",
"ui": {
"icon": "plutonium.png",
"color": "#8B0000",
"map_color": "#FF0000",
"particle_effect": "plutonium_energy"
}
}
}

View File

@ -0,0 +1,81 @@
{
"rare_earth_elements": {
"name": "Rare Earth Elements",
"category": "exotic_material",
"logistic_category": "resource",
"density": 7.2,
"stack_size": 5,
"container_type": "exotic_material",
"rarity": "very_rare",
"ui": {
"icon": "rare_earth_elements.png",
"color": "#FF69B4",
"map_color": "#FF1493",
"particle_effect": "rare_earth_glow"
}
},
"unknown_minerals": {
"name": "Unknown Minerals",
"category": "xenomaterial",
"logistic_category": "resource",
"density": 12.0,
"stack_size": 1,
"container_type": "xenomaterial",
"rarity": "legendary",
"processing_note": "Composition defies known physics",
"ui": {
"icon": "unknown_minerals.png",
"color": "#8A2BE2",
"map_color": "#9400D3",
"particle_effect": "xenomineral_aura"
}
},
"unknown_isotopes": {
"name": "Unknown Isotopes",
"category": "exotic_radioactive",
"logistic_category": "resource",
"density": 15.8,
"stack_size": 1,
"container_type": "hazmat_container",
"rarity": "legendary",
"processing_note": "Isotopes not found in periodic table",
"ui": {
"icon": "unknown_isotopes.png",
"color": "#FF0000",
"map_color": "#DC143C",
"particle_effect": "isotope_radiation"
}
},
"mystery_inclusions": {
"name": "Mystery Inclusions",
"category": "unknown_material",
"logistic_category": "resource",
"density": 8.5,
"stack_size": 1,
"container_type": "anomalous_material",
"rarity": "artifact",
"processing_note": "Origin and purpose unknown",
"ui": {
"icon": "mystery_inclusions.png",
"color": "#8B008B",
"map_color": "#9932CC",
"particle_effect": "mystery_sparkle"
}
},
"rare_earth_metals": {
"name": "Rare Earth Metals",
"category": "high_tech_material",
"logistic_category": "resource",
"density": 6.8,
"stack_size": 10,
"container_type": "specialized_alloy",
"rarity": "rare",
"processing_note": "Essential for advanced electronics",
"ui": {
"icon": "rare_earth_metals.png",
"color": "#DA70D6",
"map_color": "#BA55D3",
"particle_effect": "tech_shimmer"
}
}
}

View File

@ -0,0 +1,93 @@
{
"wood": {
"name": "Wood",
"category": "biomass",
"logistic_category": "resource",
"density": 0.6,
"stack_size": 100,
"container_type": "organic_material",
"renewable": true,
"ui": {
"icon": "wood.png",
"color": "#8B4513",
"map_color": "#A0522D",
"particle_effect": "wood_chips"
}
},
"rubber": {
"name": "Rubber",
"category": "elastic_polymer",
"logistic_category": "resource",
"density": 0.9,
"stack_size": 50,
"container_type": "polymer_material",
"renewable": true,
"ui": {
"icon": "rubber.png",
"color": "#2F2F2F",
"map_color": "#1C1C1C",
"particle_effect": "rubber_bits"
}
},
"organic_compounds": {
"name": "Organic Compounds",
"category": "biological_material",
"logistic_category": "resource",
"density": 1.2,
"stack_size": 50,
"container_type": "organic_material",
"processing_note": "Complex carbon-based molecules from space",
"ui": {
"icon": "organic_compounds.png",
"color": "#228B22",
"map_color": "#32CD32",
"particle_effect": "organic_particles"
}
},
"plastic_waste": {
"name": "Plastic Waste",
"category": "recyclable_polymer",
"logistic_category": "resource",
"density": 1.1,
"stack_size": 100,
"container_type": "waste_material",
"recyclable": true,
"ui": {
"icon": "plastic_waste.png",
"color": "#FF69B4",
"map_color": "#FF1493",
"particle_effect": "plastic_fragments"
}
},
"electronic_scrap": {
"name": "Electronic Scrap",
"category": "tech_waste",
"logistic_category": "resource",
"density": 3.5,
"stack_size": 50,
"container_type": "electronic_waste",
"recyclable": true,
"processing_note": "Contains valuable metals and rare earth elements",
"ui": {
"icon": "electronic_scrap.png",
"color": "#32CD32",
"map_color": "#228B22",
"particle_effect": "circuit_sparks"
}
},
"metal_scrap": {
"name": "Metal Scrap",
"category": "recyclable_metal",
"logistic_category": "resource",
"density": 4.5,
"stack_size": 100,
"container_type": "scrap_metal",
"recyclable": true,
"ui": {
"icon": "metal_scrap.png",
"color": "#708090",
"map_color": "#2F4F4F",
"particle_effect": "metal_shavings"
}
}
}

View File

@ -0,0 +1,257 @@
{
"iron_ore": {
"name": "Iron Ore",
"category": "basic_metal",
"logistic_category": "resource",
"density": 5.2,
"melting_point_celsius": 1538,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "iron_ore.png",
"color": "#8B4513",
"map_color": "#654321",
"particle_effect": "metallic_dust"
}
},
"copper_ore": {
"name": "Copper Ore",
"category": "basic_metal",
"logistic_category": "resource",
"density": 4.8,
"melting_point_celsius": 1085,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "copper_ore.png",
"color": "#CD7F32",
"map_color": "#B87333",
"particle_effect": "metallic_dust"
}
},
"aluminum_ore": {
"name": "Aluminum Ore (Bauxite)",
"category": "basic_metal",
"logistic_category": "resource",
"density": 2.8,
"melting_point_celsius": 660,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "bauxite.png",
"color": "#CD853F",
"map_color": "#D2691E",
"particle_effect": "clay_dust"
}
},
"zinc_ore": {
"name": "Zinc Ore",
"category": "basic_metal",
"logistic_category": "resource",
"density": 4.2,
"melting_point_celsius": 420,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "zinc_ore.png",
"color": "#A8A8A8",
"map_color": "#DCDCDC",
"particle_effect": "metallic_dust"
}
},
"tin_ore": {
"name": "Tin Ore",
"category": "basic_metal",
"logistic_category": "resource",
"density": 4.5,
"melting_point_celsius": 232,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "tin_ore.png",
"color": "#C0C0C0",
"map_color": "#B8860B",
"particle_effect": "metallic_dust"
}
},
"lead_ore": {
"name": "Lead Ore",
"category": "basic_metal",
"logistic_category": "resource",
"density": 6.8,
"melting_point_celsius": 327,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "lead_ore.png",
"color": "#708090",
"map_color": "#696969",
"particle_effect": "heavy_dust"
}
},
"nickel_ore": {
"name": "Nickel Ore",
"category": "advanced_metal",
"logistic_category": "resource",
"density": 5.6,
"melting_point_celsius": 1455,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "nickel_ore.png",
"color": "#C0C0C0",
"map_color": "#A9A9A9",
"particle_effect": "metallic_dust"
}
},
"chromium_ore": {
"name": "Chromium Ore",
"category": "advanced_metal",
"logistic_category": "resource",
"density": 3.8,
"melting_point_celsius": 1907,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "chromium_ore.png",
"color": "#708090",
"map_color": "#778899",
"particle_effect": "metallic_dust"
}
},
"antimony_ore": {
"name": "Antimony Ore",
"category": "advanced_metal",
"logistic_category": "resource",
"density": 4.6,
"melting_point_celsius": 631,
"stack_size": 50,
"container_type": "metal_ore",
"ui": {
"icon": "antimony_ore.png",
"color": "#A8A8A8",
"map_color": "#C0C0C0",
"particle_effect": "metallic_dust"
}
},
"gold_ore": {
"name": "Gold Ore",
"category": "precious_metal",
"logistic_category": "resource",
"density": 8.9,
"melting_point_celsius": 1064,
"stack_size": 25,
"container_type": "precious_ore",
"ui": {
"icon": "gold_ore.png",
"color": "#FFD700",
"map_color": "#DAA520",
"particle_effect": "precious_dust"
}
},
"silver_ore": {
"name": "Silver Ore",
"category": "precious_metal",
"logistic_category": "resource",
"density": 6.1,
"melting_point_celsius": 962,
"stack_size": 25,
"container_type": "precious_ore",
"ui": {
"icon": "silver_ore.png",
"color": "#C0C0C0",
"map_color": "#E6E6FA",
"particle_effect": "precious_dust"
}
},
"platinum_ore": {
"name": "Platinum Ore",
"category": "precious_metal",
"logistic_category": "resource",
"density": 9.8,
"melting_point_celsius": 1768,
"stack_size": 10,
"container_type": "precious_ore",
"ui": {
"icon": "platinum_ore.png",
"color": "#E5E4E2",
"map_color": "#B0C4DE",
"particle_effect": "precious_dust"
}
},
"titanium_ore": {
"name": "Titanium Ore",
"category": "rare_metal",
"logistic_category": "resource",
"density": 3.2,
"melting_point_celsius": 1668,
"stack_size": 25,
"container_type": "metal_ore",
"ui": {
"icon": "titanium_ore.png",
"color": "#D3D3D3",
"map_color": "#B0C4DE",
"particle_effect": "light_metallic_dust"
}
},
"tungsten_ore": {
"name": "Tungsten Ore",
"category": "rare_metal",
"logistic_category": "resource",
"density": 8.2,
"melting_point_celsius": 3414,
"stack_size": 25,
"container_type": "metal_ore",
"ui": {
"icon": "tungsten_ore.png",
"color": "#696969",
"map_color": "#2F4F4F",
"particle_effect": "heavy_metallic_dust"
}
},
"iridium_ore": {
"name": "Iridium Ore",
"category": "rare_metal",
"logistic_category": "resource",
"density": 11.2,
"melting_point_celsius": 2466,
"stack_size": 5,
"container_type": "precious_ore",
"ui": {
"icon": "iridium_ore.png",
"color": "#F8F8FF",
"map_color": "#E6E6FA",
"particle_effect": "rare_dust"
}
},
"lithium": {
"name": "Lithium",
"category": "alkali_metal",
"logistic_category": "resource",
"density": 0.5,
"melting_point_celsius": 181,
"stack_size": 25,
"container_type": "light_metal",
"ui": {
"icon": "lithium.png",
"color": "#F0F8FF",
"map_color": "#E6E6FA",
"particle_effect": "light_metallic_dust"
}
},
"cobalt": {
"name": "Cobalt",
"category": "strategic_metal",
"logistic_category": "resource",
"density": 8.9,
"melting_point_celsius": 1495,
"stack_size": 25,
"container_type": "metal_ore",
"ui": {
"icon": "cobalt.png",
"color": "#0047AB",
"map_color": "#4169E1",
"particle_effect": "blue_metallic_dust"
}
}
}

View File

@ -0,0 +1,280 @@
{
"stone": {
"name": "Stone",
"category": "basic_rock",
"logistic_category": "resource",
"density": 2.5,
"melting_point_celsius": 1200,
"stack_size": 100,
"container_type": "bulk_solid",
"ui": {
"icon": "stone.png",
"color": "#808080",
"map_color": "#696969",
"particle_effect": "stone_dust"
}
},
"silicate_rock": {
"name": "Silicate Rock",
"category": "meteorite_material",
"logistic_category": "resource",
"density": 2.8,
"melting_point_celsius": 1400,
"stack_size": 50,
"container_type": "bulk_solid",
"ui": {
"icon": "silicate_rock.png",
"color": "#A0522D",
"map_color": "#8B4513",
"particle_effect": "rock_dust"
}
},
"cosmic_dust": {
"name": "Cosmic Dust",
"category": "meteorite_material",
"logistic_category": "resource",
"density": 1.2,
"melting_point_celsius": 1100,
"stack_size": 25,
"container_type": "fine_powder",
"ui": {
"icon": "cosmic_dust.png",
"color": "#C0C0C0",
"map_color": "#A9A9A9",
"particle_effect": "fine_dust"
}
},
"carbon_matrix": {
"name": "Carbon Matrix",
"category": "meteorite_material",
"logistic_category": "resource",
"density": 1.8,
"melting_point_celsius": 3550,
"stack_size": 25,
"container_type": "carbon_solid",
"ui": {
"icon": "carbon_matrix.png",
"color": "#2F4F4F",
"map_color": "#36454F",
"particle_effect": "carbon_dust"
}
},
"pumice_like_rock": {
"name": "Pumice-like Rock",
"category": "meteorite_material",
"logistic_category": "resource",
"density": 0.6,
"melting_point_celsius": 1200,
"stack_size": 50,
"container_type": "light_rock",
"ui": {
"icon": "pumice_rock.png",
"color": "#D3D3D3",
"map_color": "#DCDCDC",
"particle_effect": "light_dust"
}
},
"silicate_foam": {
"name": "Silicate Foam",
"category": "meteorite_material",
"logistic_category": "resource",
"density": 0.4,
"melting_point_celsius": 1400,
"stack_size": 50,
"container_type": "foam_material",
"ui": {
"icon": "silicate_foam.png",
"color": "#F5F5F5",
"map_color": "#E0E0E0",
"particle_effect": "foam_particles"
}
},
"granite": {
"name": "Granite",
"category": "construction_rock",
"logistic_category": "resource",
"density": 2.7,
"melting_point_celsius": 1260,
"stack_size": 100,
"container_type": "bulk_solid",
"ui": {
"icon": "granite.png",
"color": "#708090",
"map_color": "#778899",
"particle_effect": "stone_dust"
}
},
"limestone": {
"name": "Limestone",
"category": "construction_rock",
"logistic_category": "resource",
"density": 2.3,
"melting_point_celsius": 825,
"stack_size": 100,
"container_type": "bulk_solid",
"ui": {
"icon": "limestone.png",
"color": "#F5F5DC",
"map_color": "#F0E68C",
"particle_effect": "limestone_dust"
}
},
"sandstone": {
"name": "Sandstone",
"category": "construction_rock",
"logistic_category": "resource",
"density": 2.2,
"melting_point_celsius": 1713,
"stack_size": 100,
"container_type": "bulk_solid",
"ui": {
"icon": "sandstone.png",
"color": "#F4A460",
"map_color": "#DEB887",
"particle_effect": "sand_dust"
}
},
"marble": {
"name": "Marble",
"category": "construction_rock",
"logistic_category": "resource",
"density": 2.7,
"stack_size": 50,
"container_type": "stone_block",
"ui": {
"icon": "marble.png",
"color": "#F8F8FF",
"map_color": "#E6E6FA",
"particle_effect": "fine_stone_dust"
}
},
"clay": {
"name": "Clay",
"category": "sedimentary_rock",
"logistic_category": "resource",
"density": 1.9,
"stack_size": 100,
"container_type": "clay_material",
"ui": {
"icon": "clay.png",
"color": "#CD853F",
"map_color": "#D2691E",
"particle_effect": "clay_dust"
}
},
"sand": {
"name": "Sand",
"category": "sedimentary_rock",
"logistic_category": "resource",
"density": 1.5,
"stack_size": 100,
"container_type": "fine_granules",
"ui": {
"icon": "sand.png",
"color": "#F4A460",
"map_color": "#DEB887",
"particle_effect": "sand_particles"
}
},
"gravel": {
"name": "Gravel",
"category": "sedimentary_rock",
"logistic_category": "resource",
"density": 1.8,
"stack_size": 100,
"container_type": "coarse_granules",
"ui": {
"icon": "gravel.png",
"color": "#696969",
"map_color": "#808080",
"particle_effect": "gravel_dust"
}
},
"obsidian": {
"name": "Obsidian",
"category": "volcanic_rock",
"logistic_category": "resource",
"density": 2.4,
"melting_point_celsius": 1100,
"stack_size": 25,
"container_type": "glass_rock",
"ui": {
"icon": "obsidian.png",
"color": "#000000",
"map_color": "#2F2F2F",
"particle_effect": "glass_shards"
}
},
"basalt": {
"name": "Basalt",
"category": "volcanic_rock",
"logistic_category": "resource",
"density": 3.0,
"melting_point_celsius": 1200,
"stack_size": 100,
"container_type": "volcanic_rock",
"ui": {
"icon": "basalt.png",
"color": "#2F4F4F",
"map_color": "#36454F",
"particle_effect": "volcanic_dust"
}
},
"pumice": {
"name": "Pumice",
"category": "volcanic_rock",
"logistic_category": "resource",
"density": 0.9,
"melting_point_celsius": 1200,
"stack_size": 100,
"container_type": "light_rock",
"ui": {
"icon": "pumice.png",
"color": "#D3D3D3",
"map_color": "#DCDCDC",
"particle_effect": "light_volcanic_dust"
}
},
"slate": {
"name": "Slate",
"category": "metamorphic_rock",
"logistic_category": "resource",
"density": 2.8,
"stack_size": 50,
"container_type": "layered_rock",
"ui": {
"icon": "slate.png",
"color": "#708090",
"map_color": "#2F4F4F",
"particle_effect": "slate_chips"
}
},
"quartzite": {
"name": "Quartzite",
"category": "metamorphic_rock",
"logistic_category": "resource",
"density": 2.6,
"stack_size": 50,
"container_type": "hard_rock",
"ui": {
"icon": "quartzite.png",
"color": "#F5F5F5",
"map_color": "#E0E0E0",
"particle_effect": "quartz_dust"
}
},
"gneiss": {
"name": "Gneiss",
"category": "metamorphic_rock",
"logistic_category": "resource",
"density": 2.7,
"stack_size": 50,
"container_type": "banded_rock",
"ui": {
"icon": "gneiss.png",
"color": "#8B7D6B",
"map_color": "#A0522D",
"particle_effect": "metamorphic_dust"
}
}
}

View File

@ -0,0 +1,78 @@
{
"mystery_inclusions": {
"name": "Mystery Inclusions",
"category": "unknown_material",
"logistic_category": "resource",
"density": 8.5,
"stack_size": 1,
"container_type": "anomalous_material",
"ui": {
"icon": "mystery_inclusions.png",
"color": "#8B008B",
"map_color": "#9932CC",
"particle_effect": "mystery_sparkle"
}
},
"trapped_gases": {
"name": "Trapped Gases",
"category": "exotic_gas",
"logistic_category": "fluid",
"density": 0.002,
"stack_size": 0,
"container_type": "pressure_vessel",
"ui": {
"icon": "trapped_gases.png",
"color": "#E0FFFF",
"map_color": "#F0F8FF",
"particle_effect": "gas_bubbles"
}
},
"trace_metals": {
"name": "Trace Metals",
"category": "metal_mixture",
"logistic_category": "resource",
"density": 6.2,
"stack_size": 10,
"container_type": "mixed_metals",
"ui": {
"icon": "trace_metals.png",
"color": "#C0C0C0",
"map_color": "#A9A9A9",
"particle_effect": "fine_metallic_dust"
}
},
"metal_inclusions": {
"name": "Metal Inclusions",
"category": "embedded_metal",
"logistic_category": "resource",
"density": 4.8,
"stack_size": 5,
"container_type": "composite_material",
"ui": {
"icon": "metal_inclusions.png",
"color": "#696969",
"map_color": "#708090",
"particle_effect": "embedded_sparkle"
}
},
"meteoric_iron_ore": {
"name": "Meteoric Iron Ore",
"category": "space_alloy",
"logistic_category": "resource",
"density": 6.8,
"melting_point_celsius": 1600,
"stack_size": 25,
"container_type": "meteoric_ore",
"processing_note": "Space-forged iron-nickel alloy, produces superior steel with minimal processing",
"ui": {
"icon": "meteoric_iron_ore.png",
"color": "#4682B4",
"map_color": "#5F9EA0",
"particle_effect": "meteoric_sparkle"
}
},
// DECOMPOSED MATERIALS - Use individual ores instead:
// "other_metals" zinc_ore + tin_ore + lead_ore + antimony_ore (random distribution)
// "precious_metals" silver_ore + gold_ore + platinum_ore (random distribution)
// "rare_metals" titanium_ore + tungsten_ore + iridium_ore (random distribution)
}

View File

@ -0,0 +1,49 @@
{
"water_ice": {
"name": "Water Ice",
"category": "frozen_liquid",
"logistic_category": "resource",
"density": 0.92,
"stack_size": 100,
"container_type": "ice_material",
"melting_point_celsius": 0,
"processing_note": "Melts to produce water",
"ui": {
"icon": "water_ice.png",
"color": "#B0E0E6",
"map_color": "#87CEEB",
"particle_effect": "ice_crystals"
}
},
"methane_ice": {
"name": "Methane Ice",
"category": "frozen_gas",
"logistic_category": "resource",
"density": 0.42,
"stack_size": 50,
"container_type": "volatile_ice",
"melting_point_celsius": -182,
"processing_note": "Sublimates to methane gas",
"ui": {
"icon": "methane_ice.png",
"color": "#FFF8DC",
"map_color": "#F0E68C",
"particle_effect": "methane_vapor"
}
},
"trapped_gases": {
"name": "Trapped Gases",
"category": "exotic_gas",
"logistic_category": "fluid",
"density": 0.002,
"stack_size": 0,
"container_type": "pressure_vessel",
"processing_note": "Mixed atmospheric gases from space",
"ui": {
"icon": "trapped_gases.png",
"color": "#E0FFFF",
"map_color": "#F0F8FF",
"particle_effect": "gas_bubbles"
}
}
}

View File

@ -0,0 +1,919 @@
{
"geological_simulation": {
"description": "Complete planetary formation simulation over 4.65 billion years",
"total_duration_years": 4650000000,
"phases": [
// ===== PHASE 0: WORLD INITIALIZATION (1 cycle × 100M years = 0.1 Ga) =====
{
"name": "world_initialization",
"description": "Initialize world state with starting conditions",
"duration_cycles": 1,
"years_per_cycle": 100000000,
"steps": [
{
"name": "initialize_world_terrain",
"process_type": "initialize_world_terrain",
"parameters": {
"surface_temperature_celsius": -100,
"surface_elevation_meters": -30000,
"world_size": {"width": 1000, "height": 1000}
}
},
{
"name": "initialize_planetary_core",
"process_type": "initialize_planetary_core",
"parameters": {
"core_temperature_celsius": -100,
"max_core_capacity": 1940000000000000000000,
"base_composition": {
"iron_ore": 155200000000000000000,
"stone": 38800000000000000000
}
}
}
]
},
// ===== PHASE 1: PLANETARY ACCRETION (30 cycles × 100M years = 3.0 Ga) =====
{
"name": "planetary_accretion",
"description": "Initial planetary formation through meteorite bombardment",
"duration_cycles": 30,
"years_per_cycle": 100000000,
"steps": [
{
"name": "meteorite_impact_generation",
"process_type": "generate_meteorite_impacts",
"parameters": {
"impacts_per_wave": {"min": 100, "max": 500},
"meteorite_source": "meteorites.json",
"size_bias": "larger",
"type_weights": {
"chondrite_ordinary": 60,
"carbonaceous_chondrite": 15,
"stony_iron": 12,
"iron_meteorite": 8,
"ice_comet_fragment": 3,
"platinum_rich_rare": 2,
"bubble_meteorite": 1,
"magnetic_anomaly": 0.8,
"crystal_meteorite": 0.5,
"glass_meteorite": 0.3,
"diamond_meteorite": 0.2,
"radioactive_anomaly": 0.1
}
}
},
{
"name": "impact_effects_application",
"process_type": "apply_impact_effects",
"parameters": {
"kinetic_energy_to_heat_ratio": 2000,
"crater_formation_factor": 1.0,
"surface_metal_deposit_ratio": 0.3
}
},
{
"name": "planetary_differentiation",
"process_type": "heavy_metal_sinking",
"parameters": {
"sinking_rate_per_cycle": 0.7,
"heavy_metal_threshold_density": 5.0
}
},
{
"name": "volcanic_redistribution",
"process_type": "core_driven_volcanism",
"parameters": {
"core_pressure_threshold": 0.8,
"volcanic_overflow_rate": 0.2,
"volcanic_generation": {
"base_material_per_volcano": 1000000000000,
"main_pick_count": 3,
"secondary_pick_count": 5,
"default_volcano_type": "stratovolcano"
}
}
},
{
"name": "cooling_phase",
"process_type": "gradual_cooling",
"parameters": {
"surface_cooling_rate_per_cycle": 50,
"energy_to_core_ratio": 0.3,
"energy_to_space_ratio": 0.7,
"minimum_surface_temperature": -273,
"minimum_core_temperature": 1000,
"optimal_cooling_core_temperature": 2000,
"reference_surface_temperature": 1000
}
},
{
"name": "universal_region_fusion",
"process_type": "manage_all_region_fusion",
"parameters": {
"enabled": true,
"radius_calculation": "natural_logarithm",
"base_radius": 1.5,
"mass_reference": 5.0,
"fusion_threshold_percentage": 0.3,
"use_largest_radius_for_threshold": true,
"weighted_position_update": true,
"mass_combination": "additive",
"applies_to_all_region_types": true
}
}
]
},
// ===== PHASE 2: TECTONIC FORMATION (25 cycles × 100M years = 2.5 Ga) =====
{
"name": "tectonic_formation",
"description": "Formation of tectonic plates and crustal thickening",
"duration_cycles": 25,
"years_per_cycle": 100000000,
"steps": [
{
"name": "reduced_meteorite_bombardment",
"process_type": "generate_meteorite_impacts",
"parameters": {
"impacts_per_wave": {"min": 10, "max": 50},
"meteorite_source": "meteorites.json",
"impact_probability_per_cycle": 0.3,
"size_bias": "smaller",
"type_weights": {
"chondrite_ordinary": 35,
"carbonaceous_chondrite": 20,
"ice_comet_fragment": 15,
"stony_iron": 8,
"iron_meteorite": 5,
"crystal_meteorite": 4,
"magnetic_anomaly": 4,
"bubble_meteorite": 3,
"glass_meteorite": 2,
"platinum_rich_rare": 2,
"diamond_meteorite": 1.5,
"radioactive_anomaly": 0.5
}
}
},
{
"name": "initial_tectonic_region_creation",
"process_type": "create_tectonic_regions",
"parameters": {
"target_region_count": {"min": 15, "max": 25},
"region_types": ["oceanic", "continental", "volcanic"],
"initial_type_distribution": {
"oceanic": 0.6,
"continental": 0.35,
"volcanic": 0.05
},
"initial_radius_range": {"min": 50, "max": 200},
"random_placement": true
}
},
{
"name": "tectonic_physics_simulation",
"process_type": "tectonic_physics_engine",
"parameters": {
"repulsion_constant": 0.8,
"velocity_damping": 0.95,
"max_velocity": 5.0,
"collision_detection": true,
"force_calculation": "overlap_squared"
}
},
{
"name": "region_evolution",
"process_type": "tectonic_region_evolution",
"parameters": {
"split_probability_per_cycle": 0.01,
"growth_rate_range": {"min": -0.5, "max": 1.0},
"stability_factor": 0.8,
"minimum_region_radius": 20,
"maximum_region_radius": 500
}
},
{
"name": "collision_effects",
"process_type": "tectonic_collision_processing",
"parameters": {
"mountain_formation_threshold": 1.0,
"mountain_height_multiplier": 2000,
"rift_valley_depth": 500,
"volcanic_zone_creation": true,
"volcanic_zone_lifetime_cycles": 10
}
},
{
"name": "universal_region_fusion",
"process_type": "manage_all_region_fusion",
"parameters": {
"enabled": true,
"radius_calculation": "natural_logarithm",
"base_radius": 1.8,
"mass_reference": 8.0,
"fusion_threshold_percentage": 0.25,
"use_largest_radius_for_threshold": true,
"weighted_position_update": true,
"mass_combination": "additive",
"applies_to_all_region_types": true
}
}
]
},
// ===== PHASE 3: GEOLOGICAL PREPARATION (25 cycles × 20M years = 0.5 Ga) =====
{
"name": "geological_preparation",
"description": "Sea level rise and geological basin formation (preparation for future hydrology)",
"duration_cycles": 25,
"years_per_cycle": 20000000,
"steps": [
{
"name": "tectonic_movement_slowdown",
"process_type": "tectonic_physics_engine",
"parameters": {
"velocity_reduction_factor": 0.8,
"repulsion_constant": 0.64,
"velocity_damping": 0.95,
"max_velocity": 4.0,
"collision_detection": true,
"force_calculation": "overlap_squared"
}
},
{
"name": "residual_meteorite_impacts",
"process_type": "generate_meteorite_impacts",
"parameters": {
"impacts_per_wave": {"min": 1, "max": 5},
"meteorite_source": "meteorites.json",
"impact_probability_per_cycle": 0.1,
"size_bias": "smaller",
"type_weights": {
"chondrite_ordinary": 20,
"carbonaceous_chondrite": 15,
"ice_comet_fragment": 25,
"crystal_meteorite": 10,
"magnetic_anomaly": 10,
"glass_meteorite": 8,
"bubble_meteorite": 7,
"diamond_meteorite": 3,
"platinum_rich_rare": 2
}
}
},
{
"name": "residual_volcanism",
"process_type": "core_driven_volcanism",
"parameters": {
"volcanic_activity_reduction": 0.1,
"core_overflow_rate": 0.05,
"eruption_probability_per_cycle": 0.2,
"eruption_intensity_factor": 0.3,
"core_pressure_threshold": 0.4
}
},
{
"name": "sea_level_elevation",
"process_type": "elevate_sea_level",
"parameters": {
"initial_sea_level_meters": -5000,
"target_sea_level_meters": 0,
"elevation_rate_per_cycle": 200,
"ice_volume_effect": true,
"thermal_expansion_effect": true
}
},
{
"name": "tectonic_erosion",
"process_type": "apply_tectonic_erosion",
"parameters": {
"erosion_rate_factor": 1.0,
"elevation_erosion_threshold": 1000,
"mass_to_core_transfer": true,
"mountain_erosion_rate": 5.0,
"weathering_rate": 0.1
}
},
{
"name": "geological_basin_formation",
"process_type": "form_geological_basins",
"parameters": {
"basin_formation_probability": 0.05,
"valley_carving_intensity": 2.0,
"depression_depth_factor": 1.5,
"future_drainage_preparation": true
}
},
{
"name": "basic_climate_stabilization",
"process_type": "stabilize_basic_climate",
"parameters": {
"temperature_stabilization_rate": 0.1,
"co2_equilibrium_target": 350,
"volcanic_co2_reduction": 0.05,
"weathering_co2_absorption": 0.02
}
},
{
"name": "coastal_zone_preparation",
"process_type": "prepare_coastal_zones",
"parameters": {
"shallow_water_threshold": 50,
"deep_water_threshold": 200,
"coastal_shelf_formation": true,
"sediment_accumulation_zones": true
}
},
{
"name": "universal_region_fusion",
"process_type": "manage_all_region_fusion",
"parameters": {
"enabled": true,
"radius_calculation": "natural_logarithm",
"base_radius": 1.9,
"mass_reference": 9.0,
"fusion_threshold_percentage": 0.22,
"use_largest_radius_for_threshold": true,
"weighted_position_update": true,
"mass_combination": "additive",
"applies_to_all_region_types": true
}
}
]
},
// ===== PHASE 4: CARBONIFEROUS PERIOD (35 cycles × 10M years = 0.35 Ga) =====
{
"name": "carboniferous_period",
"description": "Dynamic forest evolution and coal formation through geological cycles",
"duration_cycles": 35,
"years_per_cycle": 10000000,
"steps": [
{
"name": "tectonic_movement_continued",
"process_type": "tectonic_physics_engine",
"parameters": {
"velocity_reduction_factor": 0.6,
"repulsion_constant": 0.48,
"velocity_damping": 0.96,
"max_velocity": 3.0,
"collision_detection": true,
"force_calculation": "overlap_squared",
"carbon_region_attachment_update": true
}
},
{
"name": "dynamic_forest_seeding",
"process_type": "seed_new_forests",
"parameters": {
"base_forest_seed_rate": 0.001,
"temperature_optimal_range": {"min": 15.0, "max": 35.0},
"temperature_bonus": 2.0,
"humidity_threshold": 0.4,
"humidity_bonus": 1.5,
"elevation_max": 2000.0,
"elevation_bonus": 1.2
}
},
{
"name": "forest_expansion",
"process_type": "expand_existing_forests",
"parameters": {
"forest_expansion_rate": 0.05,
"neighbor_viability_check": true,
"expansion_distance": 1,
"density_growth_factor": 1.1
}
},
{
"name": "carbon_region_formation",
"process_type": "create_carbon_regions",
"parameters": {
"minimum_forest_density": 0.3,
"carbon_mass_base": 100.0,
"region_radius_factor": 8.0,
"tectonic_attachment_strength": 0.9,
"carbon_type_initial": "COAL"
}
},
{
"name": "carbon_region_movement",
"process_type": "update_carbon_regions",
"parameters": {
"attachment_strength": 0.9,
"merge_distance_factor": 0.8
}
},
{
"name": "coal_to_oil_conversion",
"process_type": "convert_carbon_deposits",
"parameters": {
"conversion_rate_per_cycle": 0.01,
"underwater_cycles_required": 3,
"minimum_conversion_threshold": 1.0,
"underwater_depth_minimum": 50.0,
"surface_based_conversion": true,
"create_separate_oil_regions": true,
"oil_position_calculation": "underwater_center_of_mass",
"natural_gas_generation": false
}
},
{
"name": "universal_region_fusion",
"process_type": "manage_all_region_fusion",
"parameters": {
"enabled": true,
"radius_calculation": "natural_logarithm",
"base_radius": 2.0,
"mass_reference": 10.0,
"fusion_threshold_percentage": 0.2,
"use_largest_radius_for_threshold": true,
"weighted_position_update": true,
"mass_combination": "additive",
"applies_to_all_region_types": true
}
},
{
"name": "geological_forest_destruction",
"process_type": "destroy_forests_by_events",
"parameters": {
"volcanic_destruction_radius": 10.0,
"flood_destruction_threshold": 100,
"erosion_destruction_threshold": 5.0,
"temperature_destruction_min": -10.0,
"temperature_destruction_max": 50.0
}
}
]
},
// ===== PHASE 5: PRE-FAUNAL STABILIZATION (15 cycles × 10M years = 0.15 Ga) =====
{
"name": "pre_faunal_stabilization",
"description": "Final geological maturation and climate stabilization",
"duration_cycles": 15,
"years_per_cycle": 10000000,
"steps": [
{
"name": "tectonic_movement_final_slowdown",
"process_type": "tectonic_physics_engine",
"parameters": {
"velocity_reduction_factor": 0.48,
"repulsion_constant": 0.38,
"velocity_damping": 0.97,
"max_velocity": 2.4,
"collision_detection": true,
"force_calculation": "overlap_squared"
}
},
{
"name": "reduced_carbon_formation",
"process_type": "create_carbon_regions",
"parameters": {
"no_new_forests": true,
"existing_forest_to_carbon_only": true,
"carbon_mass_base": 50.0,
"region_radius_factor": 8.0,
"tectonic_attachment_strength": 0.9,
"carbon_type_initial": "COAL"
}
},
{
"name": "hydrocarbon_maturation_continued",
"process_type": "convert_carbon_deposits",
"parameters": {
"conversion_rate_per_cycle": 0.01
}
},
{
"name": "universal_region_fusion",
"process_type": "manage_all_region_fusion",
"parameters": {
"enabled": true,
"radius_calculation": "natural_logarithm",
"base_radius": 2.2,
"mass_reference": 15.0,
"fusion_threshold_percentage": 0.2,
"use_largest_radius_for_threshold": true,
"weighted_position_update": true,
"mass_combination": "additive",
"applies_to_all_region_types": true
}
},
{
"name": "petroleum_migration_to_traps",
"process_type": "migrate_petroleum_to_geological_traps",
"parameters": {
"trap_identification": true,
"anticline_formation_factor": 1.0,
"fault_trap_creation": true,
"salt_dome_probability": 0.05,
"migration_efficiency": 0.3,
"trap_capacity_factor": 50.0
}
},
{
"name": "final_erosion_phase",
"process_type": "apply_final_erosion",
"parameters": {
"erosion_rate_reduction": 0.5,
"coal_seam_exposure": true,
"river_valley_carving": true,
"coastal_feature_formation": true,
"erosion_depth_threshold": 50.0
}
},
{
"name": "soil_development",
"process_type": "develop_soil_layers",
"parameters": {
"soil_types": ["clay", "sand", "loam", "peat", "rocky", "alluvial"],
"soil_depth_factor": 0.1,
"climate_soil_correlation": true,
"river_alluvial_bonus": true,
"elevation_soil_effects": true
}
},
{
"name": "final_climate_stabilization",
"process_type": "stabilize_final_climate",
"parameters": {
"volcanic_activity_reduction": 0.8,
"climate_stability_increase": 0.1,
"climate_zone_establishment": true,
"temperature_variance_reduction": 0.9
}
}
]
},
// ===== PHASE 6A: LANDMASS ANALYSIS & ITCZ PREPARATION (1 cycle × 1M years) =====
{
"name": "landmass_analysis_and_itcz_preparation",
"description": "Analyze continental masses from existing TectonicRegions and create Inter-Tropical Convergence Zones",
"duration_cycles": 1,
"years_per_cycle": 1000000,
"steps": [
{
"name": "continental_mass_analysis",
"process_type": "analyze_continental_masses",
"parameters": {
"_comment": "Uses existing TectonicRegions to identify continental masses for ITCZ placement",
"continental_grouping": {
"proximity_threshold": 100,
"minimum_region_count": 2,
"mass_calculation_method": "area_weighted",
"continental_type_filter": ["continental", "volcanic"]
},
"landmass_requirements": {
"minimum_total_area": 5000,
"minimum_individual_region_area": 1000,
"connectivity_analysis": true
},
"equatorial_filtering": {
"latitude_band": [0.40, 0.60],
"strict_equatorial_requirement": false,
"latitude_scoring_weight": 0.7
}
}
},
{
"name": "ocean_basin_detection",
"process_type": "detect_ocean_basins",
"parameters": {
"_comment": "Inverse analysis to identify ocean masses from continental positions",
"ocean_detection_method": "inverse_continental_analysis",
"minimum_ocean_size": 5000,
"coastal_connectivity_check": true,
"ocean_temperature_estimation": {
"latitude_based": true,
"equator_temp": 28.0,
"pole_temp": 2.0,
"thermal_gradient": "cosine_distribution"
},
"evaporation_potential_calculation": {
"temperature_factor": true,
"surface_area_factor": true,
"wind_exposure_factor": true
}
}
},
{
"name": "itcz_zone_creation",
"process_type": "create_itcz_convergence_zones",
"parameters": {
"_comment": "Create ITCZ zones on qualifying equatorial landmasses",
"itcz_requirements": {
"latitude_band": [0.45, 0.55],
"min_landmass_size": 10000,
"max_ocean_distance": 800,
"continental_heating_threshold": 5000
},
"itcz_zone_properties": {
"center_calculation": "continental_center_of_mass",
"gravitational_range_formula": "sqrt(landmass_area) * 50",
"mass_calculation": "landmass_total_area",
"amplification_factor": 3.0,
"intensity_falloff": "inverse_square_law"
},
"multiple_itcz_handling": {
"allow_multiple_zones": true,
"minimum_separation_distance": 500,
"interaction_between_zones": false
}
}
},
{
"name": "climate_infrastructure_preparation",
"process_type": "prepare_climate_simulation_infrastructure",
"parameters": {
"_comment": "Clean slate preparation for WindRegion-based simulation",
"data_cleanup": {
"clear_legacy_wind_data": true,
"clear_legacy_humidity_data": true,
"preserve_temperature_gradients": true,
"preserve_elevation_data": true
},
"token_system_initialization": {
"initialize_token_counters": true,
"token_types": ["wind", "rain", "highWind", "flood", "hurricane"],
"reset_all_tokens": true
},
"performance_optimization": {
"pre_allocate_wind_region_pool": true,
"max_concurrent_wind_regions": 200,
"spatial_indexing_setup": true
}
}
}
]
},
// ===== PHASE 6B: CLIMATE SIMULATION & BIOME GENERATION (300 cycles × 100K years = 30M years) =====
{
"name": "climate_simulation_and_biome_generation",
"description": "Advanced climate simulation using mobile WindRegions and ITCZ zones for realistic weather patterns",
"duration_cycles": 300,
"years_per_cycle": 100000,
"steps": [
{
"name": "wind_region_spawning_system",
"process_type": "spawn_mobile_wind_regions",
"parameters": {
"_comment": "Mobile WindRegions spawn from ocean masses with biased distribution",
"spawn_system": {
"spawn_locations": "ocean_masses_only",
"spawn_frequency_formula": "water_mass_size / 1000",
"spawn_distribution": "random_within_water_region_biased_toward_center",
"max_concurrent_regions": 200,
"initial_strength_formula": "water_temperature * evaporation_factor"
},
"wind_region_properties": {
"initial_wind_strength": 1.0,
"initial_wetness": 0.0,
"wind_tokens": 100,
"rain_tokens": 0,
"decay_per_move": 0.02,
"decay_per_tile": 0.01,
"minimum_survival_threshold": 0.1
},
"ocean_moisture_gain": {
"ocean_moisture_rate": 0.1,
"temperature_factor": true,
"evaporation_efficiency": 1.0
}
}
},
{
"name": "planetary_circulation_and_movement",
"process_type": "apply_planetary_circulation",
"parameters": {
"_comment": "Planetary rotation bands based on real atmospheric data",
"planetary_circulation_bands": {
"polar_jet_north": {
"latitude_range": [0.10, 0.25],
"direction": "west_to_east",
"strength": 1.8
},
"calm_transition_1": {
"latitude_range": [0.25, 0.40],
"movement": "chaos_plus_procedural"
},
"equatorial_trades": {
"latitude_range": [0.40, 0.60],
"direction": "east_to_west",
"strength": 1.5
},
"calm_transition_2": {
"latitude_range": [0.60, 0.75],
"movement": "chaos_plus_procedural"
},
"polar_jet_south": {
"latitude_range": [0.75, 0.95],
"direction": "west_to_east",
"strength": 1.8
}
},
"movement_calculation": {
"planetary_circulation_weight": 0.6,
"equator_to_pole_bias_weight": 0.2,
"terrain_deflection_weight": 0.1,
"random_variation_weight": 0.1
},
"movement_physics": {
"velocity_damping": 0.95,
"terrain_interaction": true,
"boundary_wrapping": "spherical_world"
}
}
},
{
"name": "wind_region_evolution_and_interactions",
"process_type": "evolve_wind_regions",
"parameters": {
"_comment": "WindRegion interactions including repulsion system and ITCZ effects",
"repulsion_system": {
"enabled": true,
"repulsion_calculation": "spatial_competition_proxy",
"acceleration_factor": 1.0,
"maximum_interaction_distance": 50.0,
"_design_note": "Prevents region stacking while creating realistic dispersion patterns",
"_alternative_algorithms": {
"density_based_drift": false,
"no_interaction": false,
"collision_division": false
}
},
"itcz_gravitational_effects": {
"enabled": true,
"attraction_formula": "itcz.mass / (distance * distance)",
"gravitational_metaphor": "influence_strength_not_literal_physics",
"amplification_calculation": {
"proximity_factor": "(itcz.range - distance) / itcz.range",
"max_amplification": 3.0,
"wind_strength_multiplier": true,
"wetness_multiplier": true
}
},
"regional_evolution": {
"wind_strength_decay": true,
"moisture_accumulation": true,
"death_threshold": 0.1,
"lifecycle_management": true
}
}
},
{
"name": "token_distribution_and_climate_zones",
"process_type": "distribute_climate_tokens",
"parameters": {
"_comment": "Token-based climate zone classification system",
"basic_token_distribution": {
"wind_token_factor": 10,
"rain_token_factor": 10,
"tokens_per_tile_visit": true,
"accumulation_system": true
},
"climate_zone_thresholds": {
"high_wind_threshold": 2.0,
"flood_threshold": 1.5,
"hurricane_wind_threshold": 2.5,
"hurricane_rain_threshold": 2.0
},
"special_climate_tokens": {
"high_wind_tokens": {
"description": "Hostile to forests",
"biome_effect": "prevents_forest_growth",
"token_value": 1
},
"flood_tokens": {
"description": "Forces wetlands/marshes",
"biome_effect": "mandatory_wetlands",
"token_value": 1
},
"hurricane_tokens": {
"description": "Specialized hurricane biome",
"biome_effect": "storm_resistant_vegetation",
"token_value": 1
}
},
"token_persistence": {
"accumulation_method": "additive",
"decay_rate": 0.0,
"permanent_climate_record": true
}
}
},
{
"name": "biome_classification_from_tokens",
"process_type": "classify_biomes_from_climate_tokens",
"parameters": {
"_comment": "Load biome system from external definitions - all rules and modifiers defined in biome files",
"biome_system_source": "gameData/Biomes/biome_index.json",
"load_all_biome_definitions": true,
"use_external_classification_rules": true,
"use_external_resource_modifiers": true,
"fallback_biome": "scrubland"
}
},
{
"name": "temporal_token_dissipation",
"process_type": "apply_token_dissipation",
"parameters": {
"_comment": "Random token dissipation - high for normal tokens (variation), low for catastrophe tokens (preserve special zones)",
"rain_tokens": {
"dissipation_range": [5, 25],
"dissipation_frequency": 0.12
},
"wind_tokens": {
"dissipation_range": [3, 15],
"dissipation_frequency": 0.10
},
"highWind_tokens": {
"dissipation_range": [2, 8],
"dissipation_frequency": 0.08
},
"flood_tokens": {
"dissipation_range": [1, 2],
"dissipation_frequency": 0.02
},
"hurricane_tokens": {
"dissipation_range": [1, 2],
"dissipation_frequency": 0.015
}
}
}
]
},
// ===== PHASE 7: BUDGET ASSIGNMENT =====
{
"name": "budget_assignment",
"description": "Random budget score distribution for economic gameplay",
"duration_cycles": 1,
"years_per_cycle": 1000000,
"steps": [
{
"name": "assign_budget_scores",
"process_type": "random_budget_assignment",
"parameters": {
"distribution": "normal",
"mean": 0.0,
"std_dev": 3.0,
"range": [-10, 10]
}
}
]
},
// ===== PHASE 7: BUDGET & FEATURES =====
{
"name": "budget_and_features",
"description": "Random budget assignment and biome-appropriate natural features placement",
"duration_cycles": 1,
"years_per_cycle": 1000000,
"steps": [
{
"name": "assign_budget_scores",
"process_type": "random_budget_assignment",
"parameters": {
"distribution": "normal",
"mean": 0.0,
"std_dev": 3.0,
"range": [-10, 10]
}
},
{
"name": "place_natural_features",
"process_type": "biome_based_feature_placement",
"parameters": {
"chance": 0.05,
"feature_sources": [
"gameData/MapFeatures/geological_formations.json",
"gameData/MapFeatures/natural_landmarks.json",
"gameData/MapFeatures/water_features.json",
"gameData/MapFeatures/volcanic_features.json",
"gameData/MapFeatures/underground_features.json",
"gameData/MapFeatures/forest_features.json",
"gameData/MapFeatures/coastal_features.json"
],
"biome_compatibility": {
"tropical_rainforest": ["giant_tree", "ancient_grove", "bamboo_grove", "fruit_orchard", "carboniferous_forest", "underground_river"],
"hot_desert": ["canyon", "cliff", "sinkhole", "oasis", "volcano", "lava_field", "obsidian_field"],
"temperate_forest": ["forest_clearing", "ancient_grove", "medicinal_grove", "mushroom_grove", "carboniferous_forest", "underground_lake"],
"grassland": ["plateau", "natural_bridge", "sinkhole", "lake", "spring"],
"tundra": ["geyser", "sinkhole", "cliff", "lake", "crater", "fumarole", "deep_cavern"],
"alpine": ["canyon", "cliff", "gorge", "volcano", "caldera", "crystal_cavern", "volcanic_vent"],
"cold_desert": ["canyon", "cliff", "sinkhole", "hoodoo", "crater", "obsidian_field"],
"hills": ["cave", "spring", "plateau", "gorge", "cave_network", "bat_cave"],
"rocky_plateau": ["canyon", "cliff", "natural_bridge", "mesa", "rock_spire", "monolith"],
"hurricane_zone": ["cave", "gorge", "marsh", "central_hill_swamp", "bat_cave"],
"wetlands": ["central_hill_swamp", "islands_swamp", "hilly_swampy", "underground_lake", "delta"],
"storm_prairie": ["plateau", "sinkhole", "natural_bridge", "hoodoo", "monolith"],
"badlands": ["canyon", "cliff", "gorge", "mesa", "sinkhole", "lava_field"],
"coastal_plain": ["delta", "pond", "marsh", "estuary", "natural_harbor"],
"cliffs": ["sea_cave", "cliff", "natural_arch", "blowhole", "sea_stack"],
"sandy_coast": ["beach_dunes", "delta", "natural_harbor", "tidal_pool", "estuary"],
"rocky_shore": ["sea_cave", "tidal_pool", "sea_stack", "blowhole", "coral_reef"],
"scrubland": ["cave", "plateau", "spring", "sinkhole", "canyon", "monolith", "rock_spire"]
}
}
}
]
}
]
}
}

View File

@ -0,0 +1,33 @@
{
"world_generation_scenarios": {
"description": "Available world generation scenarios and their configurations",
"default_scenario": "regular_world",
"scenarios": {
"regular_world": {
"name": "Regular World",
"description": "Standard planetary formation with realistic geological processes",
"config_file": "Regular_world.json",
"difficulty": "standard",
"estimated_generation_time_seconds": 30,
"features": [
"complete_geological_simulation",
"meteorite_bombardment",
"tectonic_activity",
"climate_formation",
"resource_distribution"
],
"recommended_for": ["standard_gameplay", "balanced_resources", "realistic_geology"]
}
}
},
"shared_resources": {
"meteorite_definitions": "meteorites.json",
"process_definitions": "process_definitions.json"
},
"generation_settings": {
"default_map_size": {"width": 1000, "height": 1000},
"performance_mode": "balanced",
"debug_output": false,
"save_intermediate_states": false
}
}

View File

@ -0,0 +1,222 @@
{
"_comments": {
"decomposed_materials": "Future materials to implement:",
"other_metals": "zinc_ore + tin_ore + lead_ore + antimony_ore (random distribution)",
"precious_metals": "silver_ore + gold_ore + platinum_ore (random distribution)",
"rare_metals": "titanium_ore + tungsten_ore + iridium_ore (random distribution)",
"note": "meteoric_iron_ore should be rare (1-5%) - premium material for superior steel"
},
"meteorite_types": {
"chondrite_ordinary": {
"name": "Ordinary Chondrite",
"description": "Most common meteorite type - rocky with some metal",
"composition": {
"silicate_rock": 85,
"iron_ore": 8,
"meteoric_iron_ore": 1,
"nickel_ore": 3,
"zinc_ore": 2,
"tin_ore": 1
},
"mass_range": {"min": 1e10, "max": 1e13},
"impact_characteristics": {
"crater_factor": 1.0,
"heat_generation": 800,
"fragmentation": "medium"
}
},
"carbonaceous_chondrite": {
"name": "Carbonaceous Chondrite",
"description": "Water and organic-rich meteorites",
"composition": {
"silicate_rock": 70,
"water_ice": 15,
"organic_compounds": 10,
"iron_ore": 3,
"nickel_ore": 2
},
"mass_range": {"min": 5e9, "max": 8e12},
"impact_characteristics": {
"crater_factor": 0.8,
"heat_generation": 600,
"fragmentation": "high"
}
},
"iron_meteorite": {
"name": "Iron Meteorite",
"description": "Almost pure metal - core fragments from destroyed planetoids",
"composition": {
"iron_ore": 80,
"meteoric_iron_ore": 5,
"nickel_ore": 12,
"silver_ore": 1,
"gold_ore": 1,
"platinum_ore": 1
},
"mass_range": {"min": 1e12, "max": 1e15},
"impact_characteristics": {
"crater_factor": 1.5,
"heat_generation": 1500,
"fragmentation": "low"
}
},
"stony_iron": {
"name": "Stony-Iron Meteorite",
"description": "Mixed rock and metal - rare but valuable",
"composition": {
"silicate_rock": 50,
"iron_ore": 30,
"meteoric_iron_ore": 3,
"nickel_ore": 10,
"silver_ore": 2,
"gold_ore": 1,
"zinc_ore": 2,
"tin_ore": 1,
"lead_ore": 1
},
"mass_range": {"min": 5e11, "max": 5e14},
"impact_characteristics": {
"crater_factor": 1.2,
"heat_generation": 1200,
"fragmentation": "medium"
}
},
"platinum_rich_rare": {
"name": "Platinum-Rich Asteroid Fragment",
"description": "Extremely rare precious metal rich meteorite",
"composition": {
"silicate_rock": 30,
"iron_ore": 18,
"meteoric_iron_ore": 5,
"nickel_ore": 15,
"platinum_ore": 15,
"gold_ore": 8,
"titanium_ore": 4,
"tungsten_ore": 2,
"iridium_ore": 2,
"silver_ore": 1
},
"mass_range": {"min": 1e11, "max": 1e14},
"impact_characteristics": {
"crater_factor": 1.3,
"heat_generation": 1000,
"fragmentation": "low"
}
},
"crystal_meteorite": {
"name": "Crystalline Meteorite",
"description": "Bizarre meteorite made of pure quartz crystals - origin unknown",
"composition": {
"quartz_crystal": 90,
"rare_earth_elements": 5,
"unknown_minerals": 5
},
"mass_range": {"min": 1e9, "max": 1e12},
"impact_characteristics": {
"crater_factor": 0.3,
"heat_generation": 200,
"fragmentation": "explosive",
"special_effects": ["crystal_formations", "electromagnetic_anomaly"]
}
},
"ice_comet_fragment": {
"name": "Dirty Snowball Fragment",
"description": "Massive chunk of dirty ice from the outer solar system",
"composition": {
"water_ice": 60,
"methane_ice": 20,
"cosmic_dust": 15,
"organic_compounds": 5
},
"mass_range": {"min": 1e12, "max": 1e16},
"impact_characteristics": {
"crater_factor": 2.0,
"heat_generation": 300,
"fragmentation": "explosive",
"special_effects": ["steam_explosion", "temporary_atmosphere", "organic_seeding"]
}
},
"radioactive_anomaly": {
"name": "Radioactive Anomaly",
"description": "Highly radioactive meteorite of unknown composition - handle with care",
"composition": {
"uranium_ore": 40,
"thorium_ore": 25,
"plutonium": 15,
"unknown_isotopes": 20
},
"mass_range": {"min": 1e10, "max": 1e13},
"impact_characteristics": {
"crater_factor": 1.0,
"heat_generation": 3000,
"fragmentation": "low",
"special_effects": ["radiation_zone", "mutation_field", "thermal_anomaly"]
}
},
"magnetic_anomaly": {
"name": "Magnetic Core Fragment",
"description": "Intensely magnetic meteorite that disrupts compasses for kilometers",
"composition": {
"magnetite": 70,
"iron_ore": 20,
"rare_earth_magnets": 10
},
"mass_range": {"min": 1e11, "max": 1e14},
"impact_characteristics": {
"crater_factor": 1.4,
"heat_generation": 1200,
"fragmentation": "medium",
"special_effects": ["magnetic_field_disruption", "compass_anomaly", "metallic_attraction"]
}
},
"glass_meteorite": {
"name": "Obsidian Wanderer",
"description": "Perfectly smooth glass meteorite - natural or artificial origin unclear",
"composition": {
"volcanic_glass": 95,
"trace_metals": 3,
"mystery_inclusions": 2
},
"mass_range": {"min": 1e9, "max": 1e11},
"impact_characteristics": {
"crater_factor": 0.5,
"heat_generation": 400,
"fragmentation": "high",
"special_effects": ["razor_sharp_shards", "perfect_reflections", "optical_effects"]
}
},
"bubble_meteorite": {
"name": "Foam Stone",
"description": "Incredibly light meteorite full of gas bubbles - floats on water",
"composition": {
"pumice_like_rock": 40,
"trapped_gases": 50,
"silicate_foam": 10
},
"mass_range": {"min": 1e8, "max": 1e10},
"impact_characteristics": {
"crater_factor": 0.1,
"heat_generation": 100,
"fragmentation": "low",
"special_effects": ["gas_release", "floating_debris", "minimal_damage"]
}
},
"diamond_meteorite": {
"name": "Diamond Rain",
"description": "Meteorite studded with micro-diamonds - forms under extreme pressure",
"composition": {
"micro_diamonds": 30,
"carbon_matrix": 50,
"silicate_rock": 15,
"metal_inclusions": 5
},
"mass_range": {"min": 1e10, "max": 1e12},
"impact_characteristics": {
"crater_factor": 1.1,
"heat_generation": 900,
"fragmentation": "low",
"special_effects": ["diamond_scatter", "extreme_hardness", "cutting_capability"]
}
}
}
}

110
gameconfig.json Normal file
View File

@ -0,0 +1,110 @@
{
"metadata": {
"version": "1.0.0",
"created": "2025-01-27",
"description": "Warfactory system configuration - infrastructure only",
"hash": "sha256:placeholder"
},
"coordination": {
"enabled": true,
"module_deployment_timeout": 30000,
"health_check_interval": 5000,
"hot_reload": {
"enabled": true,
"watch_directories": ["modules/", "config/"],
"extensions": [".so", ".json"]
}
},
"modules": {
"debug_world_gen": {
"enabled": true,
"priority": 1,
"frequency": 1.0,
"library_path": "modules/debug_world_gen/build/libdebug_world_gen.so",
"config_file": "config/debug_world_gen.json"
},
"tank": {
"enabled": true,
"priority": 2,
"frequency": 60.0,
"library_path": "modules/tank/build/libtank.so",
"config_file": "config/tank.json"
},
"economy": {
"enabled": true,
"priority": 3,
"frequency": 0.1,
"library_path": "modules/economy/build/libeconomy.so",
"config_file": "config/economy.json"
},
"factory": {
"enabled": true,
"priority": 4,
"frequency": 60.0,
"library_path": "modules/factory/build/libfactory.so",
"config_file": "config/factory.json"
},
"logistic": {
"enabled": true,
"priority": 5,
"frequency": 1.0,
"library_path": "modules/logistic/build/liblogistic.so",
"config_file": "config/logistic.json"
}
},
"engine": {
"type": "DEBUG",
"target_fps": 60,
"step_by_step": false,
"verbose_logging": true,
"performance_monitoring": true,
"module_system": {
"type": "SEQUENTIAL",
"thread_pool_size": 4,
"task_queue_size": 1000
}
},
"performance": {
"targets": {
"v1_client_fps": 30,
"v2_client_fps": 60,
"v1_server_players": 10,
"v2_server_players": 100,
"iteration_cycle_seconds": 5,
"hot_reload_ms": 1
},
"optimization": {
"simd": false,
"cluster_distribution": false,
"memory_pooling": true,
"cache_friendly_data": true
}
},
"debugging": {
"sanitizers": {
"address": true,
"undefined_behavior": true,
"leak": true
},
"profiling": {
"enabled": true,
"per_module_metrics": true,
"memory_tracking": true
},
"logging": {
"level": "DEBUG",
"file_output": true,
"console_output": true,
"json_structured": true
}
}
}

View File

@ -1,23 +0,0 @@
#pragma once
#include <string>
#include <memory>
#include "IDataTree.h"
namespace warfactory {
/**
* @brief Factory for creating data tree instances
*/
class DataTreeFactory {
public:
/**
* @brief Create data tree from configuration source
* @param type Tree type ("json", "database", etc.)
* @param sourcePath Path to configuration source
* @return Data tree instance
*/
static std::unique_ptr<IDataTree> create(const std::string& type, const std::string& sourcePath);
};
} // namespace warfactory

View File

@ -1,233 +0,0 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
#include <functional>
#include <nlohmann/json.hpp>
namespace warfactory {
using json = nlohmann::json;
/**
* @brief Interface for a single node in the data tree
*
* Each node can have:
* - Children nodes (tree navigation)
* - Its own data blob (JSON)
* - Properties accessible by name with type safety
*/
class IDataNode {
public:
virtual ~IDataNode() = default;
// ========================================
// TREE NAVIGATION
// ========================================
/**
* @brief Get direct child by name
* @param name Exact name of the child
* @return Child node or nullptr if not found
*/
virtual std::unique_ptr<IDataNode> getChild(const std::string& name) = 0;
/**
* @brief Get names of all direct children
* @return Vector of child names
*/
virtual std::vector<std::string> getChildNames() = 0;
/**
* @brief Check if this node has any children
* @return true if children exist
*/
virtual bool hasChildren() = 0;
// ========================================
// EXACT SEARCH IN CHILDREN
// ========================================
/**
* @brief Find all children with exact name (direct children only)
* @param name Exact name to search for
* @return Vector of matching child nodes
*/
virtual std::vector<IDataNode*> getChildrenByName(const std::string& name) = 0;
/**
* @brief Check if any children have the exact name
* @param name Exact name to search for
* @return true if found
*/
virtual bool hasChildrenByName(const std::string& name) const = 0;
/**
* @brief Get first child with exact name
* @param name Exact name to search for
* @return First matching child or nullptr
*/
virtual IDataNode* getFirstChildByName(const std::string& name) = 0;
// ========================================
// PATTERN MATCHING SEARCH (DEEP SEARCH IN WHOLE SUBTREE)
// ========================================
/**
* @brief Find all nodes in subtree matching pattern
* @param pattern Pattern with wildcards (* supported)
* @return Vector of matching nodes in entire subtree
*
* Examples:
* - "component*" matches "component_armor", "component_engine"
* - "*heavy*" matches "tank_heavy_mk1", "artillery_heavy"
* - "model_*" matches "model_01", "model_02"
*/
virtual std::vector<IDataNode*> getChildrenByNameMatch(const std::string& pattern) = 0;
/**
* @brief Check if any nodes in subtree match pattern
* @param pattern Pattern with wildcards
* @return true if any matches found
*/
virtual bool hasChildrenByNameMatch(const std::string& pattern) const = 0;
/**
* @brief Get first node in subtree matching pattern
* @param pattern Pattern with wildcards
* @return First matching node or nullptr
*/
virtual IDataNode* getFirstChildByNameMatch(const std::string& pattern) = 0;
// ========================================
// QUERY BY PROPERTIES
// ========================================
/**
* @brief Query nodes in subtree by property value
* @param propName Property name to check
* @param predicate Function to test property value
* @return Vector of nodes where predicate returns true
*
* Example:
* // Find all tanks with armor > 150
* queryByProperty("armor", [](const json& val) {
* return val.is_number() && val.get<int>() > 150;
* });
*/
virtual std::vector<IDataNode*> queryByProperty(const std::string& propName,
const std::function<bool(const json&)>& predicate) = 0;
// ========================================
// NODE'S OWN DATA
// ========================================
/**
* @brief Get this node's data blob
* @return JSON data or empty JSON if no data
*/
virtual json getData() = 0;
/**
* @brief Check if this node has data
* @return true if data exists
*/
virtual bool hasData() = 0;
/**
* @brief Set this node's data
* @param data JSON data to set
*/
virtual void setData(const json& data) = 0;
// ========================================
// TYPED DATA ACCESS BY PROPERTY NAME
// ========================================
/**
* @brief Get string property from this node's data
* @param name Property name
* @param defaultValue Default if property not found or wrong type
* @return Property value or default
*/
virtual std::string getString(const std::string& name, const std::string& defaultValue = "") = 0;
/**
* @brief Get integer property from this node's data
* @param name Property name
* @param defaultValue Default if property not found or wrong type
* @return Property value or default
*/
virtual int getInt(const std::string& name, int defaultValue = 0) = 0;
/**
* @brief Get double property from this node's data
* @param name Property name
* @param defaultValue Default if property not found or wrong type
* @return Property value or default
*/
virtual double getDouble(const std::string& name, double defaultValue = 0.0) = 0;
/**
* @brief Get boolean property from this node's data
* @param name Property name
* @param defaultValue Default if property not found or wrong type
* @return Property value or default
*/
virtual bool getBool(const std::string& name, bool defaultValue = false) = 0;
/**
* @brief Check if property exists in this node's data
* @param name Property name
* @return true if property exists
*/
virtual bool hasProperty(const std::string& name) = 0;
// ========================================
// HASH SYSTEM FOR VALIDATION & SYNCHRO
// ========================================
/**
* @brief Get hash of this node's data only
* @return SHA256 hash of data blob
*/
virtual std::string getDataHash() = 0;
/**
* @brief Get recursive hash of this node and all children
* @return SHA256 hash of entire subtree
*/
virtual std::string getTreeHash() = 0;
/**
* @brief Get hash of specific child subtree
* @param childPath Path to child from this node
* @return SHA256 hash of child subtree
*/
virtual std::string getSubtreeHash(const std::string& childPath) = 0;
// ========================================
// METADATA
// ========================================
/**
* @brief Get full path from root to this node
* @return Path string (e.g., "vehicles/tanks/heavy/model5")
*/
virtual std::string getPath() = 0;
/**
* @brief Get this node's name
* @return Node name
*/
virtual std::string getName() = 0;
/**
* @brief Get node type (extensible for templates/inheritance later)
* @return Node type identifier
*/
virtual std::string getNodeType() = 0;
};
} // namespace warfactory

View File

@ -1,69 +0,0 @@
#pragma once
#include <string>
#include <memory>
#include <functional>
#include "IDataNode.h"
namespace warfactory {
/**
* @brief Interface for the root data tree container
*
* Manages the entire tree structure and provides hot-reload capabilities
*/
class IDataTree {
public:
virtual ~IDataTree() = default;
// ========================================
// TREE ACCESS
// ========================================
/**
* @brief Get root node of the tree
* @return Root node
*/
virtual std::unique_ptr<IDataNode> getRoot() = 0;
/**
* @brief Get node by path from root
* @param path Path from root (e.g., "vehicles/tanks/heavy")
* @return Node at path or nullptr if not found
*/
virtual std::unique_ptr<IDataNode> getNode(const std::string& path) = 0;
// ========================================
// MANUAL HOT-RELOAD (SIMPLE & EFFECTIVE)
// ========================================
/**
* @brief Check if source files have changed
* @return true if changes detected
*/
virtual bool checkForChanges() = 0;
/**
* @brief Reload entire tree if changes detected
* @return true if reload was performed
*/
virtual bool reloadIfChanged() = 0;
/**
* @brief Register callback for when tree is reloaded
* @param callback Function called after successful reload
*/
virtual void onTreeReloaded(std::function<void()> callback) = 0;
// ========================================
// METADATA
// ========================================
/**
* @brief Get tree implementation type
* @return Type identifier (e.g., "JSONDataTree", "DatabaseDataTree")
*/
virtual std::string getType() = 0;
};
} // namespace warfactory

View File

@ -1,129 +0,0 @@
#pragma once
#include <nlohmann/json.hpp>
#include <string>
#include <functional>
namespace warfactory {
using json = nlohmann::json;
/**
* @brief Pure Generic UI Interface - Zero assumptions about content
*
* Completely data-agnostic. Implementation decides how to handle each data type.
*/
class IUI {
public:
virtual ~IUI() = default;
// ========================================
// LIFECYCLE
// ========================================
/**
* @brief Initialize UI system
* @param config Generic config, implementation interprets
*/
virtual void initialize(const json& config) = 0;
/**
* @brief Update/render one frame
* @return true to continue, false to quit
*/
virtual bool update() = 0;
/**
* @brief Clean shutdown
*/
virtual void shutdown() = 0;
// ========================================
// GENERIC DATA FLOW
// ========================================
/**
* @brief Display any data of any type with layout/windowing info
* @param dataType "economy", "map", "inventory", "status", whatever
* @param data JSON with content + layout:
* {
* "content": {...}, // Actual data to display
* "window": { // Window/layout configuration
* "id": "economy_main", // Unique window ID
* "title": "Economy Dashboard",
* "parent": "main_dock", // Parent window/dock ID (optional)
* "dock": "left", // Dock position: "left", "right", "top", "bottom", "center", "tab"
* "size": {"width": 400, "height": 300},
* "position": {"x": 100, "y": 50},
* "floating": false, // true = floating window, false = docked
* "resizable": true,
* "closeable": true
* }
* }
*/
virtual void showData(const std::string& dataType, const json& data) = 0;
/**
* @brief Handle any user request of any type
* @param requestType "get_prices", "move_unit", "save_game", whatever
* @param callback Function to call when request happens
*/
virtual void onRequest(const std::string& requestType, std::function<void(const json&)> callback) = 0;
/**
* @brief Show any event/message
* @param level "info", "error", "debug", whatever
* @param message Human readable text
*/
virtual void showEvent(const std::string& level, const std::string& message) = 0;
// ========================================
// WINDOW MANAGEMENT
// ========================================
/**
* @brief Create or configure a dock/container window
* @param dockId Unique dock identifier
* @param config Dock configuration:
* {
* "type": "dock", // "dock", "tabbed", "split"
* "orientation": "horizontal", // "horizontal", "vertical" (for splits)
* "parent": "main_window", // Parent dock (for nested docks)
* "position": "left", // Initial position
* "size": {"width": 300}, // Initial size
* "collapsible": true, // Can be collapsed
* "tabs": true // Enable tabbed interface
* }
*/
virtual void createDock(const std::string& dockId, const json& config) = 0;
/**
* @brief Close/remove window or dock
* @param windowId Window or dock ID to close
*/
virtual void closeWindow(const std::string& windowId) = 0;
/**
* @brief Focus/bring to front a specific window
* @param windowId Window ID to focus
*/
virtual void focusWindow(const std::string& windowId) = 0;
// ========================================
// GENERIC STATE
// ========================================
/**
* @brief Get current UI state
* @return JSON state, implementation defines structure
*/
virtual json getState() const = 0;
/**
* @brief Restore UI state
* @param state JSON state from previous getState()
*/
virtual void setState(const json& state) = 0;
};
} // namespace warfactory

View File

@ -1,340 +0,0 @@
#pragma once
#include <nlohmann/json.hpp>
#include <string>
#include <functional>
namespace warfactory {
using json = nlohmann::json;
// ========================================
// ENUMS FOR TYPE SAFETY
// ========================================
/**
* @brief Data types for UI display
*/
enum class DataType {
ECONOMY,
MAP,
INVENTORY,
CONSOLE,
PERFORMANCE,
COMPANIES,
ALERTS,
PRODUCTION,
LOGISTICS,
PLAYER,
SETTINGS,
DEBUG,
CUSTOM // For extending with string fallback
};
/**
* @brief Request types from UI
*/
enum class RequestType {
GET_PRICES,
GET_CHUNK,
MOVE_PLAYER,
SAVE_GAME,
LOAD_GAME,
CLOSE_WINDOW,
FOCUS_WINDOW,
UPDATE_SETTINGS,
EXECUTE_COMMAND,
CUSTOM // For extending with string fallback
};
/**
* @brief Event/message levels
*/
enum class EventLevel {
INFO,
SUCCESS,
WARNING,
ERROR,
DEBUG,
TRACE
};
/**
* @brief Dock types for window management
*/
enum class DockType {
DOCK, // Standard dockable panel
SPLIT, // Horizontal/vertical split
TABBED, // Tabbed container
FLOATING // Floating window
};
/**
* @brief Dock positions
*/
enum class DockPosition {
LEFT,
RIGHT,
TOP,
BOTTOM,
CENTER,
TAB // Add as tab to parent
};
/**
* @brief Split orientations
*/
enum class Orientation {
HORIZONTAL,
VERTICAL
};
/**
* @brief Pure Generic UI Interface - Type-safe with enums
*/
class IUI {
public:
virtual ~IUI() = default;
// ========================================
// LIFECYCLE
// ========================================
virtual void initialize(const json& config) = 0;
virtual bool update() = 0;
virtual void shutdown() = 0;
// ========================================
// GENERIC DATA FLOW - ENUM VERSIONS
// ========================================
/**
* @brief Display data with type-safe enum
* @param dataType Enum data type
* @param data JSON with content + optional window config:
* {
* "content": {...}, // Actual data to display
* "window": { // Window configuration (optional)
* "id": "window_id",
* "title": "Window Title",
* "parent": "parent_dock_id",
* "dock": "left|right|top|bottom|center|tab",
*
* // SIZE SYSTEM - Hybrid percentage + absolute constraints
* "size": {"width": "20%", "height": 300}, // Target: 20% of parent width, 300px height
* "size": {"width": 400, "height": "50%"}, // Target: 400px width, 50% of parent height
* "size": {"width": "30%", "height": "40%"}, // Target: 30% width, 40% height
*
* "min_size": {"width": 200, "height": 150}, // ABSOLUTE minimum in pixels (always respected)
* "max_size": {"width": 800, "height": "80%"}, // Maximum: 800px width OR 80% of parent (whichever smaller)
*
* "position": {"x": 100, "y": 50},
* "floating": false,
* "resizable": true,
* "closeable": true,
* "collapsible": false
* }
* }
*/
virtual void showData(DataType dataType, const json& data) = 0;
/**
* @brief Display custom data type (fallback to string)
* @param customType Custom data type name
* @param data JSON data
*/
virtual void showDataCustom(const std::string& customType, const json& data) = 0;
/**
* @brief Handle user request with type-safe enum
* @param requestType Enum request type
* @param callback Function to call when request happens
*/
virtual void onRequest(RequestType requestType, std::function<void(const json&)> callback) = 0;
/**
* @brief Handle custom request type (fallback to string)
* @param customType Custom request type name
* @param callback Function to call when request happens
*/
virtual void onRequestCustom(const std::string& customType, std::function<void(const json&)> callback) = 0;
/**
* @brief Show event with type-safe level
* @param level Event level enum
* @param message Human readable text
*/
virtual void showEvent(EventLevel level, const std::string& message) = 0;
// ========================================
// WINDOW MANAGEMENT - ENUM VERSIONS
// ========================================
/**
* @brief Create dock with type-safe enums
* @param dockId Unique dock identifier
* @param type Dock type enum
* @param position Dock position enum
* @param config Additional configuration:
* {
* "parent": "parent_dock_id", // Parent dock (optional)
*
* // HYBRID SIZE SYSTEM
* "size": {"width": "25%", "height": 200}, // Target: 25% of parent width, 200px height
* "min_size": {"width": 200, "height": 100}, // ABSOLUTE minimum pixels (overrides percentage)
* "max_size": {"width": "50%", "height": 600}, // Maximum: 50% of parent OR 600px (whichever smaller)
*
* "orientation": "horizontal", // For SPLIT type
* "collapsible": true, // Can be collapsed
* "resizable": true, // Can be resized
* "tabs": true // Enable tabbed interface
* }
*/
virtual void createDock(const std::string& dockId, DockType type, DockPosition position, const json& config = {}) = 0;
/**
* @brief Create split dock with orientation
* @param dockId Unique dock identifier
* @param orientation Split orientation
* @param config Additional configuration:
* {
* "parent": "parent_dock_id", // Parent dock (optional)
* "size": {"width": 300, "height": 200}, // Initial size
* "min_size": {"width": 100, "height": 50}, // Minimum split size in pixels
* "max_size": {"width": 1000, "height": 800}, // Maximum split size in pixels
* "split_ratio": 0.5, // Split ratio (0.0 to 1.0)
* "min_panel_size": 80, // Minimum size for each panel in split
* "resizable": true // Can be resized by dragging splitter
* }
*/
virtual void createSplit(const std::string& dockId, Orientation orientation, const json& config = {}) = 0;
/**
* @brief Close window or dock
* @param windowId Window/dock ID to close
*/
virtual void closeWindow(const std::string& windowId) = 0;
/**
* @brief Focus window
* @param windowId Window ID to focus
*/
virtual void focusWindow(const std::string& windowId) = 0;
// ========================================
// GENERIC STATE
// ========================================
virtual json getState() const = 0;
virtual void setState(const json& state) = 0;
// ========================================
// CONVENIENCE METHODS WITH ENUMS
// ========================================
void info(const std::string& message) {
showEvent(EventLevel::INFO, message);
}
void success(const std::string& message) {
showEvent(EventLevel::SUCCESS, message);
}
void warning(const std::string& message) {
showEvent(EventLevel::WARNING, message);
}
void error(const std::string& message) {
showEvent(EventLevel::ERROR, message);
}
void debug(const std::string& message) {
showEvent(EventLevel::DEBUG, message);
}
};
// ========================================
// ENUM TO STRING CONVERSIONS (for implementations)
// ========================================
/**
* @brief Convert DataType enum to string (for implementations that need strings)
*/
constexpr const char* toString(DataType type) {
switch (type) {
case DataType::ECONOMY: return "economy";
case DataType::MAP: return "map";
case DataType::INVENTORY: return "inventory";
case DataType::CONSOLE: return "console";
case DataType::PERFORMANCE: return "performance";
case DataType::COMPANIES: return "companies";
case DataType::ALERTS: return "alerts";
case DataType::PRODUCTION: return "production";
case DataType::LOGISTICS: return "logistics";
case DataType::PLAYER: return "player";
case DataType::SETTINGS: return "settings";
case DataType::DEBUG: return "debug";
case DataType::CUSTOM: return "custom";
default: return "unknown";
}
}
constexpr const char* toString(RequestType type) {
switch (type) {
case RequestType::GET_PRICES: return "get_prices";
case RequestType::GET_CHUNK: return "get_chunk";
case RequestType::MOVE_PLAYER: return "move_player";
case RequestType::SAVE_GAME: return "save_game";
case RequestType::LOAD_GAME: return "load_game";
case RequestType::CLOSE_WINDOW: return "close_window";
case RequestType::FOCUS_WINDOW: return "focus_window";
case RequestType::UPDATE_SETTINGS: return "update_settings";
case RequestType::EXECUTE_COMMAND: return "execute_command";
case RequestType::CUSTOM: return "custom";
default: return "unknown";
}
}
constexpr const char* toString(EventLevel level) {
switch (level) {
case EventLevel::INFO: return "info";
case EventLevel::SUCCESS: return "success";
case EventLevel::WARNING: return "warning";
case EventLevel::ERROR: return "error";
case EventLevel::DEBUG: return "debug";
case EventLevel::TRACE: return "trace";
default: return "unknown";
}
}
constexpr const char* toString(DockType type) {
switch (type) {
case DockType::DOCK: return "dock";
case DockType::SPLIT: return "split";
case DockType::TABBED: return "tabbed";
case DockType::FLOATING: return "floating";
default: return "unknown";
}
}
constexpr const char* toString(DockPosition pos) {
switch (pos) {
case DockPosition::LEFT: return "left";
case DockPosition::RIGHT: return "right";
case DockPosition::TOP: return "top";
case DockPosition::BOTTOM: return "bottom";
case DockPosition::CENTER: return "center";
case DockPosition::TAB: return "tab";
default: return "unknown";
}
}
constexpr const char* toString(Orientation orient) {
switch (orient) {
case Orientation::HORIZONTAL: return "horizontal";
case Orientation::VERTICAL: return "vertical";
default: return "unknown";
}
}
} // namespace warfactory

View File

@ -1,707 +0,0 @@
#pragma once
#include "IUI_Enums.h"
#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>
#include <GLFW/glfw3.h>
#include <GL/gl.h>
#include <map>
#include <vector>
#include <string>
#include <functional>
#include <chrono>
namespace warfactory {
/**
* @brief ImGui implementation of IUI interface
*
* Provides full windowing system with docking, tabs, splits, and floating windows.
* Handles hybrid percentage + pixel sizing with automatic constraint enforcement.
*/
class ImGuiUI : public IUI {
private:
// ========================================
// CORE STATE
// ========================================
GLFWwindow* window = nullptr;
bool initialized = false;
bool should_close = false;
int frame_count = 0;
// Screen/parent sizes for percentage calculations
ImVec2 screen_size = {1400, 900};
ImVec2 previous_screen_size = {0, 0};
// ========================================
// WINDOW MANAGEMENT
// ========================================
struct WindowInfo {
std::string id;
std::string title;
std::string parent;
DockPosition dock_position = DockPosition::CENTER;
bool is_open = true;
bool is_floating = false;
bool resizable = true;
bool closeable = true;
// Size system
ImVec2 size = {400, 300};
ImVec2 min_size = {100, 100};
ImVec2 max_size = {2000, 1500};
ImVec2 position = {0, 0};
// Percentage tracking
std::string size_width_percent = "";
std::string size_height_percent = "";
std::string min_width_percent = "";
std::string min_height_percent = "";
std::string max_width_percent = "";
std::string max_height_percent = "";
// Content
DataType data_type = DataType::CUSTOM;
json content_data;
};
std::map<std::string, WindowInfo> windows;
struct DockInfo {
std::string id;
DockType type = DockType::DOCK;
DockPosition position = DockPosition::LEFT;
std::string parent;
bool collapsible = true;
bool resizable = true;
ImVec2 size = {300, 200};
ImVec2 min_size = {100, 100};
ImVec2 max_size = {1000, 800};
std::vector<std::string> child_windows;
};
std::map<std::string, DockInfo> docks;
// ========================================
// CALLBACKS
// ========================================
std::map<RequestType, std::function<void(const json&)>> request_callbacks;
std::map<std::string, std::function<void(const json&)>> custom_request_callbacks;
// ========================================
// MESSAGE SYSTEM
// ========================================
struct LogMessage {
EventLevel level;
std::string message;
std::chrono::steady_clock::time_point timestamp;
};
std::vector<LogMessage> log_messages;
static constexpr size_t MAX_LOG_MESSAGES = 100;
public:
ImGuiUI() = default;
~ImGuiUI() override { shutdown(); }
// ========================================
// LIFECYCLE IMPLEMENTATION
// ========================================
void initialize(const json& config) override {
if (initialized) return;
// Initialize GLFW
if (!glfwInit()) {
throw std::runtime_error("Failed to initialize GLFW");
}
// OpenGL 3.3 Core
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create window
std::string title = config.value("title", "Warfactory ImGui UI");
auto window_size = config.value("window_size", json{{"width", 1400}, {"height", 900}});
if (window_size.is_object()) {
screen_size.x = window_size.value("width", 1400);
screen_size.y = window_size.value("height", 900);
} else {
screen_size.x = 1400;
screen_size.y = 900;
}
window = glfwCreateWindow(
static_cast<int>(screen_size.x),
static_cast<int>(screen_size.y),
title.c_str(), nullptr, nullptr
);
if (!window) {
glfwTerminate();
throw std::runtime_error("Failed to create GLFW window");
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1); // VSync
// Initialize ImGui
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
// Note: Docking features depend on ImGui docking branch
// Using manual docking simulation for compatibility
// Basic style setup
ImGui::StyleColorsDark();
// Platform/Renderer backends
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 330 core");
initialized = true;
}
bool update() override {
if (!initialized || !window) return false;
if (glfwWindowShouldClose(window)) {
should_close = true;
return false;
}
// Update screen size for percentage calculations
int fb_width, fb_height;
glfwGetFramebufferSize(window, &fb_width, &fb_height);
ImVec2 new_screen_size = {static_cast<float>(fb_width), static_cast<float>(fb_height)};
// Detect screen size changes and recalculate if needed
if (new_screen_size.x != previous_screen_size.x || new_screen_size.y != previous_screen_size.y) {
if (frame_count > 0) { // Skip first frame (initialization)
debug("🔄 Screen size changed: " + std::to_string((int)new_screen_size.x) + "x" + std::to_string((int)new_screen_size.y));
recalculateAllSizes();
}
previous_screen_size = screen_size;
}
screen_size = new_screen_size;
frame_count++;
// Poll events
glfwPollEvents();
// Start ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Render all windows
renderAllWindows();
// Render ImGui
ImGui::Render();
// OpenGL rendering
glViewport(0, 0, static_cast<int>(screen_size.x), static_cast<int>(screen_size.y));
glClearColor(0.45f, 0.55f, 0.60f, 1.00f);
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
return !should_close;
}
void shutdown() override {
if (!initialized) return;
if (window) {
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate();
window = nullptr;
}
initialized = false;
}
private:
// ========================================
// SIZE CALCULATION HELPERS
// ========================================
/**
* @brief Parse size value - handles both pixels and percentages
*/
float parseSize(const json& size_value, float parent_size, float default_size) {
try {
if (size_value.is_number()) {
return size_value.get<float>();
}
if (size_value.is_string()) {
std::string size_str = size_value.get<std::string>();
if (!size_str.empty() && size_str.back() == '%') {
float percent = std::stof(size_str.substr(0, size_str.length() - 1));
return (percent / 100.0f) * parent_size;
} else {
// String but not percentage - try to parse as number
return std::stof(size_str);
}
}
} catch (...) {
// Any JSON or parsing error - return default
}
// Neither number nor string or error - return default
return default_size;
}
/**
* @brief Calculate effective size with hybrid constraints
*/
ImVec2 calculateEffectiveSize(const WindowInfo& win, ImVec2 parent_size) {
// Use already parsed sizes (converted in showData)
float target_width = win.size.x;
float target_height = win.size.y;
// Calculate constraint bounds
float min_width = win.min_size.x;
float min_height = win.min_size.y;
float max_width = win.max_size.x;
float max_height = win.max_size.y;
// Apply constraints (clamp)
float final_width = std::max(min_width, std::min(target_width, max_width));
float final_height = std::max(min_height, std::min(target_height, max_height));
return {final_width, final_height};
}
/**
* @brief Calculate window position based on docking
*/
ImVec2 calculateDockedPosition(const WindowInfo& win, ImVec2 size) {
if (win.parent.empty() || win.is_floating) {
// For windows without parent, use explicit position or calculate smart default
debug("🔍 Checking position for '" + win.id + "': pos=" +
std::to_string(win.position.x) + "," + std::to_string(win.position.y) +
" floating=" + (win.is_floating ? "true" : "false"));
// Only use explicit position if it was actually set by user (not just default values)
if (win.position.x > 10 && win.position.y > 10) {
debug("📌 Using explicit position for '" + win.id + "'");
return win.position; // Use explicit position
} else {
// Simple approach: use actual window sizes from economy_main window
float left_edge_end = 252; // Real end of economy_main (we know it's 252px wide)
float top_edge_end = 88; // Real end of toolbar + margin
// Find the right sidebar start by looking for info_panel_main
float right_edge_start = 1050; // We know info_panel starts at 1050px
debug("🔧 Simple positioning for window '" + win.id + "': left_end=" +
std::to_string(left_edge_end) + "px, right_start=" +
std::to_string(right_edge_start) + "px, top_end=" +
std::to_string(top_edge_end) + "px");
// Position directly against the real edge of existing windows
float x = left_edge_end; // Directly touching end of left sidebar (252px)
float y = top_edge_end; // Directly below toolbar (88px)
// If window would overlap with right sidebar, push it left to touch right edge
if (x + size.x > right_edge_start) {
x = right_edge_start - size.x; // Touch right sidebar windows
}
debug("🎯 Calculated position for '" + win.id + "': " +
std::to_string(x) + "," + std::to_string(y) +
" (touching real window edges)");
return {x, y};
}
}
// Find parent dock
auto dock_it = docks.find(win.parent);
if (dock_it == docks.end()) {
return {0, 0}; // Parent dock not found
}
const DockInfo& dock = dock_it->second;
// Calculate dock area based on position
switch (dock.position) {
case DockPosition::LEFT:
return {0, 80}; // Left edge but below toolbar (72px + margin)
case DockPosition::RIGHT:
return {screen_size.x - dock.size.x, 80}; // Right edge but below toolbar
case DockPosition::TOP:
// Top edge - if dock spans full width, start at 0, else offset
if (dock.size.x >= screen_size.x * 0.9f) {
return {0, 0}; // Full width toolbar starts at screen edge
} else {
return {280, 0}; // Partial width toolbar starts after sidebar
}
case DockPosition::BOTTOM:
return {0, screen_size.y - dock.size.y}; // Bottom edge
case DockPosition::CENTER:
default:
return {screen_size.x * 0.5f - size.x * 0.5f, screen_size.y * 0.5f - size.y * 0.5f}; // Center
}
}
// ========================================
// RECALCULATION METHODS
// ========================================
void recalculateAllSizes() {
// Recalculate dock sizes
for (auto& [dock_id, dock] : docks) {
// Recalculate dock size if it uses percentages
recalculateDockSize(dock);
}
// Recalculate window sizes
for (auto& [window_id, win] : windows) {
recalculateWindowSize(win);
}
}
void recalculateDockSize(DockInfo& dock) {
// Re-parse dock size with new screen size
// This would need the original JSON config, for now just log
debug("📐 Recalculating dock: " + dock.id);
// TODO: Store original percentage strings to recalculate properly
}
void recalculateWindowSize(WindowInfo& win) {
// Re-parse window size with new screen/parent sizes
debug("📐 Recalculating window: " + win.id);
// Recalculate width if percentage
if (!win.size_width_percent.empty()) {
float parent_width = screen_size.x;
if (!win.parent.empty() && docks.find(win.parent) != docks.end()) {
parent_width = docks[win.parent].size.x;
}
win.size.x = parseSize(win.size_width_percent, parent_width, 400);
}
// Recalculate height if percentage
if (!win.size_height_percent.empty()) {
float parent_height = screen_size.y;
if (!win.parent.empty() && docks.find(win.parent) != docks.end()) {
parent_height = docks[win.parent].size.y;
}
win.size.y = parseSize(win.size_height_percent, parent_height, 300);
}
}
// ========================================
// RENDERING IMPLEMENTATION
// ========================================
void renderAllWindows() {
// Log screen size for debugging (only first frame to avoid spam)
if (frame_count == 1) {
debug("🖥️ Screen Size: " + std::to_string((int)screen_size.x) + "x" + std::to_string((int)screen_size.y) + "px");
info("🏗️ Manual docking system active (simulated docking layout)");
}
for (auto& [window_id, win] : windows) {
if (!win.is_open) continue;
if (frame_count <= 5) { // Log first 5 frames for each window
debug("🪟 Window: " + window_id + " (" + win.title + ")");
debug(" 📐 Target Size: " + std::to_string((int)win.size.x) + "x" + std::to_string((int)win.size.y) + "px");
debug(" 📏 Size %: width='" + win.size_width_percent + "' height='" + win.size_height_percent + "'");
debug(" ⚖️ Constraints: min=" + std::to_string((int)win.min_size.x) + "x" + std::to_string((int)win.min_size.y) +
" max=" + std::to_string((int)win.max_size.x) + "x" + std::to_string((int)win.max_size.y));
debug(" 🔗 Docking: parent='" + win.parent + "' position=" + std::to_string((int)win.dock_position));
}
// Calculate effective size with constraints
ImVec2 effective_size = calculateEffectiveSize(win, screen_size);
if (frame_count <= 5) {
debug(" ✅ Effective Size: " + std::to_string((int)effective_size.x) + "x" + std::to_string((int)effective_size.y) + "px");
}
// Set window constraints
ImGui::SetNextWindowSizeConstraints(win.min_size, win.max_size);
// Set window size
if (win.is_floating) {
// For floating windows, force initial size and position
ImGuiCond size_condition = (frame_count <= 3) ? ImGuiCond_Always : ImGuiCond_FirstUseEver;
ImGui::SetNextWindowSize(effective_size, size_condition);
// Calculate smart position that avoids dock overlaps
ImVec2 floating_position = calculateDockedPosition(win, effective_size);
ImGuiCond position_condition = (frame_count <= 3) ? ImGuiCond_Always : ImGuiCond_FirstUseEver;
ImGui::SetNextWindowPos(floating_position, position_condition);
if (frame_count <= 5) {
debug(" 🎈 Floating Position: " + std::to_string((int)floating_position.x) + "," + std::to_string((int)floating_position.y));
}
} else {
// For docked windows, calculate position and force it during initial frames
ImVec2 dock_position = calculateDockedPosition(win, effective_size);
ImGuiCond condition = (frame_count <= 3) ? ImGuiCond_Always : ImGuiCond_FirstUseEver;
ImGui::SetNextWindowSize(effective_size, condition);
ImGui::SetNextWindowPos(dock_position, condition);
if (frame_count <= 5) {
debug(" 📍 Docked Position: " + std::to_string((int)dock_position.x) + "," + std::to_string((int)dock_position.y));
}
}
// Window flags
ImGuiWindowFlags flags = ImGuiWindowFlags_None;
if (!win.resizable) flags |= ImGuiWindowFlags_NoResize;
// Render window
if (ImGui::Begin(win.title.c_str(), win.closeable ? &win.is_open : nullptr, flags)) {
// Log actual ImGui window size after rendering (first 5 frames only)
if (frame_count <= 5) {
ImVec2 current_size = ImGui::GetWindowSize();
ImVec2 current_pos = ImGui::GetWindowPos();
debug(" 🎯 ImGui Actual: pos=" + std::to_string((int)current_pos.x) + "," + std::to_string((int)current_pos.y) +
" size=" + std::to_string((int)current_size.x) + "x" + std::to_string((int)current_size.y) + "px");
}
renderWindowContent(win);
}
ImGui::End();
}
}
void renderWindowContent(const WindowInfo& win) {
switch (win.data_type) {
case DataType::ECONOMY:
renderEconomyContent(win.content_data);
break;
case DataType::MAP:
renderMapContent(win.content_data);
break;
case DataType::INVENTORY:
renderInventoryContent(win.content_data);
break;
case DataType::CONSOLE:
renderConsoleContent(win.content_data);
break;
case DataType::PERFORMANCE:
renderPerformanceContent(win.content_data);
break;
case DataType::COMPANIES:
renderCompaniesContent(win.content_data);
break;
case DataType::ALERTS:
renderAlertsContent(win.content_data);
break;
case DataType::SETTINGS:
renderSettingsContent(win.content_data);
break;
default:
renderGenericContent(win.content_data);
break;
}
}
public:
// ========================================
// IUI INTERFACE IMPLEMENTATION - DATA DISPLAY
// ========================================
void showData(DataType dataType, const json& data) override {
// Extract window configuration
json window_config = data.value("window", json{});
json content = data.value("content", data);
// Generate ID if not provided
std::string window_id = window_config.value("id", "window_" + std::to_string(windows.size()));
// Create or update window info
WindowInfo& win = windows[window_id];
win.id = window_id;
win.title = window_config.value("title", toString(dataType));
win.data_type = dataType;
win.content_data = content;
win.is_open = true;
// Parse parent first (needed for size calculations)
win.parent = window_config.value("parent", "");
// Parse size configuration with percentage support
if (window_config.contains("size")) {
auto size_config = window_config["size"];
if (size_config.is_object()) {
if (size_config.contains("width")) {
auto width_val = size_config["width"];
if (width_val.is_string()) {
win.size_width_percent = width_val.get<std::string>();
debug("🔧 Processing width percentage '" + win.size_width_percent +
"' for window '" + win.id + "' with parent='" + win.parent + "'");
// Calculate parent size for percentage - use dock size if docked
float parent_width = screen_size.x;
if (!win.parent.empty() && docks.find(win.parent) != docks.end()) {
parent_width = docks[win.parent].size.x;
debug("🔍 Found parent dock '" + win.parent + "' with width=" +
std::to_string((int)parent_width) + "px");
} else if (!win.parent.empty()) {
debug("❌ Parent dock '" + win.parent + "' not found! Using screen width.");
}
win.size.x = parseSize(width_val, parent_width, 400);
} else if (width_val.is_number()) {
win.size.x = width_val.get<float>();
} else {
win.size.x = 400; // Default fallback
}
}
if (size_config.contains("height")) {
auto height_val = size_config["height"];
if (height_val.is_string()) {
win.size_height_percent = height_val.get<std::string>();
float parent_height = screen_size.y;
if (!win.parent.empty() && docks.find(win.parent) != docks.end()) {
parent_height = docks[win.parent].size.y;
}
win.size.y = parseSize(height_val, parent_height, 300);
} else if (height_val.is_number()) {
win.size.y = height_val.get<float>();
} else {
win.size.y = 300; // Default fallback
}
}
}
}
// Parse constraints
if (window_config.contains("min_size")) {
auto min_config = window_config["min_size"];
if (min_config.is_object()) {
if (min_config.contains("width")) {
win.min_size.x = parseSize(min_config["width"], screen_size.x, 100);
} else {
win.min_size.x = 100;
}
if (min_config.contains("height")) {
win.min_size.y = parseSize(min_config["height"], screen_size.y, 100);
} else {
win.min_size.y = 100;
}
}
}
if (window_config.contains("max_size")) {
auto max_config = window_config["max_size"];
if (max_config.is_object()) {
if (max_config.contains("width")) {
win.max_size.x = parseSize(max_config["width"], screen_size.x, 2000);
} else {
win.max_size.x = 2000;
}
if (max_config.contains("height")) {
win.max_size.y = parseSize(max_config["height"], screen_size.y, 1500);
} else {
win.max_size.y = 1500;
}
}
}
// Parse other properties
win.is_floating = window_config.value("floating", false);
win.resizable = window_config.value("resizable", true);
win.closeable = window_config.value("closeable", true);
// Parse dock position if specified
if (window_config.contains("dock")) {
std::string dock_str = window_config["dock"].get<std::string>();
if (dock_str == "left") win.dock_position = DockPosition::LEFT;
else if (dock_str == "right") win.dock_position = DockPosition::RIGHT;
else if (dock_str == "top") win.dock_position = DockPosition::TOP;
else if (dock_str == "bottom") win.dock_position = DockPosition::BOTTOM;
else if (dock_str == "tab") win.dock_position = DockPosition::CENTER; // tabs go in center
else win.dock_position = DockPosition::CENTER;
}
if (window_config.contains("position")) {
auto pos = window_config["position"];
if (pos.is_object()) {
win.position.x = pos.value("x", 0);
win.position.y = pos.value("y", 0);
}
}
}
void showDataCustom(const std::string& customType, const json& data) override {
// Treat as generic data with custom type in title
json modified_data = data;
if (!modified_data.contains("window")) {
modified_data["window"] = json{};
}
if (!modified_data["window"].contains("title")) {
modified_data["window"]["title"] = customType;
}
showData(DataType::CUSTOM, modified_data);
}
// ========================================
// IUI INTERFACE IMPLEMENTATION - REQUESTS & EVENTS
// ========================================
void onRequest(RequestType requestType, std::function<void(const json&)> callback) override;
void onRequestCustom(const std::string& customType, std::function<void(const json&)> callback) override;
void showEvent(EventLevel level, const std::string& message) override;
// ========================================
// WINDOW MANAGEMENT IMPLEMENTATION
// ========================================
void createDock(const std::string& dockId, DockType type, DockPosition position, const json& config = {}) override;
void createSplit(const std::string& dockId, Orientation orientation, const json& config = {}) override;
void closeWindow(const std::string& windowId) override;
void focusWindow(const std::string& windowId) override;
// ========================================
// STATE MANAGEMENT
// ========================================
json getState() const override;
void setState(const json& state) override;
private:
// ========================================
// CONTENT RENDERING IMPLEMENTATIONS
// ========================================
void renderEconomyContent(const json& content);
void renderMapContent(const json& content);
void renderInventoryContent(const json& content);
void renderConsoleContent(const json& content);
void renderPerformanceContent(const json& content);
void renderCompaniesContent(const json& content);
void renderAlertsContent(const json& content);
void renderSettingsContent(const json& content);
void renderGenericContent(const json& content);
void renderLogConsole();
};
} // namespace warfactory

View File

@ -1,546 +0,0 @@
#include "warfactory/ImGuiUI.h"
#include <sstream>
#include <iomanip>
#include <iostream>
namespace warfactory {
// ========================================
// IUI INTERFACE IMPLEMENTATION - REQUESTS & EVENTS
// ========================================
void ImGuiUI::onRequest(RequestType requestType, std::function<void(const json&)> callback) {
request_callbacks[requestType] = callback;
}
void ImGuiUI::onRequestCustom(const std::string& customType, std::function<void(const json&)> callback) {
custom_request_callbacks[customType] = callback;
}
void ImGuiUI::showEvent(EventLevel level, const std::string& message) {
LogMessage log_msg;
log_msg.level = level;
log_msg.message = message;
log_msg.timestamp = std::chrono::steady_clock::now();
log_messages.push_back(log_msg);
// Keep only last MAX_LOG_MESSAGES
if (log_messages.size() > MAX_LOG_MESSAGES) {
log_messages.erase(log_messages.begin());
}
// Also output to console for debugging
const char* level_str = toString(level);
std::cout << "[" << level_str << "] " << message << std::endl;
}
// ========================================
// WINDOW MANAGEMENT IMPLEMENTATION
// ========================================
void ImGuiUI::createDock(const std::string& dockId, DockType type, DockPosition position, const json& config) {
DockInfo& dock = docks[dockId];
dock.id = dockId;
dock.type = type;
dock.position = position;
dock.parent = config.value("parent", "");
// Parse size with percentage support
if (config.contains("size")) {
auto size_config = config["size"];
if (size_config.is_object()) {
if (size_config.contains("width")) {
dock.size.x = parseSize(size_config["width"], screen_size.x, 300);
} else {
dock.size.x = 300; // Default
}
if (size_config.contains("height")) {
dock.size.y = parseSize(size_config["height"], screen_size.y, 200);
} else {
dock.size.y = 200; // Default
}
}
}
if (config.contains("min_size")) {
auto min_config = config["min_size"];
if (min_config.is_object()) {
if (min_config.contains("width")) {
dock.min_size.x = parseSize(min_config["width"], screen_size.x, 100);
} else {
dock.min_size.x = 100;
}
if (min_config.contains("height")) {
dock.min_size.y = parseSize(min_config["height"], screen_size.y, 100);
} else {
dock.min_size.y = 100;
}
}
}
if (config.contains("max_size")) {
auto max_config = config["max_size"];
if (max_config.is_object()) {
if (max_config.contains("width")) {
dock.max_size.x = parseSize(max_config["width"], screen_size.x, 1000);
} else {
dock.max_size.x = 1000;
}
if (max_config.contains("height")) {
dock.max_size.y = parseSize(max_config["height"], screen_size.y, 800);
} else {
dock.max_size.y = 800;
}
}
}
dock.collapsible = config.value("collapsible", true);
dock.resizable = config.value("resizable", true);
// Debug logging for dock creation
showEvent(EventLevel::DEBUG, "🏗️ Created dock '" + dockId + "': " + std::string(toString(type)) +
" size=" + std::to_string((int)dock.size.x) + "x" + std::to_string((int)dock.size.y) + "px");
showEvent(EventLevel::INFO, "Created " + std::string(toString(type)) + " dock: " + dockId);
}
void ImGuiUI::createSplit(const std::string& dockId, Orientation orientation, const json& config) {
// Create as a split dock
json split_config = config;
split_config["orientation"] = toString(orientation);
createDock(dockId, DockType::SPLIT, DockPosition::CENTER, split_config);
}
void ImGuiUI::closeWindow(const std::string& windowId) {
auto it = windows.find(windowId);
if (it != windows.end()) {
it->second.is_open = false;
showEvent(EventLevel::INFO, "Closed window: " + windowId);
}
}
void ImGuiUI::focusWindow(const std::string& windowId) {
auto it = windows.find(windowId);
if (it != windows.end()) {
ImGui::SetWindowFocus(it->second.title.c_str());
showEvent(EventLevel::DEBUG, "Focused window: " + windowId);
}
}
// ========================================
// STATE MANAGEMENT
// ========================================
json ImGuiUI::getState() const {
json state;
state["frame_count"] = frame_count;
state["window_open"] = !should_close;
state["screen_size"] = {{"width", screen_size.x}, {"height", screen_size.y}};
// Save window states
json window_states = json::object();
for (const auto& [id, win] : windows) {
window_states[id] = {
{"is_open", win.is_open},
{"size", {{"width", win.size.x}, {"height", win.size.y}}},
{"position", {{"x", win.position.x}, {"y", win.position.y}}},
{"floating", win.is_floating}
};
}
state["windows"] = window_states;
return state;
}
void ImGuiUI::setState(const json& state) {
if (state.contains("windows")) {
for (const auto& [id, win_state] : state["windows"].items()) {
auto it = windows.find(id);
if (it != windows.end()) {
auto& win = it->second;
win.is_open = win_state.value("is_open", true);
if (win_state.contains("size")) {
auto size_state = win_state["size"];
if (size_state.is_object()) {
win.size.x = size_state.value("width", win.size.x);
win.size.y = size_state.value("height", win.size.y);
}
}
if (win_state.contains("position")) {
auto pos_state = win_state["position"];
if (pos_state.is_object()) {
win.position.x = pos_state.value("x", win.position.x);
win.position.y = pos_state.value("y", win.position.y);
}
}
win.is_floating = win_state.value("floating", win.is_floating);
}
}
}
}
// ========================================
// CONTENT RENDERING IMPLEMENTATIONS
// ========================================
void ImGuiUI::renderEconomyContent(const json& content) {
ImGui::Text("💰 Economy Dashboard");
ImGui::Separator();
if (content.contains("prices")) {
ImGui::Text("Market Prices:");
ImGui::BeginTable("prices_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg);
ImGui::TableSetupColumn("Item");
ImGui::TableSetupColumn("Price");
ImGui::TableSetupColumn("Trend");
ImGui::TableHeadersRow();
for (const auto& [item, price] : content["prices"].items()) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s", item.c_str());
ImGui::TableNextColumn();
if (price.is_number()) {
ImGui::Text("%.2f", price.get<float>());
} else {
ImGui::Text("%s", price.dump().c_str());
}
ImGui::TableNextColumn();
// Show trend if available
if (content.contains("trends") && content["trends"].contains(item)) {
std::string trend = content["trends"][item];
if (trend[0] == '+') {
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "%s", trend.c_str());
} else if (trend[0] == '-') {
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "%s", trend.c_str());
} else {
ImGui::Text("%s", trend.c_str());
}
} else {
ImGui::Text("--");
}
}
ImGui::EndTable();
}
ImGui::Spacing();
// Action buttons
if (ImGui::Button("🔄 Refresh Prices")) {
if (request_callbacks.count(RequestType::GET_PRICES)) {
request_callbacks[RequestType::GET_PRICES]({});
}
}
ImGui::SameLine();
if (ImGui::Button("📊 Market Analysis")) {
if (custom_request_callbacks.count("market_analysis")) {
custom_request_callbacks["market_analysis"]({});
}
}
}
void ImGuiUI::renderMapContent(const json& content) {
ImGui::Text("🗺️ Global Map");
ImGui::Separator();
if (content.contains("current_chunk")) {
auto chunk = content["current_chunk"];
if (chunk.is_object()) {
ImGui::Text("Current Chunk: (%d, %d)", chunk.value("x", 0), chunk.value("y", 0));
}
}
if (content.contains("tiles")) {
ImGui::Text("Map Display:");
// Navigation controls
if (ImGui::Button("⬆️")) {
if (request_callbacks.count(RequestType::GET_CHUNK)) {
request_callbacks[RequestType::GET_CHUNK]({{"action", "move_up"}});
}
}
if (ImGui::Button("⬅️")) {
if (request_callbacks.count(RequestType::GET_CHUNK)) {
request_callbacks[RequestType::GET_CHUNK]({{"action", "move_left"}});
}
}
ImGui::SameLine();
if (ImGui::Button("➡️")) {
if (request_callbacks.count(RequestType::GET_CHUNK)) {
request_callbacks[RequestType::GET_CHUNK]({{"action", "move_right"}});
}
}
if (ImGui::Button("⬇️")) {
if (request_callbacks.count(RequestType::GET_CHUNK)) {
request_callbacks[RequestType::GET_CHUNK]({{"action", "move_down"}});
}
}
// Simple tile grid representation
ImGui::Text("Tile Grid (sample):");
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 8; x++) {
if (x > 0) ImGui::SameLine();
// Generate simple tile representation
char tile_str[2] = "."; // Null-terminated string
if ((x + y) % 3 == 0) tile_str[0] = 'I'; // Iron
else if ((x + y) % 5 == 0) tile_str[0] = 'C'; // Copper
else if ((x + y) % 7 == 0) tile_str[0] = 'T'; // Tree
ImGui::Button(tile_str, ImVec2(20, 20));
}
}
}
ImGui::Spacing();
if (ImGui::Button("🔄 Refresh Map")) {
if (request_callbacks.count(RequestType::GET_CHUNK)) {
request_callbacks[RequestType::GET_CHUNK]({{"type", "refresh"}});
}
}
}
void ImGuiUI::renderInventoryContent(const json& content) {
ImGui::Text("🎒 Inventory");
ImGui::Separator();
if (content.contains("items")) {
ImGui::BeginTable("inventory_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg);
ImGui::TableSetupColumn("Item");
ImGui::TableSetupColumn("Quantity");
ImGui::TableSetupColumn("Reserved");
ImGui::TableHeadersRow();
for (const auto& item : content["items"]) {
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::Text("%s", item.value("name", "Unknown").c_str());
ImGui::TableNextColumn();
ImGui::Text("%d", item.value("quantity", 0));
ImGui::TableNextColumn();
ImGui::Text("%d", item.value("reserved", 0));
}
ImGui::EndTable();
}
}
void ImGuiUI::renderConsoleContent(const json& content) {
ImGui::Text("🖥️ Console");
ImGui::Separator();
// Console output area
ImGui::BeginChild("console_output", ImVec2(0, -30), true);
if (content.contains("logs")) {
for (const auto& log : content["logs"]) {
std::string level = log.value("level", "info");
std::string message = log.value("message", "");
std::string timestamp = log.value("timestamp", "");
// Color based on level
if (level == "error") {
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "[%s] %s - %s",
timestamp.c_str(), level.c_str(), message.c_str());
} else if (level == "warning") {
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "[%s] %s - %s",
timestamp.c_str(), level.c_str(), message.c_str());
} else if (level == "success") {
ImGui::TextColored(ImVec4(0.0f, 1.0f, 0.0f, 1.0f), "[%s] %s - %s",
timestamp.c_str(), level.c_str(), message.c_str());
} else {
ImGui::Text("[%s] %s - %s", timestamp.c_str(), level.c_str(), message.c_str());
}
}
}
ImGui::EndChild();
// Command input
static char command_buffer[256] = "";
ImGui::SetNextItemWidth(-1);
if (ImGui::InputText("##command", command_buffer, sizeof(command_buffer),
ImGuiInputTextFlags_EnterReturnsTrue)) {
if (custom_request_callbacks.count("console_command")) {
custom_request_callbacks["console_command"]({{"command", std::string(command_buffer)}});
}
command_buffer[0] = '\0'; // Clear buffer
}
}
void ImGuiUI::renderPerformanceContent(const json& content) {
ImGui::Text("📊 Performance Monitor");
ImGui::Separator();
if (content.contains("fps")) {
ImGui::Text("FPS: %d", content.value("fps", 0));
}
if (content.contains("frame_time")) {
ImGui::Text("Frame Time: %s", content.value("frame_time", "0ms").c_str());
}
if (content.contains("memory_usage")) {
ImGui::Text("Memory: %s", content.value("memory_usage", "0MB").c_str());
}
if (content.contains("entities")) {
ImGui::Text("Entities: %d", content.value("entities", 0));
}
// Real-time FPS display
ImGui::Spacing();
ImGui::Text("Real-time FPS: %.1f", ImGui::GetIO().Framerate);
}
void ImGuiUI::renderCompaniesContent(const json& content) {
ImGui::Text("🏢 Companies");
ImGui::Separator();
for (const auto& [company_name, company_data] : content.items()) {
if (ImGui::CollapsingHeader(company_name.c_str())) {
if (company_data.contains("cash")) {
ImGui::Text("💰 Cash: $%d", company_data.value("cash", 0));
}
if (company_data.contains("status")) {
ImGui::Text("📊 Status: %s", company_data.value("status", "unknown").c_str());
}
if (company_data.contains("strategy")) {
ImGui::Text("🎯 Strategy: %s", company_data.value("strategy", "none").c_str());
}
}
}
}
void ImGuiUI::renderAlertsContent(const json& content) {
ImGui::Text("⚠️ Alerts");
ImGui::Separator();
if (content.contains("urgent_alerts")) {
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "🚨 URGENT:");
for (const auto& alert : content["urgent_alerts"]) {
if (alert.is_string()) {
ImGui::BulletText("%s", alert.get<std::string>().c_str());
} else {
ImGui::BulletText("%s", alert.dump().c_str());
}
}
}
if (content.contains("warnings")) {
ImGui::TextColored(ImVec4(1.0f, 1.0f, 0.0f, 1.0f), "⚠️ Warnings:");
for (const auto& warning : content["warnings"]) {
if (warning.is_string()) {
ImGui::BulletText("%s", warning.get<std::string>().c_str());
} else {
ImGui::BulletText("%s", warning.dump().c_str());
}
}
}
ImGui::Spacing();
if (ImGui::Button("✅ Acknowledge All")) {
if (custom_request_callbacks.count("acknowledge_alerts")) {
custom_request_callbacks["acknowledge_alerts"]({});
}
}
}
void ImGuiUI::renderSettingsContent(const json& content) {
ImGui::Text("⚙️ Settings");
ImGui::Separator();
if (content.contains("graphics")) {
if (ImGui::CollapsingHeader("🖥️ Graphics")) {
auto graphics = content["graphics"];
if (graphics.is_object()) {
ImGui::Text("Resolution: %s", graphics.value("resolution", "Unknown").c_str());
bool fullscreen = graphics.value("fullscreen", false);
if (ImGui::Checkbox("Fullscreen", &fullscreen)) {
// Handle setting change
}
bool vsync = graphics.value("vsync", true);
if (ImGui::Checkbox("VSync", &vsync)) {
// Handle setting change
}
}
}
}
if (content.contains("audio")) {
if (ImGui::CollapsingHeader("🔊 Audio")) {
auto audio = content["audio"];
if (audio.is_object()) {
float master_vol = audio.value("master_volume", 1.0f);
if (ImGui::SliderFloat("Master Volume", &master_vol, 0.0f, 1.0f)) {
// Handle setting change
}
float effects_vol = audio.value("effects_volume", 1.0f);
if (ImGui::SliderFloat("Effects Volume", &effects_vol, 0.0f, 1.0f)) {
// Handle setting change
}
}
}
}
}
void ImGuiUI::renderGenericContent(const json& content) {
ImGui::Text("📄 Data");
ImGui::Separator();
// Generic JSON display
std::ostringstream oss;
oss << content.dump(2); // Pretty print with 2-space indent
ImGui::TextWrapped("%s", oss.str().c_str());
}
void ImGuiUI::renderLogConsole() {
// Always visible log console at bottom
ImGui::SetNextWindowSize(ImVec2(screen_size.x, 200), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(0, screen_size.y - 200), ImGuiCond_FirstUseEver);
if (ImGui::Begin("📜 System Log", nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize)) {
ImGui::BeginChild("log_scroll", ImVec2(0, 150), true);
for (const auto& log_msg : log_messages) {
auto duration = log_msg.timestamp.time_since_epoch();
auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() % 100000;
const char* level_str = toString(log_msg.level);
// Color based on level
ImVec4 color = {1.0f, 1.0f, 1.0f, 1.0f}; // Default white
switch (log_msg.level) {
case EventLevel::ERROR: color = {1.0f, 0.0f, 0.0f, 1.0f}; break;
case EventLevel::WARNING: color = {1.0f, 1.0f, 0.0f, 1.0f}; break;
case EventLevel::SUCCESS: color = {0.0f, 1.0f, 0.0f, 1.0f}; break;
case EventLevel::DEBUG: color = {0.7f, 0.7f, 0.7f, 1.0f}; break;
case EventLevel::INFO:
default: color = {1.0f, 1.0f, 1.0f, 1.0f}; break;
}
ImGui::TextColored(color, "[%05lld] [%s] %s",
millis, level_str, log_msg.message.c_str());
}
// Auto-scroll to bottom
if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
ImGui::SetScrollHereY(1.0f);
}
ImGui::EndChild();
}
ImGui::End();
}
} // namespace warfactory

78
src/modules/map/CLAUDE.md Normal file
View 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.

View 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")

View 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

View File

@ -0,0 +1,261 @@
#pragma once
#include <cstdint>
#include <algorithm>
#include <cmath>
namespace warfactory {
struct GTile {
// ========================================
// CORE DATA (16 bytes total) - Complete tile data
// ========================================
uint16_t elevation; // Elevation: 0-65535 = -32km to +32km (geological range)
int16_t temperature; // Temperature: -32768 to +32767 = -3276°C to +3276°C (0.1°C increments)
uint16_t biome_type_id; // Biome classification
uint8_t water_token; // Water/rain tokens from climate simulation
uint8_t wind_token; // Wind tokens from climate simulation
int8_t target_budget_score; // Target budget score: -10 to +10
uint16_t destruction_token; // Bits 1-4: highWind, 5-8: flood, 9-12: hurricane, 13-16: reserved
uint16_t flags; // Tile properties and state flags
uint32_t feature_set_id; // Features present on this tile (0 = no features)
/**
* @brief Constructor with default values
*/
GTile() : elevation(0), temperature(-1000), biome_type_id(0), water_token(0), wind_token(0),
target_budget_score(0), destruction_token(0), flags(0), feature_set_id(0) {}
// ========================================
// ELEVATION CONVERSION (same as WorldTileData)
// ========================================
/**
* @brief Convert elevation to meters (geological range: -32km to +32km)
*/
float getElevationMeters() const {
return (elevation / 65535.0f) * 64000.0f - 32000.0f;
}
/**
* @brief Set elevation from meters
*/
void setElevationMeters(float meters) {
float normalized = (meters + 32000.0f) / 64000.0f;
elevation = static_cast<uint16_t>(std::clamp(normalized * 65535.0f, 0.0f, 65535.0f));
}
// ========================================
// TEMPERATURE CONVERSION (same as WorldTileData)
// ========================================
/**
* @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));
}
// ========================================
// BIOME & CLIMATE DATA
// ========================================
/**
* @brief Get biome type ID
*/
uint16_t getBiomeTypeId() const { return biome_type_id; }
/**
* @brief Set biome type ID
*/
void setBiomeTypeId(uint16_t biome_id) { biome_type_id = biome_id; }
/**
* @brief Get water tokens from climate simulation
*/
uint8_t getWaterToken() const { return water_token; }
/**
* @brief Set water tokens
*/
void setWaterToken(uint8_t tokens) { water_token = tokens; }
/**
* @brief Add water tokens
*/
void addWaterToken(uint8_t additional_tokens) {
uint16_t new_total = static_cast<uint16_t>(water_token) + additional_tokens;
water_token = static_cast<uint8_t>(std::min(new_total, static_cast<uint16_t>(255)));
}
/**
* @brief Get wind tokens from climate simulation
*/
uint8_t getWindToken() const { return wind_token; }
/**
* @brief Set wind tokens
*/
void setWindToken(uint8_t tokens) { wind_token = tokens; }
/**
* @brief Add wind tokens
*/
void addWindToken(uint8_t additional_tokens) {
uint16_t new_total = static_cast<uint16_t>(wind_token) + additional_tokens;
wind_token = static_cast<uint8_t>(std::min(new_total, static_cast<uint16_t>(255)));
}
// ========================================
// DESTRUCTION TOKEN (packed in 16 bits)
// ========================================
/**
* @brief Get high wind token (bits 1-4)
*/
uint8_t getHighWindToken() const {
return destruction_token & 0x0F;
}
/**
* @brief Set high wind token (0-15)
*/
void setHighWindToken(uint8_t tokens) {
destruction_token = (destruction_token & 0xFFF0) | (tokens & 0x0F);
}
/**
* @brief Get flood token (bits 5-8)
*/
uint8_t getFloodToken() const {
return (destruction_token >> 4) & 0x0F;
}
/**
* @brief Set flood token (0-15)
*/
void setFloodToken(uint8_t tokens) {
destruction_token = (destruction_token & 0xFF0F) | ((tokens & 0x0F) << 4);
}
/**
* @brief Get hurricane token (bits 9-12)
*/
uint8_t getHurricaneToken() const {
return (destruction_token >> 8) & 0x0F;
}
/**
* @brief Set hurricane token (0-15)
*/
void setHurricaneToken(uint8_t tokens) {
destruction_token = (destruction_token & 0xF0FF) | ((tokens & 0x0F) << 8);
}
/**
* @brief Add high wind tokens
*/
void addHighWindToken(uint8_t additional) {
uint8_t current = getHighWindToken();
setHighWindToken(std::min(static_cast<uint8_t>(current + additional), static_cast<uint8_t>(15)));
}
/**
* @brief Add flood tokens
*/
void addFloodToken(uint8_t additional) {
uint8_t current = getFloodToken();
setFloodToken(std::min(static_cast<uint8_t>(current + additional), static_cast<uint8_t>(15)));
}
/**
* @brief Add hurricane tokens
*/
void addHurricaneToken(uint8_t additional) {
uint8_t current = getHurricaneToken();
setHurricaneToken(std::min(static_cast<uint8_t>(current + additional), static_cast<uint8_t>(15)));
}
// ========================================
// BUDGET SYSTEM
// ========================================
/**
* @brief Get target budget score (-10 to +10)
*/
int8_t getTargetBudgetScore() const { return target_budget_score; }
/**
* @brief Set target budget score
*/
void setTargetBudgetScore(int8_t score) { target_budget_score = score; }
// ========================================
// FLAGS & FEATURES
// ========================================
/**
* @brief Get tile flags
*/
uint16_t getFlags() const { return flags; }
/**
* @brief Set specific flag
*/
void setFlag(uint16_t flag, bool value) {
if (value) {
flags |= flag;
} else {
flags &= ~flag;
}
}
/**
* @brief Check if flag is set
*/
bool hasFlag(uint16_t flag) const { return (flags & flag) != 0; }
/**
* @brief Get feature set ID
*/
uint32_t getFeatureSetId() const { return feature_set_id; }
/**
* @brief Set feature set ID
*/
void setFeatureSetId(uint32_t feature_id) { feature_set_id = feature_id; }
/**
* @brief Check if tile has features
*/
bool hasFeatures() const { return feature_set_id != 0; }
// ========================================
// PHASE 1 OPERATIONS
// ========================================
/**
* @brief Apply heat from meteorite impact
*/
void applyImpactHeat(float heat_celsius) {
float current_temp = getTemperatureCelsius();
setTemperatureCelsius(current_temp + heat_celsius);
}
/**
* @brief Cool tile by given amount
*/
void coolTile(float cooling_celsius) {
float current_temp = getTemperatureCelsius();
setTemperatureCelsius(current_temp - cooling_celsius);
}
};
} // namespace warfactory

View File

@ -0,0 +1,35 @@
#pragma once
#include "IAttachedElement.h"
#include "IElementData.h"
#include <memory>
namespace warfactory {
class IRegion : public IAttachedElement {
public:
virtual ~IRegion() = default;
virtual void setPosition(float x, float y) = 0;
virtual void setMass(float mass) = 0;
virtual void setRadius(float radius) = 0;
virtual std::unique_ptr<IElementData> getRegionData() const = 0;
virtual void setRegionData(std::unique_ptr<IElementData> data) = 0;
virtual void updatePosition(float delta_x, float delta_y) = 0;
virtual void updateMass(float delta_mass) = 0;
virtual void updateRadius(float delta_radius) = 0;
virtual float getAttachmentStrength(int attached_element_id) const = 0;
virtual void setAttachmentStrength(int attached_element_id, float strength) = 0;
virtual bool canFuseWith(const IRegion& other) const = 0;
virtual void fuseWith(const IRegion& other) = 0;
};
} // namespace warfactory

Some files were not shown because too many files have changed in this diff Show More