1 /* 2 * Copyright (C) 2004-2006 3 * Michael Maurer <mjmaurer@yahoo.com> 4 * Loic Dachary <loic@dachary.org> 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 /* $Id: enumord.h 5146 2008-12-04 03:11:22Z bkuhn $ */ 22 /* 23 Definitions for computing a histogram of final hand orderings. 24 25 A final hand ordering is defined by the relative rank of each player's hand 26 after all cards are dealt. For example, in a high-only game with 3 players, 27 the possible final hand orderings for players A, B, and C are (where 28 comma denotes tie): 29 A B C 30 A C B 31 B A C 32 B C A 33 C A B 34 C B A 35 A B,C 36 B A,C 37 C A,B 38 A,B C 39 A,C B 40 B,C A 41 A,B,C 42 Another way to reprsent this is to assign a player to a column and write 43 the relative hand rank (1=best) in that column. Then the possibilities 44 above are written (in the same order as above) as 45 A B C 46 ----- 47 1 2 3 48 1 3 2 49 2 1 3 50 2 3 1 51 3 1 2 52 3 2 1 53 1 2 2 54 2 1 2 55 2 2 1 56 1 1 2 57 1 2 1 58 2 1 1 59 1 1 1 60 Our encoding here is based on the second form. 61 62 For high/low games, we track the full combination of outcomes. In a 63 2-person game with a qualifier for low, the possible outcomes are: 64 HI LO 65 A B A B 66 1 1 1 1 tie for high; tie for low 67 1 1 1 2 tie for high; A wins low 68 1 1 1 NQ tie for high; A wins low, B doesn't qualify low 69 1 1 2 1 tie for high; B wins low 70 1 1 NQ 1 etc. 71 1 1 NQ NQ 72 1 2 1 1 73 1 2 1 2 74 1 2 1 NQ 75 1 2 2 1 76 1 2 NQ 1 77 1 2 NQ NQ 78 2 1 1 1 79 2 1 1 2 80 2 1 1 NQ 81 2 1 2 1 82 2 1 NQ 1 83 2 1 NQ NQ 84 85 For ease of programming, we are somewhat wasteful of memory when storing the 86 histogram of outcomes. We allocate an array such that hist[i] is the number 87 of times that outcome i occurs. The integer i encodes the ordering of N 88 players' hand ranks by using N bit fields, each bit field just large enough 89 to represent the numbers [0..N]. The value 0 in bit field K indicates that 90 player K has the strongest hand (possibly tying another player); the value 91 N-1 indicates player K has the weakest hand; the value N indicates a 92 non-qualifying hand (such as a 9-low in 8-or-better). Note that not all 93 integers i correspond to valid rank orderings, both due the fact that for 94 some values of N the bit field can encode values greater than N, and due to 95 the fact that some rank orderings, like a 3-way tie for 3rd place, are 96 impossible. That is the wasteful part; a hash table would solve it. 97 98 For high-low games, we use two such sets of bit fields, packed adjacent to 99 one another in a single integer. The high-order bit fields correspond to 100 the high hand; the low-order bit fields correspond to the low hand. 101 102 Michael Maurer, Jun 2002 103 */ 104 105 #ifndef ENUMORD_H 106 #define ENUMORD_H 107 108 #include "pokereval_export.h" 109 #include "poker_defs.h" 110 111 /* largest integer N such that N * ENUM_ORDERING_NBITS(N) < 32 */ 112 #define ENUM_ORDERING_MAXPLAYERS 7 113 114 /* largest integer N such that 2 * N * ENUM_ORDERING_NBITS(N) < 32 */ 115 #define ENUM_ORDERING_MAXPLAYERS_HILO 5 116 117 typedef enum { 118 enum_ordering_mode_none = 0, 119 enum_ordering_mode_hi, 120 enum_ordering_mode_lo, 121 enum_ordering_mode_hilo 122 } enum_ordering_mode_t; 123 124 typedef struct { 125 enum_ordering_mode_t mode; 126 unsigned int nplayers; 127 unsigned int nentries; /* equal to ENUM_ORDERING_NENTRIES(nplayers) 128 or ENUM_ORDERING_NENTRIES_HILO(nplayers), 129 depending on mode */ 130 /* hist[i] is the number of outcomes in which the ordering of players' 131 relative hand values corresponds to ordering i. We encode each ordering 132 as an integer i such that ENUM_ORDERING_DECODE_PLAYER_K(i, n, k) gives 133 the relative hand rank of player k out of n players. Rank is encoded as 134 an integer in [0,n] where 0=strongest, n-1=weakest, n=non-qualifying. */ 135 unsigned int *hist; /* has nenetries elements */ 136 } enum_ordering_t; 137 138 extern POKEREVAL_EXPORT int enum_nbits[ENUM_ORDERING_MAXPLAYERS+1]; 139 extern POKEREVAL_EXPORT void enum_ordering_rank(HandVal *hands, int noqual, 140 int nplayers, int *ranks, int reverse); 141 142 /* the bit field size for one player's relative hand rank */ 143 #define ENUM_ORDERING_NBITS(nplayers) \ 144 ((nplayers < 0 || nplayers >= sizeof(enum_nbits)/sizeof(enum_nbits[0])) \ 145 ? -1 : enum_nbits[nplayers]) 146 147 /* the number of elements in the hist[] array */ 148 #define ENUM_ORDERING_NENTRIES(nplayers) \ 149 (((nplayers > ENUM_ORDERING_MAXPLAYERS) || \ 150 ENUM_ORDERING_NBITS(nplayers) < 0) \ 151 ? -1 : (1 << (nplayers * ENUM_ORDERING_NBITS(nplayers)))) 152 153 /* the number of elements in the hist[] array in high/low games */ 154 #define ENUM_ORDERING_NENTRIES_HILO(nplayers) \ 155 (((nplayers > ENUM_ORDERING_MAXPLAYERS_HILO) || \ 156 ENUM_ORDERING_NBITS(nplayers) < 0) \ 157 ? -1 : (1 << (2 * nplayers * ENUM_ORDERING_NBITS(nplayers)))) 158 159 /* Compute the integer encoding of a given array of relative hand rankings. 160 ranks[k] is relative hand rank of player k's hand; rank=0 is best, 161 rank=nplayers-1 is worst, rank=nplayers is non-qualifying. Caller must 162 ensure that 0 <= ranks[k] <= nplayers. */ 163 #define ENUM_ORDERING_ENCODE(encoding, nplayers, ranks) \ 164 do { \ 165 int _k; \ 166 int _nbits = ENUM_ORDERING_NBITS(nplayers); \ 167 (encoding) = 0; \ 168 for (_k=0; _k<(nplayers); _k++) \ 169 (encoding) = ((encoding) << _nbits) | ((ranks)[_k]); \ 170 } while (0) 171 172 /* Compute the integer encoding of a given array of relative hand rankings 173 for high/low games. */ 174 #define ENUM_ORDERING_ENCODE_HILO(encoding, nplayers, hiranks, loranks) \ 175 do { \ 176 int _k; \ 177 int _nbits = ENUM_ORDERING_NBITS(nplayers); \ 178 (encoding) = 0; \ 179 for (_k=0; _k<(nplayers); _k++) \ 180 (encoding) = ((encoding) << _nbits) | ((hiranks)[_k]); \ 181 for (_k=0; _k<(nplayers); _k++) \ 182 (encoding) = ((encoding) << _nbits) | ((loranks)[_k]); \ 183 } while (0) 184 185 /* the number of bits to the start of the bit field for player k */ 186 #define ENUM_ORDERING_SHIFT_K(nplayers, k) \ 187 (((nplayers) - (k) - 1) * ENUM_ORDERING_NBITS(nplayers)) 188 189 /* the number of bits to the start of the bit field for player k's high 190 hand, in a high/low game */ 191 #define ENUM_ORDERING_SHIFT_HILO_K_HI(nplayers, k) \ 192 ((2*(nplayers) - (k) - 1) * ENUM_ORDERING_NBITS(nplayers)) 193 194 /* the number of bits to the start of the bit field for player k's low 195 hand, in a high/low game */ 196 #define ENUM_ORDERING_SHIFT_HILO_K_LO(nplayers, k) \ 197 (((nplayers) - (k) - 1) * ENUM_ORDERING_NBITS(nplayers)) 198 199 /* a bit mask covering the bit field for player k */ 200 #define ENUM_ORDERING_MASK_K(nplayers, k) \ 201 ((~(~0 << ENUM_ORDERING_NBITS(nplayers))) << \ 202 ENUM_ORDERING_SHIFT_K((nplayers), (k))) 203 204 /* a bit mask covering the bit field for player k's high hand, in a high/low 205 game */ 206 #define ENUM_ORDERING_MASK_HILO_K_HI(nplayers, k) \ 207 ((~(~0 << ENUM_ORDERING_NBITS(nplayers))) << \ 208 ENUM_ORDERING_SHIFT_HILO_K_HI((nplayers), (k))) 209 210 /* a bit mask covering the bit field for player k's low hand, in a high/low 211 game */ 212 #define ENUM_ORDERING_MASK_HILO_K_LO(nplayers, k) \ 213 ((~(~0 << ENUM_ORDERING_NBITS(nplayers))) << \ 214 ENUM_ORDERING_SHIFT_HILO_K_LO((nplayers), (k))) 215 216 /* decodes the integer encoding to yield the relative rank of 217 player k's hand */ 218 #define ENUM_ORDERING_DECODE_K(encoding, nplayers, k) \ 219 (((encoding) & ENUM_ORDERING_MASK_K((nplayers), (k))) >> \ 220 ENUM_ORDERING_SHIFT_K((nplayers), (k))) 221 222 /* decodes the integer encoding to yield the relative rank of 223 player k's high hand in a high/low game */ 224 #define ENUM_ORDERING_DECODE_HILO_K_HI(encoding, nplayers, k) \ 225 (((encoding) & ENUM_ORDERING_MASK_HILO_K_HI((nplayers), (k))) >> \ 226 ENUM_ORDERING_SHIFT_HILO_K_HI((nplayers), (k))) 227 228 /* decodes the integer encoding to yield the relative rank of 229 player k's low hand in a high/low game */ 230 #define ENUM_ORDERING_DECODE_HILO_K_LO(encoding, nplayers, k) \ 231 (((encoding) & ENUM_ORDERING_MASK_HILO_K_LO((nplayers), (k))) >> \ 232 ENUM_ORDERING_SHIFT_HILO_K_LO((nplayers), (k))) 233 234 /* given hands[], assigns ranks[k] such that a rank of 0 indicates that 235 hands[k] is the highest hand value in hands[], a rank of 1 indicates 236 that hands[k] is the next highest value, etc., and a rank of nplayers 237 indicates that hands[k] is equal to noqual (the not-qualifying hand) */ 238 #define ENUM_ORDERING_RANK_HI(hands, noqual, nplayers, ranks) \ 239 enum_ordering_rank((hands), (noqual), (nplayers), (ranks), 0) 240 241 /* given hands[], assigns ranks[k] such that a rank of 0 indicates that 242 hands[k] is the lowest hand value in hands[], a rank of 1 indicates 243 that hands[k] is the next lowest value, etc., and a rank of nplayers 244 indicates that hands[k] is equal to noqual (the not-qualifying hand) */ 245 #define ENUM_ORDERING_RANK_LO(hands, noqual, nplayers, ranks) \ 246 enum_ordering_rank((hands), (noqual), (nplayers), (ranks), 1) 247 248 /* increments the histogram bin value corresponding to the ranks[] array */ 249 #define ENUM_ORDERING_INCREMENT(ordering, nplayers, ranks) \ 250 do { \ 251 int _encoding; \ 252 ENUM_ORDERING_ENCODE(_encoding, (nplayers), (ranks)); \ 253 (ordering)->hist[_encoding]++; \ 254 } while (0) 255 256 /* increments the histogram bin value corresponding to the ranks[] array, 257 for high/low games*/ 258 #define ENUM_ORDERING_INCREMENT_HILO(ordering, nplayers, hiranks, loranks) \ 259 do { \ 260 int _encoding; \ 261 ENUM_ORDERING_ENCODE_HILO(_encoding, (nplayers), (hiranks), (loranks)); \ 262 (ordering)->hist[_encoding]++; \ 263 } while (0) 264 265 #endif 266