Skip to main content

manabrew_engine/ability/effects/
villainous_choice_effect.rs

1//! VillainousChoice effect — opponent chooses which punishment to receive.
2//!
3//! Ported 1:1 from Java's `VillainousChoiceEffect.java`.
4//! Each target/defined player chooses one of the Choices sub-abilities
5//! to resolve against them. The opponent picks their punishment.
6
7use super::EffectContext;
8
9/// Struct form of this effect so it can participate in the
10/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
11/// `VillainousChoiceEffect` class extending `SpellAbilityEffect`.
12#[manabrew_engine_macros::spell_effect(VillainousChoiceEffect)]
13fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
14    let controller = sa.activating_player;
15
16    // Get choices (sub-ability names from Choices$ param)
17    let choice_names: Vec<String> = sa
18        .ir
19        .choices
20        .as_deref()
21        .map(|s| s.split(',').map(|c| c.trim().to_string()).collect())
22        .unwrap_or_default();
23
24    if choice_names.is_empty() {
25        return;
26    }
27
28    let players = if let Some(def) = sa.defined_player() {
29        super::resolve_defined_players(def, controller, ctx.game)
30    } else {
31        vec![ctx.game.opponent_of(controller)]
32    };
33
34    for pid in players {
35        if ctx.game.player(pid).has_lost {
36            continue;
37        }
38
39        // Player chooses which ability resolves (opponent picks their punishment)
40        ctx.agents[pid.index()].snapshot_state(ctx.game, ctx.mana_pools);
41        let chose_first = ctx.agents[pid.index()].confirm_action(
42            pid,
43            Some("VillainousChoice"),
44            &format!("Choose: {}", choice_names.join(" or ")),
45            &choice_names,
46            None,
47            None,
48        );
49
50        // The chosen sub-ability is resolved via the SA's sub-ability chain.
51        // Store the choice index for the parent resolution system.
52        if let Some(source_id) = sa.source {
53            let choice_idx = if chose_first {
54                0
55            } else {
56                1.min(choice_names.len() - 1)
57            };
58            ctx.game
59                .card_mut(source_id)
60                .add_remembered_cmc(choice_idx as i32);
61            ctx.game.card_mut(source_id).add_remembered_player(pid);
62        }
63    }
64}