docs: document LLM observation contract and expanded action options
This commit is contained in:
@@ -410,16 +410,21 @@ Règles modélisées :
|
|||||||
- Manœuvres de combat : trip, disarm, bull_rush, sunder, grapple, escape,
|
- Manœuvres de combat : trip, disarm, bull_rush, sunder, grapple, escape,
|
||||||
overrun, dirty trick, steal, reposition et drag sont modélisées, chacune
|
overrun, dirty trick, steal, reposition et drag sont modélisées, chacune
|
||||||
comme une tentative unique (1d20 + CMB contre CMD) :
|
comme une tentative unique (1d20 + CMB contre CMD) :
|
||||||
trip → `prone` ; disarm → `disarmed` (−4 attaque) ; bull_rush → pousse la cible ;
|
trip → `prone` ; disarm → `disarmed` (−4 attaque) ; bull_rush → pousse la
|
||||||
|
cible (direction sélectionnable via `Action.direction`) ;
|
||||||
grapple → `grappled`/`pinned` ; escape → **une** sauvegarde (bonus statique de la
|
grapple → `grappled`/`pinned` ; escape → **une** sauvegarde (bonus statique de la
|
||||||
compétence `escape_artist` ou CMB, + un d20) contre CMD — une seule tentative,
|
compétence `escape_artist` ou CMB, + un d20) contre CMD — une seule tentative,
|
||||||
sans boucle multi-tour. Un sunder endommage l'**arme**, pas les PV : `str_mod + 2`
|
sans boucle multi-tour. Un sunder endommage l'**arme**, pas les PV : `str_mod + 2`
|
||||||
de dégâts à l'arme, qui se brise à 10 d'usure cumulée (`_WEAPON_DURABILITY`) →
|
de dégâts à l'arme, qui se brise à 10 d'usure cumulée (`_WEAPON_DURABILITY`) →
|
||||||
`disarmed` ; une arme brisée est exclue de `usable_attacks()`. overrun →
|
`disarmed` ; une arme brisée est exclue de `usable_attacks()` et réparable via
|
||||||
|
`Action(kind="repair_weapon")`. overrun →
|
||||||
`prone` 1 round + passage au travers si la case au-delà est libre ; dirty trick →
|
`prone` 1 round + passage au travers si la case au-delà est libre ; dirty trick →
|
||||||
`dazzled` 1 round ; steal → l'arme de mêlée de la cible est volée (exclue de
|
condition choisie par `Action.trick_condition` (défaut `dazzled` 1 round ;
|
||||||
`usable_attacks()`) ; reposition → déplacement de 5 ft de la cible vers le
|
`blinded`/`deafened`/`entangled`/`nauseated` possibles) ; steal → l'arme de
|
||||||
premier voisin libre ; drag → traction de 5 ft de la cible, l'attaquant
|
mêlée de la cible est volée (exclue de `usable_attacks()`, récupérable via
|
||||||
|
`Action(kind="retrieve_weapon")`) ; reposition → déplacement de 5 ft de la
|
||||||
|
cible vers le premier voisin libre (direction sélectionnable via
|
||||||
|
`Action.direction`) ; drag → traction de 5 ft de la cible, l'attaquant
|
||||||
occupant sa case d'origine. `default_policy` ne
|
occupant sa case d'origine. `default_policy` ne
|
||||||
choisit pas ces manœuvres (utilisables via `Action(kind="maneuver")` ou une
|
choisit pas ces manœuvres (utilisables via `Action(kind="maneuver")` ou une
|
||||||
politique personnalisée).
|
politique personnalisée).
|
||||||
@@ -448,14 +453,24 @@ Règles modélisées :
|
|||||||
`shaken` 1 round, au début de son tour) et contact paralysant (au toucher,
|
`shaken` 1 round, au début de son tour) et contact paralysant (au toucher,
|
||||||
`paralysé` 1d4+1 rounds), RD 15/magie+contondant ; son JSON porte un dictionnaire
|
`paralysé` 1d4+1 rounds), RD 15/magie+contondant ; son JSON porte un dictionnaire
|
||||||
`spell_slots` sans clés dupliquées.
|
`spell_slots` sans clés dupliquées.
|
||||||
|
- Snapshot d'observation (contrat LLM, Phase 2) : avant chaque appel de
|
||||||
|
politique, le moteur construit une `Observation` sérialisable (`to_dict()` →
|
||||||
|
JSON) figée — champs par combattant (id, side, pos, occupied_cells,
|
||||||
|
hp/hp_max, active/dead, conditions noms+durées, resources_left,
|
||||||
|
weapon_broken/weapon_stolen, grappled_with, moved_this_turn, power_attack),
|
||||||
|
par paire combattant actif × cible (distance_ft, weapon_for, range_penalty,
|
||||||
|
can_charge, can_step5_to_attack, has_line_of_effect, flanking) et couches
|
||||||
|
terrain/élévation de la grille. Les API de décision exposées (items L1-L8)
|
||||||
|
s'y retrouvent : `direction`/`trick_condition`/`weapon_id` sur `Action`,
|
||||||
|
`can_charge` → `ChargeResult`, zones menacées `threatened_squares`/
|
||||||
|
`enemies_threatening`, coûts `reachable_ft`/`movement_cost_ft`, kinds
|
||||||
|
`retrieve_weapon`/`repair_weapon`. Une politique LLM se branche via
|
||||||
|
`CombatEngine(..., llm_policy=...)` (`LLMPolicy(observation, state) ->
|
||||||
|
tuple[Action, ...]`) ; le snapshot est la SEULE source d'info de la LLM
|
||||||
|
(aucune référence `engine.*` exposée, collections copiées/figées).
|
||||||
|
|
||||||
Non modélisé (couche `markers` présente mais non appliquée dans la
|
Non modélisé : la couche `markers` (points nommés de la carte) est validée à
|
||||||
résolution) :
|
la lecture mais non appliquée dans la résolution.
|
||||||
- Manœuvres : dirty trick applique toujours `dazzled` (le choix
|
|
||||||
aveuglé/assourdi/entravé/malade n'est pas modélisé) ; reposition et drag
|
|
||||||
utilisent une direction déterministe (premier voisin libre / au-delà de la
|
|
||||||
cible) ; un objet volé n'est pas récupérable en cours de combat. Une arme
|
|
||||||
brisée ne peut pas être réparée en cours de combat.
|
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
@@ -479,7 +494,9 @@ résolution) :
|
|||||||
multi-cases, zones menacées en anneau), high ground, actions immédiates
|
multi-cases, zones menacées en anneau), high ground, actions immédiates
|
||||||
opt-in (réactions hors-tour), états de vie, incantation
|
opt-in (réactions hors-tour), états de vie, incantation
|
||||||
(emplacements, concentration par situation, AoO d'incantation), invocation,
|
(emplacements, concentration par situation, AoO d'incantation), invocation,
|
||||||
manœuvres, capacités de classe, transcripts, politique par défaut. Les
|
manœuvres (avec sélection directionnelle et choix de condition d'état),
|
||||||
|
capacités de classe, transcripts, politique par défaut, snapshot
|
||||||
|
d'observation sérialisable `Observation`/`LLMPolicy` (frontière LLM). Les
|
||||||
modificateurs conditionnés (`StatModifier.condition`) sont évalués via
|
modificateurs conditionnés (`StatModifier.condition`) sont évalués via
|
||||||
`_modifier_condition_holds` avec le contexte d'action (arme, portée,
|
`_modifier_condition_holds` avec le contexte d'action (arme, portée,
|
||||||
descripteurs de sauvegarde) ; les conditions inconnues restent exclues.
|
descripteurs de sauvegarde) ; les conditions inconnues restent exclues.
|
||||||
@@ -538,7 +555,7 @@ résolution) :
|
|||||||
La gate de validation complète (tests + lint + types) :
|
La gate de validation complète (tests + lint + types) :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run pytest -q # 480 tests
|
uv run pytest -q # 664 tests
|
||||||
uv run ruff check src tests
|
uv run ruff check src tests
|
||||||
uv run basedpyright src # mode strict
|
uv run basedpyright src # mode strict
|
||||||
```
|
```
|
||||||
@@ -561,8 +578,10 @@ uv run basedpyright src # mode strict
|
|||||||
(coût de déplacement + high ground), tailles Large+ (occupation multi-cases),
|
(coût de déplacement + high ground), tailles Large+ (occupation multi-cases),
|
||||||
allonges > 5 ft (allonge naturelle + `reach_ft`, zones menacées en anneau) et
|
allonges > 5 ft (allonge naturelle + `reach_ft`, zones menacées en anneau) et
|
||||||
actions immédiates hors-tour (politique de réaction opt-in). Restent hors du
|
actions immédiates hors-tour (politique de réaction opt-in). Restent hors du
|
||||||
socle (voir « Non modélisé ») : les markers et les manœuvres avancées.
|
socle (voir « Non modélisé ») : les markers.
|
||||||
- **Phase 2** — couche tactique LLM : stratégies en langage naturel traduites
|
- **Phase 2** — couche tactique LLM : stratégies en langage naturel traduites
|
||||||
en politiques, balayage de matrices de positionnement. (Non implémentée.)
|
en politiques, balayage de matrices de positionnement. Le contrat
|
||||||
|
d'observation (snapshot sérialisable `Observation` + wrapper `LLMPolicy`)
|
||||||
|
est en place ; la couche LLM elle-même reste à implémenter.
|
||||||
- **Phase 3** — rapporteur LLM local : agrégation des statistiques et
|
- **Phase 3** — rapporteur LLM local : agrégation des statistiques et
|
||||||
rédaction du rapport d'équilibrage en français. (Non implémentée.)
|
rédaction du rapport d'équilibrage en français. (Non implémentée.)
|
||||||
|
|||||||
Reference in New Issue
Block a user