Skip to main content

manabrew_engine/ability/effects/
investigate_effect.rs

1//! Investigate effect — create Clue artifact tokens.
2//!
3//! Ported from Java's `InvestigateEffect.java`.
4//! Investigate: Create a colorless Clue artifact token with
5//! "{2}, Sacrifice this artifact: Draw a card."
6
7use super::token_effect_base::{TokenEffectBase, TOKEN_EFFECT_BASE};
8use super::EffectContext;
9use crate::card::card_zone_table::CardZoneTable;
10use crate::ids::{CardId, PlayerId};
11use crate::parsing::keys;
12use crate::spellability::SpellAbility;
13
14/// Struct form of this effect so it can participate in the
15/// `SpellAbilityEffect` trait hierarchy — mirrors Java's
16/// `InvestigateEffect` class extending `SpellAbilityEffect`.
17#[manabrew_engine_macros::spell_effect(InvestigateEffect)]
18fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
19    let amount = super::resolve_numeric_svar(ctx.game, sa, "Num", 1).max(0) as usize;
20    let controller = sa.activating_player;
21
22    let players = if let Some(def) = sa.defined_player() {
23        super::resolve_defined_players(def, controller, ctx.game)
24    } else {
25        vec![controller]
26    };
27
28    let mut created_tokens: Vec<CardId> = Vec::new();
29    let mut trigger_list = CardZoneTable::default();
30    for _ in 0..amount {
31        for &pid in &players {
32            if let Some(tid) = create_clue_token(ctx, sa, pid, &mut trigger_list) {
33                created_tokens.push(tid);
34            }
35        }
36    }
37
38    // Fire ChangesZoneAll for the batch of tokens entering the battlefield.
39    // Needed for triggers like Woodland Champion (Mode$ ChangesZoneAll).
40    if !created_tokens.is_empty() {
41        trigger_list.trigger_changes_zone_all(ctx.trigger_handler, ctx.game, Some(sa));
42    }
43}
44
45/// Create a single Clue artifact token. Returns the created token ID.
46fn create_clue_token(
47    ctx: &mut EffectContext,
48    sa: &SpellAbility,
49    player: PlayerId,
50    trigger_list: &mut CardZoneTable,
51) -> Option<CardId> {
52    let token_table = TOKEN_EFFECT_BASE.make_token_table_internal_from_script(
53        ctx,
54        player,
55        "c_a_clue_draw",
56        1,
57        sa,
58    );
59    let result = TOKEN_EFFECT_BASE.make_token_table(ctx, token_table, false, trigger_list, sa);
60    let token_id = result.created.first().copied()?;
61
62    // RememberInvestigatingPlayers$
63    if sa.param_is_true(keys::REMEMBER_INVESTIGATING_PLAYERS) {
64        if let Some(sid) = sa.source {
65            ctx.game.card_mut(sid).add_remembered_player(player);
66        }
67    }
68
69    Some(token_id)
70}