From ad34be05e3afedef49e41bb327eb781638c0e449 Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Sun, 20 Nov 2022 23:17:40 -0800
Subject: [PATCH] Working on refactoring winning.

---
 src/dawn/poker/Card.cpp         |  1 +
 src/dawn/poker/Card.hpp         |  8 +++
 src/dawn/poker/PokerPlayer.cpp  | 92 +++++++++++++++++++--------------
 src/dawn/poker/PokerWinning.hpp |  1 +
 4 files changed, 62 insertions(+), 40 deletions(-)

diff --git a/src/dawn/poker/Card.cpp b/src/dawn/poker/Card.cpp
index 6622523e..05e7de7e 100644
--- a/src/dawn/poker/Card.cpp
+++ b/src/dawn/poker/Card.cpp
@@ -13,6 +13,7 @@ void Card::fillDeck(std::vector<struct Card> *deck) {
   }
 }
 
+
 void Card::sort(std::vector<struct Card> *deck) {
   std::sort(deck->begin(), deck->end(), &cardSorter);
 }
diff --git a/src/dawn/poker/Card.hpp b/src/dawn/poker/Card.hpp
index 41933ed3..c3713486 100644
--- a/src/dawn/poker/Card.hpp
+++ b/src/dawn/poker/Card.hpp
@@ -45,6 +45,11 @@ namespace Dawn {
 
       static void fillDeck(std::vector<struct Card> *deck); 
       static void shuffle(std::vector<struct Card> *deck);
+      static bool_t contains(std::vector<struct Card> *deck, struct Card);
+      static std::vector<struct Card> countPairs(
+        std::vector<struct Card> *deck,
+        enum CardValue value
+      );
 
       /**
        * Sort a hand of cards. Cards are ordered in descending weight, aces are
@@ -58,9 +63,12 @@ namespace Dawn {
       Card(CardSuit suit, CardValue num) :
         cardValue((suit * CARD_COUNT_PER_SUIT) + num)
       {
+        assertTrue(suit < CARD_SUIT_COUNT);
+        assertTrue(num < CARD_COUNT_PER_SUIT);
       }
 
       Card(uint8_t cv) : cardValue(cv) {
+        assertTrue(cv < CARD_DECK_SIZE);
       }
 
       CardValue getValue() {
diff --git a/src/dawn/poker/PokerPlayer.cpp b/src/dawn/poker/PokerPlayer.cpp
index 176e2537..1a524799 100644
--- a/src/dawn/poker/PokerPlayer.cpp
+++ b/src/dawn/poker/PokerPlayer.cpp
@@ -239,6 +239,7 @@ int32_t PokerPlayer::getSumOfChips() {
 
 struct PokerWinning PokerPlayer::getWinning() {
   struct PokerWinning winning;
+  uint8_t i, j, l;
 
   // Get the full poker hand (should be a 7 card hand, but MAY not be)
   auto itHand = this->hand.begin();
@@ -260,78 +261,89 @@ struct PokerWinning PokerPlayer::getWinning() {
   auto it = winning.full.begin();
   while(it != winning.full.end()) {
     auto number = it->getValue();
+    auto suit = it->getSuit();
     if(number < CARD_FIVE) {
       ++it;
       continue;
     }
 
-    auto suit = it->getSuit();
-    winning->setSize = 1;
+    winning.set.clear();
+    winning.set.push_back(*it);
 
     // 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++;
+      auto c = Card(suit, (CardValue)l);
+      if(!Card::contains(&winning.full, c)) break;
+      winning.set.push_back(c);
     }
 
     // Check if has all necessary cards.
-    if(winning->setSize < POKER_WINNING_SET_SIZE) continue;
+    if(winning.set.size() != 5) {
+      ++it;
+      continue;
+    }
 
     // Add self to array
-    winning->set[0] = winning->full[i];
-    winning->type = (
+    winning.type = (
       number == CARD_ACE ? POKER_WINNING_TYPE_ROYAL_FLUSH : 
       POKER_WINNING_TYPE_STRAIGHT_FLUSH
     );
     pokerWinnerFillRemaining(winning);
-    return;
+    return winning;
   }
 
   // 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(winning->setSize > 0 && (winning->set, winning->setSize, card) != -1) {
+  it = winning.full.begin();
+  while(it != winning.full.end()) {
+    auto pairs = Card::countPairs(&winning.full, it->getValue());
+    if(pairs.size() < CARD_SUIT_COUNT) {
+      ++it;
       continue;
     }
 
-    number = cardGetNumber(card);
-    pairCount = cardCountPairs(winning->full, winning->fullSize, number, pairs);
+    winning.set = pairs;
+    winning.type = POKER_WINNING_TYPE_FOUR_OF_A_KIND;
+    pokerWinnerFillRemaining(winning);
+    return winning;
+  }
+
+  // Full House
+  winning.set.clear();
+  it = winning.full.begin();
+  while(it != winning.full.end()) {
+    // Check we haven't already added this card.
+    if(Card::contains(&winning.set, *it) != -1) {
+      ++it;
+      continue;
+    }
+
+    auto pairs = Card::countPairs(&winning.full, it->getValue());
 
     // 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.
+    if(pairs.size() != 2 && pairs.size() != 3) {
+      ++it;
+      continue;
+    }
+    if(winning.set.size() == 3) {
+      winning.set.pop_back();
+    }
 
     // Copy found pairs.
-    for(j = 0; j < pairCount; j++) {
-      winning->set[winning->setSize + j] = winning->full[pairs[j]];
+    auto itPairs = pairs.begin();
+    while(itPairs != pairs.end()) {
+      winning.set.push_back(*itPairs);
+      ++itPairs;
     }
-    winning->setSize += pairCount;
 
     // Winned?
-    if(winning->setSize != POKER_WINNING_SET_SIZE) continue;
-    winning->type = POKER_WINNING_TYPE_FULL_HOUSE;
+    if(winning.set.size() != 5) {
+      ++it;
+      continue;
+    }
+    winning.type = POKER_WINNING_TYPE_FULL_HOUSE;
     pokerWinnerFillRemaining(winning);
-    return;
+    return winning;
   }
 
   // Flush (5 same suit)
diff --git a/src/dawn/poker/PokerWinning.hpp b/src/dawn/poker/PokerWinning.hpp
index 65904817..cbca6bf3 100644
--- a/src/dawn/poker/PokerWinning.hpp
+++ b/src/dawn/poker/PokerWinning.hpp
@@ -37,6 +37,7 @@ namespace Dawn {
     public:
       enum PokerWinningType type;
       std::vector<struct Card> full;
+      std::vector<struct Card> set;
       
       static float_t getWinningTypeConfidence(enum PokerWinningType type);
   };