manabrew_engine/ability/effects/
vote_effect.rs1use std::collections::HashMap;
9
10use super::EffectContext;
11use crate::event::RunParams;
12use crate::ids::PlayerId;
13use crate::parsing::keys;
14use crate::trigger::TriggerType;
15
16#[manabrew_engine_macros::spell_effect(VoteEffect)]
20fn resolve(ctx: &mut EffectContext, sa: &crate::spellability::SpellAbility) {
21 let controller = sa.activating_player;
22
23 let mut voters: Vec<PlayerId> = if let Some(def) = sa.defined_player() {
25 super::resolve_defined_players(def, controller, ctx.game)
26 } else {
27 ctx.game.player_order.clone()
28 };
29
30 if let Some(pos) = voters.iter().position(|&p| p == controller) {
32 voters.rotate_left(pos);
33 }
34
35 let choices: Vec<String> = if let Some(choices_str) = sa.ir.choices.as_deref() {
37 choices_str
38 .split(',')
39 .map(|s| s.trim().to_string())
40 .collect()
41 } else if let Some(msg) = sa.ir.vote_message_text.as_deref() {
42 msg.split(" or ").map(|s| s.trim().to_string()).collect()
44 } else {
45 return;
46 };
47
48 if choices.is_empty() {
49 return;
50 }
51
52 let mut vote_counts: HashMap<String, Vec<PlayerId>> = HashMap::new();
54 for choice in &choices {
55 vote_counts.insert(choice.clone(), Vec::new());
56 }
57
58 for &voter in &voters {
59 if ctx.game.player(voter).has_lost {
60 continue;
61 }
62
63 ctx.agents[voter.index()].snapshot_state(ctx.game, ctx.mana_pools);
65 let chosen = ctx.agents[voter.index()].confirm_action(
66 voter,
67 Some("Vote"),
68 &format!("Vote: {}", choices.join(" or ")),
69 &choices,
70 sa.source,
71 sa.api,
72 );
73
74 let choice_idx = if chosen { 0 } else { 1.min(choices.len() - 1) };
76 let chosen_str = &choices[choice_idx];
77
78 if let Some(voters_list) = vote_counts.get_mut(chosen_str) {
79 voters_list.push(voter);
80 }
81 }
82
83 let max_votes = vote_counts.values().map(|v| v.len()).max().unwrap_or(0);
85 let winners: Vec<String> = vote_counts
86 .iter()
87 .filter(|(_, v)| v.len() == max_votes)
88 .map(|(k, _)| k.clone())
89 .collect();
90
91 let all_votes = vote_counts
92 .iter()
93 .map(|(choice, voters)| (choice.clone(), voters.clone()))
94 .collect();
95 ctx.trigger_handler.run_trigger(
96 TriggerType::Vote,
97 RunParams {
98 all_votes: Some(all_votes),
99 ..Default::default()
100 },
101 false,
102 );
103
104 if sa.param_is_true(keys::STORE_VOTE_NUM) {
106 if let Some(source_id) = sa.source {
107 for (choice, voters_list) in &vote_counts {
108 let svar_name = format!("VoteNum{choice}");
109 let svar_val = format!("Number${}", voters_list.len());
110 ctx.game.card_mut(source_id).set_s_var(svar_name, svar_val);
111 }
112 }
113 }
114
115 if sa.param_is_true(keys::REMEMBER_VOTED_OBJECTS) {
117 if let Some(source_id) = sa.source {
119 for winner in &winners {
120 if let Some(idx) = choices.iter().position(|c| c == winner) {
121 ctx.game.card_mut(source_id).add_remembered_cmc(idx as i32);
122 }
123 }
124 }
125 }
126
127 }