Skip to content

feat(parser): parse mixed variable+fixed P/T grant (Cranial Ram +X/+1)#5447

Merged
matthewevans merged 2 commits into
phase-rs:mainfrom
nickmopen:feat/mixed-variable-pt-pump
Jul 9, 2026
Merged

feat(parser): parse mixed variable+fixed P/T grant (Cranial Ram +X/+1)#5447
matthewevans merged 2 commits into
phase-rs:mainfrom
nickmopen:feat/mixed-variable-pt-pump

Conversation

@nickmopen

Copy link
Copy Markdown
Contributor

Problem

parse_variable_pt_pattern restricted each P/T axis of a variable grant to x or 0. A mixed grant — one dynamic axis and one fixed nonzero axis — failed the pattern outright, so the whole static was dropped.

The clearest example is Cranial Ram: Equipped creature gets +X/+1, where X is the number of artifacts you control. The +1 toughness could not be represented, so the equip static produced no P/T modification at all.

Fix

  • parse_variable_pt_pattern (grammar.rs) now parses each axis as either the variable X (dynamic, returned as None) or a fixed integer magnitude (Some(n)).
  • parse_dynamic_pt_in_text (anthem.rs) emits a constant AddPower/AddToughness for a fixed nonzero axis alongside the AddDynamicPower/AddDynamicToughness for the dynamic axis (CR 613.4c layer 7c).
  • A fixed 0 axis still contributes nothing, so +X/+0, -X/-X, +0/+X, etc. are unchanged.

Tests

  • New dynamic_pt_in_text_mixed_dynamic_power_fixed_toughness asserts +X/+1 emits both the X power modification and a constant AddToughness { value: 1 } (and that the fixed axis is not dynamic).
  • All existing dynamic-P/T tests (+X/+0, -X/-0, -X/-X, +0/+X, cost-X defaults) remain green — the fixed-0 path preserves their behavior.
  • Full parser::oracle_static module: 1070 passed. cargo fmt, clippy (-D warnings), and the parser-combinator / engine-authorities gates are clean.

parse_variable_pt_pattern restricted each P/T axis to `x`/`0`, so a
mixed grant such as Cranial Ram's "Equipped creature gets +X/+1, where X
is the number of artifacts you control" failed the pattern outright and
the whole equip static was dropped.

Generalize each axis to carry either the variable X (dynamic) or a fixed
integer magnitude. parse_dynamic_pt_in_text now emits the constant
modification (AddPower/AddToughness) for a fixed nonzero axis alongside
the X-valued modification for the dynamic axis. A fixed 0 axis still
contributes nothing, preserving +X/+0, -X/-X and the other existing
forms (covered by the unchanged dynamic-pt tests).
@nickmopen
nickmopen requested a review from matthewevans as a code owner July 9, 2026 15:12

@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 updates the parser to support mixed dynamic and fixed power/toughness modifications (such as "+X/+1") under CR 613.4c. It refactors parse_variable_pt_pattern to return optional magnitudes for each axis and updates the parser logic to apply either dynamic or constant modifications accordingly. Feedback suggests using nom::combinator::map_res instead of map with unwrap_or(0) to properly propagate integer parsing errors instead of swallowing them.

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.

Comment thread crates/engine/src/parser/oracle_static/grammar.rs Outdated
@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

Parse changes introduced by this PR · 1 card(s), 2 signature(s) (baseline: main e8244c78d4a9)

1 card(s) · static/Continuous · added: Continuous (affects=equipped by self creature, mods=add dynamic power, toughness +1)

Examples: Cranial Ram

1 card(s) · ability/static_structure · removed: static_structure

Examples: Cranial Ram

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

@matthewevans matthewevans added the bug Bug fix label Jul 9, 2026
@matthewevans matthewevans self-assigned this Jul 9, 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.

Maintainer review clean: the mixed X/fixed P/T parser change is at the shared dynamic-P/T seam, Gemini’s stale map_res finding is fixed at head, parse-diff is scoped to Cranial Ram, and required checks are green.

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

Labels

bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants