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