manabrew_engine/ability/effects/
protect_effect.rs1use forge_foundation::ZoneType;
2
3use super::EffectContext;
4use crate::ability::ability_ir::DefinedRef;
5use crate::card::card_util;
6use crate::spellability::SpellAbility;
7
8pub fn get_protection_list(sa: &SpellAbility) -> Vec<String> {
16 let gains = sa.ir.gains.as_deref().unwrap_or("");
17 if gains != "Choice" && !gains.contains("chosen color") {
18 return gains
19 .split(',')
20 .map(|c| c.trim().to_string())
21 .filter(|s| !s.is_empty())
22 .collect();
23 }
24
25 let mut out = Vec::new();
26 let choices = sa.ir.choices.as_deref().unwrap_or("");
27 let mut choices_mut = choices.to_string();
28 if choices_mut.contains("AnyColor") {
29 out.extend(
30 ["White", "Blue", "Black", "Red", "Green"]
31 .iter()
32 .map(|s| s.to_string()),
33 );
34 choices_mut = choices_mut.replace("AnyColor,", "").replace("AnyColor", "");
35 }
36 let trimmed = choices_mut.trim().trim_end_matches(',');
37 if !trimmed.is_empty() {
38 out.extend(
39 trimmed
40 .split(',')
41 .map(|c| c.trim().to_string())
42 .filter(|s| !s.is_empty()),
43 );
44 }
45 if out.is_empty() {
46 out = ["White", "Blue", "Black", "Red", "Green"]
47 .iter()
48 .map(|s| s.to_string())
49 .collect();
50 }
51 out
52}
53
54pub fn run(game: &mut crate::game::GameState, card_id: crate::ids::CardId, keyword: &str) {
58 if game.card(card_id).zone == ZoneType::Battlefield {
59 game.card_mut(card_id).pump_keywords.remove(keyword);
60 }
61}
62
63#[manabrew_engine_macros::spell_effect(ProtectEffect)]
78fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
79 let controller = sa.activating_player;
80
81 let target = sa
83 .target_chosen
84 .target_card
85 .or_else(|| match sa.defined_ref() {
86 Some(DefinedRef::SelfCard) => sa.source,
87 Some(DefinedRef::ParentTarget) => ctx.parent_target_card,
88 _ => sa.source,
89 });
90
91 let gains = sa.ir.gains.clone().unwrap_or_default();
92
93 let is_choice = gains.contains("Choice") || gains.contains("chosen color");
96
97 let mut targets = target.into_iter().collect::<Vec<_>>();
98 targets.extend(card_util::get_radiance(ctx.game, sa).iter().copied());
99 targets.retain(|&id| ctx.game.card(id).zone == ZoneType::Battlefield);
100 targets.sort_unstable_by_key(|cid| cid.0);
101 targets.dedup();
102 if targets.is_empty() {
103 return;
104 }
105
106 if is_choice {
107 let choices = get_protection_list(sa);
108 let chosen = ctx.agents[controller.index()].choose_color(controller, &choices);
109 if let Some(color) = chosen {
110 let prot_kw = format!("Protection from {}", color.to_lowercase());
111 for card_id in targets {
112 ctx.game.card_mut(card_id).add_pump_keyword(&prot_kw);
113 }
114 }
115 } else {
116 for card_id in targets {
118 ctx.game.card_mut(card_id).add_pump_keyword(&gains);
119 }
120 }
121}