From 131c59fbf644f5d43d6ecdba8a92990990214d8b Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sat, 9 Oct 2021 15:43:26 -0700 Subject: [PATCH] Started merging new poker code in. --- {src => backup}/poker/actions/blinds.c | 0 {src => backup}/poker/actions/blinds.h | 0 {src => backup}/poker/actions/deal.c | 0 {src => backup}/poker/actions/deal.h | 0 {src => backup}/poker/actions/flop.c | 0 {src => backup}/poker/actions/flop.h | 0 {src => backup}/poker/actions/match.c | 0 {src => backup}/poker/actions/match.h | 0 {src => backup}/poker/actions/round.c | 0 {src => backup}/poker/actions/round.h | 0 {src => backup}/poker/bet.c | 0 {src => backup}/poker/bet.h | 0 {src => backup}/poker/dealer.c | 0 {src => backup}/poker/dealer.h | 0 {src => backup}/poker/player.c | 0 {src => backup}/poker/player.h | 0 backup/poker/poker.c | 39 ++ backup/poker/poker.h | 60 +++ {src => backup}/poker/turn.c | 0 {src => backup}/poker/turn.h | 0 {src => backup}/poker/winner.c | 0 {src => backup}/poker/winner.h | 0 src/game/poker/actions/bet.h | 3 - src/game/poker/actions/flop.h | 3 - src/game/poker/actions/restack.h | 3 - src/game/poker/actions/round.h | 4 - src/game/poker/actions/start.c | 2 +- src/game/poker/actions/start.h | 1 - src/game/poker/actions/winner.h | 2 - src/game/poker/pokerdiscussion.c | 14 +- src/game/poker/pokerdiscussion.h | 1 - src/game/poker/pokerui.c | 164 +++---- src/game/poker/pokerui.h | 7 +- src/game/poker/pokerworld.c | 2 +- src/game/poker/pokerworld.h | 11 +- src/poker/poker.c | 643 ++++++++++++++++++++++++- src/poker/poker.h | 451 +++++++++++++++-- src/poker2/poker.c | 633 ------------------------ src/poker2/poker.h | 171 ------- test/{poker2 => poker}/poker.c | 249 ++++++---- test/{poker2 => poker}/poker.h | 0 41 files changed, 1380 insertions(+), 1083 deletions(-) rename {src => backup}/poker/actions/blinds.c (100%) rename {src => backup}/poker/actions/blinds.h (100%) rename {src => backup}/poker/actions/deal.c (100%) rename {src => backup}/poker/actions/deal.h (100%) rename {src => backup}/poker/actions/flop.c (100%) rename {src => backup}/poker/actions/flop.h (100%) rename {src => backup}/poker/actions/match.c (100%) rename {src => backup}/poker/actions/match.h (100%) rename {src => backup}/poker/actions/round.c (100%) rename {src => backup}/poker/actions/round.h (100%) rename {src => backup}/poker/bet.c (100%) rename {src => backup}/poker/bet.h (100%) rename {src => backup}/poker/dealer.c (100%) rename {src => backup}/poker/dealer.h (100%) rename {src => backup}/poker/player.c (100%) rename {src => backup}/poker/player.h (100%) create mode 100644 backup/poker/poker.c create mode 100644 backup/poker/poker.h rename {src => backup}/poker/turn.c (100%) rename {src => backup}/poker/turn.h (100%) rename {src => backup}/poker/winner.c (100%) rename {src => backup}/poker/winner.h (100%) delete mode 100644 src/poker2/poker.c delete mode 100644 src/poker2/poker.h rename test/{poker2 => poker}/poker.c (92%) rename test/{poker2 => poker}/poker.h (100%) diff --git a/src/poker/actions/blinds.c b/backup/poker/actions/blinds.c similarity index 100% rename from src/poker/actions/blinds.c rename to backup/poker/actions/blinds.c diff --git a/src/poker/actions/blinds.h b/backup/poker/actions/blinds.h similarity index 100% rename from src/poker/actions/blinds.h rename to backup/poker/actions/blinds.h diff --git a/src/poker/actions/deal.c b/backup/poker/actions/deal.c similarity index 100% rename from src/poker/actions/deal.c rename to backup/poker/actions/deal.c diff --git a/src/poker/actions/deal.h b/backup/poker/actions/deal.h similarity index 100% rename from src/poker/actions/deal.h rename to backup/poker/actions/deal.h diff --git a/src/poker/actions/flop.c b/backup/poker/actions/flop.c similarity index 100% rename from src/poker/actions/flop.c rename to backup/poker/actions/flop.c diff --git a/src/poker/actions/flop.h b/backup/poker/actions/flop.h similarity index 100% rename from src/poker/actions/flop.h rename to backup/poker/actions/flop.h diff --git a/src/poker/actions/match.c b/backup/poker/actions/match.c similarity index 100% rename from src/poker/actions/match.c rename to backup/poker/actions/match.c diff --git a/src/poker/actions/match.h b/backup/poker/actions/match.h similarity index 100% rename from src/poker/actions/match.h rename to backup/poker/actions/match.h diff --git a/src/poker/actions/round.c b/backup/poker/actions/round.c similarity index 100% rename from src/poker/actions/round.c rename to backup/poker/actions/round.c diff --git a/src/poker/actions/round.h b/backup/poker/actions/round.h similarity index 100% rename from src/poker/actions/round.h rename to backup/poker/actions/round.h diff --git a/src/poker/bet.c b/backup/poker/bet.c similarity index 100% rename from src/poker/bet.c rename to backup/poker/bet.c diff --git a/src/poker/bet.h b/backup/poker/bet.h similarity index 100% rename from src/poker/bet.h rename to backup/poker/bet.h diff --git a/src/poker/dealer.c b/backup/poker/dealer.c similarity index 100% rename from src/poker/dealer.c rename to backup/poker/dealer.c diff --git a/src/poker/dealer.h b/backup/poker/dealer.h similarity index 100% rename from src/poker/dealer.h rename to backup/poker/dealer.h diff --git a/src/poker/player.c b/backup/poker/player.c similarity index 100% rename from src/poker/player.c rename to backup/poker/player.c diff --git a/src/poker/player.h b/backup/poker/player.h similarity index 100% rename from src/poker/player.h rename to backup/poker/player.h diff --git a/backup/poker/poker.c b/backup/poker/poker.c new file mode 100644 index 00000000..3c7b322c --- /dev/null +++ b/backup/poker/poker.c @@ -0,0 +1,39 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "poker.h" + +void pokerGameWin(poker_t *poker) { + uint8_t i; + pokerplayerwinning_t *winning; + pokerplayer_t *player; + int32_t chipsRounded, chipsDifferent; + float chipsEach; + + poker->state = POKER_STATE_DECIDING_WINNER; + + // Get the chips each. + chipsEach = poker->bet.pot / ((float)poker->winner.winnerCount); + + // Now work out the rounded offset chips. + chipsRounded = (int32_t)mathFloor(chipsEach); + chipsDifferent = poker->bet.pot - chipsRounded; + + // Let's start by rewarding the winnings to the players. + for(i = 0; i < poker->winner.winnerCount; i++) { + player = poker->players + poker->winner.winners[i]; + winning = poker->winner.winnings + i; + player->chips += chipsRounded; + if(i == 0) player->chips += chipsDifferent; + } + + // Now kill the players who are terrible low life gamblers. + for(i = 0; i < POKER_PLAYER_COUNT; i++) { + player = poker->players + i; + if(player->chips <= 0) player->state &= POKER_PLAYER_STATE_OUT; + } +} \ No newline at end of file diff --git a/backup/poker/poker.h b/backup/poker/poker.h new file mode 100644 index 00000000..aab60377 --- /dev/null +++ b/backup/poker/poker.h @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2021 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "../libs.h" +#include "bet.h" +#include "dealer.h" +#include "winner.h" + +/** How many cards to deal each player during the deal round */ +#define POKER_DEAL_CARD_EACH 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 + + +#define POKER_STATE_NULL 0x00 +#define POKER_STATE_STARTING_MATCH 0x01 +#define POKER_STATE_STARTING_ROUND 0x02 +#define POKER_STATE_TAKING_BLINDS 0x03 +#define POKER_STATE_DEALING 0x04 +#define POKER_STATE_CARDS_FLOPPING 0x05 +#define POKER_STATE_BETTING 0x06 +#define POKER_STATE_DECIDING_WINNER 0x07 + +typedef struct { + /** Poker betting state */ + pokerbet_t bet; + + /** Player States */ + pokerdealer_t dealer; + pokerplayer_t players[POKER_PLAYER_COUNT]; + + /** Winning player states */ + pokerwinner_t winner; + + /** The current player that is the dealer */ + uint8_t roundDealer; + + /** Which player is the small blind for this round */ + uint8_t roundSmallBlind; + + /** Which player is the big blind for this round */ + uint8_t roundBigBlind; + + uint8_t state; +} poker_t; + +/** + * Action the poker game winning state after it has been calculated previously. + * + * @param poker Poker game to action the winning state of. + */ +void pokerGameWin(poker_t *poker); \ No newline at end of file diff --git a/src/poker/turn.c b/backup/poker/turn.c similarity index 100% rename from src/poker/turn.c rename to backup/poker/turn.c diff --git a/src/poker/turn.h b/backup/poker/turn.h similarity index 100% rename from src/poker/turn.h rename to backup/poker/turn.h diff --git a/src/poker/winner.c b/backup/poker/winner.c similarity index 100% rename from src/poker/winner.c rename to backup/poker/winner.c diff --git a/src/poker/winner.h b/backup/poker/winner.h similarity index 100% rename from src/poker/winner.h rename to backup/poker/winner.h diff --git a/src/game/poker/actions/bet.h b/src/game/poker/actions/bet.h index 304c7af3..a2dd367b 100644 --- a/src/game/poker/actions/bet.h +++ b/src/game/poker/actions/bet.h @@ -7,9 +7,6 @@ #pragma once #include "../../../libs.h" -#include "../../../poker/actions/flop.h" -#include "../../../poker/turn.h" -#include "../../../poker/bet.h" #include "../pokerdiscussion.h" #include "action.h" #include "restack.h" diff --git a/src/game/poker/actions/flop.h b/src/game/poker/actions/flop.h index bd2a4e25..eed35b47 100644 --- a/src/game/poker/actions/flop.h +++ b/src/game/poker/actions/flop.h @@ -7,9 +7,6 @@ #pragma once #include "../../../libs.h" -#include "../../../poker/actions/flop.h" -#include "../../../poker/turn.h" -#include "../../../poker/bet.h" #include "../pokerdiscussion.h" #include "action.h" #include "restack.h" diff --git a/src/game/poker/actions/restack.h b/src/game/poker/actions/restack.h index d2f98fc2..a6a2d3ba 100644 --- a/src/game/poker/actions/restack.h +++ b/src/game/poker/actions/restack.h @@ -11,9 +11,6 @@ #include "action.h" #include "../pokergame.h" #include "../../../display/animation/queue.h" -#include "../../../poker/turn.h" -#include "../../../poker/bet.h" -#include "../../../poker/actions/flop.h" /** Callback for when the queue restack action stars. */ void _pokerGameActionRestackOnStart( diff --git a/src/game/poker/actions/round.h b/src/game/poker/actions/round.h index 63e55a44..319044d4 100644 --- a/src/game/poker/actions/round.h +++ b/src/game/poker/actions/round.h @@ -6,10 +6,6 @@ #pragma once #include "../../../libs.h" #include "action.h" -#include "../../../poker/bet.h" -#include "../../../poker/actions/round.h" -#include "../../../poker/actions/blinds.h" -#include "../../../poker/actions/deal.h" #include "../pokerdiscussion.h" #include "bet.h" diff --git a/src/game/poker/actions/start.c b/src/game/poker/actions/start.c index 0d7bb7af..8a587819 100644 --- a/src/game/poker/actions/start.c +++ b/src/game/poker/actions/start.c @@ -18,7 +18,7 @@ void _pokerGameActionStartOnEnd(queue_t *queue,queueaction_t *action,uint8_t i){ pokergame_t *game = (pokergame_t *)action->data; // Begin the match - pokerActionMatchAdd(&game->scene.conversation.actionQueue, &game->poker); + pokerInit(&game->poker); // Say that. data.poker = game; diff --git a/src/game/poker/actions/start.h b/src/game/poker/actions/start.h index b018d727..876be9f9 100644 --- a/src/game/poker/actions/start.h +++ b/src/game/poker/actions/start.h @@ -9,7 +9,6 @@ #include "../../../libs.h" #include "../../../vn/conversation/talk.h" #include "../../../display/animation/queue.h" -#include "../../../poker/actions/match.h" #include "../pokerdiscussion.h" #include "round.h" #include "action.h" diff --git a/src/game/poker/actions/winner.h b/src/game/poker/actions/winner.h index 431c2cf6..1b0faa35 100644 --- a/src/game/poker/actions/winner.h +++ b/src/game/poker/actions/winner.h @@ -7,8 +7,6 @@ #pragma once #include "../../../libs.h" -#include "../../../poker/winner.h" -#include "../../../poker/poker.h" #include "../pokerdiscussion.h" #include "action.h" #include "round.h" diff --git a/src/game/poker/pokerdiscussion.c b/src/game/poker/pokerdiscussion.c index 38d6f0d6..bf31115b 100644 --- a/src/game/poker/pokerdiscussion.c +++ b/src/game/poker/pokerdiscussion.c @@ -20,7 +20,7 @@ void pokerDiscussionGet( case POKER_DISCUSSION_REASON_MATCH_START: discussion->count++; discussion->messages[0] = "Match Start"; - discussion->players[0] = POKER_DEALER_INDEX; + discussion->players[0] = POKER_WORLD_DEALER_INDEX; discussion->emotions[0] = VN_CHARACTER_EMOTION_BORED; break; @@ -28,7 +28,7 @@ void pokerDiscussionGet( case POKER_DISCUSSION_REASON_ROUND_START: discussion->count++; discussion->messages[0] = "Round Start"; - discussion->players[0] = POKER_DEALER_INDEX; + discussion->players[0] = POKER_WORLD_DEALER_INDEX; discussion->emotions[0] = VN_CHARACTER_EMOTION_BORED; break; @@ -36,7 +36,7 @@ void pokerDiscussionGet( case POKER_DISCUSSION_REASON_BLINDS_TAKEN: discussion->count++; discussion->messages[0] = "Blinds\nhave been taken."; - discussion->players[0] = POKER_DEALER_INDEX; + discussion->players[0] = POKER_WORLD_DEALER_INDEX; discussion->emotions[0] = VN_CHARACTER_EMOTION_BORED; break; @@ -44,7 +44,7 @@ void pokerDiscussionGet( case POKER_DISCUSSION_REASON_DEAL: discussion->count++; discussion->messages[0] = "Cards dealt."; - discussion->players[0] = POKER_DEALER_INDEX; + discussion->players[0] = POKER_WORLD_DEALER_INDEX; discussion->emotions[0] = VN_CHARACTER_EMOTION_BORED; break; @@ -88,14 +88,14 @@ void pokerDiscussionGet( case POKER_DISCUSSION_REASON_FLOP: discussion->count++; discussion->messages[0] = "Doing the flop."; - discussion->players[0] = POKER_DEALER_INDEX; + discussion->players[0] = POKER_WORLD_DEALER_INDEX; discussion->emotions[0] = VN_CHARACTER_EMOTION_ANIME_MOM; break; case POKER_DISCUSSION_REASON_BETTING_DONE: discussion->count++; discussion->messages[0] = "Winner Winner Chicken Dinner"; - discussion->players[0] = POKER_DEALER_INDEX; + discussion->players[0] = POKER_WORLD_DEALER_INDEX; discussion->emotions[0] = VN_CHARACTER_EMOTION_SMUG_VERY; break; @@ -103,7 +103,7 @@ void pokerDiscussionGet( default: discussion->count++; discussion->messages[0] = "Hmm, this seems to be an error message."; - discussion->players[0] = POKER_DEALER_INDEX; + discussion->players[0] = POKER_WORLD_DEALER_INDEX; discussion->emotions[0] = VN_CHARACTER_EMOTION_CONCERNED_WORRIED; break; } diff --git a/src/game/poker/pokerdiscussion.h b/src/game/poker/pokerdiscussion.h index 9b153b4a..837fe2d5 100644 --- a/src/game/poker/pokerdiscussion.h +++ b/src/game/poker/pokerdiscussion.h @@ -10,7 +10,6 @@ #include "../../vn/conversation/vnconversation.h" #include "../../vn/conversation/talk.h" #include "actions/look.h" -#include "../../poker/turn.h" /** Maximum number of messages that the discussion buffer can hold */ #define POKER_DISCUSSION_MESSAGE_COUNT_MAX 32 diff --git a/src/game/poker/pokerui.c b/src/game/poker/pokerui.c index 9ff81430..a89778a6 100644 --- a/src/game/poker/pokerui.c +++ b/src/game/poker/pokerui.c @@ -35,7 +35,7 @@ void pokerUiInit(pokerui_t *ui) { labelInit(&ui->label); // Initialize the frames for each player. - for(i = 0; i < POKER_PLAYER_COUNT; i++) { + for(i = 0; i < POKER_PLAYER_COUNT_MAX; i++) { frameBufferInit(ui->frames + i, POKER_UI_PLAYER_IMAGE_RESOLUTION, POKER_UI_PLAYER_IMAGE_RESOLUTION @@ -65,7 +65,7 @@ void pokerUiUpdate( // Render the face of each player. j = 0; shaderUse(shader); - for(i = 0; i < POKER_PLAYER_COUNT; i++) { + for(i = 0; i < POKER_PLAYER_COUNT_MAX; i++) { player = players + j; // Locate the XYZ position of the camera to look at the player @@ -108,100 +108,102 @@ void pokerUiRender( scale = fontGetScale(FONT_SIZE_DEFAULT); // - if(poker->state >= POKER_STATE_DEALING) { - for(j = 0; j < POKER_PLAYER_COUNT; j++) { - player = poker->players + j; - for(i = 0; i < player->cardCount; i++) { - pokerUiSetImageToCard(&ui->card,&assets->cardTexture,player->cards[i]); - imageRender(&ui->card, &assets->shader, i * 64.0f, j * 100.0f); - } - } + // if(poker->state >= POKER_STATE_DEALING) { + // for(j = 0; j < POKER_PLAYER_COUNT_MAX; j++) { + // player = poker->players + j; + // for(i = 0; i < player->cardCount; i++) { + // pokerUiSetImageToCard(&ui->card,&assets->cardTexture,player->cards[i]); + // imageRender(&ui->card, &assets->shader, i * 64.0f, j * 100.0f); + // } + // } - for(j = 0; j < poker->dealer.cardsFacing; j++) { - pokerUiSetImageToCard( - &ui->card, &assets->cardTexture, poker->dealer.cards[j] - ); - imageRender(&ui->card, &assets->shader, 200, j * 100.0f); - } - } + // for(j = 0; j < poker->communitySize; j++) { + // pokerUiSetImageToCard( + // &ui->card, &assets->cardTexture, poker->community[j] + // ); + // imageRender(&ui->card, &assets->shader, 200, j * 100.0f); + // } + // // } - // Betting UI - if(ui->betShow) { - sprintf(message, "Press down to fold, up to raise, right to check/call."); - labelSetText(&ui->label, &assets->font, message); - labelRender(&ui->label, &assets->shader, 300, 100); + // // Betting UI + // if(ui->betShow) { + // sprintf(message, "Press down to fold, up to raise, right to check/call."); + // labelSetText(&ui->label, &assets->font, message); + // labelRender(&ui->label, &assets->shader, 300, 100); - if(inputIsPressed(&engine->input, INPUT_DOWN)) { - ui->betTurn = pokerTurnFold(poker, poker->bet.better); - ui->betTurnMade = true; - } else if(inputIsPressed(&engine->input, INPUT_RIGHT)) { - if(pokerTurnCanPlayerCheck(poker, poker->bet.better)) { - ui->betTurn = pokerTurnCheck(poker, poker->bet.better); - } else { - ui->betTurn = pokerTurnCall(poker, poker->bet.better); - } - ui->betTurnMade = true; - } + // if(inputIsPressed(&engine->input, INPUT_DOWN)) { + // ui->betTurn = pokerTurnFold(poker, poker->bet.better); + // ui->betTurnMade = true; + // } else if(inputIsPressed(&engine->input, INPUT_RIGHT)) { + // if(pokerTurnCanPlayerCheck(poker, poker->bet.better)) { + // ui->betTurn = pokerTurnCheck(poker, poker->bet.better); + // } else { + // ui->betTurn = pokerTurnCall(poker, poker->bet.better); + // } + // ui->betTurnMade = true; + // } - if(ui->betTurnMade) ui->betShow = false; - } + // if(ui->betTurnMade) ui->betShow = false; + // } - // Player UI - j = 0; - for(i = 0; i < POKER_PLAYER_COUNT; i++) { - // Get the player. - player = poker->players + i; + // // Player UI + // j = 0; + // for(i = 0; i < POKER_PLAYER_COUNT; i++) { + // // Get the player. + // player = poker->players + i; - // Position the grid itself. - x = engine->render.width - POKER_UI_PLAYER_WIDTH; - y = (float)(POKER_UI_PLAYER_HEIGHT * j); + // // Position the grid itself. + // x = engine->render.width - POKER_UI_PLAYER_WIDTH; + // y = (float)(POKER_UI_PLAYER_HEIGHT * j); - // Render face - gridGetChild(&ui->grid, 1, 0, 1, 2, &gx, &gy, &gw, &gh); - shaderUseTexture(&assets->shader, &(ui->frames + j)->texture); - shaderUsePosition(&assets->shader, x + gx, y + gy, 0, 0,0,0); - primitiveDraw(&ui->quad, 0, -1); + // // Render face + // gridGetChild(&ui->grid, 1, 0, 1, 2, &gx, &gy, &gw, &gh); + // shaderUseTexture(&assets->shader, &(ui->frames + j)->texture); + // shaderUsePosition(&assets->shader, x + gx, y + gy, 0, 0,0,0); + // primitiveDraw(&ui->quad, 0, -1); - // Render chips - sprintf(message, "$%i", player->chips); - ui->label.maxWidth = -1; - labelSetText(&ui->label, &assets->font, message); - align = gridGetAndAlignChild( - &ui->grid, 0, 0, 1, 1, - ALIGN_POS_END|ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER|ALIGN_SIZE_ORIGINAL, - ui->label.info.width, ui->label.info.height - ); - labelRender(&ui->label, &assets->shader, x+align.x, y+align.y); + // // Render chips + // sprintf(message, "$%i", player->chips); + // ui->label.maxWidth = -1; + // labelSetText(&ui->label, &assets->font, message); + // align = gridGetAndAlignChild( + // &ui->grid, 0, 0, 1, 1, + // ALIGN_POS_END|ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER|ALIGN_SIZE_ORIGINAL, + // ui->label.info.width, ui->label.info.height + // ); + // labelRender(&ui->label, &assets->shader, x+align.x, y+align.y); - // Render state - if(player->state & POKER_PLAYER_STATE_OUT) { - sprintf(message, "Out"); - } else if(player->state & POKER_PLAYER_STATE_FOLDED) { - sprintf(message, "Folded"); - } else if(player->state & POKER_PLAYER_STATE_SHOWING) { - sprintf(message, "Showing"); - } else if(poker->bet.better == j) { - sprintf(message, "Thinking"); - } else { - sprintf(message, "Whatever"); - } - labelSetText(&ui->label, &assets->font, message); - align = gridGetAndAlignChild( - &ui->grid, 0, 1, 1, 1, - ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER | ALIGN_SIZE_ORIGINAL, - ui->label.info.width, ui->label.info.height - ); - labelRender(&ui->label, &assets->shader, x+align.x, y+align.y); + // // Render state + // if(player->state & POKER_PLAYER_STATE_OUT) { + // sprintf(message, "Out"); + // } else if(player->state & POKER_PLAYER_STATE_FOLDED) { + // sprintf(message, "Folded"); + // } else if(player->state & POKER_PLAYER_STATE_SHOWING) { + // sprintf(message, "Showing"); + // } else if(poker->bet.better == j) { + // sprintf(message, "Thinking"); + // } else { + // sprintf(message, "Whatever"); + // } + // labelSetText(&ui->label, &assets->font, message); + // align = gridGetAndAlignChild( + // &ui->grid, 0, 1, 1, 1, + // ALIGN_POS_END | ALIGN_SIZE_ORIGINAL, ALIGN_POS_CENTER | ALIGN_SIZE_ORIGINAL, + // ui->label.info.width, ui->label.info.height + // ); + // labelRender(&ui->label, &assets->shader, x+align.x, y+align.y); - // Increment. - j++; - } + // // Increment. + // j++; + // } } void pokerUiDispose(pokerui_t *ui) { uint8_t i; - for(i = 0; i < POKER_PLAYER_COUNT; i++) frameBufferDispose(ui->frames + i); + for(i = 0; i < POKER_PLAYER_COUNT_MAX; i++) { + frameBufferDispose(ui->frames + i); + } labelDispose(&ui->label); primitiveDispose(&ui->quad); imageDispose(&ui->card); diff --git a/src/game/poker/pokerui.h b/src/game/poker/pokerui.h index bcc4b122..0d37c3e5 100644 --- a/src/game/poker/pokerui.h +++ b/src/game/poker/pokerui.h @@ -20,11 +20,8 @@ #include "../../vn/vncharacter.h" #include "../../ui/grid.h" #include "../../ui/align.h" -#include "../../poker/player.h" -#include "../../poker/poker.h" -#include "../../poker/bet.h" -#include "../../poker/turn.h" #include "../../vn/vnscene.h" +#include "../../poker/poker.h" #include "pokerworld.h" #include "pokergameassets.h" @@ -47,7 +44,7 @@ typedef struct { label_t label; grid_t grid; image_t card; - framebuffer_t frames[POKER_PLAYER_COUNT]; + framebuffer_t frames[POKER_PLAYER_COUNT_MAX]; /** Betting UI */ bool betShow; diff --git a/src/game/poker/pokerworld.c b/src/game/poker/pokerworld.c index 16a0e428..3ce45915 100644 --- a/src/game/poker/pokerworld.c +++ b/src/game/poker/pokerworld.c @@ -22,7 +22,7 @@ void pokerWorldInit( skywallInit(&world->skywall); // Initialize the players - for(i = 0x00; i < POKER_PLAYER_COUNT; i++) { + for(i = 0x00; i < POKER_PLAYER_COUNT_MAX; i++) { character = scene->characters + scene->characterCount; vnCharacterInit(character, &assets->pennyTexture, POKER_WORLD_PENNY_BASE_WIDTH, POKER_WORLD_PENNY_BASE_HEIGHT, diff --git a/src/game/poker/pokerworld.h b/src/game/poker/pokerworld.h index a49cdb77..12bcd649 100644 --- a/src/game/poker/pokerworld.h +++ b/src/game/poker/pokerworld.h @@ -13,9 +13,8 @@ #include "../../display/primitives/skywall.h" #include "../../vn/vnscene.h" #include "../../vn/vncharacter.h" -#include "../../poker/player.h" -#include "../../poker/dealer.h" #include "../../engine/engine.h" +#include "../../poker/poker.h" #include "pokergameassets.h" /** How far away from the camera are the characters distanced */ @@ -39,14 +38,16 @@ #define POKER_WORLD_SEAT_COUNT 8 /** The seat index for a given player index */ -#define POKER_WORLD_SEAT_FOR_PLAYER(p) (p - (POKER_PLAYER_COUNT/2)) +#define POKER_WORLD_SEAT_FOR_PLAYER(p) (p - (POKER_PLAYER_COUNT_MAX/2)) /** The seat that the dealer occupies */ -#define POKER_WORLD_SEAT_DEALER POKER_WORLD_SEAT_FOR_PLAYER(POKER_DEALER_INDEX) +#define POKER_WORLD_SEAT_DEALER POKER_WORLD_SEAT_FOR_PLAYER(\ + POKER_WORLD_DEALER_INDEX\ +) /** The seat index for a given character index */ #define pokerWorldSeatFromIndex(i) (\ - i == POKER_DEALER_INDEX ? \ + i == POKER_WORLD_DEALER_INDEX ? \ POKER_WORLD_SEAT_DEALER : \ POKER_WORLD_SEAT_FOR_PLAYER(i) \ ) diff --git a/src/poker/poker.c b/src/poker/poker.c index 3c7b322c..b00992e2 100644 --- a/src/poker/poker.c +++ b/src/poker/poker.c @@ -7,33 +7,628 @@ #include "poker.h" -void pokerGameWin(poker_t *poker) { +void pokerInit(poker_t *poker) { + poker->playerCount = 0; + poker->playerDealer = 0; + poker->playerSmallBlind = 0; + poker->playerBigBlind = 0; + pokerResetRound(poker); +} + +void pokerResetRound(poker_t *poker) { uint8_t i; - pokerplayerwinning_t *winning; pokerplayer_t *player; - int32_t chipsRounded, chipsDifferent; - float chipsEach; - poker->state = POKER_STATE_DECIDING_WINNER; + poker->deckSize = cardWriteDeck(poker->deck); + poker->graveSize = 0; + poker->communitySize = 0; + poker->potCount = 0; + pokerPotAdd(poker); - // Get the chips each. - chipsEach = poker->bet.pot / ((float)poker->winner.winnerCount); - - // Now work out the rounded offset chips. - chipsRounded = (int32_t)mathFloor(chipsEach); - chipsDifferent = poker->bet.pot - chipsRounded; - - // Let's start by rewarding the winnings to the players. - for(i = 0; i < poker->winner.winnerCount; i++) { - player = poker->players + poker->winner.winners[i]; - winning = poker->winner.winnings + i; - player->chips += chipsRounded; - if(i == 0) player->chips += chipsDifferent; - } - - // Now kill the players who are terrible low life gamblers. - for(i = 0; i < POKER_PLAYER_COUNT; i++) { + for(i = 0; i < poker->playerCount; i++) { player = poker->players + i; - if(player->chips <= 0) player->state &= POKER_PLAYER_STATE_OUT; + player->cardCount = 0; + player->currentBet = 0; + player->state &= ~( + POKER_PLAYER_STATE_FOLDED | + POKER_PLAYER_STATE_HAS_BET_THIS_ROUND | + POKER_PLAYER_STATE_SHOWING + ); } -} \ No newline at end of file +} + +void pokerNewDealer(poker_t *poker) { + uint8_t i, j, k; + pokerplayer_t *player; + bool foundDealer; + bool foundSmall; + + foundDealer = false; + foundSmall = false; + + j = poker->playerDealer + 1; + for(i = 0; i < poker->playerCount; i++) { + k = (j + i) % poker->playerCount; + player = poker->players + k; + if(player->state & POKER_PLAYER_STATE_OUT) continue; + if(!foundDealer) { + poker->playerDealer = k; + foundDealer = true; + } else if(!foundSmall) { + poker->playerSmallBlind = k; + foundSmall = true; + } else { + poker->playerBigBlind = k; + break; + } + } +} + +void pokerTakeBlinds(poker_t *poker, int32_t small, int32_t big) { + pokerPlayerBet(poker, poker->playerSmallBlind, small); + pokerPlayerBet(poker, poker->playerBigBlind, big); +} + +int32_t pokerGetCallValue(poker_t *poker) { + uint8_t i; + int32_t call; + call = 0; + for(i = 0; i < poker->playerCount; i++) { + call = mathMax(call, poker->players[i].currentBet); + } + return call; +} + +// Pot functions +uint8_t pokerPotAdd(poker_t *poker) { + pokerpot_t *pot; + uint8_t i = poker->potCount++; + pot = poker->pots + i; + pot->chips = 0; + pot->playerCount = 0; + return i; +} + +void pokerPotAddPlayer(pokerpot_t *pot, uint8_t playerIndex) { + if(arrayContains( + sizeof(uint8_t), pot->players, pot->playerCount, &playerIndex + )) return; + pot->players[pot->playerCount++] = playerIndex; +} + +// Dealer Functions +void pokerTurn(poker_t *poker, uint8_t count) { + uint8_t i; + for(i = 0; i < count; i++) { + cardDeal( + poker->deck, &poker->deckSize, poker->community, &poker->communitySize + ); + } +} + +void pokerBurn(poker_t *poker, uint8_t count) { + uint8_t i; + for(i = 0; i < count; i++) { + cardDeal(poker->deck, &poker->deckSize, poker->grave, &poker->graveSize); + } +} + +// Player Functions +uint8_t pokerPlayerAdd(poker_t *poker) { + pokerplayer_t *player; + uint8_t i = poker->playerCount++; + + player = poker->players + i; + player->cardCount = 0; + player->chips = 0; + player->currentBet = 0; + player->state = POKER_PLAYER_STATE_OUT; + + return i; +} + +void pokerPlayerDeal(poker_t *poker, pokerplayer_t *player, uint8_t count) { + uint8_t i; + for(i = 0; i < count; i++) { + cardDeal(poker->deck, &poker->deckSize, player->cards, &player->cardCount); + } +} + +void pokerPlayerChipsAdd(pokerplayer_t *player, int32_t chips) { + player->chips += chips; + if(player->chips > 0) { + player->state = flagOff(player->state, POKER_PLAYER_STATE_OUT); + } +} + +void pokerPlayerDealAll(poker_t *poker, uint8_t count) { + uint8_t i, j; + pokerplayer_t *player; + + for(j = 0; j < count; j++) { + for(i = 0; i < poker->playerCount; i++) { + player = poker->players + i; + + // Can't deal to a player who is folded or out + if(player->state & (POKER_PLAYER_STATE_FOLDED|POKER_PLAYER_STATE_OUT)) { + continue; + } + + pokerPlayerDeal(poker, player, 1); + } + } +} + +bool pokerPlayerDoesNeedToBetThisRound(poker_t *poker, uint8_t playerIndex) { + pokerplayer_t *player; + player = poker->players + playerIndex; + if(player->state & POKER_PLAYER_STATE_FOLDED) return false; + if(!(player->state & POKER_PLAYER_STATE_HAS_BET_THIS_ROUND)) return true; + if(player->currentBet < pokerGetCallValue(poker)) return true; + return false; +} + +uint8_t pokerPlayerGetRemainingBetter(poker_t *poker) { + uint8_t i, j; + + for(i = 0; i < poker->playerCount; i++) { + j = (i + poker->playerBigBlind + 1) % poker->playerCount; + if(pokerPlayerDoesNeedToBetThisRound(poker, j)) return j; + } + return 0xFF; +} + +uint8_t pokerPlayerGetNextBetter(poker_t *poker, uint8_t current) { + uint8_t i, j; + + for(i = 0; i < poker->playerCount; i++) { + j = (i + current + 1) % poker->playerCount; + if(pokerPlayerDoesNeedToBetThisRound(poker, j)) return j; + } + return 0xFF; +} + +int32_t pokerPlayerGetCallBet(poker_t *poker, pokerplayer_t *player) { + return pokerGetCallValue(poker) - player->currentBet; +} + +// Betting +void pokerPlayerBetPot( + poker_t *poker, pokerpot_t *pot, uint8_t playerIndex, int32_t chips +) { + pokerplayer_t *player; + player = poker->players + playerIndex; + player->chips -= chips; + player->currentBet += chips; + pot->chips += chips; + player->state |= POKER_PLAYER_STATE_HAS_BET_THIS_ROUND; + pokerPotAddPlayer(pot, playerIndex); +} + +void pokerPlayerBet(poker_t *poker, uint8_t playerIndex, int32_t chips) { + pokerPlayerBetPot( + poker, poker->pots + (poker->potCount - 1), playerIndex, chips + ); +} + +bool pokerPlayerCanCheck(poker_t *poker, pokerplayer_t *player) { + return pokerGetCallValue(poker) <= player->currentBet; +} + +pokerturn_t pokerTurnFold(poker_t *poker, uint8_t player) { + return (pokerturn_t){ + .chips = 0, + .confidence = 1, + .type = POKER_TURN_TYPE_FOLD + }; +} + +pokerturn_t pokerTurnBet(poker_t *poker, uint8_t playerIndex, int32_t chips) { + pokerturn_t turn; + pokerplayer_t *player; + int32_t i; + player = poker->players + playerIndex; + turn.confidence = 1; + + if(chips == 0) { + turn.type = POKER_TURN_TYPE_CHECK; + turn.chips = 0; + } else 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; + i = pokerGetCallValue(poker); + + if(chips == (i - player->currentBet)) { + turn.type = POKER_TURN_TYPE_CALL; + } + } + + return turn; +} + +// Winning +void pokerHandGetFull( + poker_t *poker, pokerplayer_t *player, card_t cards[POKER_WINNING_FULL_SIZE] +) { + uint8_t i; + + // Add the dealer hand + for(i = 0; i < poker->communitySize; i++) { + cards[i] = poker->community[i]; + } + + // Add the player hand + for(i = 0; i < player->cardCount; i++) { + cards[i+poker->communitySize] = player->cards[i]; + } +} + +void pokerWinnerFillRemaining(pokerplayerwinning_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; + } + } + + if(highest == 0xFF) break; + winning->set[winning->setSize++] = highestCard; + } + cardHandSort(winning->set, winning->setSize); +} + +void pokerWinnerGetForPlayer( + poker_t *poker, pokerplayer_t *player, pokerplayerwinning_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, but MAY not be) + winning->fullSize = poker->communitySize + player->cardCount; + pokerHandGetFull(poker, player, winning->full); + cardHandSort(winning->full, winning->fullSize); + + // 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 + ); + pokerWinnerFillRemaining(winning); + 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; + pokerWinnerFillRemaining(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; + pokerWinnerFillRemaining(winning); + 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]; + if(winning->setSize == POKER_WINNING_SET_SIZE) break; + } + if(winning->setSize < POKER_WINNING_SET_SIZE) continue; + winning->set[0] = winning->full[i]; + winning->type = POKER_WINNING_TYPE_FLUSH; + pokerWinnerFillRemaining(winning); + 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; + pokerWinnerFillRemaining(winning); + 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; + pokerWinnerFillRemaining(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[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; + + winning->type = POKER_WINNING_TYPE_TWO_PAIR; + pokerWinnerFillRemaining(winning); + return; + } + + // Pair + if(winning->setSize == 2) { + winning->type = POKER_WINNING_TYPE_PAIR; + pokerWinnerFillRemaining(winning); + return; + } + + // High card + winning->setSize = 0; + pokerWinnerFillRemaining(winning); + winning->type = POKER_WINNING_TYPE_HIGH_CARD; + + return; +} + +card_t pokerWinnerCompare(pokerplayerwinning_t *left, pokerplayerwinning_t *right) { + uint8_t i, number; + card_t card; + int32_t index; + uint8_t countCardsSame; + + card_t highCardLeft, highCardRight; + uint8_t highNumberLeft, highNumberRight; + + highNumberLeft = 0xFF; + highNumberRight = 0xFF; + countCardsSame = 0; + + + for(i = 0; i < left->setSize; i++) { + card = left->set[i]; + number = cardGetNumber(card); + if(highNumberLeft != 0xFF && number < highNumberLeft) continue;// Quick check + + // Check if this number is within the other hand or not + index = cardContainsNumber(right->set, right->setSize, number); + if(index != -1) { + // This number IS within the other hand, let's check that the EXACT card + // is a match/isn't a match. + index = cardContains(right->set, right->setSize, card); + + // Exact card match + if(index != -1) { + countCardsSame++; + continue; + } + // Not exact card match.. ? + } + + if(highNumberLeft == 0xFF||number == CARD_ACE||highNumberLeft < 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) { + index = cardContains(left->set, left->setSize, card); + if(index != -1) continue; + } + + if(highNumberRight == 0xFF||number == CARD_ACE||highNumberRight < number) { + highNumberRight = number; + highCardRight = card; + } + } + + + if(countCardsSame == left->setSize) { + for(i = 0; i < left->setSize; i++) { + card = left->set[i]; + number = cardGetNumber(card); + if(highNumberLeft == 0xFF||number == CARD_ACE||highNumberLeft < number) { + highNumberLeft = number; + highCardLeft = card; + } + } + return highCardLeft; + } + + if(highCardLeft == 0xFF) return 0xFF; + if(highNumberLeft < highNumberRight) return 0xFF; + return highCardLeft;//Greater or Equal to. +} + +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 +) { + uint8_t i, j, countPlayers, countWinners, number, highNumber; + pokerplayerwinning_t *left, *right; + pokerplayer_t *player; + card_t card, highCard; + bool isWinner; + + countPlayers = 0; + countWinners = 0; + highCard = 0xFF; + + // Get participating players and their hands. + for(i = 0; i < pot->playerCount; i++) { + player = poker->players + pot->players[i]; + if(player->state & (POKER_PLAYER_STATE_FOLDED|POKER_PLAYER_STATE_OUT)) { + continue; + } + + participants[countPlayers] = pot->players[i]; + pokerWinnerGetForPlayer(poker, player, winners + countPlayers++); + } + + // Compare participating players + for(i = 0; i < countPlayers; i++) { + left = winners + i; + isWinner = true; + highNumber = 0xFF; + + for(j = 0; j < countPlayers; j++) { + if(i == j) continue; + right = winners + j; + + // Am I the better hand / Is it the better hand? + if(left->type < right->type) continue; + if(left->type > right->type) { + isWinner = false; + break; + } + + // Equal, compare hands. + card = pokerWinnerCompare(left, right); + if(card == 0xFF) { + isWinner = false; + break; + } + + // Determine high card. + number = cardGetNumber(card); + if(highNumber == 0xFF || number == CARD_ACE || number > highNumber) { + highCard = card; + highNumber = number; + } + } + + if(!isWinner) continue; + left->kicker = highCard; + winnerPlayers[countWinners++] = participants[i]; + } + + *participantCount = countPlayers; + *winnerCount = countWinners; +} diff --git a/src/poker/poker.h b/src/poker/poker.h index aab60377..b892b604 100644 --- a/src/poker/poker.h +++ b/src/poker/poker.h @@ -7,54 +7,431 @@ #pragma once #include "../libs.h" -#include "bet.h" -#include "dealer.h" -#include "winner.h" +#include "../util/flags.h" +#include "../util/array.h" +#include "../util/math.h" +#include "card.h" -/** How many cards to deal each player during the deal round */ -#define POKER_DEAL_CARD_EACH 2 +/** 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 -/** 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 +/** 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 -#define POKER_STATE_NULL 0x00 -#define POKER_STATE_STARTING_MATCH 0x01 -#define POKER_STATE_STARTING_ROUND 0x02 -#define POKER_STATE_TAKING_BLINDS 0x03 -#define POKER_STATE_DEALING 0x04 -#define POKER_STATE_CARDS_FLOPPING 0x05 -#define POKER_STATE_BETTING 0x06 -#define POKER_STATE_DECIDING_WINNER 0x07 +/** 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) typedef struct { - /** Poker betting state */ - pokerbet_t bet; - - /** Player States */ - pokerdealer_t dealer; - pokerplayer_t players[POKER_PLAYER_COUNT]; + /** Count of chips the player has */ + int32_t chips; - /** Winning player states */ - pokerwinner_t winner; - - /** The current player that is the dealer */ - uint8_t roundDealer; - - /** Which player is the small blind for this round */ - uint8_t roundSmallBlind; - - /** Which player is the big blind for this round */ - uint8_t roundBigBlind; + /** 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; } poker_t; + /** - * Action the poker game winning state after it has been calculated previously. + * Initialize the poker game instance. * - * @param poker Poker game to action the winning state of. + * @param poker Poker game instance. */ -void pokerGameWin(poker_t *poker); \ No newline at end of file +void pokerInit(poker_t *poker); + +/** + * Reset the poker game instance for the new round. + * + * @param poker Poker game instance. + */ +void pokerResetRound(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); + + +/** + * 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 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 +); \ No newline at end of file diff --git a/src/poker2/poker.c b/src/poker2/poker.c deleted file mode 100644 index 0eaa4cc3..00000000 --- a/src/poker2/poker.c +++ /dev/null @@ -1,633 +0,0 @@ -/** - * Copyright (c) 2021 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "poker.h" - -void pokerInit(poker2_t *poker) { - poker->playerCount = 0; - poker->playerDealer = 0; - poker->playerSmallBlind = 0; - poker->playerBigBlind = 0; - pokerResetRound(poker); -} - -void pokerResetRound(poker2_t *poker) { - uint8_t i; - poker2player_t *player; - - poker->deckSize = cardWriteDeck(poker->deck); - poker->graveSize = 0; - poker->communitySize = 0; - poker->potCount = 0; - pokerPotAdd(poker); - - for(i = 0; i < poker->playerCount; i++) { - player = poker->players + i; - player->cardCount = 0; - player->currentBet = 0; - player->state &= ~( - POKER_PLAYER_STATE_FOLDED | - POKER_PLAYER_STATE_HAS_BET_THIS_ROUND - ); - } -} - -void pokerNewDealer(poker2_t *poker) { - uint8_t i, j, k; - poker2player_t *player; - bool foundDealer; - bool foundSmall; - - foundDealer = false; - foundSmall = false; - - j = poker->playerDealer + 1; - for(i = 0; i < poker->playerCount; i++) { - k = (j + i) % poker->playerCount; - player = poker->players + k; - if(player->state & POKER_PLAYER_STATE_OUT) continue; - if(!foundDealer) { - poker->playerDealer = k; - foundDealer = true; - } else if(!foundSmall) { - poker->playerSmallBlind = k; - foundSmall = true; - } else { - poker->playerBigBlind = k; - break; - } - } -} - -void pokerTakeBlinds(poker2_t *poker, int32_t small, int32_t big) { - pokerPlayerBet(poker, poker->playerSmallBlind, small); - pokerPlayerBet(poker, poker->playerBigBlind, big); -} - -int32_t pokerGetCallValue(poker2_t *poker) { - uint8_t i; - int32_t call; - call = 0; - for(i = 0; i < poker->playerCount; i++) { - call = mathMax(call, poker->players[i].currentBet); - } - return call; -} - -// Pot functions -uint8_t pokerPotAdd(poker2_t *poker) { - poker2pot_t *pot; - uint8_t i = poker->potCount++; - pot = poker->pots + i; - pot->chips = 0; - pot->playerCount = 0; - return i; -} - -void pokerPotAddPlayer(poker2pot_t *pot, uint8_t playerIndex) { - if(arrayContains( - sizeof(uint8_t), pot->players, pot->playerCount, &playerIndex - )) return; - pot->players[pot->playerCount++] = playerIndex; -} - -// Dealer Functions -void pokerTurn(poker2_t *poker, uint8_t count) { - uint8_t i; - for(i = 0; i < count; i++) { - cardDeal( - poker->deck, &poker->deckSize, poker->community, &poker->communitySize - ); - } -} - -void pokerBurn(poker2_t *poker, uint8_t count) { - uint8_t i; - for(i = 0; i < count; i++) { - cardDeal(poker->deck, &poker->deckSize, poker->grave, &poker->graveSize); - } -} - -// Player Functions -uint8_t pokerPlayerAdd(poker2_t *poker) { - poker2player_t *player; - uint8_t i = poker->playerCount++; - - player = poker->players + i; - player->cardCount = 0; - player->chips = 0; - player->currentBet = 0; - player->state = POKER_PLAYER_STATE_OUT; - - return i; -} - -void pokerPlayerDeal(poker2_t *poker, poker2player_t *player, uint8_t count) { - uint8_t i; - for(i = 0; i < count; i++) { - cardDeal(poker->deck, &poker->deckSize, player->cards, &player->cardCount); - } -} - -void pokerPlayerChipsAdd(poker2player_t *player, int32_t chips) { - player->chips += chips; - if(player->chips > 0) { - player->state = flagOff(player->state, POKER_PLAYER_STATE_OUT); - } -} - -void pokerPlayerDealAll(poker2_t *poker, uint8_t count) { - uint8_t i, j; - poker2player_t *player; - - for(j = 0; j < count; j++) { - for(i = 0; i < poker->playerCount; i++) { - player = poker->players + i; - - // Can't deal to a player who is folded or out - if(player->state & (POKER_PLAYER_STATE_FOLDED|POKER_PLAYER_STATE_OUT)) { - continue; - } - - pokerPlayerDeal(poker, player, 1); - } - } -} - -bool pokerPlayerDoesNeedToBetThisRound(poker2_t *poker, uint8_t playerIndex) { - poker2player_t *player; - player = poker->players + playerIndex; - if(player->state & POKER_PLAYER_STATE_FOLDED) return false; - if(!(player->state & POKER_PLAYER_STATE_HAS_BET_THIS_ROUND)) return true; - if(player->currentBet < pokerGetCallValue(poker)) return true; - return false; -} - -uint8_t pokerPlayerGetRemainingBetter(poker2_t *poker) { - uint8_t i, j; - - for(i = 0; i < poker->playerCount; i++) { - j = (i + poker->playerBigBlind + 1) % poker->playerCount; - if(pokerPlayerDoesNeedToBetThisRound(poker, j)) return j; - } - return 0xFF; -} - -uint8_t pokerPlayerGetNextBetter(poker2_t *poker, uint8_t current) { - uint8_t i, j; - - for(i = 0; i < poker->playerCount; i++) { - j = (i + current + 1) % poker->playerCount; - if(pokerPlayerDoesNeedToBetThisRound(poker, j)) return j; - } - return 0xFF; -} - -int32_t pokerPlayerGetCallBet(poker2_t *poker, poker2player_t *player) { - return pokerGetCallValue(poker) - player->currentBet; -} - -// Betting -void pokerPlayerBetPot( - poker2_t *poker, poker2pot_t *pot, uint8_t playerIndex, int32_t chips -) { - poker2player_t *player; - player = poker->players + playerIndex; - player->chips -= chips; - player->currentBet += chips; - pot->chips += chips; - player->state |= POKER_PLAYER_STATE_HAS_BET_THIS_ROUND; - pokerPotAddPlayer(pot, playerIndex); -} - -void pokerPlayerBet(poker2_t *poker, uint8_t playerIndex, int32_t chips) { - pokerPlayerBetPot( - poker, poker->pots + (poker->potCount - 1), playerIndex, chips - ); -} - -bool pokerPlayerCanCheck(poker2_t *poker, poker2player_t *player) { - return pokerGetCallValue(poker) <= player->currentBet; -} - -poker2turn_t pokerTurnFold(poker2_t *poker, uint8_t player) { - return (poker2turn_t){ - .chips = 0, - .confidence = 1, - .type = POKER_TURN_TYPE_FOLD - }; -} - -poker2turn_t pokerTurnBet(poker2_t *poker, uint8_t playerIndex, int32_t chips) { - poker2turn_t turn; - poker2player_t *player; - int32_t i; - player = poker->players + playerIndex; - turn.confidence = 1; - - if(chips == 0) { - turn.type = POKER_TURN_TYPE_CHECK; - turn.chips = 0; - } else 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; - i = pokerGetCallValue(poker); - - if(chips == (i - player->currentBet)) { - turn.type = POKER_TURN_TYPE_CALL; - } - } - - return turn; -} - -// Winning -void pokerHandGetFull( - poker2_t *poker, poker2player_t *player, card_t cards[POKER_WINNING_FULL_SIZE] -) { - uint8_t i; - - // Add the dealer hand - for(i = 0; i < poker->communitySize; i++) { - cards[i] = poker->community[i]; - } - - // Add the player hand - for(i = 0; i < player->cardCount; i++) { - cards[i+poker->communitySize] = player->cards[i]; - } -} - -void debug_WinnerFillRemaining(poker2playerwinning_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; - } - } - - if(highest == 0xFF) break; - winning->set[winning->setSize++] = highestCard; - } - cardHandSort(winning->set, winning->setSize); -} - -void pokerWinnerGetForPlayer( - poker2_t *poker, poker2player_t *player, poker2playerwinning_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, but MAY not be) - winning->fullSize = poker->communitySize + player->cardCount; - pokerHandGetFull(poker, player, winning->full); - cardHandSort(winning->full, winning->fullSize); - - // 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 - ); - debug_WinnerFillRemaining(winning); - 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; - debug_WinnerFillRemaining(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; - debug_WinnerFillRemaining(winning); - 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]; - if(winning->setSize == POKER_WINNING_SET_SIZE) break; - } - if(winning->setSize < POKER_WINNING_SET_SIZE) continue; - winning->set[0] = winning->full[i]; - winning->type = POKER_WINNING_TYPE_FLUSH; - debug_WinnerFillRemaining(winning); - 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; - debug_WinnerFillRemaining(winning); - 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; - debug_WinnerFillRemaining(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[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; - - winning->type = POKER_WINNING_TYPE_TWO_PAIR; - debug_WinnerFillRemaining(winning); - return; - } - - // Pair - if(winning->setSize == 2) { - winning->type = POKER_WINNING_TYPE_PAIR; - debug_WinnerFillRemaining(winning); - return; - } - - // High card - winning->setSize = 0; - debug_WinnerFillRemaining(winning); - winning->type = POKER_WINNING_TYPE_HIGH_CARD; - - return; -} - -card_t debug_pokerWinnerCompare(poker2playerwinning_t *left, poker2playerwinning_t *right) { - uint8_t i, number; - card_t card; - int32_t index; - uint8_t countCardsSame; - - card_t highCardLeft, highCardRight; - uint8_t highNumberLeft, highNumberRight; - - highNumberLeft = 0xFF; - highNumberRight = 0xFF; - countCardsSame = 0; - - - for(i = 0; i < left->setSize; i++) { - card = left->set[i]; - number = cardGetNumber(card); - if(highNumberLeft != 0xFF && number < highNumberLeft) continue;// Quick check - - // Check if this number is within the other hand or not - index = cardContainsNumber(right->set, right->setSize, number); - if(index != -1) { - // This number IS within the other hand, let's check that the EXACT card - // is a match/isn't a match. - index = cardContains(right->set, right->setSize, card); - - // Exact card match - if(index != -1) { - countCardsSame++; - continue; - } - // Not exact card match.. ? - } - - if(highNumberLeft == 0xFF||number == CARD_ACE||highNumberLeft < 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) { - index = cardContains(left->set, left->setSize, card); - if(index != -1) continue; - } - - if(highNumberRight == 0xFF||number == CARD_ACE||highNumberRight < number) { - highNumberRight = number; - highCardRight = card; - } - } - - - if(countCardsSame == left->setSize) { - for(i = 0; i < left->setSize; i++) { - card = left->set[i]; - number = cardGetNumber(card); - if(highNumberLeft == 0xFF||number == CARD_ACE||highNumberLeft < number) { - highNumberLeft = number; - highCardLeft = card; - } - } - return highCardLeft; - } - - if(highCardLeft == 0xFF) return 0xFF; - if(highNumberLeft < highNumberRight) return 0xFF; - return highCardLeft;//Greater or Equal to. -} - -void pokerWinnerDetermineForPot( - poker2_t *poker, - poker2pot_t *pot, - poker2playerwinning_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 -) { - uint8_t i, j, countPlayers, countWinners, number, highNumber; - poker2playerwinning_t *left, *right; - poker2player_t *player; - card_t card, highCard; - bool isWinner; - - countPlayers = 0; - countWinners = 0; - highCard = 0xFF; - - // Get participating players and their hands. - for(i = 0; i < pot->playerCount; i++) { - player = poker->players + pot->players[i]; - if(player->state & (POKER_PLAYER_STATE_FOLDED|POKER_PLAYER_STATE_OUT)) { - continue; - } - - participants[countPlayers] = pot->players[i]; - pokerWinnerGetForPlayer(poker, player, winners + countPlayers++); - } - - // Compare participating players - for(i = 0; i < countPlayers; i++) { - left = winners + i; - isWinner = true; - highNumber = 0xFF; - - for(j = 0; j < countPlayers; j++) { - if(i == j) continue; - right = winners + j; - - // Am I the better hand / Is it the better hand? - if(left->type < right->type) continue; - if(left->type > right->type) { - isWinner = false; - break; - } - - // Equal, compare hands. - card = debug_pokerWinnerCompare(left, right); - if(card == 0xFF) { - isWinner = false; - break; - } - - // Determine high card. - number = cardGetNumber(card); - if(highNumber == 0xFF || number == CARD_ACE || number > highNumber) { - highCard = card; - highNumber = number; - } - } - - if(!isWinner) continue; - left->kicker = highCard; - winnerPlayers[countWinners++] = participants[i]; - } - - *participantCount = countPlayers; - *winnerCount = countWinners; -} diff --git a/src/poker2/poker.h b/src/poker2/poker.h deleted file mode 100644 index c4c1db79..00000000 --- a/src/poker2/poker.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * 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 "../poker/card.h" - -#define POKER_PLAYER_COUNT_MAX 5 -#define POKER_PLAYER_HAND_SIZE_MAX 2 -#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_GRAVE_SIZE_MAX CARD_DECK_SIZE - -#define POKER_COMMUNITY_SIZE_MAX 5 -#define POKER_POT_COUNT_MAX POKER_PLAYER_COUNT_MAX - -#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 - - -#define POKER_WINNING_FULL_SIZE (\ - POKER_PLAYER_HAND_SIZE_MAX+POKER_COMMUNITY_SIZE_MAX\ -) - -#define POKER_WINNING_SET_SIZE 5 - -#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 - -typedef struct { - int32_t chips; - card_t cards[POKER_PLAYER_HAND_SIZE_MAX]; - uint8_t cardCount; - uint8_t state; - int32_t currentBet; -} poker2player_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; -} poker2playerwinning_t; - -typedef struct { - int32_t chips; - uint8_t players[POKER_PLAYER_COUNT_MAX]; - uint8_t playerCount; -} poker2pot_t; - -typedef struct { - uint8_t type; - int32_t chips; - float confidence; -} poker2turn_t; - -typedef struct { - card_t deck[CARD_DECK_SIZE]; - uint8_t deckSize; - - card_t grave[POKER_GRAVE_SIZE_MAX]; - uint8_t graveSize; - - card_t community[POKER_COMMUNITY_SIZE_MAX]; - uint8_t communitySize; - - poker2pot_t pots[POKER_POT_COUNT_MAX]; - uint8_t potCount; - - poker2player_t players[POKER_PLAYER_COUNT_MAX]; - uint8_t playerCount; - - uint8_t playerDealer; - uint8_t playerSmallBlind; - uint8_t playerBigBlind; -} poker2_t; - - - - - - - -void pokerInit(poker2_t *poker); -void pokerResetRound(poker2_t *poker); -void pokerNewDealer(poker2_t *poker); -void pokerTakeBlinds(poker2_t *poker, int32_t small, int32_t big); -int32_t pokerGetCallValue(poker2_t *poker); - -uint8_t pokerPotAdd(poker2_t *poker); -void pokerPotAddPlayer(poker2pot_t *pot, uint8_t playerIndex); - -void pokerTurn(poker2_t *poker, uint8_t count); -void pokerBurn(poker2_t *poker, uint8_t count); - -uint8_t pokerPlayerAdd(poker2_t *poker); -void pokerPlayerDeal(poker2_t *poker, poker2player_t *player, uint8_t count); -void pokerPlayerChipsAdd(poker2player_t *player, int32_t chips); -void pokerPlayerDealAll(poker2_t *poker, uint8_t count); -bool pokerPlayerDoesNeedToBetThisRound(poker2_t *poker, uint8_t playerIndex); -uint8_t pokerPlayerGetRemainingBetter(poker2_t *poker); -uint8_t pokerPlayerGetNextBetter(poker2_t *poker, uint8_t current); -int32_t pokerPlayerGetCallBet(poker2_t *poker, poker2player_t *player); -void pokerPlayerBetPot( - poker2_t *poker, poker2pot_t *pot, uint8_t playerIndex, int32_t chips -); -void pokerPlayerBet(poker2_t *poker, uint8_t playerIndex, int32_t chips); -bool pokerPlayerCanCheck(poker2_t *poker, poker2player_t *player); -poker2turn_t pokerTurnFold(poker2_t *poker, uint8_t player); -poker2turn_t pokerTurnBet(poker2_t *poker, uint8_t playerIndex, int32_t chips); -void pokerHandGetFull( - poker2_t *poker, poker2player_t *player, card_t cards[POKER_WINNING_FULL_SIZE] -); -void debug_WinnerFillRemaining(poker2playerwinning_t *winning); -void pokerWinnerGetForPlayer( - poker2_t *poker, poker2player_t *player, poker2playerwinning_t *winning -); -card_t debug_pokerWinnerCompare(poker2playerwinning_t *left, poker2playerwinning_t *right); -void pokerWinnerDetermineForPot( - poker2_t *poker, - poker2pot_t *pot, - poker2playerwinning_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 -); \ No newline at end of file diff --git a/test/poker2/poker.c b/test/poker/poker.c similarity index 92% rename from test/poker2/poker.c rename to test/poker/poker.c index 5206837f..53457e7f 100644 --- a/test/poker2/poker.c +++ b/test/poker/poker.c @@ -8,7 +8,7 @@ #include "poker.h" void test_pokerInit_should_InitializePokerGame(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); TEST_ASSERT_EQUAL_UINT8(0, poker.playerCount); TEST_ASSERT_EQUAL_UINT8(0, poker.playerDealer); @@ -17,7 +17,7 @@ void test_pokerInit_should_InitializePokerGame(void) { } void test_pokerResetRound_should_ResetTheRound(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); poker.potCount = 0x03; @@ -34,7 +34,7 @@ void test_pokerResetRound_should_ResetTheRound(void) { } void test_pokerResetRound_should_ResetThePlayers(void) { - poker2_t poker; + poker_t poker; uint8_t i; pokerInit(&poker); @@ -56,7 +56,10 @@ void test_pokerResetRound_should_ResetThePlayers(void) { TEST_ASSERT_EQUAL_INT32(0, poker.players[i].currentBet); TEST_ASSERT_EQUAL_INT32(100, poker.players[i].chips); TEST_ASSERT_BITS_LOW(POKER_PLAYER_STATE_FOLDED, poker.players[i].state); - TEST_ASSERT_BITS_LOW(POKER_PLAYER_STATE_HAS_BET_THIS_ROUND, poker.players[i].state); + TEST_ASSERT_BITS_LOW( + POKER_PLAYER_STATE_HAS_BET_THIS_ROUND, poker.players[i].state + ); + TEST_ASSERT_BITS_LOW(POKER_PLAYER_STATE_SHOWING, poker.players[i].state); TEST_ASSERT_EQUAL_UINT8( 0xFF - POKER_PLAYER_STATE_FOLDED - POKER_PLAYER_STATE_HAS_BET_THIS_ROUND, poker.players[i].state @@ -65,7 +68,7 @@ void test_pokerResetRound_should_ResetThePlayers(void) { } void test_pokerNewDealer_should_FindANewDealer(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000); @@ -101,7 +104,7 @@ void test_pokerNewDealer_should_FindANewDealer(void) { void test_pokerNewDealer_should_SkipOutPlayers(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000); @@ -127,7 +130,7 @@ void test_pokerNewDealer_should_SkipOutPlayers(void) { } void test_pokerTakeBlinds_should_TakeTheBlinds(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000); @@ -163,7 +166,7 @@ void test_pokerTakeBlinds_should_TakeTheBlinds(void) { } void test_pokerPotAdd_should_AddAPot(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); TEST_ASSERT_EQUAL_UINT8(1, poker.potCount); @@ -172,8 +175,8 @@ void test_pokerPotAdd_should_AddAPot(void) { } void test_pokerPotAdd_should_ResetThePot(void) { - poker2_t poker; - poker2pot_t *pot; + poker_t poker; + pokerpot_t *pot; uint8_t i; pokerInit(&poker); @@ -184,8 +187,8 @@ void test_pokerPotAdd_should_ResetThePot(void) { } void test_pokerPotAddPlayer_should_AddAPlayer(void) { - poker2_t poker; - poker2pot_t *pot; + poker_t poker; + pokerpot_t *pot; pokerInit(&poker); pokerPlayerAdd(&poker); @@ -204,7 +207,7 @@ void test_pokerPotAddPlayer_should_AddAPlayer(void) { } void test_pokerPlayerAdd_should_AddAPlayer(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); TEST_ASSERT_EQUAL_UINT8(0, poker.playerCount); @@ -215,8 +218,8 @@ void test_pokerPlayerAdd_should_AddAPlayer(void) { } void test_pokerPlayerAdd_should_ResetThePlayer(void) { - poker2_t poker; - poker2player_t *player; + poker_t poker; + pokerplayer_t *player; pokerInit(&poker); player = poker.players + pokerPlayerAdd(&poker); @@ -227,7 +230,7 @@ void test_pokerPlayerAdd_should_ResetThePlayer(void) { } void test_pokerTurn_should_TurnCardsFromTheDeck(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize); @@ -247,7 +250,7 @@ void test_pokerTurn_should_TurnCardsFromTheDeck(void) { } void test_pokerBurn_should_SendCardsToTheGrave(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize); @@ -268,7 +271,7 @@ void test_pokerBurn_should_SendCardsToTheGrave(void) { } void test_pokerGetCallValue_should_CalculateTheCallValue(void) { - poker2_t poker; + poker_t poker; uint8_t first, second; pokerInit(&poker); first = pokerPlayerAdd(&poker); @@ -291,7 +294,7 @@ void test_pokerGetCallValue_should_CalculateTheCallValue(void) { } void test_pokerGetCallValue_should_SkipOutPlayers(void) { - poker2_t poker; + poker_t poker; uint8_t i; pokerInit(&poker); @@ -315,9 +318,9 @@ void test_pokerGetCallValue_should_SkipOutPlayers(void) { } void test_pokerPlayerDeal_should_DealCardsToThePlayer(void) { - poker2_t poker; + poker_t poker; uint8_t playerIndex; - poker2player_t *player; + pokerplayer_t *player; pokerInit(&poker); @@ -339,9 +342,9 @@ void test_pokerPlayerDeal_should_DealCardsToThePlayer(void) { } void test_pokerPlayerChipsAdd_should_AddChipsToThePlayer(void) { - poker2_t poker; + poker_t poker; uint8_t playerIndex; - poker2player_t *player; + pokerplayer_t *player; pokerInit(&poker); playerIndex = pokerPlayerAdd(&poker); @@ -357,9 +360,9 @@ void test_pokerPlayerChipsAdd_should_AddChipsToThePlayer(void) { } void test_pokerPlayerChipsAdd_should_TurnOutStateOff(void) { - poker2_t poker; + poker_t poker; uint8_t playerIndex; - poker2player_t *player; + pokerplayer_t *player; pokerInit(&poker); playerIndex = pokerPlayerAdd(&poker); @@ -372,7 +375,7 @@ void test_pokerPlayerChipsAdd_should_TurnOutStateOff(void) { } void test_pokerPlayerDealAll_should_DealCardsToEveryone(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100); @@ -396,7 +399,7 @@ void test_pokerPlayerDealAll_should_DealCardsToEveryone(void) { } void test_pokerPlayerDealAll_should_DealMultipleCardsToEveryone(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100); @@ -420,7 +423,7 @@ void test_pokerPlayerDealAll_should_DealMultipleCardsToEveryone(void) { } void test_pokerPlayerDealAll_should_NotDealToOutPlayers(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100); @@ -442,7 +445,7 @@ void test_pokerPlayerDealAll_should_NotDealToOutPlayers(void) { } void test_pokerPlayerDealAll_should_NotDealToFoldedPlayers(void) { - poker2_t poker; + poker_t poker; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100); @@ -462,7 +465,7 @@ void test_pokerPlayerDealAll_should_NotDealToFoldedPlayers(void) { } void test_pokerPlayerDoesNeedToBetThisRound_should_CheckCallValue(void) { - poker2_t poker; + poker_t poker; uint8_t first, second; pokerInit(&poker); @@ -486,7 +489,7 @@ void test_pokerPlayerDoesNeedToBetThisRound_should_CheckCallValue(void) { } void test_pokerPlayerDoesNeedToBetThisRound_should_CheckWhetherHasBetYet(void) { - poker2_t poker; + poker_t poker; uint8_t first, second; pokerInit(&poker); first = pokerPlayerAdd(&poker); @@ -507,7 +510,7 @@ void test_pokerPlayerDoesNeedToBetThisRound_should_CheckWhetherHasBetYet(void) { } void test_pokerPlayerDoesNeedToBetThisRound_should_IgnoreFoldedPlayers(void) { - poker2_t poker; + poker_t poker; uint8_t first, second; pokerInit(&poker); first = pokerPlayerAdd(&poker); @@ -532,7 +535,7 @@ void test_pokerPlayerDoesNeedToBetThisRound_should_IgnoreFoldedPlayers(void) { } void test_pokerPlayerGetRemainingBetter_should_ReturnRemainingBetters(void) { - poker2_t poker; + poker_t poker; uint8_t p0, p1, p2, p3, p4; pokerInit(&poker); @@ -585,7 +588,7 @@ void test_pokerPlayerGetRemainingBetter_should_ReturnRemainingBetters(void) { } void test_pokerPlayerGetNextBetter_should_GetTheNextBetter(void) { - poker2_t poker; + poker_t poker; uint8_t p0, p1, p2, p3, p4; uint8_t better; pokerInit(&poker); @@ -650,7 +653,7 @@ void test_pokerPlayerGetNextBetter_should_GetTheNextBetter(void) { } void test_pokerPlayerGetCallBet_should_GetCallBet(void) { - poker2_t poker; + poker_t poker; uint8_t p0, p1, p2; pokerInit(&poker); @@ -675,9 +678,9 @@ void test_pokerPlayerGetCallBet_should_GetCallBet(void) { } void test_pokerPlayerBetPot_should_AddChipsToThePot(void) { - poker2_t poker; - poker2pot_t *pot; - poker2player_t *player; + poker_t poker; + pokerpot_t *pot; + pokerplayer_t *player; uint8_t i; pokerInit(&poker); @@ -695,9 +698,9 @@ void test_pokerPlayerBetPot_should_AddChipsToThePot(void) { } void test_pokerPlayerBetPot_should_UpdatePlayerState(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; + pokerplayer_t *player; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -716,8 +719,8 @@ void test_pokerPlayerBetPot_should_UpdatePlayerState(void) { } void test_pokerPlayerBet_should_BetToTheActivePot(void) { - poker2_t poker; - poker2pot_t *pot; + poker_t poker; + pokerpot_t *pot; uint8_t i, j; pokerInit(&poker); @@ -737,7 +740,7 @@ void test_pokerPlayerBet_should_BetToTheActivePot(void) { } void test_pokerPlayerCanCheck_should_CompareThePotAndPlayerBet(void) { - poker2_t poker; + poker_t poker; uint8_t p0, p1, p2; pokerInit(&poker); @@ -775,8 +778,8 @@ void test_pokerPlayerCanCheck_should_CompareThePotAndPlayerBet(void) { } void test_pokerTurnFold_should_ReturnAFoldAction(void) { - poker2_t poker; - poker2turn_t turn; + poker_t poker; + pokerturn_t turn; pokerInit(&poker); pokerPlayerAdd(&poker); @@ -787,8 +790,8 @@ void test_pokerTurnFold_should_ReturnAFoldAction(void) { } void test_pokerTurnBet_should_ReturnACheckAction(void) { - poker2_t poker; - poker2turn_t turn; + poker_t poker; + pokerturn_t turn; pokerInit(&poker); pokerPlayerAdd(&poker); @@ -799,8 +802,8 @@ void test_pokerTurnBet_should_ReturnACheckAction(void) { } void test_pokerTurnBet_should_ReturnAnAllInAction(void) { - poker2_t poker; - poker2turn_t turn; + poker_t poker; + pokerturn_t turn; pokerInit(&poker); pokerPlayerAdd(&poker); pokerPlayerChipsAdd(poker.players, 500); @@ -818,8 +821,8 @@ void test_pokerTurnBet_should_ReturnAnAllInAction(void) { } void test_pokerTurnBet_should_ReturnACallAction(void) { - poker2_t poker; - poker2turn_t turn; + poker_t poker; + pokerturn_t turn; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000); @@ -840,8 +843,8 @@ void test_pokerTurnBet_should_ReturnACallAction(void) { } void test_pokerTurnBet_should_ReturnARaiseAction(void) { - poker2_t poker; - poker2turn_t turn; + poker_t poker; + pokerturn_t turn; pokerInit(&poker); pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000); @@ -857,8 +860,8 @@ void test_pokerTurnBet_should_ReturnARaiseAction(void) { } void test_pokerHandGetFull_should_ReturnTheFullHand(void) { - poker2_t poker; - poker2player_t *player; + poker_t poker; + pokerplayer_t *player; uint8_t i; card_t cards[POKER_WINNING_FULL_SIZE]; @@ -905,7 +908,7 @@ void test_pokerHandGetFull_should_ReturnTheFullHand(void) { } void test_pokerWinnerFillRemaining_should_FillTheRestOfTheArray(void) { - poker2playerwinning_t winning; + pokerplayerwinning_t winning; winning.fullSize = 7; winning.full[0] = CARD_CLUBS_ACE; winning.full[1] = CARD_CLUBS_TWO; @@ -920,7 +923,7 @@ void test_pokerWinnerFillRemaining_should_FillTheRestOfTheArray(void) { winning.setSize = 1; winning.set[0] = CARD_CLUBS_ACE; - debug_WinnerFillRemaining(&winning); + pokerWinnerFillRemaining(&winning); TEST_ASSERT_EQUAL_UINT8(POKER_WINNING_SET_SIZE, winning.setSize); TEST_ASSERT_EQUAL_UINT8(CARD_CLUBS_ACE, winning.set[0]); TEST_ASSERT_EQUAL_UINT8(CARD_CLUBS_SEVEN, winning.set[1]); @@ -930,10 +933,10 @@ void test_pokerWinnerFillRemaining_should_FillTheRestOfTheArray(void) { } void test_pokerWinnerGetForPlayer_should_CalculateHighCard(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -963,10 +966,10 @@ void test_pokerWinnerGetForPlayer_should_CalculateHighCard(void) { } void test_pokerWinnerGetForPlayer_should_CalculatePair(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1008,10 +1011,10 @@ void test_pokerWinnerGetForPlayer_should_CalculatePair(void) { } void test_pokerWinnerGetForPlayer_should_CalculateTwoPair(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1037,10 +1040,10 @@ void test_pokerWinnerGetForPlayer_should_CalculateTwoPair(void) { } void test_pokerWinnerGetForPlayer_should_CalculateThreeOfAKind(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1066,10 +1069,10 @@ void test_pokerWinnerGetForPlayer_should_CalculateThreeOfAKind(void) { } void test_pokerWinnerGetForPlayer_should_CalculateAStraight(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1095,10 +1098,10 @@ void test_pokerWinnerGetForPlayer_should_CalculateAStraight(void) { } void test_pokerWinnerGetForPlayer_should_CalculateAFlush(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1124,10 +1127,10 @@ void test_pokerWinnerGetForPlayer_should_CalculateAFlush(void) { } void test_pokerWinnerGet_should_CalculateFullHouse(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1153,10 +1156,10 @@ void test_pokerWinnerGet_should_CalculateFullHouse(void) { } void test_pokerWinnerGetForPlayer_should_CalculateFourOfAKind(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1182,10 +1185,10 @@ void test_pokerWinnerGetForPlayer_should_CalculateFourOfAKind(void) { } void test_pokerWinnerGetForPlayer_should_CalculateStraightFlush(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1211,10 +1214,10 @@ void test_pokerWinnerGetForPlayer_should_CalculateStraightFlush(void) { } void test_pokerWinnerGetForPlayer_should_CalculateRoyalFlush(void) { - poker2_t poker; + poker_t poker; uint8_t i; - poker2player_t *player; - poker2playerwinning_t winning; + pokerplayer_t *player; + pokerplayerwinning_t winning; pokerInit(&poker); i = pokerPlayerAdd(&poker); @@ -1240,11 +1243,11 @@ void test_pokerWinnerGetForPlayer_should_CalculateRoyalFlush(void) { } void test_pokerWinnerCompare_should_CompareWinningHands(void) { - poker2_t poker; + poker_t poker; uint8_t p0i, p1i; - poker2player_t *p0; - poker2player_t *p1; - poker2playerwinning_t w0, w1; + pokerplayer_t *p0; + pokerplayer_t *p1; + pokerplayerwinning_t w0, w1; card_t kicker; // Construct two hands of the same type (pairs of eights) @@ -1277,7 +1280,7 @@ void test_pokerWinnerCompare_should_CompareWinningHands(void) { TEST_ASSERT_EQUAL_UINT8(w0.type, w1.type); // Get the kicker, should be the king. - kicker = debug_pokerWinnerCompare(&w0, &w1); + kicker = pokerWinnerCompare(&w0, &w1); TEST_ASSERT_EQUAL_UINT8(CARD_CLUBS_KING, kicker); // Change the kickers @@ -1285,48 +1288,53 @@ void test_pokerWinnerCompare_should_CompareWinningHands(void) { p1->cards[1] = CARD_CLUBS_KING; pokerWinnerGetForPlayer(&poker, p0, &w0); pokerWinnerGetForPlayer(&poker, p1, &w1); - kicker = debug_pokerWinnerCompare(&w0, &w1); + kicker = pokerWinnerCompare(&w0, &w1); TEST_ASSERT_EQUAL_UINT8(CARD_HEARTS_ACE, kicker); // Low left weight p0->cards[1] = CARD_HEARTS_JACK; pokerWinnerGetForPlayer(&poker, p0, &w0); - kicker = debug_pokerWinnerCompare(&w0, &w1); + kicker = pokerWinnerCompare(&w0, &w1); TEST_ASSERT_EQUAL_UINT8(0xFF, kicker); } void test_pokerWinnerDetermine_should_DecideTheWinnerCorrectly(void) { - poker2_t poker; - uint8_t p0i, p1i; - poker2player_t *p0; - poker2player_t *p1; + poker_t poker; + uint8_t p0i, p1i, p2i; + pokerplayer_t *p0; + pokerplayer_t *p1; + pokerplayer_t *p2; // Outputs uint8_t winnerCount, participantCount; uint8_t winnerPlayers[POKER_PLAYER_COUNT_MAX]; uint8_t participants[POKER_PLAYER_COUNT_MAX]; - poker2playerwinning_t winners[POKER_PLAYER_COUNT_MAX]; + pokerplayerwinning_t winners[POKER_PLAYER_COUNT_MAX]; // Set up the players pokerInit(&poker); p0i = pokerPlayerAdd(&poker); p1i = pokerPlayerAdd(&poker); + p2i = pokerPlayerAdd(&poker); p0 = poker.players + p0i; p1 = poker.players + p1i; + p2 = poker.players + p2i; pokerPotAddPlayer(poker.pots + 0, p0i); pokerPotAddPlayer(poker.pots + 0, p1i); + pokerPotAddPlayer(poker.pots + 0, p2i); pokerPlayerChipsAdd(p0, 10000); pokerPlayerChipsAdd(p1, 10000); + pokerPlayerChipsAdd(p2, 10000); // Set up the community poker.communitySize = 5; poker.community[0] = CARD_HEARTS_TWO; poker.community[1] = CARD_DIAMONDS_NINE; poker.community[2] = CARD_DIAMONDS_FOUR; - poker.community[3] = CARD_CLUBS_SIX; + poker.community[3] = CARD_DIAMONDS_SIX; poker.community[4] = CARD_HEARTS_EIGHT; // Set up the player hands @@ -1338,6 +1346,11 @@ void test_pokerWinnerDetermine_should_DecideTheWinnerCorrectly(void) { p1->cards[0] = CARD_SPADES_EIGHT; p1->cards[1] = CARD_CLUBS_QUEEN;//Low, not + p2->state |= POKER_PLAYER_STATE_FOLDED;// Start folded + p2->cardCount = 2; + p2->cards[0] = CARD_DIAMONDS_TWO; + p2->cards[1] = CARD_DIAMONDS_KING; + // Run first test. pokerWinnerDetermineForPot( &poker, poker.pots + 0, @@ -1369,10 +1382,44 @@ void test_pokerWinnerDetermine_should_DecideTheWinnerCorrectly(void) { TEST_ASSERT_EQUAL_UINT8(1, winnerPlayers[0]); TEST_ASSERT_EQUAL_UINT8(0, participants[0]); TEST_ASSERT_EQUAL_UINT8(1, participants[1]); + + // Unfold p2 + p2->state = flagOff(p2->state, POKER_PLAYER_STATE_FOLDED); + pokerWinnerDetermineForPot( + &poker, poker.pots + 0, + winners, winnerPlayers, &winnerCount, + participants, &participantCount + ); + TEST_ASSERT_EQUAL_UINT8(1, winnerCount); + TEST_ASSERT_EQUAL_UINT8(3, participantCount); + TEST_ASSERT_EQUAL_UINT8(POKER_WINNING_TYPE_PAIR, winners[0].type); + TEST_ASSERT_EQUAL_UINT8(POKER_WINNING_TYPE_TWO_PAIR, winners[1].type); + TEST_ASSERT_EQUAL_UINT8(POKER_WINNING_TYPE_FLUSH, winners[2].type); + TEST_ASSERT_EQUAL_UINT8(2, winnerPlayers[0]); + TEST_ASSERT_EQUAL_UINT8(0, participants[0]); + TEST_ASSERT_EQUAL_UINT8(1, participants[1]); + TEST_ASSERT_EQUAL_UINT8(2, participants[2]); + + // Create a new pot that P2 isn't participating in. + pokerPotAdd(&poker); + pokerPotAddPlayer(poker.pots + 1, p0i); + pokerPotAddPlayer(poker.pots + 1, p1i); + pokerWinnerDetermineForPot( + &poker, poker.pots + 1, + winners, winnerPlayers, &winnerCount, + participants, &participantCount + ); + TEST_ASSERT_EQUAL_UINT8(1, winnerCount); + TEST_ASSERT_EQUAL_UINT8(2, participantCount); + TEST_ASSERT_EQUAL_UINT8(POKER_WINNING_TYPE_PAIR, winners[0].type); + TEST_ASSERT_EQUAL_UINT8(POKER_WINNING_TYPE_TWO_PAIR, winners[1].type); + TEST_ASSERT_EQUAL_UINT8(1, winnerPlayers[0]); + TEST_ASSERT_EQUAL_UINT8(0, participants[0]); + TEST_ASSERT_EQUAL_UINT8(1, participants[1]); } -int test_poker2() { +int test_poker() { UNITY_BEGIN(); RUN_TEST(test_pokerInit_should_InitializePokerGame); diff --git a/test/poker2/poker.h b/test/poker/poker.h similarity index 100% rename from test/poker2/poker.h rename to test/poker/poker.h