//Handles discarding and drawing new cards public override PlayerAction Draw(Card[] hand) { PokerTournament.Card highCard; int handEval = Evaluate.RateAHand(this.Hand, out highCard); List <int> cardsToDelete = new List <int>(); List <int> pair = new List <int>(); pair = CheckPair(); PlayerAction pa = null; int discardAmount = 0; if (handEval > 4) { //Counts for the dominant suit and dominant value of the hand int[] suites = { 0, 0, 0, 0 }; int[] values = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; for (int i = 0; i < this.Hand.Length; i++) { //Add this card's suit to the count switch (this.Hand[i].Suit) { case "Club": suites[0]++; break; case "Diamond": suites[1]++; break; case "Heart": suites[2]++; break; default: suites[3]++; break; } values[this.Hand[i].Value]++; } //If we have a dominant suit (4 cards), discard any cards that aren't part of it List <int> discards = new List <int>(); for (int i = 0; i < suites.Length; i++) { //Add this card's suit to the count switch (suites[i]) { case 1: //Get the card's index if it should be discarded for (int k = 0; k < this.Hand.Length; i++) { if (this.Hand[k].Suit == "Club" && i == 0) { discards.Add(k); } else if (this.Hand[k].Suit == "Diamond" && i == 1) { discards.Add(k); } else if (this.Hand[k].Suit == "Club" && i == 2) { discards.Add(k); } else if (this.Hand[k].Suit == "Spade" && i == 3) { discards.Add(k); } } break; default: break; } } if (discards.Count > 0) { Console.WriteLine("Discarding " + discards[0].ToString()); pa = new PlayerAction(Name, "Draw", "draw", discards.Count); return(pa); } pa = new PlayerAction(Name, "Draw", "stand pat", 0); return(pa); } if (pair.Count == 0) { if (highCard.Value == 14) //If Ace { for (int i = 0; i < Hand.Length; i++) { if (Hand[i].Value != 14) { Console.WriteLine("Discarding " + Hand[i].ToString()); hand[i] = null; discardAmount++; } } } else //Otherwise keep highest two cards { PokerTournament.Card highCardOld; int handEvalNew = Evaluate.RateAHand(this.Hand, out highCardOld); Card[] handTemp = this.Hand; for (int i = 0; i < Hand.Length; i++) { if (Hand[i] == highCardOld) { handTemp[i] = new PokerTournament.Card("Spades", 2);; } } PokerTournament.Card highCardNew; handEvalNew = Evaluate.RateAHand(handTemp, out highCardNew); for (int i = 0; i < Hand.Length; i++) { if (Hand[i] == highCardOld || Hand[i] == highCardNew) { Hand[i] = null; discardAmount++; } } } pa = new PlayerAction(Name, "Draw", "draw", discardAmount); //Draws equal to discard amount return(pa); //Should keep ace or two highest cards } else { Console.WriteLine("There are " + pair.Count + " pairs, attempting to discard."); for (int r = 0; r < pair.Count; r++) { for (int i = 0; i < Hand.Length; i++) { if (Hand[i] != null) { if (!pair.Contains(Hand[i].Value)) { Console.WriteLine("Discarding " + Hand[i].ToString()); hand[i] = null; discardAmount++; } } } } } pa = new PlayerAction(Name, "Draw", "draw", discardAmount); //Draws equal to discard amount return(pa); }
// plays 1 round of poker private string Round() { string text = ""; // result text List <PlayerAction> actions = new List <PlayerAction>(); // list of actions // call players in order Player[] playerOrder = new Player[2]; if (p0.Dealer == true) // player 0 deals? { playerOrder[0] = p1; // p1 goes first playerOrder[1] = p0; } else { playerOrder[0] = p0; // p0 goes first playerOrder[1] = p1; } // setup deck for a new round deck.NewRound(); // dealer deals out 5 cards to each player playerOrder[0].Hand = deck.Deal(5); playerOrder[1].Hand = deck.Deal(5); // round 1 of betting - loop until both players check, // one folds, or one calls ResultWriter("Betting round 1:"); Boolean done = false; // flags when finished do { PlayerAction pa0 = playerOrder[0].BettingRound1(actions, playerOrder[0].Hand); bool valid = CheckAction("Bet1", actions, pa0); if (valid == false) { ResultWriter(playerOrder[0].Name + " played a bad action of " + pa0.ActionName + " and forfeits the hand"); pa0 = new PlayerAction(pa0.Name, pa0.ActionPhase, "fold", 0); } actions.Add(pa0); ResultWriter(pa0.ToString()); ResultWriter(" "); if (pa0.ActionName != "fold") // first player did not fold { PlayerAction pa1 = playerOrder[1].BettingRound1(actions, playerOrder[1].Hand); valid = CheckAction("Bet1", actions, pa1); if (valid == false) { ResultWriter(playerOrder[1].Name + " played a bad action of " + pa1.ActionName + " and forfeits the hand"); pa1 = new PlayerAction(pa1.Name, pa1.ActionPhase, "fold", 0); } actions.Add(pa1); ResultWriter(pa1.ToString()); ResultWriter(" "); } done = EvaluateActions(actions, "Bet1"); } while (done == false); // update the pot based on the bets int lastBet = 0; for (int i = 0; i < actions.Count; i++) { if (actions[i].ActionPhase == "Bet1") { switch (actions[i].ActionName) { case "bet": lastBet = actions[i].Amount; pot += lastBet; // adjust the pot // deduct from player if (actions[i].Name == playerOrder[0].Name) // player0 bet? { playerOrder[0].ChangeMoney(-lastBet); } else // must be player1 { playerOrder[1].ChangeMoney(-lastBet); } break; case "raise": int total = lastBet; // amt from previous player pot += lastBet; // player raising must match last bet lastBet = actions[i].Amount; total += lastBet; // amt being raised pot += lastBet; // plus the amount raised // deduct from player if (actions[i].Name == playerOrder[0].Name) // player0 bet? { playerOrder[0].ChangeMoney(-total); } else // must be player1 { playerOrder[1].ChangeMoney(-total); } break; case "call": // skip if this is a call after a bet/raise by the same player if (i - 2 >= 0) { if (actions[i - 2].ActionName == "bet" || actions[i - 2].ActionName == "raise") { break; } } pot += lastBet; // match the last bet // deduct from player if (actions[i].Name == playerOrder[0].Name) // player0 bet? { playerOrder[0].ChangeMoney(-lastBet); } else // must be player1 { playerOrder[1].ChangeMoney(-lastBet); } break; } } } ResultWriter("After Bet1, pot is " + pot); ResultWriter(" "); // see if someone folded if (actions[actions.Count - 1].ActionName == "fold") { // if the player in playerOrder[1] folded, other // player gets the pot playerOrder[0].ChangeMoney(pot); string result = actions[actions.Count - 1].Name + " folded. Other player gets the pot of " + pot; pot = 0; // clear the pot return(result); // skip rest of loop } if (actions[actions.Count - 2].ActionName == "fold") { // if the player in playerOrder[0] folded, other // player gets the pot playerOrder[1].ChangeMoney(pot); string result = actions[actions.Count - 2].Name + " folded. Other player gets the pot of " + pot; pot = 0; // clear the pot return(result); // skip rest of loop } // draw for (int i = 0; i < playerOrder.Length; i++) { PlayerAction pa = playerOrder[i].Draw(playerOrder[i].Hand); actions.Add(pa); if (pa.Amount > 0) { Card[] newCards = deck.Deal(pa.Amount); // get cards playerOrder[i].AddCards(playerOrder[i].Hand, newCards); } ResultWriter("Name: " + playerOrder[i].Name); string handList = Evaluate.ListHand(playerOrder[i].Hand); ResultWriter(handList); ResultWriter(" "); } // round 2 of betting- loop until both players check, // one folds, or one calls ResultWriter("Betting round 2:"); done = false; // flags when finished do { PlayerAction pa0 = playerOrder[0].BettingRound2(actions, playerOrder[0].Hand); bool valid = CheckAction("Bet2", actions, pa0); if (valid == false) { ResultWriter(playerOrder[0].Name + " played a bad action of " + pa0.ActionName + " and forfeits the hand"); pa0 = new PlayerAction(pa0.Name, pa0.ActionPhase, "fold", 0); } actions.Add(pa0); ResultWriter(pa0.ToString()); ResultWriter(" "); if (pa0.ActionName != "fold") // first player did not fold { PlayerAction pa1 = playerOrder[1].BettingRound2(actions, playerOrder[1].Hand); valid = CheckAction("Bet2", actions, pa1); if (valid == false) { ResultWriter(playerOrder[1].Name + " played a bad action of " + pa1.ActionName + " and forfeits the hand"); pa1 = new PlayerAction(pa1.Name, pa1.ActionPhase, "fold", 0); } actions.Add(pa1); ResultWriter(pa1.ToString()); ResultWriter(" "); } done = EvaluateActions(actions, "Bet2"); } while (done == false); // update the pot based on the bets lastBet = 0; for (int i = 0; i < actions.Count; i++) { if (actions[i].ActionPhase == "Bet2") { switch (actions[i].ActionName) { case "bet": lastBet = actions[i].Amount; pot += lastBet; // adjust the pot // deduct from player if (actions[i].Name == playerOrder[0].Name) // player0 bet? { playerOrder[0].ChangeMoney(-lastBet); } else // must be player1 { playerOrder[1].ChangeMoney(-lastBet); } break; case "raise": int total = lastBet; // amt from previous player pot += lastBet; // player raising must match last bet lastBet = actions[i].Amount; total += lastBet; // amt being raised pot += lastBet; // plus the amount raised // deduct from player if (actions[i].Name == playerOrder[0].Name) // player0 bet? { playerOrder[0].ChangeMoney(-total); } else // must be player1 { playerOrder[1].ChangeMoney(-total); } break; case "call": // skip if this is a call after a bet/raise by the same player if (i - 2 >= 0) { if (actions[i - 2].ActionName == "bet" || actions[i - 2].ActionName == "raise") { break; } } pot += lastBet; // match the last bet // deduct from player if (actions[i].Name == playerOrder[0].Name) // player0 bet? { playerOrder[0].ChangeMoney(-lastBet); } else // must be player1 { playerOrder[1].ChangeMoney(-lastBet); } break; } } } ResultWriter("After Bet2, pot is " + pot); ResultWriter(" "); // round resolution // see if there is a clear winner based on hand strength Card highCard = null; int p0Rank = Evaluate.RateAHand(playerOrder[0].Hand, out highCard); int p1Rank = Evaluate.RateAHand(playerOrder[1].Hand, out highCard); if (p0Rank > p1Rank) { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); pot = 0; } else if (p1Rank > p0Rank) { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } else // same rank - needs further examination { // sort both hands Evaluate.SortHand(playerOrder[0].Hand); Card[] hand0 = playerOrder[0].Hand; Evaluate.SortHand(playerOrder[1].Hand); Card[] hand1 = playerOrder[1].Hand; switch (p0Rank) { case 1: // high card for (int i = 4; i >= 0; i--) { if (hand0[i].Value != hand1[i].Value) { if (hand0[i].Value > hand1[i].Value) { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); pot = 0; } else if (hand1[i].Value > hand0[i].Value) { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } } } // could be a tie if (pot != 0) { playerOrder[0].ChangeMoney(pot / 2); playerOrder[1].ChangeMoney(pot / 2); text = "Tie, each player gets " + pot / 2; if (pot % 2 != 0) { pot = 1; } else { pot = 0; } } break; case 2: // one pair // get the pair for playerOrder[0] int p0Pair = 0; for (int j = 14; j >= 2; j--) { int count = Evaluate.ValueCount(j, hand0); if (count == 2) // found the pair { p0Pair = j; break; } } // do the same for the other hand int p1Pair = 0; for (int k = 14; k >= 2; k--) { int count = Evaluate.ValueCount(k, hand1); if (count == 2) // found the pair { p1Pair = k; break; } } // which is higher if (p0Pair > p1Pair) // playerOrder[0] wins { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); } else if (p1Pair > p0Pair) { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); } else { // need to see what the high // card is aside from the pair // get the cards that are not part of a pair from hand0 Card[] h0NotPair = new Card[3]; int pos = 0; for (int i = 0; i < hand0.Length; i++) { if (hand0[i].Value != p0Pair) { h0NotPair[pos] = hand0[i]; pos++; } } // do the same for the next hand Card[] h1NotPair = new Card[3]; pos = 0; for (int i = 0; i < hand1.Length; i++) { if (hand1[i].Value != p1Pair) { h1NotPair[pos] = hand1[i]; pos++; } } // see if high card breakes the tie for (int i = 2; i >= 0; i--) { if (h0NotPair[i].Value != h1NotPair[i].Value) { if (h0NotPair[i].Value > h1NotPair[i].Value) { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); pot = 0; } else if (h1NotPair[i].Value > h0NotPair[i].Value) { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } } } // could be a tie if (pot != 0) { playerOrder[0].ChangeMoney(pot / 2); playerOrder[1].ChangeMoney(pot / 2); text = "Tie, each player gets " + pot / 2; if (pot % 2 != 0) { pot = 1; } else { pot = 0; } } } break; case 3: // two pair // get the two pair int[] h0Pair = new int[2]; int[] h1Pair = new int[2]; // get hand0 pairs int pCount = 0; for (int i = 14; i >= 2; i--) { int count = Evaluate.ValueCount(i, hand0); if (count == 2) // found the pair { h0Pair[pCount] = i; pCount++; } } // get the hand1 pairs pCount = 0; for (int i = 14; i >= 2; i--) { int count = Evaluate.ValueCount(i, hand1); if (count == 2) // found the pair { h1Pair[pCount] = i; pCount++; } } // compare the pairs if (h0Pair[0] > h1Pair[0]) // playerOrder[0] wins { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); } else if (h1Pair[0] > h0Pair[0]) // playerOrder[1] wins { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } else // tie on the highest pair { // compare the second pair if (h0Pair[1] > h1Pair[1]) // playerOrder[0] wins { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); pot = 0; } else if (h1Pair[0] > h0Pair[0]) // playerOrder[1] wins { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } else // tie on the highest pair { playerOrder[0].ChangeMoney(pot / 2); playerOrder[1].ChangeMoney(pot / 2); text = "Tie, each player gets " + pot / 2; // tie overall if (pot % 2 != 0) { pot = 1; } else { pot = 0; } } } break; case 4: // three of a kind // get the pair for playerOrder[0] int p0Three = 0; for (int j = 14; j >= 2; j--) { int count = Evaluate.ValueCount(j, hand0); if (count == 3) // found the pair { p0Three = j; break; } } // do the same for the other hand int p1Three = 0; for (int k = 14; k >= 2; k--) { int count = Evaluate.ValueCount(k, hand1); if (count == 3) // found the three cards { p1Three = k; break; } } // which is higher - no possibility of a tie if (p0Three > p1Three) // playerOrder[0] wins { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); } else { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); } pot = 0; break; case 5: // straight // compare the top card - if one is higher than the other, that // player is the winner. Otherwise, there is a tie if (hand0[0].Value > hand1[0].Value) { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); pot = 0; } else if (hand1[0].Value > hand0[0].Value) { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } else // tie { playerOrder[0].ChangeMoney(pot / 2); playerOrder[1].ChangeMoney(pot / 2); text = "Tie, each player gets " + pot / 2; if (pot % 2 != 0) { pot = 1; } else { pot = 0; } } break; case 6: // flush // locate the high cards and keep testing until you // either have a tie or a winner // tie flag Boolean tie = true; for (int i = 4; i >= 0; i--) { if (hand0[i].Value != hand1[i].Value) { // determine the winner if (hand0[i].Value > hand1[i].Value) { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); pot = 0; } else { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } // not a tie tie = false; break; // exit loop } } // handle a tie if (tie == true) { playerOrder[0].ChangeMoney(pot / 2); playerOrder[1].ChangeMoney(pot / 2); text = "Tie, each player gets " + pot / 2; if (pot % 2 != 0) { pot = 1; } else { pot = 0; } } break; case 7: // full house // get the two pair int h0FH = 0; int h1FH = 0; // get hand0 triple for (int i = 14; i >= 2; i--) { int count = Evaluate.ValueCount(i, hand0); if (count == 3) // found the triple { h0FH = i; } } // get the hand1 triple for (int i = 14; i >= 2; i--) { int count = Evaluate.ValueCount(i, hand1); if (count == 3) // found the triple { h1FH = i; } } // compare the triples if (h0FH > h1FH) // playerOrder[0] wins { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); } else // playerOrder[1] wins { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); } pot = 0; break; case 8: // four of a kind // get the pair for playerOrder[0] int p0Four = 0; for (int j = 14; j >= 2; j--) { int count = Evaluate.ValueCount(j, hand0); if (count == 4) // found the 4 cards { p0Four = j; break; } } // do the same for the other hand int p1Four = 0; for (int k = 14; k >= 2; k--) { int count = Evaluate.ValueCount(k, hand1); if (count == 4) // found the pair { p1Four = k; break; } } // which is higher - no possible tie if (p0Four > p1Four) // playerOrder[0] wins { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); } else { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); } pot = 0; break; case 9: // straight flush // compare the top card - if one is higher than the other, that // player is the winner. Otherwise, there is a tie if (hand0[4].Value > hand1[4].Value) { text = playerOrder[0].Name + " has a better hand and wins " + pot; playerOrder[0].ChangeMoney(pot); pot = 0; } else if (hand1[4].Value > hand0[4].Value) { text = playerOrder[1].Name + " has a better hand and wins " + pot; playerOrder[1].ChangeMoney(pot); pot = 0; } else // tie { playerOrder[0].ChangeMoney(pot / 2); playerOrder[1].ChangeMoney(pot / 2); text = "Tie, each player gets " + pot / 2; if (pot % 2 == 0) { pot = 1; } else { pot = 0; } } break; case 10: // royal flush // automatic tie - split the pot playerOrder[0].ChangeMoney(pot / 2); playerOrder[1].ChangeMoney(pot / 2); text = "Tie, each player gets " + pot / 2; if (pot % 2 != 0) { pot = 1; } else { pot = 0; } break; } } // return results return(text); }
private PlayerAction Round1ActionSelector(TurnOrder myOrder, PlayerAction prevAction, int handStrength, Card highCard) { // decalre a param to hold the actual bet int bettingAmount; // if an action is processed, then return true switch (myOrder) { // all we have to go off of in the first round is our own hand strength case TurnOrder.FIRST: // currently in the first turn, the actions we can select are bet, check, and fold if (Round1Check(handStrength, highCard)) { currentAction = Actions.CHECK; //lastActionStr = "check"; lastActionAmount = 0; return(new PlayerAction(Name, "Bet1", "check", 0)); } if (Round1Bet(handStrength, out bettingAmount, highCard)) { currentAction = Actions.BET; //currentMoney -= bettingAmount; lastActionAmount = bettingAmount; return(new PlayerAction(Name, "Bet1", "bet", bettingAmount)); } if (Round1Fold(handStrength, prevAction)) { currentAction = Actions.FOLD; lastActionAmount = 0; return(new PlayerAction(Name, "Bet1", "fold", 0)); } break; case TurnOrder.SECOND: // currently it is the second turn, the actions we can select are call, raise, fold if (Round1PossibleCheck(handStrength, prevAction, highCard)) { currentAction = Actions.CHECK; lastActionAmount = 0; return(new PlayerAction(Name, "Bet1", "check", 0)); } if (Round1PossibleBet(handStrength, prevAction, out bettingAmount, highCard)) { currentAction = Actions.BET; lastActionAmount = bettingAmount; return(new PlayerAction(Name, "Bet1", "bet", bettingAmount)); } if (Round1Raise(handStrength, prevAction, out bettingAmount, highCard)) { currentAction = Actions.RAISE; lastActionAmount = bettingAmount; return(new PlayerAction(Name, "Bet1", "raise", bettingAmount)); } if (Round1Call(handStrength, prevAction, out bettingAmount)) { currentAction = Actions.CALL; lastActionAmount = bettingAmount; return(new PlayerAction(Name, "Bet1", "call", bettingAmount)); } if (Round1Fold(handStrength, prevAction)) { currentAction = Actions.FOLD; lastActionAmount = 0; return(new PlayerAction(Name, "Bet1", "fold", 0)); } break; default: Console.WriteLine("error: turn order not specified."); return(new PlayerAction(Name, "Bet1", "fold", 0)); } // otherwise something went wrong and return fold return(new PlayerAction(Name, "Bet1", "fold", 0)); }
private bool Round1Raise(int handStrength, PlayerAction prevAction, out int raiseAmount, Card highCard) { raiseAmount = 0; // the AI is analyzing whether it should raise for round 1 //int highestWillingBet = currentMoney / 2; int tempRaiseAmount = handStrength * 50; // difference between our hand and the estimated enemy one // if the difference in hands is negative then they've maybe got a better hand than us float diffHands = ((float)handStrength * 0.1f) - estimatedEnemyHand; if (raiseCounter >= handStrength) { return(false); } if (prevAction.ActionName == "check") { // if they checked, try to lure them in by offering a low bet if (handStrength * 15 < currentMoney) { raiseAmount = handStrength * 15; } else { raiseAmount = currentMoney; } //currentMoney -= raiseAmount + prevAction.Amount; raiseCounter++; return(true); } // first, check the states in which it can raise if (prevAction.ActionName == "bet" || prevAction.ActionName == "raise") { if (diffHands >= (0.1 + risk) && handStrength >= 3) { if (tempRaiseAmount / 2 < currentMoney) { raiseAmount = rng.Next(tempRaiseAmount / 4, tempRaiseAmount / 2) + (int)(risk * 10); } else { raiseAmount = currentMoney; } currentMoney -= raiseAmount + prevAction.Amount; raiseCounter++; return(true); } if (diffHands >= (0.1 + risk) && highCard.Value > rng.Next(9, 11)) { if (handStrength > 1) { if (tempRaiseAmount / 2 < currentMoney) { raiseAmount = rng.Next(tempRaiseAmount / 4, tempRaiseAmount / 2) + (int)(risk * 10); } else { raiseAmount = currentMoney; } currentMoney -= raiseAmount + prevAction.Amount; raiseCounter++; return(true); } } } return(false); }
bool turnOfBluffing = false; //this becomes true if we find an AI that doesn't fall for 'stand pat' bluff // handle the first round of betting public override PlayerAction BettingRound1(List <PlayerAction> actions, Card[] hand) { //increment bluff counter at start of bet1 if we haven't already if (!alreadyIncrementedBluffCounter) { bluffCounter++; alreadyIncrementedBluffCounter = true; } // list the hand ListTheHand(hand); //get rank manually Card highCard = null; int rank = Evaluate.RateAHand(hand, out highCard); // select an action string actionSelection = ""; PlayerAction pa = null; do { Console.WriteLine("Select an action:\n1 - bet\n2 - raise\n3 - call\n4 - check\n5 - fold"); //AI input for this round /* Decision Tree * * BET1 | DRAW | BET2 * / \ | / \ * FIRST? SECOND RANK FIRST? SECOND? * RANK ACTION CHECK THEIR DISCARD ACTION * RANK CHECK RANK CHECK THEIR DISCARD * CHECK RANK * */ if (actions.Count < 1) //BET1, going first { actionSelection = Bet1Start(rank, hand); } else { //get what phase we are in PlayerAction lastAction = actions[actions.Count - 1]; if (lastAction.ActionPhase.Equals("Bet1")) //BET1 responding { actionSelection = Bet1(rank, hand, lastAction); } else if (lastAction.ActionPhase.Equals("Bet2")) //BET2, responding { actionSelection = Bet2(rank, hand, lastAction, actions); } else if (lastAction.ActionPhase.ToLower().Equals("draw")) //you are going first in Bet2 { actionSelection = Bet2Start(rank, hand, lastAction); } } // get amount if appropriate int amount = 0; if (actionSelection[0] == '1' || actionSelection[0] == '2') { do { if (actionSelection[0] == '1') // bet { Console.Write("Amount to bet? "); //amtText = Console.ReadLine(); //amtText = "10"; } else if (actionSelection[0] == '2') // raise { Console.Write("Amount to raise? "); //amtText = Console.ReadLine(); //amtText = "10"; } // convert the string to an int int tempAmt = 0; int.TryParse(amtText, out tempAmt); // check input if (tempAmt > this.Money) // { Console.WriteLine("Amount bet is more than the amount you have available."); amount = 0; } else if (tempAmt < 0) { Console.WriteLine("Amount bet or raised cannot be less than zero."); amount = 0; } else { amount = tempAmt; } } while (amount <= 0); } // create the PlayerAction switch (actionSelection) { case "1": pa = new PlayerAction(Name, "Bet1", "bet", amount); break; case "2": pa = new PlayerAction(Name, "Bet1", "raise", amount); break; case "3": pa = new PlayerAction(Name, "Bet1", "call", amount); break; case "4": pa = new PlayerAction(Name, "Bet1", "check", amount); break; case "5": pa = new PlayerAction(Name, "Bet1", "fold", amount); break; default: Console.WriteLine("Invalid menu selection - try again"); continue; } } while (actionSelection != "1" && actionSelection != "2" && actionSelection != "3" && actionSelection != "4" && actionSelection != "5"); // return the player action return(pa); }
//Probabilities: http://www.math.hawaii.edu/~ramsey/Probability/PokerHands.html public override PlayerAction BettingRound1(List <PlayerAction> actions, Card[] hand) { // create a test hand to test reactions Card[] testHand = new Card[5]; testHand[0] = new Card("Spades", 4); testHand[1] = new Card("Diamonds", 6); testHand[2] = new Card("Diamonds", 11); testHand[3] = new Card("Spades", 12); testHand[4] = new Card("Hearts", 7); int test = (int)(((float)rng.Next(33, 100) / 0.01) * 100); //Console.Writ //info to keep track of roundNum = actions.Count; // evaluate the hand Card highCard = null; int handStrength = Evaluate.RateAHand(hand, out highCard); //update stats if (actions.Count > 0) //ai goes second { //Console.WriteLine("\n*round stats-> First Player: " + actions[0].Name + " total turns taken: " + actions.Count); for (int i = 0; i < actions.Count; i++) { //Console.WriteLine(" (" + (i) + "): PLR: " + actions[i].Name + ", action: " + actions[i].ActionName + ", inPhase: " + actions[i].ActionPhase + ", amount: " + actions[i].Amount); } } else //ai goes first { //Console.WriteLine("\n*round stats-> player 1: " + Name + " takes first turn of round."); } //setup action PlayerAction pa = null; //start turn //Console.WriteLine("\n-> in ai betting round 1"); //Console.WriteLine(" Total games played: "+roundNum); //ListTheHand(hand); //if ai is first // actions available: bet, check, fold if (Round1FirstCheck(handStrength, out pa, highCard)) { // we're at round 0, increment so we get an accurate read //roundNum++; return(pa); } else // the ai is going second, actions available: check, call, raise, fold { // evaluate the enemy's hand estimatedEnemyHand = EvaluateEnemyHand(actions); //Console.WriteLine("Estimated enemy hand strength: " + estimatedEnemyHand); pa = Round1ActionSelector(TurnOrder.SECOND, actions[roundNum - 1], handStrength, highCard); return(pa); } }
// check over the last set of actions to see if we are // done betting private bool EvaluateActions(List <PlayerAction> actions, string phase) { // special case - the last player is the dealer and calls // then we are done PlayerAction lastAction = actions[actions.Count - 1]; //Console.WriteLine(phase + " " + lastAction.ActionPhase + " " + lastAction.ActionName); //Console.WriteLine("-----Evaluating-----"); if (lastAction.ActionPhase == phase && (phase == "Bet1" || phase == "Bet2") && lastAction.ActionName == "call") { // see if the player is the dealer if (lastAction.Name == p0.Name && p0.Dealer == true) { return(true); // dealer called - betting ends } else if (lastAction.Name == p1.Name && p1.Dealer == true) { return(true); // dealer called - betting ends } } // look at the last two actions for the given phase int count = 0; PlayerAction pa0 = null; PlayerAction pa1 = null; for (int i = actions.Count - 1; i >= 0; i--) { PlayerAction temp = actions[i]; if (temp.ActionPhase == phase) { if (count == 0) { pa0 = temp; count++; } else { pa1 = temp; break; } } } /* * if (pa0 != null) * { * Console.WriteLine("pa0: " + pa0.ActionName); * } * * if(pa1 != null) * { * Console.WriteLine("pa1: " + pa1.ActionName); * } */ // check for end conditions if (pa1 != null && pa1.ActionName == "fold") { return(true); // somebody folded } else if (pa0 != null && pa0.ActionName == "fold") { return(true); // somebody folded } else if (pa1 != null && pa0 != null && pa1.ActionName == "check" && pa0.ActionName == "check") { return(true); // both checked } else if (pa1 != null && pa0 != null && pa1.ActionName == "call" && pa0.ActionName == "call") { return(true); // both checked } // if none of the above, still betting return(false); }
public override PlayerAction Draw(Card[] hand) { /// Keeping it super rudimentary /// Fuzzy logic might be better here /// But since every rank corresponds with a different set of cards (IE: 1 = high card, 2 = Two pair, 10 is always = Royal Flush), 10 if statements are easier to manage imo /// PlayerAction pa = new PlayerAction(Name, "Draw", "stand pat", 0); // Print out the hand so we can see it //ListTheHand(hand); Console.WriteLine("\n"); // The first thing we should do is to evaluate our hand Card highCard = null; int rank = Evaluate.RateAHand(hand, out highCard); // If you have nothing switch (rank) { case 1: // You have nothing; #region Section 1 (High Card) Console.WriteLine("\n AI didn't like their hand."); // If your high is 10 or greater, then get rid of everything but the 10+ // Otherwise, dump everything and redraw if (highCard.Value >= 10) { for (int i = 0; i < hand.Length; i++) { if (hand[i] == highCard) { continue; } hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 4); Console.WriteLine("\n AI Discarded 4 cards, and kept their high card"); } else { // Dump! for (int i = 0; i < hand.Length; i++) { hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 5); Console.WriteLine("\n AI Discarded all 5 cards."); } #endregion break; case 2: // We have exactly a 1 pair #region Section 2 (Single Pair) // First identify what number of a pair we have int pairValue = 0; for (int i = 2; i < 15; i++) // Loop through every possible card number { if (Evaluate.ValueCount(i, hand) == 2) // Thankfully we have this method { pairValue = i; break; } } // We know which number it is // If our high card is 10 or higher, we'll want to dump every card, except for the high card and our double if (highCard.Value >= 10 && highCard.Value != pairValue) // Also check to make sure our high card isn't actually our pairValue. If it is then we'll just dump everything except for the pair { for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == pairValue || hand[i].Value == highCard.Value) { continue; } hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 2); Console.WriteLine("\n AI has a 2 pair and has discarded everything but the 2 pair and their high card."); } else { // If our high card isn't 10 or higher, then dump every card except for the high cards // Dump! for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == pairValue) { continue; } hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 3); Console.WriteLine("\n AI has a 2 pair and has discarded everything but the 2 pair."); } #endregion break; case 3: // We have two pairs! #region Section 3 (Two Pairs) // Ok first thing we need to do is to figure out which numbers are the two pair int pairValue1 = 0; int pairValue2 = 0; for (int i = 2; i < 15; i++) // Loop through every possible card number { if (Evaluate.ValueCount(i, hand) == 2) { pairValue1 = i; break; } } // Do it again and get the second one for (int i = 2; i < 15; i++) // Loop through every possible card number { if (Evaluate.ValueCount(i, hand) == 2) { if (i == pairValue2) { continue; } pairValue2 = i; break; } } if (pairValue1 == highCard.Value || pairValue2 == highCard.Value) { // Dump the other card and hope for a higher card for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == pairValue1 || hand[i].Value == pairValue2) { continue; } hand[i] = null; pa = new PlayerAction(Name, "Draw", "draw", 1); } } else { // Keep it! Your hand is good! pa = new PlayerAction(Name, "Draw", "stand pat", 0); } #endregion break; case 4: // Three of a kind #region Section 4 (Three of a Kind) // Pretty simple. Exactly the same as 1 pair except that it's with 3 // First identify what number of a pair we have int triValue = 0; for (int i = 2; i < 15; i++) // Loop through every possible card number { if (Evaluate.ValueCount(i, hand) == 3) // Thankfully we have this method { pairValue = i; break; } } // We know which number it is // If our high card is 10 or higher, we'll want to dump every card, except for the high card and our tripple if (highCard.Value >= 10 && highCard.Value != triValue) // Also check to make sure our high card isn't actually our trieValue. If it is then we'll just dump everything except for the tripple { for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == triValue || hand[i].Value == highCard.Value) { continue; } hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 1); Console.WriteLine("\n AI has a tripple and has discarded everything but the 3 of a kind and their high card."); } else { // If our high card isn't 10 or higher, then dump every card except for the high cards // Dump! for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == triValue) { continue; } hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 2); Console.WriteLine("\n AI has a 3 of a kind and has discarded everything but the tripple."); } #endregion break; // There's no reason for a case. Case 5 is a stroke, and we stand pat if we have a stroke case 8: // 4 of a kind #region Section 8 (Four of a Kind) // Check to see if our high is high enough. If it isn't drop it and as for another. int theQuadNumber = hand[3].Value; if (theQuadNumber == highCard.Value || highCard.Value <= 10) { // Get rid of the other card because we can do better for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == theQuadNumber) { continue; } hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 1); } #endregion break; // Any other selection is just a hold hand because we don't want to drop anything } return(pa); }
// handle the first round of betting public override PlayerAction BettingRound1(List <PlayerAction> actions, Card[] hand) { // list the hand ListTheHand(hand); // select an action string actionSelection = ""; PlayerAction pa = null; do { Console.WriteLine("Select an action:\n1 - bet\n2 - raise\n3 - call\n4 - check\n5 - fold"); actionSelection = Console.ReadLine(); // get amount if appropriate int amount = 0; if (actionSelection[0] == '1' || actionSelection[0] == '2') { string amtText = ""; do { if (actionSelection[0] == '1') // bet { Console.Write("Amount to bet? "); amtText = Console.ReadLine(); } else if (actionSelection[0] == '2') // raise { Console.Write("Amount to raise? "); amtText = Console.ReadLine(); } // convert the string to an int int tempAmt = 0; int.TryParse(amtText, out tempAmt); // check input if (tempAmt > this.Money) // { Console.WriteLine("Amount bet is more than the amount you have available."); amount = 0; } else if (tempAmt < 0) { Console.WriteLine("Amount bet or raised cannot be less than zero."); amount = 0; } else { amount = tempAmt; } } while (amount <= 0); } // create the PlayerAction switch (actionSelection) { case "1": pa = new PlayerAction(Name, "Bet1", "bet", amount); break; case "2": pa = new PlayerAction(Name, "Bet1", "raise", amount); break; case "3": pa = new PlayerAction(Name, "Bet1", "call", amount); break; case "4": pa = new PlayerAction(Name, "Bet1", "check", amount); break; case "5": pa = new PlayerAction(Name, "Bet1", "fold", amount); break; default: Console.WriteLine("Invalid menu selection - try again"); continue; } }while (actionSelection != "1" && actionSelection != "2" && actionSelection != "3" && actionSelection != "4" && actionSelection != "5"); // return the player action return(pa); }
public override PlayerAction BettingRound2(List <PlayerAction> actions, Card[] hand) { Random rand = new Random(); Card highCard = null; int rank = Evaluate.RateAHand(hand, out highCard); //Create the variable that will be returned PlayerAction pa; PlayerAction mostRecentAction = actions[actions.Count - 1]; //Decision Tree //If the other player has already made a move if (actions.Count > 0) { //If the opponent checks if (mostRecentAction.ActionName == "check") { //If your hand is One Pair or worse, check if (rank < 2) { pa = new PlayerAction(Name, "Bet2", "check", 0); } //Your hand is better than one pair, bet a small bet to try and coax out more money from the opponent else { pa = new PlayerAction(Name, "Bet2", "bet", rand.Next(1, 10) * rank); } } //If the opponenet doesn't check else { //The oppponent bet if (mostRecentAction.ActionName == "bet") { //The bet was small (it's hard to know how people are going to bet with their AIs, I'm hoping under 50 is small) if (mostRecentAction.Amount < 50) { //If your hand is good, raise a little bit in order to coax out more money from them if (rank > 3) { pa = new PlayerAction(Name, "Bet2", "raise", rand.Next(20, 25)); } //Your hand isn't good else { //Your hand is decent, so you call that small bet if (rank == 3) { pa = new PlayerAction(Name, "Bet2", "call", 0); //call, so amount doesn't matter } //Your hand is bad, so you fold else { pa = new PlayerAction(Name, "Bet2", "fold", 0); } } } //The bet was not small else { //Great hand, so you call if (rank > 6) { pa = new PlayerAction(Name, "Bet2", "call", 0); } //You won't be able to compete so you fold else { pa = new PlayerAction(Name, "Bet2", "fold", 0); } } } //The opponent did not bet or check, so they must have raised else { //They raised a lot if (mostRecentAction.Amount >= 50) { //Your hand is great if (rank > 6) { pa = new PlayerAction(Name, "Bet2", "raise", rand.Next(20, 25)); } //Your hand is not great else { //Your hand isn't good enough if (rank < 4) { pa = new PlayerAction(Name, "Bet2", "fold", 0); } //our hand is just good enough else { pa = new PlayerAction(Name, "Bet2", "call", 0); } } } //They didn't raise a lot else { //Your hand is trash if (rank < 2) { pa = new PlayerAction(Name, "Bet2", "fold", 0); } //Your hand is good enough to call else { pa = new PlayerAction(Name, "Bet2", "call", 0); } } } } } //If you are the first decision else { //If your hand is One Pair or worse, check if (rank < 2) { pa = new PlayerAction(Name, "Bet2", "check", 0); } //If your hand is better than one pair, bet low else { pa = new PlayerAction(Name, "Bet2", "bet", rand.Next(1, 10)); } } return(pa); }
public override PlayerAction Draw(Card[] hand) { // list the hand ListTheHand(hand); // determine how many cards to delete int cardsToDelete = 0; do { Console.Write("How many cards to delete? "); // get the count string deleteStr = Console.ReadLine(); int.TryParse(deleteStr, out cardsToDelete); } while (cardsToDelete < 0 || cardsToDelete > 5); // which cards to delete if any PlayerAction pa = null; if (cardsToDelete > 0 && cardsToDelete < 5) { for (int i = 0; i < cardsToDelete; i++) // loop to delete cards { Console.WriteLine("\nDelete card " + (i + 1) + ":"); for (int j = 0; j < hand.Length; j++) { Console.WriteLine("{0} - {1}", (j + 1), hand[j]); } // selete cards to delete int delete = 0; do { Console.Write("Which card to delete? (1 - 5): "); string delStr = Console.ReadLine(); int.TryParse(delStr, out delete); // see if the entry is valid if (delete < 1 || delete > 5) { Console.WriteLine("Invalid entry - enter a value between 1 and 5."); delete = 0; } else if (hand[delete - 1] == null) { Console.WriteLine("Entry was already deleted."); delete = 0; } else { hand[delete - 1] = null; // delete entry delete = 99; // flag to exit loop } } while (delete == 0); } // set the PlayerAction object pa = new PlayerAction(Name, "Draw", "draw", cardsToDelete); } else if (cardsToDelete == 5) { // delete them all for (int i = 0; i < hand.Length; i++) { hand[i] = null; } pa = new PlayerAction(Name, "Draw", "draw", 5); } else // no cards deleted { pa = new PlayerAction(Name, "Draw", "stand pat", 0); } // return the action return(pa); }
//helper method to handle the decision in Bet2 phase private string Bet2(int rank, Card[] hand, PlayerAction lastAction, List <PlayerAction> actions) { //update the cards our opponent threw away if applicable...get three turns ago to check if it was a draw phase PlayerAction drawAction = actions[actions.Count - 3]; if (drawAction.ActionPhase.ToLower().Equals("draw")) { //Console.WriteLine("OPPONENT DREW CARDS THREE TURNS AGO"); //Console.WriteLine("CARDS TOSSED: " + drawAction.Amount); if (drawAction.ActionName.Equals("stand pat")) { numCardsTossedByOpponent = 0; } else { numCardsTossedByOpponent = drawAction.Amount; } } if (lastAction.ActionName.Equals("check")) { if (bluffing) { amtText = "10"; return("1"); } else if (rank <= 1) //bad hand, let's check as well { return("4"); } else { if (numCardsTossedByOpponent == 0) { return("4"); } else if (numCardsTossedByOpponent == 1) //they had two pair { if (rank > 3) { amtText = "10"; if (rank >= 4) { amtText = "30"; } return("1"); } else { return("4"); } } else if (numCardsTossedByOpponent == 2) //they had triple { if (rank >= 4) { amtText = "10"; if (rank >= 5) { amtText = "30"; } return("1"); } else { return("4"); } } else if (numCardsTossedByOpponent == 3) //they had a pair { if (rank >= 2) { amtText = "10"; if (rank >= 4) { amtText = "30"; } return("1"); } else { return("4"); } } else //they threw away 4 cards { return("1"); } } } else if (lastAction.ActionName.Equals("bet")) { if (bluffing) //if they bet us after we discarded { turnOfBluffing = true; return("5"); } else if (rank <= 1) //bad hand, fold { return("5"); } if (numCardsTossedByOpponent == 0) //they stood pat { if (rank == 5 || rank == 6) //straight or flush we call { return("3"); } else if (rank >= 7) //full house or better we raise { if (timesRaisedBet2 < 2) { amtText = "10"; timesRaisedBet2++; return("2"); } else //don't raise more than twice { return("3"); } } else { return("5"); } } else if (numCardsTossedByOpponent == 1) //two pair { if (rank == 3) { return("3"); } else if (rank >= 4) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 4) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("5"); } } else if (numCardsTossedByOpponent == 2) //triple { if (rank == 4) { return("3"); } else if (rank >= 5) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 5) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("5"); } } else if (numCardsTossedByOpponent == 3) //pair { if (rank == 2) { return("3"); } else if (rank >= 3) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 4) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("5"); } } else //they threw away 4 cards { if (rank == 2) { return("3"); } else if (rank >= 3) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 3) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("3"); } } } else if (lastAction.ActionName.Equals("raise")) { if (bluffing) //they raised our bet when doing a stand pat bluff, turn off bluffing { turnOfBluffing = true; return("5"); } else if (rank <= 1) //bad hand, fold { return("5"); } else if (numCardsTossedByOpponent == 0) //they stood pat { if (rank == 5 || rank == 6) //straight or flush we call { return("3"); } else if (rank >= 7) //full house or better we raise { if (timesRaisedBet2 < 2) { amtText = "10"; timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("5"); } } else if (numCardsTossedByOpponent == 1) //two pair { if (rank == 3) { return("3"); } else if (rank >= 4) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 4) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("5"); } } else if (numCardsTossedByOpponent == 2) //triple { if (rank == 4) { return("3"); } else if (rank >= 5) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 5) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("5"); } } else if (numCardsTossedByOpponent == 3) //pair { if (rank == 2 || rank == 3) { return("3"); } else if (rank >= 4) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 4) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("5"); } } else //they threw away 4 cards { if (rank == 2) { return("3"); } else if (rank >= 3) { if (timesRaisedBet2 < 1) { amtText = "10"; if (rank >= 3) { amtText = "30"; } timesRaisedBet2++; return("2"); } else //don't raise more than once { return("3"); } } else { return("3"); } } } else if (lastAction.ActionName.Equals("call")) { //if they called us, we must have already bet so ignore bad hands return("3"); } //otherwise check - should never get here else { return("4"); } }
//helper method to handle the decision in Bet2 phase - GOING FIRST private string Bet2Start(int rank, Card[] hand, PlayerAction lastAction) { //bluff if (bluffing) { amtText = "10"; return("1"); } else if (rank <= 1) //bad hand, just check { return("4"); } else if (lastAction.ActionName.Equals("stand pat")) //nothing { //probably fold, however they may be bluffing return("4"); } else //get # of cards they threw away { int cardsTossed = lastAction.Amount; if (cardsTossed >= 4) //bad hand, bet { amtText = "10"; return("1"); } if (cardsTossed == 3) //they had a pair { if (rank > 2) //pair or better { amtText = "10"; if (rank >= 4) { amtText = "30"; } return("1"); } else { return("4"); } } if (cardsTossed == 2) //they had a triple { if (rank > 4) { amtText = "10"; if (rank >= 5) { amtText = "30"; } return("1"); } else { return("4"); } } if (cardsTossed == 1) //had a two pair { if (rank > 3) { if (rank >= 4) { amtText = "30"; } return("1"); } else { return("4"); } } return("4"); //never hits this, check if it does } }
/// <summary> /// Used to chose what action to do in response to the last act of the other player and our weights /// </summary> /// <param name="lastAct">Last PlayerAction done by the other player</param> /// <returns></returns> private PlayerAction ResponseAction(PlayerAction lastAct, Card highCard, string phase) { //Edge case for not having enough money to bet, just fold if (lastAct != null && (lastAct.ActionName == "bet" || lastAct.ActionName == "raise") && localMoney < lastAct.Amount) { return(new PlayerAction(Name, phase, "fold", 0)); //Fold } //how much wiggle room are we giving our estimatedHand weights? float wiggleRoom = -1; //negative for downward wiggle //round the estimated hand stregnth, also accounts for wiggle room int roundedEstimate = (int)Math.Round(theirHand + wiggleRoom, MidpointRounding.AwayFromZero); //PlayerAction to be returned and done by our AI PlayerAction response = new PlayerAction(Name, phase, "fold", 0); //Fold //First round betting this will be null if (lastAct != null && lastAct.ActionPhase != "Draw") { //switch for action switch (lastAct.ActionName) { case "call": //call or fold if (roundedEstimate <= handStrength) //compare estimHand and our own hands strength { //we trust our hand- call response = new PlayerAction(Name, lastAct.ActionPhase, "call", 0); } else { //estim is more we should fold response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); //fold in the same phase with 0 dollars bc folding } break; case "fold": //they folded, we shouldnt do anything break; case "check": //check, bet, or fold //how weak is our hand? if (handStrength == 1) { if (roundedEstimate > handStrength) { //theirs is better and we dont have anything, we should fold response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); //fold in the same phase with 0 dollars bc folding } else { //how strong is our high card? if (highCard.Value > 9) { //a 10 or better - we'll check response = new PlayerAction(Name, lastAct.ActionPhase, "check", 0); } else { //we should fold response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); } } } else { //compare our hands if (roundedEstimate > handStrength) { //are we willing to just bluff and try it? if (roundedEstimate > handStrength + bluffWeight) { //theirs is prolly too good - dont chance it response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); } else { //how many times have we bet? OR are we too far from their strength to risk a bluff? - AND do we have money to use? if ((bettingCycleCount > 3 || Math.Abs(roundedEstimate - handStrength) > bluffWeight) && localMoney > 0) { //we've done it too many times, just check bud response = new PlayerAction(Name, lastAct.ActionPhase, "check", 0); } else { //bet- with bluffing enabled response = new PlayerAction(Name, lastAct.ActionPhase, "bet", CalcAmount(highCard.Value, true)); } } } else { //how many times have we bet? and do we have money to bet? if (bettingCycleCount > 3 && Money > 0) { //we've done it too many times, just check bud response = new PlayerAction(Name, lastAct.ActionPhase, "check", 0); } else { //bet response = new PlayerAction(Name, lastAct.ActionPhase, "bet", CalcAmount(highCard.Value, false)); } } } break; case "bet": //bet and raise should have same logic case "raise": //raise, call, or fold if (handStrength >= roundedEstimate) { //we think we have a better hand lets see our options switch (handStrength) { case 1: //check our hand against their if (handStrength > roundedEstimate) { //we still think we can win response = new PlayerAction(Name, lastAct.ActionPhase, "call", 0); //call } else { response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); //we dont have anything and dont trust ourselves } break; case 2: case 3: response = new PlayerAction(Name, lastAct.ActionPhase, "call", 0); break; case 4: case 5: case 6: //bluff? Random rand = new Random(); if (rand.Next(2) == 0 && bettingCycleCount >= 3) //bluffing or bet cycle { //we can bluff response = new PlayerAction(Name, lastAct.ActionPhase, "raise", CalcAmount(highCard.Value, true)); } else { //not bluuffing or we bet too many times in a row, just call response = new PlayerAction(Name, lastAct.ActionPhase, "call", 0); } break; case 7: case 8: case 9: case 10: //how many times have we looped through betting? if (bettingCycleCount >= 3) { //too many times just call response = new PlayerAction(Name, lastAct.ActionPhase, "call", 0); } else { //raise back fight me nerd response = new PlayerAction(Name, lastAct.ActionPhase, "raise", CalcAmount(highCard.Value, false)); } break; } } else { if (handStrength == 1) { response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); //we dont think our hand is better } else if (handStrength == 2) { response = new PlayerAction(Name, lastAct.ActionPhase, "call", 0); //Call, our hand might be sort of okay } else if (handStrength >= 3 && handStrength < 5 && bettingCycleCount < 3) { if (Math.Abs(roundedEstimate - handStrength) > bluffWeight * 2) { response = new PlayerAction(Name, lastAct.ActionPhase, "raise", CalcAmount(highCard.Value, false)); //Raise } else if (Math.Abs(roundedEstimate - handStrength) > bluffWeight * 3) { response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); //we dont think our hand is better } else { response = new PlayerAction(Name, lastAct.ActionPhase, "call", 0); //Call, our hand might be sort of okay } } else if (bettingCycleCount < 3) { response = new PlayerAction(Name, lastAct.ActionPhase, "raise", CalcAmount(highCard.Value, false)); //Raise } else //Should never reach here { response = new PlayerAction(Name, lastAct.ActionPhase, "fold", 0); //we dont think our hand is better } } break; } } else { response = InitialBetting(lastAct, highCard, roundedEstimate); //Go through initial betting proceidures } //we know what todo! - return our repsonse return(response); }
public override PlayerAction BettingRound2(List <PlayerAction> actions, Card[] hand) { Console.WriteLine("-> in ai betting round 2"); // evaluate the hand Card highCard = null; int handStrength = Evaluate.RateAHand(hand, out highCard); //setup action Actions action = Actions.BET; PlayerAction pa = null; Random rng = new Random(); //keep track of float amount = 0; int risk = 0; int act = 0; bool isFirst = true; float riskTaking = rng.Next(100); //low=take no risk -- high=take much risk //probably replace with calculated value based on overall game //get previous bet for (int i = actions.Count - 1; i > 0; i--) { if (actions[i].ActionPhase == "Bet1" && (actions[i].ActionName == "bet" || (actions[i].ActionName == "call") || (actions[i].ActionName == "raise"))) { previousBet = currentBet = actions[i].Amount; //update last bet (round 1 bet) break; } } //check if first if (actions[actions.Count - 1].ActionPhase == "Draw") //if was just in last phase { if (actions[actions.Count - 1].Name == Name) //if ai went last { isFirst = false; } } //check hand strength and decide on move if (handStrength == 1 || handStrength == 2) { if (riskTaking < 100 * 1 / 6) { action = Actions.FOLD; Console.WriteLine("AI gives in and folds"); } else if (riskTaking < 100 * 4 / 6) { action = Actions.CHECK; Console.WriteLine("AI plays it safe and checks"); } else if (riskTaking < 100 * 5 / 6) { act = rng.Next(3); //2/3 chance of folding if (act == 0) { action = Actions.CHECK; } else if (act == 1) { action = Actions.CHECK; } else if (act == 2) { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); } Console.WriteLine("AI is considering taking a risk"); } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); Console.WriteLine("AI is taking a risk"); } } if (handStrength > 2 && handStrength <= 5) // 3, 4, 5 { //check or evaluate risk float mod = riskTaking * (handStrength / 10 * 0.55f); if (riskTaking + mod < 100 * 1 / 10) { action = Actions.FOLD; Console.WriteLine("AI gives in and folds"); } else if (riskTaking + mod < 100 * 3 / 6) { action = Actions.CHECK; Console.WriteLine("AI plays it safe and checks"); } else if (riskTaking + mod < 100 * 5 / 6) { act = rng.Next(100); if (act + mod < 25) { action = Actions.CHECK; } else if (act + mod < 50 && !isFirst) { action = Actions.CALL; } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); } Console.WriteLine("AI is considering taking a risk"); } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); Console.WriteLine("AI is taking a risk"); } } if (handStrength > 5 && handStrength <= 8) // 6, 7, 8 { //check or evaluate risk float mod = riskTaking * (handStrength / 10 * 0.7f); if (riskTaking + mod < 100 * 1 / 18) { action = Actions.CHECK; Console.WriteLine("AI gives in and checks"); } else if (riskTaking + mod < 100 * 1.8 / 6) { if (!isFirst) { action = Actions.CALL; } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking * 0.8f, out action); } Console.WriteLine("AI plays it safe and calls"); } else if (riskTaking + mod < 100 * 5 / 6) { act = rng.Next(100); if (act + mod < 10) { action = Actions.CHECK; } if (act + mod < 50 && !isFirst) { action = Actions.CALL; } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); } Console.WriteLine("AI is considering taking a risk"); } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); Console.WriteLine("AI is taking a risk"); } } if (handStrength == 9 || handStrength == 10) // 9, 10 { //check or evaluate risk //check or evaluate risk float mod = riskTaking * (handStrength / 10 * 0.9f); if (riskTaking + mod < 100 * 4.5 / 10) { if (!isFirst) { action = Actions.CALL; } Console.WriteLine("AI tries to bluff and calls"); } else if (riskTaking + mod < 100 * 7 / 10) { act = rng.Next(100); if (act + mod < 50 && !isFirst) { action = Actions.CALL; } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); } Console.WriteLine("AI is considering bluffing to raise pot"); } else { amount = Bet(isFirst, handStrength, previousBet, riskTaking, out action); Console.WriteLine("AI is confident and raises the bet"); } } //end turn and submit action //create the PlayerAction switch (action) { case Actions.BET: pa = new PlayerAction(Name, "Bet2", "bet", (int)Math.Ceiling(amount)); break; case Actions.RAISE: pa = new PlayerAction(Name, "Bet2", "raise", (int)Math.Ceiling(amount)); break; case Actions.CALL: pa = new PlayerAction(Name, "Bet2", "call", (int)Math.Ceiling(amount)); break; case Actions.CHECK: pa = new PlayerAction(Name, "Bet2", "check", (int)Math.Ceiling(amount)); break; case Actions.FOLD: pa = new PlayerAction(Name, "Bet2", "fold", (int)Math.Ceiling(amount)); break; default: Console.WriteLine("Invalid menu selection - try again"); break; } Console.WriteLine("< end ai betting round 2 >"); roundNum++; return(pa); }
/// <summary> /// Initial betting for when going first or after draw phase /// Can bet, check, and fold /// </summary> /// <param name="highCard"></param> /// <returns></returns> private PlayerAction InitialBetting(PlayerAction lastAct, Card highCard, int roundedEstimate) { string phase = null; //Get the right phase name if (lastAct == null) { phase = "Bet1"; } else { phase = "Bet2"; } switch (handStrength) { case 1: //Junk if (highCard.Value >= 11) { return(new PlayerAction(Name, phase, "bet", CalcAmount(0, false))); } else if (roundedEstimate <= handStrength) //Check if we feel good about this hand { return(new PlayerAction(Name, phase, "check", 0)); } else //Fold if we don't { return(new PlayerAction(Name, phase, "fold", 0)); } case 2: //One pair if (roundedEstimate < handStrength) //Bet if we feel good about this hand { for (int i = 2; i < 15; i++) //Loop for pair { if (Evaluate.ValueCount(i, Hand) == 2) { if (i > 12) { return(new PlayerAction(Name, phase, "bet", CalcAmount(i / 2, true))); } else { return(new PlayerAction(Name, phase, "bet", CalcAmount(i / 2, false))); } } } } else if (roundedEstimate == handStrength) //Check if we could win this hand { return(new PlayerAction(Name, phase, "check", 0)); } return(new PlayerAction(Name, phase, "fold", 0)); //Fold if we don't feel good about this hand case 3: //Two pair if (roundedEstimate < handStrength) //Bet if we feel good about this hand { for (int i = 15; i > 2; i--) //Loop for pair { if (Evaluate.ValueCount(i, Hand) == 2) { return(new PlayerAction(Name, phase, "bet", CalcAmount(i * (3 / 4), true))); } } } else if (roundedEstimate == handStrength) //Check if we could win this hand { return(new PlayerAction(Name, phase, "check", 0)); } return(new PlayerAction(Name, phase, "fold", 0)); //Fold if we don't feel good about this hand case 4: //Three of a kind if (roundedEstimate < handStrength) //Bet if we feel good about this hand { for (int i = 2; i < 15; i++) //Loop for pair { if (Evaluate.ValueCount(i, Hand) == 3) { return(new PlayerAction(Name, phase, "bet", CalcAmount(i, true))); } } } else if (roundedEstimate == handStrength) //Check if we could win this hand { return(new PlayerAction(Name, phase, "check", 0)); } return(new PlayerAction(Name, phase, "fold", 0)); //Fold if we don't feel good about this hand case 5: //Straight if (roundedEstimate < handStrength) //Bet if we feel good about this hand { return(new PlayerAction(Name, phase, "bet", CalcAmount(highCard.Value, false))); } else if (roundedEstimate == handStrength) //Check if we could win this hand { return(new PlayerAction(Name, phase, "check", 0)); } return(new PlayerAction(Name, phase, "fold", 0)); //Fold if we don't feel good about this hand case 6: //Flush if (roundedEstimate < handStrength) //Bet if we feel good about this hand { return(new PlayerAction(Name, phase, "bet", CalcAmount(highCard.Value, false))); } else if (roundedEstimate == handStrength) //Check if we could win this hand { return(new PlayerAction(Name, phase, "check", 0)); } return(new PlayerAction(Name, phase, "fold", 0)); //Fold if we don't feel good about this hand case 7: //Full house //Loop if (roundedEstimate < handStrength) //Bet if we feel good about this hand { for (int i = 2; i < 15; i++) //Loop for pair { if (Evaluate.ValueCount(i, Hand) == 3) { return(new PlayerAction(Name, phase, "bet", CalcAmount(i, true))); } } } else if (roundedEstimate == handStrength) //Check if we could win this hand { return(new PlayerAction(Name, phase, "check", 0)); } return(new PlayerAction(Name, phase, "fold", 0)); //Fold if we don't feel good about this hand case 8: //Four of a kind if (roundedEstimate < handStrength) //Bet if we feel good about this hand { for (int i = 2; i < 15; i++) //Loop for pair { if (Evaluate.ValueCount(i, Hand) == 4) { return(new PlayerAction(Name, phase, "bet", CalcAmount(i, true))); } } } else if (roundedEstimate == handStrength) //Check if we could win this hand { return(new PlayerAction(Name, phase, "check", 0)); } return(new PlayerAction(Name, phase, "fold", 0)); //Fold if we don't feel good about this hand case 9: //Straight flush return(new PlayerAction(Name, phase, "bet", CalcAmount(highCard.Value, false))); //Bet because who's gonna pull a royal flush case 10: //Royal flush return(new PlayerAction(Name, phase, "bet", CalcAmount(highCard.Value, false))); //Bet because we're UNSTOPPABLE } return(new PlayerAction(Name, phase, "fold", 0)); //Fold, but this should never happen }
public override PlayerAction Draw(Card[] hand) { Card curHighCard; int curHandStrength = Evaluate.RateAHand(hand, out curHighCard); bool takeASmallRisk = false; bool takeABigRisk = false; //Determine if we need to take a risk if (estimatedEnemyHand > 0.15f && estimatedEnemyHand <= 0.35f) { takeASmallRisk = true; } else if (estimatedEnemyHand > 0.35f) { takeASmallRisk = true; takeABigRisk = true; } //Decision Tree (if statements for now) PlayerAction pa = null; List <int> deleteIndices = new List <int>(); if (curHandStrength >= 5) //Do we have a strong hand? { if (curHandStrength >= 7) //Is it almost unbeatable? { if (curHandStrength == 8) //Is it a 4 of a kind? { if (curHighCard.Value > 10) //Get rid of a low high card { pa = new PlayerAction(Name, "Draw", "stand pat", 0); } else { DeleteCards(hand, UnmatchingCards(hand, 4)); pa = new PlayerAction(Name, "Draw", "draw", 1); } } else //Nothing to get rid of that wouldn't ruin the hand { pa = new PlayerAction(Name, "Draw", "stand pat", 0); } } else { if (takeABigRisk) //Do we need to take a risk? { if (curHandStrength == 5) //Is it a straight? { if (SimilarSuitedCards(hand, out deleteIndices) == 4) //Is it almost a flush? { DeleteCards(hand, deleteIndices); pa = new PlayerAction(Name, "Draw", "draw", 1); } else { pa = new PlayerAction(Name, "Draw", "stand pat", 0); } } else { if (ConsecutiveCards(hand, out deleteIndices) == 4) //Is it almost a straight flush? { DeleteCards(hand, deleteIndices); pa = new PlayerAction(Name, "Draw", "draw", 1); } else { pa = new PlayerAction(Name, "Draw", "stand pat", 0); } } } else { pa = new PlayerAction(Name, "Draw", "stand pat", 0); } } } else { if (takeASmallRisk) //Do we need to take a risk? { if (curHandStrength > 2) //Is it a medium strength hand? { if (curHandStrength == 4) //Is it a 3 of a kind? { DeleteCards(hand, UnmatchingCards(hand, 3)); pa = new PlayerAction(Name, "Draw", "stand pat", 2); } else { if (SimilarSuitedCards(hand, out deleteIndices) >= 3) //Is it almost a flush? { DeleteCards(hand, deleteIndices); pa = new PlayerAction(Name, "Draw", "draw", deleteIndices.Count); } else if (ConsecutiveCards(hand, out deleteIndices) >= 3) //Is it almost a straight? { DeleteCards(hand, deleteIndices); pa = new PlayerAction(Name, "Draw", "draw", deleteIndices.Count); } else // Ditch the 5th card { hand[OddCardOut(hand)] = null; pa = new PlayerAction(Name, "Draw", "stand pat", 1); } } } else { if (SimilarSuitedCards(hand, out deleteIndices) >= 3) //Is it almost a flush? { DeleteCards(hand, deleteIndices); pa = new PlayerAction(Name, "Draw", "draw", deleteIndices.Count); } else if (ConsecutiveCards(hand, out deleteIndices) >= 3) //Is it almost a straight? { DeleteCards(hand, deleteIndices); pa = new PlayerAction(Name, "Draw", "draw", deleteIndices.Count); } else { if (curHandStrength == 2) //Is it a pair? { DeleteCards(hand, UnmatchingCards(hand, 2)); pa = new PlayerAction(Name, "Draw", "draw", 3); } else //Ditch all but the high card { for (int i = 0; i < hand.Length; i++) { if (i != 4) { hand[i] = null; } } pa = new PlayerAction(Name, "Draw", "draw", 4); } } } } else { if (curHandStrength > 2) //Is it a medium strength hand? { if (curHandStrength == 4) //Is it a 3 of a kind? { //Find the high card of the 2 remaining, discard the lower List <int> tempCardList = UnmatchingCards(hand, 3); int deleteIndex = 0; foreach (int i in tempCardList) { if (deleteIndex == 0) { deleteIndex = i; } else { if (hand[deleteIndex].Value > hand[i].Value) { hand[i] = null; } else { hand[deleteIndex] = null; } } } pa = new PlayerAction(Name, "Draw", "draw", 1); } else //If a two pair, ditch the 5th card { hand[OddCardOut(hand)] = null; pa = new PlayerAction(Name, "Draw", "stand pat", 1); } } else { if (curHandStrength == 2) //If a pair, lose the other 3 { DeleteCards(hand, UnmatchingCards(hand, 2)); pa = new PlayerAction(Name, "Draw", "draw", 3); } else //Discard all but the high card { for (int i = 0; i < hand.Length; i++) { if (i != 4) { hand[i] = null; } } pa = new PlayerAction(Name, "Draw", "draw", 4); } } } } // return the action return(pa); }
public override PlayerAction BettingRound2(List <PlayerAction> actions, Card[] hand) { //reset values PlayerAction decision = null; int amount = 0; string action_suggestion = ""; PlayerAction last_action = (actions.Count > 0) ? actions[actions.Count - 1] : null; //bet needs to be played to raise or call if (bet == false && last_action != null) { if (last_action.ActionName == "bet") { bet = true; } } double rateOfReturn = CalculateRateOfReturn(last_action, hand, out action_suggestion, out amount); Console.Write(rateOfReturn); Console.Write(action_suggestion); Console.Write(amount); Random rnd = new Random(); //These values are the probabilities that the AI will choose a given action based on the rate of return //There is some randomness to ensure that you can never tell how strong the AI's hand is based on its actions //This is so the AI is able to bluff /* * If RR < 0.8 then 90% fold, 0 % call, 10% raise (bluff) * If RR < 1.0 then 70% fold, 10% call, 20% raise (bluff) * If RR <1.3 then decides based on call/bet odds * Else (RR >= 1.3) then decides based on call/bet odds * If fold and amount to call is zero, then call. */ //Low rate of return, AI is very likely to fold but may occasionally raise if (rateOfReturn < 0.8) { int tmp = rnd.Next(100); int tmp_momey = (Money > 10) ? 10 : Money; if (last_action == null) { decision = FoldAction(last_action); } else { if (tmp > 90)//Bluff { if (bet) { decision = new PlayerAction(Name, "Bet1", "raise", tmp_momey); } else { decision = new PlayerAction(Name, "Bet1", "bet", tmp_momey); bet = true; } } else { decision = FoldAction(last_action); } } } //somewhat low rate of return, likely to fold, but also may call and somewhat more likely to raise than call else if (rateOfReturn < 1) { int tmp = rnd.Next(100); if (last_action == null) { decision = FoldAction(last_action); } else { if (tmp < 70) { decision = FoldAction(last_action); } else if (tmp > 70 && tmp <= 80) { if (bet) { decision = new PlayerAction(Name, "Bet1", "call", 0); } else { decision = new PlayerAction(Name, "Bet1", "fold", 0); } } else//bluff { int tmp_money = (Money > 20) ? 20 : Money; decision = new PlayerAction(Name, "Bet1", "raise", tmp_money); } } } //high rate of return, decides in "Calculate Rate of Return" based on call odds and bet odds else if (rateOfReturn < 1.3) { int tmp = rnd.Next(100); int tmp_money = (Money > amount) ? amount : Money; if (last_action == null) { decision = new PlayerAction(Name, "Bet1", "bet", tmp_money); } else { switch (action_suggestion) { case "call": if (bet) { decision = new PlayerAction(Name, "Bet1", "call", tmp_money); } else { decision = new PlayerAction(Name, "Bet1", "bet", tmp_money); } break; case "bet": tmp_money = (Money > amount * 2) ? tmp_money : 0; if (bet && tmp_money != 0) { decision = new PlayerAction(Name, "Bet1", "raise", amount); } break; } } } //very high rate of return, decides in "Calculate Rate of Return" based on call odds and bet odds else if (rateOfReturn >= 1.3) { int tmp = rnd.Next(100); int tmp_money = (Money > amount) ? amount : Money; if (last_action == null) { decision = new PlayerAction(Name, "Bet1", "bet", tmp_money); } else { switch (action_suggestion) { case "call": if (bet) { decision = new PlayerAction(Name, "Bet1", "call", tmp_money); } else { decision = new PlayerAction(Name, "Bet1", "bet", tmp_money); } break; case "bet": tmp_money = (Money > amount * 2) ? tmp_money : 0; if (bet && tmp_money != 0) { decision = new PlayerAction(Name, "Bet1", "raise", amount); } break; } } } Console.Write("Decision" + decision.ActionName); return(decision); }
public override PlayerAction Draw(Card[] hand) { //reset the timesRaised variable after Bet1 is done timesRaisedBet1 = 0; timesRaisedBet2 = 0; //increment bluffCounter in draw because we only draw once every round (unlike betting that has //multiple phases alreadyIncrementedBluffCounter = false; bluffing = false; // list the hand ListTheHand(hand); //card index to deletes List <int> deleteIndexes = new List <int>(); //get rank manually Card highCard = null; int rank = Evaluate.RateAHand(hand, out highCard); // determine how many cards to delete int cardsToDelete = 0; do { Console.Write("How many cards to delete? "); // get the count //string deleteStr = Console.ReadLine(); string deleteStr; //use a decision tree to figure out the cards to delete deleteStr = "0"; //straight, flush, full house, straight flush, or royal flush if (rank == 5 || rank == 6 || rank == 7 || rank == 9 || rank == 10) { deleteStr = "0"; } //4 of a kind if (rank == 8) { //throw out 1 unless it's a King or Ace Dictionary <int, int> handMap = new Dictionary <int, int>(); for (int i = 0; i < hand.Length; i++) { if (handMap.ContainsKey(hand[i].Value)) { handMap[hand[i].Value]++; } else { handMap.Add(hand[i].Value, 1); } } int v = handMap.FirstOrDefault(x => x.Value == 1).Key; if (v < 14) //if less than ace { deleteStr = "1"; for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == v) { deleteIndexes.Add(i); } } } else { deleteStr = "0"; } } //3 of a kind if (rank == 4) { //throw out 2 that are not part of 3 of kind Dictionary <int, int> handMap = new Dictionary <int, int>(); for (int i = 0; i < hand.Length; i++) { if (handMap.ContainsKey(hand[i].Value)) { handMap[hand[i].Value]++; } else { handMap.Add(hand[i].Value, 1); } } int v = handMap.FirstOrDefault(x => x.Value == 3).Key; //3 kind value for (int i = 0; i < hand.Length; i++) { if (hand[i].Value != v) { deleteIndexes.Add(i); } } deleteStr = "2"; } //2 pair if (rank == 3) { //throw out 1 card not in either pair Dictionary <int, int> handMap = new Dictionary <int, int>(); for (int i = 0; i < hand.Length; i++) { if (handMap.ContainsKey(hand[i].Value)) { handMap[hand[i].Value]++; } else { handMap.Add(hand[i].Value, 1); } } int v = handMap.FirstOrDefault(x => x.Value == 1).Key; if (v < 14) //if less than ace { deleteStr = "1"; for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == v) { deleteIndexes.Add(i); } } } else { deleteStr = "0"; } } //1 pair if (rank == 2) { //throw out 3 cards not in the pair Dictionary <int, int> handMap = new Dictionary <int, int>(); for (int i = 0; i < hand.Length; i++) { if (handMap.ContainsKey(hand[i].Value)) { handMap[hand[i].Value]++; } else { handMap.Add(hand[i].Value, 1); } } int v = handMap.FirstOrDefault(x => x.Value == 2).Key; for (int i = 0; i < hand.Length; i++) { if (hand[i].Value != v) { deleteIndexes.Add(i); } } deleteStr = "3"; } //nothing - throw out 4 lowest if (rank <= 1) { if (bluffCounter > timeToBluff && turnOfBluffing == false) { deleteStr = "0"; bluffing = true; bluffCounter = 0; //Console.WriteLine("bluffing"); //Console.ReadLine(); } else { deleteStr = "4"; for (int i = 0; i < 4; i++) { deleteIndexes.Add(i); } } } int.TryParse(deleteStr, out cardsToDelete); } while (cardsToDelete < 0 || cardsToDelete > 5); // which cards to delete if any PlayerAction pa = null; if (cardsToDelete > 0 && cardsToDelete < 5) { for (int i = 0; i < cardsToDelete; i++) // loop to delete cards { Console.WriteLine("\nDelete card " + (i + 1) + ":"); for (int j = 0; j < hand.Length; j++) { Console.WriteLine("{0} - {1}", (j + 1), hand[j]); } // selete cards to delete int delete = 0; do { Console.Write("Which card to delete? (1 - 5): "); //string delStr = Console.ReadLine(); //int.TryParse(delStr, out delete); delete = deleteIndexes[i] + 1; // see if the entry is valid if (delete < 1 || delete > 5) { Console.WriteLine("Invalid entry - enter a value between 1 and 5."); delete = 0; } else if (hand[delete - 1] == null) { Console.WriteLine("Entry was already deleted."); delete = 0; } else { hand[delete - 1] = null; // delete entry delete = 99; // flag to exit loop } } while (delete == 0); } // set the PlayerAction object pa = new PlayerAction(Name, "draw", "draw", cardsToDelete); } else if (cardsToDelete == 5) { // delete them all for (int i = 0; i < hand.Length; i++) { hand[i] = null; } pa = new PlayerAction(Name, "draw", "draw", 5); } else // no cards deleted { pa = new PlayerAction(Name, "draw", "stand pat", 0); } // return the action return(pa); }