manabrew_engine/combat/
attacking_band.rs1use crate::ids::CardId;
2
3#[derive(Debug, Clone)]
12pub struct AttackingBand {
13 pub attackers: Vec<CardId>,
14 pub blocked: Option<bool>,
16}
17
18impl AttackingBand {
19 pub fn new(card: CardId) -> Self {
20 Self {
21 attackers: vec![card],
22 blocked: None,
23 }
24 }
25
26 pub fn from_list(cards: Vec<CardId>) -> Self {
27 Self {
28 attackers: cards,
29 blocked: None,
30 }
31 }
32
33 pub fn get_attackers(&self) -> &[CardId] {
34 &self.attackers
35 }
36
37 pub fn add_attacker(&mut self, card: CardId) {
38 self.attackers.push(card);
39 }
40
41 pub fn remove_attacker(&mut self, card: CardId) {
42 self.attackers.retain(|&c| c != card);
43 }
44
45 pub fn contains(&self, card: CardId) -> bool {
47 self.attackers.contains(&card)
48 }
49
50 pub fn is_blocked(&self) -> Option<bool> {
51 self.blocked
52 }
53
54 pub fn set_blocked(&mut self, value: bool) {
55 self.blocked = Some(value);
56 }
57
58 pub fn is_empty(&self) -> bool {
59 self.attackers.is_empty()
60 }
61
62 pub fn is_valid_band(band: &[CardId], cards: &[crate::card::Card], share_damage: bool) -> bool {
69 if band.is_empty() {
70 return false;
71 }
72 if band.len() == 1 {
73 return true;
74 }
75 let banding_count = band
77 .iter()
78 .filter(|&&cid| {
79 let card = &cards[cid.index()];
80 card.has_keyword("Banding")
81 })
82 .count();
83 let needed = if share_damage { 1 } else { band.len() - 1 };
84 banding_count >= needed
85 }
86
87 pub fn can_join_band(&self, card: CardId, cards: &[crate::card::Card]) -> bool {
89 let mut new_band: Vec<CardId> = self.attackers.clone();
90 new_band.push(card);
91 Self::is_valid_band(&new_band, cards, false)
92 }
93}
94
95impl std::fmt::Display for AttackingBand {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 let blocked_str = match self.blocked {
98 None => " ? ",
99 Some(true) => ">||",
100 Some(false) => ">>>",
101 };
102 write!(f, "{:?} {}", self.attackers, blocked_str)
103 }
104}