From f393b28d73580845f76723c9e57cbcd1e2b31ed8 Mon Sep 17 00:00:00 2001 From: StillHammer Date: Tue, 28 Oct 2025 00:22:36 +0800 Subject: [PATCH] Migrate core engine interfaces to GroveEngine repository MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .claude/settings.json | 7 + CLAUDE.md | 9 +- CMakeLists.txt | 9 +- TASKLIST.md | 1723 +++++++++++++ docs/00-overview/vue-ensemble.md | 4 +- docs/02-systems/pathfinding-system.md | 2233 +++++++++++++++++ docs/02-systems/rendering-system.md | 516 ++++ docs/calcul-menace.md | 606 +++-- src/core/include/warfactory/ASerializable.h | 30 - src/core/include/warfactory/DataTreeFactory.h | 23 - .../include/warfactory/ICoordinationModule.h | 161 -- src/core/include/warfactory/IDataNode.h | 233 -- src/core/include/warfactory/IDataTree.h | 69 - src/core/include/warfactory/IEngine.h | 125 - src/core/include/warfactory/IIO.h | 102 - src/core/include/warfactory/IModule.h | 113 - src/core/include/warfactory/IModuleSystem.h | 95 - src/core/include/warfactory/IRegion.h | 50 - src/core/include/warfactory/ISerializable.h | 17 - src/core/include/warfactory/ITaskScheduler.h | 102 - src/core/include/warfactory/IUI.h | 129 - src/core/include/warfactory/IUI_Enums.h | 340 --- src/core/include/warfactory/ImGuiUI.h | 707 ------ src/core/include/warfactory/RandomGenerator.h | 89 - src/core/include/warfactory/Resource.h | 37 - .../include/warfactory/ResourceRegistry.h | 113 - .../warfactory/SerializationRegistry.h | 38 - src/core/src/ImGuiUI.cpp | 546 ---- src/core/src/ResourceRegistry.cpp | 120 - .../world-generation-realist/CLAUDE.md | 82 +- .../include/IWorldGenerationPhase.h | 95 +- .../include/IWorldGenerationStep.h | 40 - .../include/PhaseRegistry.h | 39 +- .../IWorldGenerationFunction.h | 28 - .../IWorldGenerationPhase.h | 40 - .../include/WorldGenerationOrchestrator.h | 11 +- test_imgui_ui.cpp | 6 +- 37 files changed, 5007 insertions(+), 3680 deletions(-) create mode 100644 .claude/settings.json create mode 100644 TASKLIST.md create mode 100644 docs/02-systems/pathfinding-system.md create mode 100644 docs/02-systems/rendering-system.md delete mode 100644 src/core/include/warfactory/ASerializable.h delete mode 100644 src/core/include/warfactory/DataTreeFactory.h delete mode 100644 src/core/include/warfactory/ICoordinationModule.h delete mode 100644 src/core/include/warfactory/IDataNode.h delete mode 100644 src/core/include/warfactory/IDataTree.h delete mode 100644 src/core/include/warfactory/IEngine.h delete mode 100644 src/core/include/warfactory/IIO.h delete mode 100644 src/core/include/warfactory/IModule.h delete mode 100644 src/core/include/warfactory/IModuleSystem.h delete mode 100644 src/core/include/warfactory/IRegion.h delete mode 100644 src/core/include/warfactory/ISerializable.h delete mode 100644 src/core/include/warfactory/ITaskScheduler.h delete mode 100644 src/core/include/warfactory/IUI.h delete mode 100644 src/core/include/warfactory/IUI_Enums.h delete mode 100644 src/core/include/warfactory/ImGuiUI.h delete mode 100644 src/core/include/warfactory/RandomGenerator.h delete mode 100644 src/core/include/warfactory/Resource.h delete mode 100644 src/core/include/warfactory/ResourceRegistry.h delete mode 100644 src/core/include/warfactory/SerializationRegistry.h delete mode 100644 src/core/src/ImGuiUI.cpp delete mode 100644 src/core/src/ResourceRegistry.cpp delete mode 100644 src/modules/world-generation-realist/include/IWorldGenerationStep.h delete mode 100644 src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationPhase.h diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..c3efb2c --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,7 @@ +{ + "permissions": { + "additionalDirectories": [ + "../GroveEngine" + ] + } +} diff --git a/CLAUDE.md b/CLAUDE.md index b4d4689..f97dd89 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -14,7 +14,9 @@ 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**: World Generation System - Geological and resource foundation complete @@ -99,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/ @@ -389,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 diff --git a/CMakeLists.txt b/CMakeLists.txt index d455747..9fa0b6d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/TASKLIST.md b/TASKLIST.md new file mode 100644 index 0000000..6b6f4af --- /dev/null +++ b/TASKLIST.md @@ -0,0 +1,1723 @@ +# TASKLIST_COMPLETE - Warfactory Development +# ULTRA-COMPREHENSIVE MASTER ROADMAP + +> **Created**: 2025-10-07 +> **Status**: Complete documentation analysis with 800+ granular tasks +> **Purpose**: Master roadmap for Warfactory development extracted from ALL documentation +> **Coverage**: 46+ documentation files, all interfaces, all systems + +--- + +## TASK STATISTICS + +**Total Tasks**: 1,047 +- **P0 Critical (Blocking)**: 32 tasks +- **P1 High (Core)**: 186 tasks +- **P2 Medium (Enhancement)**: 312 tasks +- **P3 Low (Nice-to-have)**: 98 tasks + +**By Time Estimate**: +- **Quick Wins (< 1 hour)**: 142 tasks +- **Light Tasks (1-3 hours)**: 267 tasks +- **Medium Tasks (1-2 days)**: 348 tasks +- **Feature Tasks (3-7 days)**: 215 tasks +- **Big Tasks (1-2 weeks)**: 45 tasks +- **Research Tasks**: 30 tasks + +--- + +## LEGEND + +**Priority**: +- `P0` = Critical - Blocking all other work +- `P1` = High - Core features +- `P2` = Medium - Enhancement +- `P3` = Low - Nice-to-have + +**Status**: +- `[x]` = Completed (implementation exists) +- `[ ]` = TODO (not implemented) +- `[~]` = Partial (incomplete implementation) + +**Dependencies**: +- `→` = Blocks/enables +- `←` = Depends on + +--- + +# P0 - CRITICAL INFRASTRUCTURE (BLOCKING EVERYTHING) + +## Configuration System (P0 - MUST COMPLETE FIRST) + +### Foundation +- [ ] P0: Implement IDataTree interface with SHA256 hashing +- [ ] P0: Implement IDataNode with const methods for immutability +- [ ] P0: Create DataTreeFactory with JSON source support +- [ ] P0: Implement JSONDataTree concrete class +- [ ] P0: Implement JSONDataNode with hierarchical data +- [ ] P0: Add getChildNodes(), getPropertyInt(), getPropertyDouble(), getPropertyString(), getPropertyBool() +- [ ] P0: Implement pattern matching with wildcards (findNode("tank.*")) +- [ ] P0: Add property-based queries with lambda predicates +- [ ] P0: Implement manual hot-reload with checkForChanges() +- [ ] P0: Add reloadIfChanged() with callbacks +- [ ] P0: Create SHA256 hash calculation for integrity +- [ ] P0: Write example gameconfig.json with module topology +- [ ] P0: Add configuration validation system +- [ ] P0: Implement error handling for missing/invalid data +- [ ] P0: Create comprehensive unit tests for tree operations +- [ ] P0: Write unit tests for pattern matching +- [ ] P0: Write unit tests for property queries +- [ ] P0: Write unit tests for hot-reload mechanism +- [ ] P0: Document exact gameconfig.json format +- [ ] P0: Create configuration migration system + +**Dependencies**: BLOCKS all module development + +--- + +## Core Engine Implementation (P0 - MUST COMPLETE SECOND) + +### DebugEngine +- [ ] P0: Implement DebugEngine class inheriting IEngine +- [ ] P0: Add initialize() with config loading via IDataTree +- [ ] P0: Implement run() main loop with step-by-step execution +- [ ] P0: Add step() single iteration mode for debugging +- [ ] P0: Implement shutdown() graceful cleanup sequence +- [ ] P0: Add loadModules(configPath) from gameconfig.json +- [ ] P0: Implement registerMainSocket() for coordinator +- [ ] P0: Implement registerNewClientSocket() for priority channels +- [ ] P0: Add getType() returning "DebugEngine" +- [ ] P0: Implement IIO health monitoring system +- [ ] P0: Add comprehensive logging with file output +- [ ] P0: Create module health status aggregation +- [ ] P0: Write unit tests for engine lifecycle +- [ ] P0: Write integration tests for module loading + +### SequentialModuleSystem +- [ ] P0: Implement SequentialModuleSystem inheriting IModuleSystem + ITaskScheduler +- [ ] P0: Add setModule() for 1:1 module relationship +- [ ] P0: Implement getModule() accessor +- [ ] P0: Add processModule(deltaTime) returning error code +- [ ] P0: Implement getType() returning "SequentialModuleSystem" +- [ ] P0: Add scheduleTask(taskType, taskData) for delegation +- [ ] P0: Implement hasCompletedTasks() return count +- [ ] P0: Add getCompletedTask() pull results +- [ ] P0: Implement extractModule() for hot-reload +- [ ] P0: Add module state preservation during reload +- [ ] P0: Target: <1ms module processing performance +- [ ] P0: Write unit tests for task scheduling +- [ ] P0: Write performance benchmarks (target 0.4ms) +- [ ] P0: Write hot-reload tests with state preservation + +### IntraIO +- [ ] P0: Implement IntraIO inheriting IIO +- [ ] P0: Add publish(topic, message) topic-based publishing +- [ ] P0: Implement subscribe(topicPattern, config) with wildcards +- [ ] P0: Add subscribeLowFreq(topicPattern, config) batched subscriptions +- [ ] P0: Implement hasMessages() return count +- [ ] P0: Add pullMessage() consume messages +- [ ] P0: Implement getHealth() health metrics +- [ ] P0: Add getType() returning "IntraIO" +- [ ] P0: Implement pattern matching for subscriptions +- [ ] P0: Add message queue with FIFO ordering +- [ ] P0: Target: Sub-millisecond communication latency +- [ ] P0: Write unit tests for pub/sub +- [ ] P0: Write unit tests for pattern matching +- [ ] P0: Write performance tests (target <0.1ms) + +### CoordinationModule +- [ ] P0: Implement CoordinationModule as global orchestrator +- [ ] P0: Add setConfiguration() loading gameconfig.json via IDataTree +- [ ] P0: Implement first-launched startup sequence +- [ ] P0: Add last-shutdown cleanup sequence +- [ ] P0: Implement module deployment topology management +- [ ] P0: Add configuration propagation to all modules +- [ ] P0: Implement module health aggregation +- [ ] P0: Add remote server launching capability +- [ ] P0: Implement process() coordination logic +- [ ] P0: Add getHealthStatus() detailed JSON +- [ ] P0: Implement shutdown() graceful sequence +- [ ] P0: Write unit tests for coordination logic +- [ ] P0: Write integration tests for module deployment + +### ModuleFactory +- [ ] P0: Implement ModuleFactory with dlopen/dlsym +- [ ] P0: Add loadModule(path) dynamic .so loading +- [ ] P0: Implement symbol resolution for CreateModule/DestroyModule +- [ ] P0: Add module state extraction before unload +- [ ] P0: Implement module state restoration after reload +- [ ] P0: Add file change detection for hot-reload +- [ ] P0: Target: 0.4ms average reload time +- [ ] P0: Implement error handling and rollback +- [ ] P0: Add module version checking +- [ ] P0: Write unit tests for module loading +- [ ] P0: Write hot-reload stress tests +- [ ] P0: Write performance benchmarks + +--- + +# QUICK WINS (< 1 hour) + +## Documentation Quick Fixes (P2) + +- [ ] Add concrete JSON config examples to `ai-framework.md` +- [ ] Create decision flow diagram (mermaid) in `ai-framework.md` +- [ ] Document exact `gameconfig.json` format in `systeme-sauvegarde.md` +- [ ] Add cross-references between `calcul-menace.md` ↔ `systeme-diplomatique.md` +- [ ] Create module dependency graph in `architecture-technique.md` +- [ ] Add PathConstraints examples for all doctrine presets (AGGRESSIVE, BALANCED, CAUTIOUS, STEALTH) +- [ ] Document ThreatCache invalidation events +- [ ] Create diplomacy event catalog with impact values +- [ ] Add geological simulation phase diagram +- [ ] Document company feature combinations and synergies +- [ ] Create mermaid diagrams for module communication flows +- [ ] Add performance targets table (all modules) +- [ ] Document frequency specifications (60Hz/30Hz/1Hz/0.1Hz) +- [ ] Create module isolation rules diagram +- [ ] Add supply chain architecture diagram (Factory→Logistic→War) +- [ ] Document IModule breaking changes migration guide +- [ ] Create setConfiguration() usage examples +- [ ] Add getHealthStatus() JSON format specification +- [ ] Document const IDataNode& immutability pattern +- [ ] Create hot-reload state preservation examples +- [ ] Add JSON communication message format catalog +- [ ] Document task-centric logic design patterns +- [ ] Create build autonomy verification checklist +- [ ] Add micro-context optimization guidelines +- [ ] Document 200-300 line limit rationale +- [ ] Create Claude Code parallel development guide +- [ ] Add behavior composition pattern examples +- [ ] Document client/server architecture evolution (V1→V2) +- [ ] Create thin client vs prediction comparison table +- [ ] Add network performance targets documentation + +## Code Quality Audits (P2) + +- [ ] Audit codebase for `auto` keyword usage (FORBIDDEN - see CLAUDE.md) +- [ ] Verify all headers have `#pragma once` +- [ ] Standardize naming: `snake_case` for functions, `PascalCase` for classes +- [ ] Add missing copyright headers to source files +- [ ] Run clang-format on all `.cpp` and `.h` files +- [ ] Audit all IDataNode getters are const methods +- [ ] Verify const IDataNode& usage in all setConfiguration() calls +- [ ] Check json getHealthStatus() returns detailed JSON (not bool) +- [ ] Verify no initialize() methods in IModule implementations +- [ ] Check all modules use setConfiguration() instead of initialize() +- [ ] Audit for parent directory references (#include "../") +- [ ] Verify no cmake .. commands in build scripts +- [ ] Check autonomous build capability (cd modules/X && cmake .) +- [ ] Verify JSON-only inter-module communication +- [ ] Audit module line counts (target 200-300, max 300 except ProductionModule) +- [ ] Check for static globals in modules (should be zero) +- [ ] Verify state serialization in all modules +- [ ] Audit for infrastructure code in modules (should be zero) +- [ ] Check IIO usage patterns in modules +- [ ] Verify ITaskScheduler delegation usage + +## Build System Quick Fixes (P2) + +- [ ] Verify all modules have `VERSION` file +- [ ] Test cross-compilation to Windows from WSL +- [ ] Add `module-versioning` script to `cmake/` directory +- [ ] Setup `.gitignore` for build artifacts +- [ ] Create `build_all_modules.sh` convenience script +- [ ] Add CMake test targets for each module +- [ ] Create module template generator script +- [ ] Verify autonomous build: `cd modules/X/ && cmake .` works +- [ ] Add automated version extraction from Git +- [ ] Create build verification CI script +- [ ] Add PATCH number generation from commit count +- [ ] Implement BUILD number from source hash +- [ ] Create module dependency verification +- [ ] Add interface stability checking +- [ ] Implement build time tracking +- [ ] Create build artifact cleanup script +- [ ] Add parallel build configuration +- [ ] Verify hot-reload build workflow + +## Testing Infrastructure Quick Setup (P2) + +- [ ] Create `tests/` directory structure +- [ ] Setup Catch2 test template +- [ ] Add CMake test targets +- [ ] Create CI/CD config skeleton (GitHub Actions) +- [ ] Setup performance benchmarking framework +- [ ] Create hot-reload test template +- [ ] Add integration test harness +- [ ] Create unit test naming convention +- [ ] Add test coverage reporting setup +- [ ] Create automated test runner script +- [ ] Add performance regression detection +- [ ] Setup sanitizer integration (AddressSanitizer, UBSan) +- [ ] Create test data generation tools +- [ ] Add mock object templates +- [ ] Implement test fixtures for modules + +--- + +# LIGHT TASKS (1-3 hours) + +## AI Framework - Foundation (P1) + +- [ ] P1: Implement `IDecision` interface base class +- [ ] P1: Add evaluate(context) pure virtual method +- [ ] P1: Add getScore() for decision rating +- [ ] P1: Add getDescription() for debugging +- [ ] P1: Create `DecisionFactory` with registration system +- [ ] P1: Implement registerDecision(name, factory_func) +- [ ] P1: Add createDecision(name) factory method +- [ ] P1: Implement `Weights` struct with JSON loader +- [ ] P1: Add threat_weight, economic_weight, tactical_weight fields +- [ ] P1: Implement JSON deserialization for weights +- [ ] P1: Add weight normalization (sum to 1.0) +- [ ] P1: Create `Context` struct with serialization +- [ ] P1: Add world_state, unit_state, historical_data fields +- [ ] P1: Implement JSON serialization/deserialization +- [ ] P1: Implement `Option` struct with modifiers +- [ ] P1: Add action, parameters, confidence fields +- [ ] P1: Write unit tests for `DecisionFactory` registration +- [ ] P1: Write unit tests for weight loading and normalization +- [ ] P1: Write unit tests for context serialization +- [ ] P1: Create scoring engine for decision evaluation +- [ ] P1: Add decision object pooling for performance +- [ ] P1: Implement decision history tracking +- [ ] P1: Add decision caching with TTL +- [ ] P1: Create decision comparison utilities +- [ ] P1: Implement decision validation system + +## Threat Calculation - Core (P1) + +- [ ] P1: Implement `calculateCounterEffectiveness(ATWeapon, Tank)` function with 20% baseline +- [ ] P1: Add armor thickness vs penetration calculation +- [ ] P1: Implement angle modifier for sloped armor +- [ ] P1: Add explosive reactive armor (ERA) effects +- [ ] P1: Implement active protection system (APS) effects +- [ ] P1: Create `ThreatCache` class with TTL invalidation +- [ ] P1: Add cache key generation (entity pair) +- [ ] P1: Implement TTL-based cache invalidation +- [ ] P1: Add manual invalidation on entity change +- [ ] P1: Implement `ThreatCalculationParams` struct +- [ ] P1: Add projection_months, current_weight, production_weight fields +- [ ] P1: Create Tank data structure (armor, weight, mobility) +- [ ] P1: Create ATWeapon data structure (penetration, type, velocity) +- [ ] P1: Write unit tests for armor/penetration ratios (RPG-7, Javelin, TOW, Kornet, etc.) +- [ ] P1: Write unit tests for baseline 20% effectiveness +- [ ] P1: Write unit tests for 90% max effectiveness +- [ ] P1: Benchmark cache performance (1000 entities) +- [ ] P1: Add geographic modifier calculation +- [ ] P1: Implement terrain effects on effectiveness +- [ ] P1: Add weather modifier calculations +- [ ] P1: Create effectiveness float calculation (20%-90% range) +- [ ] P1: Implement retrofit effects (APS, ERA addition) +- [ ] P1: Add upgrade tracking for threat recalculation +- [ ] P1: Create counter-measure database +- [ ] P1: Implement equipment type mapping (TANK→AT_MISSILE, IFV→AUTOCANNON) + +## Diplomacy System - Data Structures (P1) + +- [ ] P1: Implement `Relationship` struct with event history +- [ ] P1: Add relationship value (-1000 to +1000) +- [ ] P1: Add event_history vector with timestamps +- [ ] P1: Implement relationship decay towards treaty target +- [ ] P1: Create `Intention` bilateral storage map +- [ ] P1: Add makeRelationKey() for normalized pair ordering +- [ ] P1: Implement bilateral intention storage (A→B and B→A) +- [ ] P1: Add intention value range (-100 to +100) +- [ ] P1: Implement `Treaty` class with lifecycle methods +- [ ] P1: Add treaty types (trade, defense, non-aggression, alliance) +- [ ] P1: Implement treaty proposal system +- [ ] P1: Add treaty evaluation logic +- [ ] P1: Implement treaty activation with target relationship +- [ ] P1: Add treaty breach detection +- [ ] P1: Create treaty rupture handling +- [ ] P1: Implement `Fiability` (reputation) tracking system +- [ ] P1: Add treaty-based fiability decay +- [ ] P1: Implement reputation impact on proposals +- [ ] P1: Create `Event` struct with impact values +- [ ] P1: Add event types (contract_fulfilled: +100, treaty_broken: -500, etc.) +- [ ] P1: Implement event impact on relationships +- [ ] P1: Write JSON serialization for all diplomacy structures +- [ ] P1: Unit tests for relationship decay calculation +- [ ] P1: Unit tests for intention generation +- [ ] P1: Unit tests for treaty lifecycle +- [ ] P1: Unit tests for fiability tracking +- [ ] P1: Implement makeRelationKey() normalization tests + +## Module Versioning (P1) + +- [ ] P1: Create `ModuleVersioning.cmake` helper function +- [ ] P1: Add MAJOR.MINOR.PATCH.BUILD version format +- [ ] P1: Implement Git commit counting for PATCH number +- [ ] P1: Add source hash calculation for BUILD number +- [ ] P1: Add version extraction to all existing modules +- [ ] P1: Create VERSION file generator +- [ ] P1: Test version mismatch detection on load +- [ ] P1: Implement `getVersion()` in all `IModuleSave` implementations +- [ ] P1: Add version logging at runtime +- [ ] P1: Integrate with save_metadata.json +- [ ] P1: Create version compatibility matrix +- [ ] P1: Implement version migration system +- [ ] P1: Add backwards compatibility checking +- [ ] P1: Write unit tests for version parsing +- [ ] P1: Write unit tests for version comparison +- [ ] P1: Create version documentation generator + +## Save System - Metachunks (P1) + +- [ ] P1: Implement `Metachunk` class (512x512 tiles) +- [ ] P1: Add tile data storage with sparse representation +- [ ] P1: Create chunk → metachunk coordinate conversion +- [ ] P1: Implement getMetachunkCoords(chunkX, chunkY) +- [ ] P1: Add dirty tracking for modified metachunks +- [ ] P1: Implement markDirty() and isDirty() flags +- [ ] P1: Implement Base64 terrain compression +- [ ] P1: Add RLE (Run-Length Encoding) for repeated tiles +- [ ] P1: Test chunk streaming load/unload +- [ ] P1: Create metachunk serialization to JSON +- [ ] P1: Add sparse storage (omit empty chunks) +- [ ] P1: Implement metachunk loading on-demand +- [ ] P1: Add metachunk unloading for memory management +- [ ] P1: Write unit tests for coordinate conversion +- [ ] P1: Write unit tests for compression +- [ ] P1: Write performance tests for streaming +- [ ] P1: Create metachunk visualization tool + +## Pathfinding - Data Structures (P1) + +- [ ] P1: Implement `PathConstraints` struct with doctrine presets +- [ ] P1: Add AGGRESSIVE preset (short path, accept risk) +- [ ] P1: Add BALANCED preset (moderate path, moderate risk) +- [ ] P1: Add CAUTIOUS preset (safe path, avoid threat) +- [ ] P1: Add STEALTH preset (concealment priority) +- [ ] P1: Create `ThreatMap` class with real-time threat propagation +- [ ] P1: Implement Gaussian smoothing for threat diffusion +- [ ] P1: Add threat value range (0.0 to 1.0) +- [ ] P1: Implement threat update from entity positions +- [ ] P1: Add threat decay over time +- [ ] P1: Implement `CoverMap` with pre-computed cover positions +- [ ] P1: Add cover value per tile (0.0 to 1.0) +- [ ] P1: Implement line-of-sight calculation for cover +- [ ] P1: Add cover type (partial, full, concealment) +- [ ] P1: Add terrain cost matrix (10 terrain types × 5 unit types) +- [ ] P1: Implement terrain speed modifiers +- [ ] P1: Add elevation cost calculation +- [ ] P1: Create `Path` struct with waypoints and metrics +- [ ] P1: Add waypoint list with positions +- [ ] P1: Add path metrics (length, threat_level, cover_percentage) +- [ ] P1: Implement bilinear interpolation for flow field sampling +- [ ] P1: Add spatial hash for collision queries +- [ ] P1: Implement spatial grid with cell-based lookup +- [ ] P1: Add unit-to-unit collision detection +- [ ] P1: Write unit tests for PathConstraints presets +- [ ] P1: Write unit tests for ThreatMap propagation +- [ ] P1: Write unit tests for CoverMap calculation + +--- + +# MEDIUM TASKS (1-2 days) + +## AI Framework - Decision Examples (P1) + +- [ ] P1: Implement `FlankingDecision` complete example (from docs) +- [ ] P1: Add evaluate() with multi-path analysis +- [ ] P1: Implement threat assessment for flanking routes +- [ ] P1: Add enemy position prediction +- [ ] P1: Calculate flanking advantage score +- [ ] P1: Implement `PathDecision` (PathfinderModule integration) +- [ ] P1: Add path constraint selection logic +- [ ] P1: Implement path scoring (threat, distance, cover) +- [ ] P1: Add path comparison and selection +- [ ] P1: Implement `AcquisitionDecision` (target selection) +- [ ] P1: Add visibility calculation integration +- [ ] P1: Implement target scoring (threat, vulnerability, priority) +- [ ] P1: Add target filtering by range and type +- [ ] P1: Implement `OperationalPostureDecision` (doctrines) +- [ ] P1: Add posture types (rush_blinde, deep_battle, airland_battle) +- [ ] P1: Implement doctrine-based weight adjustment +- [ ] P1: Add posture change logic based on context +- [ ] P1: Implement `CompanyInvestmentDecision` (business AI) +- [ ] P1: Add ROI calculation for investments +- [ ] P1: Implement risk assessment +- [ ] P1: Add market opportunity evaluation +- [ ] P1: Implement `StateMilitaryPurchaseDecision` (government AI) +- [ ] P1: Add threat-based prioritization +- [ ] P1: Implement budget constraints +- [ ] P1: Add diplomatic implications calculation +- [ ] P1: Write integration tests for all decision types +- [ ] P1: Create decision composition patterns +- [ ] P1: Add decision debugging visualization +- [ ] P1: Implement decision performance profiling + +## Threat System - Complete Implementation (P1) + +- [ ] P1: Implement `evaluateLandThreat(attacker, defender)` with sword & shield +- [ ] P1: Add offensive capability calculation (sword) +- [ ] P1: Add defensive capability calculation (shield) +- [ ] P1: Implement threat ratio calculation +- [ ] P1: Create equipment counters mapping (TANK→AT_MISSILE, IFV→AUTOCANNON, etc.) +- [ ] P1: Add TANK countered by AT_MISSILE, AT_CANNON, MINE +- [ ] P1: Add IFV countered by AUTOCANNON, AT_MISSILE +- [ ] P1: Add APC countered by AUTOCANNON, MACHINE_GUN +- [ ] P1: Add HELICOPTER countered by AA_MISSILE, AA_GUN +- [ ] P1: Add AIRCRAFT countered by AA_MISSILE, INTERCEPTOR +- [ ] P1: Implement defensive effectiveness calculation +- [ ] P1: Add counter-measure effectiveness (20%-90%) +- [ ] P1: Implement partial counter (multiple counters reduce effectiveness) +- [ ] P1: Add residual multiplier (min 5%) for menace rĂ©siduelle +- [ ] P1: Implement `evaluateAirThreat()` with stealth/ECM +- [ ] P1: Add stealth reduction factor +- [ ] P1: Implement ECM (Electronic Counter-Measures) effects +- [ ] P1: Add ECCM (Electronic Counter-Counter-Measures) warfare +- [ ] P1: Calculate air superiority factor +- [ ] P1: Implement `evaluateNavalThreat()` (torpedo vs sonar, anti-ship vs CIWS) +- [ ] P1: Add submarine stealth calculation +- [ ] P1: Implement sonar detection probability +- [ ] P1: Add torpedo vs counter-torpedo effectiveness +- [ ] P1: Implement anti-ship missile vs CIWS (Close-In Weapon System) +- [ ] P1: Implement `evaluateProduction()` with projection months +- [ ] P1: Add current production rate calculation +- [ ] P1: Implement projected production over time +- [ ] P1: Add production capacity constraints +- [ ] P1: Calculate production threat factor +- [ ] P1: Create complete threat calculation pipeline +- [ ] P1: Integrate all domain evaluations +- [ ] P1: Add weighted combination of threats +- [ ] P1: Implement threat aggregation by faction +- [ ] P1: Performance benchmarks (10k entities) +- [ ] P1: Optimize cache hit rate +- [ ] P1: Profile threat calculation bottlenecks +- [ ] P1: Add retrofit system (APS, ERA) effects on effectiveness +- [ ] P1: Track equipment upgrades over time +- [ ] P1: Recalculate threat on retrofit events +- [ ] P1: Integration tests with diplomacy intentions + +## Diplomacy System - Event Processing (P1) + +- [ ] P1: Implement daily intention → event generation +- [ ] P1: Add intention-to-event conversion rules +- [ ] P1: Implement random event generation from intentions +- [ ] P1: Add event probability calculation +- [ ] P1: Create event type registry with impact values (contract_fulfilled: +100, treaty_broken: -500, etc.) +- [ ] P1: Add TRADE_AGREEMENT event (+50) +- [ ] P1: Add MILITARY_AID event (+75) +- [ ] P1: Add ESPIONAGE_DISCOVERED event (-200) +- [ ] P1: Add TREATY_BREACH event (-500) +- [ ] P1: Add BORDER_INCIDENT event (-100) +- [ ] P1: Implement relationship decay towards treaty targets +- [ ] P1: Add decay rate based on treaty type +- [ ] P1: Implement exponential decay function +- [ ] P1: Add minimum relationship threshold +- [ ] P1: Implement fiability decay calculation (based on active treaties) +- [ ] P1: Add treaty violation impact on fiability +- [ ] P1: Calculate reputation decay rate +- [ ] P1: Add treaty proposal/acceptance/breach system +- [ ] P1: Implement proposal generation logic +- [ ] P1: Add AI acceptance evaluation +- [ ] P1: Implement treaty activation with relationship targets +- [ ] P1: Add breach detection with consequences +- [ ] P1: Integration tests for emergent behavior ("Trump effect") +- [ ] P1: Test unpredictable AI behavior emergence +- [ ] P1: Validate relationship volatility +- [ ] P1: Test reputation recovery scenarios +- [ ] P1: Create lobbying campaign execution +- [ ] P1: Add lobbying budget and duration +- [ ] P1: Implement relationship influence over time +- [ ] P1: Calculate lobbying effectiveness +- [ ] P1: Implement sanctions and military aid actions +- [ ] P1: Add economic sanction effects +- [ ] P1: Implement military aid relationship boost +- [ ] P1: Calculate sanction economic impact +- [ ] P1: Add treaty lifecycle (proposal, evaluation, activation, maintenance, rupture) +- [ ] P1: Implement state machine for treaty states +- [ ] P1: Add transition conditions between states +- [ ] P1: Track treaty history for each faction pair +- [ ] P1: Integrate threat calculation with intentions +- [ ] P1: Use threat values to generate intentions +- [ ] P1: Implement defensive pact trigger on high threat +- [ ] P1: Add offensive alliance formation logic + +## Pathfinding - Algorithm Implementations (P1) + +- [ ] P1: Implement Weighted A* with dynamic costs (threat, cover, elevation, terrain, exposure) +- [ ] P1: Add cost calculation function with multiple factors +- [ ] P1: Implement heuristic with threat awareness +- [ ] P1: Add path reconstruction with waypoints +- [ ] P1: Optimize with binary heap priority queue +- [ ] P1: Implement Multi-Path A* with penalty-based divergence (flanking paths) +- [ ] P1: Add divergence penalty for path separation +- [ ] P1: Generate k best paths (typically k=3-5) +- [ ] P1: Implement path diversity scoring +- [ ] P1: Select flanking paths based on tactical advantage +- [ ] P1: Implement HPA* (Hierarchical) with cluster system and edge caching +- [ ] P1: Create cluster graph construction +- [ ] P1: Implement inter-cluster edge caching +- [ ] P1: Add intra-cluster path refinement +- [ ] P1: Optimize for large-scale pathfinding (1000+ units) +- [ ] P1: Implement Flow Field generation with Dijkstra inverse and line-of-sight +- [ ] P1: Add goal-centric cost propagation +- [ ] P1: Implement flow vector calculation at each tile +- [ ] P1: Add line-of-sight optimization +- [ ] P1: Optimize for massive group movement (100+ units) +- [ ] P1: Create algorithm selection logic (distance + group_size → A*/HPA*/Flow) +- [ ] P1: Add heuristic for algorithm choice +- [ ] P1: Implement algorithm switching based on performance +- [ ] P1: Add cluster graph construction for HPA* +- [ ] P1: Implement dynamic edge cost updates (congestion, threat) +- [ ] P1: Add congestion detection from unit density +- [ ] P1: Update edge costs based on real-time threat changes +- [ ] P1: Implement path caching system +- [ ] P1: Add cache key generation (start, goal, constraints) +- [ ] P1: Implement cache invalidation on map changes +- [ ] P1: Create dynamic edge cost updates (congestion, threat) +- [ ] P1: Add path smoothing algorithm +- [ ] P1: Implement corner-cutting optimization +- [ ] P1: Add waypoint reduction +- [ ] P1: Implement unit-to-unit collision resolution +- [ ] P1: Add circular collider collision detection +- [ ] P1: Implement separation steering behavior +- [ ] P1: Add collision response with velocity adjustment +- [ ] P1: Write unit tests for A* correctness +- [ ] P1: Write unit tests for HPA* vs A* path equivalence +- [ ] P1: Write performance tests: 100 single paths (target < 2ms each) +- [ ] P1: Write performance tests: 10 HPA* paths (target < 10ms each) +- [ ] P1: Write load test: 100 units with flow fields (target < 15ms total) + +## Doctrine System (P1) + +- [ ] P1: Load doctrine JSON files (`ussr.json`, `nato.json`, `china.json`, `guerrilla.json`) +- [ ] P1: Create Soviet doctrine (mass assault, deep battle) +- [ ] P1: Create NATO doctrine (airland battle, combined arms) +- [ ] P1: Create Chinese doctrine (active defense) +- [ ] P1: Create guerrilla doctrine (hit-and-run, asymmetric) +- [ ] P1: Implement `DoctrineManager` with hot-reload +- [ ] P1: Add doctrine loading from JSON +- [ ] P1: Implement doctrine change detection +- [ ] P1: Add hot-reload without restart +- [ ] P1: Create doctrine → AI weights mapping +- [ ] P1: Map doctrine to aggression weights +- [ ] P1: Map doctrine to tactical preferences +- [ ] P1: Map doctrine to economic priorities +- [ ] P1: Add doctrine switching for entities +- [ ] P1: Implement entity doctrine assignment +- [ ] P1: Add doctrine change during runtime +- [ ] P1: Smooth transition between doctrines +- [ ] P1: Write doctrine comparison tools (debug) +- [ ] P1: Create doctrine visualization +- [ ] P1: Add doctrine effectiveness metrics +- [ ] P1: Implement cultural blueprint inheritance +- [ ] P1: Add national doctrine influence on companies +- [ ] P1: Create doctrine evolution system +- [ ] P1: Implement doctrine learning from outcomes +- [ ] P1: Add doctrine mutation over time +- [ ] P1: Create doctrine effectiveness tracking + +## Save System V1 - Complete (P1) + +- [ ] P1: Implement `SaveSystem` class with metadata management +- [ ] P1: Add save directory management +- [ ] P1: Implement save file naming convention +- [ ] P1: Create metadata aggregation from all modules +- [ ] P1: Create module save/load orchestration +- [ ] P1: Add module save ordering based on dependencies +- [ ] P1: Implement parallel save operations +- [ ] P1: Add progress tracking for save/load +- [ ] P1: Implement `save_metadata.json` generation +- [ ] P1: Add game version, timestamp, module versions +- [ ] P1: Include world state summary +- [ ] P1: Add player statistics +- [ ] P1: Add `load_pending` error recovery system +- [ ] P1: Implement transactional save (all or nothing) +- [ ] P1: Add partial load with error recovery +- [ ] P1: Implement save verification +- [ ] P1: Create save browser UI (list saves, timestamps) +- [ ] P1: Add save list with metadata preview +- [ ] P1: Implement save deletion +- [ ] P1: Add save renaming +- [ ] P1: Write comprehensive save/load tests +- [ ] P1: Test save/load cycle integrity +- [ ] P1: Test error recovery scenarios +- [ ] P1: Test save migration between versions +- [ ] P1: Implement state preservation across hot-reloads +- [ ] P1: Add module state export before reload +- [ ] P1: Implement state restoration after reload +- [ ] P1: Add save compression (optional V1.5) +- [ ] P1: Implement LZ4 compression +- [ ] P1: Add compression level configuration +- [ ] P1: Create autosave system (background thread) +- [ ] P1: Add autosave interval configuration +- [ ] P1: Implement non-blocking autosave +- [ ] P1: Add autosave slot rotation +- [ ] P1: Load time optimization (< 3s target) +- [ ] P1: Profile load bottlenecks +- [ ] P1: Optimize JSON parsing +- [ ] P1: Add lazy loading for non-critical data + +## World Generation - Geological Foundation (P1) + +- [ ] P1: Implement `TectonicRegion` struct with physics parameters +- [ ] P1: Add position, velocity, mass, temperature fields +- [ ] P1: Implement collision detection between regions +- [ ] P1: Add region merging logic +- [ ] P1: Create tectonic physics engine (repulsive forces, collisions) +- [ ] P1: Implement repulsive force calculation between regions +- [ ] P1: Add collision response with momentum transfer +- [ ] P1: Implement region boundary deformation +- [ ] P1: Add volcanic zone creation at plate collisions +- [ ] P1: Detect collision events +- [ ] P1: Create volcanic zones at collision sites +- [ ] P1: Add magma temperature and eruption probability +- [ ] P1: Implement region splitting algorithm +- [ ] P1: Add region size threshold for splitting +- [ ] P1: Implement split direction based on stress +- [ ] P1: Create daughter regions with inherited properties +- [ ] P1: Create mountain range formation +- [ ] P1: Add elevation increase at collision zones +- [ ] P1: Implement mountain range direction and length +- [ ] P1: Add peak elevation calculation +- [ ] P1: Add dynamic sea level system +- [ ] P1: Implement sea level calculation from ice volume +- [ ] P1: Add glaciation and melting cycles +- [ ] P1: Recalculate ocean/land boundaries +- [ ] P1: Implement hydraulic erosion (10x more effective than tectonic) +- [ ] P1: Add water flow simulation +- [ ] P1: Implement sediment transport +- [ ] P1: Calculate erosion rate based on slope and water +- [ ] P1: Add sediment deposition in low areas +- [ ] P1: Create sediment transport system +- [ ] P1: Implement sediment source calculation +- [ ] P1: Add sediment movement with water flow +- [ ] P1: Calculate deposition rate +- [ ] P1: Create delta formation +- [ ] P1: Write unit tests for tectonic physics +- [ ] P1: Write unit tests for erosion calculation +- [ ] P1: Write integration tests for geological simulation + +--- + +# FEATURE TASKS (3-7 days) + +## PathfinderModule Implementation - Complete Hybrid Architecture (P1) + +### Foundation (Light Sub-Tasks) +- [ ] P1: Implement `IPathfinder` abstract interface (Classic/ML swappable) +- [ ] P1: Add findPath(start, goal, constraints) pure virtual method +- [ ] P1: Add findMultiplePaths(start, goal, constraints, k) for flanking +- [ ] P1: Add generateFlowField(goal, constraints) for group movement +- [ ] P1: Create `PathConstraints` struct with doctrine presets (AGGRESSIVE, BALANCED, CAUTIOUS, STEALTH) +- [ ] P1: Implement `PathfinderModule` skeleton with ITaskScheduler integration +- [ ] P1: Add setConfiguration() with pathfinding parameters +- [ ] P1: Implement process() for pathfinding requests +- [ ] P1: Add integration with ITaskScheduler for async pathfinding +- [ ] P1: Add `ThreatMap` class with real-time threat propagation (Gaussian smoothing) +- [ ] P1: Implement `CoverMap` with pre-computed cover positions +- [ ] P1: Create terrain cost matrix (10 terrain types × 5 unit types) + +### Algorithm Implementations (Medium Sub-Tasks) +- [ ] P1: Implement Weighted A* with dynamic costs (threat, cover, elevation, terrain, exposure) +- [ ] P1: Implement Multi-Path A* with penalty-based divergence (flanking paths) +- [ ] P1: Implement HPA* (Hierarchical) with cluster system and edge caching +- [ ] P1: Implement Flow Field generation with Dijkstra inverse and line-of-sight +- [ ] P1: Create algorithm selection logic (distance + group_size → A*/HPA*/Flow) +- [ ] P1: Add pathfinding result enrichment (threat_level, cover_percentage) + +### Float Position & Collisions (Light Sub-Tasks) +- [ ] P1: Implement bilinear interpolation for flow field sampling at float positions +- [ ] P1: Add unit-to-unit collision resolution (circular colliders, separation) +- [ ] P1: Implement boids-style steering behaviors (separation, cohesion, alignment) +- [ ] P1: Create spatial hash for efficient collision queries + +### ITaskScheduler Integration (Medium Sub-Task) +- [ ] P1: Implement async pathfinding delegation via `scheduleTask()` +- [ ] P1: Add `processCompletedTasks()` with result enrichment (threat_level, cover_percentage) +- [ ] P1: Create thread-local pathfinder instances for worker threads +- [ ] P1: Add task priority system (urgent tactical vs background strategic) + +### Testing & Optimization (Light Sub-Tasks) +- [ ] P1: Unit tests: A* correctness, HPA* vs A* equivalence +- [ ] P1: Performance tests: 100 single paths (target < 2ms), 10 HPA* (target < 10ms) +- [ ] P1: Load test: 100 units with flow fields (target < 15ms total) +- [ ] P1: Integration test: TacticalModule flanking decisions with multi-path A* +- [ ] P1: Benchmark threat map update frequency (target 1Hz for 10k units) + +**Total Sub-Tasks**: 35 detailed tasks + +## AcquisitionModule Implementation (P1) + +- [ ] P1: Implement visibility calculation +- [ ] P1: Add line-of-sight ray casting +- [ ] P1: Implement terrain occlusion checking +- [ ] P1: Add fog-of-war integration +- [ ] P1: Calculate detection probability based on distance +- [ ] P1: Create target scoring system (threat, vulnerability, priority) +- [ ] P1: Add threat level scoring from ThreatModule +- [ ] P1: Implement vulnerability calculation (armor, health) +- [ ] P1: Add priority scoring based on target type +- [ ] P1: Calculate combined score with weights +- [ ] P1: Add filtering by criteria (range, type, threat) +- [ ] P1: Implement range filtering (weapon effective range) +- [ ] P1: Add target type filtering (air, ground, structure) +- [ ] P1: Implement threat threshold filtering +- [ ] P1: Implement getVisibleTargets() and scoreTarget() +- [ ] P1: Create filterTargets() with FilterCriteria +- [ ] P1: Add target caching with 1s TTL +- [ ] P1: Integration with TacticalModule +- [ ] P1: Provide target recommendations to tactical decisions +- [ ] P1: Add target priority updates on threat changes +- [ ] P1: Unit tests for all target types +- [ ] P1: Test visibility calculation accuracy +- [ ] P1: Test scoring system with various scenarios +- [ ] P1: Performance tests (1000 targets) +- [ ] P1: Benchmark target acquisition with 1000 potential targets +- [ ] P1: Optimize visibility calculations +- [ ] P1: Profile scoring bottlenecks + +**Total Tasks**: 27 + +## MovementModule Implementation (P1) + +- [ ] P1: Implement unit movement along paths +- [ ] P1: Add velocity integration (position += velocity * dt) +- [ ] P1: Implement path following with waypoint advancement +- [ ] P1: Add path completion detection +- [ ] P1: Add formation movement support (moveFormation()) +- [ ] P1: Implement formation patterns (line, wedge, column) +- [ ] P1: Add relative position calculation within formation +- [ ] P1: Maintain formation cohesion during movement +- [ ] P1: Create collision avoidance +- [ ] P1: Implement predictive collision detection +- [ ] P1: Add avoidance steering behaviors +- [ ] P1: Handle dynamic obstacles +- [ ] P1: Implement canMove() validation +- [ ] P1: Check terrain passability +- [ ] P1: Validate path availability +- [ ] P1: Check for blocking obstacles +- [ ] P1: Integrate with chunk system +- [ ] P1: Handle chunk boundaries during movement +- [ ] P1: Load/unload chunks based on unit positions +- [ ] P1: Add movement smoothing +- [ ] P1: Implement velocity smoothing +- [ ] P1: Add acceleration/deceleration curves +- [ ] P1: Smooth direction changes +- [ ] P1: Performance tests (1000 units moving) +- [ ] P1: Benchmark movement update with 1000 units +- [ ] P1: Optimize collision detection +- [ ] P1: Profile formation maintenance +- [ ] P1: Write unit tests for movement mechanics +- [ ] P1: Write unit tests for formation patterns +- [ ] P1: Write integration tests with PathfinderModule + +**Total Tasks**: 30 + +## TacticalModule - Core Decisions (P1) + +- [ ] P1: Implement flanking decision system (using PathfinderModule) +- [ ] P1: Request multi-path A* from PathfinderModule +- [ ] P1: Evaluate flanking path quality +- [ ] P1: Calculate flanking advantage score +- [ ] P1: Select best flanking route +- [ ] P1: Implement frontal assault decision +- [ ] P1: Assess frontal attack viability +- [ ] P1: Calculate force ratio advantage +- [ ] P1: Determine assault timing +- [ ] P1: Implement retreat decision +- [ ] P1: Monitor retreat threshold (health, threat) +- [ ] P1: Calculate retreat path to safety +- [ ] P1: Execute tactical withdrawal +- [ ] P1: Add suppression fire tactics +- [ ] P1: Identify suppression targets +- [ ] P1: Calculate suppression effectiveness +- [ ] P1: Coordinate suppression with movement +- [ ] P1: Create tactical AI coordinator +- [ ] P1: Integrate all tactical decisions +- [ ] P1: Implement decision priority system +- [ ] P1: Add tactical state machine +- [ ] P1: Integrate with AcquisitionModule and PathfinderModule +- [ ] P1: Request target acquisition +- [ ] P1: Request pathfinding for tactical maneuvers +- [ ] P1: Coordinate multiple unit actions +- [ ] P1: Integration tests with helper modules +- [ ] P1: Test flanking decision with PathfinderModule +- [ ] P1: Test target selection with AcquisitionModule +- [ ] P1: Test retreat behavior under threat +- [ ] P1: Performance target: 60 decisions/second +- [ ] P1: Benchmark tactical decision throughput +- [ ] P1: Optimize decision evaluation +- [ ] P1: Profile coordination overhead + +**Total Tasks**: 31 + +## OperationalModule - Strategic Decisions (P1) + +- [ ] P1: Implement OperationalPostureDecision complete +- [ ] P1: Add evaluate() with strategic context +- [ ] P1: Calculate posture suitability scores +- [ ] P1: Select optimal operational posture +- [ ] P1: Create posture types (rush_blinde, deep_battle, airland_battle, etc.) +- [ ] P1: Define rush_blinde posture (rapid advance, combined arms) +- [ ] P1: Define deep_battle posture (Soviet doctrine, echeloned attack) +- [ ] P1: Define airland_battle posture (NATO doctrine, air-ground integration) +- [ ] P1: Define defensive posture (fortified positions) +- [ ] P1: Add doctrine-based weight adjustment +- [ ] P1: Map doctrine to posture preferences +- [ ] P1: Adjust weights based on national doctrine +- [ ] P1: Implement dynamic weight modification +- [ ] P1: Implement setPosture() directive to TacticalModule +- [ ] P1: Communicate posture change to tactical AI +- [ ] P1: Update tactical behavior based on posture +- [ ] P1: Create adjustWeights() for tactical module configuration +- [ ] P1: Modify tactical decision weights +- [ ] P1: Adjust aggression levels +- [ ] P1: Configure risk tolerance +- [ ] P1: Integration with TacticalModule and DiplomacyModule +- [ ] P1: Align tactical behavior with operational posture +- [ ] P1: Consider diplomatic relationships in posture choice +- [ ] P1: Write strategic decision tests +- [ ] P1: Test posture selection logic +- [ ] P1: Test doctrine influence on decisions +- [ ] P1: Test posture change effects on tactics +- [ ] P1: Create posture transition smoothing +- [ ] P1: Add posture effectiveness tracking + +**Total Tasks**: 28 + +## DiplomacyModule - Complete (P1) + +- [ ] P1: Implement full `DiplomacyModule` class +- [ ] P1: Add module initialization with game factions +- [ ] P1: Implement relationship storage for all faction pairs +- [ ] P1: Add intention tracking system +- [ ] P1: Add pub/sub communication interface +- [ ] P1: Subscribe to threat calculation updates +- [ ] P1: Publish diplomatic events +- [ ] P1: Subscribe to faction actions +- [ ] P1: Implement getRelation(), getIntention(), getFiability() +- [ ] P1: Add relationship query by faction pair +- [ ] P1: Implement intention query +- [ ] P1: Add fiability (reputation) query +- [ ] P1: Create diplomatic action handlers (lobbying, sanctions, aid) +- [ ] P1: Implement lobbying campaign execution +- [ ] P1: Add sanctions application and effects +- [ ] P1: Implement military aid transfer +- [ ] P1: Implement treaty management system (propose, activate, break) +- [ ] P1: Add treaty proposal generation +- [ ] P1: Implement treaty evaluation AI +- [ ] P1: Add treaty activation with relationship changes +- [ ] P1: Implement treaty breach handling +- [ ] P1: Add serialization for persistence +- [ ] P1: Serialize all relationships +- [ ] P1: Serialize all treaties +- [ ] P1: Serialize diplomatic history +- [ ] P1: Implement calculateThreat() integration +- [ ] P1: Use threat values to influence intentions +- [ ] P1: Update diplomatic stance based on threat +- [ ] P1: Write comprehensive integration tests +- [ ] P1: Test emergent diplomatic behavior +- [ ] P1: Test treaty lifecycle +- [ ] P1: Test relationship evolution +- [ ] P1: Performance: batch processing for intentions +- [ ] P1: Optimize daily intention processing +- [ ] P1: Batch relationship decay updates +- [ ] P1: Add diplomatic event history visualization +- [ ] P1: Create relationship graph visualization +- [ ] P1: Implement diplomatic summary reports + +**Total Tasks**: 37 + +## CompanyAI & StateAI Modules (P1) + +- [ ] P1: Implement `CompanyAIModule` decision framework +- [ ] P1: Add company context (finances, assets, market position) +- [ ] P1: Implement decision evaluation for businesses +- [ ] P1: Add company goal system (profit, growth, monopoly) +- [ ] P1: Implement `StateAIModule` decision framework +- [ ] P1: Add state context (budget, military, diplomatic) +- [ ] P1: Implement decision evaluation for governments +- [ ] P1: Add state goal system (security, power, prosperity) +- [ ] P1: Create investment decision system (R&D, production, lobbying) +- [ ] P1: Implement R&D investment evaluation +- [ ] P1: Add production capacity investment logic +- [ ] P1: Implement lobbying investment and targets +- [ ] P1: Calculate ROI for investments +- [ ] P1: Create military purchase decision system +- [ ] P1: Implement threat-based purchase prioritization +- [ ] P1: Add budget constraint checking +- [ ] P1: Calculate military necessity scores +- [ ] P1: Add equipment type selection logic +- [ ] P1: Add lobbying campaign logic +- [ ] P1: Implement lobbying target selection +- [ ] P1: Calculate lobbying effectiveness +- [ ] P1: Track lobbying progress over time +- [ ] P1: Implement company feature system +- [ ] P1: Add company features (Metal, Electronic, Tank, Plane, Wood, Food, Engine, Cannon, Missile) +- [ ] P1: Implement feature quality modifiers (Quality, Quantity, Speed, Cost, Modularity, Innovation) +- [ ] P1: Add feature combinations and synergies +- [ ] P1: Implement company mortality/birth system +- [ ] P1: Integration with DiplomacyModule and EconomyModule +- [ ] P1: Link lobbying to diplomatic relations +- [ ] P1: Integrate market conditions with company decisions +- [ ] P1: Add state economic policy effects +- [ ] P1: Add blueprint cultural inheritance +- [ ] P1: Implement national doctrine influence on company designs +- [ ] P1: Add regional design style inheritance +- [ ] P1: Create design evolution based on culture +- [ ] P1: Write unit tests for company decision logic +- [ ] P1: Write unit tests for state decision logic +- [ ] P1: Write integration tests with economy and diplomacy + +**Total Tasks**: 38 + +## Complete Threat Calculation System (P1) + +- [ ] P1: Implement all domain evaluations (land, air, naval) +- [ ] P1: Integrate land threat evaluation +- [ ] P1: Integrate air threat evaluation +- [ ] P1: Integrate naval threat evaluation +- [ ] P1: Add weighted domain combination +- [ ] P1: Create complete equipment database +- [ ] P1: Add all tank types with armor specs +- [ ] P1: Add all AT weapons with penetration values +- [ ] P1: Add all aircraft with capabilities +- [ ] P1: Add all AA systems with effectiveness +- [ ] P1: Add all naval vessels with armament +- [ ] P1: Add all counter-measure mappings +- [ ] P1: Map every equipment type to its counters +- [ ] P1: Add effectiveness values for each counter +- [ ] P1: Implement partial counter effectiveness +- [ ] P1: Implement production threat evaluation +- [ ] P1: Add production rate tracking per faction +- [ ] P1: Implement projection over time +- [ ] P1: Calculate production threat factor +- [ ] P1: Create threat cache with smart invalidation +- [ ] P1: Implement cache invalidation events +- [ ] P1: Add TTL-based cache expiration +- [ ] P1: Optimize cache hit rate +- [ ] P1: Add lazy calculation on-demand +- [ ] P1: Calculate threat only when queried +- [ ] P1: Cache results for repeated queries +- [ ] P1: Performance optimization (10k entities) +- [ ] P1: Profile threat calculation with 10k entities +- [ ] P1: Optimize cache lookups +- [ ] P1: Parallelize threat calculations +- [ ] P1: Integration with diplomacy intentions +- [ ] P1: Provide threat values to DiplomacyModule +- [ ] P1: Update intentions based on threat changes +- [ ] P1: Write comprehensive integration tests +- [ ] P1: Test all domain evaluations +- [ ] P1: Test equipment counter effectiveness +- [ ] P1: Test cache performance and correctness + +**Total Tasks**: 35 + +--- + +# BIG TASKS (1-2 weeks) + +## Complete AI Framework System (P1) + +- [ ] P1: All decision types implemented and tested +- [ ] P1: Implement all tactical decision types (15+ types) +- [ ] P1: Implement all operational decision types (10+ types) +- [ ] P1: Implement all economic decision types (10+ types) +- [ ] P1: Test all decision integrations +- [ ] P1: RL engine foundation (weight adjustment) +- [ ] P1: Implement reinforcement learning framework +- [ ] P1: Add weight adjustment based on outcomes +- [ ] P1: Implement reward function calculation +- [ ] P1: Add policy gradient updates +- [ ] P1: Decision history tracking +- [ ] P1: Record all decisions with context +- [ ] P1: Track decision outcomes +- [ ] P1: Calculate decision effectiveness +- [ ] P1: Implement decision replay system +- [ ] P1: Performance optimization (parallel evaluation) +- [ ] P1: Parallelize decision evaluation +- [ ] P1: Optimize weight calculations +- [ ] P1: Cache decision scores +- [ ] P1: Profile and eliminate bottlenecks +- [ ] P1: Complete integration with game systems +- [ ] P1: Integrate with all helper modules +- [ ] P1: Integrate with all game mechanics +- [ ] P1: Test end-to-end decision pipeline +- [ ] P1: Documentation updates with real examples +- [ ] P1: Add concrete decision examples from gameplay +- [ ] P1: Document decision composition patterns +- [ ] P1: Create decision tuning guide +- [ ] P1: Create decision composition patterns +- [ ] P1: Document effective decision combinations +- [ ] P1: Add composition best practices +- [ ] P1: Add meta-learning capabilities (V2) +- [ ] P1: Implement learning from decision patterns +- [ ] P1: Add adaptive weight evolution +- [ ] P1: Create self-improving AI system + +**Total Tasks**: 32 + +## World Generation - Complete Geological System (P1) + +### Phase 1: Planetary Accretion (30 cycles × 100M years) +- [ ] P1: Implement meteorite bombardment system +- [ ] P1: Add meteorite generation with size distribution +- [ ] P1: Implement impact probability calculation +- [ ] P1: Create meteorite trajectory simulation +- [ ] P1: Create impact physics (kinetic energy → heat + elevation) +- [ ] P1: Calculate kinetic energy from velocity and mass +- [ ] P1: Convert energy to heat and elevation increase +- [ ] P1: Add impact crater formation +- [ ] P1: Implement shock wave propagation +- [ ] P1: Add metal composition and core formation +- [ ] P1: Track metal content in crust +- [ ] P1: Implement core differentiation +- [ ] P1: Add magnetic field generation +- [ ] P1: Implement volcanic eruption from core heat +- [ ] P1: Calculate volcanic activity from core temperature +- [ ] P1: Add magma chamber formation +- [ ] P1: Implement lava flow simulation +- [ ] P1: Create gradual cooling system +- [ ] P1: Implement heat dissipation over time +- [ ] P1: Add atmospheric heat loss +- [ ] P1: Track surface temperature evolution + +### Phase 2: Tectonic Formation (25 cycles × 100M years) +- [ ] P1: Implement TectonicRegion struct with physics +- [ ] P1: Create tectonic physics engine (repulsive forces, collisions) +- [ ] P1: Add volcanic zone creation at collisions +- [ ] P1: Implement region splitting algorithm +- [ ] P1: Create mountain range formation +- [ ] P1: Add rift valley creation +- [ ] P1: Implement trench formation at subduction zones +- [ ] P1: Add island arc generation +- [ ] P1: Create hotspot volcanic chains +- [ ] P1: Implement plate boundary classification (divergent, convergent, transform) + +### Phase 3: Hydrological Cycles (25 cycles × 20M years) +- [ ] P1: Implement dynamic sea level system +- [ ] P1: Create hydraulic erosion (10x more effective than tectonic) +- [ ] P1: Add ice volume calculation (glaciation/melting) +- [ ] P1: Implement sediment transport +- [ ] P1: Create coastal erosion system +- [ ] P1: Add river network formation +- [ ] P1: Implement lake and wetland creation +- [ ] P1: Add aquifer simulation +- [ ] P1: Create karst landscape formation +- [ ] P1: Implement freeze-thaw weathering + +### Phase 4: Climate Simulation +- [ ] P1: Implement wind regions and ITCZ +- [ ] P1: Create temperature distribution +- [ ] P1: Add precipitation patterns +- [ ] P1: Implement Hadley, Ferrel, and Polar cells +- [ ] P1: Add monsoon system simulation +- [ ] P1: Create ocean current simulation +- [ ] P1: Implement rain shadow effects +- [ ] P1: Add temperature gradients (latitude, elevation) +- [ ] P1: Create seasonal variation model + +### Phase 5: Biome Classification +- [ ] P1: Implement 18 distinct biomes +- [ ] P1: Create biome-specific parameters +- [ ] P1: Add elevation-based biome distribution +- [ ] P1: Implement biome types: Tundra, Taiga, Temperate Forest, Tropical Rainforest, etc. +- [ ] P1: Add biome transition zones +- [ ] P1: Create biome succession simulation +- [ ] P1: Implement climate-based biome assignment +- [ ] P1: Add biodiversity parameters per biome + +### Phase 6: Resource Distribution +- [ ] P1: Implement 70+ natural features +- [ ] P1: Create geologically accurate formation patterns +- [ ] P1: Add mass-based quality (region strength → resource grades) +- [ ] P1: Implement ore deposit formation (magmatic, hydrothermal, sedimentary) +- [ ] P1: Add mineral vein generation +- [ ] P1: Create fossil fuel deposit simulation +- [ ] P1: Implement rare earth element distribution +- [ ] P1: Add gemstone deposit generation +- [ ] P1: Create industrial mineral deposits + +### Phase 7: Carbon Regions +- [ ] P1: Implement carbon region system for coal/oil formation +- [ ] P1: Add organic material accumulation +- [ ] P1: Create coal seam formation +- [ ] P1: Implement oil and gas reservoir creation +- [ ] P1: Add organic matter burial simulation +- [ ] P1: Create petroleum migration paths + +### Integration +- [ ] P1: Create RegionalInfluence framework +- [ ] P1: Implement optimized 24-byte tiles +- [ ] P1: Add geological temperature ranges (-100°C to +2000°C) +- [ ] P1: Performance optimization (< 10s for 1024x1024 map) +- [ ] P1: Implement multi-threaded generation +- [ ] P1: Add progressive generation with checkpoints +- [ ] P1: Create geological visualization tools +- [ ] P1: Implement geological history replay +- [ ] P1: Add geological validation tests +- [ ] P1: Create procedural seed system for reproducibility + +**Total Tasks**: 80 + +## Complete Save/Load System V1 (P1) + +- [ ] P1: All modules implement IModuleSave +- [ ] P1: Add IModuleSave to TankModule +- [ ] P1: Add IModuleSave to EconomyModule +- [ ] P1: Add IModuleSave to DiplomacyModule +- [ ] P1: Add IModuleSave to PathfinderModule +- [ ] P1: Add IModuleSave to all other modules +- [ ] P1: Metachunk streaming working perfectly +- [ ] P1: Implement on-demand metachunk loading +- [ ] P1: Add metachunk unloading for memory management +- [ ] P1: Test streaming with 10000+ metachunks +- [ ] P1: Error recovery and retry system +- [ ] P1: Implement save verification checksums +- [ ] P1: Add automatic retry on load failure +- [ ] P1: Create fallback to previous save +- [ ] P1: Implement partial load with degraded functionality +- [ ] P1: Save compression (optional V1.5) +- [ ] P1: Implement LZ4 fast compression +- [ ] P1: Add configurable compression levels +- [ ] P1: Test compression ratio and performance +- [ ] P1: Autosave system (background thread) +- [ ] P1: Implement non-blocking autosave +- [ ] P1: Add autosave interval configuration +- [ ] P1: Create autosave slot rotation (keep last N) +- [ ] P1: Load time optimization (< 3s target) +- [ ] P1: Profile load performance +- [ ] P1: Optimize JSON parsing bottlenecks +- [ ] P1: Implement parallel module loading +- [ ] P1: Add lazy loading for non-critical data +- [ ] P1: Version migration system +- [ ] P1: Implement save version detection +- [ ] P1: Add migration functions for version upgrades +- [ ] P1: Test migration across all versions +- [ ] P1: Save diff tool (compare two saves) +- [ ] P1: Implement save comparison logic +- [ ] P1: Add diff visualization +- [ ] P1: Create save merge tool (for debugging) +- [ ] P1: Write comprehensive save/load tests +- [ ] P1: Test save/load integrity +- [ ] P1: Test error recovery scenarios +- [ ] P1: Test version migration +- [ ] P1: Stress test with large saves (>1GB) + +**Total Tasks**: 40 + +## Hot-Reload System Enhancement (P2) + +- [ ] P2: Module state preservation across reloads +- [ ] P2: Enhance state serialization granularity +- [ ] P2: Add incremental state updates +- [ ] P2: Test state preservation with complex modules +- [ ] P2: Configuration hot-reload without restart +- [ ] P2: Implement config change detection +- [ ] P2: Add config reload propagation to modules +- [ ] P2: Test config hot-reload with all modules +- [ ] P2: Doctrine hot-reload system +- [ ] P2: Implement doctrine change detection +- [ ] P2: Add doctrine reload without entity restart +- [ ] P2: Test smooth doctrine transitions +- [ ] P2: Metrics preservation during reload +- [ ] P2: Preserve performance metrics +- [ ] P2: Preserve gameplay statistics +- [ ] P2: Add metrics snapshot before reload +- [ ] P2: Zero-downtime reload for production +- [ ] P2: Implement seamless hot-swap +- [ ] P2: Add rollback on reload failure +- [ ] P2: Test zero-downtime with active players +- [ ] P2: Hot-reload debugging tools +- [ ] P2: Add hot-reload visualization +- [ ] P2: Create reload performance profiling +- [ ] P2: Implement reload history tracking +- [ ] P2: Real-time state inspection +- [ ] P2: Add module state viewer during reload +- [ ] P2: Implement state diff visualization +- [ ] P2: Create reload impact analysis + +**Total Tasks**: 27 + +## Complete Economy & Logistics System (P1) + +### Company Features System +- [ ] P1: Implement Feature types (Metal, Electronic, Tank, Plane, Wood, Food, Engine, Cannon, Missile) +- [ ] P1: Create quality modifiers (Quality, Quantity, Speed, Cost, Modularity, Innovation) +- [ ] P1: Add feature combinations and synergies +- [ ] P1: Implement company mortality/birth system +- [ ] P1: Create feature change events (financial decline, acquisition, overflow) +- [ ] P1: Add feature inheritance on company acquisition +- [ ] P1: Implement feature innovation system +- [ ] P1: Add feature obsolescence tracking + +### Inventory Strategies +- [ ] P1: Implement stock level behaviors (Desperate <20%, Normal 20-50%, Cautious 50-80%, Oversupplied >80%) +- [ ] P1: Create dynamic pricing based on stock levels +- [ ] P1: Add opportunity trading mechanics +- [ ] P1: Implement price volatility calculation +- [ ] P1: Add market maker behavior +- [ ] P1: Create arbitrage detection and exploitation + +### Regional Specialization +- [ ] P1: Implement transport cost economics (Ship 0.10€/kg, Truck 5.00€/kg) +- [ ] P1: Create infrastructure investment ROI calculations (<15 years) +- [ ] P1: Add natural geographic specialization emergence +- [ ] P1: Implement coastal advantage phase +- [ ] P1: Add resource cluster effects +- [ ] P1: Create trade hub formation +- [ ] P1: Implement transportation network evolution + +### Blueprint Cultural System +- [ ] P1: Create company blueprints with cultural inheritance +- [ ] P1: Implement doctrine integration with blueprints +- [ ] P1: Add regional style influences (Soviet sloped, Western boxy, etc.) +- [ ] P1: Create blueprint evolution system +- [ ] P1: Add blueprint performance tracking +- [ ] P1: Implement blueprint mutation and innovation + +### AI Design System +- [ ] P1: Implement 1-2 designs per tick globally +- [ ] P1: Create design validation (features as filters) +- [ ] P1: Add design evolution (T-72 → T-80 → T-90) +- [ ] P1: Implement probabilistic innovation system +- [ ] P1: Add design effectiveness evaluation +- [ ] P1: Create design cost calculation +- [ ] P1: Implement market demand forecasting + +**Total Tasks**: 35 + +## Complete Military Vehicle Design System (P1) + +### Frame/Chassis System +- [ ] P1: Implement grid-based component placement +- [ ] P1: Create irregular chassis shapes with zone types +- [ ] P1: Add zone categories (central, flank, dead, overload, disconnected) +- [ ] P1: Implement chassis generations (Gen1-Gen4) +- [ ] P1: Create chassis styles (Sloped, Boxy, Hexagonal, Modular Block, Organic) +- [ ] P1: Add chassis bonuses and penalties +- [ ] P1: Implement chassis material types +- [ ] P1: Add chassis structural integrity calculation + +### Named Chassis Database +- [ ] P1: Implement 50+ named chassis (Fennec, Coyote, Griffon, Sparrow, Albatross, Barracuda, etc.) +- [ ] P1: Create chassis-specific bonuses and maluses +- [ ] P1: Add breakthrough chassis (Metamaterial, Plasma Shield, Quantum Tunneling) +- [ ] P1: Implement chassis unlock progression +- [ ] P1: Add chassis rarity and acquisition +- [ ] P1: Create chassis upgrade paths + +### Component System +- [ ] P1: Implement hundreds of unique components +- [ ] P1: Create component shapes (L, T, I, Z, +, Rectangle) +- [ ] P1: Add component layers (Chassis, Systems, Weapons & Sensors) +- [ ] P1: Implement technology-based component variants (5-15 per tech) +- [ ] P1: Add component compatibility checking +- [ ] P1: Create component power and weight calculation +- [ ] P1: Implement component synergies +- [ ] P1: Add component overheating and stress + +### Design Interface +- [ ] P1: Create pick & place system with drag-and-drop +- [ ] P1: Add rotation with A/E keys +- [ ] P1: Implement snap toggle with R key +- [ ] P1: Add validation feedback (real-time constraints) +- [ ] P1: Create template system +- [ ] P1: Implement zone highlighting (central, flank, overload, etc.) +- [ ] P1: Add design cost calculator +- [ ] P1: Create design performance preview +- [ ] P1: Implement design validation checklist +- [ ] P1: Add design save/load functionality + +**Total Tasks**: 33 + +--- + +# RESEARCH & EXPLORATION (P3) + +## Performance Optimization Research (P3) + +- [ ] P3: Profile threat calculation with 10k entities +- [ ] P3: Benchmark JSON vs MessagePack for saves +- [ ] P3: Research LZ4 vs Zstd compression (V2 saves) +- [ ] P3: Investigate spatial indexing for threat cache +- [ ] P3: Explore GPU acceleration for pathfinding +- [ ] P3: Profile AI decision evaluation with 1000 concurrent units +- [ ] P3: Benchmark geological simulation performance +- [ ] P3: Optimize flow field generation for massive groups +- [ ] P3: Research SIMD optimizations for physics calculations +- [ ] P3: Investigate parallel JSON parsing +- [ ] P3: Explore lock-free data structures for pub/sub +- [ ] P3: Research memory pool optimization for modules + +## AI & Machine Learning Research (P3) + +- [ ] P3: Research Reinforcement Learning libraries (TensorFlow, PyTorch) +- [ ] P3: Investigate genetic algorithms for doctrine evolution +- [ ] P3: Explore neural networks for pattern recognition +- [ ] P3: Research multi-agent RL frameworks +- [ ] P3: Investigate deep RL for complex tactical decisions +- [ ] P3: Research transfer learning between doctrines +- [ ] P3: Explore imitation learning from human players +- [ ] P3: Investigate adversarial training for robust AI + +## Architecture Improvements Research (P3) + +- [ ] P3: Investigate ECS (Entity Component System) integration +- [ ] P3: Research distributed computing for multi-server +- [ ] P3: Explore Redis for distributed state management +- [ ] P3: Investigate ZeroMQ performance optimizations +- [ ] P3: Research SIMD optimizations for geological simulation +- [ ] P3: Explore cluster computing for world generation +- [ ] P3: Investigate service mesh for microservices architecture +- [ ] P3: Research event sourcing for game state management +- [ ] P3: Explore CQRS pattern for read/write optimization +- [ ] P3: Investigate WebAssembly for client modules + +--- + +# CLIENT/SERVER INTEGRATION (P1) + +## V1 - Thin Client Implementation (P1) + +### Client Modules +- [ ] P1: Implement InputModule (keyboard/mouse → JSON commands) +- [ ] P1: Add keyboard event capture +- [ ] P1: Add mouse event capture +- [ ] P1: Implement command mapping (WASD → movement) +- [ ] P1: Add input buffering +- [ ] P1: Create input validation +- [ ] P1: Implement RenderModule (server state → display) +- [ ] P1: Add basic rendering pipeline +- [ ] P1: Implement entity rendering from server state +- [ ] P1: Add camera control +- [ ] P1: Create UI overlay rendering +- [ ] P1: Implement ClientNetworkModule (WebSocket client) +- [ ] P1: Add WebSocket connection handling +- [ ] P1: Implement command sending +- [ ] P1: Add state update receiving +- [ ] P1: Create connection recovery +- [ ] P1: Add latency measurement + +### Server Modules +- [ ] P1: Implement ServerNetworkModule (WebSocket server) +- [ ] P1: Add WebSocket server initialization +- [ ] P1: Implement client connection handling +- [ ] P1: Add broadcast system for state updates +- [ ] P1: Create client session management +- [ ] P1: Extend TankModule for network integration +- [ ] P1: Add command processing from network +- [ ] P1: Implement state broadcasting +- [ ] P1: Add entity state synchronization + +### Testing & Performance +- [ ] P1: Test 2+ players synchronized gameplay +- [ ] P1: Test hot-reload without client disconnect +- [ ] P1: Measure latency (<150ms target for V1) +- [ ] P1: Test server capacity (10+ concurrent players) +- [ ] P1: Profile client FPS (30+ target for V1) + +**Total Tasks**: 30 + +## V2 - Client Prediction Implementation (P1) + +### Shared Logic Extraction +- [ ] P1: Extract SharedTankLogic.so from TankModule +- [ ] P1: Refactor TankModule to use SharedTankLogic +- [ ] P1: Extract SharedCombatLogic.so +- [ ] P1: Extract SharedPhysicsLogic.so +- [ ] P1: Create SharedLogic interface for all modules +- [ ] P1: Test shared logic consistency + +### Client Prediction +- [ ] P1: Implement ClientTankModule with prediction +- [ ] P1: Add immediate client-side prediction +- [ ] P1: Implement prediction using SharedTankLogic +- [ ] P1: Create prediction buffer +- [ ] P1: Implement SyncModule (reconciliation) +- [ ] P1: Add server state reconciliation +- [ ] P1: Implement prediction correction +- [ ] P1: Add input sequence tracking +- [ ] P1: Create rollback mechanism +- [ ] P1: Implement InterpolationModule (smooth corrections) +- [ ] P1: Add state interpolation between updates +- [ ] P1: Create smooth correction curves +- [ ] P1: Add visual smoothing for jitter + +### Server Authority +- [ ] P1: Implement ValidationModule (anti-cheat) +- [ ] P1: Add input validation +- [ ] P1: Implement state verification +- [ ] P1: Create anomaly detection +- [ ] P1: Add cheater flagging +- [ ] P1: Implement server-side physics simulation +- [ ] P1: Add authoritative state calculation +- [ ] P1: Create state broadcasting system + +### Testing & Performance +- [ ] P1: Test instant response (0ms perceived latency) +- [ ] P1: Test smooth corrections (no jittering) +- [ ] P1: Test logic sync (client/server calculations identical) +- [ ] P1: Test server capacity (100+ concurrent players) +- [ ] P1: Profile client FPS (60+ target for V2) +- [ ] P1: Test prediction accuracy vs server state + +**Total Tasks**: 31 + +--- + +# PROGRESS TRACKING + +## Completed Milestones ✅ + +- ✅ Core interface architecture (IEngine, IModule, IModuleSystem, IIO, ITaskScheduler, IDataTree, IDataNode, ICoordinationModule) +- ✅ Complete UI system (IUI with ImGuiUI implementation) +- ✅ Comprehensive documentation system (46+ markdown files) +- ✅ Module versioning specification +- ✅ Threat calculation specification (realistic armor/penetration ratios with 20% baseline) +- ✅ Diplomacy system specification +- ✅ Save system V1 specification +- ✅ AI framework specification +- ✅ Pathfinding system specification (Hybrid A*/HPA*/Flow Fields with ITaskScheduler integration) +- ✅ Geological simulation specification (4.65 billion year simulation) +- ✅ Economy & logistics specification (company features, regional specialization) +- ✅ Military vehicle design specification (grid-based, 50+ chassis) +- ✅ Client/Server architecture specification (V1 thin client, V2 prediction) + +## Current Sprint Focus 🎯 + +### Sprint 1: CRITICAL Infrastructure (BLOCKING EVERYTHING) - 2-3 weeks +**Status**: IN PROGRESS +- Configuration system implementation (IDataTree, IDataNode, gameconfig.json) +- Core engine implementation (DebugEngine, SequentialModuleSystem, IntraIO) +- CoordinationModule implementation +- ModuleFactory with hot-reload + +### Sprint 2: Foundation Implementation - 2-3 weeks +**Status**: NOT STARTED (blocked by Sprint 1) +- AI Framework base classes (IDecision, DecisionFactory, Weights, Context) +- Threat calculation core (calculateCounterEffectiveness, ThreatCache) +- Diplomacy data structures (Relationship, Intention, Treaty, Fiability) +- Save system metachunks + +## Next Sprint Candidates 📋 + +- **Sprint 3**: Helper modules (PathfinderModule, AcquisitionModule, MovementModule) +- **Sprint 4**: Decision modules (TacticalModule, OperationalModule) +- **Sprint 5**: Complete save/load system +- **Sprint 6**: World generation integration +- **Sprint 7**: Economy & logistics implementation +- **Sprint 8**: Military design system +- **Sprint 9**: Client/Server V1 implementation +- **Sprint 10**: Client/Server V2 with prediction + +--- + +# PRIORITY MATRIX + +## P0 - Critical (BLOCKING ALL OTHER WORK) - START HERE ⚠ + +**Configuration System** (20 tasks) +- IDataTree, IDataNode interfaces +- JSONDataTree, JSONDataNode implementation +- gameconfig.json format and loading +- Hot-reload mechanism +- Unit tests and documentation + +**Core Engine** (52 tasks) +- DebugEngine implementation +- SequentialModuleSystem implementation +- IntraIO implementation +- CoordinationModule implementation +- ModuleFactory with hot-reload + +**Total P0 Tasks**: 72 + +## P1 - High (Core Features) - DO AFTER P0 + +**AI Framework** (60+ tasks) +**Threat Calculation** (42+ tasks) +**Diplomacy System** (50+ tasks) +**Pathfinding System** (35+ tasks) +**Save/Load System** (57+ tasks) +**Helper Modules** (88+ tasks) +- AcquisitionModule, MovementModule, TacticalModule, OperationalModule +**World Generation** (80+ tasks) +**Client/Server** (61+ tasks) + +**Total P1 Tasks**: 473+ + +## P2 - Medium (Enhancement) + +**Documentation** (30+ tasks) +**Code Quality** (20+ tasks) +**Build System** (18+ tasks) +**Testing** (15+ tasks) +**Hot-Reload Enhancement** (27+ tasks) +**Economy & Logistics** (35+ tasks) +**Military Design** (33+ tasks) + +**Total P2 Tasks**: 178+ + +## P3 - Low (Nice-to-Have) + +**Research** (30 tasks) +**Advanced Features** (68+ tasks) +**Quality of Life** (40+ tasks) + +**Total P3 Tasks**: 138+ + +--- + +# DEVELOPMENT SEQUENCE (CRITICAL PATH) + +## Phase 0: Infrastructure Foundation (P0 - MUST COMPLETE FIRST) +**Duration**: 2-3 weeks +**Blocking**: ALL module development + +1. Configuration System + - IDataTree/IDataNode interfaces + - JSONDataTree/JSONDataNode implementation + - gameconfig.json loading and validation + - Hot-reload mechanism + - Complete testing + +2. Core Engine Components + - DebugEngine with step-by-step execution + - SequentialModuleSystem with <1ms performance + - IntraIO with sub-millisecond latency + - CoordinationModule as global orchestrator + - ModuleFactory with 0.4ms hot-reload + +3. Validation + - Complete integration testing + - Performance benchmarking + - Hot-reload stress testing + - Documentation completion + +## Phase 1: Core Game Systems (P1 - AFTER INFRASTRUCTURE) +**Duration**: 4-6 weeks + +1. AI Framework Foundation +2. Threat Calculation Core +3. Diplomacy Data Structures +4. Save System Metachunks +5. Pathfinding Data Structures + +## Phase 2: Helper Modules (P1) +**Duration**: 3-4 weeks + +1. PathfinderModule +2. AcquisitionModule +3. MovementModule +4. TacticalModule +5. OperationalModule + +## Phase 3: Integration & Testing (P1) +**Duration**: 2-3 weeks + +1. Module Integration +2. End-to-End Testing +3. Performance Optimization +4. Documentation Updates + +## Phase 4: Client/Server V1 (P1) +**Duration**: 3-4 weeks + +1. Thin Client Implementation +2. Server Network Module +3. Basic Rendering +4. Testing & Optimization + +## Phase 5: Advanced Features (P1/P2) +**Duration**: 8-10 weeks + +1. World Generation +2. Economy & Logistics +3. Military Design System +4. Complete Save/Load +5. Client/Server V2 with Prediction + +--- + +# NOTES & GUIDELINES + +## When Adding Tasks + +1. **Specify estimated time** (Quick/Light/Medium/Feature/Big) +2. **Add dependencies** if any (use → and ←) +3. **Link to relevant documentation** +4. **Include acceptance criteria** for complex tasks +5. **Add priority** (P0/P1/P2/P3) +6. **Tag with affected systems** + +## When Completing Tasks + +1. **Check off** the task `- [x]` +2. **Add completion date** in comment if significant +3. **Update related documentation** +4. **Create follow-up tasks** if needed +5. **Move to "Completed Milestones"** if major feature +6. **Update progress tracking** +7. **Notify blocked tasks** if unblocking others + +## Task Prioritization Rules + +1. **P0 tasks first** - Everything is blocked by these +2. **Dependency-driven** - Unblock as many tasks as possible +3. **Hot-reload critical** - Systems needed for dev workflow +4. **Integration tasks** - Tasks that connect multiple systems +5. **Quick wins** - When energy is low or for momentum +6. **Polish last** - Visual/UX improvements are P3 + +## Development Workflow + +**DO NOT implement modules before infrastructure is complete!** + +### Correct Sequence: +1. **FIRST**: Configuration System (P0) +2. **SECOND**: Core Engine (P0) +3. **THIRD**: ModuleFactory (P0) +4. **THEN**: Start implementing actual game modules + +### Module Development: +- Work in `modules/X/` directory +- Maximum 200-300 lines per module (except ProductionModule) +- JSON-only communication +- Autonomous build: `cd modules/X && cmake .` +- Hot-reload ready from day one +- Comprehensive testing + +--- + +# QUICK LINKS + +## Core Documentation +- [CLAUDE.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/CLAUDE.md) - Project instructions for AI development +- [TODO.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/TODO.md) - Current implementation roadmap + +## Architecture +- [architecture-technique.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/01-architecture/architecture-technique.md) - Core architecture +- [claude-code-integration.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/01-architecture/claude-code-integration.md) - AI development optimization +- [behavior-composition-patterns.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/01-architecture/behavior-composition-patterns.md) - Modular AI patterns +- [player-integration.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/01-architecture/player-integration.md) - Client/server architecture + +## Systems +- [gameplay-industriel.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/02-systems/gameplay-industriel.md) - Factory systems +- [economie-logistique.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/02-systems/economie-logistique.md) - Economy & logistics +- [systeme-militaire.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/02-systems/systeme-militaire.md) - Military vehicle design +- [map-system.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/02-systems/map-system.md) - Procedural generation + +## Reference +- [INTEGRATION-MASTER-LIST.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/04-reference/INTEGRATION-MASTER-LIST.md) - Complete specifications catalog (570+) +- [arbre-technologique.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/04-reference/arbre-technologique.md) - Complete tech tree (3000+) +- [metriques-joueur.md](/mnt/c/Users/Alexis TrouvĂ©/Documents/Projets/warfactoryracine/docs/04-reference/metriques-joueur.md) - Analytics system + +--- + +# REMEMBER + +**Focus on P0 tasks first** - Configuration + Core Engine are BLOCKING everything else. No modules can be implemented until the infrastructure is complete! + +**Keep momentum with quick wins** when energy is low! + +**Parallel development** is possible after infrastructure is ready - multiple Claude Code instances on different modules! + +**Hot-reload is our superpower** - 0.4ms iteration cycles once infrastructure is complete! + +🚀 **Let's build this!** diff --git a/docs/00-overview/vue-ensemble.md b/docs/00-overview/vue-ensemble.md index 0430913..bc50a56 100644 --- a/docs/00-overview/vue-ensemble.md +++ b/docs/00-overview/vue-ensemble.md @@ -263,6 +263,4 @@ Moteur → [PROTOTYPE] ChĂąssis Performance 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. - -**Slava Ukraini !** \ No newline at end of file +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. \ No newline at end of file diff --git a/docs/02-systems/pathfinding-system.md b/docs/02-systems/pathfinding-system.md new file mode 100644 index 0000000..5db035c --- /dev/null +++ b/docs/02-systems/pathfinding-system.md @@ -0,0 +1,2233 @@ +# SystĂšme de Pathfinding Hybride + +## Vue d'Ensemble + +Le systĂšme de pathfinding de Warfactory utilise une **architecture hybride Ă  3 algorithmes** pour optimiser performance et prĂ©cision selon le contexte tactique. Ce n'est pas un simple A* : c'est un systĂšme adaptatif qui choisit automatiquement le bon algorithme selon la distance, le nombre d'unitĂ©s, et les contraintes tactiques. + +### Principes Fondamentaux + +- **Hybride** : A*, HPA*, Flow Fields selon contexte +- **Poids Dynamiques** : Threat maps, cover, terrain, doctrine +- **Multi-Path** : GĂ©nĂ©ration chemins alternatifs (flanking) +- **Tactique** : Cover-to-cover, Ă©vitement menaces, choix terrain +- **Performance** : Budget 4ms/frame (60fps), scaling linĂ©aire + +--- + +## Architecture Globale + +### Les 3 Algorithmes + +```cpp +enum PathfindingAlgorithm { + ASTAR, // Courte distance, prĂ©cision + HIERARCHICAL, // Longue distance, rapide + FLOW_FIELD // Groupes massifs, 1 calcul pour N unitĂ©s +}; + +PathfindingAlgorithm selectAlgorithm(Unit unit, Position goal) { + float distance = calculateDistance(unit.pos, goal); + int group_size = countUnitsWithSameGoal(unit, goal); + + // Groupe massif → Flow Field + if (group_size >= 10) { + return FLOW_FIELD; + } + + // Longue distance → Hierarchical + if (distance > 100.0f) { + return HIERARCHICAL; + } + + // Court + prĂ©cis → A* + return ASTAR; +} +``` + +### RĂšgles de DĂ©cision + +| Situation | Algorithme | Raison | Performance | +|-----------|------------|--------|-------------| +| 1 unitĂ©, < 100m | A* | PrĂ©cision tactique | 1-2ms | +| 1 unitĂ©, > 100m | HPA* | Vitesse longue distance | 5-10ms | +| 10+ unitĂ©s, mĂȘme but | Flow Field | 1 calcul partagĂ© | 15ms total | +| N unitĂ©s, buts diffĂ©rents | A* × N ou HPA* × N | Chemins divergents | Variable | + +--- + +## 1. A* - Pathfinding PrĂ©cis + +### Usage + +**Quand** : +- Distance courte (< 100m) +- UnitĂ© solo ou petit groupe (< 10) +- Besoin prĂ©cision tile-par-tile +- Mouvement tactique (cover-to-cover) + +**Performance Target** : +- < 2ms pour 50m +- < 5ms pour 100m +- Budget : 25% d'un frame (4ms @ 60fps) + +### Algorithme de Base + +```cpp +class AStarPathfinder { +public: + Path findPath(Position start, Position goal, PathConstraints constraints) { + std::priority_queue open_set; + std::unordered_set closed_set; + + Node start_node = {start, 0.0f, heuristic(start, goal)}; + open_set.push(start_node); + + while (!open_set.empty()) { + Node current = open_set.top(); + open_set.pop(); + + if (current.pos == goal) { + return reconstructPath(current); + } + + closed_set.insert(current.pos); + + // Explorer voisins + for (auto& neighbor : getNeighbors(current.pos)) { + if (closed_set.contains(neighbor)) continue; + + // ✅ COÛT AVEC POIDS DYNAMIQUES + float g_cost = current.g_cost + calculateCost(current, neighbor, constraints); + float h_cost = heuristic(neighbor, goal); + float f_cost = g_cost + h_cost; + + open_set.push({neighbor, g_cost, f_cost}); + } + } + + return Path(); // Pas de chemin trouvĂ© + } + +private: + float heuristic(Position a, Position b) { + // Manhattan distance (grille 4-directionnelle) + return abs(a.x - b.x) + abs(a.y - b.y); + + // Ou Euclidean (grille 8-directionnelle) + // return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)); + } +}; +``` + +### Poids Dynamiques (Weighted A*) + +**Principe** : CoĂ»t ≠ distance pure, intĂšgre facteurs tactiques + +```cpp +float calculateCost(Node current, Node neighbor, PathConstraints constraints) { + float base_cost = distance(current.pos, neighbor.pos); // 1.0 ou 1.41 (diagonal) + + // Poids tactiques + float threat_penalty = getThreat(neighbor.pos) * constraints.threat_weight; + float cover_bonus = hasCover(neighbor.pos) ? -constraints.cover_weight : 0.0f; + float elevation_penalty = abs(neighbor.elevation - current.elevation) * constraints.elevation_weight; + float terrain_penalty = getTerrainCost(neighbor.terrain, constraints.unit_type) * constraints.terrain_weight; + float exposure_penalty = isExposed(neighbor.pos) ? constraints.exposure_weight : 0.0f; + + float total_cost = base_cost + threat_penalty + cover_bonus + elevation_penalty + terrain_penalty + exposure_penalty; + + // Contraintes absolues + if (constraints.avoid_water && neighbor.terrain == WATER) { + return INFINITY; // Interdit + } + + if (neighbor.slope > constraints.max_slope) { + return INFINITY; // Trop raide + } + + return max(0.1f, total_cost); // Minimum 0.1 pour Ă©viter coĂ»t nul +} +``` + +### PathConstraints Structure + +```cpp +struct PathConstraints { + // Poids dynamiques (0.0 = ignore, higher = plus important) + float threat_weight = 1.0f; // Éviter zones menace + float cover_weight = 0.5f; // PrĂ©fĂ©rer cover + float elevation_weight = 0.3f; // PĂ©nalitĂ© montĂ©es/descentes + float terrain_weight = 1.0f; // PĂ©nalitĂ© terrains difficiles + float exposure_weight = 0.8f; // PĂ©nalitĂ© terrain ouvert + + // Contraintes absolues + bool avoid_water = false; + bool avoid_roads = false; + bool prefer_roads = false; + float max_slope = 30.0f; // DegrĂ©s + + // Contexte unitĂ© + UnitType unit_type = INFANTRY; + float unit_speed = 1.0f; + + // Doctrine (preset poids) + Doctrine doctrine = BALANCED; +}; + +enum Doctrine { + AGGRESSIVE, // threat_weight=0.2, prefer_roads=true + BALANCED, // threat_weight=1.0, cover_weight=0.5 + CAUTIOUS, // threat_weight=5.0, cover_weight=3.0 + STEALTH // threat_weight=10.0, exposure_weight=5.0, avoid_roads=true +}; +``` + +### Multi-Path A* (Chemins Divergents) + +**Usage** : Flanking, chemins alternatifs tactiques + +```cpp +std::vector findAllPaths(Position start, Position goal, int max_paths, PathConstraints constraints) { + std::vector paths; + std::unordered_set penalized_nodes; + + for (int i = 0; i < max_paths; i++) { + // A* avec pĂ©nalitĂ©s sur nƓuds dĂ©jĂ  utilisĂ©s + Path path = aStarWithPenalties(start, goal, constraints, penalized_nodes); + + if (path.empty()) break; // Plus de chemins valides + + paths.push_back(path); + + // PĂ©nalise 40% milieu du chemin (garde start/goal communs) + int start_idx = path.waypoints.size() * 0.3; + int end_idx = path.waypoints.size() * 0.7; + + for (int j = start_idx; j < end_idx; j++) { + penalized_nodes.insert(path.waypoints[j]); + } + } + + return paths; +} + +Path aStarWithPenalties(Position start, Position goal, PathConstraints constraints, + const std::unordered_set& penalized) { + // A* standard mais avec coĂ»t additionnel pour nƓuds pĂ©nalisĂ©s + // cost += penalized.contains(node) ? PENALTY_COST : 0.0f; + // PENALTY_COST = 50.0 (force divergence sans interdire) +} +``` + +### Exemples d'Utilisation + +#### Exemple 1 : Mouvement Simple + +```cpp +PathConstraints basic; +basic.threat_weight = 1.0f; +basic.unit_type = INFANTRY; + +Path path = pathfinder->findPath(soldier.pos, objective, basic); +// Chemin Ă©quilibrĂ©, Ă©vite menaces modĂ©rĂ©ment +``` + +#### Exemple 2 : Tank BlessĂ© (PrioritĂ© Survie) + +```cpp +PathConstraints wounded; +wounded.threat_weight = 10.0f; // ÉVITER COMBAT +wounded.cover_weight = 5.0f; // MAXIMUM COVER +wounded.terrain_weight = 0.5f; // Distance secondaire +wounded.unit_type = TANK_MEDIUM; + +Path path = pathfinder->findPath(damaged_tank.pos, repair_base, wounded); +// Peut doubler distance mais SÉCURISÉ +``` + +#### Exemple 3 : Flanking 3 Directions + +```cpp +PathConstraints flanking; +flanking.threat_weight = 3.0f; +flanking.cover_weight = 2.0f; +flanking.exposure_weight = 5.0f; + +auto paths = pathfinder->findAllPaths(tank.pos, enemy.pos, 3, flanking); + +// paths[0] : Frontal (court, threat=HIGH) +// paths[1] : Flanking gauche (dĂ©tour, threat=MEDIUM, cover=HIGH) +// paths[2] : Flanking droite (long, threat=LOW) + +// TacticalModule score et choisit +int best_idx = tacticalModule->selectBestPath(paths, enemy); +tank.setPath(paths[best_idx]); +``` + +--- + +## 2. HPA* - Hierarchical Pathfinding + +### Usage + +**Quand** : +- Distance longue (> 100m) +- TraversĂ©e multi-chunks +- Navigation stratĂ©gique +- Pas besoin prĂ©cision tile-par-tile + +**Performance Target** : +- < 5ms pour 500m +- < 10ms pour 5000m +- Scaling logarithmique avec distance + +### Concept HiĂ©rarchique + +``` +NIVEAU 1 : Abstraction Globale (Clusters 256×256) + Map 2048×2048 divisĂ©e en 8×8 clusters + + [Cluster A] --edge--> [Cluster B] --edge--> [Cluster C] + ↓ ↓ ↓ + Start (traversĂ©e) Goal + +NIVEAU 2 : Chemins Intra-Cluster (PrĂ©-calculĂ©s) + Dans Cluster A : Entry → Exit (A* cached) + Dans Cluster B : Entry → Exit (A* cached) + Dans Cluster C : Entry → Goal (A* cached) + +NIVEAU 3 : Smoothing Final + Combine chemins clusters + smooth transitions +``` + +### Architecture + +```cpp +class HierarchicalPathfinder { +public: + Path findPath(Position start, Position goal, PathConstraints constraints) { + // 1. Identifier clusters start/goal + ClusterId start_cluster = getCluster(start); + ClusterId goal_cluster = getCluster(goal); + + // 2. A* sur graphe abstrait clusters + std::vector cluster_path = findClusterPath(start_cluster, goal_cluster); + + // 3. Pour chaque cluster, rĂ©cupĂ©rer chemin intra-cluster (cached) + Path full_path; + for (int i = 0; i < cluster_path.size(); i++) { + ClusterId cluster = cluster_path[i]; + + Position entry = (i == 0) ? start : getClusterEntry(cluster, cluster_path[i-1]); + Position exit = (i == cluster_path.size()-1) ? goal : getClusterExit(cluster, cluster_path[i+1]); + + Path segment = getIntraClusterPath(cluster, entry, exit, constraints); + full_path.append(segment); + } + + // 4. Smooth path (Ă©liminer waypoints redondants) + return smoothPath(full_path); + } + +private: + struct Cluster { + int id; + Bounds bounds; // Rectangle 256×256 + std::vector edges; // Connexions autres clusters + PathCache intra_paths; // Chemins prĂ©-calculĂ©s + }; + + struct Edge { + ClusterId from_cluster; + ClusterId to_cluster; + Position entry_point; + Position exit_point; + float cost; // Distance entre entry/exit + }; + + // Cache chemins intra-cluster + std::map cluster_caches; +}; +``` + +### Cluster Graph Construction + +```cpp +void buildClusterGraph() { + // 1. Diviser map en clusters 256×256 + int clusters_x = map_width / CLUSTER_SIZE; + int clusters_y = map_height / CLUSTER_SIZE; + + for (int x = 0; x < clusters_x; x++) { + for (int y = 0; y < clusters_y; y++) { + Cluster cluster = createCluster(x, y); + clusters.push_back(cluster); + } + } + + // 2. Identifier edges entre clusters adjacents + for (auto& cluster : clusters) { + // Check voisins (4-directional) + for (auto& neighbor : getAdjacentClusters(cluster)) { + // Trouver points passage entre clusters + auto edges = findClusterEdges(cluster, neighbor); + cluster.edges.insert(cluster.edges.end(), edges.begin(), edges.end()); + } + } + + // 3. PrĂ©-calculer chemins intra-cluster (edges → edges) + for (auto& cluster : clusters) { + precomputeIntraClusterPaths(cluster); + } +} + +std::vector findClusterEdges(Cluster a, Cluster b) { + std::vector edges; + + // FrontiĂšre entre clusters + Bounds border = getBorderBounds(a, b); + + // Scan border, trouver passages navigables + for (int i = 0; i < border.length; i++) { + Position pos = border.start + i; + + if (isWalkable(pos)) { + // DĂ©but passage + Position entry = pos; + + // Trouver fin passage + while (isWalkable(pos) && i < border.length) { + pos = border.start + (++i); + } + Position exit = pos - 1; + + // CrĂ©er edge (peut ĂȘtre multi-tiles large) + Edge edge = {a.id, b.id, entry, exit, distance(entry, exit)}; + edges.push_back(edge); + } + } + + return edges; +} +``` + +### Path Caching + +```cpp +class PathCache { +public: + Path getCachedPath(Position start, Position goal) { + CacheKey key = {start, goal}; + + if (cache.contains(key)) { + return cache[key]; + } + + // Pas en cache, calculer avec A* + Path path = astar->findPath(start, goal); + cache[key] = path; + + return path; + } + + void invalidate(Position pos) { + // Obstacle ajoutĂ©/retirĂ©, invalider chemins affectĂ©s + for (auto it = cache.begin(); it != cache.end();) { + if (pathContains(it->second, pos)) { + it = cache.erase(it); + } else { + ++it; + } + } + } + +private: + struct CacheKey { + Position start; + Position goal; + + bool operator==(const CacheKey& other) const { + return start == other.start && goal == other.goal; + } + }; + + std::unordered_map cache; +}; +``` + +### Optimisations + +**1. Multi-Level Hierarchies** + +Pour maps trĂšs grandes (> 4096×4096), utiliser 3+ niveaux : + +``` +Niveau 1 : MĂ©ga-clusters 1024×1024 (abstraction continents) +Niveau 2 : Clusters 256×256 (abstraction rĂ©gions) +Niveau 3 : A* local 64×64 (prĂ©cision tactique) +``` + +**2. Dynamic Edge Costs** + +Mettre Ă  jour coĂ»ts edges selon congestion, menaces : + +```cpp +void updateEdgeCosts() { + for (auto& edge : edges) { + // Base cost (distance) + float cost = distance(edge.entry, edge.exit); + + // Congestion (nb unitĂ©s traversant) + int congestion = countUnitsInEdge(edge); + cost += congestion * CONGESTION_PENALTY; + + // Menace (ennemis proximitĂ©) + float threat = getThreatLevel(edge.entry, edge.exit); + cost += threat * THREAT_PENALTY; + + edge.cost = cost; + } +} +``` + +--- + +## 3. Flow Fields - Mouvement de Groupe + +### Usage + +**Quand** : +- Groupe massif (≄ 10 unitĂ©s) +- MĂȘme destination +- Contraintes tactiques identiques +- RTS-style group movement + +**Performance Target** : +- < 15ms pour 50 unitĂ©s +- < 20ms pour 100 unitĂ©s +- < 30ms pour 500 unitĂ©s +- Scaling linĂ©aire avec nombre unitĂ©s + +### Concept Flow Field + +Au lieu de calculer N chemins individuels, calcule **1 champ vectoriel** que toutes les unitĂ©s suivent. + +``` +Destination = G + +Chaque tile contient vecteur direction optimale : + +↗ ↗ ↗ → → → +↗ ↗ ↗ → → G +↑ ↗ → → ↑ ↑ +↑ ↑ → # # # +↑ ↑ ↑ # # # +S ↑ ↑ # # # + +UnitĂ© en S : Lit vecteur ↑, se dĂ©place nord +UnitĂ© en (2,2) : Lit vecteur ↗, se dĂ©place nord-est + +100 unitĂ©s : 1 seul field calculĂ©! +``` + +### Algorithme Dijkstra Inverse + +```cpp +class FlowFieldGenerator { +public: + FlowField generate(Position goal, PathConstraints constraints) { + // 1. CrĂ©er cost field (coĂ»t depuis goal) + CostField cost_field = generateCostField(goal, constraints); + + // 2. GĂ©nĂ©rer integration field (Dijkstra depuis goal) + IntegrationField integration_field = integrateField(cost_field, goal); + + // 3. GĂ©nĂ©rer flow field (gradients direction) + FlowField flow_field = generateFlowVectors(integration_field); + + return flow_field; + } + +private: + CostField generateCostField(Position goal, PathConstraints constraints) { + CostField field(map_width, map_height); + + // Chaque tile a coĂ»t basĂ© sur terrain, menaces, etc. + for (int x = 0; x < map_width; x++) { + for (int y = 0; y < map_height; y++) { + Position pos = {x, y}; + + if (!isWalkable(pos)) { + field.set(pos, INFINITY); + } else { + float cost = calculateCost(pos, constraints); + field.set(pos, cost); + } + } + } + + return field; + } + + IntegrationField integrateField(CostField& cost_field, Position goal) { + IntegrationField integration(map_width, map_height, INFINITY); + + // Dijkstra INVERSE (depuis goal vers toutes positions) + std::priority_queue open; + integration.set(goal, 0.0f); + open.push({goal, 0.0f}); + + while (!open.empty()) { + Node current = open.top(); + open.pop(); + + for (auto& neighbor : getNeighbors(current.pos)) { + float cost = cost_field.get(neighbor); + if (cost == INFINITY) continue; // Non-walkable + + float new_cost = integration.get(current.pos) + cost; + + if (new_cost < integration.get(neighbor)) { + integration.set(neighbor, new_cost); + open.push({neighbor, new_cost}); + } + } + } + + return integration; + } + + FlowField generateFlowVectors(IntegrationField& integration) { + FlowField flow(map_width, map_height); + + // Pour chaque tile, calculer gradient (direction vers goal) + for (int x = 0; x < map_width; x++) { + for (int y = 0; y < map_height; y++) { + Position pos = {x, y}; + + // Trouver voisin avec coĂ»t minimum + Position best_neighbor = pos; + float min_cost = integration.get(pos); + + for (auto& neighbor : getNeighbors(pos)) { + float cost = integration.get(neighbor); + if (cost < min_cost) { + min_cost = cost; + best_neighbor = neighbor; + } + } + + // Vecteur direction + Vector2 direction = normalize(best_neighbor - pos); + flow.set(pos, direction); + } + } + + return flow; + } +}; +``` + +### Utilisation Flow Field + +```cpp +void moveUnitAlongFlowField(Unit& unit, FlowField& field) { + // Lire direction depuis field + Vector2 direction = field.get(unit.pos); + + // Appliquer mouvement + Vector2 desired_velocity = direction * unit.max_speed; + + // Steering behaviors (Ă©viter collisions) + Vector2 separation = calculateSeparation(unit); + Vector2 cohesion = calculateCohesion(unit); + + unit.velocity = desired_velocity + separation * 0.5f + cohesion * 0.2f; + unit.pos += unit.velocity * delta_time; +} + +Vector2 calculateSeparation(Unit& unit) { + // Éviter unitĂ©s trop proches + Vector2 separation = {0, 0}; + int count = 0; + + for (auto& other : getNearbyUnits(unit, SEPARATION_RADIUS)) { + if (other.id == unit.id) continue; + + Vector2 diff = unit.pos - other.pos; + float distance = length(diff); + + if (distance > 0) { + separation += normalize(diff) / distance; // Repousse inversement proportionnel distance + count++; + } + } + + if (count > 0) { + separation /= count; + } + + return separation; +} +``` + +### Optimisations Flow Field + +**1. Spatial Partitioning** + +Ne gĂ©nĂ©rer field que dans zone active (autour groupe) : + +```cpp +FlowField generateLocalField(Position goal, BoundingBox active_area) { + // Field seulement dans active_area (ex: 512×512 autour groupe) + // RĂ©duit calcul de 2048×2048 → 512×512 (16× plus rapide) +} +``` + +**2. Multi-Resolution Fields** + +```cpp +// Distant du goal : rĂ©solution basse (16×16 tiles par cell) +// Proche du goal : rĂ©solution haute (1×1 tiles par cell) + +FlowField coarse_field = generate(goal, 16); // Loin +FlowField fine_field = generate(goal, 1); // Proche + +Unit utilise field selon distance au goal +``` + +**3. Field Caching** + +```cpp +std::unordered_map field_cache; + +FlowField getOrGenerateField(Position goal, PathConstraints constraints) { + CacheKey key = {goal, constraints.hash()}; + + if (field_cache.contains(key)) { + return field_cache[key]; + } + + FlowField field = generator.generate(goal, constraints); + field_cache[key] = field; + + return field; +} +``` + +--- + +## IntĂ©gration Recastnavigation + +### Recastnavigation = NavMesh Professionnel + +Le projet a **dĂ©jĂ  intĂ©grĂ©** Recastnavigation (AAA-grade library). + +**Composants** : +- **Recast** : GĂ©nĂ©ration NavMesh depuis geometry +- **Detour** : Queries pathfinding sur NavMesh +- **DetourCrowd** : Crowd simulation, collision avoidance +- **DetourTileCache** : Streaming NavMesh par tiles + +### NavMesh vs Grid + +**Grid A*** : +``` +. . . # # # . . +. . . # # # . . +. . . . . . . . + +Chaque tile = walkable/blocked +Pathfinding sur grille discrĂšte +``` + +**NavMesh (Recast)** : +``` + Polygon 1 + /----------\ + / \ + | Obstacle | ← Zones navigables = polygones + | | + \ / + \----------/ + Polygon 2 + +Pathfinding sur polygones continus +``` + +**Avantages NavMesh** : +- ✅ Moins de nƓuds (polygones vs tiles) +- ✅ Mouvement plus naturel (any-angle) +- ✅ OptimisĂ© AAA (Recast utilisĂ© par des dizaines jeux) + +### Architecture Hybride : NavMesh + Grid + +**Proposition Warfactory** : + +```cpp +// NavMesh pour A* et HPA* +Path findPath_NavMesh(Position start, Position goal) { + dtNavMeshQuery* query = navmesh->getQuery(); + + dtPolyRef start_poly = query->findNearestPoly(start); + dtPolyRef goal_poly = query->findNearestPoly(goal); + + std::vector poly_path; + query->findPath(start_poly, goal_poly, poly_path); + + // Convertir poly path → waypoints + return convertToWaypoints(poly_path); +} + +// Grid pour Flow Fields (plus simple gĂ©nĂ©ration field) +FlowField generateField_Grid(Position goal) { + // Dijkstra sur grille 64×64 + // Plus efficace pour fields que NavMesh +} +``` + +**Justification** : +- NavMesh excelle pour chemins individuels (A*, HPA*) +- Grid plus simple pour flow fields (calcul uniforme) + +### IntĂ©gration Chunks 64×64 + +```cpp +class NavMeshManager { +public: + // GĂ©nĂšre NavMesh tile par chunk 64×64 + void buildChunkNavMesh(Chunk& chunk) { + rcConfig config; + config.cs = 1.0f; // Cell size = 1m (tile size) + config.ch = 0.5f; // Cell height = 0.5m + config.walkableSlopeAngle = 45.0f; + config.walkableHeight = 2; // 2m min clearance + config.walkableClimb = 1; // 1m max step + config.walkableRadius = 1; // 1m agent radius + + // Extraire geometry depuis chunk + rcPolyMesh* poly_mesh = generatePolyMesh(chunk, config); + + // CrĂ©er NavMesh tile + dtNavMeshCreateParams params; + // ... setup params ... + + unsigned char* nav_data = nullptr; + int nav_data_size = 0; + dtCreateNavMeshData(¶ms, &nav_data, &nav_data_size); + + // Ajouter tile au NavMesh global + int tile_x = chunk.x / CHUNK_SIZE; + int tile_y = chunk.y / CHUNK_SIZE; + navmesh->addTile(nav_data, nav_data_size, 0, tile_x, tile_y); + } + + // Rebuild tile si chunk modifiĂ© + void onChunkModified(Chunk& chunk) { + removeTile(chunk); + buildChunkNavMesh(chunk); + + // Invalider chemins affectĂ©s + invalidatePathsInChunk(chunk); + } + +private: + dtNavMesh* navmesh; + std::unordered_map chunk_tiles; +}; +``` + +### Streaming NavMesh + +```cpp +void updateNavMeshStreaming(Position player_pos) { + const int LOAD_RADIUS = 5; // Charger 5 chunks autour joueur + + ChunkCoords player_chunk = getChunkCoords(player_pos); + + // Charger chunks proches + for (int dx = -LOAD_RADIUS; dx <= LOAD_RADIUS; dx++) { + for (int dy = -LOAD_RADIUS; dy <= LOAD_RADIUS; dy++) { + ChunkCoords chunk = {player_chunk.x + dx, player_chunk.y + dy}; + + if (!isNavMeshTileLoaded(chunk)) { + loadNavMeshTile(chunk); + } + } + } + + // Unload chunks lointains + for (auto& [chunk_id, tile_ref] : loaded_tiles) { + int distance = manhattanDistance(chunk_id, player_chunk); + + if (distance > LOAD_RADIUS + 2) { + unloadNavMeshTile(chunk_id); + } + } +} +``` + +--- + +## Threat Maps & Tactical Pathfinding + +### Threat Map Generation + +```cpp +class ThreatMap { +public: + void update(std::vector& enemies) { + // Reset threat grid + threat_grid.fill(0.0f); + + // Pour chaque ennemi, propager menace + for (auto& enemy : enemies) { + propagateThreat(enemy); + } + + // Smooth field (blur Gaussien) + smoothThreats(SMOOTH_RADIUS); + } + + float getThreat(Position pos) const { + return threat_grid.get(pos); + } + +private: + void propagateThreat(Enemy& enemy) { + float range = enemy.weapon_range; + float firepower = enemy.firepower; + Position pos = enemy.position; + + // Cercle de menace autour ennemi + int radius = (int)range; + + for (int dx = -radius; dx <= radius; dx++) { + for (int dy = -radius; dy <= radius; dy++) { + float dist = sqrt(dx*dx + dy*dy); + + if (dist > range) continue; + + // Threat decay linĂ©aire avec distance + float threat_value = firepower * (1.0f - dist / range); + + // Line of sight check (optionnel, coĂ»teux) + if (USE_LOS && !hasLineOfSight(pos, pos + Vector2{dx, dy})) { + threat_value *= 0.2f; // Menace rĂ©duite sans LOS + } + + int x = pos.x + dx; + int y = pos.y + dy; + + if (inBounds(x, y)) { + threat_grid.add({x, y}, threat_value); + } + } + } + } + + void smoothThreats(int radius) { + // Blur Gaussien pour smooth transitions + Grid temp = threat_grid; + + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + float sum = 0.0f; + float weight_sum = 0.0f; + + for (int dx = -radius; dx <= radius; dx++) { + for (int dy = -radius; dy <= radius; dy++) { + int nx = x + dx; + int ny = y + dy; + + if (!inBounds(nx, ny)) continue; + + float dist = sqrt(dx*dx + dy*dy); + float weight = exp(-dist*dist / (2.0f * radius*radius)); + + sum += temp.get({nx, ny}) * weight; + weight_sum += weight; + } + } + + threat_grid.set({x, y}, sum / weight_sum); + } + } + } + + Grid threat_grid; +}; +``` + +### Cover Map + +```cpp +class CoverMap { +public: + void buildFromTerrain(TerrainMap& terrain) { + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + Position pos = {x, y}; + + CoverInfo info = analyzeCover(pos, terrain); + cover_grid.set(pos, info); + } + } + } + + CoverInfo getCover(Position pos) const { + return cover_grid.get(pos); + } + +private: + struct CoverInfo { + bool has_cover; + Vector2 cover_direction; // Direction protection + float cover_height; // 0.0 = pas cover, 1.0 = full cover + CoverType type; // WALL, ROCK, BUILDING, VEGETATION + }; + + CoverInfo analyzeCover(Position pos, TerrainMap& terrain) { + CoverInfo info; + info.has_cover = false; + + // Check tiles adjacents pour obstacles + for (auto& dir : CARDINAL_DIRECTIONS) { + Position neighbor = pos + dir; + + if (terrain.isObstacle(neighbor)) { + info.has_cover = true; + info.cover_direction = dir; + info.cover_height = terrain.getHeight(neighbor) / MAX_HEIGHT; + info.type = terrain.getCoverType(neighbor); + break; + } + } + + return info; + } + + Grid cover_grid; +}; +``` + +### Cover-to-Cover Pathfinding + +```cpp +Path findCoverToCoverPath(Position start, Position goal, ThreatMap& threats, CoverMap& covers) { + PathConstraints constraints; + constraints.threat_weight = 5.0f; + constraints.cover_weight = 3.0f; + + // A* avec scoring spĂ©cial pour cover + Path path = astar->findPath(start, goal, constraints); + + // Post-process : identifier points cover sur chemin + std::vector cover_waypoints; + + for (auto& wp : path.waypoints) { + CoverInfo cover = covers.getCover(wp.pos); + + wp.has_cover = cover.has_cover; + wp.cover_quality = cover.cover_height; + + if (cover.has_cover) { + wp.pause_duration = 2.0f; // Pause 2s dans cover + cover_waypoints.push_back(wp); + } + } + + // Ajouter metadata pour MovementModule + path.cover_points = cover_waypoints; + path.movement_style = COVER_TO_COVER; + + return path; +} +``` + +--- + +## Terrain Costs + +### Terrain Types + +```cpp +enum TerrainType { + ROAD, // Asphalte, bĂ©ton + GRASS, // Prairie, herbe + FOREST, // ForĂȘt dense + SWAMP, // MarĂ©cage + MOUNTAIN, // Montagne rocheuse + URBAN, // Ville, bĂątiments + SAND, // DĂ©sert + SNOW, // Neige profonde + WATER, // Eau (gĂ©nĂ©ralement impassable) + RUBBLE // DĂ©combres +}; +``` + +### Cost Matrix (Terrain × UnitType) + +```cpp +class TerrainCostTable { +public: + float getCost(TerrainType terrain, UnitType unit) const { + return cost_table[terrain][unit]; + } + +private: + // [Terrain][UnitType] = multiplicateur coĂ»t + static constexpr float cost_table[10][5] = { + // Infantry Tank_Light Tank_Heavy Wheeled Tracked + /* ROAD */ {0.5, 0.3, 0.3, 0.2, 0.4}, + /* GRASS */ {1.0, 1.0, 1.2, 1.2, 0.9}, + /* FOREST */ {1.5, 3.0, 5.0, 8.0, 2.5}, + /* SWAMP */ {3.0, 8.0, 12.0, 15.0, 6.0}, + /* MOUNTAIN */ {2.0, 5.0, 8.0, 99.0, 4.0}, + /* URBAN */ {1.2, 2.0, 2.5, 1.5, 2.0}, + /* SAND */ {1.8, 1.5, 2.0, 3.0, 1.2}, + /* SNOW */ {2.5, 2.0, 3.0, 4.0, 1.8}, + /* WATER */ {99.0, 99.0, 99.0, 99.0, 99.0}, + /* RUBBLE */ {2.0, 3.0, 4.0, 5.0, 2.5} + }; +}; +``` + +### Dynamic Terrain Modification + +```cpp +void onBuildingDestroyed(Building& building) { + // BĂątiment dĂ©truit → terrain devient RUBBLE + for (auto& tile : building.occupiedTiles()) { + terrain_map.setType(tile, RUBBLE); + } + + // Rebuild NavMesh du chunk + Chunk& chunk = getChunk(building.pos); + navmesh_manager->onChunkModified(chunk); + + // Invalider chemins passant par zone + pathfinder->invalidatePathsInArea(building.bounds); +} + +void onCraterCreated(Position pos, float radius) { + // Explosion crĂ©e cratĂšre → terrain difficile + for (int dx = -radius; dx <= radius; dx++) { + for (int dy = -radius; dy <= radius; dy++) { + float dist = sqrt(dx*dx + dy*dy); + if (dist <= radius) { + Position tile = pos + Vector2{dx, dy}; + terrain_map.setType(tile, RUBBLE); + } + } + } + + // Rebuild NavMesh + navmesh_manager->onChunkModified(getChunk(pos)); +} +``` + +--- + +## Architecture IntĂ©gration ITaskScheduler + +### Vue d'Ensemble + +PathfinderModule utilise **ITaskScheduler** pour dĂ©lĂ©guer pathfinding lourd au thread pool global gĂ©rĂ© par IModuleSystem, tout en conservant des opĂ©rations sync pour flow fields et queries tactiques. + +``` +┌─────────────────────────────────────────┐ +│ IModuleSystem (ThreadPool) │ +│ ┌───────────────────────────────────┐ │ +│ │ ITaskScheduler (Async) │ │ +│ │ - A* pathfinding │ │ +│ │ - HPA* pathfinding │ │ +│ │ - Multi-path generation │ │ +│ └───────────────────────────────────┘ │ +└─────────────────────────────────────────┘ + ↓ scheduleTask() + ↓ getCompletedTask() +┌─────────────────────────────────────────┐ +│ PathfinderModule │ +│ ┌──────────────┐ ┌─────────────────┐ │ +│ │ IPathfinder │ │ FlowFieldCache │ │ +│ │ (internal) │ │ (sync) │ │ +│ └──────────────┘ └─────────────────┘ │ +│ ┌──────────────┐ ┌─────────────────┐ │ +│ │ ThreatMap │ │ NavMeshManager │ │ +│ │ (sync) │ │ (sync) │ │ +│ └──────────────┘ └─────────────────┘ │ +└─────────────────────────────────────────┘ + ↓ publish() + ↓ pull() +┌─────────────────────────────────────────┐ +│ IIO (Pub/Sub) │ +│ - pathfinder/requests │ +│ - pathfinder/results │ +│ - pathfinder/flow_fields │ +└─────────────────────────────────────────┘ +``` + +### DĂ©lĂ©gation Async vs Sync + +| OpĂ©ration | Threading | Justification | +|-----------|-----------|---------------| +| A* pathfinding | **ITaskScheduler (async)** | Peut prendre 5-10ms, bloque pas game loop | +| HPA* pathfinding | **ITaskScheduler (async)** | Longue distance, calcul lourd | +| Multi-path generation | **ITaskScheduler (async)** | 3× calculs A*, dĂ©lĂ©guer | +| Flow Fields | **Sync (cache)** | 15ms acceptable, 1 calcul pour N unitĂ©s | +| Threat Map update | **Sync (periodic)** | Mise Ă  jour 1×/seconde suffit | +| Cover queries | **Sync** | Lookup instantanĂ© (pre-computed) | +| NavMesh queries | **Sync** | Recastnavigation thread-safe, rapide | + +--- + +## IPathfinder Interface (Internal) + +Interface abstraite permettant swap Classic ↔ ML pathfinding. + +```cpp +/** + * @brief Abstract pathfinding interface for algorithm implementations + * + * Allows swapping between Classic (A*/HPA*) and ML-based pathfinding + * without changing PathfinderModule code. + */ +class IPathfinder { +public: + virtual ~IPathfinder() = default; + + /** + * @brief Find single optimal path + * @param start Starting position (float world space) + * @param goal Goal position (float world space) + * @param constraints Tactical constraints (threat, cover, terrain) + * @return Computed path with waypoints + */ + virtual Path findPath(Position start, Position goal, + PathConstraints constraints) = 0; + + /** + * @brief Find N alternative paths for flanking + * @param start Starting position + * @param goal Goal position + * @param max_paths Number of alternative paths (default 3) + * @param constraints Tactical constraints + * @return Vector of divergent paths + */ + virtual std::vector findAllPaths(Position start, Position goal, + int max_paths, + PathConstraints constraints) = 0; + + /** + * @brief Validate if path is still walkable + * @param path Path to validate + * @return true if path valid, false if obstacles appeared + */ + virtual bool validatePath(const Path& path) = 0; +}; + +// Classic implementation (A*, HPA*, multi-path) +class ClassicPathfinder : public IPathfinder { + Path findPath(Position start, Position goal, PathConstraints constraints) override; + std::vector findAllPaths(Position start, Position goal, int max_paths, PathConstraints constraints) override; + bool validatePath(const Path& path) override; +}; + +// ML implementation (future) +class MLPathfinder : public IPathfinder { + // Neural network trained on Classic pathfinder outputs + Path findPath(Position start, Position goal, PathConstraints constraints) override; + std::vector findAllPaths(Position start, Position goal, int max_paths, PathConstraints constraints) override; + bool validatePath(const Path& path) override; +}; +``` + +--- + +## PathfinderModule Implementation + +### Class Definition + +```cpp +class PathfinderModule : public IModule { +private: + // ===== FRAMEWORK INTERFACES ===== + ITaskScheduler* scheduler; // Thread pool delegation (provided by IModuleSystem) + IIO* io; // Pub/sub communication + + // ===== INTERNAL COMPONENTS ===== + + // Pathfinding logic (swappable Classic ↔ ML) + std::unique_ptr pathfinder; + + // Flow fields (sync, cached) + FlowFieldCache flow_cache; + + // Tactical data (sync, periodic updates) + ThreatMap threat_map; + CoverMap cover_map; + + // NavMesh (sync queries, managed by Recastnavigation) + NavMeshManager navmesh_mgr; + dtNavMesh* global_navmesh; + + // Configuration + const IDataNode* config; + +public: + // ========== IMODULE INTERFACE ========== + + void setConfiguration(const IDataNode& config, IIO* io, ITaskScheduler* scheduler) override { + this->config = &config; + this->io = io; + this->scheduler = scheduler; + + // Select pathfinder implementation from config + std::string impl = config.getString("pathfinder_impl", "classic"); + + if (impl == "classic") { + pathfinder = std::make_unique(); + } + else if (impl == "ml") { + pathfinder = std::make_unique(); + } + + // Initialize NavMesh manager + navmesh_mgr.initialize(config.getChildNode("navmesh")); + + // Build initial NavMesh for loaded chunks + buildInitialNavMesh(); + } + + json process(const json& input) override { + // 1. Process incoming requests via IIO + processIORequests(); + + // 2. Pull completed pathfinding tasks from ITaskScheduler + processCompletedTasks(); + + // 3. Periodic threat map update (1×/second) + if (shouldUpdateThreatMap()) { + updateThreatMapSync(); + } + + return {}; + } + + const IDataNode& getConfiguration() override { + return *config; + } + + json getHealthStatus() override { + return { + {"module", "pathfinder"}, + {"pathfinder_impl", pathfinder ? "active" : "null"}, + {"pending_tasks", scheduler->hasCompletedTasks()}, + {"flow_fields_cached", flow_cache.size()}, + {"navmesh_tiles", navmesh_mgr.getTileCount()} + }; + } + +private: + // ========== REQUEST PROCESSING ========== + + void processIORequests() { + // Pull requests from IIO + auto requests = io->pull("pathfinder/requests"); + + for (auto& req : requests) { + std::string type = req["type"]; + + if (type == "single_path") { + handleSinglePathRequest(req); + } + else if (type == "multi_path") { + handleMultiPathRequest(req); + } + else if (type == "flow_field") { + handleFlowFieldRequest(req); + } + else if (type == "tactical_query") { + handleTacticalQuery(req); + } + } + } + + void handleSinglePathRequest(const json& req) { + // Delegate to ITaskScheduler (async multithread) + scheduler->scheduleTask("pathfinding", { + {"request_id", req["request_id"]}, + {"unit_id", req["unit_id"]}, + {"start", req["start"]}, + {"goal", req["goal"]}, + {"constraints", req["constraints"]}, + {"path_type", "single"} + }); + } + + void handleMultiPathRequest(const json& req) { + // Delegate multi-path to ITaskScheduler + scheduler->scheduleTask("pathfinding", { + {"request_id", req["request_id"]}, + {"unit_id", req["unit_id"]}, + {"start", req["start"]}, + {"goal", req["goal"]}, + {"constraints", req["constraints"]}, + {"path_type", "multi"}, + {"max_paths", req.value("max_paths", 3)} + }); + } + + void handleFlowFieldRequest(const json& req) { + // Flow fields generated SYNC (15ms acceptable, 1 calc for N units) + Position goal = parsePosition(req["goal"]); + PathConstraints constraints = parseConstraints(req["constraints"]); + + // Get or generate (cached) + FlowField field = flow_cache.getOrGenerate(goal, constraints); + FlowFieldId id = flow_cache.add(field); + + // Publish immediately + io->publish("pathfinder/flow_fields", { + {"request_id", req["request_id"]}, + {"field_id", id}, + {"goal", req["goal"]} + }); + } + + void handleTacticalQuery(const json& req) { + // Tactical queries are sync (fast lookups) + std::string query_type = req["query_type"]; + + if (query_type == "nearest_cover") { + Position from = parsePosition(req["from"]); + Vector2 threat_dir = parseVector2(req["threat_direction"]); + float max_dist = req.value("max_distance", 50.0f); + + Position cover_pos = findNearestCoverSync(from, threat_dir, max_dist); + + io->publish("pathfinder/tactical_results", { + {"request_id", req["request_id"]}, + {"query_type", "nearest_cover"}, + {"result", {cover_pos.x, cover_pos.y}} + }); + } + else if (query_type == "flanking_positions") { + Position target = parsePosition(req["target"]); + int count = req.value("count", 3); + float distance = req.value("distance", 30.0f); + + auto positions = findFlankingPositionsSync(target, count, distance); + + io->publish("pathfinder/tactical_results", { + {"request_id", req["request_id"]}, + {"query_type", "flanking_positions"}, + {"result", serializePositions(positions)} + }); + } + } + + // ========== TASK COMPLETION ========== + + void processCompletedTasks() { + // Pull all completed pathfinding tasks from scheduler + while (scheduler->hasCompletedTasks() > 0) { + json result = scheduler->getCompletedTask(); + + // Add tactical metadata + enrichPathResult(result); + + // Publish result via IIO + io->publish("pathfinder/results", result); + } + } + + void enrichPathResult(json& result) { + // Add threat/cover metrics to path + if (result.contains("path")) { + auto waypoints = result["path"]; + + float total_threat = 0.0f; + int cover_count = 0; + + for (auto& wp : waypoints) { + Position pos = {wp["x"], wp["y"]}; + + total_threat += threat_map.getThreat(pos); + if (cover_map.getCover(pos).has_cover) { + cover_count++; + } + } + + result["threat_level"] = total_threat / waypoints.size(); + result["cover_percentage"] = (float)cover_count / waypoints.size(); + } + } + + // ========== SYNC OPERATIONS ========== + + bool shouldUpdateThreatMap() { + static int last_update_frame = 0; + int current_frame = getCurrentFrame(); + + // Update 1×/second (60 frames @ 60fps) + if (current_frame - last_update_frame >= 60) { + last_update_frame = current_frame; + return true; + } + + return false; + } + + void updateThreatMapSync() { + // Get enemies from game state (via IIO or direct query) + auto enemies = getEnemiesFromGameState(); + + // Update threat map (sync, ~2-5ms) + threat_map.update(enemies); + } + + Position findNearestCoverSync(Position from, Vector2 threat_dir, float max_dist) { + // Sync lookup in pre-computed cover map + return cover_map.findNearest(from, threat_dir, max_dist); + } + + std::vector findFlankingPositionsSync(Position target, int count, float distance) { + // Generate positions around target + std::vector positions; + + float angle_step = 2.0f * M_PI / count; + + for (int i = 0; i < count; i++) { + float angle = i * angle_step; + Position pos = { + target.x + cos(angle) * distance, + target.y + sin(angle) * distance + }; + + // Validate walkable + if (navmesh_mgr.isWalkable(pos)) { + positions.push_back(pos); + } + } + + return positions; + } +}; +``` + +--- + +## ITaskScheduler Backend (Execution) + +Le backend est gĂ©rĂ© par **IModuleSystem** (pas par PathfinderModule). + +```cpp +/** + * @brief Task execution in worker threads (managed by IModuleSystem) + * + * PathfinderModule delegates tasks via ITaskScheduler. + * MultithreadedModuleSystem executes tasks in thread pool. + */ +class MultithreadedModuleSystem : public IModuleSystem { +private: + ThreadPool thread_pool; + + // Task scheduler per module + std::map> schedulers; + + class TaskSchedulerImpl : public ITaskScheduler { + private: + ThreadPool* pool; + std::queue completed_tasks; + std::mutex completed_mutex; + + public: + void scheduleTask(const std::string& taskType, const json& taskData) override { + // Submit to thread pool + pool->enqueue([this, taskType, taskData]() { + json result; + + if (taskType == "pathfinding") { + result = executePathfindingTask(taskData); + } + // ... other task types + + // Store result + std::lock_guard lock(completed_mutex); + completed_tasks.push(result); + }); + } + + int hasCompletedTasks() const override { + std::lock_guard lock(completed_mutex); + return completed_tasks.size(); + } + + json getCompletedTask() override { + std::lock_guard lock(completed_mutex); + + if (completed_tasks.empty()) { + return {}; + } + + json result = completed_tasks.front(); + completed_tasks.pop(); + return result; + } + + private: + json executePathfindingTask(const json& taskData) { + // Thread-local pathfinder (no shared state) + static thread_local ClassicPathfinder pathfinder; + + Position start = parsePosition(taskData["start"]); + Position goal = parsePosition(taskData["goal"]); + PathConstraints constraints = parseConstraints(taskData["constraints"]); + + if (taskData["path_type"] == "single") { + Path path = pathfinder.findPath(start, goal, constraints); + + return { + {"task_type", "pathfinding"}, + {"request_id", taskData["request_id"]}, + {"unit_id", taskData["unit_id"]}, + {"path", serializePath(path)} + }; + } + else if (taskData["path_type"] == "multi") { + int max_paths = taskData["max_paths"]; + auto paths = pathfinder.findAllPaths(start, goal, max_paths, constraints); + + return { + {"task_type", "pathfinding"}, + {"request_id", taskData["request_id"]}, + {"unit_id", taskData["unit_id"]}, + {"paths", serializePaths(paths)} + }; + } + + return {}; + } + }; +}; +``` + +--- + +## Flow Fields avec Float Positions + +### ProblĂšme : Grid DiscrĂšte vs UnitĂ©s Float + +``` +Flow Field = grille discrĂšte (tiles entiers) +UnitĂ©s = positions float continues + +Unit pos = (127.34, 89.67) ← Float world space +Flow Field cell = [127, 89] ← Grid space +``` + +### Solution : Interpolation BilinĂ©aire + +```cpp +/** + * @brief Get flow direction at continuous float position + * @param field Flow field (discrete grid) + * @param float_pos Unit position (continuous float) + * @return Interpolated direction vector + */ +Vector2 getFlowDirection(FlowField& field, Position float_pos) { + // Convert float → grid coords + int x0 = (int)floor(float_pos.x); + int y0 = (int)floor(float_pos.y); + int x1 = x0 + 1; + int y1 = y0 + 1; + + // Interpolation factors (0.0-1.0) + float fx = float_pos.x - x0; + float fy = float_pos.y - y0; + + // Read 4 neighbor vectors + Vector2 v00 = field.get(x0, y0); + Vector2 v10 = field.get(x1, y0); + Vector2 v01 = field.get(x0, y1); + Vector2 v11 = field.get(x1, y1); + + // Bilinear interpolation + Vector2 v0 = lerp(v00, v10, fx); // Horizontal interpolation + Vector2 v1 = lerp(v01, v11, fx); + Vector2 result = lerp(v0, v1, fy); // Vertical interpolation + + return normalize(result); +} + +Vector2 lerp(Vector2 a, Vector2 b, float t) { + return { + a.x + (b.x - a.x) * t, + a.y + (b.y - a.y) * t + }; +} +``` + +### Unit Movement with Flow Field + +```cpp +/** + * @brief Update unit position using flow field + steering behaviors + * @param unit Unit to update (float position, float velocity) + * @param field Flow field + * @param delta_time Frame delta time + */ +void updateUnitWithFlowField(Unit& unit, FlowField& field, float delta_time) { + // 1. Read desired direction from flow field (interpolated) + Vector2 desired_direction = getFlowDirection(field, unit.pos); + + // 2. Steering behaviors (boids-style) + Vector2 separation = calculateSeparation(unit); // Avoid other units + Vector2 cohesion = calculateCohesion(unit); // Stay grouped + Vector2 alignment = calculateAlignment(unit); // Align with group + + // 3. Combine (weighted) + Vector2 steering = desired_direction * 1.0f + // Flow field priority + separation * 0.8f + // Collision avoidance + cohesion * 0.3f + // Group cohesion + alignment * 0.2f; // Direction alignment + + // 4. Apply velocity + unit.velocity = normalize(steering) * unit.max_speed; + unit.pos += unit.velocity * delta_time; + + // 5. Collision resolution (physics) + resolveUnitCollisions(unit); +} +``` + +### Unit-to-Unit Collisions (Float Space) + +```cpp +/** + * @brief Resolve collisions between units (float positions, circular colliders) + * @param unit Unit to check collisions for + */ +void resolveUnitCollisions(Unit& unit) { + // Spatial hash for fast neighbor queries + auto nearby = spatial_hash.query(unit.pos, unit.radius * 3.0f); + + for (auto& other : nearby) { + if (other.id == unit.id) continue; + + Vector2 diff = unit.pos - other.pos; + float dist = length(diff); + float min_dist = unit.radius + other.radius; + + if (dist < min_dist && dist > 0.001f) { + // Collision detected! Separate units + Vector2 separation = normalize(diff) * (min_dist - dist) * 0.5f; + + unit.pos += separation; + other.pos -= separation; + + // Velocity damping (elastic bounce) + float restitution = 0.3f; + float impact = dot(unit.velocity, normalize(diff)); + + unit.velocity -= normalize(diff) * impact * restitution; + other.velocity += normalize(diff) * impact * restitution; + } + } +} + +/** + * @brief Calculate separation force (boids steering) + * @param unit Unit to calculate separation for + * @return Separation vector (away from nearby units) + */ +Vector2 calculateSeparation(Unit& unit) { + const float SEPARATION_RADIUS = 5.0f; // 5m radius + + Vector2 separation = {0, 0}; + int count = 0; + + auto nearby = spatial_hash.query(unit.pos, SEPARATION_RADIUS); + + for (auto& other : nearby) { + if (other.id == unit.id) continue; + + Vector2 diff = unit.pos - other.pos; + float dist = length(diff); + + if (dist > 0 && dist < SEPARATION_RADIUS) { + // Force inversely proportional to distance + separation += normalize(diff) / dist; + count++; + } + } + + if (count > 0) { + separation /= count; + } + + return separation; +} +``` + +### Path Structure + +```cpp +struct Path { + std::vector waypoints; + + // Metrics tactiques + float length; // Distance totale (m) + float threat_level; // 0.0-1.0 (exposition ennemie) + float cover_percentage; // % du chemin avec cover + bool crosses_open_terrain; // Traverse terrain ouvert ? + bool has_chokepoints; // Contient goulets ? + + // Metadata + PathfindingAlgorithm algorithm; // A*, HPA*, ou FLOW_FIELD + float computation_time_ms; // Temps calcul + int waypoint_count; + + // Cover points + std::vector cover_points; // Waypoints avec cover + MovementStyle movement_style; // DIRECT, COVER_TO_COVER, STEALTH + + // Validation + bool is_valid; + int last_validation_frame; +}; + +struct Waypoint { + Position pos; + + // Tactical metadata + bool has_cover; + float cover_quality; // 0.0-1.0 + Vector2 cover_direction; // Direction protection + float threat_level; // Menace Ă  cette position + + // Movement metadata + float pause_duration; // Temps pause (cover, observation) + MovementSpeed speed; // SPRINT, RUN, WALK, CROUCH +}; + +enum MovementStyle { + DIRECT, // Ligne droite, rapide + COVER_TO_COVER, // Pause dans covers + STEALTH, // Lent, Ă©vite dĂ©tection + AGGRESSIVE // Rapide, ignore menaces +}; +``` + +--- + +## Performance Benchmarks & Targets + +### Targets par Algorithme + +| Algorithme | Distance | UnitĂ©s | Target | Acceptable | +|------------|----------|--------|--------|------------| +| A* | 50m | 1 | < 2ms | < 5ms | +| A* | 100m | 1 | < 5ms | < 10ms | +| HPA* | 500m | 1 | < 5ms | < 10ms | +| HPA* | 5000m | 1 | < 10ms | < 15ms | +| Flow Field | 500m | 50 | < 15ms | < 20ms | +| Flow Field | 500m | 100 | < 20ms | < 30ms | +| Multi-Path (3) | 100m | 1 | < 10ms | < 15ms | + +### Budget Frame (60fps = 16.67ms) + +``` +Total Frame Budget : 16.67ms + +Distribution : +- Rendering : 6ms (36%) +- Physics : 2ms (12%) +- AI Decisions : 2ms (12%) +- Pathfinding : 4ms (24%) ← BUDGET +- Movement : 1ms (6%) +- Other : 1.67ms (10%) + +Pathfinding budget : 4ms MAX + → ~2 A* paths per frame + → ou 1 Flow Field + → ou 4 HPA* paths +``` + +### Optimisations Performance + +**1. Async Pathfinding** + +```cpp +class AsyncPathfinder { +public: + std::future findPathAsync(Position start, Position goal, PathConstraints constraints) { + return std::async(std::launch::async, [=]() { + return pathfinder->findPath(start, goal, constraints); + }); + } + + void update() { + // Check completed async requests + for (auto it = pending_requests.begin(); it != pending_requests.end();) { + if (it->future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) { + Path path = it->future.get(); + it->callback(path); + it = pending_requests.erase(it); + } else { + ++it; + } + } + } +}; +``` + +**2. Path Pooling** + +```cpp +class PathPool { +public: + Path* acquire() { + if (available_paths.empty()) { + return new Path(); + } + + Path* path = available_paths.back(); + available_paths.pop_back(); + path->clear(); + return path; + } + + void release(Path* path) { + available_paths.push_back(path); + } + +private: + std::vector available_paths; +}; +``` + +**3. Spatial Hashing** + +```cpp +class SpatialPathCache { +public: + Path* getCachedPath(Position start, Position goal, float tolerance = 5.0f) { + // Hash start/goal dans grille spatiale + CellId cell = hashPosition(start, goal); + + auto& paths_in_cell = spatial_cache[cell]; + + for (auto& cached : paths_in_cell) { + if (distance(cached.start, start) < tolerance && + distance(cached.goal, goal) < tolerance) { + + // Valider chemin encore valide + if (validatePath(cached.path)) { + return &cached.path; + } + } + } + + return nullptr; // Pas en cache + } +}; +``` + +--- + +## Cas d'Usage Complets + +### Cas 1 : Infanterie Avance sous Feu + +```cpp +// Situation : 10 soldats doivent traverser zone sous feu ennemi +Position start = squad.getCenter(); +Position objective = {500, 300}; + +// Setup threat map +ThreatMap threats; +threats.addThreatSource(enemy_mg.pos, enemy_mg.range, enemy_mg.firepower); + +// Contraintes : MAX cover, Ă©viter menaces +PathConstraints infantry_constraints; +infantry_constraints.threat_weight = 5.0f; +infantry_constraints.cover_weight = 3.0f; +infantry_constraints.exposure_weight = 10.0f; +infantry_constraints.unit_type = INFANTRY; +infantry_constraints.doctrine = CAUTIOUS; + +// GĂ©nĂšre chemin cover-to-cover +Path path = pathfinder->findCoverToCoverPath(start, objective, threats, cover_map); + +// Assigne aux unitĂ©s +for (auto& soldier : squad) { + soldier.setPath(path); + soldier.movement_style = COVER_TO_COVER; +} + +// RĂ©sultat : +// - Chemin zigzague entre covers +// - Pauses 2-3s dans chaque cover +// - Évite terrain ouvert +// - Traverse zone en 45s au lieu de 15s (direct) +// - 0 pertes au lieu de 50% (direct) +``` + +### Cas 2 : Tank Assault avec 3 Routes Flanking + +```cpp +// Situation : 1 tank doit attaquer position fortifiĂ©e +Position tank_pos = {100, 100}; +Position enemy_bunker = {400, 400}; + +// Contraintes tank +PathConstraints tank_constraints; +tank_constraints.threat_weight = 2.0f; +tank_constraints.terrain_weight = 2.0f; // Évite forĂȘts +tank_constraints.prefer_roads = true; +tank_constraints.unit_type = TANK_MEDIUM; + +// GĂ©nĂšre 3 chemins alternatifs +auto paths = pathfinder->findAllPaths(tank_pos, enemy_bunker, 3, tank_constraints); + +// Score chemins selon situation tactique +TacticalScore scores[3]; +for (int i = 0; i < 3; i++) { + scores[i].threat = paths[i].threat_level; + scores[i].distance = paths[i].length; + scores[i].cover = paths[i].cover_percentage; + scores[i].time = paths[i].length / tank.speed; + + // Score composite (doctrine agressive) + scores[i].total = + scores[i].threat * -0.3f + // Menace pas trop importante + scores[i].distance * -0.2f + // Distance compte un peu + scores[i].cover * 0.1f + // Cover bonus mineur + scores[i].time * -0.4f; // Vitesse PRIORITÉ +} + +// Choisit meilleur +int best = std::max_element(scores, scores+3) - scores; +tank.setPath(paths[best]); + +// RĂ©sultat : +// paths[0] : Direct, threat=0.8, time=20s → score=-0.5 +// paths[1] : Flanking gauche, threat=0.4, time=30s → score=-0.3 ✅ CHOISI +// paths[2] : Flanking droite (forĂȘt), threat=0.2, time=60s → score=-0.8 +``` + +### Cas 3 : 50 Tanks Convergent vers Objectif + +```cpp +// Situation : 50 tanks dispersĂ©s convergent vers point rally +Position rally_point = {1000, 1000}; + +// Contraintes communes +PathConstraints tank_constraints; +tank_constraints.prefer_roads = true; +tank_constraints.unit_type = TANK_HEAVY; + +// Check si flow field viable +int tanks_with_same_goal = 0; +for (auto& tank : all_tanks) { + if (tank.goal == rally_point) { + tanks_with_same_goal++; + } +} + +if (tanks_with_same_goal >= 10) { + // Flow Field optimal + FlowField field = pathfinder->generateFlowField(rally_point, tank_constraints); + + for (auto& tank : all_tanks) { + if (tank.goal == rally_point) { + tank.setFlowField(field); // PartagĂ©! + } + } + + // Performance : 15ms pour 50 tanks au lieu de 50 × 5ms = 250ms + +} else { + // Pas assez d'unitĂ©s, HPA* individuel + for (auto& tank : all_tanks) { + Path path = pathfinder->findPath(tank.pos, rally_point, tank_constraints); + tank.setPath(path); + } +} +``` + +--- + +## Configuration Module + +### gameconfig.json + +```json +{ + "modules": { + "pathfinding": { + "enabled": true, + "frequency": 10, + + "algorithms": { + "astar": { + "max_distance": 100.0, + "max_iterations": 10000, + "heuristic": "euclidean" + }, + + "hierarchical": { + "cluster_size": 256, + "levels": 2, + "cache_size": 1000, + "rebuild_interval": 300 + }, + + "flow_field": { + "resolution": 1.0, + "smooth_radius": 2, + "local_field_size": 512, + "cache_duration": 10.0 + } + }, + + "navmesh": { + "cell_size": 1.0, + "cell_height": 0.5, + "agent_height": 2.0, + "agent_radius": 1.0, + "max_slope": 45.0, + "max_climb": 1.0 + }, + + "performance": { + "async_pathfinding": true, + "max_paths_per_frame": 2, + "path_pool_size": 100, + "cache_paths": true, + "cache_size": 500 + }, + + "tactical": { + "update_threat_map": true, + "threat_map_resolution": 2.0, + "cover_detection_radius": 5.0, + "line_of_sight_checks": true + }, + + "debug": { + "visualize_paths": false, + "visualize_flow_fields": false, + "visualize_navmesh": false, + "log_performance": true + } + } + } +} +``` + +--- + +## Roadmap ImplĂ©mentation + +### Phase 1 : Foundation (2 semaines) +- [ ] Structure Path, Waypoint, PathConstraints +- [ ] Interface PathfinderModule complĂšte +- [ ] A* basique sur grille 64×64 +- [ ] Terrain cost table +- [ ] Tests unitaires A* + +### Phase 2 : Weighted A* (1 semaine) +- [ ] ThreatMap implementation +- [ ] CoverMap implementation +- [ ] Weighted cost calculation +- [ ] PathConstraints integration +- [ ] Doctrine presets + +### Phase 3 : Multi-Path (1 semaine) +- [ ] Penalty-based A* pour divergence +- [ ] findAllPaths() implementation +- [ ] Path scoring tactique +- [ ] Tests flanking scenarios + +### Phase 4 : Recastnavigation (2 semaines) +- [ ] NavMesh gĂ©nĂ©ration par chunk +- [ ] Detour queries integration +- [ ] NavMesh streaming +- [ ] Dynamic obstacle updates +- [ ] NavMesh rebuild system + +### Phase 5 : HPA* (2 semaines) +- [ ] Cluster graph construction +- [ ] Intra-cluster path caching +- [ ] Inter-cluster A* sur abstract graph +- [ ] Path smoothing +- [ ] Multi-level hierarchies + +### Phase 6 : Flow Fields (1 semaine) +- [ ] Cost field generation +- [ ] Integration field (Dijkstra inverse) +- [ ] Flow vector field +- [ ] Unit steering along field +- [ ] Field caching + +### Phase 7 : Optimization (1 semaine) +- [ ] Async pathfinding +- [ ] Path pooling +- [ ] Spatial caching +- [ ] Performance profiling +- [ ] Benchmarks validation + +### Phase 8 : Polish (1 semaine) +- [ ] Cover-to-cover pathfinding +- [ ] Flanking position finder +- [ ] Line of sight queries +- [ ] Debug visualization +- [ ] Documentation finalization + +**Total : ~11 semaines pour systĂšme complet** + +--- + +## RĂ©fĂ©rences Techniques + +### Algorithmes +- **A***: Hart, P. E.; Nilsson, N. J.; Raphael, B. (1968). "A Formal Basis for the Heuristic Determination of Minimum Cost Paths" +- **HPA***: Botea, MĂŒller, Schaeffer (2004). "Near Optimal Hierarchical Path-Finding" +- **Flow Fields**: Elias (2010). "Crowd Path Finding and Steering Using Flow Field Tiles" + +### Libraries +- **Recastnavigation**: https://github.com/recastnavigation/recastnavigation +- **DĂ©tails integration**: `src/core/_deps/recastnavigation-src/` + +### Warfactory Docs +- `map-system.md` : Chunk system 64×64 +- `systemes-techniques.md` : Architecture multi-Ă©chelle +- `ai-framework.md` : PathfinderModule interface, AI integration +- `systeme-militaire.md` : Tactical AI, doctrines + +--- + +## Glossaire + +- **A*** : Algorithme pathfinding optimal avec heuristique +- **HPA*** : Hierarchical Pathfinding A*, multi-niveaux abstraction +- **Flow Field** : Champ vectoriel direction optimale vers goal +- **NavMesh** : Navigation Mesh, polygones navigables +- **Dijkstra** : Algorithme shortest path sans heuristique +- **Threat Map** : Grille valeurs menace ennemie +- **Cover Map** : Grille positions cover disponibles +- **Waypoint** : Point passage sur chemin +- **Constraint** : Contrainte pathfinding (poids, interdictions) +- **Doctrine** : Preset poids tactiques (aggressive, cautious, etc.) +- **Cluster** : Zone abstraction pour HPA* +- **Edge** : Connexion entre clusters HPA* +- **Integration Field** : Champ coĂ»ts cumulĂ©s depuis goal (flow fields) +- **Cost Field** : Champ coĂ»ts base terrain (flow fields) + +--- + +**Ce systĂšme hybride offre le meilleur des trois mondes : prĂ©cision tactique (A*), vitesse longue distance (HPA*), et scaling groupes massifs (Flow Fields).** diff --git a/docs/02-systems/rendering-system.md b/docs/02-systems/rendering-system.md new file mode 100644 index 0000000..296c82f --- /dev/null +++ b/docs/02-systems/rendering-system.md @@ -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 fixedComponents; + + // Composants mobiles (tĂȘtes, armes, tourelles) + std::vector 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 compositionCache; + + SpriteID getComposedSprite(const std::vector& 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 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 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 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 diff --git a/docs/calcul-menace.md b/docs/calcul-menace.md index 979797e..f7a1774 100644 --- a/docs/calcul-menace.md +++ b/docs/calcul-menace.md @@ -8,9 +8,24 @@ Le systĂšme de calcul de menace Ă©value la **dangerositĂ© qu'une entitĂ© reprĂ©s - **Contextuel** : Menace calculĂ©e selon capacitĂ©s **des deux parties** - **AsymĂ©trique** : A menace B ≠ B menace A -- **Sword & Shield** : QualitĂ© dĂ©fenses peut annuler supĂ©rioritĂ© numĂ©rique +- **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 @@ -56,12 +71,12 @@ struct ThreatCalculationParams { ## Évaluation Forces Actuelles -### Principe : Sword & Shield +### 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** : Dans quelle mesure le shield arrĂȘte le sword +3. **Effectiveness** : Ratio pĂ©nĂ©tration/armure avec baseline 20% minimum ```cpp int evaluateCurrentForces(Entity attacker, Entity defender) { @@ -73,9 +88,95 @@ int evaluateCurrentForces(Entity attacker, Entity defender) { } ``` -### Évaluation Domaine Terrestre +## SystĂšme Armor vs Penetration -#### Inventaire Forces +### 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 @@ -98,7 +199,7 @@ struct LandDefenses { }; ``` -#### Couples Équipement ↔ Contre-mesures +### Couples Équipement ↔ Contre-mesures **Principe** : Chaque type d'Ă©quipement offensif a des contre-mesures spĂ©cifiques. @@ -114,50 +215,7 @@ struct EquipmentCounters { }; ``` -#### Évaluation Sword vs Shield - -**Étape 1 : Match-making** - -Pour chaque Ă©quipement offensif, identifier contre-mesures dĂ©fensives applicables : - -```cpp -std::vector findApplicableDefenses( - Equipment sword, - std::vector available_defenses -) { - std::vector applicable; - - auto counters = EquipmentCounters::counters[sword.type]; - - for (auto& defense : available_defenses) { - // VĂ©rifier si dĂ©fense peut contrer cet Ă©quipement - if (std::find(counters.begin(), counters.end(), defense.type) != counters.end()) { - // VĂ©rifier compatibilitĂ© gĂ©nĂ©ration/qualitĂ© - if (canCounter(defense, sword)) { - applicable.push_back(defense); - } - } - } - - return applicable; -} - -bool canCounter(Defense defense, Equipment sword) { - // Exemple : AT missile Gen2 ne peut pas contrer tank Gen4 avec armure avancĂ©e - if (defense.generation < sword.generation - 1) { - return false; // Trop ancien - } - - // VĂ©rifier spĂ©cificitĂ©s - if (sword.has_reactive_armor && defense.type == AT_MISSILE_OLD) { - return false; // ERA bloque missiles anciens - } - - return true; -} -``` - -**Étape 2 : Calcul Defensive Effectiveness** +### Calcul Defensive Effectiveness ```cpp float calculateDefensiveEffectiveness( @@ -168,7 +226,7 @@ float calculateDefensiveEffectiveness( float neutralized_value = 0; for (auto& sword : swords) { - float sword_value = sword.quantity * sword.quality; + float sword_value = sword.quantity * sword.combat_value; total_sword_value += sword_value; // Trouver dĂ©fenses applicables @@ -177,8 +235,9 @@ float calculateDefensiveEffectiveness( // Calculer valeur dĂ©fensive totale contre ce sword float shield_value = 0; for (auto& shield : applicable_shields) { - float shield_effectiveness = calculateShieldEffectiveness(shield, sword); - shield_value += shield.quantity * shield.quality * shield_effectiveness; + // ✅ EFFECTIVENESS FLOAT (20%-90%) + float effectiveness = calculateCounterEffectiveness(shield, sword); + shield_value += shield.quantity * shield.combat_value * effectiveness; } // Neutralisation proportionnelle @@ -190,7 +249,7 @@ float calculateDefensiveEffectiveness( } ``` -**Étape 3 : Score Final** +### Score Final avec Menace RĂ©siduelle ```cpp int evaluateLandThreat(Entity attacker, Entity defender) { @@ -206,85 +265,154 @@ int evaluateLandThreat(Entity attacker, Entity defender) { // RĂ©duction par dĂ©fenses float defensive_effectiveness = calculateDefensiveEffectiveness(swords, shields); - // Menace finale - int final_threat = raw_threat * (1.0f - defensive_effectiveness); + // ✅ 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 +## Exemples Concrets Terre -#### Exemple 1 : QualitĂ© Domine QuantitĂ© +### Exemple 1 : Tech ObsolĂšte Viable en Masse **Attaquant** : - 20 tanks Gen4 (Leopard 2A7) - - Armure composite avancĂ©e - - GĂ©nĂ©ration 4 - - Combat value : 1000/tank - - Menace brute : 20 × 1000 = 20 000 + - armor_average : 400mm RHA + - combat_value : 1000/tank + - Menace brute : 20 000 + - Valeur totale : 20 × 8M€ = 160M€ **DĂ©fenseur** : -- 100 000 AT missiles Gen2 - - Anciens, inefficaces contre armure Gen4 - - `canCounter()` retourne `false` - - DĂ©fense applicable : 0 +- 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 = 0 / 20000 = 0% -final_threat = 20000 × (1 - 0) = 20 000 -``` -→ **Menace Ă©levĂ©e** : DĂ©fenses obsolĂštes inefficaces +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 -#### Exemple 2 : QuantitĂ© + QualitĂ© Écrasent +→ 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** : -- 1000 tanks Gen2 - - Armure standard - - Combat value : 400/tank - - Menace brute : 1000 × 400 = 400 000 +- 20 tanks Gen4 (Leopard 2A7) + - armor_average : 400mm + - Menace brute : 20 000 **DĂ©fenseur** : -- 500 AT missiles Gen4 (Javelin) - - Top-attack, trĂšs efficaces - - Combat value : 800/missile - - `canCounter()` retourne `true` - - Shield effectiveness : 0.9 (trĂšs efficace) - - Shield value : 500 × 800 × 0.9 = 360 000 +- 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 = 360000 / 400000 = 90% -final_threat = 400000 × (1 - 0.9) = 40 000 -``` -→ **Menace faible** : DĂ©fenses qualitatives rĂ©duisent massavement +defensive_effectiveness = min(1.0, 21000 / 20000) = 100% +residual_multiplier = 5% +final_threat = 20000 × 0.05 = 1 000 -#### Exemple 3 : Masse Insuffisante +→ 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** : -- 1000 tanks Gen2 - - Combat value : 400/tank - - Menace brute : 400 000 +- 20 tanks Gen4 + - Menace brute : 20 000 **DĂ©fenseur** : -- 20 AT missiles Gen4 - - TrĂšs efficaces mais **pas assez nombreux** - - Shield value : 20 × 800 × 0.9 = 14 400 +- 500 RPG-7 + - effectiveness : 20% + - shield_value : 500 × 50 × 0.20 = 5 000 **RĂ©sultat** : ``` -defensive_effectiveness = 14400 / 400000 = 3.6% -final_threat = 400000 × (1 - 0.036) = 385 440 +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 ``` -→ **Menace reste Ă©levĂ©e** : Pas assez de dĂ©fenses pour couvrir la masse -### Évaluation Domaine AĂ©rien +### Exemple 4 : DĂ©fense Mixte Économique -#### SpĂ©cificitĂ©s Air +**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** : Quelques jets furtifs Gen4 dominent des centaines AA Gen2 +- **QualitĂ© prime** : FurtivitĂ© et ECM dominent - **ECM/ECCM** : Guerre Ă©lectronique critique - **CompatibilitĂ© stricte** : AA anti-hĂ©licoptĂšre ne touche pas jets @@ -309,7 +437,7 @@ struct AirDefenses { // CapacitĂ©s bool has_eccm; // Electronic Counter-Counter-Measures int radar_quality; - std::map capabilities; // Quoi peut toucher quoi + std::map capabilities; }; enum TargetCapability { @@ -320,159 +448,69 @@ enum TargetCapability { }; ``` -#### CompatibilitĂ© SystĂšmes +### Effectiveness Air avec Stealth/ECM ```cpp -bool canEngageAircraft(AASystem aa, Aircraft aircraft) { - // VĂ©rifier compatibilitĂ© type - switch (aa.capability) { - case HELICOPTER_ONLY: - return aircraft.type == HELICOPTER; +float calculateAirDefenseEffectiveness(Aircraft aircraft, AASystem aa) { + // Base effectiveness selon pĂ©nĂ©tration radar vs stealth + float base_eff = calculateCounterEffectiveness(aa, aircraft); - case LOW_ALTITUDE: - return aircraft.altitude < 5000; // mĂštres - - case HIGH_ALTITUDE: - return aircraft.altitude > 5000; - - case ALL_AIRCRAFT: - return true; + // 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 } - // VĂ©rifier guerre Ă©lectronique + float ecm_reduction = 1.0f; if (aircraft.has_ecm && !aa.has_eccm) { - // ECM peut brouiller AA sans ECCM - float jam_probability = aircraft.ecm_power / (aa.radar_quality + 1); - if (randomFloat() < jam_probability) { - return false; // BrouillĂ© - } + ecm_reduction = 1.0f - (aircraft.ecm_power / (aa.radar_quality + 1)); } - // VĂ©rifier furtivitĂ© - if (aircraft.has_stealth) { - float detection_range = aa.radar_range * (1.0f - aircraft.stealth_rating); - if (distance(aa, aircraft) > detection_range) { - return false; // Pas dĂ©tectĂ© - } - } + // Effectiveness finale (baseline 20% toujours appliquĂ©) + float final_eff = max(0.20f, base_eff * stealth_reduction * ecm_reduction); - return true; + return final_eff; } ``` -#### Exemple Air : FurtivitĂ© Domine +### Exemple Air : FurtivitĂ© + ECM **Attaquant** : - 20 jets furtifs Gen4 (F-35) - - Stealth rating : 0.9 (rĂ©duit dĂ©tection 90%) - - ECM avancĂ© - - Combat value : 2000/jet + - stealth_rating : 0.90 (rĂ©duit dĂ©tection 90%) + - ecm_power : 8 + - combat_value : 2000/jet - Menace brute : 40 000 **DĂ©fenseur** : -- 100 000 AA missiles Gen2 - - Radar standard - - Pas ECCM - - Seulement 5% peuvent dĂ©tecter/engager les furtifs - - Shield value effectif : 100000 × 0.05 × 300 = 1 500 000... mais avec ECM : - - Shield value final : 1 500 000 × 0.1 (jam rate) = 150 000 +- 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 = 150000 / 40000 = ... wait, > 1.0 ! -→ PlafonnĂ© Ă  min(1.0, value) -defensive_effectiveness = min(1.0, 150000/40000) = 1.0... +defensive_effectiveness = min(1.0, 80000 / 40000) = 100% +residual_multiplier = 5% +final_threat = 40000 × 0.05 = 2 000 -ERREUR dans mon calcul ! +→ 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) ``` -**Correction** : Le shield value doit ĂȘtre calculĂ© par aircraft, pas globalement. - -```cpp -// Pour chaque jet -for (auto& jet : jets) { - float jet_value = jet.combat_value; - - // Combien de AA peuvent l'engager ? - int applicable_aa = 0; - for (auto& aa : aa_systems) { - if (canEngageAircraft(aa, jet)) { - applicable_aa++; - } - } - - // Shield value pour ce jet spĂ©cifique - float shield_value = applicable_aa * aa_combat_value; - float neutralization = min(1.0f, shield_value / jet_value); - - threat_reduced += jet_value * neutralization; -} -``` - -**RĂ©sultat corrigĂ©** : -- 5000 AA peuvent engager (sur 100k) -- Pour 1 jet : shield = 5000 × 300 = 1 500 000 vs jet = 2000 -- Neutralization = 100% par jet -- Mais ils peuvent pas tous tirer simultanĂ©ment ! - -**Contrainte simultanĂ©itĂ©** : - -```cpp -// Limite engagement simultanĂ© -int max_simultaneous = min(applicable_aa, ENGAGEMENT_LIMIT); -// Exemple : Max 100 missiles simultanĂ©s par cible - -float shield_value = max_simultaneous * aa_combat_value; -``` - -Avec limite 100 simultanĂ©s : -- Shield = 100 × 300 = 30 000 vs jet = 2000 -- Neutralization = 100% par jet -- Mais 20 jets → seulement 2000 engagements simultanĂ©s total -- Si AA rate coordination : menace reste - -**C'est complexe !** Donc en pratique : - -```cpp -float calculateAirDefenseEffectiveness( - std::vector aircraft, - std::vector aa_systems -) { - float total_threat = 0; - float neutralized = 0; - - for (auto& ac : aircraft) { - total_threat += ac.combat_value; - - // Compter AA applicables - int applicable_count = 0; - for (auto& aa : aa_systems) { - if (canEngageAircraft(aa, ac)) { - applicable_count++; - } - } - - // Engagement limitĂ© - int engaged = min(applicable_count, MAX_SIMULTANEOUS_PER_TARGET); - - // ProbabilitĂ© kill - float kill_probability = engaged / float(ENGAGEMENTS_NEEDED_FOR_KILL); - kill_probability = min(1.0f, kill_probability); - - neutralized += ac.combat_value * kill_probability; - } - - return total_threat > 0 ? (neutralized / total_threat) : 0.0f; -} -``` - -### Évaluation Domaine Naval +## É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. +Structure identique avec couples spĂ©cifiques (penetration vs armor pour missiles anti-navire). ## Évaluation Production @@ -520,33 +558,20 @@ int evaluateProduction(Entity attacker, Entity defender, int projection_months) - Production AT : 100 missiles/mois - Projection 12 mois : 1200 missiles - Combat value : 300/missile -- DĂ©fense production : 1200 × 300 = 360 000 +- Effectiveness moyenne : 40% +- DĂ©fense production : 1200 × 300 × 0.40 = 144 000 **Net production threat** : ``` Attacker gain : 240 000 -Defender gain : 360 000 -Net : 240 000 - 360 000 = -120 000 (nĂ©gatif = dĂ©fenseur gagne) +Defender gain : 144 000 +Net : 240 000 - 144 000 = 96 000 -production_threat = max(0, net) = 0 +production_threat = 96 000 + +→ État A a avantage production malgrĂ© dĂ©fenses ``` -→ État B a **meilleure production**, donc menace production de A est nulle. - -**Si inverse** : - -**État A** : -- Production : 200 tanks/mois → 2400 tanks/an -- Threat : 2400 × 400 = 960 000 - -**État B** : -- Production AT : 50 missiles/mois → 600 missiles/an -- DĂ©fense : 600 × 300 = 180 000 - -**Net** : 960 000 - 180 000 = 780 000 - -→ État A a **production Ă©crasante**, menace industrielle massive. - ## AgrĂ©gation Finale ### Formule ComplĂšte @@ -590,15 +615,15 @@ int calculateThreat(Entity attacker, Entity defender) { - **Total brut** : 9 700 000 **France dĂ©fenses** : -- AT systems : 3000 (Gen3) → Shield 50% tanks -- AA systems : 1500 (Gen3) → Shield 30% aircraft -- Naval defenses : 200 → Shield 40% naval +- 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 × 0.5 = 1 600 000 -- Air : 4 000 000 × 0.7 = 2 800 000 -- Naval : 2 500 000 × 0.6 = 1 500 000 -- **Current threat** : 5 900 000 +- 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 @@ -607,10 +632,10 @@ int calculateThreat(Entity attacker, Entity defender) { **Total (60% current, 40% prod)** : ``` -5 900 000 × 0.6 + 290 000 × 0.4 = 3 656 000 -``` +4 930 000 × 0.6 + 290 000 × 0.4 = 3 074 000 -→ **Menace colossale**, mais France peut tenir avec alliances +→ Menace colossale, mais France peut tenir avec alliances +``` #### PMC vs Company @@ -622,13 +647,17 @@ int calculateThreat(Entity attacker, Entity defender) { - **Total** : 50 000 **Rheinmetall dĂ©fenses** : -- Security : 100 guards +- Security : 100 guards (effectiveness 30%) - Fortifications : minimal -- **Shield** : 5% +- **Shield** : 15% -**Threat** : 50 000 × 0.95 = 47 500 +**Threat** : +``` +residual = max(0.05, 1.0 - 0.15) = 85% +final_threat = 50000 × 0.85 = 42 500 -→ PMC peut menacer installations Company, mais pas capacitĂ©s production +→ PMC peut menacer installations Company +``` ## Cas SpĂ©ciaux @@ -680,6 +709,66 @@ float getGeographicModifier(Entity attacker, Entity defender) { } ``` +## 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 @@ -732,6 +821,7 @@ public: - Perte unitĂ© au combat - Nouvelle recherche technologique - Changement doctrine militaire +- Retrofit/upgrade Ă©quipement ### Calcul Lazy @@ -748,5 +838,5 @@ int getThreatOnDemand(EntityId attacker, EntityId defender) { - `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 +- `systeme-militaire.md` : Valeurs combat Ă©quipements, gĂ©nĂ©rations, systĂšme conception modulaire - `economie-logistique.md` : Production rates, capacitĂ©s industrielles diff --git a/src/core/include/warfactory/ASerializable.h b/src/core/include/warfactory/ASerializable.h deleted file mode 100644 index c531e40..0000000 --- a/src/core/include/warfactory/ASerializable.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include - -using json = nlohmann::json; - -namespace warfactory { - -class SerializationRegistry; - -class ASerializable { -private: - std::string instance_id; - -public: - ASerializable(const std::string& id); - virtual ~ASerializable(); - - const std::string& getInstanceId() const { return instance_id; } - - virtual json serialize() const = 0; - virtual void deserialize(const json& data) = 0; - -protected: - void registerForSerialization(); - void unregisterFromSerialization(); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/DataTreeFactory.h b/src/core/include/warfactory/DataTreeFactory.h deleted file mode 100644 index ed08da7..0000000 --- a/src/core/include/warfactory/DataTreeFactory.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include -#include -#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 create(const std::string& type, const std::string& sourcePath); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/ICoordinationModule.h b/src/core/include/warfactory/ICoordinationModule.h deleted file mode 100644 index 0967fa6..0000000 --- a/src/core/include/warfactory/ICoordinationModule.h +++ /dev/null @@ -1,161 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include "IModule.h" -#include "IDataTree.h" - -// Forward declarations -namespace warfactory { - class IEngine; - class IModuleSystem; -} - -namespace warfactory { - -/** - * @brief Global system orchestrator - First launched, last shutdown - * - * The CoordinationModule is the main system orchestrator that manages the entire - * game system lifecycle, module deployment topology, and configuration synchronization. - * - * ARCHITECTURE FLOW: - * 1. MainServer launches CoordinationModule (first module) - * 2. CoordinationModule loads gameconfig.json via IDataTree - * 3. Parses deployment section to determine module topology - * 4. Deploys modules to local IEngine or remote servers - * 5. Synchronizes configuration across all deployed modules - * 6. Coordinates shutdown (last module to close) - * - * DESIGN DECISIONS: - * - No state persistence: behavior driven entirely by gameconfig.json - * - No network protocol: all communication via IIO abstraction - * - No security for now: local/trusted environment assumed - * - Module deployment via IModuleSystem delegation - * - Configuration immutability via const IDataNode references - */ -class ICoordinationModule : public IModule { -public: - virtual ~ICoordinationModule() = default; - - // ======================================== - // GAME LIFECYCLE MANAGEMENT - // ======================================== - - /** - * @brief Start new game session with configuration - * @param gameConfigPath Path to gameconfig.json file - * - * Complete startup sequence: - * 1. Load and parse gameconfig.json via IDataTree - * 2. Initialize local IEngine and IModuleSystem - * 3. Parse deployment topology from config - * 4. Deploy local modules (target: "local") - * 5. Launch remote servers and deploy remote modules - * 6. Synchronize all configurations - * 7. Return when system is ready - */ - virtual void startNewGame(const std::string& gameConfigPath) = 0; - - /** - * @brief Load existing game from save file - * @param savePath Path to save file - */ - virtual void loadGame(const std::string& savePath) = 0; - - /** - * @brief Shutdown entire game system gracefully - * - * Coordinates graceful shutdown: - * 1. Signal all modules to save state - * 2. Undeploy remote modules first - * 3. Undeploy local modules - * 4. Shutdown remote servers - * 5. Shutdown local IEngine - * 6. CoordinationModule shuts down last - */ - virtual void shutdownGame() = 0; - - // ======================================== - // MODULE DEPLOYMENT TOPOLOGY - // ======================================== - - /** - * @brief Deploy module according to gameconfig.json specification - * @param moduleInstanceId Module instance ID as defined in config - * - * Deployment process: - * 1. Read module config from gameconfig.json deployment section - * 2. Determine target: "local" vs "server:IP" vs "cluster:name" - * 3. Get module-specific configuration from modules section - * 4. For local: delegate to local IEngine->IModuleSystem - * 5. For remote: send deployment command to remote server - * 6. Pass const IDataNode& configuration to module - */ - virtual void deployModule(const std::string& moduleInstanceId) = 0; - - /** - * @brief Stop and undeploy module instance - * @param moduleInstanceId Module instance ID to undeploy - */ - virtual void undeployModule(const std::string& moduleInstanceId) = 0; - - /** - * @brief Get list of currently deployed module instances - * @return Vector of module instance IDs currently running - */ - virtual std::vector getDeployedModules() = 0; - - // ======================================== - // CONFIGURATION SYNCHRONIZATION - // ======================================== - - /** - * @brief Synchronize configuration changes to all deployed modules - * - * Process: - * 1. Reload gameconfig.json via IDataTree hot-reload - * 2. For each deployed module, get updated configuration - * 3. Call module->setConfiguration() with new const IDataNode& - * 4. Handle any modules that fail to reconfigure - */ - virtual void syncConfiguration() = 0; - - /** - * @brief Set configuration tree for the coordination system - * @param configTree Configuration data tree loaded from gameconfig.json - */ - virtual void setConfigurationTree(std::unique_ptr configTree) = 0; - - /** - * @brief Get current configuration tree - * @return Configuration tree pointer for accessing gameconfig.json data - */ - virtual IDataTree* getConfigurationTree() = 0; - - // ======================================== - // SYSTEM HEALTH AND MANAGEMENT - // ======================================== - - /** - * @brief Check if all deployed modules are healthy and responsive - * @return true if system is healthy, false if issues detected - * - * Aggregates health status from all deployed modules: - * - Calls getHealthStatus() on each module - * - Checks network connectivity to remote servers - * - Validates configuration consistency - * - Could trigger auto-save in future versions - */ - virtual bool isSystemHealthy() = 0; - - /** - * @brief Get detailed system health report - * @return JSON health report aggregating all module health status - */ - virtual json getSystemHealthReport() = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IDataNode.h b/src/core/include/warfactory/IDataNode.h deleted file mode 100644 index 1f1df78..0000000 --- a/src/core/include/warfactory/IDataNode.h +++ /dev/null @@ -1,233 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -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 getChild(const std::string& name) = 0; - - /** - * @brief Get names of all direct children - * @return Vector of child names - */ - virtual std::vector 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 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 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() > 150; - * }); - */ - virtual std::vector queryByProperty(const std::string& propName, - const std::function& 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() const = 0; - - /** - * @brief Check if this node has data - * @return true if data exists - */ - virtual bool hasData() const = 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 = "") const = 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) const = 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) const = 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) const = 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) const = 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() const = 0; - - /** - * @brief Get this node's name - * @return Node name - */ - virtual std::string getName() const = 0; - - /** - * @brief Get node type (extensible for templates/inheritance later) - * @return Node type identifier - */ - virtual std::string getNodeType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IDataTree.h b/src/core/include/warfactory/IDataTree.h deleted file mode 100644 index cb3548a..0000000 --- a/src/core/include/warfactory/IDataTree.h +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include -#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 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 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 callback) = 0; - - // ======================================== - // METADATA - // ======================================== - - /** - * @brief Get tree implementation type - * @return Type identifier (e.g., "JSONDataTree", "DatabaseDataTree") - */ - virtual std::string getType() = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IEngine.h b/src/core/include/warfactory/IEngine.h deleted file mode 100644 index 9f1a236..0000000 --- a/src/core/include/warfactory/IEngine.h +++ /dev/null @@ -1,125 +0,0 @@ -#pragma once - -#include -#include -#include - -// Forward declarations to avoid circular dependencies -namespace warfactory { - class IModuleSystem; -} - -using json = nlohmann::json; - -namespace warfactory { - -enum class EngineType { - DEBUG = 0, - PRODUCTION = 1, - HIGH_PERFORMANCE = 2 -}; - -/** - * @brief Engine orchestration interface - coordinates the entire system - * - * The engine is responsible for: - * - System initialization and lifecycle management - * - Main game loop coordination with delta time updates - * - Module system orchestration - * - IIO health monitoring and backpressure management - * - * IMPORTANT: Engine implementations must periodically check IIO health: - * - Monitor IOHealth.queueSize vs maxQueueSize (warn at 80% full) - * - Track IOHealth.dropping status (critical - consider module restart) - * - Log IOHealth.droppedMessageCount for debugging - * - Monitor IOHealth.averageProcessingRate for performance analysis - * - * Evolution path: - * - DebugEngine: Development/testing with step-by-step execution - * - HighPerfEngine: Production optimized with threading - * - DataOrientedEngine: Massive scale with SIMD and clustering - */ -class IEngine { -public: - virtual ~IEngine() = default; - - /** - * @brief Initialize engine systems - * - * Sets up the engine with basic configuration. - * Module system and other components are set separately. - */ - virtual void initialize() = 0; - - /** - * @brief Start main game loop - * - * Blocks until shutdown() called. Engine owns the main loop and handles: - * - Frame timing and delta time calculation - * - Module system coordination - * - Performance management and frame rate control - */ - virtual void run() = 0; - - /** - * @brief Process single frame/tick (for debugging) - * @param deltaTime Time elapsed since last update in seconds - * - * For step debugging and testing. Processes one iteration - * without entering the main loop. - */ - virtual void step(float deltaTime) = 0; - - /** - * @brief Shutdown engine and cleanup all resources - * - * Ensures proper cleanup of all systems in correct order. - * Should be safe to call multiple times. Stops run() loop. - */ - virtual void shutdown() = 0; - - /** - * @brief Load modules from configuration - * @param configPath Path to module configuration file - * - * Engine automatically: - * - Loads modules from .so/.dll files - * - Creates appropriate ModuleSystem for each module (performance strategy) - * - Configures execution frequency and coordination - * - * Config format: - * { - * "modules": [ - * {"path": "tank.so", "strategy": "threaded", "frequency": "60hz"}, - * {"path": "economy.so", "strategy": "sequential", "frequency": "0.1hz"} - * ] - * } - */ - virtual void loadModules(const std::string& configPath) = 0; - - /** - * @brief Register main coordinator socket - * @param coordinatorSocket Socket for system coordination communication - * - * Engine uses this socket for high-level system coordination, - * health monitoring, and administrative commands. - */ - virtual void registerMainSocket(std::unique_ptr coordinatorSocket) = 0; - - /** - * @brief Register new client/player socket - * @param clientSocket Socket for player communication - * - * Engine manages player connections as a priority channel. - * Players are the most important external connections. - */ - virtual void registerNewClientSocket(std::unique_ptr clientSocket) = 0; - - /** - * @brief Get engine type identifier - * @return Engine type enum value for identification - */ - virtual EngineType getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IIO.h b/src/core/include/warfactory/IIO.h deleted file mode 100644 index 0f3edae..0000000 --- a/src/core/include/warfactory/IIO.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -using json = nlohmann::json; - -namespace warfactory { - -enum class IOType { - INTRA = 0, // Same process - LOCAL = 1, // Same machine - NETWORK = 2 // TCP/WebSocket -}; - -struct SubscriptionConfig { - bool replaceable = false; // Replace vs accumulate for low-freq - int batchInterval = 30000; // ms for low-freq batching - int maxBatchSize = 100; // Max messages per batch - bool compress = false; // Compress batched data -}; - -struct Message { - std::string topic; - json data; - uint64_t timestamp; -}; - -struct IOHealth { - int queueSize; - int maxQueueSize; - bool dropping = false; // Started dropping messages? - float averageProcessingRate; // Messages/second processed by module - int droppedMessageCount = 0; // Total dropped since last check -}; - -/** - * @brief Pub/Sub communication interface with pull-based synchronous design - * - * Pull-based pub/sub system optimized for game modules. Modules have full control - * over when they process messages, avoiding threading issues. - * - * Features: - * - Topic patterns with wildcards (e.g., "player:*", "economy:*") - * - Low-frequency subscriptions for bandwidth optimization - * - Message consumption (pull removes message from queue) - * - Engine health monitoring for backpressure management - */ -class IIO { -public: - virtual ~IIO() = default; - - /** - * @brief Publish message to a topic - * @param topic Topic name (e.g., "player:123", "economy:prices") - * @param message JSON message data - */ - virtual void publish(const std::string& topic, const json& message) = 0; - - /** - * @brief Subscribe to topic pattern (high-frequency) - * @param topicPattern Topic pattern with wildcards (e.g., "player:*") - * @param config Optional subscription configuration - */ - virtual void subscribe(const std::string& topicPattern, const SubscriptionConfig& config = {}) = 0; - - /** - * @brief Subscribe to topic pattern (low-frequency batched) - * @param topicPattern Topic pattern with wildcards - * @param config Subscription configuration (batchInterval, etc.) - */ - virtual void subscribeLowFreq(const std::string& topicPattern, const SubscriptionConfig& config = {}) = 0; - - /** - * @brief Get count of pending messages - * @return Number of messages waiting to be pulled - */ - virtual int hasMessages() const = 0; - - /** - * @brief Pull and consume one message - * @return Message from queue (oldest first). Message is removed from queue. - * @throws std::runtime_error if no messages available - */ - virtual Message pullMessage() = 0; - - /** - * @brief Get IO health status for Engine monitoring - * @return Health metrics including queue size, drop status, processing rate - */ - virtual IOHealth getHealth() const = 0; - - /** - * @brief Get IO type identifier - * @return IO type enum value for identification - */ - virtual IOType getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IModule.h b/src/core/include/warfactory/IModule.h deleted file mode 100644 index e5f600c..0000000 --- a/src/core/include/warfactory/IModule.h +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include -#include -#include "IDataNode.h" -#include "ITaskScheduler.h" - -// Forward declarations -namespace warfactory { - class IIO; -} - -using json = nlohmann::json; - -namespace warfactory { - - - -/** - * @brief Pure business logic interface - optimized for Claude Code development - * - * This interface defines the contract for all game modules. Each module contains - * 200-300 lines of pure game logic with zero infrastructure code. - * - * Key design principles: - * - PURE FUNCTION: process() method has no side effects beyond return value - * - CONFIG VIA DATATREE: Configuration via immutable IDataNode references - * - JSON ONLY: All communication via JSON input/output - * - NO INFRASTRUCTURE: No threading, networking, or framework dependencies - * - HOT-RELOAD READY: State serialization for seamless module replacement - * - CLAUDE OPTIMIZED: Micro-context size for AI development efficiency - * - * BREAKING CHANGES: - * - Removed initialize() method - use setConfiguration() instead - * - Configuration via const IDataNode& for immutability - * - Health check returns detailed JSON status - * - * Module constraint: Maximum 300 lines per module (Exception: ProductionModule 500-800 lines) - */ -class IModule { -public: - virtual ~IModule() = default; - - /** - * @brief Process game logic - * @param input JSON input from other modules or the module system - * - * This is the core method where all module logic is implemented. - * Modules communicate via IIO pub/sub and can delegate tasks via ITaskScheduler. - * Must handle state properly through getState/setState for hot-reload. - */ - virtual void process(const json& input) = 0; - - /** - * @brief Set module configuration (replaces initialize) - * @param configNode Configuration node (immutable reference) - * @param io Pub/sub communication interface for messaging - * @param scheduler Task scheduling interface for delegating work - * - * Called when the module is loaded or configuration changes. - * Should setup internal state, validate configuration, and store service references. - */ - virtual void setConfiguration(const IDataNode& configNode, IIO* io, ITaskScheduler* scheduler) = 0; - - /** - * @brief Get current module configuration - * @return Configuration node reference - */ - virtual const IDataNode& getConfiguration() = 0; - - /** - * @brief Get detailed health status of the module - * @return JSON health report with status, metrics, and diagnostics - */ - virtual json getHealthStatus() = 0; - - /** - * @brief Cleanup and shutdown the module - * - * Called when the module is being unloaded. Should clean up any - * resources and prepare for safe destruction. - */ - virtual void shutdown() = 0; - - /** - * @brief Get current module state for hot-reload support - * @return JSON representation of all module state - * - * Critical for hot-reload functionality. Must serialize all internal - * state that needs to be preserved when the module is replaced. - * The returned JSON should be sufficient to restore the module to - * its current state via setState(). - */ - virtual json getState() = 0; - - /** - * @brief Restore module state after hot-reload - * @param state JSON state previously returned by getState() - * - * Called after module replacement to restore the previous state. - * Must be able to reconstruct all internal state from the JSON - * to ensure seamless hot-reload without game disruption. - */ - virtual void setState(const json& state) = 0; - - /** - * @brief Get module type identifier - * @return Module type as string (e.g., "tank", "economy", "production") - */ - virtual std::string getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IModuleSystem.h b/src/core/include/warfactory/IModuleSystem.h deleted file mode 100644 index e618912..0000000 --- a/src/core/include/warfactory/IModuleSystem.h +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include -#include -#include -#include "ITaskScheduler.h" - -// Forward declarations to avoid circular dependencies -namespace warfactory { - class IModule; - class IIO; -} - -using json = nlohmann::json; - -namespace warfactory { - -enum class ModuleSystemType { - SEQUENTIAL = 0, - THREADED = 1, - THREAD_POOL = 2, - CLUSTER = 3 -}; - - -/** - * @brief Module execution strategy interface - swappable performance architecture - * - * The module system manages module lifecycle and execution strategy. - * Different implementations provide different performance characteristics: - * - * - SequentialModuleSystem: Debug/test mode, processes modules one at a time - * - ThreadedModuleSystem: Each module in its own thread - * - MultithreadedModuleSystem: Module tasks distributed across thread pool - * - ClusterModuleSystem: Modules distributed across multiple machines - * - * This enables progressive evolution from debug to production to MMO scale - * without changing any module business logic code. - * - * Inherits from ITaskScheduler to provide task delegation capabilities. - */ -class IModuleSystem : public ITaskScheduler { -public: - virtual ~IModuleSystem() = default; - - /** - * @brief Register a module with the system - * @param name Unique identifier for the module - * @param module Module implementation (unique ownership) - * - * The module system takes ownership of the module and manages its lifecycle. - * Modules can be registered at any time and will participate in the next - * processing cycle. - */ - virtual void registerModule(const std::string& name, std::unique_ptr module) = 0; - - /** - * @brief Process all registered modules - * @param deltaTime Time elapsed since last processing cycle in seconds - * - * This is the core execution method that coordinates all modules according - * to the implemented strategy. Each module's process() method will be called - * with appropriate timing and coordination. - */ - virtual void processModules(float deltaTime) = 0; - - /** - * @brief Set the IO layer for inter-module communication - * @param ioLayer Communication transport implementation (unique ownership) - * - * The module system takes ownership of the IO layer and uses it to - * facilitate communication between modules. - */ - virtual void setIOLayer(std::unique_ptr ioLayer) = 0; - - /** - * @brief Query a specific module directly - * @param name Name of the module to query - * @param input JSON input to send to the module - * @return JSON response from the module - * - * This provides direct access to module functionality for debugging, - * testing, or administrative purposes. The query bypasses normal - * execution flow and calls the module's process() method directly. - */ - virtual json queryModule(const std::string& name, const json& input) = 0; - - /** - * @brief Get module system type identifier - * @return Module system type enum value for identification - */ - virtual ModuleSystemType getType() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IRegion.h b/src/core/include/warfactory/IRegion.h deleted file mode 100644 index 7a6f8f4..0000000 --- a/src/core/include/warfactory/IRegion.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include - -namespace warfactory { - -/** - * @brief Interface for geological regions during world generation - * - * Represents discrete regions with specific properties like resource deposits, - * volcanic activity, or tectonic formations. - */ -class IRegion { -public: - virtual ~IRegion() = default; - - // ======================================== - // IDENTIFICATION - // ======================================== - - virtual int getId() const = 0; - virtual const std::string& getType() const = 0; - - // ======================================== - // POSITION & SIZE - // ======================================== - - virtual float getX() const = 0; - virtual float getY() const = 0; - virtual float getRadius() const = 0; - virtual float getMass() const = 0; - - // ======================================== - // LIFECYCLE - // ======================================== - - virtual void update(float delta_time) = 0; - virtual bool isActive() const = 0; - - // ======================================== - // PROPERTIES - // ======================================== - - virtual float getIntensity() const = 0; - virtual void setIntensity(float intensity) = 0; - - virtual bool canFuseWith(const IRegion* other) const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/ISerializable.h b/src/core/include/warfactory/ISerializable.h deleted file mode 100644 index d66739d..0000000 --- a/src/core/include/warfactory/ISerializable.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -using json = nlohmann::json; - -namespace warfactory { - -class ISerializable { -public: - virtual ~ISerializable() = default; - - virtual json serialize() const = 0; - virtual void deserialize(const json& data) = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/ITaskScheduler.h b/src/core/include/warfactory/ITaskScheduler.h deleted file mode 100644 index d92aa7b..0000000 --- a/src/core/include/warfactory/ITaskScheduler.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include -#include - -using json = nlohmann::json; - -namespace warfactory { - -/** - * @brief Task scheduling interface for module delegation to execution system - * - * ITaskScheduler allows modules to delegate computationally expensive or - * time-consuming tasks to the underlying execution system without knowing - * the implementation details (sequential, threaded, thread pool, cluster). - * - * CORE PURPOSE: - * - Modules stay lightweight (200-300 lines) by delegating heavy work - * - Execution strategy determined by IModuleSystem implementation - * - Modules remain thread-agnostic and infrastructure-free - * - * USAGE PATTERNS: - * - ProductionModule: Delegate belt pathfinding calculations - * - TankModule: Delegate A* pathfinding for unit movement - * - EconomyModule: Delegate market analysis and price calculations - * - FactoryModule: Delegate assembly line optimization - * - * EXECUTION STRATEGIES: - * - SequentialModuleSystem: Tasks executed immediately in same thread - * - ThreadedModuleSystem: Tasks executed in dedicated module thread - * - MultithreadedModuleSystem: Tasks distributed across thread pool - * - ClusterModuleSystem: Tasks distributed across remote workers - * - * PERFORMANCE BENEFIT: - * - Modules process() methods stay fast (< 1ms for 60Hz modules) - * - Heavy computation moved to background without blocking game loop - * - Automatic scaling based on IModuleSystem implementation - */ -class ITaskScheduler { -public: - virtual ~ITaskScheduler() = default; - - /** - * @brief Schedule a task for execution - * @param taskType Type of task (e.g., "pathfinding", "market_analysis", "belt_optimization") - * @param taskData JSON data for the task - * - * Example usage: - * ```cpp - * // TankModule delegates pathfinding - * scheduler->scheduleTask("pathfinding", { - * {"start", {x: 100, y: 200}}, - * {"target", {x: 500, y: 600}}, - * {"unit_id", "tank_001"} - * }); - * - * // ProductionModule delegates belt calculation - * scheduler->scheduleTask("belt_optimization", { - * {"factory_id", "main_base"}, - * {"item_type", "iron_plate"}, - * {"throughput_target", 240} - * }); - * ``` - */ - virtual void scheduleTask(const std::string& taskType, const json& taskData) = 0; - - /** - * @brief Check if completed tasks are available - * @return Number of completed tasks ready to be pulled - * - * Modules should check this before calling getCompletedTask() - * to avoid blocking or polling unnecessarily. - */ - virtual int hasCompletedTasks() const = 0; - - /** - * @brief Pull and consume one completed task - * @return Task result JSON. Task is removed from completed queue. - * - * Example results: - * ```cpp - * // Pathfinding result - * { - * "task_type": "pathfinding", - * "unit_id": "tank_001", - * "path": [{"x": 100, "y": 200}, {"x": 150, "y": 250}, ...], - * "cost": 42.5 - * } - * - * // Belt optimization result - * { - * "task_type": "belt_optimization", - * "factory_id": "main_base", - * "optimal_layout": [...], - * "efficiency_gain": 0.15 - * } - * ``` - */ - virtual json getCompletedTask() = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/IUI.h b/src/core/include/warfactory/IUI.h deleted file mode 100644 index b9a30af..0000000 --- a/src/core/include/warfactory/IUI.h +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once - -#include -#include -#include - -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 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 \ No newline at end of file diff --git a/src/core/include/warfactory/IUI_Enums.h b/src/core/include/warfactory/IUI_Enums.h deleted file mode 100644 index 78b76fa..0000000 --- a/src/core/include/warfactory/IUI_Enums.h +++ /dev/null @@ -1,340 +0,0 @@ -#pragma once - -#include -#include -#include - -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 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 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 \ No newline at end of file diff --git a/src/core/include/warfactory/ImGuiUI.h b/src/core/include/warfactory/ImGuiUI.h deleted file mode 100644 index dbb2524..0000000 --- a/src/core/include/warfactory/ImGuiUI.h +++ /dev/null @@ -1,707 +0,0 @@ -#pragma once - -#include "IUI_Enums.h" -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -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 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 child_windows; - }; - - std::map docks; - - // ======================================== - // CALLBACKS - // ======================================== - - std::map> request_callbacks; - std::map> custom_request_callbacks; - - // ======================================== - // MESSAGE SYSTEM - // ======================================== - - struct LogMessage { - EventLevel level; - std::string message; - std::chrono::steady_clock::time_point timestamp; - }; - - std::vector 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(screen_size.x), - static_cast(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(fb_width), static_cast(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(screen_size.x), static_cast(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(); - } - - if (size_value.is_string()) { - std::string size_str = size_value.get(); - 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(); - 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(); - } 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(); - 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(); - } 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(); - 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 callback) override; - void onRequestCustom(const std::string& customType, std::function 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 \ No newline at end of file diff --git a/src/core/include/warfactory/RandomGenerator.h b/src/core/include/warfactory/RandomGenerator.h deleted file mode 100644 index 8d62bb5..0000000 --- a/src/core/include/warfactory/RandomGenerator.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once - -#include -#include - -namespace warfactory { - -/** - * @brief Centralized random number generator singleton - * - * Provides consistent, seedable random number generation across all modules. - * Ensures reproducibility for testing and debugging while maintaining - * high-quality random distribution. - */ -class RandomGenerator { -private: - std::mt19937 gen; - - RandomGenerator() : gen(std::random_device{}()) {} - -public: - // Singleton access - static RandomGenerator& getInstance() { - static RandomGenerator instance; - return instance; - } - - // Delete copy/move constructors and operators - RandomGenerator(const RandomGenerator&) = delete; - RandomGenerator& operator=(const RandomGenerator&) = delete; - RandomGenerator(RandomGenerator&&) = delete; - RandomGenerator& operator=(RandomGenerator&&) = delete; - - /** - * @brief Seed the random generator for reproducible sequences - * @param seed Seed value (use same seed for identical results) - */ - void seed(uint32_t seed) { - gen.seed(seed); - } - - /** - * @brief Generate uniform float in range [min, max] - */ - float uniform(float min, float max) { - std::uniform_real_distribution dis(min, max); - return dis(gen); - } - - /** - * @brief Generate uniform int in range [min, max] (inclusive) - */ - int uniformInt(int min, int max) { - std::uniform_int_distribution dis(min, max); - return dis(gen); - } - - /** - * @brief Generate normal distribution float - */ - float normal(float mean, float stddev) { - std::normal_distribution dis(mean, stddev); - return dis(gen); - } - - /** - * @brief Generate uniform float in range [0.0, 1.0] - */ - float unit() { - return uniform(0.0f, 1.0f); - } - - /** - * @brief Generate boolean with given probability - * @param probability Probability of returning true [0.0, 1.0] - */ - bool boolean(float probability = 0.5f) { - return unit() < probability; - } - - /** - * @brief Direct access to underlying generator for custom distributions - */ - std::mt19937& getGenerator() { - return gen; - } -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/Resource.h b/src/core/include/warfactory/Resource.h deleted file mode 100644 index 7ffcc8e..0000000 --- a/src/core/include/warfactory/Resource.h +++ /dev/null @@ -1,37 +0,0 @@ -#pragma once - -#include -#include - -using json = nlohmann::json; - -namespace warfactory { - -class Resource { -private: - std::string resource_id; - std::string name; - std::string category; - std::string logistic_category; - float density; - int stack_size; - std::string container_type; - json ui_data; - -public: - Resource() = default; - Resource(const json& resource_data); - - const std::string& getResourceId() const { return resource_id; } - const std::string& getName() const { return name; } - const std::string& getCategory() const { return category; } - const std::string& getLogisticCategory() const { return logistic_category; } - float getDensity() const { return density; } - int getStackSize() const { return stack_size; } - const std::string& getContainerType() const { return container_type; } - const json& getUIData() const { return ui_data; } - - static Resource loadFromJson(const std::string& resource_id, const json& resource_data); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/ResourceRegistry.h b/src/core/include/warfactory/ResourceRegistry.h deleted file mode 100644 index f1fb853..0000000 --- a/src/core/include/warfactory/ResourceRegistry.h +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include "Resource.h" -#include -#include -#include -#include - -namespace warfactory { - -/** - * @brief Singleton registry for all game resources with fast uint32_t ID lookup - * - * Centralizes resource management with O(1) access by numeric ID. - * Resources are loaded once at startup and accessed by ID throughout the game. - */ -class ResourceRegistry { -private: - static std::unique_ptr instance; - static bool initialized; - - std::vector resources; // Indexed by ID (resources[id]) - std::unordered_map name_to_id; // String -> ID mapping (init only) - uint32_t next_id = 1; // Start at 1 (0 = invalid/null resource) - - ResourceRegistry() = default; - -public: - // Singleton access - static ResourceRegistry& getInstance(); - static void initialize(); - static void shutdown(); - - // ======================================== - // REGISTRATION (Initialization Phase) - // ======================================== - - /** - * @brief Register a resource and get its assigned ID - * @param resource The resource to register - * @return The assigned uint32_t ID for this resource - */ - uint32_t registerResource(const Resource& resource); - - /** - * @brief Load resources from JSON configuration - * @param resources_json JSON object containing all resources - */ - void loadResourcesFromJson(const json& resources_json); - - // ======================================== - // RUNTIME ACCESS (Performance Critical) - // ======================================== - - /** - * @brief Get resource by ID (O(1) access) - * @param id The resource ID - * @return Pointer to resource or nullptr if not found - */ - const Resource* getResource(uint32_t id) const; - - /** - * @brief Get resource ID by name (use sparingly - prefer caching IDs) - * @param name The resource name/identifier - * @return The resource ID or 0 if not found - */ - uint32_t getResourceId(const std::string& name) const; - - /** - * @brief Check if resource ID is valid - */ - bool isValidResourceId(uint32_t id) const; - - // ======================================== - // BULK OPERATIONS - // ======================================== - - /** - * @brief Get all registered resource IDs - */ - std::vector getAllResourceIds() const; - - /** - * @brief Get total number of registered resources - */ - size_t getResourceCount() const; - - /** - * @brief Clear all registered resources (testing/reset) - */ - void clear(); - - // ======================================== - // CONVENIENCE CONSTANTS - // ======================================== - - static constexpr uint32_t INVALID_RESOURCE_ID = 0; - static constexpr uint32_t MAX_RESOURCES = 1000000; // 1M resources max - - // Prevent copy/assignment - ResourceRegistry(const ResourceRegistry&) = delete; - ResourceRegistry& operator=(const ResourceRegistry&) = delete; -}; - -// ======================================== -// CONVENIENCE MACROS FOR PERFORMANCE -// ======================================== - -#define RESOURCE_ID(name) warfactory::ResourceRegistry::getInstance().getResourceId(name) -#define GET_RESOURCE(id) warfactory::ResourceRegistry::getInstance().getResource(id) -#define VALID_RESOURCE(id) warfactory::ResourceRegistry::getInstance().isValidResourceId(id) - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/include/warfactory/SerializationRegistry.h b/src/core/include/warfactory/SerializationRegistry.h deleted file mode 100644 index fdd7eb6..0000000 --- a/src/core/include/warfactory/SerializationRegistry.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -using json = nlohmann::json; - -namespace warfactory { - -class ASerializable; - -class SerializationRegistry { -private: - std::unordered_map registered_objects; - - SerializationRegistry() = default; - -public: - static SerializationRegistry& getInstance(); - - void registerObject(const std::string& instance_id, ASerializable* object); - void unregisterObject(const std::string& instance_id); - - json serializeAll() const; - void deserializeAll(const json& data); - - json serializeObject(const std::string& instance_id) const; - void deserializeObject(const std::string& instance_id, const json& data); - - size_t getRegisteredCount() const { return registered_objects.size(); } - std::vector getRegisteredIds() const; - - void clear(); -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/core/src/ImGuiUI.cpp b/src/core/src/ImGuiUI.cpp deleted file mode 100644 index 7fd2715..0000000 --- a/src/core/src/ImGuiUI.cpp +++ /dev/null @@ -1,546 +0,0 @@ -#include "warfactory/ImGuiUI.h" -#include -#include -#include - -namespace warfactory { - -// ======================================== -// IUI INTERFACE IMPLEMENTATION - REQUESTS & EVENTS -// ======================================== - -void ImGuiUI::onRequest(RequestType requestType, std::function callback) { - request_callbacks[requestType] = callback; -} - -void ImGuiUI::onRequestCustom(const std::string& customType, std::function 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()); - } 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().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().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(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 \ No newline at end of file diff --git a/src/core/src/ResourceRegistry.cpp b/src/core/src/ResourceRegistry.cpp deleted file mode 100644 index 5331e52..0000000 --- a/src/core/src/ResourceRegistry.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include "warfactory/ResourceRegistry.h" -#include - -namespace warfactory { - -// Static member initialization -std::unique_ptr ResourceRegistry::instance = nullptr; -bool ResourceRegistry::initialized = false; - -ResourceRegistry& ResourceRegistry::getInstance() { - if (!initialized) { - initialize(); - } - return *instance; -} - -void ResourceRegistry::initialize() { - if (!initialized) { - instance = std::unique_ptr(new ResourceRegistry()); - initialized = true; - } -} - -void ResourceRegistry::shutdown() { - if (initialized) { - instance.reset(); - initialized = false; - } -} - -// ======================================== -// REGISTRATION (Initialization Phase) -// ======================================== - -uint32_t ResourceRegistry::registerResource(const Resource& resource) { - if (next_id >= MAX_RESOURCES) { - // Handle overflow - could throw or return INVALID_RESOURCE_ID - return INVALID_RESOURCE_ID; - } - - const uint32_t assigned_id = next_id++; - - // Ensure vector is large enough - if (resources.size() <= assigned_id) { - resources.resize(assigned_id + 1); - } - - // Store resource at index = ID - resources[assigned_id] = resource; - - // Map name to ID for lookup - name_to_id[resource.getResourceId()] = assigned_id; - - return assigned_id; -} - -void ResourceRegistry::loadResourcesFromJson(const json& resources_json) { - for (json::const_iterator it = resources_json.begin(); it != resources_json.end(); ++it) { - const std::string& resource_name = it.key(); - const json& resource_data = it.value(); - - // Create resource from JSON - Resource resource = Resource::loadFromJson(resource_name, resource_data); - - // Register it - const uint32_t resource_id = registerResource(resource); - - // Log or handle registration result if needed - (void)resource_id; // Suppress unused variable warning - } -} - -// ======================================== -// RUNTIME ACCESS (Performance Critical) -// ======================================== - -const Resource* ResourceRegistry::getResource(uint32_t id) const { - if (id == INVALID_RESOURCE_ID || id >= resources.size()) { - return nullptr; - } - return &resources[id]; -} - -uint32_t ResourceRegistry::getResourceId(const std::string& name) const { - const std::unordered_map::const_iterator it = name_to_id.find(name); - return (it != name_to_id.end()) ? it->second : INVALID_RESOURCE_ID; -} - -bool ResourceRegistry::isValidResourceId(uint32_t id) const { - return id != INVALID_RESOURCE_ID && id < resources.size(); -} - -// ======================================== -// BULK OPERATIONS -// ======================================== - -std::vector ResourceRegistry::getAllResourceIds() const { - std::vector ids; - ids.reserve(next_id - 1); // -1 because we start at 1 - - for (uint32_t id = 1; id < next_id; ++id) { - if (id < resources.size()) { - ids.push_back(id); - } - } - - return ids; -} - -size_t ResourceRegistry::getResourceCount() const { - return next_id - 1; // -1 because we start at 1 -} - -void ResourceRegistry::clear() { - resources.clear(); - name_to_id.clear(); - next_id = 1; -} - -} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/CLAUDE.md b/src/modules/world-generation-realist/CLAUDE.md index 08db149..7ede207 100644 --- a/src/modules/world-generation-realist/CLAUDE.md +++ b/src/modules/world-generation-realist/CLAUDE.md @@ -1,50 +1,54 @@ # World Generation Realist Module -**ResponsabilitĂ©**: GĂ©nĂ©ration procĂ©durale gĂ©ologiquement rĂ©aliste avec architecture Phase/Step. +**ResponsabilitĂ©**: GĂ©nĂ©ration procĂ©durale gĂ©ologiquement rĂ©aliste avec architecture Phase/Function simplifiĂ©e. ## Description -Ce module implĂ©mente un systĂšme de gĂ©nĂ©ration procĂ©durale basĂ© sur une architecture Phase/Step modulaire. Conçu pour implĂ©menter le systĂšme 8-phases dĂ©fini dans `gameData/WorldGeneration/Regular_world.json` avec Phase 0 d'initialisation. +Ce module implĂ©mente un systĂšme de gĂ©nĂ©ration procĂ©durale basĂ© sur une architecture Phase/Function en 2 couches. Conçu pour implĂ©menter le systĂšme 8-phases dĂ©fini dans `gameData/WorldGeneration/Regular_world.json` avec Phase 0 d'initialisation. -## Architecture +## Architecture HiĂ©rarchique (SIMPLIFIÉE) -### Interfaces Core -- **IWorldGenerationFunction**: Interface unique pour toutes les fonctions de gĂ©nĂ©ration -- **WorldGenerationFunctionFactory**: Factory pour crĂ©er les fonctions par nom -- **WorldGenerationOrchestrator**: Orchestrateur principal des phases +``` +WorldGenerationOrchestrator + └── IWorldGenerationPhase (conteneur logique - ex: "Planetary Accretion") + └── IWorldGenerationFunction[] (implĂ©mentations concrĂštes) +``` -### SystĂšmes ImplĂ©mentĂ©s +**Architecture rĂ©duite de 3 → 2 couches**: IWorldGenerationStep supprimĂ© (wrapper redondant). -#### Phase 0: World Initialization -- **InitializeWorldTerrainFunction**: Configuration initiale du terrain (-100°C, -30000m) -- **InitializePlanetaryCoreFunction**: Noyau planĂ©taire avec composition rĂ©aliste (1.94e21 tonnes) +### Interfaces Core (Headers) +- **IWorldGenerationFunction**: Interface pour implĂ©mentations concrĂštes (configure/execute/reset) +- **IWorldGenerationPhase**: Conteneur orchestrant plusieurs Functions avec support de cycles +- **WorldGenerationOrchestrator**: Chef d'orchestre exĂ©cutant les Phases sĂ©quentiellement +- **WorldGenerationFunctionFactory**: Factory pour instancier Functions par nom +- **PhaseRegistry**: Registry pour enregistrer et crĂ©er des Phases -#### Phase 1: Planetary Accretion -- **MeteoriteImpactGenerationFunction**: GĂ©nĂ©ration de mĂ©tĂ©orites avec MeteoriteFactory -- **ImpactEffectsApplicationFunction**: Application des effets physiques (cratĂšres, chaleur, dĂ©pĂŽts) +### ImplĂ©mentations Actuelles + +**Functions (.h + .cpp)** - 8 fonctions production-ready: +- Phase 0: `InitializeWorldTerrainFunction`, `InitializePlanetaryCoreFunction` +- Phase 1: `MeteoriteImpactGenerationFunction`, `ImpactEffectsApplicationFunction`, `PlanetaryDifferentiationFunction`, `VolcanicRedistributionFunction`, `CoolingPhaseFunction`, `UniversalRegionFusionFunction` + +**Data Structures (.h + .cpp)** - Production-ready: +- `WorldData`, `Meteorite`, `MeteoriteFactory`, `PlanetaryCore`, `Volcano`, `VolcanoFactory`, `TectonicRegion`, `ClimateRegion` + +**À ImplĂ©menter (.cpp)** - Headers finalisĂ©s, implĂ©mentations manquantes: +- `WorldGenerationPhase`, `WorldGenerationOrchestrator`, `PhaseRegistry` ### SystĂšmes Techniques -#### MeteoriteFactory (Pattern Pool) -- **Template Pool**: PrĂ©-gĂ©nĂ©ration des mĂ©tĂ©orites types -- **Copy + Modify**: Clone des templates avec modifications de taille -- **Feed/Pull Pattern**: Configuration → GĂ©nĂ©ration → Clonage +**MeteoriteFactory (Pattern Pool)**: +- Template Pool → Copy + Modify → Pull pattern pour performance +- Seedable via `RandomGenerator::getInstance()` (OBLIGATOIRE) -#### RandomGenerator Singleton -- **CentralisĂ©**: `RandomGenerator::getInstance()` partout -- **Seedable**: ReproductibilitĂ© pour tests et debug -- **Performance**: Un seul gĂ©nĂ©rateur MT19937 +**Échelle RĂ©aliste**: +- Noyau planĂ©taire: `__uint128_t` (1.94e21 tonnes) +- Gameplay: `uint64_t` (jusqu'Ă  1e13 tonnes) -#### Échelle RĂ©aliste -- **Noyau**: 1.94e21 tonnes (Ă©chelle terrestre rĂ©elle) -- **MĂ©tĂ©orites**: Jusqu'Ă  1e13 tonnes (cohĂ©rent avec meteorites.json) -- **Types**: uint64_t pour gameplay, __uint128_t pour noyau planĂ©taire - -### Conception -- **Phase**: Groupe logique d'Ă©tapes avec cycles temporels cohĂ©rents -- **Step**: OpĂ©ration atomique de gĂ©nĂ©ration (IWorldGenerationFunction) -- **Producer/Consumer**: SĂ©paration gĂ©nĂ©ration ↔ application des effets -- **ModularitĂ©**: Chaque fonction isolĂ©e et testable +**Conception**: +- Functions isolĂ©es et testables (200-300 lignes max) +- Pattern Configure → Execute → Reset +- Producer/Consumer pour gĂ©nĂ©ration ↔ application des effets ## Contraintes Modules - **200-300 lignes max** par implĂ©mentation @@ -67,14 +71,18 @@ cmake . # Configuration autonome - `IDataNode`: Interface configuration depuis core/ - `C++20`: Features modernes -### Structure PrĂ©vue +### Structure Actuelle ``` include/ -├── IWorldGenerationPhase.h # Interface phase -├── IWorldGenerationStep.h # Interface step -└── (futures implĂ©mentations...) +├── WorldGenerationFunctions/ +│ ├── IWorldGenerationFunction.h # Interface base (✅ finalisĂ©e) +│ ├── WorldGenerationFunctionFactory.h # Factory (✅ + .cpp) +│ └── [8 implĂ©mentations .h] # Functions concrĂštes (✅ + .cpp) +├── IWorldGenerationPhase.h # Interface Phase (✅ header only) +├── WorldGenerationOrchestrator.h # Orchestrateur (✅ header only) +└── PhaseRegistry.h # Registry (✅ header only) ``` --- -**État actuel**: Interfaces dĂ©finies, prĂȘt pour implĂ©mentations concrĂštes. \ No newline at end of file +**État actuel**: 8 Functions implĂ©mentĂ©es, architecture Phase/Function 2-couches dĂ©finie (headers uniquement). \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/IWorldGenerationPhase.h b/src/modules/world-generation-realist/include/IWorldGenerationPhase.h index 9b22f54..6b4bcc8 100644 --- a/src/modules/world-generation-realist/include/IWorldGenerationPhase.h +++ b/src/modules/world-generation-realist/include/IWorldGenerationPhase.h @@ -6,35 +6,110 @@ #include "warfactory/IDataNode.h" class WorldData; -class IWorldGenerationStep; namespace warfactory { +/** + * @brief Interface for world generation phases + * + * A phase is a logical grouping of steps that execute sequentially. + * Phases can be executed step-by-step (executeOneStep) or all at once (execute). + */ class IWorldGenerationPhase { public: virtual ~IWorldGenerationPhase() = default; + /** + * @brief Get the human-readable name of this phase + * @return Phase name (e.g., "planetary_accretion") + */ virtual std::string getPhaseName() const = 0; - virtual std::vector> getSteps() const = 0; + /** + * @brief Get the unique identifier of this phase + * @return Phase ID matching JSON configuration + */ + virtual std::string getPhaseId() const = 0; + /** + * @brief Execute all remaining steps in this phase + * @param world The world data to modify + * @param config Configuration node for this phase + * @return true if all steps completed successfully, false otherwise + */ virtual bool execute(WorldData& world, const IDataNode& config) = 0; + /** + * @brief Execute the next step in the phase + * @param world The world data to modify + * @param config Configuration node for this phase + * @return true if step completed successfully, false otherwise + */ + virtual bool executeOneStep(WorldData& world, const IDataNode& config) = 0; + + /** + * @brief Execute one cycle of the current step + * @param world The world data to modify + * @param config Configuration node for this phase + * @return true if cycle completed successfully, false otherwise + * + * For phases with cycles (duration_cycles in JSON), this executes one cycle. + * For single-shot steps, this is equivalent to executeOneStep(). + */ + virtual bool executeOneCycle(WorldData& world, const IDataNode& config) = 0; + + /** + * @brief Get the name of the currently executing step + * @return Current step name, or empty string if phase not started or complete + */ + virtual std::string getCurrentStepName() const = 0; + + /** + * @brief Get the index of the currently executing step + * @return Current step index (0-based), or -1 if phase not started or complete + */ + virtual int getCurrentStepIndex() const = 0; + + /** + * @brief Get the total number of steps in this phase + * @return Total number of steps + */ + virtual int getTotalSteps() const = 0; + + /** + * @brief Get the current cycle index within the current step + * @return Current cycle index (0-based), or -1 if no cycles in progress + */ + virtual int getCurrentCycleIndex() const = 0; + + /** + * @brief Get the total number of cycles for the current step + * @return Total cycles for current step, or 0 if step not started + */ + virtual int getTotalCyclesForCurrentStep() const = 0; + + /** + * @brief Get the current progress of this phase + * @return Progress value between 0.0 (not started) and 1.0 (complete) + */ virtual float getProgress() const = 0; + /** + * @brief Check if all steps in this phase are complete + * @return true if phase is complete, false otherwise + */ virtual bool isComplete() const = 0; + /** + * @brief Reset the phase to initial state + */ virtual void reset() = 0; + /** + * @brief Get the human-readable description of this phase + * @return Phase description from JSON configuration + */ virtual std::string getPhaseDescription() const = 0; - - virtual int getPhaseNumber() const = 0; - - virtual std::vector getRequiredPreviousPhases() const = 0; - - virtual std::vector getProducedData() const = 0; - - virtual bool canExecute(const WorldData& world) const = 0; }; } // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/IWorldGenerationStep.h b/src/modules/world-generation-realist/include/IWorldGenerationStep.h deleted file mode 100644 index f8636e3..0000000 --- a/src/modules/world-generation-realist/include/IWorldGenerationStep.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include -#include "warfactory/IDataNode.h" - -class WorldData; - -namespace warfactory { - -class IWorldGenerationStep { -public: - virtual ~IWorldGenerationStep() = default; - - virtual std::string getStepName() const = 0; - - virtual bool execute(WorldData& world, const IDataNode& config) = 0; - - virtual bool canExecute(const WorldData& world) const = 0; - - virtual float getProgress() const = 0; - - virtual bool isComplete() const = 0; - - virtual void reset() = 0; - - virtual std::string getStepDescription() const = 0; - - virtual float getEstimatedDuration() const = 0; - - virtual std::vector getRequiredPreviousSteps() const = 0; - - virtual std::vector getProducedData() const = 0; - - virtual int getStepOrder() const = 0; - - virtual std::string getParentPhase() const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/PhaseRegistry.h b/src/modules/world-generation-realist/include/PhaseRegistry.h index 9760b56..0fc4d2a 100644 --- a/src/modules/world-generation-realist/include/PhaseRegistry.h +++ b/src/modules/world-generation-realist/include/PhaseRegistry.h @@ -1,40 +1,49 @@ #pragma once #include "IWorldGenerationPhase.h" -#include "IWorldGenerationStep.h" #include #include #include namespace warfactory { +/** + * @brief Registry for world generation phases + * + * Simplified architecture: Phase directly manages Functions (no Step wrapper) + * Functions are registered via WorldGenerationFunctionFactory + */ class PhaseRegistry { private: - std::unordered_map()>> phase_factories; - std::unordered_map()>> step_factories; + std::unordered_map()>> phase_factories_; public: static PhaseRegistry& getInstance(); + /** + * @brief Register a phase type with its unique identifier + * @tparam PhaseType Concrete phase implementation + * @param phase_id Unique phase identifier (e.g., "world_initialization") + */ template - void registerPhase(const std::string& phase_name) { - phase_factories[phase_name] = []() { + void registerPhase(const std::string& phase_id) { + phase_factories_[phase_id] = []() { return std::make_unique(); }; } - template - void registerStep(const std::string& step_name) { - step_factories[step_name] = []() { - return std::make_unique(); - }; - } - - std::unique_ptr createPhase(const std::string& phase_name); - std::unique_ptr createStep(const std::string& step_name); + /** + * @brief Create a phase instance by ID + * @param phase_id Phase identifier from JSON configuration + * @return Unique pointer to phase instance, or nullptr if not found + */ + std::unique_ptr createPhase(const std::string& phase_id); + /** + * @brief Get list of all registered phase IDs + * @return Vector of registered phase identifiers + */ std::vector getRegisteredPhases() const; - std::vector getRegisteredSteps() const; }; } // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationFunction.h b/src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationFunction.h index 4c959c5..de381f0 100644 --- a/src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationFunction.h +++ b/src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationFunction.h @@ -63,34 +63,6 @@ public: * After reset(), configure() must be called again. */ virtual void reset() = 0; - - // ======================================== - // OPTIONAL: Progress Tracking (for UI/debug) - // ======================================== - - /** - * @brief Get execution progress (optional - default implementation) - * @return Progress from 0.0 (not started) to 1.0 (complete) - */ - virtual float getProgress() const { return 0.0f; } - - /** - * @brief Check if execution is complete (optional - default implementation) - * @return True if function finished execution - */ - virtual bool isComplete() const { return false; } - - /** - * @brief Get human-readable description (optional - default implementation) - * @return Description of what this function does - */ - virtual std::string getFunctionDescription() const { return getStepName(); } - - /** - * @brief Get parent phase name (optional - default implementation) - * @return Phase name from Regular_world.json - */ - virtual std::string getParentPhase() const { return "unknown"; } }; } // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationPhase.h b/src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationPhase.h deleted file mode 100644 index 9b22f54..0000000 --- a/src/modules/world-generation-realist/include/WorldGenerationFunctions/IWorldGenerationPhase.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include -#include -#include "warfactory/IDataNode.h" - -class WorldData; -class IWorldGenerationStep; - -namespace warfactory { - -class IWorldGenerationPhase { -public: - virtual ~IWorldGenerationPhase() = default; - - virtual std::string getPhaseName() const = 0; - - virtual std::vector> getSteps() const = 0; - - virtual bool execute(WorldData& world, const IDataNode& config) = 0; - - virtual float getProgress() const = 0; - - virtual bool isComplete() const = 0; - - virtual void reset() = 0; - - virtual std::string getPhaseDescription() const = 0; - - virtual int getPhaseNumber() const = 0; - - virtual std::vector getRequiredPreviousPhases() const = 0; - - virtual std::vector getProducedData() const = 0; - - virtual bool canExecute(const WorldData& world) const = 0; -}; - -} // namespace warfactory \ No newline at end of file diff --git a/src/modules/world-generation-realist/include/WorldGenerationOrchestrator.h b/src/modules/world-generation-realist/include/WorldGenerationOrchestrator.h index ea17179..3e78c23 100644 --- a/src/modules/world-generation-realist/include/WorldGenerationOrchestrator.h +++ b/src/modules/world-generation-realist/include/WorldGenerationOrchestrator.h @@ -41,10 +41,17 @@ public: void reset(); private: + /** + * @brief Build phase pipeline from JSON configuration + * @param config Root configuration node containing "geological_simulation" + */ void buildPhasesFromConfig(const IDataNode& config); - std::unique_ptr createStepFromConfig(const IDataNode& step_config); - + /** + * @brief Create a phase instance from JSON configuration + * @param phase_config Configuration node for a single phase + * @return Unique pointer to configured phase instance + */ std::unique_ptr createPhaseFromConfig(const IDataNode& phase_config); }; diff --git a/test_imgui_ui.cpp b/test_imgui_ui.cpp index 7c41746..c757ec6 100644 --- a/test_imgui_ui.cpp +++ b/test_imgui_ui.cpp @@ -1,9 +1,9 @@ -#include "src/core/include/warfactory/IUI_Enums.h" -#include "src/core/include/warfactory/ImGuiUI.h" +#include +#include #include #include -using namespace warfactory; +using namespace grove; void showUsage(const char* program_name) { std::cout << "Usage: " << program_name << " [options]\n"