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