-
Notifications
You must be signed in to change notification settings - Fork 0
/
Hand.c
420 lines (362 loc) · 6.77 KB
/
Hand.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
#include <stdio.h>
#include <stdbool.h>
#include <Hand.h>
#include <Card.h>
const unsigned int HAND_NUM_HIGH_CARDS = RANK_ACE - RANK_SIX + 1; // 9
const unsigned int HAND_NUM_PAIRS = 0;
const unsigned int HAND_NUM_TWO_PAIRS = 0;
const unsigned int HAND_NUM_THREE_KINDS = 0;
const unsigned int HAND_NUM_STRAIGHTS = 0;
const unsigned int HAND_NUM_FLUSHES = 0;
const unsigned int HAND_NUM_FULL_HOUSES = 0;
const unsigned int HAND_NUM_FOUR_KINDS;
const unsigned int HAND_NUM_STRAIGHT_FLUSHES = 0;
const unsigned int HAND_SIZE = HAND_SIZE_MACRO;
void Hand_init(Hand* const hand, const Card* const cards)
{
for (int i = 0; i < HAND_SIZE; ++i)
{
hand->cards[i] = cards[i];
}
}
unsigned int Hand_calcValue(const Hand hand)
{
HandType type = Hand_getType(hand);
unsigned int value = 0;
switch (type)
{
case HAND_STRAIGHT_FLUSH:
case HAND_FOUR_KIND:
if (type == HAND_FOUR_KIND)
{
}
else
{
value += HAND_NUM_FOUR_KINDS;
}
case HAND_FULL_HOUSE:
if (type == HAND_FULL_HOUSE)
{
}
else
{
value += HAND_NUM_FULL_HOUSES;
}
case HAND_FLUSH:
if (type == HAND_FLUSH)
{
}
else
{
value += HAND_NUM_FLUSHES;
}
case HAND_STRAIGHT:
if (type == HAND_STRAIGHT)
{
}
else
{
value += HAND_NUM_STRAIGHTS;
}
case HAND_THREE_KIND:
if (type == HAND_THREE_KIND)
{
}
else
{
value += HAND_NUM_THREE_KINDS;
}
case HAND_TWO_PAIR:
if (type == HAND_TWO_PAIR)
{
}
else
{
value += HAND_NUM_TWO_PAIRS;
}
case HAND_PAIR:
if (type == HAND_PAIR)
{
}
else
{
value += HAND_NUM_PAIRS;
}
case HAND_HIGH_CARD:
if (type == HAND_HIGH_CARD)
{
}
else
{
value += HAND_NUM_HIGH_CARDS;
}
}
}
HandType Hand_getType(const Hand hand)
{
if (Hand_hasStraightFlush(hand))
{
return HAND_STRAIGHT_FLUSH;
}
else if (Hand_hasFour(hand))
{
return HAND_FOUR_KIND;
}
else if (Hand_hasFullHouse(hand))
{
return HAND_FULL_HOUSE;
}
else if (Hand_hasFlush(hand))
{
return HAND_FLUSH;
}
else if (Hand_hasStraight(hand))
{
return HAND_STRAIGHT;
}
else if (Hand_hasThree(hand))
{
return HAND_THREE_KIND;
}
else if (Hand_hasTwoPair(hand))
{
return HAND_TWO_PAIR;
}
else if (Hand_hasPair(hand))
{
return HAND_PAIR;
}
else
{
return HAND_HIGH_CARD;
}
}
bool Hand_hasPair(const Hand hand)
{
for (int i = 0; i < HAND_SIZE; ++i)
{
if (Hand_countRank(hand, hand.cards[i].rank) == 2)
{
return true;
}
}
return false;
}
bool Hand_hasTwoPair(const Hand hand)
{
const Rank* first_rank = NULL;
int i;
for (i = 0; i < HAND_SIZE; ++i)
{
if (Hand_countRank(hand, hand.cards[i].rank) == 2)
{
first_rank = &hand.cards[i].rank;
break;
}
}
if (first_rank == NULL)
{
// no pair was found
return false;
}
// no need to start from zero again because of the break statement
for (Rank rank; i < HAND_SIZE; ++i)
{
rank = hand.cards[i].rank;
if (Hand_countRank(hand, rank) == 2 && rank != *first_rank)
{
return true;
}
}
// second pair not found
return false;
}
bool Hand_hasThree(const Hand hand)
{
for (int i = 0; i < HAND_SIZE; ++i)
{
if (Hand_countRank(hand, hand.cards[i].rank) == 3)
{
return true;
}
}
return false;
}
bool Hand_hasStraight(const Hand hand)
{
const Rank high_rank = Hand_getHighRank(hand);
Rank rank = high_rank;
if (rank < RANK_FIVE)
{
return false; // straights don't wrap down from ace to king
}
if (rank == RANK_ACE)
{
// look in both directions
// a straight RANK_ACE - RANK_FIVE will return RANK_ACE as high card
bool found_straight = false;
Rank_preincr(&rank);
for (int i = 0; i < HAND_SIZE - 1; ++i, Rank_preincr(&rank))
{
// assume until proven otherwise that there is a straight
found_straight = (Hand_countRank(hand, rank) == 1);
if (!found_straight)
{
// if disproven for any card, stop checking other cards
break;
}
}
// STATUS: if we've found a straight by ascending up from ace, found_straight will be true
if (found_straight)
{
return true;
}
// else search in other direction
rank = high_rank; // reset state
}
Rank_predecr(&rank);
for (int i = 0; i < HAND_SIZE - 1; ++i, Rank_predecr(&rank))
{
if (Hand_countRank(hand, rank) != 1)
{
// this loop was the last opportunity to find a straight, but it was not found
return false;
}
}
return true;
}
bool Hand_hasFlush(const Hand hand)
{
Suit last_suit = hand.cards[0].suit;
for (int i = 1; i < HAND_SIZE; ++i)
{
if (hand.cards[i].suit != last_suit)
{
return false;
}
}
return true;
}
bool Hand_hasFullHouse(const Hand hand)
{
// search for pair
Rank pair_rank;
bool found_pair = false;
for (int i = 0; i < HAND_SIZE; ++i)
{
if (Hand_countRank(hand, hand.cards[i].rank) == 2)
{
pair_rank = hand.cards[i].rank;
found_pair = true;
break; // start searching for the three of a kind
}
}
if (!found_pair)
{
return false;
}
for (int i = 0; i < HAND_SIZE; ++i)
{
if (hand.cards[i].rank != pair_rank &&
Hand_countRank(hand, hand.cards[i].rank) == 3)
{
return true;
}
}
return false;
}
bool Hand_hasFour(const Hand hand)
{
for (int i = 0; i < HAND_SIZE; ++i)
{
if (Hand_countRank(hand, hand.cards[i].rank) == 4)
{
return true;
}
}
return false;
}
bool Hand_hasStraightFlush(const Hand hand)
{
return Hand_hasFlush(hand) && Hand_hasStraight(hand);
}
Card Hand_getHighCard(const Hand hand)
{
int max_indx = 0;
int max_val = 0;
for (int i = 0, tmp; i < HAND_SIZE; ++i)
{
tmp = Card_calcValue(hand.cards[i]);
// it is possible to have a card of value 0 at an index besides 0, thus allow 'or equal to'
if (tmp >= max_val)
{
max_val = tmp;
max_indx = i;
}
}
return hand.cards[max_indx];
}
Rank Hand_getHighRank(const Hand hand)
{
// two is the lowest rank, ace counts as above king if void of context
Rank high_rank = RANK_TWO;
for (int i = 0; i < HAND_SIZE; ++i)
{
if (hand.cards[i].rank > high_rank)
{
high_rank = hand.cards[i].rank;
}
}
return high_rank;
}
Suit Hand_getHighSuit(const Hand hand)
{
// clubs are the lowest ranking suit
Suit high_suit = SUIT_CLUB;
for (int i = 0; i < HAND_SIZE; ++i)
{
if (hand.cards[i].suit > high_suit)
{
high_suit = hand.cards[i].suit;
}
}
return high_suit;
}
bool Hand_containsCard(const Hand hand, const Card card)
{
for (int i = 0; i < HAND_SIZE; ++i)
{
if (Card_equals(hand.cards[i], card))
{
return true;
}
}
return false;
}
int Hand_countRank(const Hand hand, const Rank rank)
{
int count = 0;
for (int i = 0; i < HAND_SIZE; ++i)
{
if (hand.cards[i].rank == rank)
{
++count;
}
}
return count;
}
int Hand_countSuit(const Hand hand, const Suit suit)
{
int count = 0;
for (int i = 0; i < HAND_SIZE; ++i)
{
if (hand.cards[i].suit == suit)
{
++count;
}
}
return count;
}
void Hand_setHighCard(Hand hand, const Card new_high)
{
}