fix(parser): UNSUPPORTED full-set one-off: Ood Sphere#5170
Conversation
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
matthewevans
left a comment
There was a problem hiding this comment.
Thanks for the Ood Sphere pass. I found two blocking gaps in the new CantTap enforcement: the backstop rejects some taps, but several eligibility surfaces still advertise restricted creatures as legal choices.
-
Crew, Station, and Saddle still build their
eligible_creatureslists from controller/untapped/creature checks without filteringrestrictions::object_cant_tap. Seecrates/engine/src/game/engine.rsaround the Crew list, Station list, and Saddle list. Those lists are used to decide whether the activation is possible and to construct the waiting-state selection surface, so a creature that cannot become tapped can still count toward the required total and be offered to the user/AI, then fail only later when the tap backstop runs. -
Harmonize has the same mismatch in both paths: the castability probe in
crates/engine/src/game/casting.rssimulates tapping any untapped powered creature, and theHarmonizeTapChoicelist incrates/engine/src/game/casting_costs.rsoffers any untapped powered creature. Both need to excludeobject_cant_tapcreatures before declaring the spell castable or offering the tap choice.
Please route all tap-for-cost eligibility through the same object_cant_tap authority, and add targeted tests where the only apparent contributor is a restricted creature, plus a threshold case where including the restricted creature incorrectly makes the activation/cast appear legal.
Also holding approval until the required parse-diff sticky is posted for this parser/engine head.
Parse changes introduced by this PR · 3 card(s), 8 signature(s) (baseline: main
|
# Conflicts: # crates/engine/src/game/casting.rs # crates/engine/src/game/restrictions.rs # crates/engine/src/parser/oracle_effect/mod.rs
matthewevans
left a comment
There was a problem hiding this comment.
Addressed the remaining tap-restriction blocker. Crew, Station, Saddle, Harmonize castability, and HarmonizeTapChoice now exclude creatures that can't become tapped at the eligibility surface, with focused regressions. Local checks: cargo fmt --all; git diff --check; check-parser-combinators; check-engine-authorities; cargo test -p engine --lib cant_tap.
Summary
Fixes a parser misparse affecting 1 card(s) in the Doctor Who Commander precons.
Root cause: UNSUPPORTED full-set one-off: Ood Sphere
Cards corrected
Fix
Implemented cluster 94 (Ood Sphere, WHO Planechase plane) — fully fixed both misparses and built the "can't become tapped" runtime enforcement seam across all layers. Verified via oracle-gen: 0 Unimplemented, both defects corrected.
DEFECT 1 — "Noncreature spells have convoke" was a silent misparse (runtime-inert anthem AddKeyword). Added a non-possessive, all-players branch (Pattern 4) to parse_spells_have_keyword that emits StaticMode::CastWithKeyword{Convoke} with a CONTROLLER-AGNOSTIC affected filter (Typed[Non(Creature)], controller:null), active_zones [Battlefield] → synthesis appends Command → functions in the command zone via game_active_statics/granted_spell_keywords for every player's noncreature spell. Parameterizes the controller axis of the existing casting-keyword-grant pattern; covers any plane/global "[type] spells have [keyword]" grant.
DEFECT 2 — the Red-Eye trigger's second sentence was Effect::Unimplemented("Unsupported unless clause"). Added try_parse_temporary_cant_become_tapped (nom combinators, hand-rolled ParentTarget subject + CR 508.1f attacker exemption, FAILS CLOSED for any other rider) → lowers to Effect::GenericEffect{ GrantStaticAbility(CantTap on SelfRef), affected/target: ParentTarget, duration: UntilNextTurnOf(Controller) } as the trigger's SequentialSibling sub-ability. Dispatched at the TOP of parse_effect_clause (before the unless-suffix stripper that was preempting it).
RUNTIME SEAM (per "build the seam" mandate) — turned the inert StaticMode::CantTap stub into an enforced restriction: (1) new single-authority predicate restrictions::object_cant_tap (fast-path static_kind_present + intrinsic active_static_definitions scan); (2) new single-authority restrictions::tap_permanent_for_cost routed through all 8 cost-tap chokepoints ({T} ability, convoke, crew, station, saddle, harmonize, tap-N additional cost, {T}/tap-another mana abilities); (3) process_one_tap effect-tap gate (no-op on restricted creature); (4) {T}-activation legality gate in check_summoning_sickness_for_cost (tap-only, {Q} unaffected) + mana-ability readiness gate + auto-tap mana-source exclusion; (5) AI/MP offer filtering in candidates.rs (crew/saddle/station eligibility hoist + convoke offer). Combat declare-attackers path deliberately NOT gated (CR 508.1f exemption). Helper no-ops for unrestricted objects (fast-path), so zero behavior change to existing cards.
VERIFICATION (worktree runs cargo directly, no Tilt): cargo fmt OK; cargo clippy -p engine --all-targets exit 0 clean; full engine test suite GREEN (15328 lib + 1775 integration + all targets, 0 failed); oracle-gen "Ood Sphere" → 0 Unimplemented with CastWithKeyword{Convoke}(active_zones [Battlefield,Command]) + CantTap GenericEffect; parser-combinator gate — my added production lines clean (rsplit/tag/alt only). Added building-block + runtime tests including the Finding-1 REQUIRED gate (generic_effect_cant_tap_binds_every_parent_target_object: multi-object ParentTarget binds one CantTap TCE per goaded creature, non-goaded unaffected). Did NOT commit.
Files changed
CR references
Verification
cargo fmt --all— clean (no files changed, no commit needed)check-parser-combinators.sh <upstream/main merge-base>— clean (exit 0)cargo clippy -p engine --all-targets -- -D warnings— clean (no warnings in this cluster's 17 changed files)cargo test -p engine— clean (exit 0, 0 failures; all Ood Sphere tests pass)oracle-gen -- data --filter "ood sphere"— confirmed (parses correctly, no Unimplemented/Unknown)Cards confirmed re-parsed correctly: Ood Sphere
🤖 Generated with Claude Code