315 lines
9.0 KiB
C
315 lines
9.0 KiB
C
/**
|
|
* Copyright (c) 2021 Dominic Masters
|
|
*
|
|
* This software is released under the MIT License.
|
|
* https://opensource.org/licenses/MIT
|
|
*/
|
|
|
|
#include "player.h"
|
|
|
|
void pokerPlayerBet(poker_t *poker, pokerplayer_t *player, int32_t chips) {
|
|
poker->pot += chips;
|
|
player->chips -= chips;
|
|
player->currentBet += chips;
|
|
}
|
|
|
|
bool pokerPlayerIsAlive(pokerplayer_t *player) {
|
|
return !(player->state & (POKER_PLAYER_STATE_FOLDED|POKER_PLAYER_STATE_OUT));
|
|
}
|
|
|
|
bool pokerPlayerIsHuman(poker_t *poker, pokerplayer_t *player) {
|
|
return (poker->players + POKER_PLAYER_HUMAN_INDEX) == player;
|
|
}
|
|
|
|
void pokerPlayerDeal(poker_t *poker, pokerplayer_t *player) {
|
|
cardDeal(poker->deck, &poker->deckSize, player->cards, &player->cardCount);
|
|
}
|
|
|
|
void pokerPlayerDealAll(poker_t *poker, uint8_t count) {
|
|
uint8_t x, y;
|
|
pokerplayer_t *player;
|
|
|
|
for(y = 0; y < count; y++) {
|
|
for(x = 0; x < POKER_PLAYER_COUNT; x++) {
|
|
player = poker->players + x;
|
|
if(!pokerPlayerIsAlive(player)) continue;
|
|
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);
|
|
}
|
|
|
|
void 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->fullSize = poker->cardsFacing + player->cardCount;
|
|
pokerPlayerGetFullHand(poker, player, winning->full);
|
|
|
|
// Reset the winning status.
|
|
winning->setSize = 0;
|
|
|
|
//////////////////////// Now look for the winning set ////////////////////////
|
|
|
|
// Royal / Straight Flush
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
card = winning->full[i];
|
|
number = cardGetNumber(card);
|
|
if(number < CARD_FIVE) continue;
|
|
|
|
suit = cardGetSuit(card);
|
|
winning->setSize = 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->fullSize, cardGet(l, suit));
|
|
if(index == -1) break;
|
|
winning->set[j] = winning->full[index];
|
|
winning->setSize++;
|
|
}
|
|
|
|
// Check if has all necessary cards.
|
|
if(winning->setSize < POKER_WINNING_SET_SIZE) continue;
|
|
|
|
// Add self to array
|
|
winning->set[0] = winning->full[i];
|
|
winning->type = (
|
|
number == CARD_ACE ? POKER_WINNING_TYPE_ROYAL_FLUSH :
|
|
POKER_WINNING_TYPE_STRAIGHT_FLUSH
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Four of a kind.
|
|
winning->setSize = 0;
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
card = winning->full[i];
|
|
number = cardGetNumber(card);
|
|
pairCount = cardCountPairs(winning->full, winning->fullSize, number, pairs);
|
|
if(pairCount < CARD_SUIT_COUNT) continue;
|
|
|
|
winning->setSize = pairCount;
|
|
for(j = 0; j < pairCount; j++) winning->set[j] = winning->full[pairs[j]];
|
|
winning->type = POKER_WINNING_TYPE_FOUR_OF_A_KIND;
|
|
pokerPlayerWinningFillRemaining(winning);
|
|
return;
|
|
}
|
|
|
|
// Full House
|
|
winning->setSize = 0;
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
// Check we haven't already added this card.
|
|
card = winning->full[i];
|
|
if(cardContains(winning->set, winning->setSize, card) != -1) continue;
|
|
|
|
number = cardGetNumber(card);
|
|
pairCount = cardCountPairs(winning->full, winning->fullSize, number, pairs);
|
|
|
|
// Did we find either two pair or three pair?
|
|
if(pairCount != 2 && pairCount != 3) continue;
|
|
if(winning->setSize == 3) pairCount = 2;//Clamp to 5 max.
|
|
|
|
// Copy found pairs.
|
|
for(j = 0; j < pairCount; j++) {
|
|
winning->set[winning->setSize + j] = winning->full[pairs[j]];
|
|
}
|
|
winning->setSize += pairCount;
|
|
|
|
// Winned?
|
|
if(winning->setSize != POKER_WINNING_SET_SIZE) continue;
|
|
winning->type = POKER_WINNING_TYPE_FULL_HOUSE;
|
|
printf("Full House\n");
|
|
return;
|
|
}
|
|
|
|
// Flush (5 same suit)
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
card = winning->full[i];
|
|
suit = cardGetSuit(card);
|
|
winning->setSize = 1;
|
|
for(j = i+1; j < winning->fullSize; j++) {
|
|
if(cardGetSuit(winning->full[j]) != suit) continue;
|
|
winning->set[winning->setSize] = winning->full[j];
|
|
winning->setSize++;
|
|
if(winning->setSize == POKER_WINNING_SET_SIZE) break;
|
|
}
|
|
if(winning->setSize < POKER_WINNING_SET_SIZE) continue;
|
|
winning->set[0] = winning->full[0];
|
|
winning->type = POKER_WINNING_TYPE_FLUSH;
|
|
return;
|
|
}
|
|
|
|
// Straight (sequence any suit)
|
|
winning->setSize = 0;
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
card = winning->full[i];
|
|
number = cardGetNumber(card);
|
|
if(number < CARD_FIVE) continue;
|
|
winning->setSize = 1;
|
|
|
|
for(j = 1; j <= 4; j++) {
|
|
l = number == CARD_FIVE && j == 4 ? CARD_ACE : number - j;//Ace low.
|
|
index = cardContainsNumber(winning->full, winning->fullSize, l);
|
|
if(index == -1) break;
|
|
winning->set[j] = winning->full[index];
|
|
winning->setSize++;
|
|
}
|
|
|
|
// Check if has all necessary cards.
|
|
if(winning->setSize < POKER_WINNING_SET_SIZE) continue;
|
|
winning->set[0] = winning->full[i];
|
|
winning->type = POKER_WINNING_TYPE_STRAIGHT;
|
|
return;
|
|
}
|
|
|
|
// Three of a kind
|
|
winning->setSize = 0;
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
card = winning->full[i];
|
|
number = cardGetNumber(card);
|
|
pairCount = cardCountPairs(winning->full, winning->fullSize, number, pairs);
|
|
if(pairCount != 3) continue;
|
|
|
|
winning->setSize = pairCount;
|
|
for(j = 0; j < pairCount; j++) winning->set[j] = winning->full[pairs[j]];
|
|
winning->type = POKER_WINNING_TYPE_THREE_OF_A_KIND;
|
|
pokerPlayerWinningFillRemaining(winning);
|
|
return;
|
|
}
|
|
|
|
// Two Pair
|
|
winning->setSize = 0;
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
card = winning->full[i];// Check we haven't already added this card.
|
|
if(cardContains(winning->set, winning->setSize, card) != -1) {
|
|
continue;
|
|
}
|
|
|
|
number = cardGetNumber(card);
|
|
pairCount = cardCountPairs(winning->full, winning->fullSize, number, pairs);
|
|
if(pairCount != 2) continue;
|
|
|
|
for(j = 0; j < pairCount; j++) {
|
|
winning->set[j] = winning->full[winning->setSize + pairs[j]];
|
|
}
|
|
// arrayCopy(sizeof(int32_t), pairs, pairCount, winning->set+winning->setSize);
|
|
winning->setSize += pairCount;
|
|
if(winning->setSize != 4) continue;
|
|
|
|
winning->type = POKER_WINNING_TYPE_TWO_PAIR;
|
|
pokerPlayerWinningFillRemaining(winning);
|
|
return;
|
|
}
|
|
|
|
// Pair
|
|
if(winning->setSize == 2) {
|
|
winning->type = POKER_WINNING_TYPE_PAIR;
|
|
pokerPlayerWinningFillRemaining(winning);
|
|
return;
|
|
}
|
|
|
|
// High card
|
|
winning->setSize = 0;
|
|
pokerPlayerWinningFillRemaining(winning);
|
|
winning->type = POKER_WINNNIG_TYPE_HIGH_CARD;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
card_t pokerPlayerCompareWinning(pokerwinning_t *left, pokerwinning_t *right) {
|
|
uint8_t i, number;
|
|
card_t card;
|
|
int32_t index;
|
|
|
|
card_t highCardLeft, highCardRight;
|
|
uint8_t highNumberLeft, highNumberRight;
|
|
|
|
highNumberLeft = 0xFF;
|
|
highNumberRight = 0xFF;
|
|
|
|
for(i = 0; i < left->setSize; i++) {
|
|
card = left->set[i];
|
|
number = cardGetNumber(card);
|
|
if(highNumberLeft != 0xFF && number < highNumberLeft) continue;// Quick check
|
|
index = cardContainsNumber(right->set, right->setSize, number);
|
|
if(index != -1) continue;// In other?
|
|
|
|
if(highNumberLeft == 0xFF||number == CARD_ACE||highNumberRight < number) {
|
|
highNumberLeft = number;
|
|
highCardLeft = card;
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < right->setSize; i++) {
|
|
card = right->set[i];
|
|
number = cardGetNumber(card);
|
|
if(highNumberRight != 0xFF && number < highNumberRight) continue;
|
|
index = cardContainsNumber(left->set, left->setSize, number);
|
|
if(index != -1) continue;
|
|
|
|
if(highNumberRight == 0xFF||number == CARD_ACE||highNumberRight < number) {
|
|
highNumberRight = number;
|
|
highCardRight = card;
|
|
}
|
|
}
|
|
|
|
if(highNumberLeft < highNumberRight) return 0xFF;
|
|
return highCardLeft;//Greater or Equal to.
|
|
}
|
|
|
|
void pokerPlayerWinningFillRemaining(pokerwinning_t *winning) {
|
|
uint8_t i, highest, current;
|
|
card_t highestCard, currentCard;
|
|
|
|
// Set the kicker
|
|
winning->kicker = 0xFF;
|
|
|
|
// Fill the remaining cards
|
|
while(winning->setSize < POKER_WINNING_SET_SIZE) {
|
|
highest = 0xFF;
|
|
|
|
for(i = 0; i < winning->fullSize; i++) {
|
|
currentCard = winning->full[i];
|
|
if(cardContains(winning->set, winning->setSize, currentCard) != -1) {
|
|
continue;
|
|
}
|
|
|
|
if(highest == 0xFF) {
|
|
highestCard = currentCard;
|
|
highest = cardGetNumber(highestCard);
|
|
} else {
|
|
current = cardGetNumber(currentCard);
|
|
if(current != CARD_ACE && current < highest) continue;
|
|
highestCard = currentCard;
|
|
highest = current;
|
|
}
|
|
}
|
|
|
|
winning->set[winning->setSize++] = highestCard;
|
|
}
|
|
cardHandSort(winning->set, winning->setSize);
|
|
} |