From 2b772816d818d6001c190eeda0ae5fc3c17cb87a Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Thu, 24 Jun 2021 15:06:13 -0700 Subject: [PATCH] Moved winning hand solver code to player.c --- include/dawn/poker/poker.h | 32 +++++- src/poker/player.c | 204 ++++++++++++++++++++++++++++++++++++ src/poker/player.h | 28 ++++- src/poker/round/winner.c | 206 +------------------------------------ src/poker/round/winner.h | 28 ----- 5 files changed, 263 insertions(+), 235 deletions(-) diff --git a/include/dawn/poker/poker.h b/include/dawn/poker/poker.h index 604dc1aa..9232d430 100644 --- a/include/dawn/poker/poker.h +++ b/include/dawn/poker/poker.h @@ -57,6 +57,22 @@ #define POKER_TURN_CARD_COUNT 1 #define POKER_RIVER_CARD_COUNT 1 +/** Winning Types */ +#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_WINNNIG_TYPE_HIGH_CARD 0x0A + +/** How many cards make a winning set */ +#define POKER_WINNING_SET_SIZE 5 + + typedef struct { ////////////////////////////////////////////////////////////////////////////// // Poker Logic Variables @@ -137,4 +153,18 @@ typedef struct { texture_t cardTexture; tileset_t cardTileset; primitive_t cardPrimitive; -} poker_t; \ No newline at end of file +} poker_t; + +/** Holds information about the winning player state */ +typedef struct { + /** The full set of both the dealer and player's hand */ + card_t full[POKER_PLAYER_HAND + POKER_DEALER_HAND]; + uint8_t size; + + /** Holds the winning set */ + int32_t set[POKER_WINNING_SET_SIZE]; + uint8_t count; + + /** Winning Type */ + uint8_t type; +} pokerwinning_t; \ No newline at end of file diff --git a/src/poker/player.c b/src/poker/player.c index df9d328d..5524e8dc 100644 --- a/src/poker/player.c +++ b/src/poker/player.c @@ -36,4 +36,208 @@ void pokerPlayerDealAll(poker_t *poker, uint8_t count) { pokerPlayerDeal(poker, player); } } +} + +void pokerPlayerGetFullHand(poker_t *poker,pokerplayer_t *player,card_t *cards){ + uint8_t i; + + // Add the dealer hand + for(i = 0; i < poker->cardsFacing; i++) { + cards[i] = poker->cards[i]; + } + + // Add the player hand + for(i = 0; i < player->cardCount; i++) { + cards[i+poker->cardsFacing] = player->cards[i]; + } + + // Sort by card value + cardHandSort(cards, poker->cardsFacing+player->cardCount); +} + +pokerwinning_t pokerPlayerGetWinning(poker_t *poker, pokerplayer_t *player) { + pokerwinning_t winning; + uint8_t i, j, l; + int32_t index; + card_t card; + uint8_t number, suit, pairCount; + int32_t pairs[CARD_SUIT_COUNT]; + + // Get the full poker hand (should be a 7 card hand) + winning.size = poker->cardsFacing + player->cardCount; + pokerPlayerGetFullHand(poker, player, winning.full); + + // Reset the winning status. + winning.count = 0; + winning.type = 0x00; + for(i = 0; i < POKER_WINNING_SET_SIZE; i++) winning.set[i] = -1; + + //////////////////////// Now look for the winning set //////////////////////// + + // Royal / Straight Flush + for(i = 0; i < winning.size; i++) { + card = winning.full[i]; + number = cardGetNumber(card); + if(number < CARD_FIVE) continue; + + suit = cardGetSuit(card); + winning.count = 1; + + // 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. + index = cardContains(winning.full, winning.size, cardGet(l, suit)); + if(index == -1) break; + winning.set[j] = index; + winning.count++; + } + + // Check if has all necessary cards. + if(winning.count < POKER_WINNING_SET_SIZE) continue; + + // Add self to array + winning.set[0] = i; + winning.type = ( + number == CARD_ACE ? POKER_WINNING_TYPE_ROYAL_FLUSH : + POKER_WINNING_TYPE_STRAIGHT_FLUSH + ); + return winning; + } + + // Four of a kind. + winning.count = 0; + for(i = 0; i < winning.size; i++) { + card = winning.full[i]; + number = cardGetNumber(card); + pairCount = cardCountPairs(winning.full, winning.size, number, pairs); + if(pairCount < CARD_SUIT_COUNT) continue; + + winning.count = pairCount; + arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set); + winning.type = POKER_WINNING_TYPE_FOUR_OF_A_KIND; + pokerPlayerWinningFillRemaining(&winning); + return winning; + } + + // Full House + winning.count = 0; + for(i = 0; i < winning.size; i++) { + index = i;// Check we haven't already added this card. + if(arrayContains(sizeof(int32_t),winning.set,winning.count,&index))continue; + + card = winning.full[i]; + number = cardGetNumber(card); + pairCount = cardCountPairs(winning.full, winning.size, number, pairs); + + // Did we find either two pair or three pair? + if(pairCount != 2 && pairCount != 3) continue; + if(winning.count == 3) pairCount = 2;//Clamp to 5 max. + arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set+winning.count); + winning.count += pairCount; + if(winning.count != POKER_WINNING_SET_SIZE) continue; + winning.type = POKER_WINNING_TYPE_FULL_HOUSE; + printf("Full House\n"); + return winning; + } + + // Flush (5 same suit) + for(i = 0; i < winning.size; i++) { + card = winning.full[i]; + suit = cardGetSuit(card); + winning.count = 1; + for(j = i+1; j < winning.size; j++) { + if(cardGetSuit(winning.full[j]) != suit) continue; + winning.set[winning.count] = j; + winning.count++; + if(winning.count == POKER_WINNING_SET_SIZE) break; + } + if(winning.count < POKER_WINNING_SET_SIZE) continue; + winning.set[0] = i; + winning.type = POKER_WINNING_TYPE_FLUSH; + return winning; + } + + // Straight (sequence any suit) + winning.count = 0; + for(i = 0; i < winning.size; i++) { + card = winning.full[i]; + number = cardGetNumber(card); + if(number < CARD_FIVE) continue; + winning.count = 1; + + for(j = 1; j <= 4; j++) { + l = number == CARD_FIVE && j == 4 ? CARD_ACE : number - j;//Ace low. + index = cardContainsNumber(winning.full, winning.size, l); + if(index == -1) break; + winning.set[j] = index; + winning.count++; + } + + // Check if has all necessary cards. + if(winning.count < POKER_WINNING_SET_SIZE) continue; + winning.set[0] = i; + winning.type = POKER_WINNING_TYPE_STRAIGHT; + return winning; + } + + // Three of a kind + winning.count = 0; + for(i = 0; i < winning.size; i++) { + card = winning.full[i]; + number = cardGetNumber(card); + pairCount = cardCountPairs(winning.full, winning.size, number, pairs); + if(pairCount != 3) continue; + + winning.count = pairCount; + arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set); + winning.type = POKER_WINNING_TYPE_THREE_OF_A_KIND; + pokerPlayerWinningFillRemaining(&winning); + return winning; + } + + // Two Pair + winning.count = 0; + for(i = 0; i < winning.size; i++) { + index = i;// Check we haven't already added this card. + if(arrayContains(sizeof(int32_t),winning.set,winning.count,&index))continue; + + card = winning.full[i]; + number = cardGetNumber(card); + pairCount = cardCountPairs(winning.full, winning.size, number, pairs); + if(pairCount != 2) continue; + + arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set+winning.count); + winning.count += pairCount; + if(winning.count != 4) continue; + + winning.type = POKER_WINNING_TYPE_TWO_PAIR; + pokerPlayerWinningFillRemaining(&winning); + return winning; + } + + // Pair + if(winning.count == 2) { + winning.type = POKER_WINNING_TYPE_PAIR; + pokerPlayerWinningFillRemaining(&winning); + return winning; + } + + // High card + winning.count = 0; + pokerPlayerWinningFillRemaining(&winning); + winning.type = POKER_WINNNIG_TYPE_HIGH_CARD; + + return winning; +} + +void pokerPlayerWinningFillRemaining(pokerwinning_t *winning) { + uint8_t i; + int32_t index; + + for(i = winning->count; i < POKER_WINNING_SET_SIZE; i++) { + if(arrayContains(sizeof(int32_t),winning->set,winning->count,&i)) continue; + winning->set[winning->count++] = i; + } + + arraySortInt32(winning->set, winning->count); } \ No newline at end of file diff --git a/src/poker/player.h b/src/poker/player.h index a7a22f88..b7a9bf25 100644 --- a/src/poker/player.h +++ b/src/poker/player.h @@ -6,6 +6,7 @@ */ #include +#include "card.h" /** * Let a player bet chips into the pot. @@ -48,4 +49,29 @@ void pokerPlayerDeal(poker_t *poker, pokerplayer_t *player); * @param poker Poker game instance. * @param count Count of cards to deal. */ -void pokerPlayerDealAll(poker_t *poker, uint8_t count); \ No newline at end of file +void pokerPlayerDealAll(poker_t *poker, uint8_t count); + +/** + * Returns the full hand for a given player including the best cards on the + * bench. + * + * @param poker Poker game instance. + * @param player Poker player game instance. + * @param cards Array of at least 7 length to store the array. + */ +void pokerPlayerGetFullHand(poker_t *poker,pokerplayer_t *player,card_t *cards); + +/** + * Calculates and returns the winning state for a given player + * + * @param poker Poker game instance. + * @param player Player game instance. + * @return The winning state for this player. + */ +pokerwinning_t pokerPlayerGetWinning(poker_t *poker, pokerplayer_t *player); + +/** + * Fills the remaining cards for a given poker player winning hand. + * @param winning Pointer to the poker winning to fill out. + */ +void pokerPlayerWinningFillRemaining(pokerwinning_t *winning); \ No newline at end of file diff --git a/src/poker/round/winner.c b/src/poker/round/winner.c index ee829fbf..342aef8d 100644 --- a/src/poker/round/winner.c +++ b/src/poker/round/winner.c @@ -8,210 +8,6 @@ #pragma once #include "winner.h" -void pokerWinnerGetFullHand(poker_t *poker,pokerplayer_t *player,card_t *cards){ - uint8_t i; - - // Add the dealer hand - for(i = 0; i < poker->cardsFacing; i++) { - cards[i] = poker->cards[i]; - } - - // Add the player hand - for(i = 0; i < player->cardCount; i++) { - cards[i+poker->cardsFacing] = player->cards[i]; - } - - // Sort by card value - cardHandSort(cards, poker->cardsFacing+player->cardCount); -} - -void pokerWinnerFillRemaining(winning_t *winning) { - uint8_t i; - int32_t index; - - for(i = winning->count; i < POKER_WINNING_SET_SIZE; i++) { - if(arrayContains(sizeof(int32_t),winning->set,winning->count,&i)) continue; - winning->set[winning->count++] = i; - } - - arraySortInt32(winning->set, winning->count); -} - -winning_t pokerWinnerGetStatus(poker_t *poker, pokerplayer_t *player) { - winning_t winning; - uint8_t i, j, l; - int32_t index; - card_t card; - uint8_t number, suit, pairCount; - int32_t pairs[CARD_SUIT_COUNT]; - - // Get the full poker hand (should be a 7 card hand) - winning.size = poker->cardsFacing + player->cardCount; - pokerWinnerGetFullHand(poker, player, winning.full); - - // Reset the winning status. - winning.count = 0; - winning.type = 0x00; - for(i = 0; i < POKER_WINNING_SET_SIZE; i++) winning.set[i] = -1; - - //////////////////////// Now look for the winning set //////////////////////// - - // Royal / Straight Flush - for(i = 0; i < winning.size; i++) { - card = winning.full[i]; - number = cardGetNumber(card); - if(number < CARD_FIVE) continue; - - suit = cardGetSuit(card); - winning.count = 1; - - // 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. - index = cardContains(winning.full, winning.size, cardGet(l, suit)); - if(index == -1) break; - winning.set[j] = index; - winning.count++; - } - - // Check if has all necessary cards. - if(winning.count < POKER_WINNING_SET_SIZE) continue; - - // Add self to array - winning.set[0] = i; - winning.type = ( - number == CARD_ACE ? POKER_WINNING_TYPE_ROYAL_FLUSH : - POKER_WINNING_TYPE_STRAIGHT_FLUSH - ); - return winning; - } - - // Four of a kind. - winning.count = 0; - for(i = 0; i < winning.size; i++) { - card = winning.full[i]; - number = cardGetNumber(card); - pairCount = cardCountPairs(winning.full, winning.size, number, pairs); - if(pairCount < CARD_SUIT_COUNT) continue; - - winning.count = pairCount; - arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set); - winning.type = POKER_WINNING_TYPE_FOUR_OF_A_KIND; - pokerWinnerFillRemaining(&winning); - return winning; - } - - // Full House - winning.count = 0; - for(i = 0; i < winning.size; i++) { - index = i;// Check we haven't already added this card. - if(arrayContains(sizeof(int32_t),winning.set,winning.count,&index))continue; - - card = winning.full[i]; - number = cardGetNumber(card); - pairCount = cardCountPairs(winning.full, winning.size, number, pairs); - - // Did we find either two pair or three pair? - if(pairCount != 2 && pairCount != 3) continue; - if(winning.count == 3) pairCount = 2;//Clamp to 5 max. - arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set+winning.count); - winning.count += pairCount; - if(winning.count != POKER_WINNING_SET_SIZE) continue; - winning.type = POKER_WINNING_TYPE_FULL_HOUSE; - printf("Full House\n"); - return winning; - } - - // Flush (5 same suit) - for(i = 0; i < winning.size; i++) { - card = winning.full[i]; - suit = cardGetSuit(card); - winning.count = 1; - for(j = i+1; j < winning.size; j++) { - if(cardGetSuit(winning.full[j]) != suit) continue; - winning.set[winning.count] = j; - winning.count++; - if(winning.count == POKER_WINNING_SET_SIZE) break; - } - if(winning.count < POKER_WINNING_SET_SIZE) continue; - winning.set[0] = i; - winning.type = POKER_WINNING_TYPE_FLUSH; - return winning; - } - - // Straight (sequence any suit) - winning.count = 0; - for(i = 0; i < winning.size; i++) { - card = winning.full[i]; - number = cardGetNumber(card); - if(number < CARD_FIVE) continue; - winning.count = 1; - - for(j = 1; j <= 4; j++) { - l = number == CARD_FIVE && j == 4 ? CARD_ACE : number - j;//Ace low. - index = cardContainsNumber(winning.full, winning.size, l); - if(index == -1) break; - winning.set[j] = index; - winning.count++; - } - - // Check if has all necessary cards. - if(winning.count < POKER_WINNING_SET_SIZE) continue; - winning.set[0] = i; - winning.type = POKER_WINNING_TYPE_STRAIGHT; - return winning; - } - - // Three of a kind - winning.count = 0; - for(i = 0; i < winning.size; i++) { - card = winning.full[i]; - number = cardGetNumber(card); - pairCount = cardCountPairs(winning.full, winning.size, number, pairs); - if(pairCount != 3) continue; - - winning.count = pairCount; - arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set); - winning.type = POKER_WINNING_TYPE_THREE_OF_A_KIND; - pokerWinnerFillRemaining(&winning); - return winning; - } - - // Two Pair - winning.count = 0; - for(i = 0; i < winning.size; i++) { - index = i;// Check we haven't already added this card. - if(arrayContains(sizeof(int32_t),winning.set,winning.count,&index))continue; - - card = winning.full[i]; - number = cardGetNumber(card); - pairCount = cardCountPairs(winning.full, winning.size, number, pairs); - if(pairCount != 2) continue; - - arrayCopy(sizeof(int32_t), pairs, pairCount, winning.set+winning.count); - winning.count += pairCount; - if(winning.count != 4) continue; - - winning.type = POKER_WINNING_TYPE_TWO_PAIR; - pokerWinnerFillRemaining(&winning); - return winning; - } - - // Pair - if(winning.count == 2) { - winning.type = POKER_WINNING_TYPE_PAIR; - pokerWinnerFillRemaining(&winning); - return winning; - } - - // High card - winning.count = 0; - pokerWinnerFillRemaining(&winning); - winning.type = POKER_WINNNIG_TYPE_HIGH_CARD; - - return winning; -} - void pokerWinnerInit(poker_t *poker) { uint8_t winners[POKER_PLAYER_COUNT]; uint8_t winnerCount = 0; @@ -225,7 +21,7 @@ void pokerWinnerInit(poker_t *poker) { if(!pokerPlayerIsAlive(player)) continue; // Get the players' full hand - winning_t winning = pokerWinnerGetStatus(poker, player); + pokerwinning_t winning = pokerPlayerGetWinning(poker, player); printf("Winning state %u\n", winning.type); } } \ No newline at end of file diff --git a/src/poker/round/winner.h b/src/poker/round/winner.h index 6d81566e..10cb1ebc 100644 --- a/src/poker/round/winner.h +++ b/src/poker/round/winner.h @@ -8,33 +8,5 @@ #pragma once #include #include "../player.h" -#include "../card.h" -#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_WINNNIG_TYPE_HIGH_CARD 0x0A - -#define POKER_WINNING_SET_SIZE 5 - -typedef struct { - card_t full[POKER_PLAYER_HAND + POKER_DEALER_HAND]; - uint8_t size; - - uint8_t count; - int32_t set[POKER_WINNING_SET_SIZE]; - - uint8_t type; -} winning_t; - - -void pokerWinnerGetFullHand(poker_t *poker,pokerplayer_t *player,card_t *cards); -void pokerWinnerFillRemaining(winning_t *winning); -winning_t pokerWinnerGetStatus(poker_t *poker, pokerplayer_t *player); void pokerWinnerInit(poker_t *poker); \ No newline at end of file