476 lines
14 KiB
C
476 lines
14 KiB
C
/**
|
|
* Copyright (c) 2021 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#pragma once
|
|
#include "../libs.h"
|
|
#include "../util/flags.h"
|
|
#include "../util/array.h"
|
|
#include "../util/math.h"
|
|
#include "card.h"
|
|
|
|
/** Maximum number of players that the game state can support */
|
|
#define POKER_PLAYER_COUNT_MAX 5
|
|
/** Maximum cards a players' hand can hold */
|
|
#define POKER_PLAYER_HAND_SIZE_MAX 2
|
|
|
|
/** Player States */
|
|
#define POKER_PLAYER_STATE_FOLDED flagDefine(0)
|
|
#define POKER_PLAYER_STATE_OUT flagDefine(1)
|
|
#define POKER_PLAYER_STATE_HAS_BET_THIS_ROUND flagDefine(2)
|
|
#define POKER_PLAYER_STATE_SHOWING flagDefine(3)
|
|
|
|
/** Maximum number of cards that the grave can hold */
|
|
#define POKER_GRAVE_SIZE_MAX CARD_DECK_SIZE
|
|
|
|
/** Maximum number of community cards */
|
|
#define POKER_COMMUNITY_SIZE_MAX 5
|
|
|
|
/** Maximum number of pots in the poker game. */
|
|
#define POKER_POT_COUNT_MAX POKER_PLAYER_COUNT_MAX
|
|
|
|
/** Maximum number of cards a winning state can hold. */
|
|
#define POKER_WINNING_FULL_SIZE (\
|
|
POKER_PLAYER_HAND_SIZE_MAX + POKER_COMMUNITY_SIZE_MAX\
|
|
)
|
|
|
|
/** How many cards in the winning set */
|
|
#define POKER_WINNING_SET_SIZE 5
|
|
|
|
/** Winning Types */
|
|
#define POKER_WINNING_TYPE_NULL 0x00
|
|
#define POKER_WINNING_TYPE_ROYAL_FLUSH 0x01
|
|
#define POKER_WINNING_TYPE_STRAIGHT_FLUSH 0x02
|
|
#define POKER_WINNING_TYPE_FOUR_OF_A_KIND 0x03
|
|
#define POKER_WINNING_TYPE_FULL_HOUSE 0x04
|
|
#define POKER_WINNING_TYPE_FLUSH 0x05
|
|
#define POKER_WINNING_TYPE_STRAIGHT 0x06
|
|
#define POKER_WINNING_TYPE_THREE_OF_A_KIND 0x07
|
|
#define POKER_WINNING_TYPE_TWO_PAIR 0x08
|
|
#define POKER_WINNING_TYPE_PAIR 0x09
|
|
#define POKER_WINNING_TYPE_HIGH_CARD 0x0A
|
|
|
|
#define POKER_WINNING_CONFIDENCE_ROYAL_FLUSH 1.0f
|
|
#define POKER_WINNING_CONFIDENCE_STRAIGHT_FLUSH 0.99f
|
|
#define POKER_WINNING_CONFIDENCE_FOUR_OF_A_KIND 0.9f
|
|
#define POKER_WINNING_CONFIDENCE_FULL_HOUSE 0.85f
|
|
#define POKER_WINNING_CONFIDENCE_FLUSH 0.8f
|
|
#define POKER_WINNING_CONFIDENCE_STRAIGHT 0.7f
|
|
#define POKER_WINNING_CONFIDENCE_THREE_OF_A_KIND 0.5f
|
|
#define POKER_WINNING_CONFIDENCE_TWO_PAIR 0.4f
|
|
#define POKER_WINNING_CONFIDENCE_PAIR 0.2f
|
|
#define POKER_WINNING_CONFIDENCE_HIGH_CARD 0.1f
|
|
|
|
#define POKER_WORLD_DEALER_INDEX 0x02
|
|
#define POKER_WORLD_HUMAN_INDEX 0x02
|
|
|
|
/** Turn Types */
|
|
#define POKER_TURN_TYPE_OUT 0x00
|
|
#define POKER_TURN_TYPE_FOLD 0x01
|
|
#define POKER_TURN_TYPE_BET 0x02
|
|
#define POKER_TURN_TYPE_CALL 0x03
|
|
#define POKER_TURN_TYPE_ALL_IN 0x04
|
|
#define POKER_TURN_TYPE_CALL_ALL_IN 0x04
|
|
#define POKER_TURN_TYPE_CHECK 0x05
|
|
|
|
/** How many chips each player has by defautl */
|
|
#define POKER_BET_PLAYER_CHIPS_DEFAULT 1200
|
|
|
|
/** The default blind cost for the big blind. */
|
|
#define POKER_BET_BLIND_BIG_DEFAULT 600
|
|
|
|
/** The default blind cost for the small blind. (Defaults half big blind) */
|
|
#define POKER_BET_BLIND_SMALL_DEFAULT (POKER_BET_BLIND_BIG_DEFAULT/2)
|
|
|
|
/** How many cards are dealt for the flop, turn and river */
|
|
#define POKER_FLOP_CARD_COUNT 3
|
|
#define POKER_TURN_CARD_COUNT 1
|
|
#define POKER_RIVER_CARD_COUNT 1
|
|
|
|
typedef struct {
|
|
/** Count of chips the player has */
|
|
int32_t chips;
|
|
|
|
/** Cards in the players' hand */
|
|
card_t cards[POKER_PLAYER_HAND_SIZE_MAX];
|
|
uint8_t cardCount;
|
|
|
|
/** Players current state */
|
|
uint8_t state;
|
|
|
|
/** Current bet that the player has done. */
|
|
int32_t currentBet;
|
|
} pokerplayer_t;
|
|
|
|
/** Holds information about a player's winning state */
|
|
typedef struct {
|
|
/** The full set of both the dealer and player's hand */
|
|
card_t full[POKER_WINNING_FULL_SIZE];
|
|
uint8_t fullSize;
|
|
|
|
/** Holds the winning set */
|
|
card_t set[POKER_WINNING_SET_SIZE];
|
|
uint8_t setSize;
|
|
|
|
/** Winning Type */
|
|
uint8_t type;
|
|
|
|
/** If there was a kicker card it will be here, otherwise -1 for no kicker */
|
|
card_t kicker;
|
|
} pokerplayerwinning_t;
|
|
|
|
typedef struct {
|
|
/** Current pot of chips */
|
|
int32_t chips;
|
|
/** Players who are participating in the pot */
|
|
uint8_t players[POKER_PLAYER_COUNT_MAX];
|
|
uint8_t playerCount;
|
|
} pokerpot_t;
|
|
|
|
typedef struct {
|
|
/** What type of action the turn is */
|
|
uint8_t type;
|
|
/** How many chips they did in their turn (if applicable) */
|
|
int32_t chips;
|
|
/** How confident the AI is about their turn. 0 = none, 1 = full */
|
|
float confidence;
|
|
} pokerturn_t;
|
|
|
|
typedef struct {
|
|
/** Current Card Deck (Dealer) */
|
|
card_t deck[CARD_DECK_SIZE];
|
|
uint8_t deckSize;
|
|
|
|
/** Card grave (where spent cards go when burned */
|
|
card_t grave[POKER_GRAVE_SIZE_MAX];
|
|
uint8_t graveSize;
|
|
|
|
/** Dealer Hand */
|
|
card_t community[POKER_COMMUNITY_SIZE_MAX];
|
|
uint8_t communitySize;
|
|
|
|
/** List of pots in the game (side pots) */
|
|
pokerpot_t pots[POKER_POT_COUNT_MAX];
|
|
uint8_t potCount;
|
|
|
|
/** Players within the game */
|
|
pokerplayer_t players[POKER_PLAYER_COUNT_MAX];
|
|
uint8_t playerCount;
|
|
|
|
/** Index of the dealer player */
|
|
uint8_t playerDealer;
|
|
/** Index of the small blind player */
|
|
uint8_t playerSmallBlind;
|
|
/** Index of the big blind player */
|
|
uint8_t playerBigBlind;
|
|
|
|
/** Which player is the current active better ? */
|
|
uint8_t better;
|
|
} poker_t;
|
|
|
|
|
|
/**
|
|
* Initialize the poker game instance.
|
|
*
|
|
* @param poker Poker game instance.
|
|
*/
|
|
void pokerInit(poker_t *poker);
|
|
|
|
/**
|
|
* Reset the poker game instance for the new round.
|
|
*
|
|
* @param poker Poker game instance.
|
|
*/
|
|
void pokerResetRound(poker_t *poker);
|
|
|
|
/**
|
|
* Reset the poker betting round.
|
|
*
|
|
* @param poker Poker game instance to reset for.
|
|
*/
|
|
void pokerResetBettingRound(poker_t *poker);
|
|
|
|
/**
|
|
* Cycles to the next dealer. This will also select the new small and big blind
|
|
* players.
|
|
*
|
|
* @param poker Poker game to select a new dealer for.
|
|
*/
|
|
void pokerNewDealer(poker_t *poker);
|
|
|
|
/**
|
|
* Take the blinds from the blind players.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param small Small blind amount.
|
|
* @param big Big blind amount.
|
|
*/
|
|
void pokerTakeBlinds(poker_t *poker, int32_t small, int32_t big);
|
|
|
|
/**
|
|
* Gets the amount of chips necessary to call the current bet.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @return Chips necessary to call the current bet.
|
|
*/
|
|
int32_t pokerGetCallValue(poker_t *poker);
|
|
|
|
/**
|
|
* Adds a new pot to the poker game instance.
|
|
*
|
|
* @param poker Poker game instance to add a pot to.
|
|
* @return The index of the pot within the array of pots.
|
|
*/
|
|
uint8_t pokerPotAdd(poker_t *poker);
|
|
|
|
/**
|
|
* Add a player to a pot. This will not let you add the same player to the pot
|
|
* twice.
|
|
*
|
|
* @param pot Pot to add to.
|
|
* @param playerIndex Players' index to add to the pot.
|
|
*/
|
|
void pokerPotAddPlayer(pokerpot_t *pot, uint8_t playerIndex);
|
|
|
|
|
|
/**
|
|
* Turns over cards from the deck onto the table (from the deck into the dealer
|
|
* hand)
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param count Count of cards to deal.
|
|
*/
|
|
void pokerTurn(poker_t *poker, uint8_t count);
|
|
|
|
|
|
/**
|
|
* Burns a set of cards off the top of the deck into the graveyard.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param count Count of cards to burn.
|
|
*/
|
|
void pokerBurn(poker_t *poker, uint8_t count);
|
|
|
|
/**
|
|
* Add a player to the game. The player starts in an out state (with no chips).
|
|
*
|
|
* @param poker Poker game instance to add to.
|
|
* @return Player index.
|
|
*/
|
|
uint8_t pokerPlayerAdd(poker_t *poker);
|
|
|
|
|
|
/**
|
|
* Deal a card to a player.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param player Poker player to deal to.
|
|
* @param count Count of cards to deal to the player.
|
|
*/
|
|
void pokerPlayerDeal(poker_t *poker, pokerplayer_t *player, uint8_t count);
|
|
|
|
/**
|
|
* Add chips to a player. This will also update their state if they were out
|
|
* to ensure that they are no longer.
|
|
*
|
|
* @param player Player to add chips to.
|
|
* @param chips Amount of chips to add.
|
|
*/
|
|
void pokerPlayerChipsAdd(pokerplayer_t *player, int32_t chips);
|
|
|
|
/**
|
|
* Deal card(s) to every active player.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param count Count of cards to deal.
|
|
*/
|
|
void pokerPlayerDealAll(poker_t *poker, uint8_t count);
|
|
|
|
/**
|
|
* Checks a players' state and decided whether or not the players still needs to
|
|
* bet for the current round. This will check both whether the player has bet in
|
|
* the current round yet, and whether or not they have met the call value of the
|
|
* active pot.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param playerIndex Player index to check.
|
|
* @return
|
|
*/
|
|
bool pokerPlayerDoesNeedToBetThisRound(poker_t *poker, uint8_t playerIndex);
|
|
|
|
|
|
/**
|
|
* Returns the index of the first player that remains to bet for the current
|
|
* round.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @return The player index of the remaining player, otherwise 0xFF.
|
|
*/
|
|
uint8_t pokerPlayerGetRemainingBetter(poker_t *poker);
|
|
|
|
/**
|
|
* Returns the index of the first player that remains to bet for the current
|
|
* round. This is based on whatever current better player index you provide.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param current Current better player index.
|
|
* @return The player index of the next remaining player, otherwise 0xFF.
|
|
*/
|
|
uint8_t pokerPlayerGetNextBetter(poker_t *poker, uint8_t current);
|
|
|
|
/**
|
|
* Get the bet necessary for a specific player to make a call. This takes the
|
|
* players current bet and the bet necessary to call into the pot and will
|
|
* return the difference.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param player Player instance to get the call value for.
|
|
* @return The count of chips needed to call into the current active pot.
|
|
*/
|
|
int32_t pokerPlayerGetCallBet(poker_t *poker, pokerplayer_t *player);
|
|
|
|
/**
|
|
* Gets the count of players still currently left in the round.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @return The count of players in the round.
|
|
*/
|
|
uint8_t pokerInRoundGetCount(poker_t *poker);
|
|
|
|
/**
|
|
* Returns the count of players remaining to bet.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @return Count of players left to bet.
|
|
*/
|
|
uint8_t pokerPlayerGetRemainingBetterCount(poker_t *poker);
|
|
|
|
/**
|
|
* Let a player bet chips into the pot.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param pot Poker pot to bet in to.
|
|
* @param playerIndex The players' index that is betting.
|
|
* @param chips The amount of chips the player is betting.
|
|
*/
|
|
void pokerPlayerBetPot(
|
|
poker_t *poker, pokerpot_t *pot, uint8_t playerIndex, int32_t chips
|
|
);
|
|
|
|
/**
|
|
* Let a player bet chips into the current pot.
|
|
*
|
|
* @param bet Poker game instance.
|
|
* @param playerIndex The players' index that is betting.
|
|
* @param chips The amount of chips the player is betting.
|
|
*/
|
|
void pokerPlayerBet(poker_t *poker, uint8_t playerIndex, int32_t chips);
|
|
|
|
|
|
/**
|
|
* Determine whether or not a player CAN check, given the current max bet and
|
|
* the players current bet.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param player Player to check.
|
|
* @return True if the player can check, false if they need to call first.
|
|
*/
|
|
bool pokerPlayerCanCheck(poker_t *poker, pokerplayer_t *player);
|
|
|
|
/**
|
|
* Return a turn action for the given player to fold.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param player Player index.
|
|
* @return A turn for a fold action.
|
|
*/
|
|
pokerturn_t pokerTurnFold(poker_t *poker, uint8_t player);
|
|
|
|
/**
|
|
* Perform a turn action for betting as a player.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param playerIndex Player index who is betting.
|
|
* @param chips Chips to raise by.
|
|
* @return A turn for a bet action.
|
|
*/
|
|
pokerturn_t pokerTurnBet(poker_t *poker, uint8_t playerIndex, int32_t chips);
|
|
|
|
/**
|
|
* Returns the AI result for a turn done by a non human player.
|
|
*
|
|
* @param poker Poker game instance to use.
|
|
* @param playerIndex Player index to get the turn for.
|
|
* @return Some information about the move the player is trying to perform.
|
|
*/
|
|
pokerturn_t pokerTurnGetForPlayer(poker_t *poker, uint8_t playerIndex);
|
|
|
|
/**
|
|
* Returns the full hand for a given player including the best cards on the
|
|
* bench.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param player Poker player to get the hand for.
|
|
* @param cards Array to store the cards.
|
|
*/
|
|
void pokerHandGetFull(
|
|
poker_t *poker, pokerplayer_t *player, card_t cards[POKER_WINNING_FULL_SIZE]
|
|
);
|
|
|
|
/**
|
|
* Fills the remaining cards for a given poker player winning hand. Essentially
|
|
* this will just take the highest cards and slot them into the array. This also
|
|
* sorts the cards.
|
|
*
|
|
* @param winning Pointer to the poker winning to fill out.
|
|
*/
|
|
void pokerWinnerFillRemaining(pokerplayerwinning_t *winning);
|
|
|
|
/**
|
|
* Calculates and returns the winning state for a given player
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param player Player to get the state for.
|
|
* @param winning Output winning state struct to push data in to.
|
|
*/
|
|
void pokerWinnerGetForPlayer(
|
|
poker_t *poker, pokerplayer_t *player, pokerplayerwinning_t *winning
|
|
);
|
|
|
|
/**
|
|
* Compares two winning sets. The returned card is the kicker if the LEFT side
|
|
* is the winner. If LEFT is not a winner then 0xFF will be returned.
|
|
*
|
|
* @param left Left winning set.
|
|
* @param right Right winning set.
|
|
* @return The kicker card from left's hand or 0xFF if left is not the winner.
|
|
*/
|
|
card_t pokerWinnerCompare(
|
|
pokerplayerwinning_t *left, pokerplayerwinning_t *right
|
|
);
|
|
|
|
/**
|
|
* Determines the winning player for the given pot. The pot has participating
|
|
* players, and from those participating players some will be winners. The
|
|
* participants are only the players within the pot who haven't folded or out.
|
|
*
|
|
* @param poker Poker game instance.
|
|
* @param pot Pot to get the winners for.
|
|
* @param winners Array to store the winner state in.
|
|
* @param winnerPlayers Array to store player indexes of each of the winners.
|
|
* @param winnerCount Pointer to store the count of winners in.
|
|
* @param participants Array to store player indexes of players who participate.
|
|
* @param participantCount Pointer to store the count of participants in.
|
|
*/
|
|
void pokerWinnerDetermineForPot(
|
|
poker_t *poker,
|
|
pokerpot_t *pot,
|
|
pokerplayerwinning_t winners[POKER_PLAYER_COUNT_MAX],
|
|
uint8_t winnerPlayers[POKER_PLAYER_COUNT_MAX],
|
|
uint8_t *winnerCount,
|
|
uint8_t participants[POKER_PLAYER_COUNT_MAX],
|
|
uint8_t *participantCount
|
|
); |