Skip to content

parser: compound-subject animation static strict-fails (Bello, Bard of the Brambles) #5442

Description

@claytonlin1110

Summary

Bello, Bard of the Brambles (Bloomburrow Commander)'s compound-subject animation static —

"During your turn, each non-Equipment artifact and non-Aura enchantment you control with mana value 4 or greater is a 4/4 Elemental creature in addition to its other types and has indestructible, haste, and 'Whenever this creature deals combat damage to a player, draw a card.'"

(Oracle text verified against the Scryfall API) — currently strict-fails (verified against data/coverage-data.json: supported: false, single gap "Effect:static_structure" pointing at the entire line); the whole line collapses into an Unimplemented ability.

This is the same structural gap shape as #5219 (Life and Limb's compound-subject animation static) and #5392/#5406 (Rukarumel's compound-subject chosen-type static): a compound subject joined by "and" where each individual conjunct is already independently resolvable, and the animation+keyword+ability-grant predicate is already independently resolvable — but the combination of a two-conjunct compound subject with this predicate class is unreached.

Proof the pieces are already independently correct

Two real, currently-supported: true cards confirm every constituent piece of Bello's line already works in isolation (verified against data/coverage-data.json):

  • Starfield of Nyx: "each other non-Aura enchantment you control is a creature in addition to its other types" — proves the single negated-type conjunct ("non-Aura enchantment you control ... is a creature in addition to its other types") already resolves correctly, including the non- prefix and the CR 205.1b additive "in addition to its other types" marker.
  • Mephidross Vampire: "Each creature you control is a Vampire in addition to its other creature types and has 'Whenever this creature deals damage to a creature, put a +1/+1 counter on this creature.'" — proves the combined animation + CR 205.1b additive-type + granted-ability-string predicate (the "is a <type> ... in addition to its other types and has '<ability>'" shape) already resolves correctly for a single subject.

Between them, these are the two halves Bello combines: a compound ("non-Equipment artifact and non-Aura enchantment") subject, each half individually proven by Starfield of Nyx's negated-type-conjunct pattern, applied to the animation+ability-grant predicate shape Mephidross Vampire already proves — plus a keyword list (indestructible, haste) folded into the same has ... and "..." clause, and a During your turn, turn-window gate (an established, separately-supported CR 611.3a condition prefix elsewhere in the codebase). So this is not a predicate gap — it is purely a compound-subject gap, structurally identical to the class #5219/#5406 already generalized for other predicate families.

Root cause (to be traced precisely at implementation time)

The existing compound-subject animation dispatcher, parse_compound_all_subjects_type_change (crates/engine/src/parser/oracle_static/type_change.rs, the #5219 fix), only matches the plural "All <X> and all <Y> are <predicate>" grammar (repeated all quantifier before each conjunct, plural copula are). Bello uses the singular "each <X> and <Y> ... is a <predicate>" grammar (one shared each quantifier, singular copula is a) — a different surface grammar over the same underlying CR 611.3/CR 205.1b semantics, so parse_compound_all_subjects_type_change declines it and it falls through to whatever single-subject "each <X> you control is a ..." dispatcher handles Starfield of Nyx / Mephidross Vampire, which in turn only accepts a single leaf subject (not an "<X> and <Y>" compound before the copula).

Needs tracing at implementation time to confirm the exact single-subject dispatcher (candidates: a sibling of parse_each_noncreature_subject_is_creature_with_pt_mv in type_change.rs, or a dispatcher in oracle_effect/animation.rs) and exactly which stage drops the second ("and non-Aura enchantment") conjunct.

Proposed fix (mirrors #5219 / #5406's structural shape)

Add a compound-subject sibling for this "each <X> and <Y> ... is a <predicate>" class, following the same shape as #5219 and #5406:

  1. A new parser function that recognizes the singular "each <X> and <Y> [you control] [with <suffix>] is a/an <predicate>" shape, resolves each conjunct's leaf subject independently (reusing whatever single-conjunct subject resolver already serves Starfield of Nyx), and Or-combines them — distributing any shared suffix (controller, mana-value gate) to every leg, mirroring distribute_controller_to_or / the Or-union pattern used throughout the compound-subject family.
  2. Declines unless the subject is a genuine compound (2+ conjuncts) so single-subject lines (Starfield of Nyx, Mephidross Vampire) keep routing to their existing dispatcher unchanged.
  3. Delegates the entire predicate ("is a 4/4 Elemental creature in addition to its other types and has indestructible, haste, and '<ability>'") to the already-general parse_continuous_gets_has (or whatever predicate builder Mephidross Vampire's line already routes through) rather than reinventing animation/keyword/ability-grant parsing — matching feat(parser): compound-subject chosen-type static (Rukarumel, Biologist) (#5392) #5406's "own only the subject-compound delegation, reuse the existing predicate builder wholesale" discipline.
  4. Wires the leading During your turn, condition the same way other turn-window-gated statics already do (e.g. StaticCondition::DuringYourTurn, as used by parse_compound_subject_keyword_static for the Gruul Spellbreaker class).
  5. Tests: a parser-shape test on the modeled compound sentence (asserting the Or of two negated-type Typed filters, the AddType{Creature} + base-P/T + AddKeyword modifications, and the granted-ability string), a full-oracle test for Bello, and no-regression tests confirming Starfield of Nyx and Mephidross Vampire (single-subject) still parse unchanged.

No new ContinuousModification / Layer / runtime is expected — AddType, base P/T setting (Layer 7b), AddKeyword, and ability-granting are all already exercised end-to-end by Starfield of Nyx and Mephidross Vampire.

CR references (grep-verified against docs/MagicCompRules.txt at implementation time)

  • CR 611.3 — a continuous static effect applies to every object its text indicates (the compound Or-distributed affected set).
  • CR 205.1b — additive type/subtype grants ("in addition to its other types").
  • CR 613.1d / CR 613.4b — Layer 4 (type change) and Layer 7b (base P/T) continuous effects.
  • CR 611.3a — turn-window ("During your turn") condition gating.

Scope

Parser-only (crates/engine/src/parser/oracle_static/type_change.rs and/or oracle_effect/animation.rs, plus their test files) — no engine types/runtime changes expected, matching #5219's and #5406's file footprint.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions