# AI Framework - Unified Decision System

## Philosophie

Le système d'IA de Warfactory repose sur un **framework unifié de prise de décision par scoring**. Tous les types d'IA (tactique, opérationnelle, économique, diplomatique) utilisent le même pattern fondamental :

1. **Générer options** disponibles dans le contexte actuel
2. **Scorer chaque option** selon poids configurables et situation
3. **Choisir la meilleure option** (highest score)
4. **Exécuter l'action** correspondante

Ce pattern unifié permet :
- **Cohérence** : Même logique à travers tous les systèmes IA
- **Configurabilité** : Comportements ajustables via JSON
- **Apprentissage** : Reinforcement Learning ajuste les poids
- **Modularité** : Nouveaux types de décisions ajoutables facilement
- **Testabilité** : Chaque décision isolée et vérifiable

## Architecture Globale

### Hiérarchie des Modules IA

```
AI Framework
├── Core Decision System
│   ├── IDecision (interface de base)
│   ├── Decision Factory (création objets)
│   └── Scoring Engine (évaluation uniforme)
│
├── Helper Modules (services, pas de décisions)
│   ├── PathfinderModule (calcul chemins)
│   ├── AcquisitionModule (sélection cibles)
│   └── MovementModule (exécution mouvement)
│
├── Decision Modules (utilisent helpers)
│   ├── TacticalModule (combat temps-réel)
│   ├── OperationalModule (stratégie bataille)
│   ├── CompanyAIModule (business)
│   └── StateAIModule (politique)
│
└── Data Modules (consultés par tous)
    ├── DiplomacyModule (relations, traités)
    └── EconomyModule (marché, prix)
```

### Flux de Décision Type

```
OperationalModule
    ↓ (donne posture: "rush blindé")
TacticalModule
    ↓ (demande chemins pour flanking)
PathfinderModule → retourne 3 chemins possibles
    ↓ (demande cibles prioritaires)
AcquisitionModule → retourne 5 cibles scorées
    ↓ (choisit meilleure tactique)
TacticalModule → décision: flanking par chemin 2, cible 1
    ↓ (exécute mouvement)
MovementModule → unités se déplacent
```

## Interface IDecision - Core Pattern

### Définition

Toutes les décisions IA implémentent cette interface :

```cpp
class IDecision {
public:
    virtual ~IDecision() = default;

    // 1. Générer toutes les options disponibles
    virtual std::vector<Option> generateOptions() = 0;

    // 2. Évaluer score d'une option dans le contexte
    virtual float scoreOption(const Option& opt, const Context& ctx) = 0;

    // 3. Choisir la meilleure option
    virtual Option chooseBest() = 0;

    // 4. Exécuter l'option choisie
    virtual Action execute(const Option& opt) = 0;

    // 5. Obtenir les poids configurés
    virtual Weights getWeights() const = 0;

    // 6. Définir nouveaux poids (pour RL)
    virtual void setWeights(const Weights& weights) = 0;
};
```

### Pattern d'Usage : Decision Objects Éphémères

**Principe** : New → Use → Delete

```cpp
// Création décision éphémère
IDecision* decision = DecisionFactory::create(
    "flanking_maneuver",
    context,
    weights
);

// Évaluation et choix
Option best = decision->chooseBest();

// Exécution
Action action = decision->execute(best);

// Destruction immédiate
delete decision;
```

**Avantages** :
- **Pas d'état persistant** : Chaque décision isolée
- **Parallélisation** : Évaluer N décisions simultanément sans conflits
- **Hot-reload** : Charger nouveaux types depuis modules .so
- **Memory safety** : Objets détruits après usage

**Alternative avec smart pointers** :
```cpp
auto decision = DecisionFactory::createUnique("flanking_maneuver", ctx, weights);
Option best = decision->chooseBest();
Action action = decision->execute(best);
// Auto-delete à la sortie de scope
```

### Structures de Données

#### Option

Représente une action possible :

```cpp
struct Option {
    std::string type;              // "flanking", "frontal_assault", etc.
    json parameters;               // Paramètres spécifiques
    float base_score;              // Score de base (avant modifiers)
    std::vector<Modifier> modifiers; // Bonus/malus contextuels
};
```

#### Context

État du monde pertinent pour la décision :

```cpp
struct Context {
    json world_state;              // État général (terrain, météo, etc.)
    json entities;                 // Entités pertinentes (unités, ennemis)
    json objectives;               // Objectifs actuels
    json constraints;              // Contraintes (budget, temps, etc.)
    Doctrine* doctrine;            // Doctrine appliquée (USSR, OTAN, etc.)
};
```

