4 Copyright (c) 2010 Lode Vandevenne
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
)
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";
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";
54 std::string
Combination::getNameWithAllCards() const
56 std::string result
= getName();
58 for(int i
= 0; i
< cards_used
; i
++) result
= result
+ " " + cards
[i
].getShortName();
63 std::string
Combination::getNameWithAllCardsPrintable() const
65 std::string result
= getName();
67 for(int i
= 0; i
< cards_used
; i
++) result
= result
+ " " + cards
[i
].getShortNamePrintable();
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
++)
91 while(j
< vals
.size() && vals
[j
] == vals
[i
]) j
++;
93 if(j
== i
+ 2) values
.push_back(vals
[i
]);
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
++)
108 while(j
< vals
.size() && vals
[j
] == vals
[i
]) j
++;
110 if(j
== i
+ 3) values
.push_back(vals
[i
]);
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
++)
125 while(j
< vals
.size() && vals
[j
] == vals
[i
]) j
++;
127 if(j
== i
+ 4) values
.push_back(vals
[i
]);
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
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)
155 else if(vals
[i
] < last
- 1)
159 else //if vals[i] == last
163 if(num
== 5) return vals
[i
] + 4;
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
);
230 return Card(d
, S_DIAMONDS
);
234 return Card(h
, S_HEARTS
);
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
];
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];
288 for(size_t i
= 0; i
< sorted
.size() && c
< 5; i
++)
290 if(sorted
[i
].value
!= values
[0])
292 result
[c
] = sorted
[i
];
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];
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];
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
];
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];
366 for(size_t i
= 0; i
< sorted
.size() && c
< 5; i
++)
368 if(sorted
[i
].value
!= values
[0])
370 result
[c
] = sorted
[i
];
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];
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];
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];
437 for(size_t i
= 0; i
< sorted
.size() && c
< 5; i
++)
439 if(sorted
[i
].value
!= values
[0])
441 result
[c
] = sorted
[i
];
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
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;
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
];
493 if(c
.getValue() == 5) result
[4] = Card(14, c
.getSuit()); // The ace as value 1
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;
508 for(size_t i
= 0; i
< sorted
.size() && j
< 5; i
++)
510 if(sorted
[i
].suit
== c
.suit
)
512 result
[j
] = sorted
[i
];
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;
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;
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;
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;
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;
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;
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;
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;
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
;
661 if(checkFourOfAKind(combo
.cards
, sorted
))
663 combo
.type
= C_FOUR_OF_A_KIND
;
667 if(checkFullHouse(combo
.cards
, sorted
))
669 combo
.type
= C_FULL_HOUSE
;
673 if(checkFlush(combo
.cards
, sorted
))
675 combo
.type
= C_FLUSH
;
679 if(checkStraight(combo
.cards
, sorted
))
681 combo
.type
= C_STRAIGHT
;
685 if(checkThreeOfAKind(combo
.cards
, sorted
))
687 combo
.type
= C_THREE_OF_A_KIND
;
691 if(checkTwoPair(combo
.cards
, sorted
))
693 combo
.type
= C_TWO_PAIR
;
697 if(checkPair(combo
.cards
, sorted
))
703 if(checkHighCard(combo
.cards
, sorted
))
705 combo
.type
= C_HIGH_CARD
;
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;
843 bool combinationGreater(const Combination
& a
, const Combination
& b
)
845 return compare(a
, b
) == 1;