fix(parser): count "the number of <type> you control with <keyword>" (Axebane Guardian, Doorkeeper)#5059
Conversation
…(Axebane Guardian, Doorkeeper) The "the number of" quantity grammar had a combinator for the battlefield-wide "<type> on the battlefield with <keyword>" form (parse_number_of_type_on_battlefield_with_keyword, backing Dauthi Warlord) but none for the controller-scoped "<type> you control with <keyword>" form. The bare parse_number_of_controlled_type arm matched "creatures you control" and stranded " with defender" as an unconsumed remainder, so the whole "the number of" quantity failed to fully consume and the dependent value (X mana / mill / damage / P-T) was silently dropped. Add parse_number_of_controlled_type_with_keyword, registered ahead of the bare controlled-type arm so the longer keyword-qualified form is tried first. The controller axis is generalized via parse_quantity_controller_suffix (you control / your opponents control / the chosen player controls, CR 109.4) and the keyword axis over the full KEYWORDS table via parse_keyword_name + FilterProp::WithKeyword. The keyword name is mapped through Keyword's FromStr with map_res so an unconvertible name fails the parse gracefully rather than panicking. Backs the "the number of creatures you control with defender" cycle: Axebane Guardian, Doorkeeper, Coral Colony, and Vent Sentinel. Model: claude-opus-4-8[1m] (via Claude Code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Holding current head This changes parser quantity dispatch in |
Parse changes introduced by this PR✓ No card-parse changes detected. |
matthewevans
left a comment
There was a problem hiding this comment.
Reviewed current head 469bf68. This is safe as parser architecture coverage for the distinct 'the number of you control with ' grammar path: it composes existing type/controller/keyword parser building blocks, is not redundant with #5019/#5075's 'for each' path, and has focused tests for controller/opponent scope plus the non-shadowing bare form. Parse-diff reports no card-output changes, so I am approving this as canonical parser-path cleanup rather than a new card-data unlock.
Problem (#5058)
The
the number ofquantity grammar could not parse a controller-scoped count gated on a keyword predicate —the number of <type> you control with <keyword>:The dispatch already had the battlefield-wide
parse_number_of_type_on_battlefield_with_keyword(<type> on the battlefield with <keyword>, backing Dauthi Warlord) and the bareparse_number_of_controlled_type(<type> you control), but no controller-scoped keyword-qualified arm. The bare arm matchedcreatures you controland strandedwith defender, so the wholethe number ofquantity failed and the dependent value (X mana / mill / damage) was silently dropped.Fix (
oracle_nom/quantity.rs)parse_number_of_controlled_type_with_keyword, registered in thethe number ofalt()immediately beforeparse_number_of_controlled_typeso the longer keyword-qualified form is tried first.parse_quantity_controller_suffix(you control / your opponents control / the chosen player controls, CR 109.4) and the keyword axis over the fullKEYWORDStable viaparse_keyword_name+FilterProp::WithKeyword.Keyword'sFromStrwithmap_res, so an unconvertible name fails the parse as a graceful nom error rather than panicking.No new AST/variant — it composes existing building blocks (
parse_type_filter_word+parse_quantity_controller_suffix+parse_keyword_name), producing the sameQuantityRef::ObjectCountshape the resolver already evaluates.Before / after
Result
Axebane Guardian's mana, Doorkeeper's/Coral Colony's mill, and Vent Sentinel's damage now scale with the count of Defender creatures the controller has. The combinator covers the whole
<type> <controller> with <keyword>the number ofclass, not just these cards, and is the controller-scoped counterpart of the existing battlefield-wide keyword count.Implementation method (required)
/engine-implementerpipeline/engine-implementer— explain why belowCR references
Testing
Local toolchain has no MSVC/mingw linker, so the test binaries can't be linked/run here — only the non-linking checks were run:
cargo fmt --all -- --check— clean.cargo check -p engine --lib --tests— clean.New tests (written to the conventions of the existing suite; please let CI's
nextestbe the gate):parse_number_of_controlled_type_with_keyword_scoped_count(oracle_nom/quantity.rs) — asserts the controller scope (you control / your opponents control) and theFilterProp::WithKeywordpredicate fordefender/flying.parse_number_of_controlled_type_bare_no_keyword_still_parses— guards that the new arm does not shadow the bareyou controlcount.Model: claude-opus-4-8[1m] (via Claude Code)
Closes #5058