From 65d2cf8a760638b1ba88cce1e589df8ba1f3aedd Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Sun, 3 Oct 2021 00:50:11 -0700
Subject: [PATCH] More poker tests.

---
 src/poker2/poker.c  |  65 ++++++++++++---
 src/poker2/poker.h  |  11 +++
 test/poker2/poker.c | 195 ++++++++++++++++++++++++++++++++++++++++----
 3 files changed, 244 insertions(+), 27 deletions(-)

diff --git a/src/poker2/poker.c b/src/poker2/poker.c
index 70a933af..3657bdae 100644
--- a/src/poker2/poker.c
+++ b/src/poker2/poker.c
@@ -11,6 +11,10 @@ void pokerInit(poker2_t *poker) {
   pokerResetRound(poker);
   poker->playerCount = 0;
   poker->state = 0;
+  poker->playerDealer = 0;
+  poker->playerSmallBlind = 0;
+  poker->playerBigBlind = 0;
+
 }
 
 void pokerResetRound(poker2_t *poker) {
@@ -21,6 +25,38 @@ void pokerResetRound(poker2_t *poker) {
   pokerPotAdd(poker);
 }
 
+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);
+}
+
 // Pot functions
 uint8_t pokerPotAdd(poker2_t *poker) {
   poker2pot_t *pot;
@@ -55,15 +91,16 @@ void pokerBurn(poker2_t *poker, uint8_t count) {
   }
 }
 
-
 // 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->state = 0x00;
+  player->state = POKER_PLAYER_STATE_OUT;
+  
   return i;
 }
 
@@ -77,22 +114,25 @@ void pokerPlayerDeal(poker2_t *poker, poker2player_t *player, uint8_t count) {
 void pokerPlayerChipsAdd(poker2player_t *player, int32_t chips) {
   player->chips += chips;
   if(player->chips > 0) {
-    flagOff(player->state, POKER_PLAYER_STATE_OUT);
+    player->state = flagOff(player->state, POKER_PLAYER_STATE_OUT);
   }
 }
 
 void pokerPlayerDealAll(poker2_t *poker, uint8_t count) {
-  uint8_t i;
+  uint8_t i, j;
   poker2player_t *player;
-  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, count);
+  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);
+    }
   }
 }
 
@@ -104,6 +144,7 @@ void pokerPlayerBetPot(
   player = poker->players + playerIndex;
   player->chips -= chips;
   pot->chips += chips;
+  player->state |= POKER_PLAYER_STATE_HAS_BET_THIS_ROUND;
   pokerPotAddPlayer(pot, playerIndex);
 }
 
diff --git a/src/poker2/poker.h b/src/poker2/poker.h
index fb5019fa..515e814e 100644
--- a/src/poker2/poker.h
+++ b/src/poker2/poker.h
@@ -15,6 +15,7 @@
 #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
 
@@ -50,6 +51,11 @@ typedef struct {
   poker2player_t players[POKER_PLAYER_COUNT_MAX];
   uint8_t playerCount;
 
+  uint8_t playerDealer;
+  uint8_t playerSmallBlind;
+  uint8_t playerBigBlind;
+
+
   uint8_t state;
 } poker2_t;
 
@@ -61,10 +67,15 @@ typedef struct {
 
 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);
+
 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);
