open_pql/prim/eval/
shortdeck7.rs1use 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}