#### Weights

Poids configurables pour le scoring :

```cpp
struct Weights {
    std::map<std::string, float> values;  // "aggression": 0.8, "caution": 0.3

    float get(const std::string& key, float default_val = 0.5f) const {
        auto it = values.find(key);
        return (it != values.end()) ? it->second : default_val;
    }
};

// Chargement depuis JSON
Weights Weights::fromJson(const json& data) {
    Weights w;
    for (auto& [key, val] : data.items()) {
        w.values[key] = val.get<float>();
    }
    return w;
}
```

## Système de Scoring Unifié

### Formule Générale

```cpp
float IDecision::scoreOption(const Option& opt, const Context& ctx) {
    float score = opt.base_score;

    // Application des poids
    for (auto& [factor, importance] : weights.values) {
        float factor_value = evaluateFactor(factor, opt, ctx);
        score += factor_value * importance;
    }

    // Application des modifiers contextuels
    for (auto& modifier : opt.modifiers) {
        score *= modifier.multiplier;
    }

    // Normalisation (optionnelle)
    return std::clamp(score, 0.0f, 1.0f);
}
```

### Exemple Concret : PathfinderModule

**Options** : 5 chemins possibles vers objectif

```cpp
class PathDecision : public IDecision {
    std::vector<Option> generateOptions() override {
        std::vector<Option> paths;

        // Générer chemins alternatifs
        for (auto& path : pathfinder->findAllPaths(start, end)) {
            Option opt;
            opt.type = "path";
            opt.parameters["route"] = path.waypoints;
            opt.parameters["distance"] = path.length;
            opt.parameters["safety"] = path.threat_level;
            opt.parameters["cover"] = path.cover_percentage;
            opt.base_score = 0.5f;

            // Modifiers contextuels
            if (path.crosses_open_terrain) {
                opt.modifiers.push_back({"open_terrain", 0.7f});
            }
            if (path.has_chokepoints) {
                opt.modifiers.push_back({"chokepoint", 0.85f});
            }

            paths.push_back(opt);
        }

        return paths;
    }

    float scoreOption(const Option& opt, const Context& ctx) override {
        float score = opt.base_score;

        // Facteurs de scoring
        float distance = opt.parameters["distance"];
        float safety = opt.parameters["safety"];
        float cover = opt.parameters["cover"];

        // Application poids configurables
        score += (1.0f - distance / max_distance) * weights.get("speed");
        score += safety * weights.get("safety");
        score += cover * weights.get("stealth");

        // Modifiers
        for (auto& mod : opt.modifiers) {
            score *= mod.multiplier;
        }

        return score;
    }
};
```

**Configuration Poids (JSON)** :
```json
{
  "pathfinder_weights": {
    "speed": 0.6,
    "safety": 0.3,
    "stealth": 0.1
  }
}
```

**Usage** :
```cpp
auto decision = new PathDecision(start, end, context, weights);
Option bestPath = decision->chooseBest();
Action moveAction = decision->execute(bestPath);
delete decision;
```

### Exemple : AcquisitionModule

**Options** : Cibles ennemies visibles

```cpp
class AcquisitionDecision : public IDecision {
    std::vector<Option> generateOptions() override {
        std::vector<Option> targets;

        for (auto& enemy : visibleEnemies) {
            Option opt;
            opt.type = "target";
            opt.parameters["entity_id"] = enemy.id;
            opt.parameters["threat"] = enemy.calculateThreat();
            opt.parameters["vulnerability"] = enemy.calculateVulnerability();
            opt.parameters["priority"] = enemy.strategic_value;
            opt.base_score = 0.5f;

            // Modifiers
            if (enemy.is_wounded) {
                opt.modifiers.push_back({"wounded", 1.2f});
            }
            if (enemy.has_cover) {
                opt.modifiers.push_back({"covered", 0.8f});
            }

            targets.push_back(opt);
        }

        return targets;
    }

    float scoreOption(const Option& opt, const Context& ctx) override {
        float score = opt.base_score;

        float threat = opt.parameters["threat"];
        float vulnerability = opt.parameters["vulnerability"];
        float priority = opt.parameters["priority"];

        // Poids doctrine
        score += threat * weights.get("threat_priority");
        score += vulnerability * weights.get("opportunism");
        score += priority * weights.get("strategic_focus");

        // Modifiers
        for (auto& mod : opt.modifiers) {
            score *= mod.multiplier;
        }

        return score;
    }
};
```

**Configuration** :
```json
{
  "acquisition_weights": {
    "threat_priority": 0.7,
    "opportunism": 0.2,
    "strategic_focus": 0.1
  }
}
```

