Skip to main content

manabrew_engine/player/
player_collection.rs

1use crate::game::GameState;
2use crate::ids::{CardId, PlayerId};
3use crate::player::player_predicates;
4use forge_foundation::ZoneType;
5
6#[derive(Debug, Clone, Default, PartialEq, Eq)]
7pub struct PlayerCollection(pub Vec<PlayerId>);
8
9impl IntoIterator for PlayerCollection {
10    type Item = PlayerId;
11    type IntoIter = std::vec::IntoIter<PlayerId>;
12
13    fn into_iter(self) -> Self::IntoIter {
14        self.0.into_iter()
15    }
16}
17
18impl<'a> IntoIterator for &'a PlayerCollection {
19    type Item = &'a PlayerId;
20    type IntoIter = std::slice::Iter<'a, PlayerId>;
21
22    fn into_iter(self) -> Self::IntoIter {
23        self.0.iter()
24    }
25}
26
27impl PlayerCollection {
28    pub fn new(players: Vec<PlayerId>) -> Self {
29        Self(players)
30    }
31
32    pub fn alive(game: &GameState) -> Self {
33        Self(game.alive_players())
34    }
35
36    pub fn opponents_of(game: &GameState, player: PlayerId) -> Self {
37        Self(
38            game.player_order
39                .iter()
40                .copied()
41                .filter(|&pid| player_predicates::is_opponent_of(game, player, pid))
42                .collect(),
43        )
44    }
45
46    pub fn teammates_of(game: &GameState, player: PlayerId) -> Self {
47        Self(
48            game.player_order
49                .iter()
50                .copied()
51                .filter(|&pid| player_predicates::same_team(game, player, pid))
52                .collect(),
53        )
54    }
55
56    pub fn contains(&self, player: PlayerId) -> bool {
57        self.0.contains(&player)
58    }
59
60    pub fn cards_in(&self, game: &GameState, zone: ZoneType) -> Vec<CardId> {
61        self.0
62            .iter()
63            .flat_map(|&pid| game.cards_in_zone(zone, pid).iter().copied())
64            .collect()
65    }
66
67    pub fn cards_in_zones(
68        &self,
69        game: &GameState,
70        zones: impl IntoIterator<Item = ZoneType>,
71    ) -> Vec<CardId> {
72        zones
73            .into_iter()
74            .flat_map(|zone| self.cards_in(game, zone))
75            .collect()
76    }
77
78    pub fn creatures_in_play(&self, game: &GameState) -> Vec<CardId> {
79        self.cards_in(game, ZoneType::Battlefield)
80            .into_iter()
81            .filter(|&cid| game.card(cid).is_creature())
82            .collect()
83    }
84
85    pub fn filter<F>(&self, predicate: F) -> Self
86    where
87        F: Fn(PlayerId) -> bool,
88    {
89        Self(
90            self.0
91                .iter()
92                .copied()
93                .filter(|&pid| predicate(pid))
94                .collect(),
95        )
96    }
97
98    pub fn min<F>(&self, score: F) -> Option<PlayerId>
99    where
100        F: Fn(PlayerId) -> i32,
101    {
102        self.0.iter().copied().min_by_key(|&pid| score(pid))
103    }
104
105    pub fn max<F>(&self, score: F) -> Option<PlayerId>
106    where
107        F: Fn(PlayerId) -> i32,
108    {
109        self.0.iter().copied().max_by_key(|&pid| score(pid))
110    }
111
112    pub fn sum<F>(&self, score: F) -> i32
113    where
114        F: Fn(PlayerId) -> i32,
115    {
116        self.0.iter().copied().map(score).sum()
117    }
118}