use forge_foundation::ZoneType;
use super::EffectContext;
use crate::agent::GameEntity;
use crate::card::CounterType;
use crate::event::RunParams;
use crate::ids::CardId;
use crate::replacement::replacement_handler::{apply_replacements_with_agents, ReplacementEvent};
use crate::trigger::TriggerType;
#[manabrew_engine_macros::spell_effect(CountersProliferateEffect)]
fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
let controller = sa.activating_player;
let mut prolif_event = ReplacementEvent::Proliferate {
player: controller,
count: 1,
};
let prolif_result =
apply_replacements_with_agents(&mut *ctx.game, ctx.agents, &mut prolif_event);
if prolif_result == crate::replacement::ReplacementResult::Skipped
|| prolif_result == crate::replacement::ReplacementResult::Replaced
{
return;
}
let player_ids = ctx.game.player_order.clone();
let mut candidates: Vec<GameEntity> = Vec::new();
for &pid in &player_ids {
let p = ctx.game.player(pid);
if p.poison_counters > 0 || p.energy_counters > 0 {
candidates.push(GameEntity::Player(pid));
}
}
for &pid in &player_ids {
let zone_cards = ctx.game.cards_in_zone(ZoneType::Battlefield, pid).to_vec();
for cid in zone_cards {
if !ctx.game.card(cid).counters.is_empty()
&& ctx.game.card(cid).counters.values().any(|&v| v > 0)
{
candidates.push(GameEntity::Card(cid));
}
}
}
if candidates.is_empty() {
return;
}
let chosen = ctx.agents[controller.index()].choose_entities_for_effect(
controller,
&candidates,
0,
candidates.len(),
);
for entity in chosen {
match entity {
GameEntity::Player(pid) => {
proliferate_player(ctx, pid);
}
GameEntity::Card(cid) => {
proliferate_card(ctx, cid);
}
}
}
}
fn proliferate_player(ctx: &mut EffectContext, pid: crate::ids::PlayerId) {
let p = ctx.game.player(pid);
if p.poison_counters > 0 {
ctx.game.player_add_poison(pid, 1);
}
let p = ctx.game.player(pid);
if p.energy_counters > 0 {
ctx.game.player_add_energy(pid, 1);
}
}
fn proliferate_card(ctx: &mut EffectContext, cid: CardId) {
if ctx.game.card(cid).zone != ZoneType::Battlefield {
return;
}
let counter_types: Vec<CounterType> = ctx
.game
.card(cid)
.counters
.iter()
.filter(|(_, &count)| count > 0)
.map(|(ct, _)| ct.clone())
.collect();
for ct in &counter_types {
if crate::staticability::static_ability_cant_put_counter::any_cant_put_counter_on_card(
&ctx.game.cards,
ctx.game.card(cid),
ct,
) {
continue;
}
if let Some(max) = crate::staticability::static_ability_max_counter::max_counter(
&ctx.game.cards,
ctx.game.card(cid),
ct,
) {
if ctx.game.card(cid).counter_count(ct) >= max {
continue;
}
}
let mut add_event = ReplacementEvent::AddCounter {
target: cid,
counter_type: ct.clone(),
count: 1,
is_effect: true,
};
apply_replacements_with_agents(&mut *ctx.game, ctx.agents, &mut add_event);
let final_count = if let ReplacementEvent::AddCounter { count, .. } = add_event {
count
} else {
1
};
ctx.game.card_mut(cid).add_counter(ct, final_count);
ctx.trigger_handler.run_trigger(
TriggerType::CounterAdded,
RunParams {
card: Some(cid),
counter_type: Some(format!("{:?}", ct)),
counter_amount: Some(1),
..Default::default()
},
false,
);
}
}