open_pql/prim/eval/
shortdeck5.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, holdem5, mk_masks_rank, mk_masks_rank13,
5    mk_masks_rankrank, mk_ranking, to_straightflush,
6};
7
8pub const fn eval(c: u64) -> i16 {
9    let nf = eval_nf(c);
10    let f = eval_f(c);
11
12    if f > nf { f } else { nf }
13}
14
15#[inline]
16pub const fn eval_nf(c: u64) -> i16 {
17    let (has1, has2, has3, has4) = get_card_count(c);
18
19    let res = holdem5::eval_quads(has4, has1);
20    if res != NONE_I16 {
21        return res;
22    }
23
24    let res = eval_fullhouse5s(has3, has2);
25    if res != NONE_I16 {
26        return res;
27    }
28
29    let res = eval_straight5s(has1);
30    if res != NONE_I16 {
31        return res;
32    }
33
34    let res = holdem5::eval_trips(has3, has1);
35    if res != NONE_I16 {
36        return res;
37    }
38
39    let res = holdem5::eval_twopair(has2, has1);
40    if res != NONE_I16 {
41        return res;
42    }
43
44    let res = holdem5::eval_pair(has2, has1);
45    if res != NONE_I16 {
46        return res;
47    }
48
49    mk_ranking(HIGHCARD, mk_masks_rank13(0, has1))
50}
51
52#[inline]
53pub const fn eval_f(c: u64) -> i16 {
54    let ranks = flush_ranks(c);
55
56    if ranks == u16::MIN {
57        NONE_I16
58    } else {
59        let res = eval_straight5s(ranks);
60
61        if res == NONE_I16 {
62            mk_ranking(FLUSH_SHORT, mk_masks_rank13(0, ranks))
63        } else {
64            to_straightflush(res)
65        }
66    }
67}
68
69#[inline]
70pub(super) const fn eval_fullhouse5s(has3: u16, has2: u16) -> i16 {
71    if has3 != 0 {
72        let l = has2 & !has3;
73
74        if l != 0 {
75            mk_ranking(FULLHOUSE_SHORT, mk_masks_rankrank(l, has3))
76        } else {
77            NONE_I16
78        }
79    } else {
80        NONE_I16
81    }
82}
83
84#[inline]
85pub(super) const fn eval_straight5s(ranks: u16) -> i16 {
86    if STRAIGHT_TJQKA & ranks == STRAIGHT_TJQKA {
87        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_TJQKA))
88    } else if STRAIGHT_9TJQK & ranks == STRAIGHT_9TJQK {
89        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_9TJQK))
90    } else if STRAIGHT_89TJQ & ranks == STRAIGHT_89TJQ {
91        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_89TJQ))
92    } else if STRAIGHT_789TJ & ranks == STRAIGHT_789TJ {
93        mk_ranking(STRAIGHT, mk_masks_rank(0, STRAIGHT_789TJ))
94    } else if STRAIGHT_A789T & ranks == STRAIGHT_A789T {
95        mk_ranking(STRAIGHT, mk_masks_rank(0, U16_T))
96    } else {
97        NONE_I16
98    }
99}
100
101#[cfg(test)]
102mod tests {
103    use super::*;
104    use crate::{HandType::*, *};
105
106    fn assert_ranking(cs: &str, ht: HandType, hi: &str, lo: &str) {
107        let g = PQLGame::ShortDeck;
108
109        let rating = PQLHiRating::new(eval(c64!(cs).to_u64()));
110        let l = HandRatingView::from((g, rating));
111        let r = HandRatingView::from((g, ht, r16!(hi), r16!(lo)));
112
113        assert_eq!(l, r);
114    }
115
116    #[test]
117    fn test_straight_flush() {
118        assert_ranking("As Ks Qs Js Ts", StraightFlush, "A", "");
119        assert_ranking("Kh Qh Jh Th 9h", StraightFlush, "K", "");
120        assert_ranking("Qd Jd Td 9d 8d", StraightFlush, "Q", "");
121        assert_ranking("Jc Tc 9c 8c 7c", StraightFlush, "J", "");
122        assert_ranking("Td 9d 8d 7d Ad", StraightFlush, "T", "");
123    }
124
125    #[test]
126    fn test_quad() {
127        assert_ranking("Kh As Ah Ac Ad", Quads, "A", "K");
128        assert_ranking("7s 7h 7c 7d Ts", Quads, "7", "T");
129    }
130
131    #[test]
132    fn test_full_house() {
133        assert_ranking("As Ah Ts Th Td", FullHouse, "T", "A");
134        assert_ranking("Ts Th Td 9s 9h", FullHouse, "T", "9");
135    }
136
137    #[test]
138    fn test_flush() {
139        assert_ranking("As 7s 8s 9s Js", Flush, "AJ789", "");
140        assert_ranking("Ah 7h 8h 9h Jh", Flush, "AJ789", "");
141        assert_ranking("Ad 7d 8d 9d Jd", Flush, "AJ789", "");
142        assert_ranking("Ac 7c 8c 9c Jc", Flush, "AJ789", "");
143        assert_ranking("As 7s 8s 9s Js", Flush, "A789J", "");
144    }
145
146    #[test]
147    fn test_straight() {
148        assert_ranking("As Kh Qd Jc Ts", Straight, "A", "");
149        assert_ranking("Ks Qh Jd Tc 9s", Straight, "K", "");
150        assert_ranking("Qs Jh Td 9c 8s", Straight, "Q", "");
151        assert_ranking("Js Th 9d 8c 7s", Straight, "J", "");
152        assert_ranking("Ts 9h 8d 7c As", Straight, "T", "");
153    }
154
155    #[test]
156    fn test_trips() {
157        assert_ranking("Ts Th Td As Kh", Trips, "T", "AK");
158    }
159
160    #[test]
161    fn test_two_pairs() {
162        assert_ranking("Ts Th 7s 7h Ks", TwoPair, "T7", "K");
163        assert_ranking("Ts Th 7s 7h Jd", TwoPair, "T7", "J");
164    }
165
166    #[test]
167    fn test_pair() {
168        assert_ranking("Js Jh 8d 9c Ks", Pair, "J", "K98");
169        assert_ranking("As Ah 8d Tc Ks", Pair, "A", "KT8");
170    }
171
172    #[test]
173    fn test_high_card() {
174        assert_ranking("8d 9c Js Qh Kd", HighCard, "KQJ98", "");
175    }
176}