fix(rules): allow a staggered creature to withdraw as a standard action

SRD 'Full-Round Actions - Restricted Withdraw': 'If you are limited to taking only a standard action each round you can withdraw as a standard action. In this case, you may move up to your speed.' _staggered_filter now keeps withdraw as the one move-or-standard action (spending the slot) instead of dropping it, and _flee_path halves the budget to single speed for a staggered/disabled creature (new _is_staggered_limited helper). Filter-level and engine-level tests added.

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-12 14:21:04 +02:00
parent a4487a85f9
commit 317c68ecdb
4 changed files with 95 additions and 12 deletions
+12
View File
@@ -350,6 +350,18 @@ def test_staggered_filter_drops_full_round_and_downgrades_full_attack() -> None:
assert _staggered_filter((_foe("move"), _foe("full_attack"))) == (_foe("move"),)
def test_staggered_filter_keeps_withdraw_as_restricted_standard() -> None:
# SRD "Full-Round Actions — Restricted Withdraw": a creature limited to a
# standard action each round may withdraw as a standard action (moving up
# to its speed) — the staggered filter keeps it and spends the slot.
assert _staggered_filter((_foe("withdraw"),)) == (_foe("withdraw"),)
# After the one move-or-standard slot is spent, withdraw is dropped.
assert _staggered_filter((_foe("attack"), _foe("withdraw"))) == (_foe("attack"),)
assert _staggered_filter((_foe("move"), _foe("withdraw"))) == (_foe("move"),)
# A leading withdraw spends the slot; the following standard is dropped.
assert _staggered_filter((_foe("withdraw"), _foe("attack"))) == (_foe("withdraw"),)
def test_nauseated_after_budget_keeps_single_move() -> None:
# (move, attack, move): the budget drops the second move; the nauseated
# filter then keeps only the first move and drops the standard attack.