Skip to content

feat(parser+engine): Gideon of the Trials — compound conditional emblem locks#6127

Merged
matthewevans merged 1 commit into
phase-rs:mainfrom
mcbradd:card/gideon-of-the-trials
Jul 18, 2026
Merged

feat(parser+engine): Gideon of the Trials — compound conditional emblem locks#6127
matthewevans merged 1 commit into
phase-rs:mainfrom
mcbradd:card/gideon-of-the-trials

Conversation

@mcbradd

@mcbradd mcbradd commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements Gideon of the Trials (AKH #14), with the emblem's compound conditional lock as the class-level target: "As long as you control a Gideon planeswalker, you can't lose the game and your opponents can't win the game."

  • Emblem bodies parse to multiple condition-gated statics (parse_static_line_multi): the can't-lose/can't-win conjunct splits into CantLoseTheGame + CantWinTheGame, each gated on IsPresent(Gideon planeswalker, you).
  • Both statics live in the command zone and are evaluated there (CR 114.4 seam built for Angel's Grace, Add Angel's Grace #6093).
  • Card-name normalizer keeps subtype-word short names literal in type-adjective position ("a Gideon planeswalker", CR 205.3j) while subject uses still normalize to ~.

Root cause (why the emblem never appeared)

Standalone emblem-granting spell lines (You get an emblem with "…") were misclassified by the spell IR loop: the quoted static body ("can't lose the game") pattern-matched as a static ability, so the line never reached the effect parser and no emblem was created. Fixed at the classification seam — should_defer_spell_to_effect now defers any line whose head matches the shared combinator predicate is_emblem_creation_head (single authority, reused from the effect parser; both call sites spell-scoped).

Class coverage

  • Any emblem whose body contains static-looking text (Gideon of the Trials, Teferi Hero of Dominaria–style bodies, etc.) now classifies correctly — the fix is at the head predicate, not per-card.
  • Multi-static emblem bodies generalize: any conjunct of continuous effects inside one emblem line yields N gated statics.
  • Condition gate (as long as you control …) goes through the shared condition combinator, not bespoke matching.

CR citations (all verified against MagicCompRules.txt)

  • CR 104.2b / 104.3e — can't-win / can't-lose replacement of win/loss events
  • CR 611.3a — conditional continuous effects from static abilities
  • CR 114.1 / 114.4 — emblems are command-zone objects with static abilities
  • CR 205.3j — "Gideon" is a planeswalker subtype word

Tests

  • 4 new integration tests (gideon_trials_emblem.rs): emblem materializes on −0; loss SBA blocked per-controller while a Gideon is controlled; opponents' win events blocked; protection evaporates when the last Gideon leaves.
  • Permanent parser probe: standalone spell emblem grant parses to CreateEmblem (guards the classifier seam).
  • 147 targeted parser lib tests pass; full pre-push gate (fmt, clippy, card-data release validate, combinator Gates A+G, parser tests, frontend type-check) green.

🤖 Generated with Claude Code

@mcbradd
mcbradd requested a review from matthewevans as a code owner July 18, 2026 01:44

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements support for parsing and executing compound, condition-gated game-outcome locks, specifically targeting Gideon of the Trials' emblem. It introduces a parser for compound win/lose statics, updates the card name normalizer to keep subtype-word occurrences literal when preceding a core-type word, and defers emblem-granting spells to the effect-chain parser. Comprehensive unit and integration tests are added to verify the rules and parser behavior. No review comments were provided, and the changes are highly idiomatic and compliant with the MTG Comprehensive Rules and repository guidelines.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@matthewevans matthewevans self-assigned this Jul 18, 2026
@matthewevans matthewevans added the feature Larger-scoped feature label Jul 18, 2026
@matthewevans matthewevans removed their assignment Jul 18, 2026
…em locks

Emblem bodies now parse to multiple condition-gated statics
(parse_static_line_multi); "you can't lose the game and your opponents
can't win the game" splits into CantLoseTheGame/CantWinTheGame, each
gated on IsPresent(Gideon planeswalker, you) (CR 104.2b/104.3e,
CR 611.3a, CR 114.4, CR 205.3j). Standalone emblem-granting
instants/sorceries now defer to the effect parser via the shared
is_emblem_creation_head predicate in should_defer_spell_to_effect —
previously the quoted static body misclassified the line as a static
pattern and the emblem was never created. Card-name normalizer keeps
subtype-word short names literal in type-adjective position
("a Gideon planeswalker") while subject uses still normalize.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@matthewevans
matthewevans force-pushed the card/gideon-of-the-trials branch from 910530d to e9b071b Compare July 18, 2026 02:07
@matthewevans

Copy link
Copy Markdown
Member

Maintainer rebase and implementation review completed on e9b071b676a8e97a1f138c4d0ff31c6208341cce. The conflict retained the independent Azor’s Gateway regression alongside the Gideon coverage. The compound game-outcome static parser is full-line scoped and condition-gated; the emblem deferral uses the existing quote-boundary predicate. No review finding remains. Awaiting the new GitHub CI run before approval/enqueue.

@github-actions

Copy link
Copy Markdown

Parse changes introduced by this PR · 10 card(s), 19 signature(s) (baseline: main 824b885997d8)

🟢 Added (9 signatures)

  • 1 card · ➕ trigger/Blocks · added: Blocks (active in=battlefield, valid target=creature, watches=self)
    • Affected (first 3): Wall of Caltrops
  • 1 card · ➕ trigger/ChangesZone · added: ChangesZone (active in=battlefield, to=battlefield, watches=another you control artifact)
    • Affected (first 3): Eye of Malcator
  • 1 card · ➕ trigger/ChangesZone · added: ChangesZone (active in=battlefield, to=battlefield, watches=self)
    • Affected (first 3): Knight of the New Coalition
  • 1 card · ➕ ability/CreateEmblem · added: CreateEmblem (kind=activated, timing=sorcery speed)
    • Affected (first 3): Gideon of the Trials
  • 1 card · ➕ ability/DestroyAll · added: DestroyAll (filter=creature non-Rat)
    • Affected (first 3): Rat of God
  • 1 card · ➕ trigger/Drawn · added: Drawn (active in=battlefield, constraint=on your 2th draw this turn, valid target=you)
    • Affected (first 3): Detective of the Month
  • 1 card · ➕ ability/Pump · added: Pump (duration=until end of turn, kind=activated, p/t=+1/+1, target=creature ~)
    • Affected (first 3): Assembly-Worker
  • 1 card · ➕ ability/Token · added: Token (kind=activated, token=+0/+1 Blue Plant Wall (Creature Plant Wall) with Defender)
    • Affected (first 3): Wall of Kelp
  • 1 card · ➕ ability/grant static ability, grant static ability · added: grant static ability, grant static ability (affects=parent target, grants=grant static ability, grants=grant static ability, target=parent target)
    • Affected (first 3): The Book of Exalted Deeds

🔴 Removed (9 signatures)

  • 1 card · ➖ trigger/Blocks · removed: Blocks (active in=battlefield, valid target=creature, watches=self)
    • Affected (first 3): Wall of Caltrops
  • 1 card · ➖ trigger/ChangesZone · removed: ChangesZone (active in=battlefield, to=battlefield, watches=another you control artifact)
    • Affected (first 3): Eye of Malcator
  • 1 card · ➖ trigger/ChangesZone · removed: ChangesZone (active in=battlefield, to=battlefield, watches=self)
    • Affected (first 3): Knight of the New Coalition
  • 1 card · ➖ ability/CreateEmblem · removed: CreateEmblem (kind=activated, timing=sorcery speed)
    • Affected (first 3): Gideon of the Trials
  • 1 card · ➖ ability/DestroyAll · removed: DestroyAll (filter=creature non-~)
    • Affected (first 3): Rat of God
  • 1 card · ➖ trigger/Drawn · removed: Drawn (active in=battlefield, constraint=on your 2th draw this turn, valid target=you)
    • Affected (first 3): Detective of the Month
  • 1 card · ➖ ability/Pump · removed: Pump (duration=until end of turn, kind=activated, p/t=+1/+1, target=any)
    • Affected (first 3): Assembly-Worker
  • 1 card · ➖ ability/Token · removed: Token (kind=activated, token=+0/+1 Blue Plant ~ (Creature Plant ~) with Defender)
    • Affected (first 3): Wall of Kelp
  • 1 card · ➖ ability/grant static ability · removed: grant static ability (affects=parent target, grants=grant static ability, target=parent target)
    • Affected (first 3): The Book of Exalted Deeds

🟡 Modified fields (1 signature)

  • 1 card · 🔄 ability/Tap · changed field target: untappeduntapped you control Wall
    • Affected (first 3): Wall of Fortune

2 card(s) had Oracle-text changes (errata/reprint) — excluded as non-parser.

@matthewevans matthewevans self-assigned this Jul 18, 2026
@matthewevans matthewevans added enhancement New feature or request and removed feature Larger-scoped feature labels Jul 18, 2026

@matthewevans matthewevans left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved after current-head implementation review. The rebased branch preserves both independent parser regressions. The required parse-diff shows the intended subtype-word/type-adjective class (ten cards), with no unexplained surface. The shared emblem-head and static-condition seams are used, all required checks and trust/security gates are green, and no blocking feedback remains.

@matthewevans
matthewevans added this pull request to the merge queue Jul 18, 2026
@matthewevans matthewevans removed their assignment Jul 18, 2026
Merged via the queue into phase-rs:main with commit c722501 Jul 18, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants