From 17fc0c43bfd6ccb3a3c49fc6be5f1cbc76d3f128 Mon Sep 17 00:00:00 2001 From: glorysr1209-png Date: Mon, 15 Jun 2026 16:45:46 -0400 Subject: [PATCH] feat(parser): parse explore replacement with scry prelude --- .../engine/src/parser/oracle_replacement.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/crates/engine/src/parser/oracle_replacement.rs b/crates/engine/src/parser/oracle_replacement.rs index 98cc27d253..59d312039a 100644 --- a/crates/engine/src/parser/oracle_replacement.rs +++ b/crates/engine/src/parser/oracle_replacement.rs @@ -540,6 +540,14 @@ fn parse_replacement_line_inner(text: &str, card_name: &str) -> Option Option Option { + let (rest, _) = tag::<_, _, OracleError<'_>>("if a creature you control would explore, ") + .parse(norm_lower) + .ok()?; + let (rest, _) = tag::<_, _, OracleError<'_>>("instead you scry 1, then that creature explores") + .parse(rest) + .ok()?; + let (_, _) = all_consuming(opt(tag::<_, _, OracleError<'_>>("."))) + .parse(rest) + .ok()?; + let scry = AbilityDefinition::new( + AbilityKind::Spell, + Effect::Scry { + count: QuantityExpr::Fixed { value: 1 }, + target: TargetFilter::Controller, + }, + ); + let explore = AbilityDefinition::new(AbilityKind::Spell, Effect::Explore); + Some( + ReplacementDefinition::new(ReplacementEvent::Explore) + .execute(scry.sub_ability(explore)) + .description(original_text.to_string()), + ) +} + fn parse_unconditional_life_floor_damage_replacement( norm_lower: &str, ) -> Option { @@ -12004,6 +12041,17 @@ mod tests { ); assert_eq!(def.valid_player, Some(ReplacementPlayerScope::You)); } + + #[test] + fn parses_explore_replacement_with_scry() { + let def = parse_replacement_line( + "If a creature you control would explore, instead you scry 1, then that creature explores.", + "Twists and Turns", + ) + .expect("explore replacement"); + assert_eq!(def.event, ReplacementEvent::Explore); + } + } /// Snapshot tests locking current replacement parser output before/after the IR split.