Skip to main content

manabrew_engine/replacement/
replace_life_reduced.rs

1//! Replacement logic for `Event$ LifeReduced`.
2//!
3//! Mirrors Java `ReplaceLifeReduced.java` in `forge/game/replacement/`.
4
5use crate::card::Card;
6use crate::game::GameState;
7use crate::ids::CardId;
8use crate::parsing::compare::compare_expr;
9
10use super::replacement_effect::ReplacementEffect;
11use super::replacement_handler::{execute_replace_with_numeric_update, ReplacementEvent};
12use super::replacement_result::ReplacementResult;
13use super::replacement_type::ReplacementType;
14use crate::card_trait_base::CardTrait;
15
16/// Mirrors Java `ReplaceLifeReduced.canReplace()`.
17pub fn can_replace(
18    effect: &ReplacementEffect,
19    event: &ReplacementEvent,
20    _game: &GameState,
21    source_card: &Card,
22) -> bool {
23    if effect.event != ReplacementType::LifeReduced {
24        return false;
25    }
26    let (player, amount, is_damage) = match event {
27        ReplacementEvent::LifeReduced {
28            player,
29            amount,
30            is_damage,
31        } => (*player, *amount, *is_damage),
32        _ => return false,
33    };
34    if amount <= 0 {
35        return false;
36    }
37    if let Some(valid) = effect.ir.valid_player_selector.as_ref() {
38        if !effect.matches_compiled_valid_player(valid, player, source_card) {
39            return false;
40        }
41    }
42    // Check IsDamage filter if present.
43    if let Some(expected) = effect.ir.is_damage {
44        if is_damage != expected {
45            return false;
46        }
47    }
48    if let Some(result_cmp) = effect.ir.result_text.as_deref() {
49        let final_life = _game.player(player).life - amount;
50        let rhs = result_cmp
51            .get(2..)
52            .and_then(|n| n.parse::<i32>().ok())
53            .unwrap_or(0);
54        let cmp = format!("{}{}", result_cmp.get(..2).unwrap_or("GE"), rhs);
55        if !compare_expr(final_life, &cmp) {
56            return false;
57        }
58    }
59    true
60}
61
62/// Mirrors Java `ReplacementHandler.executeReplacement()` for LifeReduced.
63pub fn execute(
64    effect: &ReplacementEffect,
65    event: &mut ReplacementEvent,
66    _game: &GameState,
67    _source_card_id: CardId,
68) -> ReplacementResult {
69    match event {
70        ReplacementEvent::LifeReduced { .. } => {}
71        _ => return ReplacementResult::NotReplaced,
72    }
73    if effect.prevents() {
74        if let ReplacementEvent::LifeReduced { amount, .. } = event {
75            *amount = 0;
76        }
77        return ReplacementResult::Prevented;
78    }
79    if let Some(result) =
80        execute_replace_with_numeric_update(effect, event, _game, _source_card_id, "Amount")
81    {
82        return result;
83    }
84    ReplacementResult::Replaced
85}