use forge_foundation::ZoneType;
use super::{matches_valid_cards_for_sa, resolve_defined_players, EffectContext};
use crate::spellability::{build_spell_ability, SpellAbility};
#[manabrew_engine_macros::spell_effect(RepeatEachEffect)]
fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
let source_id = match sa.source {
Some(id) => id,
None => return,
};
let controller = sa.activating_player;
let use_damage_map = sa.ir.damage_map;
let use_change_zone_table = sa.ir.change_zone_table;
if use_damage_map {
ctx.game.ensure_pending_damage_maps();
}
if use_change_zone_table {
ctx.game.ensure_pending_change_zone_table();
}
let sub_svar_name = match sa.ir.repeat_sub_ability.as_deref() {
Some(name) => name,
None => return,
};
let sub_text = match ctx
.game
.card(source_id)
.get_s_var(sub_svar_name)
.map(str::to_string)
{
Some(text) => text,
None => return,
};
if let Some(repeat_cards_filter) = sa.ir.repeat_cards_text.as_deref() {
let repeat_cards_selector = sa.ir.repeat_cards_selector.as_ref();
let zone = sa.ir.zone.unwrap_or(ZoneType::Battlefield);
let matching: Vec<crate::ids::CardId> = {
let mut result = Vec::new();
for &pid in &ctx.game.player_order.clone() {
let zone_cards = ctx.game.cards_in_zone(zone, pid).to_vec();
for cid in zone_cards {
if matches_valid_cards_for_sa(
ctx.game,
sa,
ctx.game.card(cid),
repeat_cards_selector,
repeat_cards_filter,
) {
result.push(cid);
}
}
}
result
};
for card_id in matching {
ctx.game.card_mut(source_id).clear_remembered();
ctx.game.card_mut(source_id).add_remembered_card(card_id);
let sub_sa = build_spell_ability(ctx.game, source_id, &sub_text, controller);
resolve_sub_chain(ctx, sub_sa);
if ctx.game.game_over {
break;
}
}
ctx.game.card_mut(source_id).clear_remembered();
} else if let Some(repeat_players) = sa.ir.repeat_players.as_deref() {
let players = resolve_defined_players(repeat_players, controller, ctx.game);
for pid in players {
ctx.game.card_mut(source_id).clear_remembered();
ctx.game.card_mut(source_id).add_remembered_player(pid);
let sub_sa = build_spell_ability(ctx.game, source_id, &sub_text, controller);
resolve_sub_chain(ctx, sub_sa);
if ctx.game.game_over {
break;
}
}
ctx.game.card_mut(source_id).clear_remembered();
}
if use_damage_map {
let mut flush_sa = sa.clone();
flush_sa.damage_map = ctx.game.pending_damage_map.clone();
flush_sa.prevent_map = ctx.game.pending_prevent_map.clone();
super::damage_resolve_effect::DamageResolveEffect::resolve(ctx, &flush_sa);
ctx.game.clear_pending_damage_maps();
}
if use_change_zone_table {
if let Some(table) = ctx.game.pending_change_zone_table.clone() {
table.trigger_changes_zone_all(ctx.trigger_handler, ctx.game, Some(sa));
ctx.game.clear_pending_change_zone_table();
}
}
}
fn resolve_sub_chain(ctx: &mut EffectContext, initial: SpellAbility) {
let mut cur_opt: Option<SpellAbility> = Some(initial);
while let Some(cur_sa) = cur_opt {
super::resolve_effect(ctx, &cur_sa);
cur_opt = cur_sa.sub_ability.map(|b| *b);
if ctx.game.game_over {
break;
}
}
}