From 1a328f0835379a1829716f8ca73579b4d0dcd0f0 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Wed, 12 Aug 2026 15:35:01 -0700 Subject: [PATCH 1/3] fix(parser): gate same-name artifact wins --- .../engine/src/parser/oracle_nom/condition.rs | 8 +++- crates/engine/src/parser/oracle_tests.rs | 41 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/parser/oracle_nom/condition.rs b/crates/engine/src/parser/oracle_nom/condition.rs index 72f1a1d872..1265fc71a9 100644 --- a/crates/engine/src/parser/oracle_nom/condition.rs +++ b/crates/engine/src/parser/oracle_nom/condition.rs @@ -3879,7 +3879,8 @@ fn parse_control_count_ge_distinct_quality(input: &str) -> OracleResult<'_, Stat )) } -/// CR 201.2 + CR 109.3: Parse "you control N or more [type] with the same name" +/// CR 201.2 + CR 109.3: Parse "you control N or more [type] with the same name +/// as one another" /// → `QuantityComparison(ObjectCountBySharedQuality[Name, Max] >= N)`. /// /// The same-quality mirror of `parse_control_count_ge_distinct_quality`. Both read @@ -3907,7 +3908,10 @@ fn parse_control_count_ge_shared_quality(input: &str) -> OracleResult<'_, Static let trimmed = remainder.trim_start(); let (after_suffix, quality) = preceded( tag("with the same "), - alt((value(SharedQuality::Name, tag("name")),)), + terminated( + alt((value(SharedQuality::Name, tag("name")),)), + opt(tag(" as one another")), + ), ) .parse(trimmed)?; let filter = inject_controller_you(filter); diff --git a/crates/engine/src/parser/oracle_tests.rs b/crates/engine/src/parser/oracle_tests.rs index b8dba929b3..0d7b84c244 100644 --- a/crates/engine/src/parser/oracle_tests.rs +++ b/crates/engine/src/parser/oracle_tests.rs @@ -6882,6 +6882,47 @@ fn thassas_oracle_win_condition_gated_by_devotion_vs_library() { ); } +#[test] +fn mechanized_production_win_requires_eight_artifacts_sharing_a_name() { + let r = parse( + "Enchant artifact you control\nAt the beginning of your upkeep, create a token that's a copy of enchanted artifact. Then if you control eight or more artifacts with the same name as one another, you win the game.", + "Mechanized Production", + &[], + &["Enchantment"], + &["Aura"], + ); + let trigger = r + .triggers + .first() + .expect("Mechanized Production must parse its upkeep trigger"); + let copy = trigger + .execute + .as_deref() + .expect("the upkeep trigger must create the token copy"); + let win = copy + .sub_ability + .as_deref() + .expect("the conditional win must follow the token copy"); + assert!(matches!(*win.effect, Effect::WinTheGame { .. })); + assert_eq!( + win.condition, + Some(AbilityCondition::QuantityCheck { + lhs: QuantityExpr::Ref { + qty: QuantityRef::ObjectCountBySharedQuality { + filter: TargetFilter::Typed( + TypedFilter::artifact().controller(ControllerRef::You) + ), + quality: SharedQuality::Name, + aggregate: AggregateFunction::Max, + }, + }, + comparator: Comparator::GE, + rhs: QuantityExpr::Fixed { value: 8 }, + }), + "the win must be gated by one shared artifact name, not the total artifact count" + ); +} + #[test] fn incubate_parses_as_effect() { let r = parse( From c5090c9a87f1adb4851139cdac636acd8aa7add1 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Wed, 12 Aug 2026 15:59:43 -0700 Subject: [PATCH 2/3] test(parser): use artifact filter constructor --- crates/engine/src/parser/oracle_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/engine/src/parser/oracle_tests.rs b/crates/engine/src/parser/oracle_tests.rs index 0d7b84c244..29c8aefdec 100644 --- a/crates/engine/src/parser/oracle_tests.rs +++ b/crates/engine/src/parser/oracle_tests.rs @@ -6910,7 +6910,7 @@ fn mechanized_production_win_requires_eight_artifacts_sharing_a_name() { lhs: QuantityExpr::Ref { qty: QuantityRef::ObjectCountBySharedQuality { filter: TargetFilter::Typed( - TypedFilter::artifact().controller(ControllerRef::You) + TypedFilter::new(TypeFilter::Artifact).controller(ControllerRef::You) ), quality: SharedQuality::Name, aggregate: AggregateFunction::Max, From 0b2f2575b6d2f24a5894a1afe9bfee813829ba56 Mon Sep 17 00:00:00 2001 From: matthewevans Date: Wed, 12 Aug 2026 16:23:10 -0700 Subject: [PATCH 3/3] test(parser): match artifact battlefield filter --- crates/engine/src/parser/oracle_tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/parser/oracle_tests.rs b/crates/engine/src/parser/oracle_tests.rs index 29c8aefdec..7c6c1a3154 100644 --- a/crates/engine/src/parser/oracle_tests.rs +++ b/crates/engine/src/parser/oracle_tests.rs @@ -6910,7 +6910,11 @@ fn mechanized_production_win_requires_eight_artifacts_sharing_a_name() { lhs: QuantityExpr::Ref { qty: QuantityRef::ObjectCountBySharedQuality { filter: TargetFilter::Typed( - TypedFilter::new(TypeFilter::Artifact).controller(ControllerRef::You) + TypedFilter::new(TypeFilter::Artifact) + .controller(ControllerRef::You) + .properties(vec![FilterProp::InZone { + zone: Zone::Battlefield, + }]) ), quality: SharedQuality::Name, aggregate: AggregateFunction::Max,