diff --git a/test/poker2/poker.c b/test/poker2/poker.c
index 18d0289f..b338e315 100644
--- a/test/poker2/poker.c
+++ b/test/poker2/poker.c
@@ -10,8 +10,11 @@
 void test_pokerInit_should_InitializePokerGame(void) {
   poker2_t poker;
   pokerInit(&poker);
-  TEST_ASSERT_EQUAL_INT8(0, poker.playerCount);
-  TEST_ASSERT_EQUAL_INT8(0, poker.state);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerCount);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.state);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerBigBlind);
 }
 
 void test_pokerResetRound_should_ResetTheRound(void) {
@@ -31,6 +34,104 @@ void test_pokerResetRound_should_ResetTheRound(void) {
   TEST_ASSERT_EQUAL_UINT8(1, poker.potCount);
 }
 
+void test_pokerNewDealer_should_FindANewDealer(void) {
+  poker2_t poker;
+  pokerInit(&poker);
+
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerBigBlind);
+
+  pokerNewDealer(&poker);
+  TEST_ASSERT_EQUAL_UINT8(1, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(2, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(3, poker.playerBigBlind);
+
+  pokerNewDealer(&poker);
+  TEST_ASSERT_EQUAL_UINT8(2, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(3, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(4, poker.playerBigBlind);
+
+  pokerNewDealer(&poker);
+  TEST_ASSERT_EQUAL_UINT8(3, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(4, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerBigBlind);
+
+  pokerNewDealer(&poker);
+  TEST_ASSERT_EQUAL_UINT8(4, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(1, poker.playerBigBlind);
+}
+
+void test_pokerNewDealer_should_SkipOutPlayers(void) {
+  
+  poker2_t poker;
+  pokerInit(&poker);
+
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerAdd(&poker);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerAdd(&poker);
+
+  pokerNewDealer(&poker);
+  TEST_ASSERT_EQUAL_UINT8(1, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(3, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerBigBlind);
+  
+  pokerNewDealer(&poker);
+  TEST_ASSERT_EQUAL_UINT8(3, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(1, poker.playerBigBlind);
+
+  pokerNewDealer(&poker);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.playerDealer);
+  TEST_ASSERT_EQUAL_UINT8(1, poker.playerSmallBlind);
+  TEST_ASSERT_EQUAL_UINT8(3, poker.playerBigBlind);
+}
+
+void test_pokerTakeBlinds_should_TakeTheBlinds(void) {
+  poker2_t poker;
+  pokerInit(&poker);
+
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 1000);
+
+  pokerNewDealer(&poker);
+
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 0)->chips);
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 1)->chips);
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 2)->chips);
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 3)->chips);
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 4)->chips);
+
+  pokerTakeBlinds(&poker, 100, 200);
+
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 0)->chips);
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 1)->chips);
+  TEST_ASSERT_EQUAL_INT32(900, (poker.players + 2)->chips);
+  TEST_ASSERT_EQUAL_INT32(800, (poker.players + 3)->chips);
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 4)->chips);
+  
+  pokerNewDealer(&poker);
+  pokerTakeBlinds(&poker, 100, 200);
+
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 0)->chips);
+  TEST_ASSERT_EQUAL_INT32(1000, (poker.players + 1)->chips);
+  TEST_ASSERT_EQUAL_INT32(900, (poker.players + 2)->chips);
+  TEST_ASSERT_EQUAL_INT32(700, (poker.players + 3)->chips);
+  TEST_ASSERT_EQUAL_INT32(800, (poker.players + 4)->chips);
+}
+
 void test_pokerPotAdd_should_AddAPot(void) {
   poker2_t poker;
   pokerInit(&poker);
@@ -90,7 +191,7 @@ void test_pokerPlayerAdd_should_ResetThePlayer(void) {
 
   player = poker.players + pokerPlayerAdd(&poker);
   TEST_ASSERT_EQUAL_INT32(0, player->chips);
-  TEST_ASSERT_EQUAL_UINT8(0, player->state);
+  TEST_ASSERT_EQUAL_UINT8(POKER_PLAYER_STATE_OUT, player->state);
   TEST_ASSERT_EQUAL_UINT8(0, player->cardCount);
 }
 
@@ -189,23 +290,24 @@ void test_pokerPlayerChipsAdd_should_TurnOutStateOff(void) {
   player->state |= POKER_PLAYER_STATE_OUT;
   TEST_ASSERT_BITS_HIGH(POKER_PLAYER_STATE_OUT, player->state);
   pokerPlayerChipsAdd(player, 32);
-  TEST_ASSERT_BIT_LOW(POKER_PLAYER_STATE_OUT, player->state);
+  TEST_ASSERT_BITS_LOW(POKER_PLAYER_STATE_OUT, player->state);
 }
 
 void test_pokerPlayerDealAll_should_DealCardsToEveryone(void) {
   poker2_t poker;
   pokerInit(&poker);
 
-  pokerPlayerAdd(&poker);
-  pokerPlayerAdd(&poker);
-  pokerPlayerAdd(&poker);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
 
   TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize);
   TEST_ASSERT_EQUAL_UINT8(0, poker.players[0].cardCount);
   TEST_ASSERT_EQUAL_UINT8(0, poker.players[1].cardCount);
   TEST_ASSERT_EQUAL_UINT8(0, poker.players[2].cardCount);
   
-  pokerPlayerDealAll(&poker, 0x01);
+  pokerPlayerDealAll(&poker, 1);
+  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE - 3, poker.deckSize);
   TEST_ASSERT_EQUAL_UINT8(1, poker.players[0].cardCount);
   TEST_ASSERT_EQUAL_UINT8(1, poker.players[1].cardCount);
   TEST_ASSERT_EQUAL_UINT8(1, poker.players[2].cardCount);
@@ -219,9 +321,9 @@ void test_pokerPlayerDealAll_should_DealMultipleCardsToEveryone(void) {
   poker2_t poker;
   pokerInit(&poker);
 
-  pokerPlayerAdd(&poker);
-  pokerPlayerAdd(&poker);
-  pokerPlayerAdd(&poker);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
 
   TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize);
   TEST_ASSERT_EQUAL_UINT8(0, poker.players[0].cardCount);
@@ -232,13 +334,55 @@ void test_pokerPlayerDealAll_should_DealMultipleCardsToEveryone(void) {
   TEST_ASSERT_EQUAL_UINT8(2, poker.players[2].cardCount);
   
   TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_ACE, poker.players[0].cards[0]);
