Recognize "there are no [type] on the battlefield" condition (Sarcomancy, Call to the Grave) - #4917
Conversation
…ce condition
Extend parse_no_on_battlefield to handle the existential there-form
("there are no Zombies on the battlefield" - Sarcomancy; "there are no
creatures on the battlefield" - Drop of Honey, Porphyry Nodes, Task Mage
Assembly) alongside the existing subject-first form ("no creatures are on
the battlefield" - Call to the Grave). Both lower to the same
QuantityComparison(ObjectCount(<filter>) == 0) (CR 603.4 intervening-if +
CR 110.1); the <type> is parsed via parse_type_phrase so subtypes, card
types, and token phrases scope the emptiness check. No controller
restriction - any players matching permanents count. Previously the
|
Warning Gemini encountered an error creating the review. You can try again by commenting |
Parse changes introduced by this PRBaseline pending for |
matthewevans
left a comment
There was a problem hiding this comment.
Maintainer review: parser condition fix is scoped and idiomatic. It extends the existing battlefield-absence condition parser rather than adding a sibling shape, keeps the output as the existing ObjectCount == 0 predicate, and the parse-diff is limited to the expected Sarcomancy / Task Mage Assembly condition gains.
|
Hi @matthewevans — quick labeling note on this one: it landed tagged only |
|
Hello @matthewevans, Thanks for merging these, and for the careful reviews. A calibration question on the Is there a distinction I'm missing, or just triage variance? Happy to match whatever bar you'd prefer. Thanks! |
Summary
Triggers/conditions of the form "there are no [type] on the battlefield" were dropped — the intervening-
ifparsed tocondition: null, so cards like Sarcomancy ("At the beginning of your upkeep, if there are no Zombies on the battlefield, ~ deals 1 damage to you"), Drop of Honey, Porphyry Nodes, and Task Mage Assembly ("when there are no creatures on the battlefield, sacrifice ~") lost their gating condition.The engine already lowered the subject-first form "no [type] are on the battlefield" (Call to the Grave) to
ObjectCount(<filter>) == 0; only the existential there-form was missing.Change
Extend
parse_no_on_battlefield(crates/engine/src/parser/oracle_nom/condition.rs) to recognize both surface forms with one shared output:"there are no <type> on the battlefield"(existential there-form) — new"no <type> are on the battlefield"(subject-first) — existingBoth lower to
StaticCondition::QuantityComparison { ObjectCount(<filter>) == 0 }. A prefixaltselects the surface form and its trailing anchor;<type>is parsed via the sharedparse_type_phrase, so a subtype ("Zombies"), a card type ("lands"), or a token phrase ("Reflection tokens") scopes the emptiness check exactly. No controller restriction — "no creatures" counts any player's matching permanents (CR 603.4 intervening-if; CR 110.1).Nom combinators only (
alt/value/tag/take_until); no new condition type.Tests
Added recognizer tests covering: the there-form ("there are no creatures / Zombies on the battlefield"), the subject-first form, card-type ("no lands"), the battlefield anchor requirement, and a guard that "there are no" is not confused with a count condition. All assert the
ObjectCount == 0lowering with the correct filter and no controller restriction.Fails-before (there-form → dropped condition) / passes-after confirmed. Green: rustfmt, parser-combinator (Rule Zero) gate,
clippy -D warnings, full engine suite, andcargo coverage(net gain, 0 regressions).