use super::{resolve_numeric_svar, EffectContext};
use crate::ability::ability_ir::EffectIr;
use crate::ability::spell_ability_effect::get_target_players;
use crate::event::RunParams;
use crate::parsing::keys;
use crate::replacement::replacement_handler::{apply_replacements_with_agents, ReplacementEvent};
use crate::replacement::ReplacementResult;
use crate::spellability::SpellAbility;
use crate::trigger::TriggerType;
#[manabrew_engine_macros::spell_effect(DrawEffect)]
fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
let num = resolve_draw_amount(ctx, sa);
let targets = get_target_players(ctx.game, sa);
for target in targets {
draw_for_player(ctx, sa, target, num);
}
}
fn draw_for_player(
ctx: &mut EffectContext,
sa: &crate::spellability::SpellAbility,
target: crate::ids::PlayerId,
num: i32,
) {
let mut actual_num = num;
if actual_num > 0 {
let mut event = ReplacementEvent::DrawCards {
player: target,
count: actual_num,
};
let result = apply_replacements_with_agents(ctx.game, ctx.agents, &mut event);
if result == ReplacementResult::Skipped || result == ReplacementResult::Replaced {
return;
}
if let ReplacementEvent::DrawCards { count, .. } = event {
actual_num = count;
}
}
let upto = sa.ir.upto;
let optional = sa.ir.optional_present || sa.ir.optional_decider.is_some() || upto;
if optional {
let _source_name = sa.source.map(|cid| ctx.game.card(cid).card_name.as_str());
let accepted = ctx.agents[target.index()].confirm_action(
target,
None,
&format!("Do you want to draw {} card(s)?", actual_num),
&[],
sa.source,
Some(crate::ability::api_type::ApiType::Draw),
);
if !accepted {
return;
}
}
if upto {
let prompt = format!("Draw up to {actual_num} card(s).");
match ctx.agents[target.index()].choose_number(
target,
sa.source,
"Draw cards",
Some(&prompt),
0,
actual_num,
) {
Some(picked) => {
actual_num = picked.clamp(0, actual_num);
if actual_num == 0 {
return;
}
}
None => return,
}
}
let remember_drawn = sa.ir.remember_drawn;
let mut drawn: Vec<crate::ids::CardId> = Vec::new();
for _ in 0..actual_num {
if let Some(card_id) = ctx.game.draw_card_with_agents(target, ctx.agents) {
drawn.push(card_id);
let drawn_snapshot = ctx.game.player(target).drawn_this_turn;
ctx.trigger_handler.run_trigger(
TriggerType::Drawn,
RunParams {
card: Some(card_id),
player: Some(target),
drawn_this_turn_snapshot: Some(drawn_snapshot),
..Default::default()
},
false,
);
if ctx.trigger_handler.has_number_drawn_triggers(ctx.game) {
ctx.trigger_handler.flush_waiting_triggers(ctx.game);
}
}
}
if remember_drawn {
if let Some(source_id) = sa.source {
let card_mut = ctx.game.card_mut(source_id);
for cid in &drawn {
card_mut.add_remembered_card(*cid);
}
}
}
}
fn resolve_draw_amount(ctx: &EffectContext, sa: &SpellAbility) -> i32 {
if let Some(EffectIr::Draw(ir)) = &sa.ir.effect {
if let Some(amount) = &ir.amount {
let resolved = amount.resolve_for_spell_ability(ctx.game, sa, 1);
#[cfg(debug_assertions)]
debug_assert_eq!(
resolved,
resolve_numeric_svar(ctx.game, sa, keys::NUM_CARDS, 1),
"compiled Draw amount diverged from string params"
);
return resolved;
}
}
resolve_numeric_svar(ctx.game, sa, keys::NUM_CARDS, 1)
}