feat(rules): encode arcane_caster and armor_spell_failure from the sheets
- arcane_caster true: misty (Magus/Bard sheet class), nairda (Witch/ Sorcerer), thrune_agent (Human magus 8, KB bestiary/thrune-agent.md); lich already true. False: oni (Cleric), tammara (Gunslinger/ Warpriest - divine), esha (Cavalier/Rogue, spell-like only), the companions harvie/ierlieth/jeanne/esha_mount and the remaining monsters. - armor_spell_failure stays 0 everywhere, as the effective PF1e value: nairda and the lich wear no armor (sheet note "Pas d'armure", KB lich block); misty's mithral shirt (RAW ASF 10%, magic-items/mithral-shirt .md) and the thrune agent's +1 studded leather (15%) are light armor and every spell they cast is on their own class list - magus and bard cast their own spells in light armor with no arcane spell failure (classes/magus.md, classes/bard.md). - tests/test_spell_failure.py: the lich/oni smoke test becomes a full-data table pinning all 15 combatants' flags with per-entry sources. No shipped combatant incurs a non-zero ASF; the failure roll itself stays covered by the synthetic armored-caster tests.
This commit is contained in:
@@ -320,15 +320,43 @@ def test_observation_exposes_components_and_caster_fields() -> None:
|
||||
json.dumps(obs)
|
||||
|
||||
|
||||
def test_lich_is_arcane_oni_is_not() -> None:
|
||||
"""Smoke test on the shipped data: the lich casts arcane spells with
|
||||
no armor (ASF 0); Oni is a divine caster and never incurs ASF."""
|
||||
lich = load_combatant(DATA_DIR / "monsters" / "lich.json")
|
||||
oni = load_combatant(DATA_DIR / "pcs" / "oni.json")
|
||||
assert lich.arcane_caster is True
|
||||
assert lich.armor_spell_failure == 0
|
||||
assert oni.arcane_caster is False
|
||||
assert oni.armor_spell_failure == 0
|
||||
def test_combatant_caster_flags_and_asf_match_sheets() -> None:
|
||||
"""Smoke test on the shipped data, one entry per combatant JSON.
|
||||
|
||||
arcane_caster follows the sheet class (fiches_personnages identity.classes
|
||||
/ bestiary KB): magus/bard/witch/sorcerer/wizard true, divine and
|
||||
non-casters false. armor_spell_failure is the EFFECTIVE percent:
|
||||
- lich: no armor (KB bestiary/lich.json, unarmored skeletal body).
|
||||
- misty: mithral shirt (sheet combat.ac note "+6 mithral shirt",
|
||||
light armor, RAW ASF 10%) but every spell she knows is a bard or
|
||||
magus spell and both classes cast their own-list spells in light
|
||||
armor with no ASF (classes/bard.md, classes/magus.md) -> 0.
|
||||
- nairda: no armor (sheet combat.ac note "Pas d'armure") -> 0.
|
||||
- thrune_agent: +1 studded leather (KB bestiary/thrune-agent.md gear,
|
||||
light armor) but all its spells are magus spells and a magus casts
|
||||
magus spells in light armor with no ASF (classes/magus.md) -> 0.
|
||||
"""
|
||||
expectations: dict[str, tuple[bool, int]] = {
|
||||
"pcs/misty.json": (True, 0),
|
||||
"pcs/nairda.json": (True, 0),
|
||||
"pcs/oni.json": (False, 0),
|
||||
"pcs/tammara.json": (False, 0),
|
||||
"pcs/esha.json": (False, 0),
|
||||
"pcs/esha_mount.json": (False, 0),
|
||||
"pcs/harvie.json": (False, 0),
|
||||
"pcs/ierlieth.json": (False, 0),
|
||||
"pcs/jeanne.json": (False, 0),
|
||||
"monsters/lich.json": (True, 0),
|
||||
"monsters/thrune_agent.json": (True, 0),
|
||||
"monsters/goblin.json": (False, 0),
|
||||
"monsters/orc.json": (False, 0),
|
||||
"monsters/celestial_wolf.json": (False, 0),
|
||||
"monsters/giant_belostomatid.json": (False, 0),
|
||||
}
|
||||
for rel, (arcane, asf) in expectations.items():
|
||||
loaded = load_combatant(DATA_DIR / rel)
|
||||
assert loaded.arcane_caster is arcane, rel
|
||||
assert loaded.armor_spell_failure == asf, rel
|
||||
|
||||
|
||||
def test_registry_spells_declare_kb_components() -> None:
|
||||
|
||||
Reference in New Issue
Block a user