diff --git a/src/game/poker/actions/flop.c b/src/game/poker/actions/flop.c index 9325d73e..8e9174da 100644 --- a/src/game/poker/actions/flop.c +++ b/src/game/poker/actions/flop.c @@ -19,7 +19,7 @@ void _pokerGameActionFlopOnStart( discussion.poker = game; // Get how many players are left in the round. - if(pokerInRoundGetCount(game->poker.players) > 1) {// Still more than 1 + if(pokerInRoundGetCount(&game->poker) > 1) {// Still more than 1 // Add the actual flop action. next = pokerActionNextFlopAdd(queue, &game->poker); @@ -31,13 +31,11 @@ void _pokerGameActionFlopOnStart( discussion.reason = POKER_DISCUSSION_REASON_FLOP; pokerDiscussionQueue(&discussion); - //TODO: Get the next player here. nextBetter = pokerPlayerGetRemainingBetter(&game->poker); // Now, get the count of players left to bet. If "everyone is all in" then // this will be 0 and no actual betting needs to happen. - - if(nextBetter != 0xFF) { + if(pokerPlayerGetRemainingBetterCount(&game->poker) > 0x01) { // Begin betting. game->poker.better = nextBetter; pokerGameActionLookAdd(game, nextBetter); diff --git a/src/poker/actions/flop.c b/src/poker/actions/flop.c index 1f6ea01e..edc01c9a 100644 --- a/src/poker/actions/flop.c +++ b/src/poker/actions/flop.c @@ -13,8 +13,8 @@ void _pokerActionFlopDo(queue_t *queue, queueaction_t *action, uint8_t count) { // TODO: Fix State // poker->state = POKER_STATE_CARDS_FLOPPING; - pokerBurn(&poker, POKER_FLOP_BURN_COUNT); - pokerTurn(&poker, count); + pokerBurn(poker, POKER_FLOP_BURN_COUNT); + pokerTurn(poker, count); printf("Turned %u cards\n", count); queueNext(queue); diff --git a/src/poker/actions/round.c b/src/poker/actions/round.c index 98cd10ab..e0ef03d4 100644 --- a/src/poker/actions/round.c +++ b/src/poker/actions/round.c @@ -8,21 +8,17 @@ #include "round.h" void _pokerActionRoundOnStart(queue_t *queue, queueaction_t *action ,uint8_t i){ - uint8_t j, indexDealer, indexSmallBlind, indexBigBlind; - bool foundDealer, foundSmallBlind; - pokerplayer_t *player; poker_t *poker; - poker = (poker_t *)action->data; // TODO: Fix State // poker->state = POKER_STATE_STARTING_ROUND; // Prepare the initial game stat - pokerResetRound(&poker); + pokerResetRound(poker); // Decide on the dealer - pokerNewDealer(&poker); + pokerNewDealer(poker); queueNext(queue); } diff --git a/src/poker/poker.c b/src/poker/poker.c index 87e1e81f..c50a3de2 100644 --- a/src/poker/poker.c +++ b/src/poker/poker.c @@ -47,6 +47,7 @@ void pokerResetBettingRound(poker_t *poker) { for(i = 0; i < poker->playerCount; i++) { player = poker->players + i; player->state =flagOff(player->state,POKER_PLAYER_STATE_HAS_BET_THIS_ROUND); + player->timesRaised = 0; } // Now reset to the first player that needs to bet. @@ -113,10 +114,14 @@ uint8_t pokerPotAdd(poker_t *poker) { return i; } -void pokerPotAddPlayer(pokerpot_t *pot, uint8_t playerIndex) { - if(arrayContains( +bool pokerPotHasPlayer(pokerpot_t *pot, uint8_t playerIndex) { + return arrayContains( sizeof(uint8_t), pot->players, pot->playerCount, &playerIndex - )) return; + ); +} + +void pokerPotAddPlayer(pokerpot_t *pot, uint8_t playerIndex) { + if(pokerPotHasPlayer(pot, playerIndex)) return; pot->players[pot->playerCount++] = playerIndex; } @@ -356,8 +361,8 @@ pokerturn_t pokerTurnGetForPlayer(poker_t *poker, uint8_t playerIndex) { confidence = confidence / 30.0f; } else { // Simulate my hand being the winning hand, use that as the confidence - // pokerWinnerPlayerGet(&poker->community, player, &winning); - // confidence = pokerWinnerGetTypeConfidence(winning.type); + pokerWinnerGetForPlayer(poker, player, &winning); + confidence = pokerWinnerGetTypeConfidence(winning.type); } // Now we know how confident the AI is, let's put a chip value to that weight @@ -365,13 +370,13 @@ pokerturn_t pokerTurnGetForPlayer(poker_t *poker, uint8_t playerIndex) { callBet = pokerPlayerGetCallBet(poker, player); // Do they need chips to call, or is it possible to check? - // if(callBet > 0) { - // potOdds = (float)callBet / ((float)callBet + (float)poker->bet.pot); - // } else { - // potOdds = ( - // 1.0f / (float)pokerBetGetRemainingPlayerCount(&poker->bet, poker->players) - // ); - // } + if(callBet > 0) { + potOdds = (float)callBet / ( + (float)callBet + (float)pokerPlayerGetPotChipsSum(poker, playerIndex) + ); + } else { + potOdds = 1.0f / (float)pokerPlayerGetRemainingBetterCount(poker); + } // Now determine the expected ROI expectedGain = confidence / potOdds; @@ -432,29 +437,43 @@ pokerturn_t pokerTurnGetForPlayer(poker_t *poker, uint8_t playerIndex) { } // Did we actually bet? - // if(amount > 0) { - // printf("AI is betting %i chips, bluff: %i\n", amount, isBluff); + if(amount > 0) { + printf("AI is betting %i chips, bluff: %i\n", amount, isBluff); - // // Let's not get caught in a raising loop with AI. - // if(player->timesRaised >= POKER_TURN_MAX_RAISES) { - // amount = callBet; - // } - - // amount = mathMax(amount, callBet); - // turn = pokerTurnRaise(poker, playerIndex, amount); - // turn.confidence = confidence; - // } else if(pokerTurnCanPlayerCheck(poker, playerIndex)) { - // turn = pokerTurnCheck(poker, playerIndex); - // turn.confidence = 1; - // } else { - // turn = pokerTurnFold(poker, playerIndex); - // turn.confidence = 1 - confidence; - // } + // Let's not get caught in a raising loop with AI. + if(player->timesRaised >= POKER_TURN_MAX_RAISES) { + amount = callBet; + } + amount = mathMax(amount, callBet); + turn = pokerTurnBet(poker, playerIndex, amount); + turn.confidence = confidence; + } else if(pokerPlayerCanCheck(poker, player)) { + turn = pokerTurnBet(poker, playerIndex, 0); + turn.confidence = 1; + } else { + turn = pokerTurnFold(poker, playerIndex); + turn.confidence = 1 - confidence; + } return turn; } +int32_t pokerPlayerGetPotChipsSum(poker_t *poker, uint8_t playerIndex) { + int32_t count; + uint8_t i; + pokerpot_t *pot; + + count = 0; + for(i = 0; i < poker->potCount; i++) { + pot = poker->pots + i; + if(!pokerPotHasPlayer(pot, playerIndex)) continue; + count += pot->chips; + } + + return count; +} + // Winning void pokerHandGetFull( poker_t *poker, pokerplayer_t *player, card_t cards[POKER_WINNING_FULL_SIZE] @@ -669,7 +688,6 @@ void pokerWinnerGetForPlayer( for(j = 0; j < pairCount; j++) { winning->set[winning->setSize+j] = winning->full[pairs[j]]; } - // arrayCopy(sizeof(int32_t), pairs, pairCount, winning->set+winning->setSize); winning->setSize += pairCount; if(winning->setSize != 4) continue; @@ -693,7 +711,9 @@ void pokerWinnerGetForPlayer( return; } -card_t pokerWinnerCompare(pokerplayerwinning_t *left, pokerplayerwinning_t *right) { +card_t pokerWinnerCompare( + pokerplayerwinning_t *left, pokerplayerwinning_t *right +) { uint8_t i, number; card_t card; int32_t index; @@ -838,3 +858,28 @@ void pokerWinnerDetermineForPot( *participantCount = countPlayers; *winnerCount = countWinners; } + +float pokerWinnerGetTypeConfidence(uint8_t type) { + switch(type) { + case POKER_WINNING_TYPE_ROYAL_FLUSH: + return POKER_WINNING_CONFIDENCE_ROYAL_FLUSH; + case POKER_WINNING_TYPE_STRAIGHT_FLUSH: + return POKER_WINNING_CONFIDENCE_STRAIGHT_FLUSH; + case POKER_WINNING_TYPE_FOUR_OF_A_KIND: + return POKER_WINNING_CONFIDENCE_FOUR_OF_A_KIND; + case POKER_WINNING_TYPE_FULL_HOUSE: + return POKER_WINNING_CONFIDENCE_FULL_HOUSE; + case POKER_WINNING_TYPE_FLUSH: + return POKER_WINNING_CONFIDENCE_FLUSH; + case POKER_WINNING_TYPE_STRAIGHT: + return POKER_WINNING_CONFIDENCE_STRAIGHT; + case POKER_WINNING_TYPE_THREE_OF_A_KIND: + return POKER_WINNING_CONFIDENCE_THREE_OF_A_KIND; + case POKER_WINNING_TYPE_TWO_PAIR: + return POKER_WINNING_CONFIDENCE_TWO_PAIR; + case POKER_WINNING_TYPE_PAIR: + return POKER_WINNING_CONFIDENCE_PAIR; + default: + return POKER_WINNING_CONFIDENCE_HIGH_CARD; + } +} \ No newline at end of file diff --git a/src/poker/poker.h b/src/poker/poker.h index 59622800..b6e54d03 100644 --- a/src/poker/poker.h +++ b/src/poker/poker.h @@ -76,6 +76,8 @@ #define POKER_TURN_TYPE_CALL_ALL_IN 0x04 #define POKER_TURN_TYPE_CHECK 0x05 +#define POKER_TURN_MAX_RAISES 0x02 + /** How many chips each player has by defautl */ #define POKER_BET_PLAYER_CHIPS_DEFAULT 1200 @@ -103,6 +105,8 @@ typedef struct { /** Current bet that the player has done. */ int32_t currentBet; + + uint8_t timesRaised; } pokerplayer_t; /** Holds information about a player's winning state */ @@ -226,6 +230,15 @@ int32_t pokerGetCallValue(poker_t *poker); */ uint8_t pokerPotAdd(poker_t *poker); +/** + * Check whether or not the given player is part of the given pot. + * + * @param pot Pot to check. + * @param playerIndex Player index to see if within the pot or not. + * @return True if in the pot, otherwise false. + */ +bool pokerPotHasPlayer(pokerpot_t *pot, uint8_t playerIndex); + /** * Add a player to a pot. This will not let you add the same player to the pot * twice. @@ -408,6 +421,16 @@ pokerturn_t pokerTurnBet(poker_t *poker, uint8_t playerIndex, int32_t chips); */ pokerturn_t pokerTurnGetForPlayer(poker_t *poker, uint8_t playerIndex); +/** + * Returns the sum of chips in the pot(s) that the specified player is in. This + * does not consider the pot, player or hand, just the pure sum of chips. + * + * @param poker Poker game instance. + * @param playerIndex Player Index to get the sum of chips from. + * @return The sum of chips from the pots the player is within. + */ +int32_t pokerPlayerGetPotChipsSum(poker_t *poker, uint8_t playerIndex); + /** * Returns the full hand for a given player including the best cards on the * bench. @@ -473,4 +496,12 @@ void pokerWinnerDetermineForPot( uint8_t *winnerCount, uint8_t participants[POKER_PLAYER_COUNT_MAX], uint8_t *participantCount -); \ No newline at end of file +); + +/** + * Get the confidence of the bet for a given winning type. + * + * @param type Winning type type. + * @return The confidence. + */ +float pokerWinnerGetTypeConfidence(uint8_t type); \ No newline at end of file diff --git a/test/poker/poker.c b/test/poker/poker.c index 42fa6955..2adcb80d 100644 --- a/test/poker/poker.c +++ b/test/poker/poker.c @@ -209,6 +209,45 @@ void test_pokerPotAdd_should_ResetThePot(void) { TEST_ASSERT_EQUAL_INT32(0, pot->chips); } +void test_pokerPotHasPlayer_should_DetermineIfPlayerInThePot(void) { + poker_t poker; + pokerpot_t *pot; + uint8_t p0, p1, p2; + + pokerInit(&poker); + p0 = pokerPlayerAdd(&poker); + p1 = pokerPlayerAdd(&poker); + p2 = pokerPlayerAdd(&poker); + + pot = poker.pots + 0; + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p0)); + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p1)); + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p2)); + + pokerPotAddPlayer(pot, p0); + TEST_ASSERT_EQUAL(true, pokerPotHasPlayer(pot, p0)); + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p1)); + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p2)); + + pokerPotAddPlayer(pot, p2); + TEST_ASSERT_EQUAL(true, pokerPotHasPlayer(pot, p0)); + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p1)); + TEST_ASSERT_EQUAL(true, pokerPotHasPlayer(pot, p2)); + + pokerPotAddPlayer(pot, p1); + TEST_ASSERT_EQUAL(true, pokerPotHasPlayer(pot, p0)); + TEST_ASSERT_EQUAL(true, pokerPotHasPlayer(pot, p1)); + TEST_ASSERT_EQUAL(true, pokerPotHasPlayer(pot, p2)); + + pokerPotAdd(&poker); + pot = poker.pots + 1; + + pokerPotAddPlayer(pot, p1); + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p0)); + TEST_ASSERT_EQUAL(true, pokerPotHasPlayer(pot, p1)); + TEST_ASSERT_EQUAL(false, pokerPotHasPlayer(pot, p2)); +} + void test_pokerPotAddPlayer_should_AddAPlayer(void) { poker_t poker; pokerpot_t *pot; @@ -1502,6 +1541,7 @@ int test_poker() { RUN_TEST(test_pokerResetBettingRound_should_ResetTheBettingRound); RUN_TEST(test_pokerPotAdd_should_AddAPot); RUN_TEST(test_pokerPotAdd_should_ResetThePot); + RUN_TEST(test_pokerPotHasPlayer_should_DetermineIfPlayerInThePot); RUN_TEST(test_pokerNewDealer_should_FindANewDealer); RUN_TEST(test_pokerNewDealer_should_SkipOutPlayers); RUN_TEST(test_pokerTakeBlinds_should_TakeTheBlinds);