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}