feat(spells): add spell system with 10 combat spells, cast_spell action
Spells are SpellSpec dataclasses with typed effects: DamageEffect (dice + types, half-on-save), ConditionEffect (condition lookup + save negates), HealEffect (capped at hp_max), BuffEffect (transient StatModifiers). Range categories (personal/touch/close/medium/long) scale with caster level via spell_range_ft. JSON loader (load_spell/load_spell_registry) reads data/spells/*.json. The engine integrates spells via Action(kind='cast_spell') and _cast_spell: range check, line-of-effect gate, save resolution (resolve_save), effect application (_apply_spell_effects with DR via _apply_dr_for_types), transcript logging. The spell_registry is passed to CombatEngine; Combatant.spells holds known spell names. - spells.py: SpellSpec, 4 effect types, SpellRange/SaveType literals, spell_range_ft, JSON loader (uses Json type from foundry.py) - conditions.py: CONDITIONS_BY_NAME registry for condition lookup - combat.py: cast_spell Action kind, _execute_cast_spell dispatch, _cast_spell (range/LoE/save/effects/log), _apply_spell_effects, _apply_dr_for_types, _save_label helper, SpellSpec/BuffEffect/etc imports, spell_registry parameter on CombatEngine - models.py: spells field on Combatant - data/spells/: 10 spells (Magic Missile, Burning Hands, Fireball, Lightning Bolt, Acid Arrow, Cure Light/Moderate Wounds, Hold Person, Fear, Bull's Strength) - tests/test_spells.py: 29 tests (loading, range, damage/save/condition/ heal/buff/DR, out-of-range, unknown spell, dispatch, DC scaling) - pyproject.toml: PLR0913 ignore for combat.py (CombatEngine.__init__) - README.md: spells.py architecture section, Sorts removed from non-modeled list, 336 tests
This commit is contained in:
@@ -339,10 +339,6 @@ Règles modélisées :
|
||||
Non modélisé (couches `elevation`/`markers` présentes mais non appliquées
|
||||
dans la résolution) :
|
||||
|
||||
- Sorts (le système d'effets `effects.py`, les règles d'empilement des
|
||||
bonus, les jets de sauvegarde `resolve_save`, le système de conditions
|
||||
`conditions.py` et les dons passifs `abilities.py` sont en place —
|
||||
l'intégration des sorts au moteur est en cours).
|
||||
- Manœuvres de combat.
|
||||
- Effets mécaniques de hauteur/élévation.
|
||||
- Tailles Large+ (2×2), allonge > 5 ft
|
||||
@@ -386,6 +382,16 @@ dans la résolution) :
|
||||
`state.power_attack`). Les modificateurs sont collectés par
|
||||
`_stat_modifiers` avec filtrage par arme (`weapon_filter`). Le champ
|
||||
`features` de `Combatant` contient les aptitudes permanentes.
|
||||
- `spells.py` — sorts : `SpellSpec` (dataclass avec niveau, école, portée,
|
||||
sauvegarde, DC de base) et types d'effets (`DamageEffect`, `ConditionEffect`,
|
||||
`HealEffect`, `BuffEffect`). Portées PF1e (personal, touch, close, medium,
|
||||
long) calculées par `spell_range_ft`. Chargeur JSON (`load_spell`,
|
||||
`load_spell_registry`) pour `data/spells/`. Le moteur intègre les sorts via
|
||||
`Action(kind="cast_spell")` et `_cast_spell` : résolution de sauvegarde,
|
||||
application des dégâts (avec RD et demi-dégâts sur sauvegarde réussie),
|
||||
conditions, soins (plafonnés à hp_max) et buffs. Le champ `spells` de
|
||||
`Combatant` contient les noms de sorts connus ; le `spell_registry` est
|
||||
passé au `CombatEngine`.
|
||||
- `metrics.py` — statistiques en forme fermée : `win_rate`, `win_rate_sigma`,
|
||||
`win_rate_band` (bande 3σ bornée à [0, 1]).
|
||||
- `runner.py` — `EncounterSpec`/`Side`, `build_states` (placement en zone +
|
||||
@@ -401,7 +407,7 @@ dans la résolution) :
|
||||
La gate de validation complète (tests + lint + types) :
|
||||
|
||||
```bash
|
||||
uv run pytest -q # 307 tests
|
||||
uv run pytest -q # 336 tests
|
||||
uv run ruff check src tests
|
||||
uv run basedpyright src # mode strict
|
||||
```
|
||||
@@ -419,8 +425,10 @@ uv run basedpyright src # mode strict
|
||||
attaques à outrance, attaques d'opportunité, charge, retraite et pas de
|
||||
placement sont déjà modélisés. Le système d'effets (`effects.py`), les
|
||||
règles d'empilement des bonus, les jets de sauvegarde (`resolve_save`), le
|
||||
système de conditions (`conditions.py`) et les dons passifs (`abilities.py`)
|
||||
sont en place.
|
||||
système de conditions (`conditions.py`), les dons passifs et actifs
|
||||
(`abilities.py`) et les sorts (`spells.py` + base JSON `data/spells/`)
|
||||
sont en place. Extension du chargeur Foundry pour l'extraction des sorts et
|
||||
dons en cours.
|
||||
- **Phase 2** — couche tactique LLM : stratégies en langage naturel traduites
|
||||
en politiques, balayage de matrices de positionnement.
|
||||
- **Phase 3** — rapporteur LLM local : agrégation des statistiques et
|
||||
|
||||
Reference in New Issue
Block a user