open_pql/prim/eval/
shortdeck7.rs

1use super::{
2    FLUSH_SHORT, FULLHOUSE_SHORT, HIGHCARD, NONE_I16, STRAIGHT, STRAIGHT_9TJQK,
3    STRAIGHT_89TJQ, STRAIGHT_789TJ, STRAIGHT_A789T, STRAIGHT_TJQKA, U16_T,
4    flush_ranks, get_card_count, holdem7, mk_masks_rank, mk_masks_rank13,
5    mk_masks_rankrank, mk_ranking, retain_leading_5_bits, retain_leading_bit,
6    to_straightflush,
7};
8
9pub const fn eval(c: u64) -> i16 {
10    let nf = eval_nf(c);
11    let f = eval_f(c);
12
13    if f > nf { f } else { nf }
14}
15
16#[inline]
17pub const fn eval_nf(c: u64) -> i16 {
18    let (has1, has2, has3, has4) = get_card_count(c);
19
20    let res = holdem7::eval_quads(has4, has1);
21    if res != NONE_I16 {
22        return res;
23    }
24
25    let res = eval_fullhouse7s(has3, has2);
26    if res != NONE_I16 {
27        return res;
28    }
29
30    let res = eval_straight7s(has1);
31    if res != NONE_I16 {
32        return res;
33    }
34
35    let res = holdem7::eval_trips(has3, has1);
36    if res != NONE_I16 {
37        return res;
38    }
39
40    let res = holdem7::eval_twopair(has2, has1);
41    if res != NONE_I16 {
42        return res;
43    }
44
45    let res = holdem7::eval_pair(has2, has1);
46    if res != NONE_I16 {
47        return res;
48    }
49
50    mk_ranking(HIGHCARD, mk_masks_rank13(0, retain_leading_5_bits(has1)))
51}
52
53#[inline]
54pub const fn eval_f(c: u64) -> i16 {
55    let ranks = flush_ranks(c);
56
57    if ranks == u16::MIN {
58        NONE_I16
59    } else {
60        let res = eval_straight7s(ranks);
61
62        if res == NONE_I16 {
63            mk_ranking(
64                FLUSH_SHORT,
65                mk_masks_rank13(0, retain_leading_5_bits(ranks)),
66            )
67        } else {
68            to_straightflush(res)
69        }
70    }
71}
72
73#[inline]
74pub(super) const fn eval_fullhouse7s(has3: u16, has2: u16) -> i16 {
75    if has3 > 0 {
76        let h = retain_leading_bit(has3);
77        let l = has2 & !h;
78
79        if l > 0 {
80            mk_ranking(FULLHOUSE_SHORT, mk_masks_rankrank(l, h))
81        } else {
82            NONE_I16
83        }
84    } else {
85        NONE_I16
86    }
87}
88
89#[inline]
90pub(super) const fn eval_straight7s(ranks: u16) -> i16 {
91    if STRAIGHT_TJQKA & ranks == STRAIGHT_TJQKA {
92        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_TJQKA))
93    } else if STRAIGHT_9TJQK & ranks == STRAIGHT_9TJQK {
94        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_9TJQK))
95    } else if STRAIGHT_89TJQ & ranks == STRAIGHT_89TJQ {
96        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_89TJQ))
97    } else if STRAIGHT_789TJ & ranks == STRAIGHT_789TJ {
98        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_789TJ))
99    } else if STRAIGHT_A789T & ranks == STRAIGHT_A789T {
100        mk_ranking(STRAIGHT, mk_masks_rank(0, U16_T))
101    } else {
102        NONE_I16
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use eval::shortdeck5;
109    use itertools::Itertools;
110
111    use super::*;
112    use crate::*;
113
114    #[quickcheck]
115    fn test_shortdeck7(cards: CardN<7, true>) -> TestResult {
116        let cards: Vec<_> = cards.into();
117
118        let res7 = eval(Card64::from(cards.as_ref()).to_u64());
119
120        let mut max5 = HandRatingInt::MIN;
121
122        for cs in cards.into_iter().combinations(5) {
123            let res = shortdeck5::eval(Card64::from(cs.as_ref()).to_u64());
124
125            if res > max5 {
126                max5 = res;
127            }
128        }
129
130        TestResult::from_bool(max5 == res7)
131    }
132}