1 /*
2 * eval.h: a fast poker hand evaluator
3 *
4 * Copyright (C) 1993-99 Brian Goetz, Keith Miyake, Clifford T. Matthews
5 *
6 * This program gives you software freedom; you can copy, convey,
7 * propagate, redistribute and/or modify this program under the terms of
8 * the GNU General Public License (GPL) as published by the Free Software
9 * Foundation (FSF), either version 3 of the License, or (at your option)
10 * any later version of the GPL published by the FSF.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program in a file in the toplevel directory called "GPLv3".
19 * If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #ifndef __EVAL_H__
23 #define __EVAL_H__
24
25 #include "poker_defs.h"
26 #include <assert.h>
27
28 /*
29 * When run over seven cards, here are the distribution of hands:
30 * high hand: 23294460
31 * pair: 58627800
32 * two pair: 31433400
33 * three of a kind: 6461620
34 * straight: 6180020
35 * flush: 4047644
36 * full house: 3473184
37 * four of a kind: 224848
38 * straight flush: 41584
39 *
40 */
41
42 #define SC sc
43 #define SD sd
44 #define SH sh
45 #define SS ss
46
47 /*
48 * is_straight used to check for a straight by masking the ranks with four
49 * copies of itself, each shifted one bit with respect to the
50 * previous one. So any sequence of five adjacent bits will still
51 * be non-zero, but any gap will result in a zero value. There's
52 * a nice side-effect of leaving the top most bit set so we can use
53 * it to set top_card.
54 * Now we use a precomputed lookup table.
55 *
56 */
57
58 #if 0
59 /* Keith's is-straight, which is still pretty good and uses one less table. */
60 if ( (ranks2 = ranks & (ranks << 1)) &&
61 (ranks2 &= (ranks << 2)) &&
62 (ranks2 &= (ranks << 3)) &&
63 (ranks2 &= (ranks << 4)) ) {
64 retval.eval_t.hand = StdRules_HandType_STRAIGHT;
65 retval.eval_t.top_card = topCardTable[ranks2];
66 } else if ((ranks & StdDeck_FIVE_STRAIGHT) == StdDeck_FIVE_STRAIGHT) {
67 retval.eval_t.hand = StdRules_HandType_STRAIGHT;
68 retval.eval_t.top_card = StdDeck_Ranks_5;
69 }
70 #endif
71
72
73 static inline HandVal
StdDeck_StdRules_EVAL_N(StdDeck_CardMask cards,int n_cards)74 StdDeck_StdRules_EVAL_N( StdDeck_CardMask cards, int n_cards )
75 {
76 HandVal retval;
77 uint32 ranks, four_mask, three_mask, two_mask,
78 n_dups, n_ranks;
79 uint32 sc, sd, sh, ss;
80
81 ss = StdDeck_CardMask_SPADES(cards);
82 sc = StdDeck_CardMask_CLUBS(cards);
83 sd = StdDeck_CardMask_DIAMONDS(cards);
84 sh = StdDeck_CardMask_HEARTS(cards);
85
86 retval = 0;
87 ranks = SC | SD | SH | SS;
88 n_ranks = nBitsTable[ranks];
89 n_dups = n_cards - n_ranks;
90
91 /* Check for straight, flush, or straight flush, and return if we can
92 determine immediately that this is the best possible hand
93 */
94 if (n_ranks >= 5) {
95 if (nBitsTable[SS] >= 5) {
96 if (straightTable[SS])
97 return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
98 + HandVal_TOP_CARD_VALUE(straightTable[SS]);
99 else
100 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
101 + topFiveCardsTable[SS];
102 }
103 else if (nBitsTable[SC] >= 5) {
104 if (straightTable[SC])
105 return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
106 + HandVal_TOP_CARD_VALUE(straightTable[SC]);
107 else
108 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
109 + topFiveCardsTable[SC];
110 }
111 else if (nBitsTable[SD] >= 5) {
112 if (straightTable[SD])
113 return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
114 + HandVal_TOP_CARD_VALUE(straightTable[SD]);
115 else
116 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
117 + topFiveCardsTable[SD];
118 }
119 else if (nBitsTable[SH] >= 5) {
120 if (straightTable[SH])
121 return HandVal_HANDTYPE_VALUE(StdRules_HandType_STFLUSH)
122 + HandVal_TOP_CARD_VALUE(straightTable[SH]);
123 else
124 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FLUSH)
125 + topFiveCardsTable[SH];
126 }
127 else {
128 int st;
129
130 st = straightTable[ranks];
131 if (st)
132 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_STRAIGHT)
133 + HandVal_TOP_CARD_VALUE(st);
134 };
135
136 /* Another win -- if there can't be a FH/Quads (n_dups < 3),
137 which is true most of the time when there is a made hand, then if we've
138 found a five card hand, just return. This skips the whole process of
139 computing two_mask/three_mask/etc.
140 */
141 if (retval && n_dups < 3)
142 return retval;
143 };
144
145 /*
146 * By the time we're here, either:
147 1) there's no five-card hand possible (flush or straight), or
148 2) there's a flush or straight, but we know that there are enough
149 duplicates to make a full house / quads possible.
150 */
151 switch (n_dups)
152 {
153 case 0:
154 /* It's a no-pair hand */
155 return HandVal_HANDTYPE_VALUE(StdRules_HandType_NOPAIR)
156 + topFiveCardsTable[ranks];
157 break;
158
159 case 1: {
160 /* It's a one-pair hand */
161 uint32 t, kickers;
162
163 two_mask = ranks ^ (SC ^ SD ^ SH ^ SS);
164
165 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_ONEPAIR)
166 + HandVal_TOP_CARD_VALUE(topCardTable[two_mask]);
167 t = ranks ^ two_mask; /* Only one bit set in two_mask */
168 /* Get the top five cards in what is left, drop all but the top three
169 * cards, and shift them by one to get the three desired kickers */
170 kickers = (topFiveCardsTable[t] >> HandVal_CARD_WIDTH)
171 & ~HandVal_FIFTH_CARD_MASK;
172 retval += kickers;
173
174 return retval;
175 }
176 break;
177
178 case 2:
179 /* Either two pair or trips */
180
181 two_mask = ranks ^ (SC ^ SD ^ SH ^ SS);
182 if (two_mask) {
183 uint32 t;
184
185 t = ranks ^ two_mask; /* Exactly two bits set in two_mask */
186 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_TWOPAIR)
187 + (topFiveCardsTable[two_mask]
188 & (HandVal_TOP_CARD_MASK | HandVal_SECOND_CARD_MASK))
189 + HandVal_THIRD_CARD_VALUE(topCardTable[t]);
190
191 return retval;
192 }
193 else {
194 int t, second;
195
196 three_mask = (( SC&SD )|( SH&SS )) & (( SC&SH )|( SD&SS ));
197
198 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_TRIPS)
199 + HandVal_TOP_CARD_VALUE(topCardTable[three_mask]);
200
201 t = ranks ^ three_mask; /* Only one bit set in three_mask */
202 second = topCardTable[t];
203 retval += HandVal_SECOND_CARD_VALUE(second);
204 t ^= (1 << second);
205 retval += HandVal_THIRD_CARD_VALUE(topCardTable[t]);
206 return retval;
207 }
208 break;
209
210 default:
211 /* Possible quads, fullhouse, straight or flush, or two pair */
212 four_mask = SH & SD & SC & SS;
213 if (four_mask) {
214 int tc;
215
216 tc = topCardTable[four_mask];
217 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_QUADS)
218 + HandVal_TOP_CARD_VALUE(tc)
219 + HandVal_SECOND_CARD_VALUE(topCardTable[ranks ^ (1 << tc)]);
220 return retval;
221 };
222
223 /* Technically, three_mask as defined below is really the set of
224 bits which are set in three or four of the suits, but since
225 we've already eliminated quads, this is OK */
226 /* Similarly, two_mask is really two_or_four_mask, but since we've
227 already eliminated quads, we can use this shortcut */
228
229 two_mask = ranks ^ (SC ^ SD ^ SH ^ SS);
230 if (nBitsTable[two_mask] != n_dups) {
231 /* Must be some trips then, which really means there is a
232 full house since n_dups >= 3 */
233 int tc, t;
234
235 three_mask = (( SC&SD )|( SH&SS )) & (( SC&SH )|( SD&SS ));
236 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_FULLHOUSE);
237 tc = topCardTable[three_mask];
238 retval += HandVal_TOP_CARD_VALUE(tc);
239 t = (two_mask | three_mask) ^ (1 << tc);
240 retval += HandVal_SECOND_CARD_VALUE(topCardTable[t]);
241 return retval;
242 };
243
244 if (retval) /* flush and straight */
245 return retval;
246 else {
247 /* Must be two pair */
248 int top, second;
249
250 retval = HandVal_HANDTYPE_VALUE(StdRules_HandType_TWOPAIR);
251 top = topCardTable[two_mask];
252 retval += HandVal_TOP_CARD_VALUE(top);
253 second = topCardTable[two_mask ^ (1 << top)];
254 retval += HandVal_SECOND_CARD_VALUE(second);
255 retval += HandVal_THIRD_CARD_VALUE(topCardTable[ranks ^ (1 << top)
256 ^ (1 << second)]);
257 return retval;
258 };
259
260 break;
261 };
262
263 /* Should never happen */
264 assert(!"Logic error in StdDeck_StdRules_EVAL_N");
265 }
266
267 #undef SC
268 #undef SH
269 #undef SD
270 #undef SS
271
272 #endif
273
274