Skip to main content

manabrew_engine/replacement/
replace_roll_dice.rs

1//! Replacement logic for `Event$ RollDice`.
2//!
3//! Mirrors Java `ReplaceRollDice.java` in `forge/game/replacement/`.
4
5use crate::card::Card;
6use crate::game::GameState;
7use crate::ids::CardId;
8
9use super::replacement_effect::resolve_replace_with_chain;
10use super::replacement_effect::ReplacementEffect;
11use super::replacement_handler::{
12    execute_replace_effect_ir, execute_replace_with_numeric_update, resolve_replace_value,
13    ReplacementEvent,
14};
15use super::replacement_result::ReplacementResult;
16use super::replacement_type::ReplacementType;
17use crate::card_trait_base::CardTrait;
18
19/// Mirrors Java `ReplaceRollDice.canReplace()`.
20pub fn can_replace(
21    effect: &ReplacementEffect,
22    event: &ReplacementEvent,
23    _game: &GameState,
24    source_card: &Card,
25) -> bool {
26    if effect.event != ReplacementType::RollDice {
27        return false;
28    }
29    let (player, sides) = match event {
30        ReplacementEvent::RollDice { player, sides, .. } => (*player, *sides),
31        _ => return false,
32    };
33    if let Some(valid) = effect.ir.valid_player_selector.as_ref() {
34        if !effect.matches_compiled_valid_player(valid, player, source_card) {
35            return false;
36        }
37    }
38    if let Some(valid_sides) = effect.ir.valid_sides_text.as_deref() {
39        let rhs = resolve_replace_value(valid_sides, _game, source_card.id, event)
40            .or_else(|| valid_sides.parse::<i32>().ok())
41            .unwrap_or(0);
42        if sides != rhs {
43            return false;
44        }
45    }
46    true
47}
48
49/// Mirrors Java `ReplacementHandler.executeReplacement()` for RollDice.
50pub fn execute(
51    effect: &ReplacementEffect,
52    _event: &mut ReplacementEvent,
53    _game: &GameState,
54    _source_card_id: CardId,
55) -> ReplacementResult {
56    if effect.prevents() || effect.has_skip() {
57        return ReplacementResult::Skipped;
58    }
59    if let Some(result) =
60        execute_replace_with_numeric_update(effect, _event, _game, _source_card_id, "Number")
61    {
62        return result;
63    }
64    if let Some(result) =
65        execute_replace_with_numeric_update(effect, _event, _game, _source_card_id, "Ignore")
66    {
67        return result;
68    }
69    if let Some(replace_with) = resolve_replace_with_chain(effect, _game.card(_source_card_id)) {
70        if let Some(result) = execute_replace_effect_ir(
71            &replace_with,
72            _event,
73            _game,
74            _source_card_id,
75            Some("IgnoreChosen"),
76        ) {
77            return result;
78        }
79        if let Some(result) = execute_replace_effect_ir(
80            &replace_with,
81            _event,
82            _game,
83            _source_card_id,
84            Some("DicePTExchanges"),
85        ) {
86            return result;
87        }
88    }
89    ReplacementResult::Replaced
90}