PF1e CRB: running is a full-round action, not a move action. The budget
filter now classifies run as full-round (consumes the standard AND the
move slot), _FULL_ROUND_KINDS includes it for the staggered filter, and
the nauseated filter drops it (run is no longer move-like). The
moved_this_turn/running flags are unchanged; the _execute_run
moved_this_turn early return stays as defense in depth. default_policy
never emits run, so the golden transcripts are untouched.
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Apply the PF1e per-turn action budget (CRB Actions in Combat: one
standard + one move, or one full-round in place of both, plus one
swift) unconditionally to every sequence a policy returns, not only
the immediate/staggered/nauseated specializations.
- _action_economy_filter: greedy in-order walk keeping the earliest
legal prefix-subsequence; a full-round action is only kept while
both the standard and move slots are still free.
- Exhaustive kind->slot classification (standard / move / swift /
full_round / free-conditional) over the Action.kind Literal,
documented and locked by tests.
- Surplus actions dropped and reported as
ActionResult(ok=False, reason="downgraded:action_economy") via a
multiset drop diff (reports duplicate-kind surplus the set-based
_dropped_kinds cannot).
- Composition order: general budget first, then the existing
immediate/staggered/nauseated filters (unchanged).
- default_policy untouched and its turns verified legal by the
validator; golden transcripts byte-identical.
Movement budget is now max(land, fly) speed. Updates the harvie golden: Harvie (land 10 / fly 80) is a flyer and now flies at 80 ft, so he wins vs the goblin instead of being pinned crawling at 10 ft.
- New Action kind activate_power_attack: free action that sets
state.power_attack = True when the combatant has the Power Attack feat;
logged no-op otherwise. Routed via _execute_movement (free-action branch)
to keep _execute under the C901 complexity ceiling.
- Consume deed_up_close_and_deadly in resolve_attack: the first attack
resolved while the flag is set gains +1d6 if it is a ranged attack within
30 ft; the flag is reset in all cases (benefit lost if out of range or
not ranged). Extracted into _consume_up_close_and_deadly helper.
- Document activate_power_attack, corrected deed semantics, and the
power_attack snapshot key in README.
- Add tests/test_engine_fixes.py (5 tests): PA activation, no-feat no-op,
deed+ranged within 30ft, deed out-of-range, deed melee.
Rename _threatened_squares -> threatened_squares and
_enemies_threatening -> enemies_threatening (public read-only API for a
future LLM policy), and add reachable_ft(state, budget) and
movement_cost_ft(state, target) accessors returning movement costs in
feet. Pure exposure: no behavior change, resolution engine untouched,
goldens bit-identical.