Fix The Boulder, Ready to Rumble#5881
Conversation
…d keeps the land target (phase-rs#4729) The Boulder, Ready to Rumble ("earthbend X, where X is the number of creatures you control with power 4 or greater") only recognized the counter-count where-clause shape. Object counts fell through to the bare-X branch, binding X to Variable{X} (resolves to 0 for a triggered ability) and mis-reading the trailing "where X is …" text as an explicit target, degrading it to TargetFilter::Any. Generalize parse_earthbend_count_expr to route any "where X is <quantity>" through the shared parse_quantity_ref (object counts incl. P/T restrictions, subtype counts, player-counter counts) then parse_event_context_quantity (mana spent to cast). A matched where-clause now always resolves to default_earthbend_target(), so no unsupported shape can re-degrade the target. Covers The Boulder, Rockalanche, and Toph, Greatest Earthbender. CR 701.66a (Earthbend) + CR 107.3 (an ability defines the value of X). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request updates the MTG engine's parser for earthbend effects to properly handle general 'where X is ' clauses in accordance with CR 701.66a and CR 107.3. Instead of degrading the target to TargetFilter::Any and failing to parse complex quantities, the parser now routes the clause through shared quantity parsers (parse_quantity_ref and parse_event_context_quantity) and correctly preserves the default earthbend target ('target land you control'). Comprehensive unit and integration tests have been added to verify these changes. There are no review comments to assess, and no additional feedback is provided.
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.
Parse changes introduced by this PR · 6 card(s), 1 signature(s) (baseline: main
|
matthewevans
left a comment
There was a problem hiding this comment.
Verdict: Changes requested
🔴 Blocker
parse_earthbend_count_exprnow accepts everyEarthbend X, where X is …clause, but an unrecognized quantity is deliberately lowered toQuantityRef::Variable("X")(crates/engine/src/parser/oracle_effect/imperative.rs:561-572). In triggered abilities that variable has no announced spell-cost X and resolves to 0, so the card is reported as parsed/supported while applying the wrong number of counters. The newglorbstest codifies that silent fallback (imperative.rs:14999-15023). Keep the default land target, but preserve anEffect::Unimplemented/strict-failure marker when the where-body cannot be parsed, rather than accepting the full clause with a fake X value.
🟡 Non-blocking
- None.
✅ Clean
- No additional findings.
Recommendation: Please address the unsupported-where-clause fallback, then request re-review.
…gap, not a fake Variable{X} (phase-rs#4729)
Addressing matthewevans's review on PR phase-rs#5881: parse_earthbend_count_expr
accepted every "earthbend X, where X is …" clause, lowering an
unrecognized quantity to QuantityRef::Variable("X"). In a triggered
ability that X has no announced spell-cost value and resolves to 0, so the
card was reported as parsed/supported while applying the wrong number of
counters — a well-typed lie.
parse_earthbend_count_expr now returns Option; a present-but-unparseable
where-body yields None, and try_parse_earthbend_clause surfaces an honest
Effect::unimplemented("where_x_binding", …) gap so coverage counts the
card as unsupported until the quantity is handled. Recognized quantities
(object counts incl. P/T restrictions, subtype counts, player-counter
counts, mana-spent-to-cast) and the genuine bare "earthbend X" spell-cost
path are unchanged. The prior test that codified the silent Variable{X}
fallback now asserts the strict failure, plus an end-to-end assertion that
the clause lowers to Effect::Unimplemented.
CR 107.3 (an ability defines the value of X).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Addressed the blocker in What changed: Unchanged: recognized quantities (object counts incl. the Tests: the Verification on the new head: Ready for re-review. |
matthewevans
left a comment
There was a problem hiding this comment.
Verdict: Changes requested
🔴 Blocker
- The new coverage is still parser/AST-only for The Boulder. Please add one runtime witness that parses the card's actual attack trigger, extracts the Earthbend
PutCounter.count, and resolves it against a board with exactly two qualifying friendly creatures (power 4 and 6), one non-qualifying friendly creature (power 3), and an opponent's qualifying creature. Assert2. This must fail for the prior unbound-X behavior (0), for a dropped power restriction (3), and for a dropped controller restriction (4).counters::resolve_addconsumes this quantity throughresolve_quantity_with_targets, so this protects the reported counter-resolution behavior rather than merely its AST shape.
🟡 Non-blocking
- Update the
parse_earthbend_count_exprdispatch-order doc comment: it still says unknown shapes becomeFixed { value: 0 }, but the implementation now returnsNonefor an unrecognized presentwhere X is …body and the caller emitsEffect::Unimplemented.
✅ Clean
- The strict-failure change itself is correct: recognized bodies route through the shared quantity parsers, preserve the default
target land you control, and no longer silently accept an unknownwhere X is …quantity as an unboundX.
Recommendation: Add the focused runtime witness and align the contract comment, then request re-review.
Summary
Fixes the "
where X is <object count>" earthbend misparse for The Boulder, Ready to Rumble.parse_earthbend_count_expronly recognized thewhere X is <counter count>shape. For an object-count X ("the number of creatures you control with power 4
or greater"), it fell through to the bare-X branch, which bound X to
QuantityRef::Variable{X}— resolving to 0 for a triggered ability — andmis-read the leftover "where X is…" text as an explicit target, degrading it to
TargetFilter::Any. The trigger fired but resolved to nothing.The where-clause handler is generalized to route any "where X is
<dynamic quantity>" through the shared building blocksparse_quantity_ref(object counts incl. P/T restrictions, subtype counts, player-counter counts)
then
parse_event_context_quantity(mana spent to cast). A matched where-clausenow always resolves to
default_earthbend_target()("target land you control"),so no unsupported shape can re-degrade the target. Covers the whole class: The
Boulder, Rockalanche ("Forests you control"), and Toph, Greatest Earthbender
("the amount of mana spent to cast her").
Closes #4729
Files changed
CR references
Implementation method (required)
Method: /engine-implementer
Track
Developer
LLM
Model: claude-opus-4-8
Thinking: high
Tier: Frontier
Verification
Required checks ran clean, or the exact CI-owned alternative is stated below.
Gate A output below is for the current committed head.
Final review-impl below is clean for the current committed head.
Both anchors cite existing analogous code at the same seam.
cargo fmt --all— cleanparser combinator gate (Gate A + Gate G) — PASS
parser lib tests — 8191 PASS
cargo clippy -p engine --lib— cleanearthbend tests — 15 pass, 5 new (object-count-with-power-restriction,
subtype count, mana-spent, unrecognized-where-clause-keeps-default-target,
end-to-end The Boulder synthesis: Animate→land target + PutCounter→ObjectCount count)
Gate A
Gate A PASS head=68cb1e61531c53f036fbad592dc048f7cae26a04 base=c0d7e0f3a5d65c22b475491f0556a2655777980f
Anchored on
parse_earthbend_paramsalready delegates a dynamic count toparse_quantity_ref; the new where-clause branch mirrors that building-block delegationtry_parse_earthbend_clausethreads the parsed(target, count)intoEffect::Animate.target+Effect::PutCounter.count; the fix changes only what the count parser returns, reusing this wiring unchangedFinal review-impl
Final review-impl PASS head=68cb1e61531c53f036fbad592dc048f7cae26a04
Claimed parse impact
Validation Failures
None.
CI Failures
None.
🤖 Generated with Claude Code