fix(parser): DamageDone trigger leaves valid_target=null, so match_damage_done skips the target/owne - #3469
Conversation
…mage_done skips the target/owne
…damagedone-trigger-leaves-valid
|
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.
DamageDone trigger valid_target fix. Adversarial review: ENQUEUE-READY. +978 is test-dominated (~150 lines production across 4 files). Right seam — populates valid_target at parse (TriggerDefinition), gates at match (match_damage_done); the new Player-arm guard is the symmetric dual of the pre-existing Object-arm guard (player-typed filters previously leaked through player_matches_filter's _=>true). One justified enum variant (DamagedPlayerIsEventSourceOwner — a recipient↔source-owner relation no TargetFilter encodes). CR 120.1/120.3/102.2/108.3/603.4 all grep-verified. Questing Beast snapshot change is a latent-bug fix (valid_target null→Typed([Planeswalker])). Strong discriminating pipeline tests (aggregate + self-ref paths). No scope creep beyond the DamageDone cluster.
Summary
Fixes a parser misparse affecting 2 card(s) in the Doctor Who Commander precons.
Root cause: DamageDone trigger leaves valid_target=null, so match_damage_done skips the target/owner check and fires on damage to any object/player; the 'to a creature' / 'to its owner' qualifier is dropped.
Cards corrected
Fix
Implemented WHO misparse cluster #2 (DamageDone trigger recipient-gating) surgically on upstream/main per the approved v3 plan. All 51-card "deals [combat] damage to a [type]" object-recipient class and the "to its owner" relational class now parse and gate correctly.
WHAT CHANGED (5 files):
_ => trueleak across BOTH delivery paths (per-event for the 37 SelfRef cards; aggregate for the 14 non-SelfRef listeners).DEVIATION FROM PLAN (necessary correction): The plan's Step 0a/0b used
!is_player_scope_damage_filter(vt)as the player-arm guard. That over-rejected the mixed "a player or planeswalker" recipient (Or{Player,Planeswalker}), regressing Hunter's Insight (a delayed-trigger card whose combat-damage-to-a-player firing broke). I introduced a dedicated building-block predicatedamage_recipient_filter_can_match_player(the player-arm dual of is_player_scope_damage_filter) that recurses through Or/And so a mixed disjunction still qualifies via its player-scope leg. Added a matcher regression test (mixed_player_or_planeswalker_recipient_fires_on_player). This is the correct, more-general gate and is what the plan's intent required.VERIFICATION (cargo run directly; worktree not under Tilt):
PARSER DIFF GATE: My HEAD diff to oracle_trigger.rs contains ZERO string-dispatch patterns (the disjunction check uses peek(tag("or ")), the alphanumeric word-boundary check mirrors the file's existing parse_enters_tapped_state_rider idiom). check-parser-combinators.sh exits non-zero ONLY because it compares against an ancient base commit (#904, a far ancestor) and flags many PRE-EXISTING lines in oracle.rs/oracle_static/* that are not mine — verified each flagged oracle_trigger line is "no (pre-existing)" and absent from my diff.
CR ANNOTATIONS (all verified against docs/MagicCompRules.txt before writing): CR 120.1 ("An object that deals damage is the source of that damage"), CR 120.3 (recipient is player or permanent), CR 102.2 (opponent is the other player), CR 108.3 (owner definition), CR 603.4 (intervening-if double-check).
MULTI-AGENT SAFETY: reverted the incidental crates/engine/data/known-tokens.toml regeneration (a side-effect of gen-card-data.sh picking up unrelated DB drift, not part of this fix). Final tree = exactly the 5 load-bearing files. No commit/push performed. Strax's Grenades "Choose a player at random" clause left untouched (cluster #5 / PR #3452 scope).
NOT alreadyCorrect: both lead cards and the class were confirmed still misparsed on upstream/main before edits.
Files changed
CR references
Verification
cargo fmt --all— pass./scripts/check-parser-combinators.sh <upstream/main merge-base 91283eafc>— passcargo clippy -p engine --all-targets -- -D warnings— passcargo test -p engine— passcargo run --profile tool --features cli --bin oracle-gen -- data --filter "the beast, deathless prince|strax, sontaran nurse"— passCards confirmed re-parsed correctly: The Beast, Deathless Prince, Strax, Sontaran Nurse
🤖 Generated with Claude Code