From 914741c17577ee1167e69b5ee162c72b26bbd311 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sat, 25 Sep 2021 01:36:25 -0700 Subject: [PATCH] Working on poker logic. --- src/game/poker/actions/bet.c | 28 ++++--- src/poker/bet.c | 13 +++- src/poker/bet.h | 10 +++ src/poker/turn.c | 137 ++++++++++++++++++++++++----------- src/poker/turn.h | 12 +-- src/poker/winner.c | 55 +++++++++++++- src/poker/winner.h | 41 ++++++++++- 7 files changed, 222 insertions(+), 74 deletions(-) diff --git a/src/game/poker/actions/bet.c b/src/game/poker/actions/bet.c index 7ccb853e..db0af09c 100644 --- a/src/game/poker/actions/bet.c +++ b/src/game/poker/actions/bet.c @@ -116,20 +116,24 @@ void _pokerGameActionBetOnEnd( // Not waiting, restack and do next action. printf("Not waiting on anything!\n"); - // No! Begin the next flop. - next = pokerActionNextFlopAdd(queue, &game->poker); - if(next != NULL) { - discussion.reason = POKER_DISCUSSION_REASON_FLOP; - pokerDiscussionQueue(&discussion); + // Is there a next round, or did someone just win? + if(pokerBetGetRemainingPlayerCount(&game->poker.bet,game->poker.players) > 1){ + // No! Begin the next flop. + next = pokerActionNextFlopAdd(queue, &game->poker); + if(next != NULL) { + discussion.reason = POKER_DISCUSSION_REASON_FLOP; + pokerDiscussionQueue(&discussion); - pokerBetResetBetter( - &game->poker.bet, game->poker.players, game->poker.roundSmallBlind - ); - pokerGameActionRestackAdd(game); - pokerGameActionLookAdd(game, game->poker.bet.better); - pokerGameActionBetAdd(game); - return; + pokerBetResetBetter( + &game->poker.bet, game->poker.players, game->poker.roundSmallBlind + ); + pokerGameActionRestackAdd(game); + pokerGameActionLookAdd(game, game->poker.bet.better); + pokerGameActionBetAdd(game); + return; + } } + // Done betting printf("All betting is done, reveal\n"); diff --git a/src/poker/bet.c b/src/poker/bet.c index 8ea0dcaa..c2b0cae2 100644 --- a/src/poker/bet.c +++ b/src/poker/bet.c @@ -42,8 +42,7 @@ void pokerBetResetBetter( } bool pokerBetPlayerCanBet(pokerbet_t *bet, pokerplayer_t *player) { - if((player->state & POKER_PLAYER_STATE_FOLDED) != 0) return false; - if(player->state & POKER_PLAYER_STATE_OUT) return false; + if(!pokerPlayerIsAlive(player)) return false; if(player->state & POKER_PLAYER_STATE_ROUND_MOVE) { if(player->currentBet >= bet->currentBet && player) return false; } @@ -63,6 +62,16 @@ uint8_t pokerBetGetRemainingPlayer( return 0xFF; } +uint8_t pokerBetGetRemainingPlayerCount(pokerbet_t *bet,pokerplayer_t *players){ + uint8_t i, c; + c = 0; + for(i = 0; i < POKER_PLAYER_COUNT; i++) { + if(!pokerPlayerIsAlive(players + i)) continue; + c++; + } + return c; +} + void pokerBetTakeBlinds( pokerbet_t *bet, pokerplayer_t *players, uint8_t roundSmallBlind, uint8_t roundBigBlind diff --git a/src/poker/bet.h b/src/poker/bet.h index f137e591..d2ce2758 100644 --- a/src/poker/bet.h +++ b/src/poker/bet.h @@ -96,6 +96,16 @@ uint8_t pokerBetGetRemainingPlayer( pokerbet_t *bet, pokerplayer_t *players, uint8_t roundSmallBlind ); +/** + * Returns the count of players who are still available to bet. This does not + * consider any round logic, simply whether or not they COULD bet. + * + * @param bet Betting instance + * @param players Players array. + * @return Count of players who can still bet. + */ +uint8_t pokerBetGetRemainingPlayerCount(pokerbet_t *bet,pokerplayer_t *players); + /** * Takes the current blinds from the correct players. * diff --git a/src/poker/turn.c b/src/poker/turn.c index ea547e15..eafb39e8 100644 --- a/src/poker/turn.c +++ b/src/poker/turn.c @@ -9,7 +9,12 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { pokerplayer_t *player; - float confidence; + float t, confidence, cardWeight, handWeight; + float betWeight, potWeight, inWeight, roundWeight, bet; + card_t bestCard; + uint8_t i, bestCardNumber; + int32_t chips; + player = poker->players + playerIndex; // Can the player do anything? @@ -26,45 +31,86 @@ pokerturn_t pokerTurnGet(poker_t *poker, uint8_t playerIndex) { pokerplayerwinning_t winning; pokerWinnerPlayerGet(&poker->dealer, player, &winning); - // Now let's determine the "base confidence". This is basically how good the - // hand is relative to a completely equal footing/player field. - switch(winning.type) { - case POKER_WINNING_TYPE_ROYAL_FLUSH: - confidence = POKER_TURN_CONFIDENCE_ROYAL_FLUSH; - break; - case POKER_WINNING_TYPE_STRAIGHT_FLUSH: - confidence = POKER_TURN_CONFIDENCE_STRAIGHT_FLUSH; - break; - case POKER_WINNING_TYPE_FOUR_OF_A_KIND: - confidence = POKER_TURN_CONFIDENCE_FOUR_OF_A_KIND; - break; - case POKER_WINNING_TYPE_FULL_HOUSE: - confidence = POKER_TURN_CONFIDENCE_FULL_HOUSE; - break; - case POKER_WINNING_TYPE_FLUSH: - confidence = POKER_TURN_CONFIDENCE_FLUSH; - break; - case POKER_WINNING_TYPE_STRAIGHT: - confidence = POKER_TURN_CONFIDENCE_STRAIGHT; - break; - case POKER_WINNING_TYPE_THREE_OF_A_KIND: - confidence = POKER_TURN_CONFIDENCE_THREE_OF_A_KIND; - break; - case POKER_WINNING_TYPE_TWO_PAIR: - confidence = POKER_TURN_CONFIDENCE_TWO_PAIR; - break; - case POKER_WINNING_TYPE_PAIR: - confidence = POKER_TURN_CONFIDENCE_PAIR; - break; - default: - confidence = POKER_TURN_CONFIDENCE_HIGH_CARD; - break; + // Now try and figure out how good the hand is + handWeight = 0; + for(i = 0; i < winning.setSize; i++) { + bestCard = winning.set[i]; + handWeight += pokerWinnerGetCardWeight(bestCard); } - - // Now we have a base confidence, let's figure out how good our hand is based - // on our high card. This will decide whether or not our hand is as strong as - // it seems on its base level + handWeight = handWeight / winning.setSize; + bestCard = pokerWinnerGetBestCard(winning.set, winning.setSize); + bestCardNumber = cardGetNumber(bestCard); + confidence = pokerWinnerGetTypeConfidence(winning.type); + cardWeight = pokerWinnerGetCardWeight(bestCard); + + // Now figure out what the risk of betting is. + inWeight = (float)player->currentBet / (float)player->chips; + roundWeight = ( + ((float)poker->dealer.cardsFacing) / ((float)POKER_DEALER_HAND_SIZE) + ); + betWeight = (float)( + poker->bet.currentBet - player->currentBet + ) / (float)player->chips; + potWeight = poker->bet.pot / (float)player->chips; + + + // We now need to act on these values. + printf("Card Weights - %.4f, %.4f, %.4f, %.4f\n", confidence, cardWeight, handWeight); + printf("Money Weights - %.4f, %.4f, %.4f, %.4f\n", inWeight, roundWeight, betWeight, potWeight); + + // Chip weight, 1 is all in. + bet = 0; + + if(roundWeight == 0) { + // First Round + + if(betWeight < 0.1) { + // The bet is "low risk" to me. (<10% of my chips), play a bit loose. + // Take any card with 70% weighting and/or any hand with a pair or better. + // if(cardWeight > 0.7 || confidence >= POKER_WINNNIG_CONFIDENCE_PAIR) { + // bet = confidence * 0.7f; + // } else if(cardWeight >= 0.5 && betWeight > 0) { + // } + bet = (1.0f - mathMin(betWeight*10, 0.5f)) * (cardWeight * confidence * 2.0f); + } else if(betWeight < 0.4) { + // Bet is "medium" risk to me (less than 40% of my chips) + // Bet on any hand that has a good chance. + if(confidence >= POKER_WINNNIG_CONFIDENCE_PAIR) { + bet = (confidence * mathMax(cardWeight, betWeight)); + } + } else if(betWeight < 0.75) { + // Bet is "high" risk to me. + if(cardWeight > 0.6 && confidence >= POKER_WINNNIG_CONFIDENCE_PAIR) { + bet = (confidence * cardWeight); + } + } else { + // Bet is likely my last hand + } + } else { + // Not first round. + if(confidence <= POKER_WINNNIG_CONFIDENCE_PAIR) { + bet = (confidence * cardWeight) / betWeight; + } else if(confidence <= POKER_WINNNIG_CONFIDENCE_THREE_OF_A_KIND) { + bet = (confidence * (cardWeight / handWeight)) / betWeight; + } else { + bet = confidence * (cardWeight / handWeight) * 2; + } + } + + + printf("Bet %.4f\n\n", bet); + + // Now determine chips based on bet. + if(bet >= 0.75) { + chips = (int32_t)(bet * (float)player->chips); + chips = mathMin(chips, player->chips); + return pokerTurnRaise(poker, playerIndex, chips); + } else if(bet >= 0.25f) { + return pokerTurnCall(poker, playerIndex); + } + + // Well, now they have decided to "not bet", or really they think that their // cards are not worth the effort. But if they CAN check, they will. if(pokerTurnCanPlayerCheck(poker, playerIndex)) { @@ -120,11 +166,6 @@ pokerturn_t pokerTurnCall(poker_t *poker, uint8_t playerIndex) { turn = pokerTurnRaise( poker, playerIndex, poker->bet.currentBet - player->currentBet ); - turn.type = ( - turn.type == POKER_TURN_TYPE_ALL_IN ? - POKER_TURN_TYPE_CALL_ALL_IN : - POKER_TURN_TYPE_CALL - ); return turn; } @@ -133,12 +174,22 @@ pokerturn_t pokerTurnRaise(poker_t *poker, uint8_t playerIndex, int32_t chips) { pokerplayer_t *player; player = poker->players + playerIndex; + if(chips < poker->bet.currentBet) chips = poker->bet.currentBet; + if(player->chips <= chips) { turn.chips = player->chips; turn.type = POKER_TURN_TYPE_ALL_IN; } else { turn.chips = chips; turn.type = POKER_TURN_TYPE_BET; + + if(chips == poker->bet.currentBet) { + turn.type = POKER_TURN_TYPE_CALL; + } + + if(chips == 0) { + turn.type = POKER_TURN_TYPE_CALL; + } } return turn; diff --git a/src/poker/turn.h b/src/poker/turn.h index 86c52c9f..784f79f2 100644 --- a/src/poker/turn.h +++ b/src/poker/turn.h @@ -8,6 +8,7 @@ #pragma once #include "../libs.h" #include "poker.h" +#include "winner.h" #define POKER_TURN_TYPE_OUT 0x00 #define POKER_TURN_TYPE_FOLD 0x01 @@ -17,17 +18,6 @@ #define POKER_TURN_TYPE_CALL_ALL_IN 0x04 #define POKER_TURN_TYPE_CHECK 0x05 -#define POKER_TURN_CONFIDENCE_ROYAL_FLUSH 1.0f -#define POKER_TURN_CONFIDENCE_STRAIGHT_FLUSH 0.9f -#define POKER_TURN_CONFIDENCE_FOUR_OF_A_KIND 0.85f -#define POKER_TURN_CONFIDENCE_FULL_HOUSE 0.83f -#define POKER_TURN_CONFIDENCE_FLUSH 0.8f -#define POKER_TURN_CONFIDENCE_STRAIGHT 0.75f -#define POKER_TURN_CONFIDENCE_THREE_OF_A_KIND 0.75f -#define POKER_TURN_CONFIDENCE_TWO_PAIR 0.7f -#define POKER_TURN_CONFIDENCE_PAIR 0.6f -#define POKER_TURN_CONFIDENCE_HIGH_CARD 0.5f - /** The turn that a player/the AI decided to do for its turn */ typedef struct { /** What type of action the turn is */ diff --git a/src/poker/winner.c b/src/poker/winner.c index e0fc1dd8..b8cbac4a 100644 --- a/src/poker/winner.c +++ b/src/poker/winner.c @@ -7,10 +7,6 @@ #include "winner.h" -void pokerWinnerGetBestCard(card_t *cards, uint8_t cardCount) { - -} - void pokerWinnerHandGetFull( pokerdealer_t *dealer, pokerplayer_t *player, card_t *cards ) { @@ -242,6 +238,7 @@ void _pokerWinnerFillRemaining(pokerplayerwinning_t *winning) { } } + if(highest == 0xFF) break; winning->set[winning->setSize++] = highestCard; } cardHandSort(winning->set, winning->setSize); @@ -385,3 +382,53 @@ void pokerWinnerCalculate( winner->winners[winner->winnerCount++] = i; } } + +card_t pokerWinnerGetBestCard(card_t *cards, uint8_t cardCount) { + uint8_t i, number, bestNumber; + card_t card, bestCard; + + bestNumber = 0xFF; + + for(i = 0; i < cardCount; i++) { + card = cards[i]; + number = cardGetNumber(card); + if(number == CARD_ACE) return card; + if(bestNumber != 0xFF && number <= bestNumber) continue; + + bestCard = card; + bestNumber = number; + } + + return bestNumber; +} + +float pokerWinnerGetTypeConfidence(uint8_t type) { + switch(type) { + case POKER_WINNING_TYPE_ROYAL_FLUSH: + return POKER_WINNNIG_CONFIDENCE_ROYAL_FLUSH; + case POKER_WINNING_TYPE_STRAIGHT_FLUSH: + return POKER_WINNNIG_CONFIDENCE_STRAIGHT_FLUSH; + case POKER_WINNING_TYPE_FOUR_OF_A_KIND: + return POKER_WINNNIG_CONFIDENCE_FOUR_OF_A_KIND; + case POKER_WINNING_TYPE_FULL_HOUSE: + return POKER_WINNNIG_CONFIDENCE_FULL_HOUSE; + case POKER_WINNING_TYPE_FLUSH: + return POKER_WINNNIG_CONFIDENCE_FLUSH; + case POKER_WINNING_TYPE_STRAIGHT: + return POKER_WINNNIG_CONFIDENCE_STRAIGHT; + case POKER_WINNING_TYPE_THREE_OF_A_KIND: + return POKER_WINNNIG_CONFIDENCE_THREE_OF_A_KIND; + case POKER_WINNING_TYPE_TWO_PAIR: + return POKER_WINNNIG_CONFIDENCE_TWO_PAIR; + case POKER_WINNING_TYPE_PAIR: + return POKER_WINNNIG_CONFIDENCE_PAIR; + default: + return POKER_WINNNIG_CONFIDENCE_HIGH_CARD; + } +} + +float pokerWinnerGetCardWeight(card_t card) { + uint8_t number; + number = cardGetNumber(card); + return ((float)number + 1)/((float)CARD_ACE + 1); +} \ No newline at end of file diff --git a/src/poker/winner.h b/src/poker/winner.h index b1e9a5ee..ca093c23 100644 --- a/src/poker/winner.h +++ b/src/poker/winner.h @@ -18,7 +18,7 @@ /** How many cards make a winning set */ #define POKER_WINNING_SET_SIZE 5 -/** Winning Types */ +/** Winning Types */ #define POKER_WINNING_TYPE_NULL 0x00 #define POKER_WINNING_TYPE_ROYAL_FLUSH 0x01 #define POKER_WINNING_TYPE_STRAIGHT_FLUSH 0x02 @@ -31,6 +31,17 @@ #define POKER_WINNING_TYPE_PAIR 0x09 #define POKER_WINNNIG_TYPE_HIGH_CARD 0x0A +#define POKER_WINNNIG_CONFIDENCE_ROYAL_FLUSH 1.0f +#define POKER_WINNNIG_CONFIDENCE_STRAIGHT_FLUSH 0.9f +#define POKER_WINNNIG_CONFIDENCE_FOUR_OF_A_KIND 0.85f +#define POKER_WINNNIG_CONFIDENCE_FULL_HOUSE 0.83f +#define POKER_WINNNIG_CONFIDENCE_FLUSH 0.8f +#define POKER_WINNNIG_CONFIDENCE_STRAIGHT 0.75f +#define POKER_WINNNIG_CONFIDENCE_THREE_OF_A_KIND 0.75f +#define POKER_WINNNIG_CONFIDENCE_TWO_PAIR 0.7f +#define POKER_WINNNIG_CONFIDENCE_PAIR 0.6f +#define POKER_WINNNIG_CONFIDENCE_HIGH_CARD 0.5f + /** Holds information about a player's winning state */ typedef struct { /** The full set of both the dealer and player's hand */ @@ -108,4 +119,30 @@ card_t pokerWinnerCompare( */ void pokerWinnerCalculate( pokerwinner_t *winner, pokerdealer_t *dealer, pokerplayer_t *players -); \ No newline at end of file +); + +/** + * Get the best valued card from a given hand. + * + * @param cards Array of cards. + * @param cardCount Count of cards in the array + * @return The best card within the array. + */ +card_t pokerWinnerGetBestCard(card_t *cards, uint8_t cardCount); + + +/** + * Get the confidence of the bet for a given winning type. + * + * @param type Winning type type. + * @return The confidence. + */ +float pokerWinnerGetTypeConfidence(uint8_t type); + +/** + * Get the weight of a card. + * + * @param card Card to get the weight of. + * @return The cards' weight. + */ +float pokerWinnerGetCardWeight(card_t card); \ No newline at end of file