fix infinite check bug
[rofl0r-oopoker.git] / combination.cpp
blob729000618a2ade953506f22a000be9e942dceb94
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 "combination.h"
25 #include "pokermath.h"
27 std::string comboTypeToName(ComboType type)
29 switch(type)
31 case C_HIGH_CARD: return "High Card";
32 case C_PAIR: return "Pair";
33 case C_TWO_PAIR: return "Two Pair";
34 case C_THREE_OF_A_KIND: return "Three Of A Kind";
35 case C_STRAIGHT: return "Straight";
36 case C_FLUSH: return "Flush";
37 case C_FULL_HOUSE: return "Full House";
38 case C_FOUR_OF_A_KIND: return "Four Of A Kind";
39 case C_STRAIGHT_FLUSH: return "Straight Flush";
40 //case ROYAL_FLUSH: return "Royal Flush";
43 return "Unknown";
46 std::string Combination::getName() const
48 if(cards_used == 0) return "Nothing";
49 std::string result = comboTypeToName(type);
50 if(type == C_STRAIGHT_FLUSH && cards[0].value == 14) result = "Royal Flush";
51 return result;
54 std::string Combination::getNameWithAllCards() const
56 std::string result = getName();
57 result += " (";
58 for(int i = 0; i < cards_used; i++) result = result + " " + cards[i].getShortName();
59 result += " )";
60 return result;
63 std::string Combination::getNameWithAllCardsPrintable() const
65 std::string result = getName();
66 result += " (";
67 for(int i = 0; i < cards_used; i++) result = result + " " + cards[i].getShortNamePrintable();
68 result += " )";
69 return result;
72 ////////////////////////////////////////////////////////////////////////////////
73 ////////////////////////////////////////////////////////////////////////////////
74 ////////////////////////////////////////////////////////////////////////////////
75 ////////////////////////////////////////////////////////////////////////////////
76 ////////////////////////////////////////////////////////////////////////////////
77 ////////////////////////////////////////////////////////////////////////////////
78 ////////////////////////////////////////////////////////////////////////////////
79 ////////////////////////////////////////////////////////////////////////////////
82 //returns amount of pairs in cards, sorted from highest to lowest
83 void getPairs(std::vector<int>& values, const std::vector<Card>& sorted)
85 std::vector<int> vals(sorted.size());
86 for(size_t i = 0; i < sorted.size(); i++) vals[i] = sorted[i].getValue();
88 for(size_t i = 0; i < vals.size(); i++)
90 size_t j = i + 1;
91 while(j < vals.size() && vals[j] == vals[i]) j++;
93 if(j == i + 2) values.push_back(vals[i]);
95 i = j - 1;
99 void getThreeOfKinds(std::vector<int>& values, const std::vector<Card>& cards)
101 std::vector<int> vals(cards.size());
102 for(size_t i = 0; i < cards.size(); i++) vals[i] = cards[i].getValue();
103 std::sort(vals.begin(), vals.end(), std::greater<int>());
105 for(size_t i = 0; i < vals.size(); i++)
107 size_t j = i + 1;
108 while(j < vals.size() && vals[j] == vals[i]) j++;
110 if(j == i + 3) values.push_back(vals[i]);
112 i = j - 1;
116 void getFourOfKinds(std::vector<int>& values, const std::vector<Card>& cards)
118 std::vector<int> vals(cards.size());
119 for(size_t i = 0; i < cards.size(); i++) vals[i] = cards[i].getValue();
120 std::sort(vals.begin(), vals.end(), std::greater<int>());
122 for(size_t i = 0; i < vals.size(); i++)
124 size_t j = i + 1;
125 while(j < vals.size() && vals[j] == vals[i]) j++;
127 if(j == i + 4) values.push_back(vals[i]);
129 i = j - 1;
133 //returns 0 if no straight, value of highest straight found if one is found. A value of "14" is ace is the highest, and the lowest possible is "5" (which represents 1-2-3-4-5)
134 //this returns a straight if it's a straight flush also. Test straight flush seperately!
135 int getStraight(const std::vector<Card>& cards)
137 if(cards.size() < 5) return 0;
139 std::vector<int> vals(cards.size());
140 for(size_t i = 0; i < cards.size(); i++) vals[i] = cards[i].getValue();
141 std::sort(vals.begin(), vals.end(), std::greater<int>());
142 if(vals[0] == 14) vals.push_back(1); //this is so that a 1-to-5 straight is also detected
144 int num = 0;
145 int last = -1;
147 for(size_t i = 0; i < vals.size(); i++)
149 if(last == -1) { last = vals[i]; num = 1; continue; }
151 if(vals[i] == last - 1)
153 num++;
155 else if(vals[i] < last - 1)
157 num = 1;
159 else //if vals[i] == last
161 //nothing to do
163 if(num == 5) return vals[i] + 4;
165 last = vals[i];
168 return 0;
172 //returns highest card of the straight flush.
173 //Also used for royal flush. If it returns an ace, it's a royal flush.
174 Card getStraightFlush(const std::vector<Card>& cards)
176 //split in the 4 suits
177 std::vector<Card> spades;
178 std::vector<Card> diamonds;
179 std::vector<Card> hearts;
180 std::vector<Card> clubs;
182 splitIntoSuits(spades, diamonds, hearts, clubs, cards);
184 int straightSpades = getStraight(spades);
185 int straightDiamonds = getStraight(diamonds);
186 int straightHearts = getStraight(hearts);
187 int straightClubs = getStraight(clubs);
189 if(straightSpades > straightDiamonds && straightSpades > straightHearts && straightSpades > straightClubs)
191 return Card(straightSpades, S_SPADES);
193 if(straightDiamonds > straightHearts && straightDiamonds > straightClubs)
195 return Card(straightDiamonds, S_DIAMONDS);
197 if(straightHearts > straightClubs)
199 return Card(straightHearts, S_HEARTS);
201 if(straightClubs > 0)
203 return Card(straightClubs, S_CLUBS);
205 return Card(-1, S_UNKNOWN);
208 //returns highest card of the flush.
209 Card getFlush(const std::vector<Card>& cards)
211 //split in the 4 suits
212 std::vector<Card> spades;
213 std::vector<Card> diamonds;
214 std::vector<Card> hearts;
215 std::vector<Card> clubs;
217 splitIntoSuits(spades, diamonds, hearts, clubs, cards);
219 int s = spades.size() < 5 ? 0 : spades[0].value;
220 int d = diamonds.size() < 5 ? 0 : diamonds[0].value;
221 int h = hearts.size() < 5 ? 0 : hearts[0].value;
222 int c = clubs.size() < 5 ? 0 : clubs[0].value;
224 if(s > d && s > h && s > c)
226 return Card(s, S_SPADES);
228 if(d > h && d > c)
230 return Card(d, S_DIAMONDS);
232 if(h > c)
234 return Card(h, S_HEARTS);
236 if(c > 0)
238 return Card(c, S_CLUBS);
240 return Card(-1, S_UNKNOWN);
243 ////////////////////////////////////////////////////////////////////////////////
244 ////////////////////////////////////////////////////////////////////////////////
245 ////////////////////////////////////////////////////////////////////////////////
246 ////////////////////////////////////////////////////////////////////////////////
247 ////////////////////////////////////////////////////////////////////////////////
248 ////////////////////////////////////////////////////////////////////////////////
249 ////////////////////////////////////////////////////////////////////////////////
250 ////////////////////////////////////////////////////////////////////////////////
252 //only call after having checked all combinations
253 bool checkHighCard(Card result[5], const std::vector<Card>& sorted)
255 if(sorted.size() < 1) return false;
257 for(size_t i = 0; i < sorted.size() && i < 5; i++)
259 result[i] = sorted[i];
262 return true;
266 //only call after already having checked for better combinations (including two pairs, three of a kind, or other things that already contain a pair in them too)
267 bool checkPair(Card result[5], const std::vector<Card>& sorted)
269 if(sorted.size() < 2) return false;
271 std::vector<int> values;
272 getPairs(values, sorted);
274 if(values.empty()) return false;
276 //values.size is 1 because higher combinations were already checked earlier
277 for(size_t i = 0; i + 1 < sorted.size(); i++)
279 if(sorted[i].value == values[0])
281 result[0] = sorted[i];
282 result[1] = sorted[i + 1];
283 break;
287 int c = 2;
288 for(size_t i = 0; i < sorted.size() && c < 5; i++)
290 if(sorted[i].value != values[0])
292 result[c] = sorted[i];
293 c++;
297 return true;
300 //only call after already having checked for better combinations
301 bool checkTwoPair(Card result[5], const std::vector<Card>& sorted)
303 if(sorted.size() < 4) return false;
305 std::vector<int> values;
306 getPairs(values, sorted);
308 if(values.size() < 2) return false;
310 for(size_t i = 0; i + 1 < sorted.size(); i++)
312 if(sorted[i].value == values[0])
314 result[0] = sorted[i];
315 result[1] = sorted[i + 1];
316 break;
320 for(size_t i = 0; i + 1 < sorted.size(); i++)
322 if(sorted[i].value == values[1])
324 result[2] = sorted[i];
325 result[3] = sorted[i + 1];
326 break;
330 int c = 4;
331 for(size_t i = 0; i < sorted.size() && c < 5; i++)
333 if(sorted[i].value != values[0] && sorted[i].value != values[1])
335 result[c] = sorted[i];
336 c++;
340 return true;
343 //only call after already having checked for better combinations (including full house, four of a kind, or other things that already contain a pair in them too)
344 bool checkThreeOfAKind(Card result[5], const std::vector<Card>& sorted)
346 if(sorted.size() < 3) return false;
348 std::vector<int> values;
349 getThreeOfKinds(values, sorted);
351 if(values.empty()) return false;
353 //values.size is 1 because higher combinations were already checked earlier
354 for(size_t i = 0; i + 2 < sorted.size(); i++)
356 if(sorted[i].value == values[0])
358 result[0] = sorted[i];
359 result[1] = sorted[i + 1];
360 result[2] = sorted[i + 2];
361 break;
365 int c = 3;
366 for(size_t i = 0; i < sorted.size() && c < 5; i++)
368 if(sorted[i].value != values[0])
370 result[c] = sorted[i];
371 c++;
375 return true;
378 //only call after already having checked for better combinations
379 bool checkFullHouse(Card result[5], const std::vector<Card>& sorted)
381 if(sorted.size() < 5) return false;
383 std::vector<int> two;
384 getPairs(two, sorted);
385 std::vector<int> three;
386 getThreeOfKinds(three, sorted);
388 if(two.empty() || three.empty()) return false;
390 for(size_t i = 0; i + 2 < sorted.size(); i++)
392 if(sorted[i].value == three[0])
394 result[0] = sorted[i];
395 result[1] = sorted[i + 1];
396 result[2] = sorted[i + 2];
397 break;
401 for(size_t i = 0; i + 1 < sorted.size(); i++)
403 if(sorted[i].value == two[0])
405 result[3] = sorted[i];
406 result[4] = sorted[i + 1];
407 break;
411 return true;
414 //only call after already having checked for better combinations
415 bool checkFourOfAKind(Card result[5], const std::vector<Card>& sorted)
417 if(sorted.size() < 4) return false;
419 std::vector<int> values;
420 getFourOfKinds(values, sorted);
422 if(values.empty()) return false;
424 for(size_t i = 0; i + 3 < sorted.size(); i++)
426 if(sorted[i].value == values[0])
428 result[0] = sorted[i];
429 result[1] = sorted[i + 1];
430 result[2] = sorted[i + 2];
431 result[3] = sorted[i + 3];
432 break;
436 int c = 4;
437 for(size_t i = 0; i < sorted.size() && c < 5; i++)
439 if(sorted[i].value != values[0])
441 result[c] = sorted[i];
442 c++;
446 return true;
449 //only call after already having checked for better combinations
450 bool checkStraight(Card result[5], const std::vector<Card>& sorted)
452 if(sorted.size() < 5) return false;
454 int s = getStraight(sorted);
456 if(s == 0) return false;
458 for(size_t i = 0; i < 5; i++) result[0] = Card(); //set to unknown cards, for checks below
460 for(size_t i = 0; i < sorted.size(); i++)
462 if(sorted[i].value == s - 0 && !result[0].isValid()) result[0] = sorted[i];
463 if(sorted[i].value == s - 1 && !result[1].isValid()) result[1] = sorted[i];
464 if(sorted[i].value == s - 2 && !result[2].isValid()) result[2] = sorted[i];
465 if(sorted[i].value == s - 3 && !result[3].isValid()) result[3] = sorted[i];
466 if(sorted[i].value == s - 4 && !result[4].isValid()) result[4] = sorted[i];
469 if(s == 5) result[4] = sorted[0]; // The ace as value 1
471 return true;
474 //only call after already having checked for better combinations
475 bool checkStraightFlush(Card result[5], const std::vector<Card>& sorted)
477 if(sorted.size() < 5) return false;
479 Card c = getStraightFlush(sorted);
481 if(!c.isValid()) return false;
483 size_t j = 0;
484 for(size_t i = 0; i < sorted.size() && j < 5; i++)
486 if(sorted[i].value + j == (size_t)c.value && sorted[i].suit == c.suit)
488 result[j] = sorted[i];
489 j++;
493 if(c.getValue() == 5) result[4] = Card(14, c.getSuit()); // The ace as value 1
495 return true;
498 //only call after already having checked for better combinations
499 bool checkFlush(Card result[5], const std::vector<Card>& sorted)
501 if(sorted.size() < 5) return false;
503 Card c = getFlush(sorted);
505 if(!c.isValid()) return false;
507 size_t j = 0;
508 for(size_t i = 0; i < sorted.size() && j < 5; i++)
510 if(sorted[i].suit == c.suit)
512 result[j] = sorted[i];
513 j++;
517 return true;
520 ////////////////////////////////////////////////////////////////////////////////
521 ////////////////////////////////////////////////////////////////////////////////
522 ////////////////////////////////////////////////////////////////////////////////
523 ////////////////////////////////////////////////////////////////////////////////
524 ////////////////////////////////////////////////////////////////////////////////
525 ////////////////////////////////////////////////////////////////////////////////
526 ////////////////////////////////////////////////////////////////////////////////
527 ////////////////////////////////////////////////////////////////////////////////
530 //only call after already having checked for better combinations (including two pairs, three of a kind, or other things that already contain a pair in them too)
531 bool checkPair(const std::vector<Card>& sorted)
533 if(sorted.size() < 2) return false;
535 std::vector<int> values;
536 getPairs(values, sorted);
538 if(values.empty()) return false;
540 return true;
543 //only call after already having checked for better combinations
544 bool checkTwoPair(const std::vector<Card>& sorted)
546 if(sorted.size() < 4) return false;
548 std::vector<int> values;
549 getPairs(values, sorted);
551 if(values.size() < 2) return false;
553 return true;
556 //only call after already having checked for better combinations (including full house, four of a kind, or other things that already contain a pair in them too)
557 bool checkThreeOfAKind(const std::vector<Card>& sorted)
559 if(sorted.size() < 3) return false;
561 std::vector<int> values;
562 getThreeOfKinds(values, sorted);
564 if(values.empty()) return false;
566 return true;
569 //only call after already having checked for better combinations
570 bool checkFullHouse(const std::vector<Card>& sorted)
572 if(sorted.size() < 5) return false;
574 std::vector<int> two;
575 getPairs(two, sorted);
576 std::vector<int> three;
577 getThreeOfKinds(three, sorted);
579 if(two.empty() || three.empty()) return false;
581 return true;
584 //only call after already having checked for better combinations
585 bool checkFourOfAKind(const std::vector<Card>& sorted)
587 if(sorted.size() < 4) return false;
589 std::vector<int> values;
590 getFourOfKinds(values, sorted);
592 if(values.empty()) return false;
594 return true;
597 //only call after already having checked for better combinations
598 bool checkStraight(const std::vector<Card>& sorted)
600 if(sorted.size() < 5) return false;
602 int s = getStraight(sorted);
604 if(s == 0) return false;
605 return true;
608 //only call after already having checked for better combinations
609 bool checkStraightFlush(const std::vector<Card>& sorted)
611 if(sorted.size() < 5) return false;
613 Card c = getStraightFlush(sorted);
615 if(!c.isValid()) return false;
616 return true;
619 //only call after already having checked for better combinations
620 bool checkFlush(const std::vector<Card>& sorted)
622 if(sorted.size() < 5) return false;
624 Card c = getFlush(sorted);
626 if(!c.isValid()) return false;
627 return true;
630 ////////////////////////////////////////////////////////////////////////////////
631 ////////////////////////////////////////////////////////////////////////////////
632 ////////////////////////////////////////////////////////////////////////////////
633 ////////////////////////////////////////////////////////////////////////////////
634 ////////////////////////////////////////////////////////////////////////////////
635 ////////////////////////////////////////////////////////////////////////////////
636 ////////////////////////////////////////////////////////////////////////////////
637 ////////////////////////////////////////////////////////////////////////////////
639 void sortCardsHighToLow(std::vector<Card>& cards)
641 std::sort(cards.begin(), cards.end(), cardGreater);
645 Returns the best combo formed by the given cards.
647 void getCombo(Combination& combo, const std::vector<Card>& cards)
649 std::vector<Card> sorted = cards;
650 sortCardsHighToLow(sorted);
652 if(cards.size() < 5) combo.cards_used = cards.size();
653 else combo.cards_used = 5;
655 if(checkStraightFlush(combo.cards, sorted))
657 combo.type = C_STRAIGHT_FLUSH;
658 return;
661 if(checkFourOfAKind(combo.cards, sorted))
663 combo.type = C_FOUR_OF_A_KIND;
664 return;
667 if(checkFullHouse(combo.cards, sorted))
669 combo.type = C_FULL_HOUSE;
670 return;
673 if(checkFlush(combo.cards, sorted))
675 combo.type = C_FLUSH;
676 return;
679 if(checkStraight(combo.cards, sorted))
681 combo.type = C_STRAIGHT;
682 return;
685 if(checkThreeOfAKind(combo.cards, sorted))
687 combo.type = C_THREE_OF_A_KIND;
688 return;
691 if(checkTwoPair(combo.cards, sorted))
693 combo.type = C_TWO_PAIR;
694 return;
697 if(checkPair(combo.cards, sorted))
699 combo.type = C_PAIR;
700 return;
703 if(checkHighCard(combo.cards, sorted))
705 combo.type = C_HIGH_CARD;
706 return;
710 //2 cards given by short names
711 void getCombo(Combination& combo
712 , const std::string& card1
713 , const std::string& card2)
715 std::vector<Card> cards;
716 cards.push_back(Card(card1));
717 cards.push_back(Card(card2));
718 getCombo(combo, cards);
721 //3 cards given by short names
722 void getCombo(Combination& combo
723 , const std::string& card1
724 , const std::string& card2
725 , const std::string& card3)
727 std::vector<Card> cards;
728 cards.push_back(Card(card1));
729 cards.push_back(Card(card2));
730 cards.push_back(Card(card3));
731 getCombo(combo, cards);
734 //4 cards given by short names
735 void getCombo(Combination& combo
736 , const std::string& card1
737 , const std::string& card2
738 , const std::string& card3
739 , const std::string& card4)
741 std::vector<Card> cards;
742 cards.push_back(Card(card1));
743 cards.push_back(Card(card2));
744 cards.push_back(Card(card3));
745 cards.push_back(Card(card4));
746 getCombo(combo, cards);
749 //5 cards given by short names
750 void getCombo(Combination& combo
751 , const std::string& card1
752 , const std::string& card2
753 , const std::string& card3
754 , const std::string& card4
755 , const std::string& card5)
757 std::vector<Card> cards;
758 cards.push_back(Card(card1));
759 cards.push_back(Card(card2));
760 cards.push_back(Card(card3));
761 cards.push_back(Card(card4));
762 cards.push_back(Card(card5));
763 getCombo(combo, cards);
766 //6 cards given by short names
767 void getCombo(Combination& combo
768 , const std::string& card1
769 , const std::string& card2
770 , const std::string& card3
771 , const std::string& card4
772 , const std::string& card5
773 , const std::string& card6)
775 std::vector<Card> cards;
776 cards.push_back(Card(card1));
777 cards.push_back(Card(card2));
778 cards.push_back(Card(card3));
779 cards.push_back(Card(card4));
780 cards.push_back(Card(card5));
781 cards.push_back(Card(card6));
782 getCombo(combo, cards);
785 //7 cards given by short names
786 void getCombo(Combination& combo
787 , const std::string& card1
788 , const std::string& card2
789 , const std::string& card3
790 , const std::string& card4
791 , const std::string& card5
792 , const std::string& card6
793 , const std::string& card7)
795 std::vector<Card> cards;
796 cards.push_back(Card(card1));
797 cards.push_back(Card(card2));
798 cards.push_back(Card(card3));
799 cards.push_back(Card(card4));
800 cards.push_back(Card(card5));
801 cards.push_back(Card(card6));
802 cards.push_back(Card(card7));
803 getCombo(combo, cards);
806 void getCombo(Combination& combo, const std::string& cards)
808 std::vector<Card> cards2;
809 for(size_t i = 0; i + 1 < cards.size(); i += 2)
811 cards2.push_back(Card(cards.substr(i, 2)));
813 getCombo(combo, cards2);
816 void getCombo(Combination& combo, const Card& card1, const Card& card2, const Card& card3, const Card& card4, const Card& card5)
818 std::vector<Card> cards;
819 cards.push_back(card1);
820 cards.push_back(card2);
821 cards.push_back(card3);
822 cards.push_back(card4);
823 cards.push_back(card5);
824 getCombo(combo, cards);
827 int compare(const Combination& a, const Combination& b)
829 if((int)a.type > (int)(b.type)) return +1;
830 if((int)a.type < (int)(b.type)) return -1;
832 int num_cards = std::min(a.cards_used, b.cards_used);
834 for(int i = 0; i < num_cards; i++)
836 if(a.cards[i].value > b.cards[i].value) return +1;
837 if(a.cards[i].value < b.cards[i].value) return -1;
840 return 0;
843 bool combinationGreater(const Combination& a, const Combination& b)
845 return compare(a, b) == 1;