This commit is contained in:
2022-11-21 22:04:05 -08:00
parent ad34be05e3
commit c1ac69a146
5 changed files with 259 additions and 128 deletions

View File

@ -8,16 +8,64 @@
using namespace Dawn;
void Card::fillDeck(std::vector<struct Card> *deck) {
assertNotNull(deck);
for(uint8_t i = 0; i < CARD_DECK_SIZE; i++) {
deck->push_back(Card(i));
}
}
int32_t Card::contains(std::vector<struct Card> *deck, struct Card c) {
assertNotNull(deck);
assertTrue(deck->size() > 0);
void Card::sort(std::vector<struct Card> *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<struct Card> *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<struct Card> Card::countPairs(
std::vector<struct Card> *deck,
enum CardValue val
) {
std::vector<struct Card> 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;
}
}
void Card::sort(std::vector<struct Card> *deck) {
assertNotNull(deck);
assertTrue(deck->size() > 1);
std::sort(deck->begin(), deck->end(), &Card::cardSorter);
}

View File

@ -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<struct Card> *deck);
/**
* Shuffles a hand / deck
*
* @param deck Array of cards to shuffle.
*/
static void shuffle(std::vector<struct Card> *deck);
static bool_t contains(std::vector<struct Card> *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<struct Card> *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<struct Card> *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<struct Card> *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<struct Card> countPairs(
std::vector<struct Card> *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);
}

View File

@ -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<struct Card> 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;
}

View File

@ -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);
}

View File

@ -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<struct Card> full;
std::vector<struct Card> set;
struct Card kicker;
PokerWinning() : kicker(0x00) {
}
static float_t getWinningTypeConfidence(enum PokerWinningType type);
void fillRemaining();
};
}