feat(rules): resolve one-round casts on the following turn

SRD Casting Time: a spell that takes 1 round is a full-round action
that comes into effect just before the caster's turn in the next round;
the caster then acts normally. _cast_spell now spends the slot and runs
the start-of-casting gates, then records a PendingCast (spell, target,
center, metamagic, slot level, hp at cast); delivery (touch attack, SR,
saves, effects) resolves at the start of the caster's next turn, before
the policy runs. Net hp lost in between forces the injured-while-casting
concentration check (DC 10 + damage + spell level, no Combat Casting) or
the spell fizzles; a caster knocked out of the fight loses it. Exposed
in the observation via pending_cast. Bounded model documented: net-hp
measurement instead of a per-damage-site hook; long (1 minute+) casting
stays out of scope.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-09-13 13:39:44 +02:00
parent 3cc0502228
commit f5dc9da0c4
5 changed files with 423 additions and 21 deletions
+4 -1
View File
@@ -8,7 +8,10 @@ distinct reason ``downgraded:cast_time``. A one-round cast is CLAMPED to the
full-round slot (documented approximation: it resolves within the turn
instead of spanning rounds). Swift casts compete with the swift bonus (and
are removed by a consumed swift); full-round casts are illegal for a
staggered creature, and run is illegal for a nauseated one.
staggered creature, and run is illegal for a nauseated one. A one-round cast
occupies the full-round slot AND defers its effect to the start of the
caster's next turn (SRD "Casting Time", PendingCast — see
tests/test_one_round_cast.py).
"""
from __future__ import annotations