## Modules Spécialisés

### Helper Modules (Services)

Ces modules **ne prennent pas de décisions**, ils fournissent des services aux decision modules.

#### PathfinderModule

**Responsabilité** : Calculer chemins navigables entre deux points

**Interface** :
```cpp
class PathfinderModule : public IModule {
public:
    // Trouver meilleur chemin unique
    Path findPath(Position start, Position end, PathConstraints constraints);

    // Trouver tous les chemins alternatifs
    std::vector<Path> findAllPaths(Position start, Position end, int max_paths = 5);

    // Vérifier si chemin encore valide
    bool validatePath(const Path& path);
};

struct Path {
    std::vector<Position> waypoints;
    float length;
    float threat_level;        // Exposition ennemie
    float cover_percentage;    // % du chemin avec couvert
    bool crosses_open_terrain;
    bool has_chokepoints;
};
```

**Utilisé par** : TacticalModule, OperationalModule

#### AcquisitionModule

**Responsabilité** : Identifier et scorer cibles potentielles

**Interface** :
```cpp
class AcquisitionModule : public IModule {
public:
    // Obtenir toutes les cibles visibles
    std::vector<Target> getVisibleTargets(Unit observer);

    // Scorer une cible selon contexte
    float scoreTarget(Target target, Context ctx, Weights weights);

    // Filtrer cibles selon critères
    std::vector<Target> filterTargets(std::vector<Target> targets, FilterCriteria criteria);
};

struct Target {
    EntityId id;
    Position position;
    float threat;              // Dangerosité
    float vulnerability;       // Facilité élimination
    float strategic_value;     // Importance stratégique
    bool is_wounded;
    bool has_cover;
};
```

**Utilisé par** : TacticalModule

#### MovementModule

**Responsabilité** : Exécuter déplacements d'unités

**Interface** :
```cpp
class MovementModule : public IModule {
public:
    // Déplacer unité selon chemin
    void moveUnit(Unit unit, Path path);

    // Déplacer formation
    void moveFormation(std::vector<Unit> units, Path path, FormationType formation);

    // Vérifier si mouvement possible
    bool canMove(Unit unit, Position target);
};
```

**Utilisé par** : TacticalModule

### Decision Modules

Ces modules **prennent des décisions** en utilisant les helpers.

#### TacticalModule

**Responsabilité** : Décisions combat temps-réel (secondes/minutes)

**Décisions prises** :
- Choix tactique (flanking, frontal assault, suppression, retreat)
- Sélection cibles
- Positionnement unités
- Utilisation couvert
- Timing engagements

**Dépendances** :
- PathfinderModule (chemins)
- AcquisitionModule (cibles)
- MovementModule (exécution)

**Exemple Décision** :
```cpp
class FlankingDecision : public IDecision {
    std::vector<Option> generateOptions() override {
        std::vector<Option> options;

        // Pour chaque flanc possible
        for (auto& flankPosition : identifyFlankPositions(enemy)) {
            // Demander chemins au PathfinderModule
            auto paths = pathfinder->findAllPaths(myPosition, flankPosition);

            for (auto& path : paths) {
                // Demander cibles à AcquisitionModule
                auto targets = acquisition->getVisibleTargets(myUnit);

                Option opt;
                opt.type = "flanking";
                opt.parameters["path"] = path;
                opt.parameters["flank_side"] = flankPosition.side; // "left"/"right"
                opt.parameters["targets"] = targets;
                opt.base_score = 0.6f; // Flanking généralement bon

                // Modifiers
                if (path.crosses_open_terrain) {
                    opt.modifiers.push_back({"exposed_approach", 0.7f});
                }
                if (targets.size() > 3) {
                    opt.modifiers.push_back({"many_targets", 1.2f});
                }

                options.push_back(opt);
            }
        }

        return options;
    }

    float scoreOption(const Option& opt, const Context& ctx) override {
        // Récupérer poids doctrine
        Doctrine* doctrine = ctx.doctrine;
        float flanking_preference = doctrine->tactical_weights["flanking"];

        float score = opt.base_score * flanking_preference;

        // Facteurs tactiques
        Path path = opt.parameters["path"];
        score += path.cover_percentage * weights.get("safety");
        score -= path.threat_level * weights.get("caution");

        // Modifiers
        for (auto& mod : opt.modifiers) {
            score *= mod.multiplier;
        }

        return score;
    }
};
```

**Configuration Poids** :
```json
{
  "tactical_weights": {
    "safety": 0.4,
    "caution": 0.3,
    "aggression": 0.7
  }
}
```

