- ai-framework.md: Unified decision framework with scoring system, RL integration, doctrines - systeme-diplomatique.md: Relations (shared), intentions (bilateral), threat, reliability systems - calcul-menace.md: Contextual threat calculation with sword & shield mechanics - systeme-sauvegarde.md: V1 save system with JSON, metachunks, module autonomy - module-versioning.md: Automatic MAJOR.MINOR.PATCH.BUILD versioning via CMake 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1091 lines
30 KiB
Markdown
1091 lines
30 KiB
Markdown
# Système Diplomatique
|
||
|
||
## Vue d'Ensemble
|
||
|
||
Le système diplomatique de Warfactory gère les relations entre toutes les entités du jeu : États (States), Compagnies (Companies), et PMCs. Il repose sur **quatre indicateurs numériques** distincts qui interagissent pour créer des comportements diplomatiques émergents et réalistes.
|
||
|
||
### Principes de Design
|
||
|
||
- **Relations partagées** : Une seule valeur relation entre deux entités, état actuel de la relation
|
||
- **Intentions bilatérales** : Chaque entité a sa propre intention envers l'autre
|
||
- **Intentions génèrent événements** : Intentions modifient le score relation partagé via événements
|
||
- **Menace contextuelle** : Évaluation sophistiquée des forces selon capacités défensives
|
||
- **Fiabilité globale** : Réputation qui se construit/détruit avec le temps
|
||
- **Traités comme objets** : Accords formalisés avec impact mécanique
|
||
|
||
## Les Quatre Indicateurs
|
||
|
||
### 1. Relations (Score Partagé)
|
||
|
||
**Définition** : Score unique représentant l'état actuel de la relation entre deux entités.
|
||
|
||
**Échelle** : `-1000` à `+1000`
|
||
- `-1000` : Hostilité maximale, guerre totale
|
||
- `-500` : Relations très mauvaises, sanctions, embargo
|
||
- `0` : Neutre, aucune relation particulière
|
||
- `+500` : Relations bonnes, coopération active
|
||
- `+1000` : Alliance parfaite, confiance totale
|
||
|
||
**Caractéristiques** :
|
||
- **Partagé** : `A ↔ B` = **une seule valeur** pour les deux entités
|
||
- **Par événements** : Score modifié uniquement via événements discrets
|
||
- **Entiers** : Valeurs entières pour garantir balance exacte
|
||
- **Persistant** : Sauvegardé avec historique événements
|
||
- **État, pas intention** : Représente situation actuelle, pas désirs futurs
|
||
|
||
#### Structure Données
|
||
|
||
```cpp
|
||
struct Relationship {
|
||
std::pair<EntityId, EntityId> entities; // Paire ordonnée (smaller_id, larger_id)
|
||
int score; // -1000 à +1000
|
||
std::vector<Event> events; // Historique complet
|
||
int decay_target; // Calculé depuis traités
|
||
};
|
||
|
||
struct Event {
|
||
EventType type;
|
||
int value; // Impact sur score (-500 à +500)
|
||
EntityId source; // Qui a généré l'événement
|
||
int date; // Timestamp événement
|
||
std::string description; // Pour logs/UI
|
||
};
|
||
|
||
// Accès relation (ordre des IDs n'importe pas)
|
||
int getRelation(EntityId a, EntityId b) {
|
||
auto key = makeRelationKey(a, b); // Ordre normalisé
|
||
return relationships[key].score;
|
||
}
|
||
|
||
std::pair<EntityId, EntityId> makeRelationKey(EntityId a, EntityId b) {
|
||
return (a < b) ? std::make_pair(a, b) : std::make_pair(b, a);
|
||
}
|
||
```
|
||
|
||
#### Exemples Événements
|
||
|
||
**Événements Positifs** :
|
||
- `contract_fulfilled` : +100 (livraison contrat à temps)
|
||
- `military_aid` : +200 (aide militaire fournie)
|
||
- `tech_sharing` : +150 (partage technologie)
|
||
- `lobbying_success` : +50 (campagne lobbying réussie)
|
||
- `joint_operation` : +180 (opération militaire conjointe)
|
||
- `trade_agreement` : +120 (nouvel accord commercial)
|
||
|
||
**Événements Négatifs** :
|
||
- `contract_breach` : -150 (contrat non-honoré)
|
||
- `espionage_caught` : -300 (espionnage découvert)
|
||
- `reverse_engineering` : -200 (reverse-engineer produit acheté)
|
||
- `civilian_casualties` : -250 (dommages collatéraux)
|
||
- `embargo_violation` : -180 (violation embargo)
|
||
- `treaty_broken` : -500 (rupture traité formel)
|
||
|
||
**Événements Massifs** :
|
||
- `declaration_war` : -800
|
||
- `peace_treaty` : +400
|
||
- `alliance_formed` : +600
|
||
|
||
#### Decay Relations
|
||
|
||
Les relations ne restent pas fixes, elles **decay vers un score cible** déterminé par les traités actifs.
|
||
|
||
**Formule Decay Target** :
|
||
|
||
```cpp
|
||
int calculateDecayTarget(EntityId a, EntityId b) {
|
||
int target = 0; // Base neutre
|
||
|
||
// Somme bonus traités entre a et b
|
||
for (auto& treaty : getTreaties(a, b)) {
|
||
if (treaty.is_active) {
|
||
target += treaty.getDecayBonus();
|
||
}
|
||
}
|
||
|
||
return target;
|
||
}
|
||
|
||
// Exemples bonus traités
|
||
Alliance: +250
|
||
Partenariat militaire: +20
|
||
Accord commercial: +10
|
||
Non-agression: +5
|
||
```
|
||
|
||
**Application Decay** :
|
||
|
||
```cpp
|
||
void applyRelationDecay(Relationship& rel, float decay_rate) {
|
||
int target = calculateDecayTarget(rel.entities.first, rel.entities.second);
|
||
int delta = target - rel.score;
|
||
|
||
// Decay linéaire dans les deux sens
|
||
if (delta > 0) {
|
||
rel.score += min(delta, (int)(decay_rate * abs(delta)));
|
||
}
|
||
else if (delta < 0) {
|
||
rel.score += max(delta, -(int)(decay_rate * abs(delta)));
|
||
}
|
||
}
|
||
```
|
||
|
||
**Exemple Concret** :
|
||
|
||
```
|
||
USA ↔ France : Alliance active
|
||
Decay target = +250
|
||
Relation actuelle = +750
|
||
|
||
Sans nouveaux événements :
|
||
→ Decay vers 250 (descend progressivement)
|
||
→ Relation se normalise vers baseline alliance
|
||
|
||
Si relation = -100 (scandal temporaire) :
|
||
→ Decay vers 250 (remonte)
|
||
→ Alliance structure force retour relation positive
|
||
```
|
||
|
||
### 2. Intentions (Volonté Bilatérale)
|
||
|
||
**Définition** : Volonté d'une entité d'améliorer ou détériorer la relation partagée avec une autre.
|
||
|
||
**Échelle** : `-1000` à `+1000`
|
||
- `-1000` : Veut activement détruire la relation
|
||
- `-500` : Veut détériorer significativement
|
||
- `0` : Maintient status quo, neutre
|
||
- `+500` : Veut améliorer activement
|
||
- `+1000` : Veut maximiser la relation
|
||
|
||
**Caractéristiques** :
|
||
- **Bilatéral** : `A → B` différent de `B → A`
|
||
- **Indépendant du score** : Intention ≠ relation actuelle
|
||
- **Génère événements** : Intentions modifient le score relation partagé
|
||
- **Asymétrique** : Les deux entités peuvent avoir intentions opposées
|
||
- **Configurable** : IA ajuste intentions selon stratégie
|
||
|
||
#### Structure Données
|
||
|
||
```cpp
|
||
struct Intention {
|
||
EntityId from;
|
||
EntityId to;
|
||
int value; // -1000 à +1000
|
||
};
|
||
|
||
// Stockage séparé (deux intentions par paire d'entités)
|
||
std::map<std::pair<EntityId, EntityId>, int> intentions;
|
||
|
||
// Accès (ordre compte !)
|
||
int getIntention(EntityId from, EntityId to) {
|
||
return intentions[{from, to}];
|
||
}
|
||
|
||
void setIntention(EntityId from, EntityId to, int value) {
|
||
intentions[{from, to}] = clamp(value, -1000, 1000);
|
||
}
|
||
```
|
||
|
||
#### Génération Événements Automatique
|
||
|
||
Les intentions **génèrent des événements** qui modifient le score relation partagé :
|
||
|
||
```cpp
|
||
void processDailyIntentions() {
|
||
for (auto& [from_to, intention] : intentions) {
|
||
if (intention == 0) continue; // Neutre
|
||
|
||
EntityId from = from_to.first;
|
||
EntityId to = from_to.second;
|
||
|
||
// Probabilité événement proportionnelle à intention
|
||
float probability = abs(intention) / 1000.0f;
|
||
|
||
if (randomFloat() < probability * DAILY_EVENT_BASE_RATE) {
|
||
if (intention > 0) {
|
||
generatePositiveEvent(from, to, intention);
|
||
}
|
||
else {
|
||
generateNegativeEvent(from, to, abs(intention));
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void generatePositiveEvent(EntityId from, EntityId to, int intention) {
|
||
// Magnitude événement selon force intention
|
||
int magnitude = (intention / 200) * 10; // 0-50 par event
|
||
|
||
EventType type = selectPositiveEvent(from, to);
|
||
|
||
// Modifier la relation PARTAGÉE
|
||
addRelationEvent(from, to, {type, magnitude, from, getCurrentDate()});
|
||
}
|
||
|
||
void addRelationEvent(EntityId a, EntityId b, Event event) {
|
||
auto key = makeRelationKey(a, b);
|
||
auto& rel = relationships[key];
|
||
|
||
rel.score = clamp(rel.score + event.value, -1000, 1000);
|
||
rel.events.push_back(event);
|
||
}
|
||
```
|
||
|
||
#### Exemple Émergence : "Trump Effect"
|
||
|
||
```
|
||
Situation initiale :
|
||
USA ↔ Europe : score = +600 (alliance historique)
|
||
|
||
Intentions :
|
||
USA → Europe : -400 (Trump : protectionnisme)
|
||
Europe → USA : +200 (veut maintenir alliance)
|
||
|
||
Évolution sur 12 mois :
|
||
|
||
Mois 1-3 :
|
||
- USA intention -400 génère : tarifs (-30), critiques OTAN (-20)
|
||
- Europe intention +200 génère : concessions (+25), coopération (+15)
|
||
- Net : -30 -20 +25 +15 = -10
|
||
- Score : 600 → 590
|
||
|
||
Mois 4-6 :
|
||
- USA : nouvelles sanctions (-40), retrait accord (-30)
|
||
- Europe : aide militaire (+40), compromis commercial (+20)
|
||
- Net : -70 +60 = -10
|
||
- Score : 590 → 580
|
||
|
||
Mois 7-12 :
|
||
- Pattern continue, balance légèrement négative
|
||
- Score : 580 → 550
|
||
|
||
Résultat final :
|
||
USA ↔ Europe : score = +550
|
||
USA → Europe : intention = -400 (inchangée)
|
||
Europe → USA : intention = +200 (inchangée)
|
||
|
||
= Relation tendue mais alliance maintenue !
|
||
Europe compense partiellement hostilité USA
|
||
```
|
||
|
||
#### Balance des Intentions
|
||
|
||
```cpp
|
||
void evaluateRelationDynamics(EntityId a, EntityId b) {
|
||
int relation = getRelation(a, b);
|
||
int intention_a = getIntention(a, b);
|
||
int intention_b = getIntention(b, a);
|
||
|
||
// Prédire évolution
|
||
int net_intention = intention_a + intention_b;
|
||
|
||
if (net_intention > 0) {
|
||
// Relation va probablement s'améliorer
|
||
}
|
||
else if (net_intention < 0) {
|
||
// Relation va probablement se détériorer
|
||
}
|
||
else {
|
||
// Équilibre, relation stable (avec decay vers traités)
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Facteurs Influençant Intentions
|
||
|
||
**Pour Companies** :
|
||
- Opportunités commerciales (+)
|
||
- Concurrence marché (-)
|
||
- Influence politique désirée (+)
|
||
- Scandales récents (-)
|
||
- Relation actuelle (feedback)
|
||
|
||
**Pour States** :
|
||
- Alignement idéologique (+/-)
|
||
- Intérêts géopolitiques (+/-)
|
||
- Pression publique interne (+/-)
|
||
- Menace perçue (voir section Menace) (-)
|
||
- Dépendance économique (+)
|
||
|
||
**Pour PMCs** :
|
||
- Contrats disponibles (+)
|
||
- Réputation avec client (+)
|
||
- Compétition autres PMCs (-)
|
||
|
||
### 3. Menace (Score Contextuel)
|
||
|
||
**Définition** : Évaluation de la dangerosité qu'une entité représente pour une autre, basée sur capacités militaires ET industrielles.
|
||
|
||
**Échelle** : `0` à `2 000 000+` (pas de maximum strict)
|
||
- `0` : Aucune menace
|
||
- `1 000` : PMC petit
|
||
- `10 000` : Company moyenne
|
||
- `100 000` : État petit
|
||
- `500 000` : État moyen
|
||
- `900 000` : Superpower
|
||
- `1 000 000+` : Menace existentielle
|
||
|
||
**Caractéristiques** :
|
||
- **Contextuelle** : Calculée dynamiquement selon capacités des deux parties
|
||
- **Asymétrique** : A menace B ≠ B menace A
|
||
- **Multi-facteurs** : Forces actuelles + production + qualité
|
||
- **Non-persistée** : Recalculée à la demande
|
||
|
||
**Note** : Voir `calcul-menace.md` pour détails complets du système d'évaluation.
|
||
|
||
#### Impact Menace sur Intentions
|
||
|
||
```cpp
|
||
void adjustIntentionsByThreat(EntityId from, EntityId to) {
|
||
int threat = calculateThreat(to, from); // Menace de 'to' envers 'from'
|
||
|
||
if (threat > 500000) {
|
||
// Menace existentielle → chercher alliance ou confrontation
|
||
if (canAlly(from, to)) {
|
||
adjustIntention(from, to, +200); // Appeasement
|
||
} else {
|
||
adjustIntention(from, to, -300); // Préparation guerre
|
||
}
|
||
}
|
||
else if (threat > 200000) {
|
||
// Menace significative → prudence
|
||
adjustIntention(from, to, -100);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4. Fiabilité (Réputation Globale)
|
||
|
||
**Définition** : Réputation globale d'une entité, visible par tous. Représente la confiance générale dans le respect des engagements.
|
||
|
||
**Échelle** : `0` à `10 000`
|
||
- `0` : Totalement non-fiable, rompt tous engagements
|
||
- `2 500` : Réputation très mauvaise
|
||
- `5 000` : Neutre, moyenne
|
||
- `7 500` : Fiable, respecte engagements
|
||
- `10 000` : Parfaitement fiable, jamais rompu traité
|
||
|
||
**Caractéristiques** :
|
||
- **Globale** : Une seule valeur par entité, vue par tous
|
||
- **Lente à changer** : Événements ont impact modéré
|
||
- **Decay vers target** : Basé sur traités actifs et leur ancienneté
|
||
- **Critique pour diplomatie** : Influence volonté autres entités à traiter
|
||
|
||
#### Calcul Decay Target Fiabilité
|
||
|
||
```cpp
|
||
float calculateFiabilityTarget(Entity entity) {
|
||
float target = 0.50f; // Base 50% sans traités
|
||
|
||
for (auto& treaty : entity.getActiveTreaties()) {
|
||
int years = treaty.getDurationYears();
|
||
float bonus = min(years, 5) * 0.01f; // Max 5% par traité
|
||
target += bonus;
|
||
}
|
||
|
||
return min(target, 1.0f); // Plafonné à 100%
|
||
}
|
||
```
|
||
|
||
**Exemples** :
|
||
|
||
```
|
||
Aucun traité : 50% (5000)
|
||
|
||
1 alliance 1 an : 50% + 1% = 51% (5100)
|
||
1 alliance 5 ans : 50% + 5% = 55% (5500)
|
||
1 alliance 10 ans : 50% + 5% = 55% (5500) [plafond 5% atteint]
|
||
|
||
7 alliances 2 ans chacune : 50% + (7 × 2%) = 64% (6400)
|
||
10 alliances 5 ans chacune : 50% + (10 × 5%) = 100% (10000) [max]
|
||
```
|
||
|
||
#### Application Decay Fiabilité
|
||
|
||
```cpp
|
||
void applyFiabilityDecay(Entity& entity, float decay_rate) {
|
||
int target = calculateFiabilityTarget(entity) * 10000;
|
||
int delta = target - entity.fiability;
|
||
|
||
// Decay linéaire vers target
|
||
if (delta > 0) {
|
||
entity.fiability += min(delta, (int)(decay_rate * abs(delta)));
|
||
}
|
||
else if (delta < 0) {
|
||
entity.fiability += max(delta, -(int)(decay_rate * abs(delta)));
|
||
}
|
||
}
|
||
```
|
||
|
||
#### Événements Impactant Fiabilité
|
||
|
||
**Positifs (lents)** :
|
||
- `treaty_honored` : +10 (honorer traité existant)
|
||
- `contract_on_time` : +5 (livraison à temps)
|
||
- `transparency` : +15 (révélation volontaire problème)
|
||
|
||
**Négatifs (brutaux)** :
|
||
- `treaty_broken` : -500 (rupture traité formel)
|
||
- `contract_breach` : -200 (non-respect contrat)
|
||
- `espionage_caught` : -150 (espionnage allié découvert)
|
||
- `scandal` : -100 (scandale qualité/corruption)
|
||
|
||
#### Impact Fiabilité sur Intentions
|
||
|
||
```cpp
|
||
void adjustIntentionsBasedOnFiability(EntityId from, EntityId to) {
|
||
int fiability = getFiability(to);
|
||
|
||
// Fiabilité très haute → bonus intention
|
||
if (fiability > 8000) {
|
||
adjustIntention(from, to, +50);
|
||
}
|
||
|
||
// Fiabilité très basse → malus intention
|
||
if (fiability < 2000) {
|
||
adjustIntention(from, to, -50); // Méfiance
|
||
}
|
||
}
|
||
```
|
||
|
||
## Traités (Treaties)
|
||
|
||
### Définition
|
||
|
||
Les traités sont des **accords formalisés** entre deux entités, avec impact mécanique sur relations, decay, et fiabilité.
|
||
|
||
### Structure
|
||
|
||
```cpp
|
||
enum TreatyType {
|
||
ALLIANCE, // Alliance militaire complète
|
||
MILITARY_PARTNERSHIP, // Coopération militaire limitée
|
||
TRADE_AGREEMENT, // Accord commercial
|
||
NON_AGGRESSION, // Pacte non-agression
|
||
VASSALAGE, // Relation hiérarchique
|
||
EMBARGO, // Interdiction commerce
|
||
// ... autres types à définir
|
||
};
|
||
|
||
struct Treaty {
|
||
TreatyType type;
|
||
EntityId party_a;
|
||
EntityId party_b;
|
||
int start_date;
|
||
bool is_active;
|
||
json terms; // Conditions spécifiques
|
||
|
||
int getDurationYears() const {
|
||
if (!is_active) return 0;
|
||
return (getCurrentDate() - start_date) / 365;
|
||
}
|
||
|
||
float getFiabilityBonus() const {
|
||
if (!is_active) return 0.0f;
|
||
int years = getDurationYears();
|
||
return min(years, 5) * 0.01f;
|
||
}
|
||
|
||
int getDecayBonus() const {
|
||
switch (type) {
|
||
case ALLIANCE: return 250;
|
||
case MILITARY_PARTNERSHIP: return 20;
|
||
case TRADE_AGREEMENT: return 10;
|
||
case NON_AGGRESSION: return 5;
|
||
default: return 0;
|
||
}
|
||
}
|
||
};
|
||
```
|
||
|
||
### Cycle de Vie Traité
|
||
|
||
**1. Proposition** :
|
||
```cpp
|
||
TreatyProposal proposal = {
|
||
.type = ALLIANCE,
|
||
.proposer = entity_a,
|
||
.target = entity_b,
|
||
.terms = {...}
|
||
};
|
||
```
|
||
|
||
**2. Évaluation** :
|
||
```cpp
|
||
bool evaluateTreatyProposal(EntityId evaluator, TreatyProposal proposal) {
|
||
// Vérifier fiabilité proposeur
|
||
if (getFiability(proposal.proposer) < 4000) return false;
|
||
|
||
// Vérifier relation actuelle
|
||
int relation = getRelation(evaluator, proposal.proposer);
|
||
if (relation < 200) return false;
|
||
|
||
// Vérifier menace
|
||
int threat = calculateThreat(proposal.proposer, evaluator);
|
||
if (threat > 600000) return false;
|
||
|
||
// Vérifier intention
|
||
int intention = getIntention(evaluator, proposal.proposer);
|
||
return intention > 300;
|
||
}
|
||
```
|
||
|
||
**3. Activation** :
|
||
```cpp
|
||
void activateTreaty(Treaty& treaty) {
|
||
treaty.is_active = true;
|
||
treaty.start_date = getCurrentDate();
|
||
|
||
// Événement relation massif (modifie score partagé)
|
||
addRelationEvent(treaty.party_a, treaty.party_b, {
|
||
TREATY_SIGNED,
|
||
+400,
|
||
treaty.party_a, // Source événement
|
||
getCurrentDate()
|
||
});
|
||
|
||
// Impact fiabilité positif (les deux parties)
|
||
adjustFiability(treaty.party_a, +50);
|
||
adjustFiability(treaty.party_b, +50);
|
||
|
||
// Intentions deviennent positives
|
||
adjustIntention(treaty.party_a, treaty.party_b, +200);
|
||
adjustIntention(treaty.party_b, treaty.party_a, +200);
|
||
}
|
||
```
|
||
|
||
**4. Maintenance** :
|
||
```cpp
|
||
void maintainTreaty(Treaty& treaty) {
|
||
if (!treaty.is_active) return;
|
||
|
||
// Chaque année, petit bonus fiabilité
|
||
int years = treaty.getDurationYears();
|
||
if (years > last_check_year) {
|
||
adjustFiability(treaty.party_a, +5);
|
||
adjustFiability(treaty.party_b, +5);
|
||
last_check_year = years;
|
||
}
|
||
}
|
||
```
|
||
|
||
**5. Rupture** :
|
||
```cpp
|
||
void breakTreaty(Treaty& treaty, EntityId breaker) {
|
||
treaty.is_active = false;
|
||
|
||
EntityId victim = (breaker == treaty.party_a) ? treaty.party_b : treaty.party_a;
|
||
|
||
// Événement relation massif négatif (modifie score partagé)
|
||
addRelationEvent(breaker, victim, {
|
||
TREATY_BROKEN,
|
||
-500,
|
||
breaker,
|
||
getCurrentDate()
|
||
});
|
||
|
||
// Impact fiabilité brutal
|
||
adjustFiability(breaker, -500);
|
||
|
||
// Intentions deviennent hostiles
|
||
adjustIntention(victim, breaker, -400);
|
||
// Breaker peut garder intention positive (opportunisme)
|
||
}
|
||
```
|
||
|
||
## Interactions Entre Indicateurs
|
||
|
||
### Relations ↔ Intentions
|
||
|
||
```cpp
|
||
void updateIntentionsBasedOnRelations(EntityId from, EntityId to) {
|
||
int relation = getRelation(from, to);
|
||
int current_intention = getIntention(from, to);
|
||
|
||
// Si relation très basse mais intention neutre → générer hostilité
|
||
if (relation < -400 && current_intention > -200) {
|
||
adjustIntention(from, to, -150);
|
||
}
|
||
|
||
// Si relation très haute mais intention négative → ajuster (rare)
|
||
if (relation > 600 && current_intention < -200) {
|
||
// Situation incohérente, normaliser
|
||
adjustIntention(from, to, +100);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Intentions → Relations (via événements)
|
||
|
||
C'est le flux principal : intentions génèrent événements qui modifient relations.
|
||
|
||
```cpp
|
||
// Chaque jour/tick
|
||
void processDailyDiplomacy() {
|
||
// 1. Intentions génèrent événements
|
||
processDailyIntentions();
|
||
|
||
// 2. Relations decay vers traités
|
||
for (auto& rel : relationships) {
|
||
applyRelationDecay(rel, DECAY_RATE);
|
||
}
|
||
|
||
// 3. Fiabilité decay vers target
|
||
for (auto& entity : entities) {
|
||
applyFiabilityDecay(entity, FIABILITY_DECAY_RATE);
|
||
}
|
||
|
||
// 4. Ajustements feedback
|
||
for (auto& rel : relationships) {
|
||
updateIntentionsBasedOnRelations(rel.entities.first, rel.entities.second);
|
||
updateIntentionsBasedOnRelations(rel.entities.second, rel.entities.first);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Menace → Intentions
|
||
|
||
```cpp
|
||
void updateIntentionsBasedOnThreat(EntityId from, EntityId to) {
|
||
int threat = calculateThreat(to, from);
|
||
|
||
if (threat > 700000) {
|
||
// Menace existentielle → chercher alliances défensives
|
||
for (auto& potential_ally : getAllEntities()) {
|
||
if (isEnemyOf(potential_ally, to)) {
|
||
adjustIntention(from, potential_ally, +200);
|
||
}
|
||
}
|
||
|
||
// Hostile envers menaçant
|
||
adjustIntention(from, to, -300);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Fiabilité → Intentions
|
||
|
||
```cpp
|
||
void adjustIntentionsBasedOnFiability(EntityId from, EntityId to) {
|
||
int fiability = getFiability(to);
|
||
|
||
if (fiability > 8000) {
|
||
adjustIntention(from, to, +30); // Confiance
|
||
}
|
||
else if (fiability < 2000) {
|
||
adjustIntention(from, to, -50); // Méfiance
|
||
}
|
||
}
|
||
```
|
||
|
||
## Actions Diplomatiques
|
||
|
||
### Lobbying (Company → State)
|
||
|
||
```cpp
|
||
struct LobbyingAction {
|
||
CompanyId company;
|
||
StateId state;
|
||
int investment;
|
||
int duration_days;
|
||
};
|
||
|
||
void executeLobbyingCampaign(LobbyingAction action) {
|
||
int relation = getRelation(action.company, action.state);
|
||
int fiability = getFiability(action.company);
|
||
|
||
float success_chance =
|
||
(action.investment / 100000.0f) * 0.4f +
|
||
(relation / 1000.0f) * 0.3f +
|
||
(fiability / 10000.0f) * 0.3f;
|
||
|
||
if (randomFloat() < success_chance) {
|
||
// Succès : améliore relation partagée
|
||
addRelationEvent(action.company, action.state, {
|
||
LOBBYING_SUCCESS,
|
||
+50 + (action.investment / 10000),
|
||
action.company,
|
||
getCurrentDate()
|
||
});
|
||
|
||
// Augmente intention state envers company
|
||
adjustIntention(action.state, action.company, +30);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Sanctions (State → State/Company)
|
||
|
||
```cpp
|
||
void imposeSanctions(EntityId from, EntityId to, SanctionType type) {
|
||
// Impact relation partagée
|
||
addRelationEvent(from, to, {
|
||
SANCTIONS_IMPOSED,
|
||
-300,
|
||
from,
|
||
getCurrentDate()
|
||
});
|
||
|
||
// Impact économique
|
||
economyModule->applySanctions(to, type);
|
||
|
||
// Ajuste intentions (bilatéral)
|
||
adjustIntention(to, from, -200); // Victime hostile
|
||
adjustIntention(from, to, -100); // Sanctionneur aussi hostile
|
||
}
|
||
```
|
||
|
||
### Aide Militaire
|
||
|
||
```cpp
|
||
void provideMilitaryAid(EntityId from, EntityId to, MilitaryAid aid) {
|
||
int value = calculateAidValue(aid);
|
||
|
||
// Impact relation partagée
|
||
addRelationEvent(from, to, {
|
||
MILITARY_AID,
|
||
value / 1000,
|
||
from,
|
||
getCurrentDate()
|
||
});
|
||
|
||
// Améliore intention bénéficiaire
|
||
adjustIntention(to, from, +50);
|
||
}
|
||
```
|
||
|
||
## Intégration Architecture Modulaire
|
||
|
||
### DiplomacyModule Interface
|
||
|
||
```cpp
|
||
class DiplomacyModule : public IModule {
|
||
public:
|
||
// Relations (partagées)
|
||
int getRelation(EntityId a, EntityId b);
|
||
void addRelationEvent(EntityId a, EntityId b, Event event);
|
||
|
||
// Intentions (bilatérales)
|
||
int getIntention(EntityId from, EntityId to);
|
||
void setIntention(EntityId from, EntityId to, int intention);
|
||
void adjustIntention(EntityId from, EntityId to, int delta);
|
||
|
||
// Menace (calculée à la demande)
|
||
int calculateThreat(EntityId attacker, EntityId defender);
|
||
|
||
// Fiabilité (globale)
|
||
int getFiability(EntityId entity);
|
||
void adjustFiability(EntityId entity, int delta);
|
||
|
||
// Traités
|
||
std::vector<Treaty> getTreaties(EntityId entity);
|
||
bool proposeTreaty(TreatyProposal proposal);
|
||
void activateTreaty(Treaty& treaty);
|
||
void breakTreaty(Treaty& treaty, EntityId breaker);
|
||
|
||
// Process cycle
|
||
json process(const json& input) override;
|
||
};
|
||
```
|
||
|
||
### Communication avec Autres Modules
|
||
|
||
**CompanyAI consulte DiplomacyModule** :
|
||
|
||
```cpp
|
||
// Vérifier relation avant action
|
||
json request;
|
||
request["action"] = "get_relation";
|
||
request["entity_a"] = company_id;
|
||
request["entity_b"] = state_id;
|
||
|
||
json response = sendToModule("diplomacy", request);
|
||
int relation = response["relation"];
|
||
|
||
if (relation < 300) {
|
||
// Relation trop basse, lobbying prioritaire
|
||
adjustIntention(company_id, state_id, +300); // Améliorer intention
|
||
}
|
||
```
|
||
|
||
**StateAI utilise menace** :
|
||
|
||
```cpp
|
||
json request;
|
||
request["action"] = "calculate_threat";
|
||
request["attacker"] = potential_enemy_id;
|
||
request["defender"] = state_id;
|
||
|
||
json response = sendToModule("diplomacy", request);
|
||
int threat = response["threat"];
|
||
|
||
if (threat > 600000) {
|
||
// Menace haute, ajuster intentions défensives
|
||
adjustIntention(state_id, potential_enemy_id, -400);
|
||
}
|
||
```
|
||
|
||
## Sérialisation et Sauvegarde
|
||
|
||
### Format Relations
|
||
|
||
```json
|
||
{
|
||
"relations": {
|
||
"company_123 ↔ state_456": {
|
||
"score": 750,
|
||
"decay_target": 270,
|
||
"events": [
|
||
{
|
||
"type": "contract_fulfilled",
|
||
"value": 100,
|
||
"source": "company_123",
|
||
"date": 1735689600,
|
||
"description": "Livraison 50 tanks à temps"
|
||
},
|
||
{
|
||
"type": "lobbying_success",
|
||
"value": 50,
|
||
"source": "company_123",
|
||
"date": 1738368000,
|
||
"description": "Campagne lobbying réussie"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Format Intentions
|
||
|
||
```json
|
||
{
|
||
"intentions": {
|
||
"company_123 → state_456": 200,
|
||
"state_456 → company_123": -100
|
||
}
|
||
}
|
||
```
|
||
|
||
### Format Fiabilité
|
||
|
||
```json
|
||
{
|
||
"fiability": {
|
||
"company_123": {
|
||
"score": 6400,
|
||
"target": 6400,
|
||
"active_treaties_count": 7
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Format Traités
|
||
|
||
```json
|
||
{
|
||
"treaties": [
|
||
{
|
||
"id": "treaty_001",
|
||
"type": "ALLIANCE",
|
||
"party_a": "state_usa",
|
||
"party_b": "state_france",
|
||
"start_date": 1672531200,
|
||
"is_active": true,
|
||
"duration_years": 3,
|
||
"terms": {
|
||
"mutual_defense": true,
|
||
"trade_bonus": 0.15
|
||
}
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
## Performance et Optimisation
|
||
|
||
### Cache Menace
|
||
|
||
```cpp
|
||
class ThreatCache {
|
||
private:
|
||
struct CachedThreat {
|
||
int value;
|
||
int timestamp;
|
||
int ttl = 3600;
|
||
};
|
||
|
||
std::map<std::pair<EntityId, EntityId>, CachedThreat> cache;
|
||
|
||
public:
|
||
int getThreat(EntityId attacker, EntityId defender) {
|
||
auto key = std::make_pair(attacker, defender);
|
||
|
||
if (cache.contains(key) &&
|
||
getCurrentTime() - cache[key].timestamp < cache[key].ttl) {
|
||
return cache[key].value;
|
||
}
|
||
|
||
int threat = calculateThreat(attacker, defender);
|
||
cache[key] = {threat, getCurrentTime()};
|
||
return threat;
|
||
}
|
||
};
|
||
```
|
||
|
||
### Batch Processing Intentions
|
||
|
||
```cpp
|
||
void processDailyIntentions() {
|
||
std::vector<std::pair<EntityId, EntityId>> to_process;
|
||
|
||
// Collecter intentions non-nulles
|
||
for (auto& [from_to, intention] : intentions) {
|
||
if (intention != 0) {
|
||
to_process.push_back(from_to);
|
||
}
|
||
}
|
||
|
||
// Traiter en batch
|
||
for (auto& [from, to] : to_process) {
|
||
int intention = intentions[{from, to}];
|
||
processIntention(from, to, intention);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Decay Incrémental
|
||
|
||
```cpp
|
||
void applyDecayIncremental(int relations_per_tick = 10) {
|
||
static int current_index = 0;
|
||
|
||
auto& rel_list = getAllRelations();
|
||
int end_index = min(current_index + relations_per_tick, (int)rel_list.size());
|
||
|
||
for (int i = current_index; i < end_index; i++) {
|
||
applyRelationDecay(rel_list[i], DECAY_RATE);
|
||
}
|
||
|
||
current_index = (end_index >= rel_list.size()) ? 0 : end_index;
|
||
}
|
||
```
|
||
|
||
## Exemples Complets
|
||
|
||
### Exemple 1 : Cycle Vie Alliance
|
||
|
||
```cpp
|
||
// Année 0 : Proposition alliance
|
||
State usa, france;
|
||
|
||
// Relation initiale
|
||
int initial_relation = getRelation(usa, france); // 400
|
||
|
||
// Intentions initiales
|
||
setIntention(usa, france, +600); // USA veut alliance
|
||
setIntention(france, usa, +500); // France aussi
|
||
|
||
TreatyProposal proposal = {
|
||
.type = ALLIANCE,
|
||
.proposer = usa,
|
||
.target = france
|
||
};
|
||
|
||
if (evaluateTreatyProposal(france, proposal)) {
|
||
// Accepté !
|
||
Treaty alliance = activateTreaty(proposal);
|
||
|
||
// Impact immédiat sur relation partagée
|
||
int relation = getRelation(usa, france); // 400 + 400 = 800
|
||
|
||
// Fiabilité augmente
|
||
adjustFiability(usa, +50);
|
||
adjustFiability(france, +50);
|
||
}
|
||
|
||
// Années 1-3 : Maintenance
|
||
for (int year = 1; year <= 3; year++) {
|
||
maintainTreaty(alliance);
|
||
}
|
||
|
||
// Année 3 : Scandales (événements externes)
|
||
addRelationEvent(usa, france, {SCANDAL, -200, usa, getCurrentDate()});
|
||
// Relation : 800 → 600
|
||
|
||
// Decay vers 250 (alliance baseline) commence
|
||
|
||
// Année 4 : USA intention devient négative (nouveau gouvernement)
|
||
setIntention(usa, france, -300);
|
||
// Génère événements négatifs automatiques
|
||
// France continue events positifs (intention +500)
|
||
// Balance : relation descend lentement
|
||
|
||
// Année 5 : USA rompt alliance
|
||
breakTreaty(alliance, usa);
|
||
// Relation : 600 - 500 = 100
|
||
// Fiabilité USA : -500
|
||
// Intention France → USA : -400 (devient hostile)
|
||
```
|
||
|
||
### Exemple 2 : Lobbying Company
|
||
|
||
```cpp
|
||
Company rheinmetall;
|
||
State germany;
|
||
|
||
// État initial
|
||
int relation = getRelation(rheinmetall, germany); // 300
|
||
setIntention(rheinmetall, germany, +500); // Veut améliorer
|
||
setIntention(germany, rheinmetall, 0); // Neutre
|
||
|
||
// Campagne lobbying 6 mois
|
||
for (int month = 0; month < 6; month++) {
|
||
LobbyingAction action = {
|
||
.company = rheinmetall,
|
||
.state = germany,
|
||
.investment = 50000,
|
||
.duration_days = 30
|
||
};
|
||
|
||
executeLobbyingCampaign(action);
|
||
// 4 succès : +50 chacun sur relation partagée
|
||
// 2 échecs : pas d'impact
|
||
}
|
||
|
||
// Résultat : relation = 300 + (4 × 50) = 500
|
||
|
||
// Lobbying a aussi ajusté intention Germany
|
||
int germany_intention = getIntention(germany, rheinmetall); // 0 + (4 × 30) = 120
|
||
|
||
// Germany commence à générer events positifs aussi
|
||
// Synergie : relation continue d'améliorer
|
||
```
|
||
|
||
## Évolutions Futures
|
||
|
||
### Version 2 : Factions et Blocs
|
||
|
||
- Alliances multi-entités (OTAN, Pacte de Varsovie)
|
||
- Relations transitives (ami de mon ami)
|
||
- Pression peer group (alignement bloc)
|
||
|
||
### Version 3 : Opinion Publique
|
||
|
||
- Fiabilité vue différemment selon idéologie
|
||
- Pression interne pour maintenir/rompre relations
|
||
- Scandales médiatiques impactent relations
|
||
|
||
### Version 4 : Espionnage et Influence
|
||
|
||
- Actions cachées affectant relations
|
||
- Découverte espionnage = événement massif
|
||
- Manipulation opinion publique adverse
|
||
|
||
## Références Croisées
|
||
|
||
- `calcul-menace.md` : Détails système évaluation menace contextuelle
|
||
- `ai-framework.md` : Utilisation diplomatie dans décisions IA
|
||
- `economie-logistique.md` : Impact sanctions, embargos, accords commerciaux
|
||
- `systeme-sauvegarde.md` : Persistence relations, traités, événements
|