# Calcul de Menace Contextuelle ## Vue d'Ensemble Le système de calcul de menace évalue la **dangerosité qu'une entité représente pour une autre** en analysant non seulement les forces brutes, mais aussi les capacités défensives, la qualité des équipements, et la production industrielle. ### Principes Fondamentaux - **Contextuel** : Menace calculée selon capacités **des deux parties** - **Asymétrique** : A menace B ≠ B menace A - **Sword & Shield** : Qualité défenses peut annuler supériorité numérique - **Production** : Capacité industrielle = menace future - **Multi-domaines** : Terre, air, mer évalués séparément puis agrégés ## Échelle de Menace **Valeurs** : `0` à `2 000 000+` (pas de maximum strict, type `int32_t`) **Ordres de grandeur** : - `0` : Aucune menace - `100 - 1 000` : PMC petit - `5 000 - 50 000` : Company moyenne - `100 000` : État petit - `500 000` : État moyen (France, UK, Allemagne) - `900 000` : Superpower (USA, Chine, Russie) - `1 000 000+` : Menace existentielle ## Architecture Calcul ### Formule Globale ```cpp int calculateThreat(Entity attacker, Entity defender) { auto params = attacker.getThreatParams(); // Composantes int current_military = evaluateCurrentForces(attacker, defender); int production_capacity = evaluateProduction(attacker, defender, params.projection_months); // Pondération configurable par entité return current_military * params.current_weight + production_capacity * params.production_weight; } struct ThreatCalculationParams { int projection_months = 12; // Horizon projection (défaut 12 mois) float current_weight = 0.6f; // Poids forces actuelles (60%) float production_weight = 0.4f; // Poids production (40%) }; ``` **Personnalisation par entité** : - Company **agressive** : `current: 0.8, production: 0.2` (focus court-terme) - State **prudent** : `current: 0.4, production: 0.6` (focus long-terme) - PMC **réactif** : `current: 0.9, production: 0.1` (menace immédiate prioritaire) ## Évaluation Forces Actuelles ### Principe : Sword & Shield 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 ```cpp int evaluateCurrentForces(Entity attacker, Entity defender) { int land_threat = evaluateLandThreat(attacker, defender); int air_threat = evaluateAirThreat(attacker, defender); int naval_threat = evaluateNavalThreat(attacker, defender); return land_threat + air_threat + naval_threat; } ``` ### Évaluation Domaine Terrestre #### Inventaire Forces **Attaquant** : ```cpp struct LandForces { std::vector tanks; std::vector ifvs; std::vector apcs; std::vector artillery; std::vector infantry; }; ``` **Défenseur** : ```cpp struct LandDefenses { std::vector anti_tank; // Systèmes anti-char std::vector counter_tanks; // Tanks défensifs std::vector anti_tank_inf; // Infanterie AT std::vector fortifications; }; ``` #### Couples Équipement ↔ Contre-mesures **Principe** : Chaque type d'équipement offensif a des contre-mesures spécifiques. ```cpp struct EquipmentCounters { std::map> counters = { {TANK, {AT_MISSILE, AT_GUN, COUNTER_TANK, AT_INFANTRY}}, {IFV, {AT_MISSILE, AT_GUN, AUTOCANNON}}, {APC, {AUTOCANNON, MACHINE_GUN, RPG}}, {INFANTRY, {MACHINE_GUN, ARTILLERY, AUTOCANNON}}, {ARTILLERY, {COUNTER_BATTERY, AIR_STRIKE}} }; }; ``` #### É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** ```cpp float calculateDefensiveEffectiveness( std::vector swords, std::vector shields ) { float total_sword_value = 0; float neutralized_value = 0; for (auto& sword : swords) { float sword_value = sword.quantity * sword.quality; total_sword_value += sword_value; // Trouver défenses applicables auto applicable_shields = findApplicableDefenses(sword, shields); // Calculer valeur défensive totale contre ce sword float shield_value = 0; for (auto& shield : applicable_shields) { float shield_effectiveness = calculateShieldEffectiveness(shield, sword); shield_value += shield.quantity * shield.quality * shield_effectiveness; } // Neutralisation proportionnelle float neutralization = min(1.0f, shield_value / sword_value); neutralized_value += sword_value * neutralization; } return total_sword_value > 0 ? (neutralized_value / total_sword_value) : 0.0f; } ``` **Étape 3 : Score Final** ```cpp int evaluateLandThreat(Entity attacker, Entity defender) { auto swords = attacker.getLandForces(); auto shields = defender.getLandDefenses(); // Menace brute (sans défenses) int raw_threat = 0; for (auto& sword : swords) { raw_threat += sword.quantity * sword.combat_value; } // Réduction par défenses float defensive_effectiveness = calculateDefensiveEffectiveness(swords, shields); // Menace finale int final_threat = raw_threat * (1.0f - defensive_effectiveness); return final_threat; } ``` ### Exemples Concrets Terre #### Exemple 1 : Qualité Domine Quantité **Attaquant** : - 20 tanks Gen4 (Leopard 2A7) - Armure composite avancée - Génération 4 - Combat value : 1000/tank - Menace brute : 20 × 1000 = 20 000 **Défenseur** : - 100 000 AT missiles Gen2 - Anciens, inefficaces contre armure Gen4 - `canCounter()` retourne `false` - Défense applicable : 0 **Résultat** : ``` defensive_effectiveness = 0 / 20000 = 0% final_threat = 20000 × (1 - 0) = 20 000 ``` → **Menace élevée** : Défenses obsolètes inefficaces #### Exemple 2 : Quantité + Qualité Écrasent **Attaquant** : - 1000 tanks Gen2 - Armure standard - Combat value : 400/tank - Menace brute : 1000 × 400 = 400 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 **Résultat** : ``` defensive_effectiveness = 360000 / 400000 = 90% final_threat = 400000 × (1 - 0.9) = 40 000 ``` → **Menace faible** : Défenses qualitatives réduisent massavement #### Exemple 3 : Masse Insuffisante **Attaquant** : - 1000 tanks Gen2 - Combat value : 400/tank - Menace brute : 400 000 **Défenseur** : - 20 AT missiles Gen4 - Très efficaces mais **pas assez nombreux** - Shield value : 20 × 800 × 0.9 = 14 400 **Résultat** : ``` defensive_effectiveness = 14400 / 400000 = 3.6% final_threat = 400000 × (1 - 0.036) = 385 440 ``` → **Menace reste élevée** : Pas assez de défenses pour couvrir la masse ### Évaluation Domaine Aérien #### Spécificités Air **Complexité supplémentaire** : - **Qualité prime** : Quelques jets furtifs Gen4 dominent des centaines AA Gen2 - **ECM/ECCM** : Guerre électronique critique - **Compatibilité stricte** : AA anti-hélicoptère ne touche pas jets ```cpp struct AirForces { std::vector fighters; std::vector bombers; std::vector helicopters; std::vector drones; // Capacités spéciales bool has_stealth; bool has_ecm; // Electronic Counter-Measures int electronic_warfare_level; }; struct AirDefenses { std::vector aa_missiles; std::vector aa_guns; std::vector interceptors; // Capacités bool has_eccm; // Electronic Counter-Counter-Measures int radar_quality; std::map capabilities; // Quoi peut toucher quoi }; enum TargetCapability { HELICOPTER_ONLY, // Seulement hélicoptères LOW_ALTITUDE, // Avions basse altitude HIGH_ALTITUDE, // Avions haute altitude ALL_AIRCRAFT // Tous types }; ``` #### Compatibilité Systèmes ```cpp bool canEngageAircraft(AASystem aa, Aircraft aircraft) { // Vérifier compatibilité type switch (aa.capability) { case HELICOPTER_ONLY: return aircraft.type == HELICOPTER; case LOW_ALTITUDE: return aircraft.altitude < 5000; // mètres case HIGH_ALTITUDE: return aircraft.altitude > 5000; case ALL_AIRCRAFT: return true; } // Vérifier guerre électronique 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é } } // 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é } } return true; } ``` #### Exemple Air : Furtivité Domine **Attaquant** : - 20 jets furtifs Gen4 (F-35) - Stealth rating : 0.9 (réduit détection 90%) - ECM avancé - 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 ``` defensive_effectiveness = 150000 / 40000 = ... wait, > 1.0 ! → Plafonné à min(1.0, value) defensive_effectiveness = min(1.0, 150000/40000) = 1.0... ERREUR dans mon calcul ! ``` **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 **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. ## Évaluation Production ### Principe La menace ne vient pas seulement des forces actuelles, mais aussi de la **capacité à produire** plus d'équipements. ```cpp int evaluateProduction(Entity attacker, Entity defender, int projection_months) { int production_threat = 0; // Pour chaque type d'équipement for (auto& equipment_type : all_equipment_types) { // Taux production attaquant int attacker_rate = attacker.getProductionRate(equipment_type); // unités/mois // Taux production défenses défenseur int defender_rate = defender.getProductionRate(getCounterType(equipment_type)); // Projection future int attacker_produced = attacker_rate * projection_months; int defender_produced = defender_rate * projection_months; // Menace nette production int net_production = attacker_produced - defender_produced; if (net_production > 0) { int equipment_value = getEquipmentValue(equipment_type); production_threat += net_production * equipment_value; } } return production_threat; } ``` ### Exemple Production **État A** : - Production actuelle : 50 tanks/mois - Projection 12 mois : 600 tanks - Combat value : 400/tank - Production threat : 600 × 400 = 240 000 **État B** (défenseur) : - Production AT : 100 missiles/mois - Projection 12 mois : 1200 missiles - Combat value : 300/missile - Défense production : 1200 × 300 = 360 000 **Net production threat** : ``` Attacker gain : 240 000 Defender gain : 360 000 Net : 240 000 - 360 000 = -120 000 (négatif = défenseur gagne) production_threat = max(0, net) = 0 ``` → É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 ```cpp int calculateThreat(Entity attacker, Entity defender) { auto params = attacker.getThreatParams(); // Forces actuelles (sword & shield par domaine) int land_threat = evaluateLandThreat(attacker, defender); int air_threat = evaluateAirThreat(attacker, defender); int naval_threat = evaluateNavalThreat(attacker, defender); int current_military = land_threat + air_threat + naval_threat; // Production future int production_threat = evaluateProduction( attacker, defender, params.projection_months ); // Pondération finale int total_threat = current_military * params.current_weight + production_threat * params.production_weight; return total_threat; } ``` ### Exemples Complets #### Superpower vs État Moyen **USA vs France** **USA forces** : - Tanks : 8000 (Gen3-4) → 3 200 000 - Aircraft : 2000 (Gen4, furtifs) → 4 000 000 - Naval : 500 ships → 2 500 000 - **Total brut** : 9 700 000 **France défenses** : - AT systems : 3000 (Gen3) → Shield 50% tanks - AA systems : 1500 (Gen3) → Shield 30% aircraft - Naval defenses : 200 → Shield 40% 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 **Production (12 mois)** : - USA : +600 tanks, +100 aircraft → 360 000 - France : +100 tanks, +50 aircraft → 70 000 - **Net production** : 290 000 **Total (60% current, 40% prod)** : ``` 5 900 000 × 0.6 + 290 000 × 0.4 = 3 656 000 ``` → **Menace colossale**, mais France peut tenir avec alliances #### PMC vs Company **PMC_Alpha vs RheinmetallCorp** **PMC forces** : - Infantry : 500 (léger armement) - Vehicles : 20 APCs - **Total** : 50 000 **Rheinmetall défenses** : - Security : 100 guards - Fortifications : minimal - **Shield** : 5% **Threat** : 50 000 × 0.95 = 47 500 → PMC peut menacer installations Company, mais pas capacités production ## Cas Spéciaux ### Menace Économique Pure Pour Companies sans capacités militaires : ```cpp int calculateEconomicThreat(Company attacker, Company defender) { // Part de marché float market_dominance = attacker.market_share / (defender.market_share + 0.01f); // Capacité production float production_ratio = attacker.production_capacity / defender.production_capacity; // Qualité produits float quality_advantage = attacker.avg_product_quality / defender.avg_product_quality; // Menace économique int economic_threat = (market_dominance * 100000) + (production_ratio * 80000) + (quality_advantage * 50000); return economic_threat; } ``` ### Menace Géographique Distance géographique module menace : ```cpp float getGeographicModifier(Entity attacker, Entity defender) { float distance_km = calculateDistance(attacker.position, defender.position); // Projection power diminue avec distance if (distance_km < 500) { return 1.0f; // Menace pleine } else if (distance_km < 2000) { return 0.7f; // 30% réduction } else if (distance_km < 5000) { return 0.4f; // 60% réduction } else { return 0.1f; // 90% réduction (trop loin) } } ``` ## Performance et Optimisation ### Cache Threat ```cpp class ThreatCache { private: struct CachedThreat { int value; int timestamp; int ttl = 3600; // 1 heure }; std::map, CachedThreat> cache; public: int getThreat(EntityId attacker, EntityId defender) { auto key = std::make_pair(attacker, defender); if (cache.contains(key)) { auto& cached = cache[key]; if (getCurrentTime() - cached.timestamp < cached.ttl) { return cached.value; } } // Recalculer int threat = calculateThreat(attacker, defender); cache[key] = {threat, getCurrentTime()}; return threat; } void invalidate(EntityId entity) { // Invalider tous les caches impliquant cette entité for (auto it = cache.begin(); it != cache.end();) { if (it->first.first == entity || it->first.second == entity) { it = cache.erase(it); } else { ++it; } } } }; ``` ### Invalidation Cache Événements invalidant cache : - Production nouvelle unité - Perte unité au combat - Nouvelle recherche technologique - Changement doctrine militaire ### Calcul Lazy ```cpp // Ne calculer que si demandé par IA int getThreatOnDemand(EntityId attacker, EntityId defender) { return threatCache.getThreat(attacker, defender); } // Pas de recalcul automatique chaque tick ``` ## Références Croisées - `systeme-diplomatique.md` : Utilisation menace dans relations diplomatiques - `ai-framework.md` : Menace influence décisions IA (achats, alliances) - `systeme-militaire.md` : Valeurs combat équipements, générations - `economie-logistique.md` : Production rates, capacités industrielles