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