feat(observation): expose spell cast time in the snapshot
The per-spell Observation dict gains the additive cast_time key: the registry spell's budget code on a hit, "standard" on a miss (mirroring the engine's resolver fallback), so an LLM policy can schedule casts against the action budget it sees reported back. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -977,7 +977,9 @@ Règles modélisées :
|
||||
spells (résumés enrichis du registre : name, level, school, range_ft,
|
||||
save, dc, summary, half_on_save, save_negates (E4), area {shape,
|
||||
radius_ft} | None (U7a : premier AreaEffect de niveau supérieur du sort,
|
||||
gabarit de zone structuré, None si le sort n'a pas de zone)),
|
||||
gabarit de zone structuré, None si le sort n'a pas de zone), cast_time
|
||||
(code de temps d'incantation, « standard » pour un sort inconnu du
|
||||
registre)),
|
||||
spell_resistance (int), resistances {type: montant}, immunities
|
||||
(tuple triée des types immunisés), sneak_dice (dés de précision disponibles :
|
||||
(niveau + 1) // 2 avec « Sneak Attack », sinon 0), engaged_in_melee (bool —
|
||||
|
||||
@@ -4574,6 +4574,7 @@ class CombatEngine:
|
||||
"half_on_save": False,
|
||||
"save_negates": False,
|
||||
"area": None,
|
||||
"cast_time": "standard",
|
||||
}
|
||||
half_on_save = _spell_half_on_save(spell)
|
||||
return {
|
||||
@@ -4587,6 +4588,7 @@ class CombatEngine:
|
||||
"half_on_save": half_on_save,
|
||||
"save_negates": spell.save != "none" and not half_on_save,
|
||||
"area": _spell_area_dict(spell),
|
||||
"cast_time": spell.cast_time,
|
||||
}
|
||||
|
||||
def _cast_spell(
|
||||
|
||||
@@ -532,6 +532,7 @@ def test_observation_enriched_spells_unknown_graceful() -> None:
|
||||
"half_on_save": False,
|
||||
"save_negates": False,
|
||||
"area": None,
|
||||
"cast_time": "standard",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ def test_area_snapshot_existing_keys_unchanged() -> None:
|
||||
"""Given: a known Fireball snapshot dict
|
||||
When: all keys and values are checked
|
||||
Then: the nine pre-U7a keys are present with unchanged values, and the
|
||||
exact key set is the old nine plus the additive "area"."""
|
||||
exact key set is the old nine plus the additive "area" and "cast_time"."""
|
||||
s = _spell_dict_for(_FIREBALL, "Fireball")
|
||||
assert s["name"] == "Fireball"
|
||||
assert s["level"] == 3
|
||||
@@ -140,6 +140,7 @@ def test_area_snapshot_existing_keys_unchanged() -> None:
|
||||
assert s["summary"] == "area 20ft"
|
||||
assert s["half_on_save"] is True
|
||||
assert s["save_negates"] is False
|
||||
assert s["cast_time"] == "standard"
|
||||
assert set(s.keys()) == {
|
||||
"name",
|
||||
"level",
|
||||
@@ -151,6 +152,7 @@ def test_area_snapshot_existing_keys_unchanged() -> None:
|
||||
"half_on_save",
|
||||
"save_negates",
|
||||
"area",
|
||||
"cast_time",
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user