feat(rules): spell components + deafened verbal failure and arcane spell failure rolls
- SpellSpec.components (frozenset of V/S/M/F/DF, JSON key accepting the RAW string notation "V, S, M/DF" or a token list; slash = alternative; unknown token is a data error). Default empty = not encoded yet -> no failure. - Combatant.armor_spell_failure (0-100 percent, authored on the JSON - the model has no equipment) and arcane_caster (divine casters never incur ASF); both load directly through load_combatant. - _cast_spell: after the start-of-casting gates and before delivery, two conditional d100 rolls (convention mirrors the concealment roll, <=): deafened + V component spoils the spell on <=20 (SRD cast-a-spell.md); arcane_caster + S component + armor_spell_failure > 0 fails the spell on <= the ASF percent (SRD arcane-spells-and-armor.md). The slot stays spent (mirrors the concentration fizzle). No condition -> no roll: the RNG stream is bit-identical for every current combat (registry encodes no components yet - full encoding is a follow-up task). - Observation: spell summary gains "components" (sorted tuple), combatant snapshot gains "armor_spell_failure"/"arcane_caster"; README documents the keys and the two former out-of-scope bullets now describe the modeled rule with its data-encoding follow-up. - Data smoke test: lich arcane_caster true / ASF 0, oni arcane_caster false. - tests/test_spell_failure.py: 21 tests (parsing, thresholds <=20 / <=ASF, divine/no-ASF/no-component never roll, roll order, slot stays spent, observation keys). Golden transcripts unchanged.
This commit is contained in:
@@ -143,6 +143,7 @@ def test_area_snapshot_existing_keys_unchanged() -> None:
|
||||
assert s["save_negates"] is False
|
||||
assert s["harmless"] is False
|
||||
assert s["cast_time"] == "standard"
|
||||
assert s["components"] == ()
|
||||
assert set(s.keys()) == {
|
||||
"name",
|
||||
"level",
|
||||
@@ -156,6 +157,7 @@ def test_area_snapshot_existing_keys_unchanged() -> None:
|
||||
"harmless",
|
||||
"area",
|
||||
"cast_time",
|
||||
"components",
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user