#### OperationalModule

**Responsabilité** : Choix stratégie/posture bataille (heures/jours)

**Décisions prises** :
- Posture opérationnelle (rush blindé, raid cavalerie, défense en profondeur)
- Allocation forces entre secteurs
- Timing offensives
- Objectifs prioritaires

**Dépendances** :
- TacticalModule (exécution tactique)
- DiplomacyModule (contexte stratégique)

**Exemple Décision** :
```cpp
class OperationalPostureDecision : public IDecision {
    std::vector<Option> generateOptions() override {
        std::vector<Option> postures;

        // Postures disponibles selon doctrine
        for (auto& [posture_name, posture_weight] : doctrine->operational_weights) {
            Option opt;
            opt.type = "posture";
            opt.parameters["name"] = posture_name;
            opt.base_score = posture_weight;

            // Évaluer faisabilité
            if (posture_name == "rush_blinde" && terrain.is_open) {
                opt.modifiers.push_back({"favorable_terrain", 1.3f});
            }
            if (posture_name == "infiltration" && units.has_infantry) {
                opt.modifiers.push_back({"suitable_units", 1.2f});
            }

            postures.push_back(opt);
        }

        return postures;
    }

    Action execute(const Option& opt) override {
        std::string posture = opt.parameters["name"];

        // Donner directive au TacticalModule
        tacticalModule->setPosture(posture);

        // Ajuster poids tactiques selon posture
        if (posture == "rush_blinde") {
            tacticalModule->adjustWeights({
                {"flanking", 1.5f},      // Boost flanking
                {"caution", 0.5f}        // Réduire caution
            });
        }

        return Action{posture, opt.parameters};
    }
};
```

**Doctrines Opérationnelles** :

```json
// doctrines/ussr.json
{
  "name": "USSR Deep Battle",
  "operational_weights": {
    "deep_battle": 0.8,
    "overwhelming_assault": 0.9,
    "mobile_defense": 0.4,
    "raid_cavalry": 0.3,
    "infiltration": 0.2
  },
  "tactical_weights": {
    "frontal_assault": 0.8,
    "flanking": 0.5,
    "combined_arms": 0.7,
    "retreat_threshold": 0.2
  }
}

// doctrines/nato.json
{
  "name": "NATO AirLand Battle",
  "operational_weights": {
    "airland_battle": 0.9,
    "maneuver_warfare": 0.8,
    "deep_strike": 0.7,
    "overwhelming_assault": 0.4,
    "mobile_defense": 0.6
  },
  "tactical_weights": {
    "frontal_assault": 0.3,
    "flanking": 0.9,
    "combined_arms": 0.9,
    "retreat_threshold": 0.6
  }
}
```

#### CompanyAIModule

**Responsabilité** : Décisions business (jours/semaines)

**Décisions prises** :
- Investissements R&D
- Production (quoi produire, combien)
- Prix et stratégie commerciale
- Lobbying états
- Acquisitions/expansions

**Dépendances** :
- EconomyModule (prix marché, demande)
- DiplomacyModule (relations, influence)

**Exemple Décision** :
```cpp
class CompanyInvestmentDecision : public IDecision {
    std::vector<Option> generateOptions() override {
        std::vector<Option> investments;

        // R&D options
        for (auto& tech : availableTechnologies) {
            Option opt;
            opt.type = "research";
            opt.parameters["tech_id"] = tech.id;
            opt.parameters["cost"] = tech.research_cost;
            opt.parameters["expected_profit"] = estimateProfit(tech);
            opt.base_score = 0.5f;

            if (tech.is_breakthrough) {
                opt.modifiers.push_back({"breakthrough", 1.5f});
            }

            investments.push_back(opt);
        }

        // Production expansion
        Option expand;
        expand.type = "expand_production";
        expand.parameters["cost"] = calculate_expansion_cost();
        expand.parameters["capacity_increase"] = 0.3f;
        expand.base_score = 0.4f;
        investments.push_back(expand);

        // Lobbying
        for (auto& state : states) {
            float influence = diplomacy->getInfluence(company_id, state.id);
            if (influence < 0.8f) {
                Option lobby;
                lobby.type = "lobbying";
                lobby.parameters["state_id"] = state.id;
                lobby.parameters["cost"] = calculateLobbyCost(state);
                lobby.parameters["influence_gain"] = 0.1f;
                lobby.base_score = 0.3f;
                investments.push_back(lobby);
            }
        }

        return investments;
    }

    float scoreOption(const Option& opt, const Context& ctx) override {
        float score = opt.base_score;

        if (opt.type == "research") {
            float expected_profit = opt.parameters["expected_profit"];
            float cost = opt.parameters["cost"];
            float roi = expected_profit / cost;

            score += roi * weights.get("innovation");
            score -= (cost / company_budget) * weights.get("risk_aversion");
        }
        else if (opt.type == "lobbying") {
            float influence_gain = opt.parameters["influence_gain"];
            score += influence_gain * weights.get("political_focus");
        }

        for (auto& mod : opt.modifiers) {
            score *= mod.multiplier;
        }

        return score;
    }
};
```

