open_pql/vm/
rng.rs

1use super::*;
2
3#[derive(Debug, Clone)]
4pub struct Rng {
5    initial_state: Vec<Card>,
6    current_state: Vec<Card>,
7    pub(crate) mem: Vec<Card>,
8    mem_unused: Vec<Card>,
9}
10
11impl Default for Rng {
12    fn default() -> Self {
13        Self::new(Card::ARR_ALL.to_vec())
14    }
15}
16
17impl Rng {
18    pub fn new(initial: Vec<Card>) -> Self {
19        let len = initial.len();
20
21        Self {
22            initial_state: initial,
23            current_state: Vec::with_capacity(len),
24            mem: Vec::with_capacity(5),
25            mem_unused: Vec::with_capacity(len),
26        }
27    }
28
29    pub fn reset(&mut self) {
30        self.current_state.clone_from(&self.initial_state);
31    }
32
33    pub fn deal_n(&mut self, range: &mut PQLRange, mut n: u8) -> Option<()> {
34        while n > 0 {
35            let len = self.current_state.len();
36
37            if len > 0 {
38                let i = fastrand::usize(0..len);
39                let c = self.current_state.swap_remove(i);
40
41                self.mem.push(c);
42
43                if range.is_satisfied(self.mem.as_ref()) {
44                    n -= 1;
45                } else {
46                    self.mem.pop();
47                    self.mem_unused.push(c);
48                }
49            } else {
50                return None;
51            }
52        }
53
54        self.current_state.append(&mut self.mem_unused);
55
56        Some(())
57    }
58
59    pub fn deal(&mut self, range: &mut PQLRange) -> Option<()> {
60        self.mem_unused.clear();
61        self.mem.clear();
62
63        match range {
64            PQLRange::Hand2(_) => self.deal_n(range, 2),
65            PQLRange::Hand4(_) => self.deal_n(range, 4),
66            PQLRange::Board(_) => {
67                self.deal_n(range, 3)?;
68                self.deal_n(range, 1)?;
69                self.deal_n(range, 1)
70            }
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::Rng;
78    use crate::{Card, Card64, c64, cards, *};
79
80    #[test]
81    fn test_reset() {
82        let cards = cards!["As 2h"];
83
84        let mut dealer = Rng::new(cards.clone());
85        dealer.current_state.clear();
86
87        dealer.reset();
88
89        assert_eq!(dealer.current_state, cards);
90    }
91
92    #[test]
93    fn test_deal() {
94        fastrand::seed(0);
95        let mut range = PQLRange::from_src("AA", PQLGame::Omaha).unwrap();
96
97        let mut dealer = Rng::new(Card::ARR_ALL.to_vec());
98        dealer.reset();
99
100        let res = dealer.deal(&mut range);
101        let c = c64!("As 2s 9c Ac");
102
103        assert!(res.is_some());
104        assert_eq!(Card64::from(dealer.mem.as_ref()), c);
105        assert_eq!(
106            Card64::from(dealer.current_state.as_ref()),
107            Card64::all() & !c
108        );
109
110        dealer.mem.clear();
111        let res = dealer.deal_n(&mut range, 2);
112        let c_n = c64!("6s Td");
113
114        assert!(res.is_some());
115        assert_eq!(Card64::from(dealer.mem.as_ref()), c_n);
116        assert_eq!(
117            Card64::from(dealer.current_state.as_ref()),
118            Card64::all() & !c & !c_n
119        );
120
121        dealer.current_state.clear();
122        assert_eq!(dealer.deal(&mut range), None);
123
124        let mut dealer = Rng::new(cards!("2s 2h 2d 2c 3s"));
125
126        dealer.reset();
127        assert!(
128            dealer
129                .deal(&mut PQLBoardRange::from_src("AAA").unwrap().into())
130                .is_none()
131        );
132        dealer.reset();
133        assert!(
134            dealer
135                .deal(&mut PQLBoardRange::from_src("222A").unwrap().into())
136                .is_none()
137        );
138    }
139}