More refactoring
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
|
||||
target_sources(${DAWN_TARGET_NAME}
|
||||
PRIVATE
|
||||
Easing.cpp
|
||||
String.cpp
|
||||
Random.cpp
|
||||
)
|
48
src/dawn/util/Easing.cpp
Normal file
48
src/dawn/util/Easing.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright (c) 2024 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "Easing.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
float_t Easing::linear(float_t t) {
|
||||
return t;
|
||||
}
|
||||
|
||||
float_t Easing::easeInQuad(float_t t) {
|
||||
return t * t;
|
||||
}
|
||||
|
||||
float_t Easing::easeOutQuad(float_t t) {
|
||||
return t * (2 - t);
|
||||
}
|
||||
|
||||
float_t Easing::easeInOutQuad(float_t t) {
|
||||
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
||||
}
|
||||
|
||||
float_t Easing::easeInCubic(float_t t) {
|
||||
return t * t * t;
|
||||
}
|
||||
|
||||
float_t Easing::easeOutCubic(float_t t) {
|
||||
return (--t) * t * t + 1;
|
||||
}
|
||||
|
||||
float_t Easing::easeInOutCubic(float_t t) {
|
||||
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
|
||||
}
|
||||
|
||||
float_t Easing::easeInQuart(float_t t) {
|
||||
return t * t * t * t;
|
||||
}
|
||||
|
||||
float_t Easing::easeOutQuart(float_t t) {
|
||||
return 1 - (--t) * t * t * t;
|
||||
}
|
||||
|
||||
float_t Easing::easeInOutQuart(float_t t) {
|
||||
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t;
|
||||
}
|
92
src/dawn/util/Easing.hpp
Normal file
92
src/dawn/util/Easing.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2024 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "dawnlibs.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class Easing final {
|
||||
public:
|
||||
/**
|
||||
* Linear easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t linear(float_t t);
|
||||
|
||||
/**
|
||||
* Quadratic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeInQuad(float_t t);
|
||||
|
||||
/**
|
||||
* Quadratic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeOutQuad(float_t t);
|
||||
|
||||
/**
|
||||
* Quadratic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeInOutQuad(float_t t);
|
||||
|
||||
/**
|
||||
* Cubic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeInCubic(float_t t);
|
||||
|
||||
/**
|
||||
* Cubic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeOutCubic(float_t t);
|
||||
|
||||
/**
|
||||
* Cubic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeInOutCubic(float_t t);
|
||||
|
||||
/**
|
||||
* Quartic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeInQuart(float_t t);
|
||||
|
||||
/**
|
||||
* Quartic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeOutQuart(float_t t);
|
||||
|
||||
/**
|
||||
* Quartic easing function.
|
||||
*
|
||||
* @param t Time value between 0 and 1.
|
||||
* @return Eased value.
|
||||
*/
|
||||
static float_t easeInOutQuart(float_t t);
|
||||
};
|
||||
}
|
@ -23,6 +23,16 @@ namespace Dawn {
|
||||
*/
|
||||
static uint64_t next();
|
||||
|
||||
/**
|
||||
* Returns a random number between 0 and RAND_MAX.
|
||||
*
|
||||
* @return Random number between 0 and RAND_MAX.
|
||||
*/
|
||||
template<typename T>
|
||||
static T random() {
|
||||
return (T)next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random number between the provided min and max values.
|
||||
*
|
||||
|
@ -42,7 +42,7 @@ int32_t Card::contains(
|
||||
);
|
||||
}
|
||||
|
||||
int32_t Card::containsNumber(
|
||||
int32_t Card::containsValue(
|
||||
const std::vector<struct Card> &deck,
|
||||
const enum CardValue number
|
||||
) {
|
||||
|
@ -29,6 +29,7 @@ namespace Dawn {
|
||||
Queen = 10,
|
||||
King = 11,
|
||||
Ace = 12,
|
||||
Invalid = 0xFF
|
||||
};
|
||||
|
||||
/** Count of cards in each suit */
|
||||
@ -77,7 +78,7 @@ namespace Dawn {
|
||||
* @param number The number to look for.
|
||||
* @returns The index that the first card is. -1 if not found.
|
||||
*/
|
||||
static int32_t containsNumber(
|
||||
static int32_t containsValue(
|
||||
const std::vector<struct Card> &deck,
|
||||
const enum CardValue number
|
||||
);
|
||||
@ -132,7 +133,6 @@ namespace Dawn {
|
||||
* @param cv Card value.
|
||||
*/
|
||||
Card(const uint8_t cv) : cardValue(cv) {
|
||||
assertTrue(cv < CARD_DECK_SIZE, "Card value out of range");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -23,7 +23,7 @@ void PokerGame::newGame() {
|
||||
|
||||
void PokerGame::newRound() {
|
||||
this->deck.clear();
|
||||
Card::fillDeck(&this->deck);
|
||||
Card::fillDeck(this->deck);
|
||||
|
||||
this->smallBlind = POKER_BLIND_SMALL_DEFAULT;
|
||||
this->bigBlind = POKER_BLIND_BIG_DEFAULT;
|
||||
@ -82,9 +82,9 @@ void PokerGame::takeBlinds() {
|
||||
playerBigBlind->hasBetThisRound = false;
|
||||
}
|
||||
|
||||
void PokerGame::setDealer(uint8_t dealer) {
|
||||
void PokerGame::setDealer(const uint8_t dealer) {
|
||||
uint8_t i, k;
|
||||
PokerPlayer *player;
|
||||
std::shared_ptr<PokerPlayer> player;
|
||||
bool_t foundDealer;
|
||||
bool_t foundSmall;
|
||||
|
||||
@ -123,44 +123,43 @@ uint8_t PokerGame::getRemainingPlayersCount() {
|
||||
uint8_t count = 0;
|
||||
auto it = this->players.begin();
|
||||
while(it != this->players.end()) {
|
||||
auto player = *it;
|
||||
if(!player->isFolded && !player->isOut) count++;
|
||||
if(!(*it)->isFolded && !(*it)->isOut) count++;
|
||||
++it;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int32_t PokerGame::getCurrentCallValue() {
|
||||
assertTrue(this->pots.size() > 0);
|
||||
assertTrue(this->pots.size() > 0, "No pots?");
|
||||
return this->pots.back().call;
|
||||
}
|
||||
|
||||
void PokerGame::burnCard() {
|
||||
assertTrue(this->deck.size() > 0);
|
||||
assertTrue(this->deck.size() > 0, "No cards to burn.");
|
||||
auto card = this->deck.back();
|
||||
this->deck.pop_back();
|
||||
this->grave.push_back(card);
|
||||
}
|
||||
|
||||
void PokerGame::dealCard(PokerPlayer *player) {
|
||||
assertTrue(this->deck.size() > 0);
|
||||
void PokerGame::dealCard(PokerPlayer &player) {
|
||||
assertTrue(this->deck.size() > 0, "No cards to deal.");
|
||||
auto card = this->deck.back();
|
||||
this->deck.pop_back();
|
||||
player->hand.push_back(card);
|
||||
player.hand.push_back(card);
|
||||
}
|
||||
|
||||
void PokerGame::dealToEveryone(uint8_t count) {
|
||||
void PokerGame::dealToEveryone(const uint8_t count) {
|
||||
for(uint8_t i = 0; i < count; i++) {
|
||||
auto it = this->players.begin();
|
||||
while(it != this->players.end()) {
|
||||
this->dealCard(*it);
|
||||
this->dealCard(*(*it));
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PokerGame::turn(uint8_t count) {
|
||||
assertTrue(this->deck.size() >= count);
|
||||
void PokerGame::turn(const uint8_t count) {
|
||||
assertTrue(this->deck.size() >= count, "Not enough cards to turn.");
|
||||
for(uint8_t i = 0; i < count; i++) {
|
||||
auto card = this->deck.back();
|
||||
this->deck.pop_back();
|
||||
|
@ -21,7 +21,6 @@ namespace Dawn {
|
||||
protected:
|
||||
std::vector<struct Card> deck;
|
||||
std::vector<struct Card> grave;
|
||||
std::vector<struct Card> community;
|
||||
uint8_t dealerIndex;
|
||||
uint8_t smallBlindIndex;
|
||||
uint8_t bigBlindIndex;
|
||||
@ -29,25 +28,101 @@ namespace Dawn {
|
||||
int32_t bigBlind = POKER_BLIND_BIG_DEFAULT;
|
||||
|
||||
public:
|
||||
std::vector<PokerPlayer*> players;
|
||||
std::vector<std::shared_ptr<PokerPlayer>> players;
|
||||
std::vector<struct PokerPot> pots;
|
||||
std::vector<struct Card> community;
|
||||
uint8_t betterIndex;
|
||||
|
||||
/**
|
||||
* Starts a new game of poker.
|
||||
*/
|
||||
void newGame();
|
||||
|
||||
/**
|
||||
* Starts a new round of poker.
|
||||
*/
|
||||
void newRound();
|
||||
|
||||
/**
|
||||
* Starts a new betting round.
|
||||
*/
|
||||
void newBettingRound();
|
||||
|
||||
/**
|
||||
* Takes the blinds from the players.
|
||||
*/
|
||||
void takeBlinds();
|
||||
void setBlinds(int32_t small, int32_t big);
|
||||
|
||||
/**
|
||||
* Sets the blinds for the game.
|
||||
*
|
||||
* @param small The cost of the small blind.
|
||||
* @param big The cost of the big blind.
|
||||
*/
|
||||
void setBlinds(const int32_t small, const int32_t big);
|
||||
|
||||
/**
|
||||
* Returns the count of players that still need to bet this round.
|
||||
*
|
||||
* @return The count of players that still need to bet this round.
|
||||
*/
|
||||
uint8_t getRemainingBettersCount();
|
||||
|
||||
/**
|
||||
* Returns the current call value for the game.
|
||||
*
|
||||
* @return The current call value for the game.
|
||||
*/
|
||||
int32_t getCurrentCallValue();
|
||||
|
||||
/**
|
||||
* Returns the next better index.
|
||||
*
|
||||
* @return The next better index.
|
||||
*/
|
||||
uint8_t getNextBetterIndex();
|
||||
void setDealer(uint8_t dealer);
|
||||
void newDealer();
|
||||
|
||||
/**
|
||||
* Sets the dealer for the game.
|
||||
*
|
||||
* @param dealer The index of the dealer.
|
||||
*/
|
||||
void setDealer(const uint8_t dealer);
|
||||
|
||||
/**
|
||||
* Sends a card to the burn pile.
|
||||
*/
|
||||
void burnCard();
|
||||
void dealCard(PokerPlayer *player);
|
||||
void dealToEveryone(uint8_t count);
|
||||
void turn(uint8_t count);
|
||||
|
||||
/**
|
||||
* Deals a card to a player.
|
||||
*
|
||||
* @param player The player to deal the card to.
|
||||
*/
|
||||
void dealCard(PokerPlayer &player);
|
||||
|
||||
/**
|
||||
* Deals a card to each player.
|
||||
*/
|
||||
void dealToEveryone(const uint8_t count);
|
||||
|
||||
/**
|
||||
* Deals a card to the community.
|
||||
*/
|
||||
void turn(const uint8_t count);
|
||||
|
||||
/**
|
||||
* Returns the count of cards that need to be turned.
|
||||
*
|
||||
* @return The count of cards that need to be turned.
|
||||
*/
|
||||
uint8_t getCountOfCardsToTurn();
|
||||
|
||||
/**
|
||||
* Returns the count of players that are still in the game.
|
||||
*
|
||||
* @return The count of players that are still in the game.
|
||||
*/
|
||||
uint8_t getRemainingPlayersCount();
|
||||
};
|
||||
}
|
@ -6,6 +6,8 @@
|
||||
#include "PokerPlayer.hpp"
|
||||
#include "PokerGame.hpp"
|
||||
#include "util/Math.hpp"
|
||||
#include "util/Random.hpp"
|
||||
#include "util/Easing.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
@ -42,7 +44,6 @@ void PokerPlayer::bet(
|
||||
struct PokerPot &pot,
|
||||
const int32_t chips
|
||||
) {
|
||||
assertNotNull(pot, "Pot must be valid.");
|
||||
assertTrue(chips >= 0, "Chips must be a positive value.");
|
||||
assertTrue(!this->isFolded, "Cannot bet if player is folded.");
|
||||
assertTrue(!this->isOut, "Cannot bet if player is out.");
|
||||
@ -68,7 +69,7 @@ void PokerPlayer::bet(const int32_t chips) {
|
||||
assertNotNull(pg, "PokerGame has become invalid.");
|
||||
assertTrue(pg->pots.size() > 0, "PokerGame has no pots?");
|
||||
assertUnreachable("Bugged");
|
||||
// this->bet(&this->pokerGame->pots.back(), chips);
|
||||
this->bet(pg->pots.back(), chips);
|
||||
}
|
||||
|
||||
void PokerPlayer::fold() {
|
||||
@ -92,6 +93,9 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
int32_t callBet;
|
||||
float_t potOdds;
|
||||
|
||||
auto pg = this->pokerGame.lock();
|
||||
assertNotNull(pg, "PokerGame has become invalid.");
|
||||
|
||||
// Can the player do anything?
|
||||
if(this->isFolded || this->isOut) {
|
||||
turn.type = POKER_TURN_TYPE_OUT;
|
||||
@ -107,8 +111,11 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
|
||||
|
||||
// Is this preflop?
|
||||
if(this->pokerGame->community.size() == 0) {
|
||||
assertTrue(this->hand.size() == POKER_PLAYER_HAND_SIZE_MAX);
|
||||
if(pg->community.size() == 0) {
|
||||
assertTrue(
|
||||
this->hand.size() == POKER_PLAYER_HAND_SIZE_MAX,
|
||||
"Invalid hand size."
|
||||
);
|
||||
|
||||
// Get the hand weight
|
||||
auto cardNumber0 = this->hand[0].getValue();
|
||||
@ -117,7 +124,7 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
auto suitNumber1 = this->hand[1].getSuit();
|
||||
|
||||
// Get delta between cards
|
||||
auto i = (uint8_t)mathAbs<int8_t>(
|
||||
auto i = (uint8_t)Math::abs<int8_t>(
|
||||
(int8_t)cardNumber0 - (int8_t)cardNumber1
|
||||
);
|
||||
|
||||
@ -142,7 +149,7 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
// This may change in future, but I was finding the AI did not want to bet
|
||||
// during the preflop enough, this curves the AI to want to preflop call
|
||||
// often.
|
||||
confidence = easeOutCubic(confidence);
|
||||
confidence = Easing::easeOutCubic(confidence);
|
||||
} else {
|
||||
// Simulate my hand being the winning hand, use that as the confidence
|
||||
auto winning = this->getWinning();
|
||||
@ -160,14 +167,14 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
(float_t)this->getSumOfChips()
|
||||
);
|
||||
} else {
|
||||
potOdds = 1.0f / (float_t)this->pokerGame->getRemainingBettersCount();
|
||||
potOdds = 1.0f / (float_t)pg->getRemainingBettersCount();
|
||||
}
|
||||
|
||||
// Now determine the expected ROI
|
||||
auto expectedGain = confidence / potOdds;
|
||||
|
||||
// Now get a random 0-100
|
||||
auto random = randomGenerate<int32_t>() % 100;
|
||||
auto random = Random::random<int32_t>() % 100;
|
||||
|
||||
// Determine the max bet that the AI is willing to make
|
||||
auto maxBet = (int32_t)((float_t)this->chips / 1.75f) - (random / 2);
|
||||
@ -206,7 +213,7 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
} else {
|
||||
amount = maxBet;
|
||||
}
|
||||
} else if(confidence < 0.95f || this->pokerGame->community.size() < 4) {
|
||||
} else if(confidence < 0.95f || pg->community.size() < 4) {
|
||||
if(random < 20) {
|
||||
amount = callBet;
|
||||
} else {
|
||||
@ -220,7 +227,7 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
// number.
|
||||
|
||||
// If this is the first round... make it a lot less likely I'll bet
|
||||
if(this->pokerGame->community.size() == 0 && amount > callBet) {
|
||||
if(pg->community.size() == 0 && amount > callBet) {
|
||||
if(random > 5) amount = callBet;
|
||||
}
|
||||
|
||||
@ -233,7 +240,7 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
amount = callBet;
|
||||
}
|
||||
|
||||
amount = mathMax<int32_t>(amount, callBet);
|
||||
amount = Math::max<int32_t>(amount, callBet);
|
||||
turn = PokerTurn::bet(this, amount);
|
||||
turn.confidence = confidence;
|
||||
} else if(this->canCheck()) {
|
||||
@ -248,13 +255,17 @@ struct PokerTurn PokerPlayer::getAITurn() {
|
||||
}
|
||||
|
||||
int32_t PokerPlayer::getCallBet() {
|
||||
return this->pokerGame->getCurrentCallValue() - this->currentBet;
|
||||
auto pg = this->pokerGame.lock();
|
||||
assertNotNull(pg, "PokerGame has become invalid.");
|
||||
return pg->getCurrentCallValue() - this->currentBet;
|
||||
}
|
||||
|
||||
int32_t PokerPlayer::getSumOfChips() {
|
||||
auto pg = this->pokerGame.lock();
|
||||
assertNotNull(pg, "PokerGame has become invalid.");
|
||||
int32_t count = 0;
|
||||
auto it = this->pokerGame->pots.begin();
|
||||
while(it != this->pokerGame->pots.end()) {
|
||||
auto it = pg->pots.begin();
|
||||
while(it != pg->pots.end()) {
|
||||
if(std::find(it->players.begin(), it->players.end(), this) != it->players.end()) {
|
||||
count += it->chips;
|
||||
}
|
||||
@ -272,16 +283,19 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
enum CardSuit suit;
|
||||
std::vector<struct Card> pairs;
|
||||
|
||||
winning.player = this;
|
||||
auto pg = this->pokerGame.lock();
|
||||
assertNotNull(pg, "PokerGame has become invalid.");
|
||||
|
||||
winning.player = shared_from_this();
|
||||
|
||||
// Get the full poker hand (should be a 7 card hand, but MAY not be)
|
||||
for(i = 0; i < this->pokerGame->community.size(); i++) {
|
||||
winning.full.push_back(this->pokerGame->community[i]);
|
||||
for(i = 0; i < pg->community.size(); i++) {
|
||||
winning.full.push_back(pg->community[i]);
|
||||
}
|
||||
for(i = 0; i < this->hand.size(); i++) {
|
||||
winning.full.push_back(this->hand[i]);
|
||||
}
|
||||
Card::sort(&winning.full);
|
||||
Card::sort(winning.full);
|
||||
|
||||
//////////////////////// Now look for the winning set ////////////////////////
|
||||
|
||||
@ -289,7 +303,7 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
for(i = 0; i < winning.full.size(); i++) {
|
||||
card = winning.full[i];
|
||||
number = card.getValue();
|
||||
if(number < CARD_FIVE) continue;
|
||||
if(number < CardValue::Five) continue;
|
||||
|
||||
suit = card.getSuit();
|
||||
|
||||
@ -300,11 +314,11 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
for(j = 1; j <= 4; j++) {
|
||||
// Ace low.
|
||||
look = (
|
||||
number == CARD_FIVE && j == 4 ?
|
||||
(enum CardValue)CARD_ACE :
|
||||
(enum CardValue)(number - j)
|
||||
number == CardValue::Five && j == 4 ?
|
||||
(enum CardValue)CardValue::Ace :
|
||||
(enum CardValue)((uint8_t)number - j)
|
||||
);
|
||||
index = Card::contains(&winning.full, Card(suit, look));
|
||||
index = Card::contains(winning.full, Card(suit, look));
|
||||
if(index == -1) break;
|
||||
winning.set.push_back(winning.full[index]);
|
||||
}
|
||||
@ -314,8 +328,8 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
|
||||
// Add self to array
|
||||
winning.type = (
|
||||
number == CARD_ACE ? POKER_WINNING_TYPE_ROYAL_FLUSH :
|
||||
POKER_WINNING_TYPE_STRAIGHT_FLUSH
|
||||
number == CardValue::Ace ? PokerWinningType::RoyalFlush :
|
||||
PokerWinningType::StraightFlush
|
||||
);
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
@ -325,11 +339,11 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
for(i = 0; i < winning.full.size(); i++) {
|
||||
card = winning.full[i];
|
||||
number = card.getValue();
|
||||
pairs = Card::countPairs(&winning.full, number);
|
||||
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;
|
||||
winning.type = PokerWinningType::FourOfAKind;
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
}
|
||||
@ -339,12 +353,12 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
for(i = 0; i < winning.full.size(); i++) {
|
||||
// Check we haven't already added this card.
|
||||
card = winning.full[i];
|
||||
if(Card::contains(&winning.set, card) != -1) {
|
||||
if(Card::contains(winning.set, card) != -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
number = card.getValue();
|
||||
pairs = Card::countPairs(&winning.full, number);
|
||||
pairs = Card::countPairs(winning.full, number);
|
||||
|
||||
// Did we find either two pair or three pair?
|
||||
if(pairs.size() != 2 && pairs.size() != 3) continue;
|
||||
@ -359,7 +373,7 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
|
||||
// Winned?
|
||||
if(winning.set.size() != POKER_WINNING_SET_SIZE) continue;
|
||||
winning.type = POKER_WINNING_TYPE_FULL_HOUSE;
|
||||
winning.type = PokerWinningType::FullHouse;
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
}
|
||||
@ -378,7 +392,7 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
if(winning.set.size() == POKER_WINNING_SET_SIZE) break;
|
||||
}
|
||||
if(winning.set.size() < POKER_WINNING_SET_SIZE) continue;
|
||||
winning.type = POKER_WINNING_TYPE_FLUSH;
|
||||
winning.type = PokerWinningType::Flush;
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
}
|
||||
@ -387,7 +401,7 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
for(i = 0; i < winning.full.size(); i++) {
|
||||
card = winning.full[i];
|
||||
number = card.getValue();
|
||||
if(number < CARD_FIVE) continue;
|
||||
if(number < CardValue::Five) continue;
|
||||
|
||||
winning.set.clear();
|
||||
winning.set.push_back(card);
|
||||
@ -395,18 +409,18 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
for(j = 1; j <= 4; j++) {
|
||||
// Ace low.
|
||||
look = (
|
||||
number == CARD_FIVE && j == 4 ?
|
||||
(enum CardValue)CARD_ACE :
|
||||
(enum CardValue)(number - j)
|
||||
number == CardValue::Five && j == 4 ?
|
||||
(enum CardValue)CardValue::Ace :
|
||||
(enum CardValue)((uint8_t)number - j)
|
||||
);
|
||||
index = Card::containsNumber(&winning.full, look);
|
||||
index = Card::containsValue(winning.full, look);
|
||||
if(index == -1) break;
|
||||
winning.set.push_back(winning.full[index]);
|
||||
}
|
||||
|
||||
// Check if has all necessary cards.
|
||||
if(winning.set.size() < POKER_WINNING_SET_SIZE) continue;
|
||||
winning.type = POKER_WINNING_TYPE_STRAIGHT;
|
||||
winning.type = PokerWinningType::Straight;
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
}
|
||||
@ -415,11 +429,11 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
for(i = 0; i < winning.full.size(); i++) {
|
||||
card = winning.full[i];
|
||||
number = card.getValue();
|
||||
pairs = Card::countPairs(&winning.full, number);
|
||||
pairs = Card::countPairs(winning.full, number);
|
||||
if(pairs.size() != 3) continue;
|
||||
|
||||
winning.set = pairs;
|
||||
winning.type = POKER_WINNING_TYPE_THREE_OF_A_KIND;
|
||||
winning.type = PokerWinningType::ThreeOfAKind;
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
}
|
||||
@ -430,26 +444,26 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
card = winning.full[i];// Check we haven't already added this card.
|
||||
if(
|
||||
winning.set.size() > 0 &&
|
||||
Card::contains(&winning.set, card) != -1
|
||||
Card::contains(winning.set, card) != -1
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
number = card.getValue();
|
||||
pairs = Card::countPairs(&winning.full, number);
|
||||
pairs = Card::countPairs(winning.full, number);
|
||||
if(pairs.size() != 2) continue;
|
||||
for(j = 0; j < pairs.size(); j++) {
|
||||
winning.set.push_back(pairs[j]);
|
||||
}
|
||||
if(winning.set.size() != 4) continue;
|
||||
winning.type = POKER_WINNING_TYPE_TWO_PAIR;
|
||||
winning.type = PokerWinningType::TwoPair;
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
}
|
||||
|
||||
// Pair
|
||||
if(winning.set.size() == 2) {
|
||||
winning.type = POKER_WINNING_TYPE_PAIR;
|
||||
winning.type = PokerWinningType::Pair;
|
||||
winning.fillRemaining();
|
||||
return winning;
|
||||
}
|
||||
@ -457,6 +471,6 @@ struct PokerWinning PokerPlayer::getWinning() {
|
||||
// High card
|
||||
winning.set.clear();
|
||||
winning.fillRemaining();
|
||||
winning.type = POKER_WINNING_TYPE_HIGH_CARD;
|
||||
winning.type = PokerWinningType::HighCard;
|
||||
return winning;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
namespace Dawn {
|
||||
class PokerGame;
|
||||
|
||||
class PokerPlayer {
|
||||
class PokerPlayer : public std::enable_shared_from_this<PokerPlayer> {
|
||||
public:
|
||||
std::weak_ptr<PokerGame> pokerGame;
|
||||
int32_t chips = 0;
|
||||
@ -69,7 +69,7 @@ namespace Dawn {
|
||||
* @param pot Poker pot to bet in to.
|
||||
* @param amount The amount of chips the player is betting.
|
||||
*/
|
||||
void bet(struct PokerPot pot, const int32_t amount);
|
||||
void bet(struct PokerPot &pot, const int32_t amount);
|
||||
|
||||
/**
|
||||
* Let a player bet chips into the current pot.
|
||||
|
@ -21,7 +21,7 @@ void PokerPotWinning::award() {
|
||||
}
|
||||
}
|
||||
|
||||
struct PokerPotWinning PokerPot::getWinners(PokerGame *game) {
|
||||
struct PokerPotWinning PokerPot::getWinners() {
|
||||
struct PokerPotWinning winning;
|
||||
|
||||
winning.pot = this;
|
||||
@ -47,8 +47,8 @@ struct PokerPotWinning PokerPot::getWinners(PokerGame *game) {
|
||||
auto playerLeft = *it2;
|
||||
auto winnerLeft = &winning.winnings[playerLeft];
|
||||
bool_t isWinner = true;
|
||||
enum CardValue highNumber = CARD_VALUE_INVALD;
|
||||
enum CardValue number = CARD_VALUE_INVALD;
|
||||
enum CardValue highNumber = CardValue::Invalid;
|
||||
enum CardValue number = CardValue::Invalid;
|
||||
struct Card highCard(0xFF);
|
||||
struct Card card(0xFF);
|
||||
|
||||
@ -82,8 +82,8 @@ struct PokerPotWinning PokerPot::getWinners(PokerGame *game) {
|
||||
// Determine high card.
|
||||
number = card.getValue();
|
||||
if(
|
||||
highNumber == CARD_VALUE_INVALD ||
|
||||
number == CARD_ACE ||
|
||||
highNumber == CardValue::Invalid ||
|
||||
number == CardValue::Ace ||
|
||||
number > highNumber
|
||||
) {
|
||||
highCard = card;
|
||||
|
@ -13,9 +13,9 @@ namespace Dawn {
|
||||
|
||||
struct PokerPotWinning {
|
||||
public:
|
||||
std::map<PokerPlayer*,struct PokerWinning> winnings;
|
||||
std::vector<PokerPlayer*> winners;
|
||||
std::vector<PokerPlayer*> participants;
|
||||
std::map<std::shared_ptr<PokerPlayer>, struct PokerWinning> winnings;
|
||||
std::vector<std::shared_ptr<PokerPlayer>> winners;
|
||||
std::vector<std::shared_ptr<PokerPlayer>> participants;
|
||||
struct PokerPot *pot;
|
||||
int32_t chipsEach;
|
||||
int32_t chipsOverflow;
|
||||
@ -27,8 +27,13 @@ namespace Dawn {
|
||||
public:
|
||||
int32_t chips;
|
||||
int32_t call;
|
||||
std::vector<PokerPlayer*> players;
|
||||
std::vector<std::shared_ptr<PokerPlayer>> players;
|
||||
|
||||
struct PokerPotWinning getWinners(PokerGame *game);
|
||||
/**
|
||||
* Get the winners of the pot.
|
||||
*
|
||||
* @return The winning state of the pot.
|
||||
*/
|
||||
struct PokerPotWinning getWinners();
|
||||
};
|
||||
}
|
@ -10,23 +10,23 @@ using namespace Dawn;
|
||||
|
||||
float_t PokerWinning::getWinningTypeConfidence(enum PokerWinningType type) {
|
||||
switch(type) {
|
||||
case POKER_WINNING_TYPE_ROYAL_FLUSH:
|
||||
case PokerWinningType::RoyalFlush:
|
||||
return POKER_WINNING_CONFIDENCE_ROYAL_FLUSH;
|
||||
case POKER_WINNING_TYPE_STRAIGHT_FLUSH:
|
||||
case PokerWinningType::StraightFlush:
|
||||
return POKER_WINNING_CONFIDENCE_STRAIGHT_FLUSH;
|
||||
case POKER_WINNING_TYPE_FOUR_OF_A_KIND:
|
||||
case PokerWinningType::FourOfAKind:
|
||||
return POKER_WINNING_CONFIDENCE_FOUR_OF_A_KIND;
|
||||
case POKER_WINNING_TYPE_FULL_HOUSE:
|
||||
case PokerWinningType::FullHouse:
|
||||
return POKER_WINNING_CONFIDENCE_FULL_HOUSE;
|
||||
case POKER_WINNING_TYPE_FLUSH:
|
||||
case PokerWinningType::Flush:
|
||||
return POKER_WINNING_CONFIDENCE_FLUSH;
|
||||
case POKER_WINNING_TYPE_STRAIGHT:
|
||||
case PokerWinningType::Straight:
|
||||
return POKER_WINNING_CONFIDENCE_STRAIGHT;
|
||||
case POKER_WINNING_TYPE_THREE_OF_A_KIND:
|
||||
case PokerWinningType::ThreeOfAKind:
|
||||
return POKER_WINNING_CONFIDENCE_THREE_OF_A_KIND;
|
||||
case POKER_WINNING_TYPE_TWO_PAIR:
|
||||
case PokerWinningType::TwoPair:
|
||||
return POKER_WINNING_CONFIDENCE_TWO_PAIR;
|
||||
case POKER_WINNING_TYPE_PAIR:
|
||||
case PokerWinningType::Pair:
|
||||
return POKER_WINNING_CONFIDENCE_PAIR;
|
||||
default:
|
||||
return POKER_WINNING_CONFIDENCE_HIGH_CARD;
|
||||
@ -34,34 +34,31 @@ float_t PokerWinning::getWinningTypeConfidence(enum PokerWinningType type) {
|
||||
}
|
||||
|
||||
struct Card PokerWinning::compare(
|
||||
struct PokerWinning *left,
|
||||
struct PokerWinning *right
|
||||
const struct PokerWinning &left,
|
||||
const struct PokerWinning &right
|
||||
) {
|
||||
assertNotNull(left);
|
||||
assertNotNull(right);
|
||||
|
||||
uint8_t i;
|
||||
enum CardValue number = CARD_VALUE_INVALD;
|
||||
enum CardValue highNumberLeft = CARD_VALUE_INVALD;
|
||||
enum CardValue highNumberRight = CARD_VALUE_INVALD;
|
||||
enum CardValue number = CardValue::Invalid;
|
||||
enum CardValue highNumberLeft = CardValue::Invalid;
|
||||
enum CardValue highNumberRight = CardValue::Invalid;
|
||||
struct Card card(0xFF), highCardLeft(0xFF), highCardRight(0xFF);
|
||||
int32_t index;
|
||||
uint8_t countCardsSame;
|
||||
|
||||
countCardsSame = 0;
|
||||
|
||||
for(i = 0; i < left->set.size(); i++) {
|
||||
card = left->set[i];
|
||||
for(i = 0; i < left.set.size(); i++) {
|
||||
card = left.set[i];
|
||||
number = card.getValue();
|
||||
// Quick check
|
||||
if(highNumberLeft != CARD_VALUE_INVALD && number < highNumberLeft) continue;
|
||||
if(highNumberLeft != CardValue::Invalid && number < highNumberLeft) continue;
|
||||
|
||||
// Check if this number is within the other hand or not
|
||||
index = Card::containsNumber(&right->set, number);
|
||||
index = Card::containsValue(right.set, number);
|
||||
if(index != -1) {
|
||||
// This number IS within the other hand, let's check that the EXACT card
|
||||
// is a match/isn't a match.
|
||||
index = Card::contains(&right->set, card);
|
||||
index = Card::contains(right.set, card);
|
||||
|
||||
// Exact card match
|
||||
if(index != -1) {
|
||||
@ -72,8 +69,8 @@ struct Card PokerWinning::compare(
|
||||
}
|
||||
|
||||
if(
|
||||
highNumberLeft == CARD_VALUE_INVALD ||
|
||||
number == CARD_ACE ||
|
||||
highNumberLeft == CardValue::Invalid ||
|
||||
number == CardValue::Ace ||
|
||||
highNumberLeft < number
|
||||
) {
|
||||
highNumberLeft = number;
|
||||
@ -81,22 +78,22 @@ struct Card PokerWinning::compare(
|
||||
}
|
||||
}
|
||||
|
||||
for(i = 0; i < right->set.size(); i++) {
|
||||
card = right->set[i];
|
||||
for(i = 0; i < right.set.size(); i++) {
|
||||
card = right.set[i];
|
||||
number = card.getValue();
|
||||
if(highNumberRight != CARD_VALUE_INVALD && number < highNumberRight) {
|
||||
if(highNumberRight != CardValue::Invalid && number < highNumberRight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
index = Card::containsNumber(&left->set, number);
|
||||
index = Card::containsValue(left.set, number);
|
||||
if(index != -1) {
|
||||
index = Card::contains(&left->set, card);
|
||||
index = Card::contains(left.set, card);
|
||||
if(index != -1) continue;
|
||||
}
|
||||
|
||||
if(
|
||||
highNumberRight == CARD_VALUE_INVALD ||
|
||||
number == CARD_ACE || highNumberRight < number
|
||||
highNumberRight == CardValue::Invalid ||
|
||||
number == CardValue::Ace || highNumberRight < number
|
||||
) {
|
||||
highNumberRight = number;
|
||||
highCardRight = card;
|
||||
@ -104,13 +101,13 @@ struct Card PokerWinning::compare(
|
||||
}
|
||||
|
||||
|
||||
if(countCardsSame == left->set.size()) {
|
||||
for(i = 0; i < left->set.size(); i++) {
|
||||
card = left->set[i];
|
||||
if(countCardsSame == left.set.size()) {
|
||||
for(i = 0; i < left.set.size(); i++) {
|
||||
card = left.set[i];
|
||||
number = card.getValue();
|
||||
if(
|
||||
highNumberLeft == CARD_VALUE_INVALD ||
|
||||
number == CARD_ACE ||
|
||||
highNumberLeft == CardValue::Invalid ||
|
||||
number == CardValue::Ace ||
|
||||
highNumberLeft < number
|
||||
) {
|
||||
highNumberLeft = number;
|
||||
@ -120,13 +117,14 @@ struct Card PokerWinning::compare(
|
||||
return highCardLeft;
|
||||
}
|
||||
|
||||
if(highCardLeft.cardValue == CARD_VALUE_INVALD) return 0xFF;
|
||||
if(highCardLeft.cardValue == 0xFF) return 0xFF;
|
||||
if(highNumberLeft < highNumberRight) return 0xFF;
|
||||
return highCardLeft;// Greater or Equal to.
|
||||
}
|
||||
|
||||
void PokerWinning::fillRemaining() {
|
||||
uint8_t i, highest, current;
|
||||
uint8_t i;
|
||||
CardValue highest, current;
|
||||
struct Card highestCard(0x00);
|
||||
struct Card currentCard(0x00);
|
||||
|
||||
@ -135,25 +133,25 @@ void PokerWinning::fillRemaining() {
|
||||
|
||||
// Fill the remaining cards
|
||||
while(this->set.size() < POKER_WINNING_SET_SIZE) {
|
||||
highest = 0xFF;
|
||||
highest = CardValue::Invalid;
|
||||
|
||||
for(i = 0; i < this->full.size(); i++) {
|
||||
currentCard = this->full[i];
|
||||
if(Card::contains(&this->set, currentCard) != -1) continue;
|
||||
if(Card::contains(this->set, currentCard) != -1) continue;
|
||||
|
||||
if(highest == 0xFF) {
|
||||
if(highest == CardValue::Invalid) {
|
||||
highestCard = currentCard;
|
||||
highest = highestCard.getValue();
|
||||
} else {
|
||||
current = currentCard.getValue();
|
||||
if(current != CARD_ACE && current < highest) continue;
|
||||
if(current != CardValue::Ace && current < highest) continue;
|
||||
highestCard = currentCard;
|
||||
highest = current;
|
||||
}
|
||||
}
|
||||
|
||||
if(highest == 0xFF) break;
|
||||
if(highest == CardValue::Invalid) break;
|
||||
this->set.push_back(highestCard);
|
||||
}
|
||||
Card::sort(&this->set);
|
||||
Card::sort(this->set);
|
||||
}
|
@ -24,18 +24,18 @@
|
||||
namespace Dawn {
|
||||
class PokerPlayer;
|
||||
|
||||
enum PokerWinningType {
|
||||
POKER_WINNING_TYPE_NULL,
|
||||
POKER_WINNING_TYPE_ROYAL_FLUSH,
|
||||
POKER_WINNING_TYPE_STRAIGHT_FLUSH,
|
||||
POKER_WINNING_TYPE_FOUR_OF_A_KIND,
|
||||
POKER_WINNING_TYPE_FULL_HOUSE,
|
||||
POKER_WINNING_TYPE_FLUSH,
|
||||
POKER_WINNING_TYPE_STRAIGHT,
|
||||
POKER_WINNING_TYPE_THREE_OF_A_KIND,
|
||||
POKER_WINNING_TYPE_TWO_PAIR,
|
||||
POKER_WINNING_TYPE_PAIR,
|
||||
POKER_WINNING_TYPE_HIGH_CARD
|
||||
enum class PokerWinningType {
|
||||
Null,
|
||||
RoyalFlush,
|
||||
StraightFlush,
|
||||
FourOfAKind,
|
||||
FullHouse,
|
||||
Flush,
|
||||
Straight,
|
||||
ThreeOfAKind,
|
||||
TwoPair,
|
||||
Pair,
|
||||
HighCard
|
||||
};
|
||||
|
||||
struct PokerWinning {
|
||||
@ -57,8 +57,8 @@ namespace Dawn {
|
||||
* @return The kicker card from left's hand or 0xFF if not the winner.
|
||||
*/
|
||||
static struct Card compare(
|
||||
struct PokerWinning *left,
|
||||
struct PokerWinning *right
|
||||
const struct PokerWinning &left,
|
||||
const struct PokerWinning &right
|
||||
);
|
||||
|
||||
/** Winning Type */
|
||||
@ -70,7 +70,7 @@ namespace Dawn {
|
||||
/** If there was a kicker card it will be here */
|
||||
struct Card kicker;
|
||||
/* The player this winning state belongs to */
|
||||
PokerPlayer *player;
|
||||
std::shared_ptr<PokerPlayer> player;
|
||||
|
||||
PokerWinning() : kicker(0xFF) {}
|
||||
|
||||
|
Reference in New Issue
Block a user