**Configuration Company** :
```json
{
  "company_ai_weights": {
    "innovation": 0.7,
    "risk_aversion": 0.4,
    "political_focus": 0.6,
    "profit_maximization": 0.8,
    "quality_focus": 0.6
  }
}
```

#### StateAIModule

**Responsabilité** : Décisions étatiques (semaines/mois)

**Décisions prises** :
- Achats militaires
- Alliances diplomatiques
- Budgets sectoriels
- Objectifs stratégiques

**Dépendances** :
- DiplomacyModule (relations)
- EconomyModule (budget disponible)
- OperationalModule (besoins militaires)

**Exemple Décision** :
```cpp
class StateMilitaryPurchaseDecision : public IDecision {
    std::vector<Option> generateOptions() override {
        std::vector<Option> purchases;

        // Pour chaque Company
        for (auto& company : companies) {
            // Vérifier relation diplomatique
            float relation = diplomacy->getRelation(state_id, company.id);
            if (relation < 0.3f) continue; // Trop mauvaise relation

            // Pour chaque véhicule disponible
            for (auto& vehicle : company.catalog) {
                Option opt;
                opt.type = "purchase";
                opt.parameters["company_id"] = company.id;
                opt.parameters["vehicle_id"] = vehicle.id;
                opt.parameters["price"] = vehicle.price;
                opt.parameters["performance"] = vehicle.combat_rating;
                opt.base_score = 0.5f;

                // Modifiers
                if (relation > 0.8f) {
                    opt.modifiers.push_back({"good_relations", 1.2f});
                }
                if (company.reputation > 0.9f) {
                    opt.modifiers.push_back({"trusted_brand", 1.1f});
                }

                purchases.push_back(opt);
            }
        }

        return purchases;
    }

    float scoreOption(const Option& opt, const Context& ctx) override {
        float score = opt.base_score;

        float price = opt.parameters["price"];
        float performance = opt.parameters["performance"];
        float value = performance / price;

        score += value * weights.get("cost_effectiveness");
        score += performance * weights.get("quality_priority");

        // Influence politique
        CompanyId company = opt.parameters["company_id"];
        float influence = diplomacy->getInfluence(company, state_id);
        score += influence * weights.get("lobbying_susceptibility");

        for (auto& mod : opt.modifiers) {
            score *= mod.multiplier;
        }

        return score;
    }
};
```

**Configuration State** :
```json
{
  "state_ai_weights": {
    "cost_effectiveness": 0.6,
    "quality_priority": 0.7,
    "lobbying_susceptibility": 0.4,
    "strategic_autonomy": 0.5
  }
}
```

## Decision Factory

### Création Dynamique

```cpp
class DecisionFactory {
public:
    // Enregistrer types de décisions
    static void registerDecision(const std::string& type, DecisionCreator creator);

    // Créer décision par nom
    static IDecision* create(
        const std::string& type,
        const Context& ctx,
        const Weights& weights
    );

    // Créer avec smart pointer
    static std::unique_ptr<IDecision> createUnique(
        const std::string& type,
        const Context& ctx,
        const Weights& weights
    );

private:
    static std::map<std::string, DecisionCreator> registry;
};

// Type pour fonction de création
using DecisionCreator = std::function<IDecision*(const Context&, const Weights&)>;
```

### Enregistrement Décisions

```cpp
// Dans l'initialisation du module
void TacticalModule::initialize() {
    DecisionFactory::registerDecision("flanking", [](auto ctx, auto weights) {
        return new FlankingDecision(ctx, weights);
    });

    DecisionFactory::registerDecision("frontal_assault", [](auto ctx, auto weights) {
        return new FrontalAssaultDecision(ctx, weights);
    });

    DecisionFactory::registerDecision("retreat", [](auto ctx, auto weights) {
        return new RetreatDecision(ctx, weights);
    });
}
```

### Chargement depuis Modules .so