-  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_KING, poker.players[0].cards[1]);
-  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_QUEEN, poker.players[1].cards[0]);
-  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_JACK, poker.players[1].cards[1]);
-  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_TEN, poker.players[2].cards[0]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_KING, poker.players[1].cards[0]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_QUEEN, poker.players[2].cards[0]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_JACK, poker.players[0].cards[1]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_TEN, poker.players[1].cards[1]);
   TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_NINE, poker.players[2].cards[1]);
 }
 
+void test_pokerPlayerDealAll_should_NotDealToOutPlayers(void) {
+  poker2_t poker;
+  pokerInit(&poker);
+
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  pokerPlayerAdd(&poker);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+
+  TEST_ASSERT_EQUAL_UINT8(CARD_DECK_SIZE, poker.deckSize);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.players[0].cardCount);
+  
+  pokerPlayerDealAll(&poker, 0x02);
+  TEST_ASSERT_EQUAL_UINT8(2, poker.players[0].cardCount);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.players[1].cardCount);
+  TEST_ASSERT_EQUAL_UINT8(2, poker.players[2].cardCount);
+  
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_ACE, poker.players[0].cards[0]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_KING, poker.players[2].cards[0]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_QUEEN, poker.players[0].cards[1]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_JACK, poker.players[2].cards[1]);
+}
+
+void test_pokerPlayerDealAll_should_NotDealToFoldedPlayers(void) {
+  poker2_t poker;
+  pokerInit(&poker);
+
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  pokerPlayerChipsAdd(poker.players + pokerPlayerAdd(&poker), 100);
+  poker.players[0].state |= POKER_PLAYER_STATE_FOLDED;
+
+  pokerPlayerDealAll(&poker, 2);
+  TEST_ASSERT_EQUAL_UINT8(0, poker.players[0].cardCount);
+  TEST_ASSERT_EQUAL_UINT8(2, poker.players[1].cardCount);
+  TEST_ASSERT_EQUAL_UINT8(2, poker.players[2].cardCount);
+  
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_ACE, poker.players[1].cards[0]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_KING, poker.players[2].cards[0]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_QUEEN, poker.players[1].cards[1]);
+  TEST_ASSERT_EQUAL_UINT8(CARD_SPADES_JACK, poker.players[2].cards[1]);
+}
+
 void test_pokerPlayerBetPot_should_AddChipsToThePot(void) {
   poker2_t poker;
   poker2pot_t *pot;
@@ -259,6 +403,21 @@ void test_pokerPlayerBetPot_should_AddChipsToThePot(void) {
   TEST_ASSERT_EQUAL_INT32(900, player->chips);
 }
 
+void test_pokerPlayerBetPot_should_UpdatePlayerState(void) {
+  poker2_t poker;
+  uint8_t i;
+  poker2player_t *player;
+
+  pokerInit(&poker);
+  i = pokerPlayerAdd(&poker);
+  player = poker.players + i;
+  pokerPlayerChipsAdd(player, 1000);
+  
+  TEST_ASSERT_BITS_LOW(POKER_PLAYER_STATE_HAS_BET_THIS_ROUND, player->state);
+  pokerPlayerBetPot(&poker, poker.pots, i, 100);
+  TEST_ASSERT_BITS_HIGH(POKER_PLAYER_STATE_HAS_BET_THIS_ROUND, player->state);
+}
+
 void test_pokerPlayerBet_should_BetToTheActivePot(void) {
   poker2_t poker;
   poker2pot_t *pot;
@@ -287,6 +446,9 @@ int test_poker() {
   RUN_TEST(test_pokerResetRound_should_ResetTheRound);
   RUN_TEST(test_pokerPotAdd_should_AddAPot);
   RUN_TEST(test_pokerPotAdd_should_ResetThePot);
+  RUN_TEST(test_pokerNewDealer_should_FindANewDealer);
+  RUN_TEST(test_pokerNewDealer_should_SkipOutPlayers);
+  RUN_TEST(test_pokerTakeBlinds_should_TakeTheBlinds);
   RUN_TEST(test_pokerPotAddPlayer_should_AddAPlayer);
   RUN_TEST(test_pokerPlayerAdd_should_ResetThePlayer);
   RUN_TEST(test_pokerTurn_should_TurnCardsFromTheDeck);
@@ -296,7 +458,10 @@ int test_poker() {
   RUN_TEST(test_pokerPlayerChipsAdd_should_TurnOutStateOff);
   RUN_TEST(test_pokerPlayerDealAll_should_DealCardsToEveryone);
   RUN_TEST(test_pokerPlayerDealAll_should_DealMultipleCardsToEveryone);
+  RUN_TEST(test_pokerPlayerDealAll_should_NotDealToOutPlayers);
+  RUN_TEST(test_pokerPlayerDealAll_should_NotDealToFoldedPlayers);
   RUN_TEST(test_pokerPlayerBetPot_should_AddChipsToThePot);
+  RUN_TEST(test_pokerPlayerBetPot_should_UpdatePlayerState);
   RUN_TEST(test_pokerPlayerBet_should_BetToTheActivePot);
 
   return UNITY_END();