diff --git a/src/dawn/poker/Card.cpp b/src/dawn/poker/Card.cpp index 05e7de7e..7a2f3846 100644 --- a/src/dawn/poker/Card.cpp +++ b/src/dawn/poker/Card.cpp @@ -8,16 +8,64 @@ using namespace Dawn; void Card::fillDeck(std::vector *deck) { + assertNotNull(deck); + for(uint8_t i = 0; i < CARD_DECK_SIZE; i++) { deck->push_back(Card(i)); } } +int32_t Card::contains(std::vector *deck, struct Card c) { + assertNotNull(deck); + assertTrue(deck->size() > 0); -void Card::sort(std::vector *deck) { - std::sort(deck->begin(), deck->end(), &cardSorter); + auto it = deck->begin(); + while(it != deck->end()) { + if(it->cardValue == c.cardValue) return (int32_t)(it - deck->begin()); + ++it; + } + return -1; } -bool_t cardSorter(struct Card left, struct Card right) { +int32_t Card::containsNumber( + std::vector *deck, + enum CardValue number +) { + assertNotNull(deck); + assertTrue(number < CARD_COUNT_PER_SUIT); + + auto it = deck->begin(); + while(it != deck->end()) { + if(it->getValue() == number) return (int32_t)(it - deck->begin()); + ++it; + } + return -1; +} + +std::vector Card::countPairs( + std::vector *deck, + enum CardValue val +) { + std::vector pairs; + + assertNotNull(deck); + assertTrue(deck->size() > 0); + + auto it = deck->begin(); + while(it != deck->end()) { + if(it->getValue() == val) pairs.push_back(*it); + ++it; + } + + return pairs; +} + +bool_t Card::cardSorter(struct Card left, struct Card right) { return left.cardValue < right.cardValue; -} \ No newline at end of file +} + +void Card::sort(std::vector *deck) { + assertNotNull(deck); + assertTrue(deck->size() > 1); + std::sort(deck->begin(), deck->end(), &Card::cardSorter); +} diff --git a/src/dawn/poker/Card.hpp b/src/dawn/poker/Card.hpp index c3713486..a1209344 100644 --- a/src/dawn/poker/Card.hpp +++ b/src/dawn/poker/Card.hpp @@ -5,6 +5,7 @@ #pragma once #include "dawnlibs.hpp" +#include "assert/assert.hpp" namespace Dawn { enum CardSuit { @@ -43,14 +44,56 @@ namespace Dawn { public: uint8_t cardValue; - static void fillDeck(std::vector *deck); + /** + * Shuffles a hand / deck + * + * @param deck Array of cards to shuffle. + */ static void shuffle(std::vector *deck); - static bool_t contains(std::vector *deck, struct Card); + + /** + * Fills a vector with all of the cards in a deck, in order. + * + * @param deck Deck to fill. + */ + static void fillDeck(std::vector *deck); + + /** + * Check if an array of cards contains a specific card. + * + * @param deck Deck/Hand/Array of cards to check. + * @param card Card to look for + * @returns The index within the array that the card is. -1 if not found. + */ + static int32_t contains(std::vector *deck, struct Card card); + + /** + * Check if the array of cards contains a specific number. + * + * @param deck Array of cards to check + * @param number The number to look for. + * @returns The index that the first card is. -1 if not found. + */ + static int32_t containsNumber( + std::vector *deck, + enum CardValue number + ); + + /** + * Counts the amount of times a card's number appears within the given + * hand. + * + * @param deck The hand to check + * @param val Value of pairs to find. + * @return Card pairs in the deck. + */ static std::vector countPairs( std::vector *deck, - enum CardValue value + enum CardValue val ); + static bool_t cardSorter(struct Card left, struct Card right); + /** * Sort a hand of cards. Cards are ordered in descending weight, aces are * high. Cards will be grouped by their suits, e.g. CARD_CLUBS_TWO will @@ -71,14 +114,21 @@ namespace Dawn { assertTrue(cv < CARD_DECK_SIZE); } + /** + * Returns the number of a given card. + * @returns The card number. + */ CardValue getValue() { return (CardValue)(cardValue % CARD_COUNT_PER_SUIT); } + /** + * Returns the suit of a given card. + * @returns The suit. + */ CardSuit getSuit() { return (CardSuit)(cardValue / CARD_COUNT_PER_SUIT); } }; - bool_t cardSorter(struct Card left, struct Card right); } \ No newline at end of file diff --git a/src/dawn/poker/PokerPlayer.cpp b/src/dawn/poker/PokerPlayer.cpp index 1a524799..888e012d 100644 --- a/src/dawn/poker/PokerPlayer.cpp +++ b/src/dawn/poker/PokerPlayer.cpp @@ -239,206 +239,196 @@ int32_t PokerPlayer::getSumOfChips() { struct PokerWinning PokerPlayer::getWinning() { struct PokerWinning winning; - uint8_t i, j, l; + struct Card card(0x00); + uint8_t i, j; + int32_t index; + enum CardValue number, look; + enum CardSuit suit; + std::vector pairs; // Get the full poker hand (should be a 7 card hand, but MAY not be) - auto itHand = this->hand.begin(); - while(itHand != this->hand.end()) { - winning.full.push_back(*itHand); - ++itHand; + for(i = 0; i < this->pokerGame->community.size(); i++) { + winning.full.push_back(this->pokerGame->community[i]); } - - auto itCommunity = this->pokerGame->community.begin(); - while(itCommunity != this->pokerGame->community.end()) { - winning.full.push_back(*itCommunity); - ++itCommunity; + for(i = 0; i < this->hand.size(); i++) { + winning.full.push_back(this->hand[i]); } Card::sort(&winning.full); //////////////////////// Now look for the winning set //////////////////////// // Royal / Straight Flush - auto it = winning.full.begin(); - while(it != winning.full.end()) { - auto number = it->getValue(); - auto suit = it->getSuit(); - if(number < CARD_FIVE) { - ++it; - continue; - } + for(i = 0; i < winning.full.size(); i++) { + card = winning.full[i]; + number = card.getValue(); + if(number < CARD_FIVE) continue; + suit = card.getSuit(); + winning.set.clear(); - winning.set.push_back(*it); + winning.set.push_back(card); // Now look for the matching cards (Reverse order to order from A to 10) for(j = 1; j <= 4; j++) { - l = number == CARD_FIVE && j == 4 ? CARD_ACE : number - j;//Ace low. - auto c = Card(suit, (CardValue)l); - if(!Card::contains(&winning.full, c)) break; - winning.set.push_back(c); + // Ace low. + look = ( + number == CARD_FIVE && j == 4 ? + (enum CardValue)CARD_ACE : + (enum CardValue)(number - j) + ); + index = Card::contains(&winning.full, Card(suit, look)); + if(index == -1) break; + winning.set.push_back(winning.full[index]); } // Check if has all necessary cards. - if(winning.set.size() != 5) { - ++it; - continue; - } + if(winning.set.size() < POKER_WINNING_SET_SIZE) continue; // Add self to array winning.type = ( number == CARD_ACE ? POKER_WINNING_TYPE_ROYAL_FLUSH : POKER_WINNING_TYPE_STRAIGHT_FLUSH ); - pokerWinnerFillRemaining(winning); + winning.fillRemaining(); return winning; } // Four of a kind. - it = winning.full.begin(); - while(it != winning.full.end()) { - auto pairs = Card::countPairs(&winning.full, it->getValue()); - if(pairs.size() < CARD_SUIT_COUNT) { - ++it; - continue; - } + for(i = 0; i < winning.full.size(); i++) { + card = winning.full[i]; + number = card.getValue(); + pairs = Card::countPairs(&winning.full, number); + if(pairs.size() < CARD_SUIT_COUNT) continue; winning.set = pairs; winning.type = POKER_WINNING_TYPE_FOUR_OF_A_KIND; - pokerWinnerFillRemaining(winning); + winning.fillRemaining(); return winning; } // Full House winning.set.clear(); - it = winning.full.begin(); - while(it != winning.full.end()) { + for(i = 0; i < winning.full.size(); i++) { // Check we haven't already added this card. - if(Card::contains(&winning.set, *it) != -1) { - ++it; + card = winning.full[i]; + if(Card::contains(&winning.set, card) != -1) { continue; } - auto pairs = Card::countPairs(&winning.full, it->getValue()); + number = card.getValue(); + pairs = Card::countPairs(&winning.full, number); // Did we find either two pair or three pair? - if(pairs.size() != 2 && pairs.size() != 3) { - ++it; - continue; - } - if(winning.set.size() == 3) { - winning.set.pop_back(); + if(pairs.size() != 2 && pairs.size() != 3) continue; + if(winning.set.size() == 3) {//Clamp to 5 max. + pairs.pop_back(); } // Copy found pairs. - auto itPairs = pairs.begin(); - while(itPairs != pairs.end()) { - winning.set.push_back(*itPairs); - ++itPairs; + for(j = 0; j < pairs.size(); j++) { + winning.set.push_back(pairs[j]); } // Winned? - if(winning.set.size() != 5) { - ++it; - continue; - } + if(winning.set.size() != POKER_WINNING_SET_SIZE) continue; winning.type = POKER_WINNING_TYPE_FULL_HOUSE; - pokerWinnerFillRemaining(winning); + winning.fillRemaining(); return winning; } // Flush (5 same suit) - for(i = 0; i < winning->fullSize; i++) { - card = winning->full[i]; - suit = cardGetSuit(card); - winning->setSize = 1; - for(j = i+1; j < winning->fullSize; j++) { - if(cardGetSuit(winning->full[j]) != suit) continue; - winning->set[winning->setSize++] = winning->full[j]; - if(winning->setSize == POKER_WINNING_SET_SIZE) break; + for(i = 0; i < winning.full.size(); i++) { + card = winning.full[i]; + suit = card.getSuit(); + + winning.set.clear(); + winning.set.push_back(card); + + for(j = i+1; j < winning.full.size(); j++) { + if(winning.full[j].getSuit() != suit) continue; + winning.set.push_back(winning.full[j]); + if(winning.set.size() == POKER_WINNING_SET_SIZE) break; } - if(winning->setSize < POKER_WINNING_SET_SIZE) continue; - winning->set[0] = winning->full[i]; - winning->type = POKER_WINNING_TYPE_FLUSH; - pokerWinnerFillRemaining(winning); - return; + if(winning.set.size() < POKER_WINNING_SET_SIZE) continue; + winning.type = POKER_WINNING_TYPE_FLUSH; + winning.fillRemaining(); + return winning; } // Straight (sequence any suit) - winning->setSize = 0; - for(i = 0; i < winning->fullSize; i++) { - card = winning->full[i]; - number = cardGetNumber(card); + for(i = 0; i < winning.full.size(); i++) { + card = winning.full[i]; + number = card.getValue(); if(number < CARD_FIVE) continue; - winning->setSize = 1; + + winning.set.clear(); + winning.set.push_back(card); for(j = 1; j <= 4; j++) { - l = number == CARD_FIVE && j == 4 ? CARD_ACE : number - j;//Ace low. - index = cardContainsNumber(winning->full, winning->fullSize, l); + // Ace low. + look = ( + number == CARD_FIVE && j == 4 ? + (enum CardValue)CARD_ACE : + (enum CardValue)(number - j) + ); + index = Card::containsNumber(&winning.full, look); if(index == -1) break; - winning->set[j] = winning->full[index]; - winning->setSize++; + winning.set.push_back(winning.full[index]); } // Check if has all necessary cards. - if(winning->setSize < POKER_WINNING_SET_SIZE) continue; - winning->set[0] = winning->full[i]; - winning->type = POKER_WINNING_TYPE_STRAIGHT; - pokerWinnerFillRemaining(winning); - return; + if(winning.set.size() < POKER_WINNING_SET_SIZE) continue; + winning.type = POKER_WINNING_TYPE_STRAIGHT; + winning.fillRemaining(); + return winning; } // Three of a kind - winning->setSize = 0; - for(i = 0; i < winning->fullSize; i++) { - card = winning->full[i]; - number = cardGetNumber(card); - pairCount = cardCountPairs(winning->full, winning->fullSize, number, pairs); - if(pairCount != 3) continue; + for(i = 0; i < winning.full.size(); i++) { + card = winning.full[i]; + number = card.getValue(); + pairs = Card::countPairs(&winning.full, number); + if(pairs.size() != 3) continue; - winning->setSize = pairCount; - for(j = 0; j < pairCount; j++) winning->set[j] = winning->full[pairs[j]]; - winning->type = POKER_WINNING_TYPE_THREE_OF_A_KIND; - pokerWinnerFillRemaining(winning); - return; + winning.set = pairs; + winning.type = POKER_WINNING_TYPE_THREE_OF_A_KIND; + winning.fillRemaining(); + return winning; } // Two Pair - winning->setSize = 0; - for(i = 0; i < winning->fullSize; i++) { - card = winning->full[i];// Check we haven't already added this card. + winning.set.clear(); + for(i = 0; i < winning.full.size(); i++) { + card = winning.full[i];// Check we haven't already added this card. if( - winning->setSize > 0 && - cardContains(winning->set, winning->setSize, card) != -1 + winning.set.size() > 0 && + Card::contains(&winning.set, card) != -1 ) { continue; } - number = cardGetNumber(card); - pairCount = cardCountPairs(winning->full, winning->fullSize, number, pairs); - if(pairCount != 2) continue; - - for(j = 0; j < pairCount; j++) { - winning->set[winning->setSize+j] = winning->full[pairs[j]]; + number = card.getValue(); + pairs = Card::countPairs(&winning.full, number); + if(pairs.size() != 2) continue; + for(j = 0; j < pairs.size(); j++) { + winning.set.push_back(pairs[j]); } - winning->setSize += pairCount; - if(winning->setSize != 4) continue; - - winning->type = POKER_WINNING_TYPE_TWO_PAIR; - pokerWinnerFillRemaining(winning); - return; + if(winning.set.size() != 4) continue; + winning.type = POKER_WINNING_TYPE_TWO_PAIR; + winning.fillRemaining(); + return winning; } // Pair - if(winning->setSize == 2) { - winning->type = POKER_WINNING_TYPE_PAIR; - pokerWinnerFillRemaining(winning); - return; + if(winning.set.size() == 2) { + winning.type = POKER_WINNING_TYPE_PAIR; + winning.fillRemaining(); + return winning; } // High card - winning->setSize = 0; - pokerWinnerFillRemaining(winning); - winning->type = POKER_WINNING_TYPE_HIGH_CARD; - - return; + winning.set.clear(); + winning.fillRemaining(); + winning.type = POKER_WINNING_TYPE_HIGH_CARD; + return winning; } \ No newline at end of file diff --git a/src/dawn/poker/PokerWinning.cpp b/src/dawn/poker/PokerWinning.cpp index 35521a35..bf1c02dc 100644 --- a/src/dawn/poker/PokerWinning.cpp +++ b/src/dawn/poker/PokerWinning.cpp @@ -30,4 +30,37 @@ float_t PokerWinning::getWinningTypeConfidence(enum PokerWinningType type) { default: return POKER_WINNING_CONFIDENCE_HIGH_CARD; } +} + +void PokerWinning::fillRemaining() { + uint8_t i, highest, current; + struct Card highestCard(0x00); + struct Card currentCard(0x00); + + // Set the kicker + this->kicker = 0xFF; + + // Fill the remaining cards + while(this->set.size() < POKER_WINNING_SET_SIZE) { + highest = 0xFF; + + for(i = 0; i < this->full.size(); i++) { + currentCard = this->full[i]; + if(Card::contains(&this->set, currentCard) != -1) continue; + + if(highest == 0xFF) { + highestCard = currentCard; + highest = highestCard.getValue(); + } else { + current = currentCard.getValue(); + if(current != CARD_ACE && current < highest) continue; + highestCard = currentCard; + highest = current; + } + } + + if(highest == 0xFF) break; + this->set.push_back(highestCard); + } + Card::sort(&this->set); } \ No newline at end of file diff --git a/src/dawn/poker/PokerWinning.hpp b/src/dawn/poker/PokerWinning.hpp index cbca6bf3..021980c3 100644 --- a/src/dawn/poker/PokerWinning.hpp +++ b/src/dawn/poker/PokerWinning.hpp @@ -18,6 +18,9 @@ #define POKER_WINNING_CONFIDENCE_PAIR 0.2f #define POKER_WINNING_CONFIDENCE_HIGH_CARD 0.1f +/** How many cards in the winning set */ +#define POKER_WINNING_SET_SIZE 5 + namespace Dawn { enum PokerWinningType { POKER_WINNING_TYPE_NULL, @@ -38,7 +41,14 @@ namespace Dawn { enum PokerWinningType type; std::vector full; std::vector set; + struct Card kicker; + + PokerWinning() : kicker(0x00) { + + } static float_t getWinningTypeConfidence(enum PokerWinningType type); + + void fillRemaining(); }; } \ No newline at end of file