```cpp
// Hot-reload de nouveaux types de décisions
void AIFramework::loadDecisionModule(const std::string& module_path) {
    void* handle = dlopen(module_path.c_str(), RTLD_LAZY);

    // Récupérer fonction d'enregistrement
    auto registerFunc = (RegisterDecisionsFunc)dlsym(handle, "registerDecisions");

    // Enregistrer les décisions du module
    registerFunc(DecisionFactory::getInstance());
}
```

## Reinforcement Learning Integration

### Ajustement des Poids

Le système RL ajuste les poids selon résultats des décisions :

```cpp
class RLEngine {
public:
    // Enregistrer une décision et son outcome
    void recordDecision(
        const std::string& decision_type,
        const Weights& weights_used,
        const Option& chosen_option,
        float outcome_reward  // -1.0 à +1.0
    );

    // Ajuster poids selon historical performance
    Weights adjustWeights(
        const std::string& decision_type,
        const Weights& current_weights,
        float learning_rate = 0.1f
    );

    // Obtenir poids optimisés pour contexte
    Weights getOptimizedWeights(
        const std::string& decision_type,
        const Context& ctx
    );

private:
    struct DecisionRecord {
        Weights weights;
        Option option;
        float reward;
        Context context;
    };

    std::map<std::string, std::vector<DecisionRecord>> history;
};
```

### Exemple RL Tactique

```cpp
// Enregistrer décision
auto decision = new FlankingDecision(ctx, current_weights);
Option best = decision->chooseBest();
Action action = decision->execute(best);
delete decision;

// Observer résultat combat
float outcome = evaluateCombatOutcome(); // -1.0 (défaite) à +1.0 (victoire)

// Enregistrer pour RL
rlEngine->recordDecision("flanking", current_weights, best, outcome);

// Ajuster poids pour prochaine fois
Weights new_weights = rlEngine->adjustWeights("flanking", current_weights);
saveWeights("tactical_flanking_weights.json", new_weights);
```

### Poids Initiaux (Manuels)

**Important** : En V1, pas de training automatique. Poids configurés manuellement dans JSON.

```json
// config/ai/tactical_initial_weights.json
{
  "flanking": {
    "safety": 0.4,
    "caution": 0.3,
    "aggression": 0.7,
    "speed": 0.6
  },
  "frontal_assault": {
    "safety": 0.2,
    "caution": 0.1,
    "aggression": 0.9,
    "overwhelming_force": 0.8
  },
  "retreat": {
    "safety": 0.9,
    "caution": 0.8,
    "preservation": 0.9
  }
}
```

Le RL ajuste ces valeurs au fil du temps selon expérience.

## Performance et Optimisation

### Object Pooling

Pour éviter new/delete fréquents :

```cpp
class DecisionPool {
public:
    template<typename T>
    T* acquire(const Context& ctx, const Weights& weights) {
        if (pool.empty()) {
            return new T(ctx, weights);
        }
        T* obj = pool.back();
        pool.pop_back();
        obj->reset(ctx, weights);
        return obj;
    }

    template<typename T>
    void release(T* obj) {
        pool.push_back(obj);
    }

private:
    std::vector<IDecision*> pool;
};
```

**Usage** :
```cpp
auto decision = decisionPool->acquire<FlankingDecision>(ctx, weights);
Option best = decision->chooseBest();
decisionPool->release(decision);
```

### Parallélisation

Évaluer plusieurs décisions simultanément :

```cpp
std::vector<Option> evaluateDecisionsParallel(
    const std::vector<std::string>& decision_types,
    const Context& ctx,
    const Weights& weights
) {
    std::vector<std::future<Option>> futures;

    for (auto& type : decision_types) {
        futures.push_back(std::async(std::launch::async, [&]() {
            auto decision = DecisionFactory::createUnique(type, ctx, weights);
            return decision->chooseBest();
        }));
    }

    std::vector<Option> results;
    for (auto& future : futures) {
        results.push_back(future.get());
    }

    return results;
}
```

### Performance Targets

- **TacticalModule** : 60 décisions/seconde (temps-réel combat)
- **OperationalModule** : 10 décisions/seconde (moins fréquent)
- **CompanyAI** : 1 décision/seconde (batch processing)
- **StateAI** : 0.1 décision/seconde (décisions rares)

## Intégration Architecture Modulaire

### AI Framework comme Module

```cpp
class AIFrameworkModule : public IModule {
public:
    void initialize() override {
        // Charger configurations
        loadDoctrines("config/doctrines/");
        loadWeights("config/ai/");

        // Enregistrer décisions
        registerAllDecisions();

        // Initialiser RL engine
        rlEngine = new RLEngine();
    }

    json process(const json& input) override {
        // Traiter requêtes de décision
        std::string decision_type = input["decision_type"];
        Context ctx = Context::fromJson(input["context"]);
        Weights weights = getWeights(decision_type);

        auto decision = DecisionFactory::createUnique(decision_type, ctx, weights);
        Option best = decision->chooseBest();

        json output;
        output["chosen_option"] = best.toJson();
        return output;
    }

    void shutdown() override {
        delete rlEngine;
    }
};
```

