# Contrat d'API — Le Cœur de la Reine (Phase 3 optimisée)

Toutes les requêtes : `POST game_api.php`, corps JSON, champ `action` obligatoire.
(`ping` et `get_state` acceptent aussi `GET ?action=...`.)

---

## Principe d'optimisation latence

Avant : ~9 appels LLM **séquentiels** par tick (7 intentions AIC + 2 batchs GM) → ~225 s.
Après : **2 vagues** seulement.

1. **Intentions AIC en parallèle** (`curl_multi`) — les 7 AIC interrogent le LLM en même temps. Durée ≈ celle d'**un** appel, pas de 7.
2. **Game Master en un seul appel** avec `format: json` (Ollama) → un gros JSON fiable à parser côté client/serveur.

> Neutralité : le Game Master ne reçoit **jamais** les missions et ne décide **jamais** de la victoire. `check_victory` est **déterministe** et hors LLM — le GM ne peut donc pas déduire qui est l'humain.

---

## `init` — initialise le monde
**Requête** `{ "action": "init", "nom_joueur": "Necromantis" }`
**Réponse** `{ status, monde_id, initial_state: { temps, tick, aics[], joueur, npc } }`

## `process_tick` — un tick complet ★
**Requête**
```json
{ "action": "process_tick", "intention_joueur": "Me faufiler vers la salle du trône" }
```
Le serveur connaît déjà l'état (session) ; il génère les intentions AIC, appelle le GM, met à jour l'état.

**Réponse** (le « gros retour » à parser)
```json
{
  "tick": 5,
  "heure_actuelle": "08:30",
  "duree_ms": 7400,
  "llm": {
    "aic_calls": [ { "aic_id", "nom", "duree_ms", "ok", "tokens", "error" } ],
    "gm_call":   { "duree_ms", "ok", "json_valide", "tokens", "error" },
    "mode": "parallele_aic + gm_unique"
  },
  "intentions":   { "<aic_id>": "phrase d'intention" },
  "tick_results": { "<player_id>": { "action_valid", "new_position": {"zone","x","y"}, "perception", "status" } },
  "interactions": [ { "type", "initiateur", "cible", "detail" } ],
  "npc_updates":  { "<npc_id>": { "position", "action", "perception" } },
  "biais":        { "suspect": false, "note": "...", "moyenne_perception": 120, "details": [...] },
  "joueur": { ... }, "aics": [ ... ], "npc": { ... }
}
```

## `check_victory` — vérification DÉTERMINISTE (hors LLM)
**Requête** `{ "action": "check_victory" }` (lit l'état serveur ; ou fournir `joueur_position`, `joueur_inventaire`, `heure_actuelle`, `status`)
**Réponse** `{ status, victoire, defaite, raison, criteres: { a_le_rubis, dehors, temps_ecoule } }`

## `get_state` — état courant (pour l'Admin, ne consomme pas le LLM)
**Réponse** `{ initialise, monde_id, tick, temps_actuel, joueur, aics[], npc, derniers_resultats, llm_journal[] }`

## `ping` — santé du serveur LLM
**Réponse** `{ up, latence_ms, http_code, erreur, url, modele_attendu, modele_present, modeles[] }`

## `reset` — réinitialise la session
**Réponse** `{ status: "reset" }`
