Skip to main content

manabrew_engine/ability/effects/
control_player_effect.rs

1//! ControlPlayer effect — take control of another player's turn (Mindslaver).
2//!
3//! Ported 1:1 from Java's `ControlPlayerEffect.java`.
4//! You control target player during their next turn. (CR 800.4b)
5//! The controlled player's decisions are made by the controller.
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/// `ControlPlayerEffect` class extending `SpellAbilityEffect`.
12#[manabrew_engine_macros::spell_effect(ControlPlayerEffect)]
13fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
14    let controller_def = sa.ir.controller_text.as_deref().unwrap_or("You");
15    let controller = super::resolve_defined_players(controller_def, sa.activating_player, ctx.game)
16        .into_iter()
17        .next()
18        .unwrap_or(sa.activating_player);
19
20    let targets = if let Some(pid) = sa.target_chosen.target_player {
21        vec![pid]
22    } else if let Some(def) = sa.defined_player() {
23        super::resolve_defined_players(def, sa.activating_player, ctx.game)
24    } else {
25        vec![ctx.game.opponent_of(sa.activating_player)]
26    };
27
28    for target_player in targets {
29        // Set the controlled_by field on the target player
30        // This will be checked by the game loop to route decisions
31        // through the controller's agent instead of the target's agent
32        ctx.game
33            .player_set_controlled_by(target_player, Some(controller));
34
35        // Register a cleanup to remove control at end of next turn
36        // Java uses addUntil on the cleanup step — we use a delayed trigger
37        ctx.trigger_handler
38            .register_delayed_trigger(crate::trigger::handler::DelayedTrigger {
39                mode: crate::trigger::TriggerType::Phase,
40                trigger_mode: Box::new(crate::trigger::trigger_always::TriggerAlways)
41                    as Box<dyn crate::trigger::TriggerBehavior>,
42                params: crate::parsing::Params::default(),
43                execute_svar: "ControlPlayerCleanup".to_string(),
44                controller,
45                source_card: sa.source.unwrap_or(crate::ids::CardId(0)),
46                created_turn: ctx.game.turn.turn_number,
47                created_phase: ctx.game.turn.phase,
48                target_card: None,
49                remembered_amount: target_player.0 as i32,
50                remembered_cards: Vec::new(),
51                remembered_players: Vec::new(),
52                remembered_lki_cards: Vec::new(),
53                sort_after_active: false,
54                trigger_order: None,
55            });
56    }
57}