### Communication avec Autres Modules

**TacticalModule demande décision** :

```cpp
// TacticalModule process()
json request;
request["decision_type"] = "flanking";
request["context"] = currentContext.toJson();

json response = sendToModule("ai_framework", request);
Option chosen = Option::fromJson(response["chosen_option"]);

// Exécuter
executeOption(chosen);
```

**OperationalModule configure TacticalModule** :

```cpp
// OperationalModule choisit posture
auto decision = new OperationalPostureDecision(ctx, weights);
Option posture = decision->chooseBest();

// Envoyer directive à TacticalModule
json directive;
directive["posture"] = posture.parameters["name"];
directive["weight_adjustments"] = calculateAdjustments(posture);

sendToModule("tactical", directive);
```

## Configuration et Données

### Structure Fichiers Config

```
config/
├── ai/
│   ├── tactical_weights.json
│   ├── operational_weights.json
│   ├── company_weights.json
│   └── state_weights.json
├── doctrines/
│   ├── ussr.json
│   ├── nato.json
│   ├── china.json
│   └── guerrilla.json
└── rl/
    ├── learning_rates.json
    └── reward_functions.json
```

### Exemple Configuration Complète

**config/ai/tactical_weights.json** :
```json
{
  "flanking": {
    "safety": 0.4,
    "caution": 0.3,
    "aggression": 0.7,
    "speed": 0.6,
    "stealth": 0.5
  },
  "frontal_assault": {
    "safety": 0.2,
    "caution": 0.1,
    "aggression": 0.9,
    "overwhelming_force": 0.8,
    "speed": 0.4
  },
  "suppression": {
    "safety": 0.6,
    "rate_of_fire": 0.9,
    "ammunition_conservation": 0.3,
    "area_denial": 0.8
  },
  "retreat": {
    "safety": 0.9,
    "caution": 0.8,
    "preservation": 0.9,
    "speed": 0.7,
    "covering_fire": 0.6
  }
}
```

**config/doctrines/ussr.json** (complet) :
```json
{
  "name": "USSR Deep Battle Doctrine",
  "description": "Emphasis on overwhelming force, combined arms, and continuous offensive operations",

  "operational_weights": {
    "deep_battle": 0.8,
    "overwhelming_assault": 0.9,
    "echeloned_attack": 0.7,
    "mobile_defense": 0.4,
    "raid_cavalry": 0.3,
    "infiltration": 0.2,
    "attritional_warfare": 0.6
  },

  "tactical_weights": {
    "frontal_assault": 0.8,
    "flanking": 0.5,
    "combined_arms": 0.7,
    "artillery_preparation": 0.9,
    "retreat_threshold": 0.2,
    "counterattack": 0.7,
    "urban_combat": 0.6
  },

  "resource_priorities": {
    "armor_quantity": 0.9,
    "artillery": 0.8,
    "infantry_mass": 0.7,
    "air_support": 0.5,
    "logistics": 0.6
  },

  "special_characteristics": {
    "accepts_high_casualties": true,
    "prefers_night_operations": true,
    "emphasizes_political_officers": true
  }
}
```

**config/doctrines/nato.json** (complet) :
```json
{
  "name": "NATO AirLand Battle Doctrine",
  "description": "Deep strike, maneuver warfare, and combined arms with heavy air integration",

  "operational_weights": {
    "airland_battle": 0.9,
    "maneuver_warfare": 0.8,
    "deep_strike": 0.7,
    "defensive_depth": 0.6,
    "overwhelming_assault": 0.4,
    "mobile_defense": 0.6,
    "decapitation_strike": 0.7
  },

  "tactical_weights": {
    "frontal_assault": 0.3,
    "flanking": 0.9,
    "combined_arms": 0.9,
    "artillery_preparation": 0.6,
    "retreat_threshold": 0.6,
    "air_strikes": 0.9,
    "precision_engagement": 0.8
  },

  "resource_priorities": {
    "armor_quality": 0.9,
    "air_superiority": 0.9,
    "precision_munitions": 0.8,
    "C4ISR": 0.9,
    "logistics": 0.8
  },

  "special_characteristics": {
    "accepts_high_casualties": false,
    "prefers_technology_advantage": true,
    "emphasizes_initiative": true
  }
}
```

## Évolution Future

