public override PlayerAction BettingRound2(List <PlayerAction> actions, Card[] hand) { //todo gather information about the other player beforehand based on what they are drawing //ie if they draw 3 cards and we have a two pair then we have a 2/3 chance of beating them //since we know they have one pair GetSuitsValues(hand); Card highCard; PlayerAction lastAction = actions[actions.Count - 1]; int handValue = Evaluate.RateAHand(hand, out highCard); //how aggressively we will raise/call //compared against aggressionR2, if opponent is not aggressive then we will assume that our hand is stronger above a certain aggressionR2 threshold initialTurn = actions.Count; //int moneyToBet = 0; bool firstPlay = false; if (lastAction.ActionName == "stand pat" || lastAction.ActionName == "draw") { firstPlay = true; } int pairHigh = -1; Card currentCard; for (int outer = 0; outer < 5; outer++) { currentCard = hand[outer]; for (int inner = 0; inner < 5; inner++) { if (outer != inner) { if ((hand[inner].Value == hand[outer].Value) && hand[inner].Value > pairHigh) { pairHigh = hand[inner].Value; } } } } if (handValue >= 8) { r2MaxRaise = Money; } else if (handValue < 2 || (handValue == 2 && pairHigh < 14)) { r2MaxRaise = 0; } else { r2MaxRaise = 20 + 20 * (handValue - 1); } //Player is playing first in round 2 if (actions[actions.Count - 1].ActionPhase == "Draw") { // if (handValue < 2 || (handValue == 2 && pairHigh < 14)) { aggressionR2 = 0; return(new PlayerAction(name, "Bet2", "check", 0)); } //pair of kings or better play conservatively else if (handValue == 2 && pairHigh >= 14) { aggressionR2 = .3f; moneyBetR2 += 10; return(new PlayerAction(name, "Bet2", "bet", 10)); } else if (handValue == 3) { if (pairHigh >= 12) //two pair high of 10s { aggressionR2 = .7f; moneyBetR2 += 20; return(new PlayerAction(name, "Bet2", "bet", 20)); } else //two pair high of less than 10s { aggressionR2 = 0.5f; moneyBetR2 += 15; return(new PlayerAction(name, "Bet2", "bet", 15)); } } else if (handValue == 4) { //3 of a kind 10s or higher if (pairHigh <= 12) { aggressionR2 = .9f; moneyBetR2 += 30; return(new PlayerAction(name, "Bet2", "bet", 30)); } else // 3 of a kind 9s or lower { aggressionR2 = .8f; moneyBetR2 += 25; return(new PlayerAction(name, "Bet2", "bet", 25)); } } else if (handValue >= 5) { aggressionR2 = 1.0f; moneyBetR2 += 30; return(new PlayerAction(name, "Bet2", "bet", 30)); } } //player is playing second in round 2 else if (actions[actions.Count - 2].ActionPhase == "Draw" && actions[actions.Count - 1].ActionPhase == "Bet2") { if (lastAction.ActionName == "check") { //neutral opponentAggression = .5f; if (aggressionR2 > .5f) { moneyBetR2 += 20; return(new PlayerAction(name, "Bet2", "bet", 20)); } else { moneyBetR2 += 10; return(new PlayerAction(name, "Bet2", "bet", 10)); } } //I'd love to scale aggression based on how much they bet but I'm really not sure how much money is a lot in this game //so I opt to scale it based on how the opponent chooses actions instead of the specific values else if (lastAction.ActionName == "bet") { opponentAggression = .5f; if (aggressionR2 > .5f) { //raise int moneyThisTurn = (int)(((float)r2MaxRaise / 2.0f * (float)aggressionR2)); moneyBetR2 += moneyThisTurn; return(new PlayerAction(name, "Bet2", "raise", moneyThisTurn)); } else if (aggressionR2 > .3f) { //call int moneyThisTurn = lastAction.Amount; moneyBetR2 += moneyThisTurn; return(new PlayerAction(name, "Bet2", "call", moneyThisTurn)); } else { //fold return(new PlayerAction(name, "Bet2", "fold", 0)); } } } //not player's first turn in the round else { } return(new PlayerAction(name, "Bet2", "fold", 0)); }
public override PlayerAction BettingRound1(List <PlayerAction> actions, Card[] hand) { PokerTournament.Card highCard; int handEval = Evaluate.RateAHand(this.Hand, out highCard); int pot = CurrentPot(actions, "Bet1"); int betAmount = GetCurrentBet(actions, "Bet1"); float odds = CalculatePotOdds(betAmount, pot); float returnRate = CalculateRateOfReturn(handEval, odds); float chance = rand.Next(0, 100); Console.WriteLine("Return rate: " + returnRate); Console.WriteLine("Chance: " + chance); if (returnRate < 0.8) { if (chance > 94) { return(new PlayerAction(Name, "Bet1", "raise", betAmount)); } else { return(new PlayerAction(Name, "Bet1", "fold", 0)); } } else if (returnRate < 1) { if (chance > 94) { return(new PlayerAction(Name, "Bet1", "call", 0)); } else if (chance > 79) { return(new PlayerAction(Name, "Bet1", "raise", betAmount)); } else { return(new PlayerAction(Name, "Bet1", "fold", 0)); } } else if (returnRate < 1.3) { if (chance > 70) { return(new PlayerAction(Name, "Bet1", "call", 0)); } else { return(new PlayerAction(Name, "Bet1", "raise", betAmount)); } } int res; if (returnRate > 0 && returnRate != float.PositiveInfinity) { float fres = betAmount * (returnRate); res = (int)fres; } else { res = 5 * handEval; } return(new PlayerAction(Name, "Bet1", "bet", res)); //return new PlayerAction(Name, "Bet1", "bet", betAmount); //throw new NotImplementedException(); }
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); }
public override PlayerAction Draw(Card[] hand) { // BRANCHING BEHAVIOR TREE (?) // // Get hand Eval Card highCard = null; handStrength = Evaluate.RateAHand(hand, out highCard); // number of tossed cards (and number to be drawn) // pass into PlayerAction return at the end int removed = 0; // Do stuff according to handStrength switch (handStrength) { case 1: // weakest hand: HIGH CARD if (highCard.Value >= 10) // Check the highCard's value, if highCard is a 10-J-Q-K-A { for (int i = 0; i < hand.Length; i++) // remove everything but the high card { if (hand[i] == highCard) { continue; // ignore if the current card is the high card } hand[i] = null; // remove removed++; } //thisAction = new PlayerAction(Name, "Draw", "draw", removed); ////////////////DO THIS AT THE END OF SWITCH????? Console.WriteLine("Player 10 threw away and will draw" + removed + " cards."); } else // if high card is not 10-J-Q-K-A then all these cards mean literally nothing, toss all { for (int i = 0; i < hand.Length; i++) { hand[i] = null; } //thisAction = new PlayerAction(Name, "Draw", "draw", 5);/////////////////////////// removed = 5; Console.WriteLine("Player 10 throws away its entire hand."); } break; case 2: // 1-PAIR int pairValue = 0; // have to get the value of the 1pair, must be initialized to something for (int i = 2; i < 15; i++) // check all values { if (Evaluate.ValueCount(i, hand) == 2) // count occurences of value (once 2 are found, break from for loop) { pairValue = i; break; } } // optimize chances of getting a higher hand // if the high card is not one of the pair AND it is 10-J-Q-K-A if (highCard.Value != pairValue && highCard.Value >= 10) { for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == pairValue || hand[i].Value == highCard.Value) { continue; // do not toss if the current card is one of the pair OR if it is the HIGH CARD (that is different from the pair in this case) } hand[i] = null; } removed = 2; } else // otherwise toss everything that isn't the pair { for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == pairValue) { continue; } hand[i] = null; } removed = 3; } break; case 3: // 2-PAIR // Get 2 pairs value int pair1Value = 0; int pair2Value = 0; // Count occurances of values and put as pair1's value for (int i = 2; i < 15; i++) { if (Evaluate.ValueCount(i, hand) == 2) { pair1Value = i; break; } } // Count occurences of values and put as pair2's value for (int i = 2; i < 15; i++) { if (Evaluate.ValueCount(i, hand) == 2) { if (i == pair1Value) { continue; // make sure to ignore pair 1 } pair2Value = i; break; } } // Check if either pair's value is the high card if (pair1Value == highCard.Value || pair2Value == highCard.Value) { for (int i = 0; i < hand.Length; i++) // toss the 1 remaining card { if (hand[i].Value == pair1Value || hand[i].Value == pair2Value) { continue; } hand[i] = null; } removed = 1; } else { // Any other factors to decide what to do???? // Otherwise return a stand pat action return(new PlayerAction(Name, "Draw", "stand pat", 0)); } break; case 4: // 3-OF-A-KIND // Get the triple's value int tripleValue = 0; for (int i = 2; i < 15; i++) { if (Evaluate.ValueCount(i, hand) == 3) { tripleValue = i; break; } } // optimize chances of getting a higher hand // if the high card is not one of the triple AND it is 10-J-Q-K-A if (highCard.Value != tripleValue && highCard.Value >= 10) { for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == tripleValue || hand[i].Value == highCard.Value) { continue; } hand[i] = null; } removed = 1; } else { // otherwise, toss the cards that aren't the triple and not 10-J-Q-K-A for (int i = 0; i < hand.Length; i++) { if (hand[i].Value == tripleValue) { continue; } hand[i] = null; } removed = 2; } break; // case 5: // STRAIGHT // probably not worth it to toss anything draw again, weigh this? // case 6: // FLUSH // same as STRIAGHT //case 7: // FULL HOUSE // which pair has the high card? (the triple or double?) // if the high card is of the triple // CASE 8: If 4 of a kind // if the diffent card is the high AND (10+) // weight whether or not to risk discarding the quadruple? // otherwise stand pat //case 8: // 4 of a kind // // Get Quadruple value // int quadValue = 0; // for (int i = 2; i < 15; i++) // { // if (Evaluate.ValueCount(i, hand) == 4) // when there are 4 occurances of one of the values (i) // { // pairValue = i; // break; // } // } // // // if (quadValue == 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 == quadValue) // continue; // hand[i] = null; // } // removed = 1; // } // break; case 5: case 6: case 7: case 8: case 9: // STRAIGHT FLUSH case 10: // ROYAL FLUSH // just stand pat like a winner return(new PlayerAction(Name, "Draw", "stand pat", 0)); } // otherwise, do approriate action return(new PlayerAction(Name, "Draw", "draw", removed)); }
/// <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 }
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); }
private void AnalyzeHand() { rank = Evaluate.RateAHand(this.Hand, out highCard); // May implement more later if necessary }
//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); }
public override PlayerAction BettingRound2(List <PlayerAction> actions, Card[] hand) { PokerTournament.Card highCard; int handEval = Evaluate.RateAHand(this.Hand, out highCard); int pot = CurrentPot(actions, "Bet2"); int betAmount = GetCurrentBet(actions, "Bet2"); float odds = CalculatePotOdds(betAmount, pot); float returnRate = CalculateRateOfReturn(handEval, odds); float chance = rand.Next(0, 100); ListTheHand(hand); Console.WriteLine("Return rate: " + returnRate); //Console.WriteLine("Chance: " + chance); //Console.WriteLine("Pairs: " + CheckPair().Count); //Console.ReadLine(); if (returnRate < 4) { if (chance > 94) { return(new PlayerAction(Name, "Bet2", "raise", betAmount)); } else { return(new PlayerAction(Name, "Bet2", "fold", 0)); } } else if (returnRate < 20) { if (chance > 94) { return(new PlayerAction(Name, "Bet2", "call", 0)); } else if (chance > 79) { return(new PlayerAction(Name, "Bet2", "raise", betAmount)); } else { return(new PlayerAction(Name, "Bet2", "fold", 0)); } } else { if (returnRate == float.PositiveInfinity) { int res; res = 5 * handEval; if (res > Money) { res = Money; } return(new PlayerAction(Name, "Bet2", "bet", res)); } if (chance > 70) { return(new PlayerAction(Name, "Bet2", "call", 0)); } else { float fres = betAmount * (returnRate); int res; res = (int)fres; if (res > Money) { res = Money; } return(new PlayerAction(Name, "Bet2", "raise", res)); } } //return new PlayerAction(Name, "Bet2", "bet", 0); }
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); }
//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); } }
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); }
private void AnalyzeHand() { rank = Evaluate.RateAHand(this.Hand, out highCard); }
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 BettingRound1(List <PlayerAction> actions, Card[] hand) { //display the hand //ListTheHand(hand); //get the suits and values of the cards GetSuitsValues(hand); Card highCard; int handValue = Evaluate.RateAHand(hand, out highCard); int moneyAvailable; int moneyToBet = 0; // 1 - 10 how agressive the betting will be int aggression = 0; //if this is the first or second action, it is this players first action of the round if (actions.Count <= 1) { //reset the money bet since it is a new round moneyBet = 0; r1MaxBet = 0; //determine the maximum bet //if the high card is in the low half of cards if (highCard.Value < 8) { r1MaxBet = 5 + 10 * (handValue - 1); } //high half of the values else { r1MaxBet = 10 + 10 * (handValue - 1); } //make sure that we are not exceeding the money that we have when trying to bet if (Money < r1MaxBet) { r1MaxBet = Money; atLimit = true; } else { atLimit = false; } //set the aggression level of the Player if (handValue == 1) { aggression = 1 + (highCard.Value - 2) / 5; } else if (handValue == 2) { //find the value of the pair for (int i = 12; i >= 0; i--) { if (values[i] == 2) { highHandValue = i; } } aggression = 4 + highHandValue / 5; } else if (handValue == 3) { //find the value of the higher pair for (int i = 12; i >= 0; i--) { if (values[i] == 2) { highHandValue = i; } } aggression = 7 + highHandValue / 5; } else { aggression = 10; } } //check to see if they are going first if (actions.Count == 0) { if (aggression <= 2) { return(new PlayerAction(name, "Bet1", "check", 0)); } else { //use random to find the next //high bet if (r.Next(3, 11) <= aggression) { moneyBet += 10; return(new PlayerAction(name, "Bet1", "bet", 10)); } //low bet else if (r.Next(1, 4) <= aggression) { moneyBet += 5; return(new PlayerAction(name, "Bet1", "bet", 5)); } //check to pass else { return(new PlayerAction(name, "Bet1", "check", 0)); } } } //if the player is not making the first move, it is following a move from the opponent else { //store the last action PlayerAction lastAction = actions[actions.Count - 1]; ///----------Check------------------------------------------------------------------ //if the last action was a check if (lastAction.ActionName == "check") { //if we are at the money limit, don't raise to same money for second bet if (atLimit) { return(new PlayerAction(name, "Bet1", "check", 0)); } //if we are not at our money limit we should try and make bets else { //get the money avaiable to bet moneyAvailable = r1MaxBet - moneyBet; //high bet if (r.Next(4, 11) <= aggression && moneyAvailable > 10) { moneyAvailable -= 10; moneyToBet = 10 + r.Next(moneyAvailable / 2, moneyAvailable * 3 / 4); moneyBet += moneyToBet; return(new PlayerAction(name, "Bet1", "bet", moneyToBet)); } //low bet else if (r.Next(1, 5) <= aggression && moneyAvailable > 5) { moneyAvailable -= 5; moneyToBet = 5 + r.Next(moneyAvailable / 2); moneyBet += moneyToBet; return(new PlayerAction(name, "Bet1", "bet", moneyToBet)); } //check to end the betting else { return(new PlayerAction(name, "Bet1", "check", 0)); } } } ///----------Call------------------------------------------------------------------ //the opponent called the players raise, the only valid move is to call else if (lastAction.ActionName == "call") { return(new PlayerAction(name, "Bet1", "call", 0)); } ///----------Raise/Bet------------------------------------------------------------------ //bet and raise are handled the same way else if (lastAction.ActionName == "raise" || lastAction.ActionName == "bet") { //adjust money the player has bet since there has been a raise/bet moneyBet += lastAction.Amount; //get the amount of money the player has to bet moneyAvailable = r1MaxBet - moneyBet; //check to see if the opponents raise will goes over the max bet set, but if the value bet is insignificant to our maximum, call the bet if (lastAction.Amount > moneyAvailable && lastAction.Amount <= Math.Max(r1MaxBet * .15, 15)) { return(new PlayerAction(name, "Bet1", "call", 0)); } //if we are at our money limit and reaching our raise max, call to end betting to try and win and not lose money from the initial ante else if (moneyAvailable < r1MaxBet * 3 / 4 && atLimit) { return(new PlayerAction(name, "Bet1", "call", 0)); } //if the amount that the opponent has bet exceeds the limit that has been placed and is significant (isnt caught in the last check), fold the hand else if (lastAction.Amount > moneyAvailable) { return(new PlayerAction(name, "Bet1", "fold", 0)); } //we still have money to bet and the last amount does not exceed it (caught before reaching here) else { //high bet if (r.Next(3, 11) <= aggression && moneyAvailable > 10) { moneyAvailable -= 10; //adjust the amount to bet by the amount that the opponent placed last turn, so the bet is limited and will not "scare" the opponent //if the bet that would be placed would be too high moneyToBet = 10 + (int)(r.Next(moneyAvailable / 2, moneyAvailable) * Math.Min(((float)lastAction.Amount / (float)moneyAvailable), 1.0f)); moneyBet += moneyToBet; return(new PlayerAction(name, "Bet1", "raise", moneyToBet)); } //low bet else if (r.Next(1, 5) <= aggression && moneyAvailable > 5) { moneyAvailable -= 5; //adjust the amount to bet by the amount that the opponent placed last turn, so the bet is limited and will not "scare" the opponent //if the bet that would be placed would be too high moneyToBet = 5 + (int)(r.Next(moneyAvailable * 1 / 4, moneyAvailable / 2) * Math.Min(((float)lastAction.Amount / (float)moneyAvailable), 1.0f)); moneyBet += moneyToBet; return(new PlayerAction(name, "Bet1", "raise", moneyToBet)); } //now decide to call the raise that was made since the player is not placing a high or low bet else { return(new PlayerAction(name, "Bet1", "call", 0)); } } } //no fold scenario since a fold will end the round before coming here } //Console.WriteLine("didnt catch"); return(new PlayerAction(name, "Bet1", "fold", 0)); }
// 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); }
public bool[] GetCardsToDelete(Card[] hand) { bool[] cardPositionToDelete = { false, false, false, false, false }; Card highCard = null; int rank = Evaluate.RateAHand(hand, out highCard); // Do not change any cards for Royal Flush, Straight Flush, Full House, Flush or Straight // In case of four of a kind try and get a better value card for the kicker if (rank == 8 && highCard.Value < 7) { if (hand[0].Value == hand[2].Value) { cardPositionToDelete[4] = true; } else { cardPositionToDelete[0] = true; } } // In case of 3 of a kind, change one card if the kicker is high, else discard 2 cards if (rank == 4 && highCard.Value > 7) { if ((hand[0].Value == hand[1].Value) && (hand[0].Value == hand[2].Value)) { cardPositionToDelete[3] = true; } else { cardPositionToDelete[0] = true; } } else if (rank == 4 && highCard.Value < 7) { if ((hand[0].Value == hand[1].Value) && (hand[0].Value == hand[2].Value)) { cardPositionToDelete[3] = true; cardPositionToDelete[4] = true; } else if ((hand[1].Value == hand[2].Value) && (hand[1].Value == hand[3].Value)) { cardPositionToDelete[0] = true; cardPositionToDelete[4] = true; } else { cardPositionToDelete[0] = true; cardPositionToDelete[1] = true; } } if (rank == 3 && highCard.Value < 7) { if ((hand[4].Value == hand[3].Value) && (hand[2].Value == hand[1].Value)) { cardPositionToDelete[0] = true; } else if ((hand[4].Value == hand[3].Value) && (hand[1].Value == hand[0].Value)) { cardPositionToDelete[2] = true; } else { cardPositionToDelete[4] = true; } } // If it is one pair or high card, check if there is a possibility of flush or straight and discard cards accordingly if (rank == 2 || rank == 1) { if (IsFlushPossible(hand, out cardPositionToDelete)) { return(cardPositionToDelete); } else if (IsStraightPossible(hand, out cardPositionToDelete)) { return(cardPositionToDelete); } else { // Discard cards with value lower than 10 for (int i = 0; i < hand.Length; i++) { if (hand[i].Value < 10) { cardPositionToDelete[i] = true; } } } } return(cardPositionToDelete); }
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); }