# Mobile Command - Data-Driven Implementation Plan **Date**: 2 décembre 2025 **Architecture**: Data-driven process engine (WarFactory-inspired) **Status**: Planning phase - Replacing hardcoded module logic --- ## 🎯 Vision Créer un système data-driven où: - **GameModule** reste hardcodé (state machine C++, orchestration) - **Systèmes de jeu** sont data-driven (crafting, combat, events définis en JSON) - **ProcessEngine** interprète et exécute les process JSON - **WarFactory compatibility** - Architecture réutilisable entre projets --- ## 📐 Architecture Cible ``` GameModule.so (C++ hardcodé) ├─ State machine (MainMenu → TrainBuilder → Expedition → Combat) ├─ Appelle les systèmes via IIO pub/sub └─ Coordonne le flow du jeu ProcessEngine (lib statique partagée) ├─ Registry: "craft_recipe" → CraftProcessor ├─ Registry: "resolve_combat" → CombatProcessor ├─ Registry: "trigger_event" → EventProcessor └─ execute(process_type, params_json, state) CraftingSystemModule.so (data-driven) ├─ CraftingState (local) ├─ Utilise ProcessEngine ├─ Config: recipes.json └─ IIO: "craft:start" → publish "craft:complete" CombatSystemModule.so (data-driven) ├─ CombatState (local) ├─ Utilise ProcessEngine ├─ Config: combat_scenarios.json └─ IIO: "combat:start" → publish "combat:ended" EventSystemModule.so (data-driven) ├─ EventState (local) ├─ Utilise ProcessEngine ├─ Config: events.json └─ IIO: "event:check" → publish "event:triggered" ``` --- ## 🗂️ Structure du Projet ``` project-mobile-command/ ├── src/ │ ├── main.cpp # GroveEngine mainloop │ ├── process_engine/ # Core data-driven engine │ │ ├── ProcessEngine.h │ │ ├── ProcessEngine.cpp │ │ ├── IProcessor.h # Interface pour processors │ │ └── processors/ # Process implementations │ │ ├── CraftProcessor.cpp │ │ ├── CombatProcessor.cpp │ │ └── EventProcessor.cpp │ │ │ └── modules/ │ ├── GameModule.cpp # Orchestrator (hardcodé) │ │ │ ├── systems/ # Data-driven systems │ │ ├── CraftingSystemModule.cpp │ │ ├── CombatSystemModule.cpp │ │ ├── EventSystemModule.cpp │ │ └── StorageSystemModule.cpp │ │ │ └── mc_specific/ # MC-only modules │ ├── TrainBuilderModule.cpp │ └── ExpeditionModule.cpp │ ├── config/ │ ├── game.json # GameModule config │ ├── systems/ # System definitions │ │ ├── crafting_recipes.json │ │ ├── combat_scenarios.json │ │ ├── events.json │ │ └── storage.json │ │ │ └── mc_specific/ # MC-specific configs │ ├── train.json │ └── expeditions.json │ └── tests/ ├── ProcessEngineTest.cpp ├── CraftingSystemTest.cpp └── IntegrationTest.cpp ``` --- ## 📋 Phase 1: ProcessEngine Foundation **Objectif**: Créer le moteur générique qui interprète les process JSON ### Tasks #### 1.1 ProcessEngine Core ```cpp class ProcessEngine { public: using ProcessFunc = std::function; void registerProcess(const std::string& type, ProcessFunc func); void execute(const std::string& processType, const IDataNode& params, IDataNode& state, IIO* io); }; ``` **Fichiers**: - [ ] `src/process_engine/ProcessEngine.h` - [ ] `src/process_engine/ProcessEngine.cpp` - [ ] `src/process_engine/IProcessor.h` (interface commune) **Tests**: - [ ] `tests/ProcessEngineTest.cpp` - [ ] Test registry (register/execute) - [ ] Test unknown process type handling #### 1.2 CMake Integration - [ ] Créer lib statique `ProcessEngine` - [ ] Link dans chaque module data-driven - [ ] Headers publics exposés **Durée estimée**: 1-2 jours --- ## 📋 Phase 2: Crafting System (Data-Driven) **Objectif**: Premier système data-driven complet ### 2.1 CraftProcessor **Logic**: ```cpp void CraftProcessor::execute(const IDataNode& params, IDataNode& state, IIO* io) { // 1. Parse params (recipe_id, inputs, outputs, duration) // 2. Check inventory in state // 3. Consume inputs // 4. Add craft job to queue // 5. Publish "craft:started" } ``` **Fichiers**: - [ ] `src/process_engine/processors/CraftProcessor.cpp` - [ ] `src/process_engine/processors/CraftProcessor.h` ### 2.2 CraftingSystemModule **State**: ```json { "inventory": { "scrap_metal": 100, "ammunition": 500 }, "craft_queue": [ {"recipe": "repair_kit", "time_remaining": 25.3} ] } ``` **Config** (`config/systems/crafting_recipes.json`): ```json { "recipes": { "repair_kit": { "process": "craft_recipe", "inputs": {"scrap_metal": 5, "electronics": 1}, "outputs": {"repair_kit": 1}, "duration": 30.0 }, "drone_recon": { "process": "craft_recipe", "inputs": {"drone_parts": 3, "electronics": 2}, "outputs": {"drone_recon": 1}, "duration": 120.0 } } } ``` **Topics**: - Subscribe: `"craft:start"` → {recipe_id} - Publish: `"craft:started"` → {recipe_id, duration} - Publish: `"craft:complete"` → {recipe_id, outputs} - Publish: `"inventory:changed"` → {resource_id, delta, total} **Fichiers**: - [ ] `src/modules/systems/CraftingSystemModule.cpp` - [ ] `src/modules/systems/CraftingSystemModule.h` - [ ] `config/systems/crafting_recipes.json` **Tests**: - [ ] `tests/CraftingSystemTest.cpp` - [ ] Test craft avec resources suffisantes - [ ] Test craft avec resources insuffisantes - [ ] Test craft queue progression - [ ] Test hot-reload state preservation **Durée estimée**: 2-3 jours --- ## 📋 Phase 3: Combat System (Data-Driven) **Objectif**: Système de combat avec formules configurables ### 3.1 CombatProcessor **Logic**: ```cpp void CombatProcessor::execute(const IDataNode& params, IDataNode& state, IIO* io) { // 1. Parse scenario (enemy stats, formulas) // 2. Setup combatants // 3. Resolve rounds (hit calculation, damage, casualties) // 4. Determine outcome (victory/defeat) // 5. Publish "combat:ended" avec loot/casualties } ``` **Config** (`config/systems/combat_scenarios.json`): ```json { "scenarios": { "scavenger_ambush": { "process": "resolve_combat", "enemy": { "firepower": 30, "armor": 10, "morale": 60, "count": 8 }, "formulas": { "hit_chance": "accuracy * (1.0 - cover)", "damage": "max(0, firepower - armor * 0.5)", "morale_loss": "casualties / total * 100" }, "loot": { "scrap_metal": {"min": 10, "max": 30}, "ammunition": {"min": 20, "max": 100} } } } } ``` **Formula Parser**: - [ ] Simple expression evaluator (pour prototype) - [ ] Variables: `accuracy`, `cover`, `firepower`, `armor`, etc. - [ ] Opérations: `+`, `-`, `*`, `/`, `max()`, `min()` **Fichiers**: - [ ] `src/process_engine/processors/CombatProcessor.cpp` - [ ] `src/process_engine/FormulaEvaluator.h` (helper) - [ ] `src/modules/systems/CombatSystemModule.cpp` - [ ] `config/systems/combat_scenarios.json` **Tests**: - [ ] Test formulas parsing - [ ] Test combat resolution - [ ] Test loot distribution - [ ] Test casualties **Durée estimée**: 3-4 jours --- ## 📋 Phase 4: Event System (Data-Driven) **Objectif**: Système d'événements scriptés avec conditions et outcomes ### 4.1 EventProcessor **Logic**: ```cpp void EventProcessor::execute(const IDataNode& params, IDataNode& state, IIO* io) { // 1. Evaluate conditions (game_time, location, resources) // 2. Trigger event si conditions met // 3. Handle player choice // 4. Apply outcomes (resources, flags, trigger_combat) } ``` **Config** (`config/systems/events.json`): ```json { "events": { "scavenger_encounter": { "process": "trigger_event", "title": "Scavengers Spotted", "description": "Your scouts report a small group nearby.", "conditions": { "game_time_min": 600, "location_type": "urban_ruins" }, "choices": [ { "id": "attack", "text": "Attack immediately", "outcomes": { "trigger_combat": "scavenger_ambush", "morale": -5 } }, { "id": "negotiate", "text": "Attempt to trade", "requirements": {"reputation": 20}, "outcomes": { "resources": {"ammunition": -50, "food": +30}, "morale": +5 } }, { "id": "avoid", "text": "Move on quietly", "outcomes": { "time_cost": 60 } } ] } } } ``` **Fichiers**: - [ ] `src/process_engine/processors/EventProcessor.cpp` - [ ] `src/modules/systems/EventSystemModule.cpp` - [ ] `config/systems/events.json` (5 events minimum) **Tests**: - [ ] Test conditions evaluation - [ ] Test event triggering - [ ] Test outcomes application - [ ] Test choice requirements **Durée estimée**: 2-3 jours --- ## 📋 Phase 5: GameModule Integration **Objectif**: GameModule orchestre tous les systèmes data-driven ### 5.1 GameModule Updates **State Machine** (reste hardcodé): ```cpp enum class GameState { MainMenu, TrainBuilder, Expedition, Combat, Event, Pause }; void GameModule::updateExpedition(float dt) { // Publish event checks auto checkEvent = make_unique("check"); checkEvent->setDouble("game_time", m_gameTime); checkEvent->setString("location", m_currentLocation); m_io->publish("event:check", move(checkEvent)); // Handle incoming events if (m_io->hasMessages()) { auto msg = m_io->pullMessage(); if (msg.topic == "event:triggered") { transitionToState(GameState::Event); } } } ``` **Topics Orchestration**: - Subscribe à tous les `*:complete` / `*:ended` - Publish vers systèmes via `craft:start`, `combat:start`, etc. - Gère transitions d'état **Fichiers**: - [ ] Update `src/modules/GameModule.cpp` - [ ] Subscribe tous les nouveaux topics - [ ] Wire systems ensemble **Durée estimée**: 2 jours --- ## 📋 Phase 6: Storage System **Objectif**: Save/load de tous les états data-driven ### 6.1 Storage Format ```json { "version": "0.1.0", "timestamp": "2025-12-02T10:30:00Z", "game_state": "Expedition", "game_time": 3600.5, "modules": { "GameModule": {...}, "CraftingSystem": {...}, "CombatSystem": {...}, "EventSystem": {...} } } ``` **Fichiers**: - [ ] `src/modules/systems/StorageSystemModule.cpp` - [ ] Collect states via IIO broadcast - [ ] Save to JSON - [ ] Restore states on load **Durée estimée**: 2 jours --- ## 📋 Phase 7: MC-Specific Modules **Objectif**: Modules spécifiques Mobile Command (pas data-driven) ### 7.1 TrainBuilderModule **Responsabilités**: - Balance train (latéral/longitudinal) - Wagon management - Performance malus **Topics**: - Publish: `"train:composition_changed"` - Publish: `"train:performance_updated"` **Config**: `config/mc_specific/train.json` ### 7.2 ExpeditionModule **Responsabilités**: - Lancer expéditions - Team composition (humains + drones) - Return avec loot **Topics**: - Subscribe: `"craft:complete"` (drones) - Publish: `"expedition:started"`, `"expedition:returned"` **Config**: `config/mc_specific/expeditions.json` **Durée estimée**: 3-4 jours --- ## 📋 Phase 8: Integration & Testing **Objectif**: Loop complet fonctionnel ### 8.1 Integration Tests - [ ] Full loop test: craft → expedition → combat → event → return - [ ] Save/load cycle complet - [ ] Hot-reload tous modules - [ ] Pub/sub message flow validation ### 8.2 Main.cpp Updates ```cpp std::vector> moduleList = { // Game orchestrator {"GameModule", "game.json"}, // Data-driven systems {"CraftingSystemModule", "systems/crafting_recipes.json"}, {"CombatSystemModule", "systems/combat_scenarios.json"}, {"EventSystemModule", "systems/events.json"}, {"StorageSystemModule", "systems/storage.json"}, // MC-specific {"TrainBuilderModule", "mc_specific/train.json"}, {"ExpeditionModule", "mc_specific/expeditions.json"} }; ``` **Durée estimée**: 2-3 jours --- ## 📊 Timeline Estimé | Phase | Durée | Cumul | Livrable | |-------|-------|-------|----------| | Phase 1: ProcessEngine | 2 jours | 2j | Core engine fonctionnel | | Phase 2: Crafting | 3 jours | 5j | Premier système data-driven | | Phase 3: Combat | 4 jours | 9j | Combat data-driven | | Phase 4: Events | 3 jours | 12j | Events data-driven | | Phase 5: GameModule | 2 jours | 14j | Orchestration complète | | Phase 6: Storage | 2 jours | 16j | Save/load | | Phase 7: MC Modules | 4 jours | 20j | Train + Expeditions | | Phase 8: Integration | 3 jours | 23j | Loop complet | **Total: ~23 jours de dev (4-5 semaines)** --- ## 🎯 Critères de Succès ### Technique - [ ] ProcessEngine avec 3+ processors (craft, combat, event) - [ ] 3+ systèmes data-driven fonctionnels - [ ] Hot-reload préserve état - [ ] Pub/sub communication fluide - [ ] Tests unitaires pass ### Gameplay - [ ] Craft 5+ items - [ ] Combat 3+ scenarios différents - [ ] Trigger 5+ events - [ ] Save/load fonctionne - [ ] Loop complet 30+ minutes jouable ### Réutilisabilité - [ ] ProcessEngine utilisable pour WarFactory - [ ] Pas de hardcode MC-specific dans systems/ - [ ] JSON configs clairs et documentés --- ## 🔄 Comparaison Avant/Après ### Avant (Architecture actuelle) ``` ResourceModule.cpp (478 lignes) ├─ Logic craft hardcodée ├─ Formulas en C++ └─ Config JSON minimal → Changer formule = recompiler → Pas réutilisable WF ``` ### Après (Architecture data-driven) ``` CraftingSystemModule.cpp (150 lignes) ├─ Utilise ProcessEngine └─ Config recipes.json complet CraftProcessor.cpp (100 lignes) └─ Logic générique réutilisable → Changer formule = edit JSON → ProcessEngine réutilisable WF ``` --- ## 🚀 Prochaines Étapes Immédiates 1. **Créer structure ProcessEngine** (Phase 1) 2. **Implémenter CraftProcessor** (Phase 2) 3. **Tester avec CraftingSystemModule** (Phase 2) 4. **Valider hot-reload** (Phase 2) --- ## 📝 Notes Importantes ### Design Decisions 1. **GameModule reste hardcodé** - State machine C++ pour clarté 2. **Systems sont data-driven** - Réutilisabilité MC/WF 3. **ProcessEngine est stateless** - State vit dans modules 4. **IIO pour tout** - Découplage maximal ### Risks - **Formula parser complexity** - Garder simple pour prototype - **JSON configs verbeux** - Trade-off accepté pour flexibilité - **Hot-reload edge cases** - Tester intensivement ### Future Enhancements - Expression parser avancé (Lua?) - Visual process editor - Process debugging tools - Performance profiling --- *Plan créé le 2 décembre 2025* *Architecture inspirée de WarFactory worldgen*