Skip to main content

manabrew_engine/replacement/
replace_draw_cards.rs

1//! Replacement logic for `Event$ DrawCards`.
2//!
3//! Mirrors Java `ReplaceDrawCards.java` in `forge/game/replacement/`.
4
5use crate::card::Card;
6use crate::game::GameState;
7use crate::ids::CardId;
8use crate::parsing::compare::compare_expr;
9use crate::parsing::{keys, Params};
10
11use super::replacement_effect::ReplacementEffect;
12use super::replacement_handler::{
13    execute_replace_with_numeric_update, resolve_replace_value, set_replacement_event_amount,
14    ReplacementEvent,
15};
16use super::replacement_result::ReplacementResult;
17use super::replacement_type::ReplacementType;
18use crate::card_trait_base::CardTrait;
19
20/// Mirrors Java `ReplaceDrawCards.canReplace()`.
21pub fn can_replace(
22    effect: &ReplacementEffect,
23    event: &ReplacementEvent,
24    _game: &GameState,
25    source_card: &Card,
26) -> bool {
27    if effect.event != ReplacementType::DrawCards {
28        return false;
29    }
30    let (player, count) = match event {
31        ReplacementEvent::DrawCards { player, count } => (*player, *count),
32        _ => return false,
33    };
34    if count <= 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    if let Some(number_cmp) = effect.ir.number_text.as_deref() {
43        let rhs = number_cmp
44            .get(2..)
45            .and_then(|n| n.parse::<i32>().ok())
46            .unwrap_or(0);
47        let cmp = format!("{}{}", number_cmp.get(..2).unwrap_or("GE"), rhs);
48        if !compare_expr(count, &cmp) {
49            return false;
50        }
51    }
52    true
53}
54
55/// Mirrors Java `ReplacementHandler.executeReplacement()` for DrawCards.
56pub fn execute(
57    effect: &ReplacementEffect,
58    event: &mut ReplacementEvent,
59    _game: &GameState,
60    _source_card_id: CardId,
61) -> ReplacementResult {
62    match event {
63        ReplacementEvent::DrawCards { .. } => {}
64        _ => return ReplacementResult::NotReplaced,
65    }
66    if effect.prevents() {
67        if let ReplacementEvent::DrawCards { count, .. } = event {
68            *count = 0;
69        }
70        return ReplacementResult::Prevented;
71    }
72    if let Some(result) =
73        execute_replace_with_numeric_update(effect, event, _game, _source_card_id, "Number")
74    {
75        return result;
76    }
77    if let Some(replace) = effect.replace_with() {
78        if let Some(raw) = _game.card(_source_card_id).svars.get(replace) {
79            let params = Params::from_raw(raw);
80            if params.get(keys::DB) == Some("Draw") {
81                let amount_expr = params.get(keys::NUM_CARDS).unwrap_or("1");
82                if let Some(amount) =
83                    resolve_replace_value(amount_expr, _game, _source_card_id, event)
84                {
85                    if set_replacement_event_amount(event, amount) {
86                        return ReplacementResult::Updated;
87                    }
88                }
89            }
90        }
91    }
92    ReplacementResult::Replaced
93}