public EvalResult evaluateHand(List<Card> hand) { List<int> cardValues = getIntCardValues(hand); Dictionary<int, int> cardValueCounts = getCardValueCounts(cardValues); Dictionary<int, int> cardSuitCounts = getCardSuitCounts(hand); // create a new result with high card 2, hand result of a high card (no special sets found) EvalResult result = new EvalResult(2, HIGH_CARD); // find the value of the high card result.setHighCard(findHighCard(hand)); // check for four of a kind Boolean fourOfAKind = hasCountCards(cardValueCounts, 4); // check for three of a kind Boolean threeOfAKind = hasCountCards(cardValueCounts, 3); // check for one pair Boolean onePair = hasCountCards(cardValueCounts, 2); // check for full house (three of a kind + two of a kind) Boolean fullHouse = threeOfAKind && onePair; // check for flush Boolean flush = hasFlush(cardSuitCounts); // check for straight Boolean straight = hasStraight(cardValues); // check for a stright flush Boolean straightFlush = straight && flush; // check for two pair Boolean twoPair = hasTwoPair(cardValueCounts); if (straightFlush) result.setHandValue(STRAIGHT_FLUSH); else if (fourOfAKind) result.setHandValue(FOUR_OF_A_KIND); else if (fullHouse) result.setHandValue(FULL_HOUSE); else if (flush) result.setHandValue(FLUSH); else if (straight) result.setHandValue(STRAIGHT); else if (threeOfAKind) result.setHandValue(THREE_OF_A_KIND); else if (twoPair) result.setHandValue(TWO_PAIR); else if (onePair) result.setHandValue(ONE_PAIR); return result; }
/// <summary> /// choose a move to preform after the river card has been shown /// </summary> public Move postRiverAction() { List<Card> fiveCardHand = new List<Card>(); fiveCardHand.AddRange(playerHand); currentHandValue = handEval.evaluateHand(fiveCardHand); List<Card> boardCards = new List<Card>(); for (int i = 2; i < playerHand.Count; i++) { boardCards.Add(playerHand[i]); } EvalResult boardValue = handEval.evaluateHand(boardCards); //If theres a huge difference between the strength of my hand + board and just the board, we generally have a strong hand //For example if the best hand on the board is a pair, and my best with my hand is a pair, we have the same evaluation and its likely that other players do aswell if (currentHandValue.getHandValue() >= boardValue.getHandValue()) { int evalDifference = currentHandValue.getHandValue() - boardValue.getHandValue(); Boolean canRaise = false; Boolean canCall = false; int raiseAmount = 1; int callAmount = 1; int highestChips = 0; // check which player in the list has the highest chips // the list of players will contain all other players still in the hand, excluding ourself foreach (Player player in players) { if (player.getChipCount() > highestChips) highestChips = player.getChipCount(); } if (highestChips == 0) { highestChips = 1; } // check if we are allowed to raise or call this turn // if we can, retrieve the minimum amounts associated with these actions foreach (Move move in possibleMoves) { if (move is Raise) { raiseAmount = ((Raise)move).getMinimumRaise(); canRaise = true; } else if (move is Call) { callAmount = ((Call)move).getCallAmount(); canCall = true; } } if (evalDifference >= 3)//significant strength compared to board, bully opponent { if (getChipCount() / highestChips > .75) { // we can try to bully the opponents // bet 10% of our chips raiseAmount += Convert.ToInt32(getChipCount() * .1); Raise moveChoice = new Raise(raiseAmount); moveChoice.setRaiseAmount(raiseAmount); return moveChoice; } // otherwise call or check depending on the call amount if (!canCall) return new Check(); else { // if the call amount is less than 10% of our chips, then if (getChipCount() / callAmount > 20) { return new Call(callAmount); } else return new Fold(); } } else if (evalDifference > 0)//moderate strength { // if we are unable to call then we can check for free if (!canCall) { return new Check(); } // if the call is a small percentage of our chips then make it else if (canCall && getChipCount() / callAmount < .05) { return new Call(callAmount); } else { return new Fold(); } } else //our hand strength is basically that of whats on the board i.e. not strong { // check if possible. if not then fold if (!canCall) return new Check(); // checking is not an option, fold return new Fold(); } } else { //I dont think its possible a board value alone is stronger than (board + hand value) ever.. return null; } // Now we know what our best hand is and know that another player either has a good hand or is bluffing since in almost all hands that get here we plan to bet(excluding the possible case were our hand is bad and we keep checkin) // again we will use isOurHandLiklyBetterThanAnyOtherPlayers to determine if our hand is better and we will bet accordingly // here we must again consider bluffing and our aggression level based on relative chip count(our compared to the players at the table }
/// <summary> /// determines what to do in any round of betting between the flop and the turn /// may need hand/ possible actions(moves) as a param/s /// will return a move that we want to preform /// </summary> public Move postFlopAction() { List<Card> fiveCardHand = new List<Card>(); fiveCardHand.AddRange(playerHand); currentHandValue = handEval.evaluateHand(fiveCardHand); List<Card> boardCards = new List<Card>(); Boolean likelyToImproveHand = false; for(int i = 2; i < playerHand.Count; i++) { boardCards.Add(playerHand[i]); } EvalResult boardValue = handEval.evaluateHand(boardCards); //If theres a huge difference between the strength of my hand + board and just the board, we generally have a strong hand //For example if the best hand on the board is a pair, and my best with my hand is a pair, we have the same evaluation and its likely that other players do aswell if(currentHandValue.getHandValue() >= boardValue.getHandValue()) { int likelyNextHandValue = getMostLikelyNextHandValue(); if(likelyNextHandValue > currentHandValue.getHandValue())//if we are likely to get a good hand value { likelyToImproveHand = true; //this will be used to skew the evalutationDifference } int evalDifference = currentHandValue.getHandValue() - boardValue.getHandValue(); if(likelyToImproveHand)//if we are likely to improve our hand, up the difference by 1 { evalDifference++; } Boolean canRaise = false; Boolean canCall = false; int raiseAmount = 1; int callAmount = 1; int highestChips = 0; // check which player in the list has the highest chips // the list of players will contain all other players still in the hand, excluding ourself foreach (Player player in players) { if (player.getChipCount() > highestChips) highestChips = player.getChipCount(); } if (highestChips == 0) { highestChips = 1; } // check if we are allowed to raise or call this turn // if we can, retrieve the minimum amounts associated with these actions foreach (Move move in possibleMoves) { if (move is Raise) { raiseAmount = ((Raise)move).getMinimumRaise(); canRaise = true; } else if (move is Call) { callAmount = ((Call)move).getCallAmount(); canCall = true; } } if (evalDifference >= 3)//significant strength compared to board, bully opponent { if ((getChipCount() / highestChips) > .60) { // we can try to bully the opponents // bet a base of 10% of our chips // hand strength is up to 8, add up to handStrength% of chips: 8 = 18% of our chips raiseAmount += Convert.ToInt32(getChipCount() * (.1 + (((double)currentHandValue.getHandValue())/100))); Raise moveChoice = new Raise(raiseAmount); moveChoice.setRaiseAmount(raiseAmount); return moveChoice; } // otherwise call or check depending on the call amount if (!canCall) return new Check(); else { // if the call amount is less than 10% of our chips, then if (( callAmount / getChipCount()) > .10) { return new Call(callAmount); } else return new Fold(); } } else if(evalDifference > 0)//moderate strength { // if we are unable to call then we can check for free if (!canCall) { return new Check(); } // if the call is a small percentage of our chips then make it else if (canCall && (callAmount / getChipCount()) > .05) { return new Call(callAmount); } else { return new Fold(); } } else //our hand strength is basically that of whats on the board i.e. not strong { // check if possible. if not then fold if (!canCall) return new Check(); // checking is not an option, fold return new Fold(); } } else { //I dont think its possible a board value alone is stronger than (board + hand value) ever.. return null; // again this should really never be reached } // at this point we have a good idea of what our hand is going to be or can possibly be // have a logic block that determines what move to make based on the returns from the 2 methods below // may also consider if the player(s) are prone to bluffing // may act different based on number of chip or an aggression attribute // learning could affect the action taken }