first commit
[rofl0r-oopoker.git] / pokermath.cpp
blobb6bcbac07dae4310f76fdc1889912425f855eee5
1 /*
2 OOPoker
4 Copyright (c) 2010 Lode Vandevenne
5 All rights reserved.
7 This file is part of OOPoker.
9 OOPoker is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 OOPoker is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with OOPoker. If not, see <http://www.gnu.org/licenses/>.
23 #include "pokermath.h"
25 #include "combination.h"
26 #include "pokereval.h"
27 #include "pokereval2.h"
28 #include "random.h"
31 double factorial(int i)
33 double result = 1.0;
34 for(int j = 1; j <= i; j++)
36 result *= j;
38 return result;
41 double combination(int n, int p)
44 Notation ascii art representation:
45 ( n )
46 ( p )
49 if(p > n / 2)
51 p = n - p; //take advantage of symmetry
54 double result = 1;
55 for(int i = 1; i <= p; i++)
57 result *= (n - p + i) / i;
60 return result;
65 bool isPair(const Card& card1, const Card& card2)
67 return card1.value == card2.value;
70 bool isSuited(const Card& card1, const Card& card2)
72 return card1.suit == card2.suit;
75 bool isConnector(const Card& card1, const Card& card2)
77 int value1 = card1.value;
78 int value2 = card2.value;
79 if(value2 > value1) std::swap(value1, value2);
81 if(value1 == 14 && value2 == 2) return true; //ace-two
82 if(value1 - value2 == 1) return true;
84 return false;
87 int getSklanskyMalmuthGroup(const Card& card1, const Card& card2)
90 From Wikipedia:
92 Texas hold 'em hand groups
93 David Sklansky and Mason Malmuth[2] assigned each hand to a group, and proposed
94 all hands in the group could normally be played similarly. Stronger starting
95 hands are identified by a lower number. Hands without a number are the weakest
96 starting hands. As a general rule, books on Texas hold'em present hand strengths
97 on the assumption of a nine or ten person table. The table below illustrates
98 these groupings with those corresponding to off-suit pairs below the main
99 diagonal and those for pairs of the same suit above.
102 if(!card1.isValid() || !card2.isValid()) return 9;
104 static const int table[169] =
105 // A K Q J T 9 8 7 6 5 4 3 2
107 /*A*/ 1, 1, 2, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5,
108 /*K*/ 2, 1, 2, 3, 7, 7, 7, 7, 7, 7, 7, 7, 7,
109 /*Q*/ 3, 4, 1, 3, 4, 5, 7, 9, 9, 9, 9, 9, 9, //<suited
110 /*J*/ 4, 5, 5, 1, 3, 4, 6, 8, 9, 9, 9, 9, 9,
111 /*T*/ 6, 6, 6, 5, 2, 4, 5, 7, 9, 9, 9, 9, 9,
112 /*9*/ 8, 8, 8, 7, 7, 3, 4, 5, 8, 9, 9, 9, 9,
113 /*8*/ 9, 9, 9, 8, 8, 7, 4, 5, 6, 8, 9, 9, 9,
114 /*7*/ 9, 9, 9, 9, 9, 9, 8, 5, 5, 6, 8, 9, 9,
115 /*6*/ 9, 9, 9, 9, 9, 9, 9, 8, 5, 6, 7, 9, 9,
116 /*5*/ 9, 9, 9, 9, 9, 9, 9, 9, 8, 6, 6, 7, 9,
117 /*4*/ 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 7, 7, 8,
118 /*3*/ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 8,
119 /*2*/ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7
120 }; //^offsuit
122 size_t index1 = 14 - card1.value;
123 size_t index2 = 14 - card2.value;
125 if(card1.suit == card2.suit)
127 //use upper triangle of table, so second index higher than first index
128 if(index1 > index2) return table[13 * index2 + index1];
129 else return table[13 * index1 + index2];
131 else
133 //use lower triangle of table, so second index higher than first index
134 if(index1 > index2) return table[13 * index1 + index2];
135 else return table[13 * index2 + index1];
139 double getRealPlayStatisticsEV(const Card& card1, const Card& card2)
142 Statistics based on real play with their associated actual value in real bets.
144 Source: http://www.pokerroom.com/poker/poker-school/ev-stats/total-stats-by-card/
145 Based on 122,031,244 games
147 The statistics are based on 122,031,244 pair of pocket cards dealt in the real
148 money tables. The unit for EV is average profit in big bets.
150 Copyright (c) PokerRoom.com Established 1999
153 if(!card1.isValid() || !card2.isValid()) return 9;
155 static const double table[169] =
156 // A K Q J T 9 8 7 6 5 4 3 2
158 /*A*/ 2.32, 0.77, 0.59, 0.43, 0.33, 0.18, 0.10, 0.08, 0.03, 0.08, 0.06, 0.02, 0.00,
159 /*K*/ 0.51, 1.67, 0.39, 0.29, 0.20, 0.09, 0.01, 0.00,-0.04,-0.05,-0.05,-0.08,-0.08,
160 /*Q*/ 0.31, 0.16, 1.22, 0.23, 0.17, 0.06,-0.02,-0.06,-0.08,-0.09,-0.10,-0.11,-0.12,
161 /*J*/ 0.19, 0.07, 0.03, 0.86, 0.15, 0.04,-0.03,-0.07,-0.11,-0.11,-0.11,-0.13,-0.14,
162 /*T*/ 0.08, 0.01,-0.02,-0.03, 0.58, 0.05, 0.00,-0.05,-0.11,-0.12,-0.13,-0.13,-0.14,
163 /*9*/-0.03,-0.07,-0.08,-0.08,-0.08, 0.38, 0.00,-0.04,-0.09,-0.12,-0.15,-0.14,-0.14,
164 /*8*/-0.07,-0.11,-0.11,-0.10,-0.09,-0.10, 0.25,-0.02,-0.07,-0.11,-0.13,-0.15,-0.14,
165 /*7*/-0.10,-0.11,-0.12,-0.12,-0.10,-0.10,-0.12, 0.16,-0.03,-0.09,-0.11,-0.14,-0.15,
166 /*6*/-0.12,-0.12,-0.13,-0.12,-0.11,-0.12,-0.11,-0.11, 0.07,-0.07,-0.09,-0.11,-0.14,
167 /*5*/-0.12,-0.13,-0.13,-0.13,-0.12,-0.12,-0.11,-0.11,-0.12, 0.02,-0.08,-0.11,-0.14,
168 /*4*/-0.12,-0.13,-0.13,-0.13,-0.12,-0.12,-0.12,-0.12,-0.12,-0.13,-0.03,-0.13,-0.14,
169 /*3*/-0.13,-0.08,-0.13,-0.13,-0.12,-0.12,-0.12,-0.12,-0.12,-0.12,-0.13,-0.07,-0.16,
170 /*2*/-0.15,-0.14,-0.13,-0.13,-0.12,-0.12,-0.12,-0.12,-0.12,-0.12,-0.12,-0.14,-0.09,
171 }; //^offsuit
173 size_t index1 = 14 - card1.value;
174 size_t index2 = 14 - card2.value;
176 if(card1.suit == card2.suit)
178 //use upper triangle of table, so second index higher than first index
179 if(index1 > index2) return table[13 * index2 + index1];
180 else return table[13 * index1 + index2];
182 else
184 //use lower triangle of table, so second index higher than first index
185 if(index1 > index2) return table[13 * index1 + index2];
186 else return table[13 * index2 + index1];
190 void splitIntoSuits(std::vector<Card>& spades
191 , std::vector<Card>& diamonds
192 , std::vector<Card>& hearts
193 , std::vector<Card>& clubs
194 , const std::vector<Card>& cards)
196 for(size_t i = 0; i < cards.size(); i++)
198 Suit suit = cards[i].getSuit();
199 if(suit == S_SPADES) spades.push_back(cards[i]);
200 else if(suit == S_DIAMONDS) diamonds.push_back(cards[i]);
201 else if(suit == S_HEARTS) hearts.push_back(cards[i]);
202 else if(suit == S_CLUBS) clubs.push_back(cards[i]);
206 void getAmountPerSuit(int& clubs, int& diamonds, int& hearts, int& spades, const std::vector<Card>& cards)
208 for(size_t i = 0; i < cards.size(); i++)
210 if(cards[i].suit == S_CLUBS) clubs++;
211 else if(cards[i].suit == S_DIAMONDS) diamonds++;
212 else if(cards[i].suit == S_HEARTS) hearts++;
213 else if(cards[i].suit == S_SPADES) spades++;
217 void getHighestNearFlush(std::vector<Card>& result, const std::vector<Card>& cards)
219 std::vector<Card> spades;
220 std::vector<Card> diamonds;
221 std::vector<Card> hearts;
222 std::vector<Card> clubs;
224 splitIntoSuits(spades, diamonds, hearts, clubs, cards);
226 if(spades.size() > diamonds.size() && spades.size() > hearts.size() && spades.size() > clubs.size())
228 result = spades;
230 else if(diamonds.size() > hearts.size() && hearts.size() > clubs.size())
232 result = diamonds;
234 else if(hearts.size() > clubs.size())
236 result = hearts;
238 else result = clubs;
241 ////////////////////////////////////////////////////////////////////////////////
242 ////////////////////////////////////////////////////////////////////////////////
243 ////////////////////////////////////////////////////////////////////////////////
244 ////////////////////////////////////////////////////////////////////////////////
245 ////////////////////////////////////////////////////////////////////////////////
246 ////////////////////////////////////////////////////////////////////////////////
247 ////////////////////////////////////////////////////////////////////////////////
248 ////////////////////////////////////////////////////////////////////////////////
249 ////////////////////////////////////////////////////////////////////////////////
250 ////////////////////////////////////////////////////////////////////////////////
253 void getWinChanceAgainst1AtFlop(double& win, double& tie, double& lose
254 , const Card& hand1, const Card& hand2
255 , const Card& table1, const Card& table2, const Card& table3)
257 win = tie = lose = 0.0;
259 //an array of 9 values, set up to contain your hand, the 5 table cards, and then the randomly generated players hand
260 int c[9];
262 c[0] = eval7_index(hand1);
263 c[1] = eval7_index(hand2);
264 c[2] = eval7_index(table1);
265 c[3] = eval7_index(table2);
266 c[4] = eval7_index(table3);
268 static const int NUMOTHER = 47;
270 int others[NUMOTHER];
272 int j = 0;
273 for(int i = 0; i < 52; i++)
275 int v = eval7_index(Card(i));
276 if(v == c[0] || v == c[1]) continue;
277 if(v == c[2] || v == c[3] || v == c[4]) continue;
278 if(j >= NUMOTHER) break;
280 others[j] = v;
281 j++;
284 int wins = 0;
285 int ties = 0;
286 int losses = 0;
288 int count = 0;
290 //all possible 2-hand combinations of the other player + cards on the table
291 for(int i = 0; i < NUMOTHER - 1; i++) //table
292 for(int j = i + 1; j < NUMOTHER; j++) //table
293 for(int k = 0; k < NUMOTHER - 1; k++) //opponent hand
295 if(k == i || k == j) continue;
296 for(int l = k + 1; l < NUMOTHER; l++) //opponent hand
298 if(l == i || l == j) continue;
299 c[5] = others[i];
300 c[6] = others[j];
301 c[7] = others[k];
302 c[8] = others[l];
304 int yourVal = eval7(&c[0]);
305 int otherVal = eval7(&c[2]);
307 if(otherVal == yourVal) ties++;
308 else if(otherVal < yourVal) wins++;
309 else losses++;
311 count++;
315 win = (double)wins / count;
316 tie = (double)ties / count;
317 lose = (double)losses / count;
320 void getWinChanceAgainst1AtTurn(double& win, double& tie, double& lose
321 , const Card& hand1, const Card& hand2
322 , const Card& table1, const Card& table2, const Card& table3, const Card& table4)
324 win = tie = lose = 0.0;
326 //an array of 9 values, set up to contain your hand, the 5 table cards, and then the randomly generated players hand
327 int c[9];
329 c[0] = eval7_index(hand1);
330 c[1] = eval7_index(hand2);
331 c[2] = eval7_index(table1);
332 c[3] = eval7_index(table2);
333 c[4] = eval7_index(table3);
334 c[5] = eval7_index(table4);
336 static const int NUMOTHER = 46;
338 int others[NUMOTHER];
340 int j = 0;
341 for(int i = 0; i < 52; i++)
343 int v = eval7_index(Card(i));
344 if(v == c[0] || v == c[1]) continue;
345 if(v == c[2] || v == c[3] || v == c[4] || v == c[5]) continue;
346 if(j >= NUMOTHER) break;
348 others[j] = v;
349 j++;
354 int wins = 0;
355 int ties = 0;
356 int losses = 0;
358 int count = 0;
360 //all possible 2-hand combinations of the other player + cards on the table
361 for(int i = 0; i < NUMOTHER; i++) //table
362 for(int j = 0; j < NUMOTHER - 1; j++) //opponent hand
364 if(j == i) continue;
365 for(int k = j + 1; k < NUMOTHER; k++) //opponent hand
367 if(k == i) continue;
369 c[6] = others[i];
370 c[7] = others[j];
371 c[8] = others[k];
373 int yourVal = eval7(&c[0]);
374 int otherVal = eval7(&c[2]);
376 if(otherVal == yourVal) ties++;
377 else if(otherVal < yourVal) wins++;
378 else losses++;
380 count++;
384 win = (double)wins / count;
385 tie = (double)ties / count;
386 lose = (double)losses / count;
389 void getWinChanceAgainst1AtRiver(double& win, double& tie, double& lose
390 , const Card& hand1, const Card& hand2
391 , const Card& table1, const Card& table2, const Card& table3, const Card& table4, const Card& table5)
393 win = tie = lose = 0.0;
395 //an array of 9 values, set up to contain your hand, the 5 table cards, and then the randomly generated players hand
396 int c[9];
398 c[0] = eval7_index(hand1);
399 c[1] = eval7_index(hand2);
400 c[2] = eval7_index(table1);
401 c[3] = eval7_index(table2);
402 c[4] = eval7_index(table3);
403 c[5] = eval7_index(table4);
404 c[6] = eval7_index(table5);
406 static const int NUMOTHER = 45;
408 int others[NUMOTHER];
410 int j = 0;
411 for(int i = 0; i < 52; i++)
413 int v = eval7_index(Card(i));
414 if(v == c[0] || v == c[1]) continue;
415 if(v == c[2] || v == c[3] || v == c[4] || v == c[5] || v == c[6]) continue;
416 if(j >= NUMOTHER) break;
418 others[j] = v;
419 j++;
422 int yourVal = eval7(&c[0]);
424 int wins = 0;
425 int ties = 0;
426 int losses = 0;
428 int count = 0;
430 //all possible 2-hand combinations of the other player
431 for(int i = 0; i < NUMOTHER; i++)
432 for(int j = i + 1; j < NUMOTHER; j++)
434 c[7] = others[i];
435 c[8] = others[j];
437 int otherVal = eval7(&c[2]);
439 if(otherVal == yourVal) ties++;
440 else if(otherVal < yourVal) wins++;
441 else losses++;
443 count++;
446 win = (double)wins / count;
447 tie = (double)ties / count;
448 lose = (double)losses / count;
451 ////////////////////////////////////////////////////////////////////////////////
452 ////////////////////////////////////////////////////////////////////////////////
453 ////////////////////////////////////////////////////////////////////////////////
454 ////////////////////////////////////////////////////////////////////////////////
455 ////////////////////////////////////////////////////////////////////////////////
456 ////////////////////////////////////////////////////////////////////////////////
457 ////////////////////////////////////////////////////////////////////////////////
458 ////////////////////////////////////////////////////////////////////////////////
461 This function is there for efficiently choosing "amount" unique random cards
462 out of a list of "size" cards. For that, this function shuffles the first "amount"
463 cards of the list.
464 The intention is that this function is:
465 -Fast (it's for monte carlo simulations of many hands)
466 -Properly Random (no errors that skew the randomness)
467 So the function is made O(amount), instead of shuffling
468 the whole deck all the time which would result in an O(size) function.
469 When the function is done, use the first "amount" cards from "values" to
470 have your really new randomly shuffled cards.
472 static void shuffleN(int* values, int size, int amount)
474 for(int i = 0; i < amount; i++)
476 int r = getRandomFast(0, size - 1);
477 std::swap(values[i], values[r]);
481 void getWinChanceAgainstNAtPreFlop(double& win, double& tie, double& lose
482 , const Card& hand1, const Card& hand2
483 , int numOpponents, int numSamples)
485 win = tie = lose = 0.0;
487 //an array of 9 values, set up to contain your hand, the 5 table cards, and then the randomly generated players hand
488 int c[9];
490 c[0] = eval7_index(hand1);
491 c[1] = eval7_index(hand2);
493 static const int NUMOTHER = 50;
495 int others[NUMOTHER];
497 int j = 0;
498 for(int i = 0; i < 52; i++)
500 int v = eval7_index(Card(i));
501 if(v == c[0] || v == c[1]) continue;
502 if(j >= NUMOTHER) break;
504 others[j] = v;
505 j++;
508 int wins = 0;
509 int ties = 0;
510 int losses = 0;
512 for(int i = 0; i < numSamples; i++)
514 shuffleN(others, NUMOTHER, 2 + numOpponents * 2); //the two extra table cards, and the cards of all opponents
516 c[2] = others[0];
517 c[3] = others[1];
518 c[4] = others[2];
519 c[5] = others[3];
520 c[6] = others[4];
522 int yourVal = eval7(&c[0]);
524 int status = 2; //2: you win, 1: you tie, 0: you lose
526 for(int j = 0; j < numOpponents; j++)
528 //opponents hand
529 c[7] = others[5 + j * 2];
530 c[8] = others[6 + j * 2];
532 int opponentVal = eval7(&c[2]);
534 if(opponentVal == yourVal) status = 1; //tie
535 else if(opponentVal > yourVal) { status = 0; break; } //lose, stop rest of loop.
538 if(status == 0) losses++;
539 else if(status == 1) ties++;
540 else wins++;
543 win = (double)wins / numSamples;
544 tie = (double)ties / numSamples;
545 lose = (double)losses / numSamples;
548 void getWinChanceAgainstNAtFlop(double& win, double& tie, double& lose
549 , const Card& hand1, const Card& hand2
550 , const Card& table1, const Card& table2, const Card& table3
551 , int numOpponents, int numSamples)
553 win = tie = lose = 0.0;
555 //an array of 9 values, set up to contain your hand, the 5 table cards, and then the randomly generated players hand
556 int c[9];
558 c[0] = eval7_index(hand1);
559 c[1] = eval7_index(hand2);
560 c[2] = eval7_index(table1);
561 c[3] = eval7_index(table2);
562 c[4] = eval7_index(table3);
564 static const int NUMOTHER = 47;
566 int others[NUMOTHER];
568 int j = 0;
569 for(int i = 0; i < 52; i++)
571 int v = eval7_index(Card(i));
572 if(v == c[0] || v == c[1]) continue;
573 if(v == c[2] || v == c[3] || v == c[4]) continue;
574 if(j >= NUMOTHER) break;
576 others[j] = v;
577 j++;
580 int wins = 0;
581 int ties = 0;
582 int losses = 0;
584 for(int i = 0; i < numSamples; i++)
586 shuffleN(others, NUMOTHER, 2 + numOpponents * 2); //the two extra table cards, and the cards of all opponents
588 c[5] = others[0];
589 c[6] = others[1];
591 int yourVal = eval7(&c[0]);
593 int status = 2; //2: you win, 1: you tie, 0: you lose
595 for(int j = 0; j < numOpponents; j++)
597 //opponents hand
598 c[7] = others[2 + j * 2];
599 c[8] = others[3 + j * 2];
601 int opponentVal = eval7(&c[2]);
603 if(opponentVal == yourVal) status = 1; //tie
604 else if(opponentVal > yourVal) { status = 0; break; } //lose, stop rest of loop.
607 if(status == 0) losses++;
608 else if(status == 1) ties++;
609 else wins++;
612 win = (double)wins / numSamples;
613 tie = (double)ties / numSamples;
614 lose = (double)losses / numSamples;
617 void getWinChanceAgainstNAtTurn(double& win, double& tie, double& lose
618 , const Card& hand1, const Card& hand2
619 , const Card& table1, const Card& table2, const Card& table3, const Card& table4
620 , int numOpponents, int numSamples)
622 win = tie = lose = 0.0;
624 //an array of 9 values, set up to contain your hand, the 5 table cards, and then the randomly generated players hand
625 int c[9];
627 c[0] = eval7_index(hand1);
628 c[1] = eval7_index(hand2);
629 c[2] = eval7_index(table1);
630 c[3] = eval7_index(table2);
631 c[4] = eval7_index(table3);
632 c[5] = eval7_index(table4);
634 static const int NUMOTHER = 46;
636 int others[NUMOTHER];
638 int j = 0;
639 for(int i = 0; i < 52; i++)
641 int v = eval7_index(Card(i));
642 if(v == c[0] || v == c[1]) continue;
643 if(v == c[2] || v == c[3] || v == c[4] || v == c[5]) continue;
644 if(j >= NUMOTHER) break;
646 others[j] = v;
647 j++;
650 int wins = 0;
651 int ties = 0;
652 int losses = 0;
654 for(int i = 0; i < numSamples; i++)
656 shuffleN(others, NUMOTHER, 1 + numOpponents * 2); //the one extra table card, and the cards of all opponents
658 c[6] = others[0];
660 int yourVal = eval7(&c[0]);
662 int status = 2; //2: you win, 1: you tie, 0: you lose
664 for(int j = 0; j < numOpponents; j++)
666 //opponents hand
667 c[7] = others[1 + j * 2];
668 c[8] = others[2 + j * 2];
670 int opponentVal = eval7(&c[2]);
672 if(opponentVal == yourVal) status = 1; //tie
673 else if(opponentVal > yourVal) { status = 0; break; } //lose, stop rest of loop.
676 if(status == 0) losses++;
677 else if(status == 1) ties++;
678 else wins++;
681 win = (double)wins / numSamples;
682 tie = (double)ties / numSamples;
683 lose = (double)losses / numSamples;
686 void getWinChanceAgainstNAtRiver(double& win, double& tie, double& lose
687 , const Card& hand1, const Card& hand2
688 , const Card& table1, const Card& table2, const Card& table3, const Card& table4, const Card& table5
689 , int numOpponents, int numSamples)
691 win = tie = lose = 0.0;
693 //an array of 9 values, set up to contain your hand, the 5 table cards, and then the randomly generated players hand
694 int c[9];
696 c[0] = eval7_index(hand1);
697 c[1] = eval7_index(hand2);
698 c[2] = eval7_index(table1);
699 c[3] = eval7_index(table2);
700 c[4] = eval7_index(table3);
701 c[5] = eval7_index(table4);
702 c[6] = eval7_index(table5);
704 static const int NUMOTHER = 45;
706 int others[NUMOTHER];
708 int j = 0;
709 for(int i = 0; i < 52; i++)
711 int v = eval7_index(Card(i));
712 if(v == c[0] || v == c[1]) continue;
713 if(v == c[2] || v == c[3] || v == c[4] || v == c[5] || v == c[6]) continue;
714 if(j >= NUMOTHER) break;
716 others[j] = v;
717 j++;
720 int wins = 0;
721 int ties = 0;
722 int losses = 0;
724 for(int i = 0; i < numSamples; i++)
726 shuffleN(others, NUMOTHER, numOpponents * 2); //the cards of all opponents
728 int yourVal = eval7(&c[0]);
730 int status = 2; //2: you win, 1: you tie, 0: you lose
732 for(int j = 0; j < numOpponents; j++)
734 //opponents hand
735 c[7] = others[0 + j * 2];
736 c[8] = others[1 + j * 2];
738 int opponentVal = eval7(&c[2]);
740 if(opponentVal == yourVal) status = 1; //tie
741 else if(opponentVal > yourVal) { status = 0; break; } //lose, stop rest of loop.
744 if(status == 0) losses++;
745 else if(status == 1) ties++;
746 else wins++;
749 win = (double)wins / numSamples;
750 tie = (double)ties / numSamples;
751 lose = (double)losses / numSamples;
754 ////////////////////////////////////////////////////////////////////////////////
755 ////////////////////////////////////////////////////////////////////////////////
756 ////////////////////////////////////////////////////////////////////////////////
757 ////////////////////////////////////////////////////////////////////////////////
758 ////////////////////////////////////////////////////////////////////////////////
759 ////////////////////////////////////////////////////////////////////////////////
760 ////////////////////////////////////////////////////////////////////////////////
761 ////////////////////////////////////////////////////////////////////////////////
764 #if 0
766 //slow
768 int eval7(const int* cards)
770 static bool inited = false;
771 if(!inited) { PokerEval::InitTheEvaluator(); inited = true; }
772 return PokerEval::GetHandValue(cards);
775 int eval7_index(const Card& card)
778 PokerEval expects per-rank ordering, not per-suit.
780 2c = 1 2d = 2 2h = 3 2s = 4 3c = 5 3d = 6 3h = 7 3s = 8 4c = 9 4d = 10 4h = 11 4s = 12 5c = 13 5d = 14 5h = 15 5s = 16 6c = 17 6d = 18 6h = 19 6s = 20 7c = 21 7d = 22 7h = 23 7s = 24 8c = 25 8d = 26 8h = 27 8s = 28 9c = 29 9d = 30 9h = 31 9s = 32 Tc = 33 Td = 34 Th = 35 Ts = 36 Jc = 37 Jd = 38 Jh = 39 Js = 40 Qc = 41 Qd = 42 Qh = 43 Qs = 44 Kc = 45 Kd = 46 Kh = 47 Ks = 48 Ac = 49 Ad = 50 Ah = 51 As = 52
782 int v = (card.value - 2) * 4;
783 int s = (int)card.suit + 1;
784 return s + v;
787 ComboType eval7_category(int result)
789 int handCategory = result >> 12;
790 //int rankWithinCategory = result & 0x00000FFF;
792 return (ComboType)(handCategory - 1); //handCategory is 1 for high card, 2 for pair, etc...
795 #elif 0
797 //slowest
799 int eval7(const int* cards)
801 return 7462 - PokerEval::eval_7hand(cards); //subtracted from highest possible value, because higher is better in my case.
804 int eval7_index(const Card& card)
806 static bool inited = false;
807 static int deck[52];
808 if(!inited)
810 PokerEval::init_deck(deck);
811 inited = true;
814 int value = card.value + 13 * (int)card.suit - 2;
816 return deck[value];
819 ComboType eval7_category(int result)
821 return eval5_category(result);
824 #else
826 //fast
828 int eval7(const int* cards)
830 static bool inited = false;
831 if(!inited) { PokerEval2::InitializeHandRankingTables(); inited = true; }
833 return (int)PokerEval2::RankHand( PokerEval2::HandMasksTable[cards[0]] | PokerEval2::HandMasksTable[cards[1]] |
834 PokerEval2::HandMasksTable[cards[2]] | PokerEval2::HandMasksTable[cards[3]] |
835 PokerEval2::HandMasksTable[cards[4]] | PokerEval2::HandMasksTable[cards[5]] |
836 PokerEval2::HandMasksTable[cards[6]] );
839 int eval7_index(const Card& card)
841 //return card.getIndex();
843 int v = (card.value - 2);
844 int s = (int)card.suit * 13;
845 return s + v;
848 ComboType eval7_category(int result)
850 return (ComboType)(result >> 20);
853 #endif
856 ////////////////////////////////////////////////////////////////////////////////
858 int eval5(const int* cards)
860 return 7462 - PokerEval::eval_5hand(cards); //subtracted from highest possible value, because higher is better in my case.
863 int eval5_index(const Card& card)
865 static bool inited = false;
866 static int deck[52];
867 if(!inited)
869 PokerEval::init_deck(deck);
870 inited = true;
873 int value = card.value + 13 * (int)card.suit - 2;
875 return deck[value];
878 ComboType eval5_category(int result)
880 if (result < 1277) return C_HIGH_CARD;
881 else if (result < 4137) return C_PAIR;
882 else if (result < 4995) return C_TWO_PAIR;
883 else if (result < 5853) return C_THREE_OF_A_KIND;
884 else if (result < 5863) return C_STRAIGHT;
885 else if (result < 7140) return C_FLUSH;
886 else if (result < 7296) return C_FULL_HOUSE;
887 else if (result < 7452) return C_FOUR_OF_A_KIND;
888 else return C_STRAIGHT_FLUSH;
891 ////////////////////////////////////////////////////////////////////////////////
893 int eval6_slow(const int* cards)
895 int cards_perm[10] = {cards[0], cards[1], cards[2], cards[3], cards[4], cards[5], cards[0], cards[1], cards[2], cards[3]};
896 int result = -1;
897 int val;
899 val = eval5(&cards_perm[0]);
900 if(val > result) result = val;
901 val = eval5(&cards_perm[1]);
902 if(val > result) result = val;
903 val = eval5(&cards_perm[2]);
904 if(val > result) result = val;
905 val = eval5(&cards_perm[3]);
906 if(val > result) result = val;
907 val = eval5(&cards_perm[4]);
908 if(val > result) result = val;
909 val = eval5(&cards_perm[5]);
910 if(val > result) result = val;
912 return result;
915 int eval6_slow_index(const Card& card)
917 return eval5_index(card);
920 ComboType eval6_category(int result)
922 return eval5_category(result);
925 ////////////////////////////////////////////////////////////////////////////////
927 int eval4_2_5_3_slow(const int* cards)
929 //This is for Omaha Hold'm
931 //6 possible permutations of 2 out of 4 hand cards
932 static const int perm4_1[6] = { 0, 1, 2, 3, 0, 1 };
933 static const int perm4_2[6] = { 1, 2, 3, 0, 2, 3 };
934 //10 possible permutations of 3 out of 5 community cards
935 static const int perm5_1[10] = { 4+2,4+0,4+0,4+0,4+1, 4+0,4+1,4+0,4+1,4+0 };
936 static const int perm5_2[10] = { 4+3,4+3,4+1,4+1,4+2, 4+1,4+2,4+2,4+3,4+2 };
937 static const int perm5_3[10] = { 4+4,4+4,4+4,4+2,4+3, 4+3,4+4,4+3,4+4,4+4 };
939 int cards5[5];
941 int result = -1;
943 for(size_t j = 0; j < 10; j++)
945 cards5[0] = cards[perm5_1[j]];
946 cards5[1] = cards[perm5_2[j]];
947 cards5[2] = cards[perm5_3[j]];
948 for(size_t i = 0; i < 6; i++)
950 cards5[3] = cards[perm4_1[i]];
951 cards5[4] = cards[perm4_2[i]];
953 int val = eval5(cards5);
954 if(val > result) result = val;
958 return result;
961 int eval4_2_5_3_slow_index(const Card& card)
963 return eval5_index(card);
966 ComboType eval4_2_5_3_slow_category(int result)
968 return eval5_category(result);
971 ////////////////////////////////////////////////////////////////////////////////
972 ////////////////////////////////////////////////////////////////////////////////
973 ////////////////////////////////////////////////////////////////////////////////
974 ////////////////////////////////////////////////////////////////////////////////
975 ////////////////////////////////////////////////////////////////////////////////
976 ////////////////////////////////////////////////////////////////////////////////
977 ////////////////////////////////////////////////////////////////////////////////
978 ////////////////////////////////////////////////////////////////////////////////
980 double getPotEquity(const std::vector<Card>& holeCards, const std::vector<Card>& boardCards, int numOpponents, int numSamples)
982 double win = 0, tie = 0, lose = 0;
984 if(boardCards.empty()) //pre-flop
986 getWinChanceAgainstNAtPreFlop(win, tie, lose, holeCards[0], holeCards[1], numOpponents, numSamples);
988 else if(boardCards.size() == 3) //flop
990 getWinChanceAgainstNAtFlop(win, tie, lose, holeCards[0], holeCards[1], boardCards[0], boardCards[1], boardCards[2], numOpponents, numSamples);
992 else if(boardCards.size() == 4) //turn
994 if(numOpponents == 1) getWinChanceAgainst1AtTurn(win, tie, lose, holeCards[0], holeCards[1], boardCards[0], boardCards[1], boardCards[2], boardCards[3]);
995 else getWinChanceAgainstNAtTurn(win, tie, lose, holeCards[0], holeCards[1], boardCards[0], boardCards[1], boardCards[2], boardCards[3], numOpponents, numSamples);
997 else if(boardCards.size() == 5) //river
999 if(numOpponents == 1) getWinChanceAgainst1AtRiver(win, tie, lose, holeCards[0], holeCards[1], boardCards[0], boardCards[1], boardCards[2], boardCards[3], boardCards[4]);
1000 else getWinChanceAgainstNAtRiver(win, tie, lose, holeCards[0], holeCards[1], boardCards[0], boardCards[1], boardCards[2], boardCards[3], boardCards[4], numOpponents, numSamples);
1003 double result = win;
1004 result += tie / numOpponents; //split pots
1005 return result;
1008 ////////////////////////////////////////////////////////////////////////////////
1009 ////////////////////////////////////////////////////////////////////////////////
1010 ////////////////////////////////////////////////////////////////////////////////
1011 ////////////////////////////////////////////////////////////////////////////////
1012 ////////////////////////////////////////////////////////////////////////////////
1013 ////////////////////////////////////////////////////////////////////////////////
1014 ////////////////////////////////////////////////////////////////////////////////
1015 ////////////////////////////////////////////////////////////////////////////////
1018 Parameters:
1019 wins, ties, losses: output, counter of number of wins, ties and losses of each player so far
1020 val: input, current hand combination rank of each player (better = winner)
1021 numPlayers: input, amount of players
1023 static void addWinTieLose(int* wins, int* ties, int* losses, const int* val, int numPlayers)
1025 //find winner or ties without sorting
1026 int highest = -1;
1027 bool tie = false;
1029 for(int j = 0; j < numPlayers; j++)
1031 if(val[j] > highest)
1033 tie = false;
1034 highest = val[j];
1036 else if(val[j] == highest)
1038 tie = true;
1042 for(int j = 0; j < numPlayers; j++)
1044 if(val[j] == highest)
1046 if(tie) ties[j]++;
1047 else wins[j]++;
1049 else losses[j]++;
1054 Parameters:
1055 wins, ties, losses: output, counter of number of wins, ties and losses of each player so far
1056 v: data structure with places for cards. in positions 0,1 you fill in hole cards of opponents. Positions 2-7 have the table cards. Positions after that are used for monte carlo search, but not for exhaustive search.
1057 val: array of numPlayers ints, used as working memory (to avoid recreating it all the time)
1058 numPlayers: input, amount of players
1060 void testPlayers(int* wins, int* ties, int* losses
1061 , int* v, int* val
1062 , const int* holeCards1, const int* holeCards2
1063 , int numPlayers)
1065 for(int j = 0; j < numPlayers; j++)
1067 //hand
1068 v[0] = holeCards1[j];
1069 v[1] = holeCards2[j];
1071 val[j] = eval7(&v[0]);
1074 addWinTieLose(&wins[0], &ties[0], &losses[0], &val[0], numPlayers);
1078 bool getWinChanceWithKnownHands(std::vector<double>& win, std::vector<double>& tie, std::vector<double>& lose
1079 , const std::vector<Card>& holeCards1
1080 , const std::vector<Card>& holeCards2
1081 , const std::vector<Card>& boardCards
1082 , int numSamples)
1084 int numPlayers = holeCards1.size();
1085 int numBoard = (int)boardCards.size();
1086 if(numPlayers != (int)holeCards2.size()) return false;
1087 if(numPlayers > 23) return false;
1088 if(numBoard > 5) return false;
1090 win.resize(numPlayers);
1091 tie.resize(numPlayers);
1092 lose.resize(numPlayers);
1094 std::vector<int> wins(numPlayers);
1095 std::vector<int> ties(numPlayers);
1096 std::vector<int> losses(numPlayers);
1098 std::vector<int> holeCardsInt1;
1099 std::vector<int> holeCardsInt2;
1100 std::vector<int> boardCardsInt;
1102 std::vector<int> known_index;
1103 for(int i = 0; i < numPlayers; i++)
1105 known_index.push_back(holeCards1[i].getIndex());
1106 known_index.push_back(holeCards2[i].getIndex());
1107 holeCardsInt1.push_back(eval7_index(holeCards1[i].getIndex()));
1108 holeCardsInt2.push_back(eval7_index(holeCards2[i].getIndex()));
1110 wins[i] = 0;
1111 ties[i] = 0;
1112 losses[i] = 0;
1114 for(int i = 0; i < numBoard; i++)
1116 known_index.push_back(boardCards[i].getIndex());
1117 boardCardsInt.push_back(eval7_index(boardCards[i].getIndex()));
1120 bool flags[52];
1122 for(int i = 0; i < 52; i++)
1124 flags[i] = true;
1127 for(size_t i = 0; i < known_index.size(); i++)
1129 if(known_index[i] < 0 || known_index[i] >= 52) return false;
1130 flags[known_index[i]] = false;
1134 int numOther = 52 - numPlayers * 2 - numBoard;
1136 int numUnknown = 5 - numBoard;
1138 double exhaustiveSamples = combination(numOther, numUnknown) + 0.5; //avoid rounding errors
1140 int val[numPlayers];
1142 int count = 0;
1144 if(exhaustiveSamples > (double)numSamples) //use monte carlo
1146 count = numSamples;
1148 //this is a memory structure made to easily have 7 cards in a row that can be evaluated, and can be shuffled at the locations where needed. It contains: 2 hand cards, 0-5 known board cards, and the unknown cards with the unknown board cards first (can be shuffled)
1149 std::vector<int> v(2 + numBoard + numOther);
1150 for(int i = 0; i < numBoard; i++) v[2 + i] = boardCardsInt[i];
1152 int* other = &v[2 + numBoard]; //cards other than the known ones
1155 for(int i = 0, j = 0; i < 52; i++)
1157 if(flags[i])
1159 other[j] = eval7_index(Card(i));
1160 j++;
1164 for(int i = 0; i < numSamples; i++)
1166 shuffleN(&other[0], numOther, numUnknown); //the cards of all opponents
1167 testPlayers(&wins[0], &ties[0], &losses[0], &v[0], &val[0], &holeCardsInt1[0], &holeCardsInt2[0], numPlayers);
1170 else //do it exhaustively
1173 //this is a memory structure made to easily have 7 cards in a row that can be evaluated, and can be shuffled at the locations where needed. It contains: 2 hand cards, 0-5 known board cards, and the unknown cards with the unknown board cards first (can be shuffled)
1174 std::vector<int> others;
1175 for(int i = 0; i < 52; i++) others.push_back(eval7_index(Card(i)));
1177 int c[7];
1179 if(numBoard == 0)
1181 for (int card1 = 0; card1 < numOther - 4; card1++)
1183 c[2] = others[card1];
1184 for (int card2 = card1 + 1; card2 < numOther - 3; card2++)
1186 c[3] = others[card2];
1187 for (int card3 = card2 + 1; card3 < numOther - 2; card3++)
1189 c[4] = others[card3];
1190 for (int card4 = card3 + 1; card4 < numOther - 1; card4++)
1192 c[5] = others[card4];
1193 for (int card5 = card4 + 1; card5 < numOther - 0; card5++)
1195 c[6] = others[card5];
1196 testPlayers(&wins[0], &ties[0], &losses[0], c, val, &holeCardsInt1[0], &holeCardsInt2[0], numPlayers);
1197 count++;
1204 else if(numBoard == 1)
1206 c[2] = boardCardsInt[0];
1208 for (int card1 = 0; card1 < numOther - 3; card1++)
1210 c[3] = others[card1];
1211 for (int card2 = card1 + 1; card2 < numOther - 2; card2++)
1213 c[4] = others[card2];
1214 for (int card3 = card2 + 1; card3 < numOther - 1; card3++)
1216 c[5] = others[card3];
1217 for (int card4 = card3 + 1; card4 < numOther - 0; card4++)
1219 c[6] = others[card4];
1220 testPlayers(&wins[0], &ties[0], &losses[0], c, val, &holeCardsInt1[0], &holeCardsInt2[0], numPlayers);
1221 count++;
1227 else if(numBoard == 2)
1229 c[2] = boardCardsInt[0];
1230 c[3] = boardCardsInt[1];
1232 for (int card1 = 0; card1 < numOther - 2; card1++)
1234 c[4] = others[card1];
1235 for (int card2 = card1 + 1; card2 < numOther - 1; card2++)
1237 c[5] = others[card2];
1238 for (int card3 = card2 + 1; card3 < numOther - 0; card3++)
1240 c[6] = others[card3];
1241 testPlayers(&wins[0], &ties[0], &losses[0], c, val, &holeCardsInt1[0], &holeCardsInt2[0], numPlayers);
1242 count++;
1247 else if(numBoard == 3)
1249 c[2] = boardCardsInt[0];
1250 c[3] = boardCardsInt[1];
1251 c[4] = boardCardsInt[2];
1253 for (int card1 = 0; card1 < numOther - 1; card1++)
1255 c[5] = others[card1];
1256 for (int card2 = card1 + 1; card2 < numOther - 0; card2++)
1258 c[6] = others[card2];
1259 testPlayers(&wins[0], &ties[0], &losses[0], c, val, &holeCardsInt1[0], &holeCardsInt2[0], numPlayers);
1260 count++;
1264 else if(numBoard == 4)
1266 c[2] = boardCardsInt[0];
1267 c[3] = boardCardsInt[1];
1268 c[4] = boardCardsInt[2];
1269 c[5] = boardCardsInt[3];
1271 for (int card1 = 0; card1 < numOther - 0; card1++)
1273 c[6] = others[card1];
1274 testPlayers(&wins[0], &ties[0], &losses[0], c, val, &holeCardsInt1[0], &holeCardsInt2[0], numPlayers);
1275 count++;
1278 else if(numBoard == 5)
1280 c[2] = boardCardsInt[0];
1281 c[3] = boardCardsInt[1];
1282 c[4] = boardCardsInt[2];
1283 c[5] = boardCardsInt[3];
1284 c[6] = boardCardsInt[4];
1286 testPlayers(&wins[0], &ties[0], &losses[0], c, val, &holeCardsInt1[0], &holeCardsInt2[0], numPlayers);
1287 count++;
1292 for(int i = 0; i < numPlayers; i++)
1294 win[i] = (double)wins[i] / count;
1295 tie[i] = (double)ties[i] / count;
1296 lose[i] = (double)losses[i] / count;
1299 return true;