Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions crates/engine/src/parser/oracle_replacement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,12 @@
return Some(def);
}

if nom_primitives::scan_contains(&norm_lower, "double all damage") {
if let Some(def) = parse_global_damage_double_replacement(&norm_lower, &text) {
return Some(def);
}
}

// --- "If [source] would deal [noncombat] damage ... it deals that much damage plus N instead" ---
// CR 614.1a: Damage boost/reduction replacement effects.
if nom_primitives::scan_contains(&lower, "would deal")
Expand Down Expand Up @@ -6105,6 +6111,71 @@
.parse(input)
}

/// CR 614.1a: Global "Double all damage … would deal" doublers.
fn parse_global_damage_double_replacement(
norm_lower: &str,
original_text: &str,
) -> Option<ReplacementDefinition> {
let (_, rest) = split_once_on_lower(original_text, norm_lower, "double all damage ")?;
let (source_filter, tail) = if let Ok((rest, _)) =
tag::<_, _, OracleError<'_>>("~ would deal").parse(rest)
{
(Some(TargetFilter::SelfRef), rest)
} else if let Ok((rest, _)) =
tag::<_, _, OracleError<'_>>("that permanent sources you control would deal").parse(rest)
{
(
Some(TargetFilter::Typed(
TypedFilter::permanent().controller(ControllerRef::You),
)),
rest,
)
} else if let Ok((rest, _)) =
tag::<_, _, OracleError<'_>>("that creature sources you control would deal").parse(rest)
{
(
Some(TargetFilter::Typed(
TypedFilter::creature().controller(ControllerRef::You),
)),
rest,
)
} else if let Ok((rest, _)) =
tag::<_, _, OracleError<'_>>("that sources you control would deal").parse(rest)
{
(
Some(TargetFilter::Typed(
TypedFilter::default().controller(ControllerRef::You),
)),

Check warning on line 6148 in crates/engine/src/parser/oracle_replacement.rs

View workflow job for this annotation

GitHub Actions / Rust lint (fmt, clippy, parser gate)

Diff in /home/runner/work/phase/phase/crates/engine/src/parser/oracle_replacement.rs
rest,
)
} else if let Ok((rest, _)) = tag::<_, _, OracleError<'_>>(
"that sources you control of the chosen type would deal",
)
.parse(rest)
{
(
Some(TargetFilter::Typed(
TypedFilter::default().controller(ControllerRef::You),
)),
rest,
)
} else {
return None;
};
if !tail.trim_end_matches('.').trim().is_empty()
&& !nom_primitives::scan_contains(tail, "instead")
{
return None;
}
let mut def = ReplacementDefinition::new(ReplacementEvent::DamageDone)
.damage_modification(DamageModification::Double)
.description(original_text.to_string());
if let Some(sf) = source_filter {
def = def.damage_source_filter(sf);
}
Some(def)
}

/// CR 614.1d: Parse "enters tapped unless a player has N or less life" (bond lands).
/// Extract "unless a player has N or less life" condition (bond lands).
/// CR 614.1d
Expand Down Expand Up @@ -12004,6 +12075,17 @@
);
assert_eq!(def.valid_player, Some(ReplacementPlayerScope::You));
}

#[test]
fn parses_global_damage_double_sources_you_control() {
let def = parse_replacement_line(
"Double all damage that sources you control of the chosen type would deal.",
"Collective Inferno",
)
.expect("global doubler");

Check warning on line 12085 in crates/engine/src/parser/oracle_replacement.rs

View workflow job for this annotation

GitHub Actions / Rust lint (fmt, clippy, parser gate)

Diff in /home/runner/work/phase/phase/crates/engine/src/parser/oracle_replacement.rs
assert_eq!(def.damage_modification, Some(DamageModification::Double));
}

}

/// Snapshot tests locking current replacement parser output before/after the IR split.
Expand Down
Loading