openpql_prelude/game/
player.rs

1use super::{Add, AddAssign, Display, Into};
2
3pub type PlayerIdx = u8;
4
5#[derive(
6    Debug,
7    Clone,
8    Copy,
9    PartialEq,
10    Eq,
11    Default,
12    derive_more::From,
13    Into,
14    Display,
15    Add,
16    AddAssign,
17)]
18#[display("Player {_0}")]
19pub struct Player(PlayerIdx);
20
21impl Player {
22    pub fn iter(n: PlayerIdx) -> impl Iterator<Item = Self> {
23        (0..n).map(Self::from)
24    }
25
26    pub fn iter_opponents(self, n: PlayerIdx) -> impl Iterator<Item = Self> {
27        Self::iter(n).filter(move |&p| p != self)
28    }
29}
30
31impl From<usize> for Player {
32    #[cfg_attr(coverage_nightly, coverage(off))]
33    fn from(i: usize) -> Self {
34        debug_assert!(i < PlayerIdx::MAX.into());
35
36        Self(i.to_le_bytes()[0])
37    }
38}
39
40impl From<i32> for Player {
41    #[cfg_attr(coverage_nightly, coverage(off))]
42    fn from(i: i32) -> Self {
43        debug_assert!(i >= 0 && i < PlayerIdx::MAX.into());
44
45        Self(i.to_le_bytes()[0])
46    }
47}
48
49impl From<Player> for usize {
50    fn from(player: Player) -> Self {
51        player.0 as Self
52    }
53}
54
55#[cfg(test)]
56#[cfg_attr(coverage_nightly, coverage(off))]
57mod tests {
58    use super::*;
59    use crate::*;
60
61    impl Arbitrary for Player {
62        fn arbitrary(g: &mut quickcheck::Gen) -> Self {
63            Self(PlayerIdx::arbitrary(g))
64        }
65    }
66
67    #[test]
68    fn test_conversion() {
69        for i in 0..10 {
70            let player = Player::from(i);
71            assert_eq!(player.0, i);
72            assert_eq!(usize::from(player), i as usize);
73        }
74    }
75
76    #[quickcheck]
77    fn test_iter(n: PlayerIdx) {
78        let n_players = n % 10;
79        let v: Vec<_> = Player::iter(n_players).collect();
80
81        assert_eq!(v, (0..n_players).map(Player::from).collect::<Vec<_>>());
82    }
83
84    #[quickcheck]
85    fn test_iter_opponents(n: PlayerIdx, player_idx: PlayerIdx) {
86        let n_players = n % 10;
87        if n_players == 0 {
88            return;
89        }
90
91        let player = Player::from(player_idx % n_players);
92        let opponents: Vec<_> = player.iter_opponents(n_players).collect();
93
94        assert!(!opponents.contains(&player));
95        assert_eq!(opponents.len(), (n_players - 1) as usize);
96
97        let expected: Vec<_> = (0..n_players)
98            .map(Player::from)
99            .filter(|&p| p != player)
100            .collect();
101        assert_eq!(opponents, expected);
102    }
103}