### Version 2 : Apprentissage Actif

- **Auto-training** : RL s'entraîne via simulations automatiques
- **Meta-learning** : Adaptation rapide à nouvelles situations
- **Transfer learning** : Connaissances transférées entre doctrines

### Version 3 : Comportements Émergents

- **Genetic algorithms** : Companies/States évoluent génération par génération
- **Multi-agent RL** : Plusieurs IA apprennent en compétition/coopération
- **Adaptive doctrines** : Doctrines mutent selon expérience

### Version 4 : Neural Networks

- **Deep RL** : Réseaux neurones pour décisions complexes
- **Pattern recognition** : Reconnaître situations similaires historiques
- **Predictive modeling** : Anticiper actions adversaires

## Références Croisées

- `systeme-militaire.md` : Combat, véhicules, doctrines militaires
- `economie-logistique.md` : Marché, pricing, supply chains
- `architecture-modulaire.md` : Intégration modules, hot-reload
- `systeme-sauvegarde.md` : Persistence états IA, poids RL

## Exemples Pratiques

### Exemple Complet : Décision Tactique

```cpp
// Contexte bataille
Context ctx;
ctx.world_state = {
    {"terrain", "open_plains"},
    {"weather", "clear"},
    {"time_of_day", "dawn"}
};
ctx.entities = {
    {"my_units", {{"tanks", 10}, {"ifv", 5}}},
    {"enemy_units", {{"tanks", 8}, {"infantry", 20}}}
};
ctx.objectives = {
    {"primary", "secure_hill"},
    {"secondary", "minimize_casualties"}
};
ctx.doctrine = doctrineManager->getDoctrine("nato");

// Charger poids
Weights weights = loadWeights("config/ai/tactical_weights.json", "flanking");

// Créer décision
auto decision = DecisionFactory::createUnique("flanking", ctx, weights);

// Générer et évaluer options
std::vector<Option> options = decision->generateOptions();
for (auto& opt : options) {
    float score = decision->scoreOption(opt, ctx);
    LOG_DEBUG("Option: {} - Score: {}", opt.type, score);
}

// Choisir meilleure
Option best = decision->chooseBest();
LOG_INFO("Chosen: {} (score: {})", best.type, best.base_score);

// Exécuter
Action action = decision->execute(best);

// Observer résultat et apprendre
float outcome = waitForBattleResult();
rlEngine->recordDecision("flanking", weights, best, outcome);
```

### Exemple : Company AI Investment

```cpp
// Contexte company
Context ctx;
ctx.world_state = {
    {"market_demand", "high"},
    {"tech_level", "gen3"},
    {"competition", "moderate"}
};
ctx.entities = {
    {"budget", 1000000},
    {"reputation", 0.75},
    {"research_capacity", 5}
};

Weights weights = companyProfile.weights; // Profil company unique

auto decision = new CompanyInvestmentDecision(ctx, weights);
Option investment = decision->chooseBest();

if (investment.type == "research") {
    TechId tech = investment.parameters["tech_id"];
    startResearch(tech);
}
else if (investment.type == "lobbying") {
    StateId state = investment.parameters["state_id"];
    float cost = investment.parameters["cost"];
    lobbyState(state, cost);
}

delete decision;
```

## Testing et Validation

### Test Unitaire Decision

```cpp
#ifdef TESTING
void testFlankingDecision() {
    // Setup contexte test
    Context ctx = createTestContext();
    Weights weights = {{"safety", 0.5}, {"aggression", 0.8}};

    // Créer décision
    auto decision = new FlankingDecision(ctx, weights);

    // Vérifier génération options
    auto options = decision->generateOptions();
    assert(options.size() > 0);

    // Vérifier scoring
    for (auto& opt : options) {
        float score = decision->scoreOption(opt, ctx);
        assert(score >= 0.0f && score <= 1.0f);
    }

    // Vérifier choix cohérent
    Option best = decision->chooseBest();
    assert(best.type == "flanking");

    delete decision;
}
#endif
```

### Benchmark Performance

```cpp
void benchmarkDecisionSpeed() {
    Context ctx = createBenchmarkContext();
    Weights weights = loadWeights("tactical_weights.json", "flanking");

    auto start = std::chrono::high_resolution_clock::now();

    for (int i = 0; i < 1000; i++) {
        auto decision = new FlankingDecision(ctx, weights);
        Option best = decision->chooseBest();
        delete decision;
    }

    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);

    std::cout << "1000 decisions in " << duration.count() << "μs\n";
    std::cout << "Average: " << (duration.count() / 1000.0f) << "μs per decision\n";
}
```
