1 /*
2  * Copyright (C) 2002 Michael Maurer <mjmaurer@yahoo.com>
3  *
4  * This program gives you software freedom; you can copy, convey,
5  * propagate, redistribute and/or modify this program under the terms of
6  * the GNU General Public License (GPL) as published by the Free Software
7  * Foundation (FSF), either version 3 of the License, or (at your option)
8  * any later version of the GPL published by the FSF.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program in a file in the toplevel directory called "GPLv3".
17  * If not, see <http://www.gnu.org/licenses/>.
18  */
19 /* eval_omaha.h -- Omaha High and Omaha High/Low 8-or-better hand evaluators
20  *
21  * Uses brute-force enumeration of legal hole-card board-card combinations,
22  * and is probably at least 60 times slower than Holdem evaluation.  A legal
23  * hole-card board-card combination uses exactly 2 hole cards and 3 board
24  * cards.
25  *
26  * Michael Maurer, Mar 2002.
27  */
28 
29 #ifndef __EVAL_OMAHA_H__
30 #define __EVAL_OMAHA_H__
31 
32 #include "inlines/eval.h"
33 #include "inlines/eval_low8.h"
34 #include "deck_std.h"
35 #include "rules_std.h"
36 
37 #define OMAHA_MINHOLE 4		/* must be at least 2 */
38 #define OMAHA_MAXHOLE 4		/* could be larger */
39 #define OMAHA_MINBOARD 3	/* must be at least 3 */
40 #define OMAHA_MAXBOARD 5	/* could be larger */
41 
42 /* Evaluate an omaha hand for both high and low.  Return nonzero on error.
43    If hival is NULL, skips high evaluation; if loval is NULL, skips
44    low evaluation.  Low eval could be sped up with 256x256 rank table. */
45 
46 static inline int
StdDeck_OmahaHiLow8_EVAL(StdDeck_CardMask hole,StdDeck_CardMask board,HandVal * hival,LowHandVal * loval)47 StdDeck_OmahaHiLow8_EVAL(StdDeck_CardMask hole, StdDeck_CardMask board,
48                          HandVal *hival, LowHandVal *loval) {
49   StdDeck_CardMask allcards;
50   LowHandVal allval;
51   HandVal curhi, besthi;
52   LowHandVal curlo, bestlo;
53   StdDeck_CardMask hole1[OMAHA_MAXHOLE];
54   StdDeck_CardMask board1[OMAHA_MAXBOARD];
55   StdDeck_CardMask n1, n2, n3, n4, n5;
56   int nhole, nboard;
57   int eligible = 0;
58   int i, h1, h2, b1, b2, b3;
59 
60   /* pluck out individual cards from hole and board masks, save in arrays */
61   nhole = nboard = 0;
62   for (i=0; i<StdDeck_N_CARDS; i++) {
63     if (StdDeck_CardMask_CARD_IS_SET(hole, i)) {
64       if (nhole >= OMAHA_MAXHOLE)
65         return 1;                               /* too many hole cards */
66       StdDeck_CardMask_RESET(hole1[nhole]);
67       StdDeck_CardMask_SET(hole1[nhole], i);
68       nhole++;
69     }
70     if (StdDeck_CardMask_CARD_IS_SET(board, i)) {
71       if (StdDeck_CardMask_CARD_IS_SET(hole, i)) /* same card in hole and board */
72         return 2;
73       if (nboard >= OMAHA_MAXBOARD)
74         return 3;                               /* too many board cards */
75       StdDeck_CardMask_RESET(board1[nboard]);
76       StdDeck_CardMask_SET(board1[nboard], i);
77       nboard++;
78     }
79   }
80 
81   if (nhole < OMAHA_MINHOLE || nhole > OMAHA_MAXHOLE)
82     return 4;                                   /* wrong # of hole cards */
83   if (nboard < OMAHA_MINBOARD || nboard > OMAHA_MAXBOARD)
84     return 5;                                   /* wrong # of board cards */
85 
86   /* quick test in case no low is possible with all 9 cards */
87   if (loval != NULL) {
88     StdDeck_CardMask_OR(allcards, hole, board);
89     allval = StdDeck_Lowball8_EVAL(allcards, nhole + nboard);
90     eligible = (allval != LowHandVal_NOTHING);
91   }
92 
93   /* loop over all combinations of hole with board (60 for 4 hole cards
94      and 5 board cards). */
95   besthi = HandVal_NOTHING;
96   bestlo = LowHandVal_NOTHING;
97   /* {h1,h2} loop over all hole card combinations */
98   for (h1=0; h1<nhole-1; h1++) {
99     StdDeck_CardMask_RESET(n1);
100     StdDeck_CardMask_OR(n1, n1, hole1[h1]);
101     for (h2=h1+1; h2<nhole; h2++) {
102       StdDeck_CardMask_OR(n2, n1, hole1[h2]);
103       /* {b1,b2,b3} loop over all board card combinations */
104       for (b1=0; b1<nboard-2; b1++) {
105         StdDeck_CardMask_OR(n3, n2, board1[b1]);
106         for (b2=b1+1; b2<nboard-1; b2++) {
107           StdDeck_CardMask_OR(n4, n3, board1[b2]);
108           for (b3=b2+1; b3<nboard; b3++) {
109             if (hival != NULL) {
110               StdDeck_CardMask_OR(n5, n4, board1[b3]);
111               curhi = StdDeck_StdRules_EVAL_N(n5, 5);
112               if (curhi > besthi || besthi == HandVal_NOTHING)
113                 besthi = curhi;
114             }
115             if (loval != NULL && eligible) {
116               curlo = StdDeck_Lowball8_EVAL(n5, 5);
117               if (curlo < bestlo || bestlo == LowHandVal_NOTHING)
118                 bestlo = curlo;
119             }
120           }
121         }
122       }
123     }
124   }
125   if (hival != NULL) *hival = besthi;
126   if (loval != NULL) *loval = bestlo;
127   return 0;
128 }
129 
130 /* Evaluate an omaha hand for high only.  Return nonzero on error. */
131 
132 static inline int
StdDeck_OmahaHi_EVAL(StdDeck_CardMask hole,StdDeck_CardMask board,HandVal * hival)133 StdDeck_OmahaHi_EVAL(StdDeck_CardMask hole, StdDeck_CardMask board,
134                      HandVal *hival) {
135   return StdDeck_OmahaHiLow8_EVAL(hole, board, hival, NULL);
136 }
137 
138 #endif
139