feat(engine): implement CountersCantBeRemoved static (Fear of Sleep Paralysis) - #50
feat(engine): implement CountersCantBeRemoved static (Fear of Sleep Paralysis)#50Whovencroft wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 02117a20ca
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| /// the given object for the given counter type. Used by the untap-step stun- | ||
| /// counter removal to skip removal when blocked (Fear of Sleep Paralysis). |
There was a problem hiding this comment.
Enforce counter-removal prohibition on all removal paths
This helper is only used by the two untap-step stun-counter branches in turns.rs, so the new supported CountersCantBeRemoved static does not affect other production counter-removal paths such as effects::counters::apply_counter_removal or move-counter/cost removals. In a game with Fear of Sleep Paralysis, an opponent can still remove or move a stun counter from their affected permanent through those paths even though the static says the counter can't be removed; please put this check at the central counter-removal authority or route all removals through it.
Useful? React with 👍 / 👎.
02117a2 to
7360750
Compare
Parse changes introduced by this PR · 1 card(s), 2 signature(s) (baseline: main
|
cb15f98 to
a9f58b6
Compare
…aralysis)
Implements the missing static/replacement effect for Fear of Sleep
Paralysis: "Stun counters can't be removed from permanents your
opponents control."
Changes:
- types/statics.rs: Add StaticMode::CountersCantBeRemoved { counter_type }
variant with all required trait impls (Hash, Display, FromStr, to_kind,
as_keyword).
- game/coverage.rs: Register in is_data_carrying_static().
- game/turns.rs: Add counter_removal_blocked() helper gating the untap-step
stun-counter removal (both main path and Seedborn-Muse secondary path).
- parser/oracle_static/dispatch.rs: Add parse_counters_cant_be_removed_static()
to parse the Oracle text pattern.
- game/turns.rs (tests): Two integration tests verifying the prohibition
blocks removal and the baseline still works.
Comprehensive Rules: CR 122.1d, CR 101.2
Card: Fear of Sleep Paralysis (DSC #12)
a9f58b6 to
9872246
Compare
Summary
Implements the missing static/replacement effect for Fear of Sleep Paralysis (DSC #12):
This is a counter-removal prohibition governed by CR 122.1d (stun counter removal as a replacement for untapping) and CR 101.2 ("can't" overrides "can").
Changes
crates/engine/src/types/statics.rsStaticMode::CountersCantBeRemoved { counter_type: CounterType }variant with all required trait impls (Hash,Display,FromStr,to_kind,as_keyword).crates/engine/src/game/coverage.rsis_data_carrying_static()so the coverage classifier recognizes the new data-carrying variant.crates/engine/src/game/turns.rscounter_removal_blocked()helper that checks activeCountersCantBeRemovedstatics against the target permanent; gate the untap-step stun-counter removal in both the main untap path and the Seedborn-Muse secondary untap path.crates/engine/src/parser/oracle_static/dispatch.rsparse_counters_cant_be_removed_static()to parse the Oracle text pattern"<counter> counters can't be removed from <subject>".crates/engine/src/game/turns.rs(tests)Design Decisions
CountersCantBeRemovedcarries aCounterTypefield so the same mechanism can be reused for future cards that protect other counter types (e.g., oil counters, shield counters).turns.rs(both main path and Seedborn path), which is the only place CR 122.1d removal currently occurs. Future counter-removal sites (e.g., explicit "remove a counter" effects) would need their own gate.static_filter_matcheswith aStaticCheckContext { target_id }to evaluate theaffectedfilter (e.g., "permanents your opponents control") against the permanent whose counter would be removed.str::findanchor on" counters can't be removed from ", thenparse_strict_counter_typefor the prefix andparse_type_phrasefor the subject suffix.Comprehensive Rules
Testing
execute_untap_honors_counters_cant_be_removed_static— verifies that with Fear of Sleep Paralysis on the battlefield, an opponent's stunned creature stays tapped AND keeps its stun counter.execute_untap_removes_stun_counter_without_prohibition— baseline: without the prohibition, stun counter is removed normally per CR 122.1d.