cleaned all trailing white space from source files.
[sdk] / samples / games / cards / poker / pokerUtils.ec
1 /****************************************************************************
2    POKER Game Interface
3
4    Copyright (c) 2001 Jerome Jacovella-St-Louis
5    All Rights Reserved.
6
7    pokerutils.c - Poker Backend Utilities
8 ****************************************************************************/
9 import "poker.ec"
10
11 // --- Data ---
12
13 static int handsRests[10] = { 5, 3, 1, 2, 0, 0, 0, 1, 0, 0 };
14
15 // { 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A }
16 // { 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A }
17 // { 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A }
18 // { 2, 3, 4, 5, 6, 7, 8, 9, 10, J, Q, K, A }
19
20 // --- Static Utilities ---
21
22 static int Compare(const int * a, const int * b)
23 {
24    if(*a > *b) return 1; else if(*a < *b) return -1; else return 0;
25 }
26
27 static bool POKER_Straight(int cards[5])
28 {
29    int c;
30    for(c = 1; c<5; c++)
31       if((cards[c] / 4 != cards[c-1] / 4 + 1) && !(cards[c - 1] / 4 == 12 && cards[c] / 4 == 0))
32          return false;
33    return true;
34 }
35
36 static bool POKER_Flush(int cards[5])
37 {
38    int c;
39    for(c = 1; c<5; c++)
40       if(cards[c] % 4 != cards[0] % 4)
41          return false;
42    return true;
43 }
44
45 static bool POKER_Same(int cards[5], int howMany, int what[2], int rest[3])
46 {
47    int c;
48    int card;
49    int numPairs = 0;
50
51    for(card = 0; card<13; card++)
52    {
53       int num = 0;
54       for(c = 0; c < 5; c++)
55       {
56          if(cards[c] / 4 == card)
57             num++;
58       }
59       if(num == howMany)
60       {
61          what[numPairs++] = card;
62       }
63    }
64    if(numPairs)
65    {
66       int d;
67       qsort(what, numPairs, sizeof(int), Compare);
68       for(d = 0, c = 0; c<5; c++)
69       {
70          int w;
71          for(w = 0; w < numPairs; w++)
72             if(cards[c] / 4 == what[w])
73                break;
74          if(w == numPairs)
75             rest[d++] = cards[c];
76       }
77    }
78    return numPairs;
79 }
80
81 // --- External Functions ---
82
83 void POKER_SortCards(int * cards, int numCards)
84 {
85    qsort(cards, numCards, sizeof(int), Compare);
86 }
87
88 int POKER_Card(int card)
89 {
90    if(card / 4 == 12)
91       card -= 13 * 4;
92    card += 4;
93    return card;
94 }
95
96 void POKER_ShuffleDeck(int deck[52])
97 {
98    int t;
99    int count;
100
101    count = GetRandom(1000, 2000);
102    for(t = 0; t<count; t++)
103    {
104       // cut the deck in 2
105       int cuts[2][52];
106       int numCut[2];
107       int indexCut[2] = {0,0};
108       int cut = GetRandom(13, 39);
109       int c;
110
111       for(c = 0; c<cut; c++)
112          cuts[0][c] = deck[c];
113       for(c = cut; c<52; c++)
114          cuts[1][c - cut] = deck[c];
115
116       numCut[0] = cut;
117       numCut[1] = 52 - cut;
118
119       // Mix the cards
120       for(c = 0; c<52; c++)
121       {
122          int whichCut;
123
124          if(indexCut[0] < numCut[0] && indexCut[1] < numCut[1])
125             whichCut = GetRandom(0,1);
126          else if(indexCut[0] < numCut[0])
127             whichCut = 0;
128          else if(indexCut[1] < numCut[1])
129             whichCut = 1;
130
131          deck[c] = cuts[whichCut][indexCut[whichCut]++];
132       }
133    }
134 }
135
136 PokerHand POKER_HandType(int cards[5])
137 {
138    bool flush, straight;
139    int numPairs, numTris, numQuads;
140    int rest[5];
141    int pairs[2], tris, quads;
142
143    /*** DETERMINE HAND TYPE ***/
144    flush    = POKER_Flush(cards);
145    straight = POKER_Straight(cards);
146    numPairs = POKER_Same(cards, 2, pairs, rest);
147    numTris  = POKER_Same(cards, 3, &tris, rest);
148    numQuads = POKER_Same(cards, 4, &quads, rest);
149
150    if(straight && flush)
151    {
152       if(cards[4] / 4 == 12)
153          return royalFlush;
154       else
155          return straightFlush;
156    }
157    else if(numQuads)
158       return fourOfAKind;
159    else if(numPairs && numTris)
160       return fullHouse;
161    else if(flush)
162       return PokerHand::flush;
163    else if(straight)
164       return PokerHand::straight;
165    else if(numTris)
166       return threeOfAKind;
167    else if(numPairs == 2)
168       return twoPair;
169    else if(numPairs)
170       return onePair;
171    else
172       return nothing;
173 }
174
175 int POKER_Compare(int cards1[5], int cards2[5])
176 {
177    bool flush[2], straight[2];
178    int numPairs[2], numTris[2], numQuads[2];
179    int * cards;
180
181    int rest[2][5];
182    int pairs[2][2], tris[2], quads[2];
183    PokerHand handType[2];
184    int h;
185    int c;
186    int numRest[2];
187
188    int winner = 0;
189
190    for(h = 0; h<2; h++)
191    {
192       cards = (h == 0) ? cards1 : cards2;
193
194       /*** DETERMINE HAND TYPE ***/
195       flush[h]    = POKER_Flush(cards);
196       straight[h] = POKER_Straight(cards);
197       numPairs[h] = POKER_Same(cards, 2, pairs[h], rest[h]);
198       numTris[h]  = POKER_Same(cards, 3, &tris[h], rest[h]);
199       numQuads[h] = POKER_Same(cards, 4, &quads[h], rest[h]);
200
201       if(straight[h] && flush[h])
202       {
203          if(cards[4] / 4 == 12)
204             handType[h] = royalFlush;
205          else
206             handType[h] = straightFlush;
207       }
208       else if(numQuads[h])
209          handType[h] = fourOfAKind;
210       else if(numPairs[h] && numTris[h])
211          handType[h] = fullHouse;
212       else if(flush[h])
213          handType[h] = PokerHand::flush;
214       else if(straight[h])
215          handType[h] = PokerHand::straight;
216       else if(numTris[h])
217          handType[h] = threeOfAKind;
218       else if(numPairs[h] == 2)
219          handType[h] = twoPair;
220       else if(numPairs[h])
221          handType[h] = onePair;
222       else
223       {
224          handType[h] = nothing;
225          CopyBytesBy4(rest[h], cards, 5);
226       }
227       numRest[h] = handsRests[handType[h]];
228    }
229
230    /*** DETERMINE WINNING HAND ***/
231    if(handType[1] > handType[0])
232       winner = 1;
233    else if(handType[0] > handType[1])
234       winner = -1;
235    else
236    {
237       switch(handType[0])
238       {
239          case straightFlush:
240             if(cards2[4] / 4 > cards1[4] / 4)
241                winner = 1;
242             else if(cards1[4] / 4> cards2[4] / 4)
243                winner = -1;
244             break;
245          case fourOfAKind:
246             if(quads[1] > quads[0] )
247                winner = 1;
248             else if(quads[0] > quads[1])
249                winner = -1;
250             break;
251          case fullHouse:
252             if(tris[1] > tris[0] )
253                winner = 1;
254             else if(tris[0] > tris[1])
255                winner = -1;
256             else if(pairs[1][0] > pairs[0][0])
257                winner = 1;
258             else if(pairs[0][0] > pairs[1][0])
259                winner = -1;
260             break;
261          case PokerHand::flush:
262             for(c = 4; c>=0; c--)
263             {
264                if(cards2[c] / 4 > cards1[c] / 4)
265                {
266                   winner = 1;
267                   break;
268                }
269                else if(cards1[c] / 4 > cards2[c] / 4)
270                {
271                   winner = -1;
272                   break;
273                }
274             }
275             break;
276          case PokerHand::straight:
277             if(cards2[4] / 4> cards1[4] / 4)
278                winner = 1;
279             else if(cards1[4] / 4> cards2[4] / 4)
280                winner = -1;
281             break;
282          case threeOfAKind:
283             if(tris[1] > tris[0] )
284                winner = 1;
285             else if(tris[0] > tris[1])
286                winner = -1;
287             break;
288          case twoPair:
289             if(pairs[1][1] > pairs[0][1])
290                winner = 1;
291             else if(pairs[0][1] > pairs[1][1])
292                winner = -1;
293             else if(pairs[1][0] > pairs[0][0])
294                winner = 1;
295             else if(pairs[0][0] > pairs[1][0])
296                winner = -1;
297             break;
298          case onePair:
299             if(pairs[1][0] > pairs[0][0])
300                winner = 1;
301             else if(pairs[0][0] > pairs[1][0])
302                winner = -1;
303             break;
304       }
305
306       /*** NO WINNER FROM TYPES, TRY TO SPLIT WITH THE rest ***/
307       if(!winner)
308       {
309          for(c = numRest[0] - 1; c>=0; c--)
310          {
311             if(rest[1][c] / 4> rest[0][c] / 4)
312             {
313                winner = 1;
314                break;
315             }
316             else if(rest[0][c] / 4 > rest[1][c] / 4)
317             {
318                winner = -1;
319                break;
320             }
321          }
322       }
323    }
324    return winner;
325 }
326
327 void POKER_BestHand(int * cards1, int * cards2, int n1, int n2, int r1, int r2, int output[5])
328 {
329    static int pos = 0;
330    static int start1 = 0;
331    static int start2 = 0;
332    static int currentHand[5];
333
334    if(pos == 5)
335    {
336       int temp[5];
337       CopyBytesBy4(temp, currentHand, 5);
338       qsort(temp, 5, sizeof(int), Compare);
339       if(POKER_Compare(output, temp) == 1)
340          CopyBytesBy4(output, temp, 5);
341    }
342    else
343    {
344       int oldStart, c;
345
346       if(pos >= r1)
347       {
348          oldStart = start2;
349          for(c = start2; c < n2 - (5 - pos - 1); c++)
350          {
351             start2 = c + 1;
352             currentHand[pos++] = cards2[c];
353             POKER_BestHand(cards1, cards2, n1, n2, r1, r2, output);
354             pos--;
355          }
356          start2 = oldStart;
357       }
358       else
359       {
360          oldStart = start1;
361          for(c = start1; c < n1 - (r1 - pos - 1); c++)
362          {
363             start1 = c + 1;
364             currentHand[pos++] = cards1[c];
365             POKER_BestHand(cards1, cards2, n1, n2, r1, r2, output);
366             pos--;
367          }
368          start1 = oldStart;
369       }
370
371       // Added this recently : was only using 5-r1 from cards2
372       if(pos >= r2)
373       {
374          oldStart = start1;
375          for(c = start1; c < n1 - (5 - pos - 1); c++)
376          {
377             start1 = c + 1;
378             currentHand[pos++] = cards1[c];
379             POKER_BestHand(cards1, cards2, n1, n2, r1, r2, output);
380             pos--;
381          }
382          start1 = oldStart;
383       }
384       else
385       {
386          oldStart = start2;
387          for(c = start2; c < n2 - (r2 - pos - 1); c++)
388          {
389             start2 = c + 1;
390             currentHand[pos++] = cards2[c];
391             POKER_BestHand(cards1, cards2, n1, n2, r1, r2, output);
392             pos--;
393          }
394          start2 = oldStart;
395       }
396    }
397 }
398
399 /*
400 void POKER_BestHand(int * cards, int n, int output[5])
401 {
402    static int pos = 0;
403    static int start = 0;
404    static int currentHand[5];
405    int c;
406
407    for(c = start; c < n - (5 - pos - 1); c++)
408    {
409       currentHand[pos] = cards[c];
410       if(pos == 5 - 1)
411       {
412          int temp[5];
413          CopyBytesBy4(temp, currentHand, 5);
414          qsort(temp, 5, sizeof(int), Compare);
415          if(POKER_Compare(output, temp) == 1)
416             CopyBytesBy4(output, temp, 5);
417       }
418       else
419       {
420          int oldStart = start;
421          start = c + 1;
422          pos++;
423          POKER_BestHand(cards, n, output);
424          pos--;
425          start = oldStart;
426       }
427    }
428 }
429 */