public StartRoundContext(GameRoundType roundType, IReadOnlyCollection<Card> communityCards, int moneyLeft, int currentPot) { this.RoundType = roundType; this.CommunityCards = communityCards; this.MoneyLeft = moneyLeft; this.CurrentPot = currentPot; }
public StartRoundContext(GameRoundType roundType, List <Card> boardCards, int moneyLeft, int currentPot) { this.RoundType = roundType; this.BoardCards = boardCards; this.MoneyLeft = moneyLeft; this.CurrentPot = currentPot; }
public float[] Evaluate( Card firstCard, Card secondCard, IReadOnlyCollection<Card> communityCards, GameRoundType round ) { InitializeAllCardsToEvaluate(firstCard, secondCard, communityCards); byte maxSameSuits = 0; byte maxSameTypes = 0; byte maxStraight = 0; GetPresentCombinations(ref maxSameSuits, ref maxSameTypes, ref maxStraight); // edited chance for 2, 3 and 4 of a kind DrawSameType(maxSameTypes); // edited chance for Flush allCombinationsProbabillity[5] = DrawSameSuit(maxSameSuits); // edited chance for Straight allCombinationsProbabillity[4] = DrawStraight(maxStraight); return allCombinationsProbabillity; }
public StartRoundContext(GameRoundType roundType, IReadOnlyCollection <Card> communityCards, int moneyLeft, int currentPot) { this.RoundType = roundType; this.CommunityCards = communityCards; this.MoneyLeft = moneyLeft; this.CurrentPot = currentPot; }
private void PlayRound(GameRoundType gameRoundType, int communityCardsCount) { for (var i = 0; i < communityCardsCount; i++) { this.communityCards.Add(this.deck.GetNextCard()); } foreach (var player in this.players) { var startRoundContext = new StartRoundContext( gameRoundType, this.communityCards.AsReadOnly(), player.PlayerMoney.Money, this.bettingLogic.Pot, this.bettingLogic.MainPot, this.bettingLogic.SidePots); player.StartRound(startRoundContext); } this.bettingLogic.Bet(gameRoundType); foreach (var player in this.players) { var endRoundContext = new EndRoundContext(this.bettingLogic.HandBets, gameRoundType); player.EndRound(endRoundContext); } }
public GetTurnContext( GameRoundType roundType, IReadOnlyCollection <PlayerActionAndName> previousRoundActions, int smallBlind, int moneyLeft, int currentPot, int myMoneyInTheRound, int currentMaxBet, int minRaise, Pot mainPot, List <Pot> sidePots, ICollection <Opponent> opponents) { this.RoundType = roundType; this.PreviousRoundActions = previousRoundActions; this.SmallBlind = smallBlind; this.MoneyLeft = moneyLeft; this.CurrentPot = currentPot; this.MyMoneyInTheRound = myMoneyInTheRound; this.CurrentMaxBet = currentMaxBet; this.MinRaise = minRaise; this.MainPot = mainPot; this.SidePots = sidePots; this.Opponents = opponents; }
public GetActionContext( IReadOnlyCollection <PlayerActionAndName> previousRoundActions, GameStackStage currentGameStackStage, List <IReadOnlyCollection <PlayerActionAndName> > roundsActions, GameRoundType roundType, Card firstCard, Card secondCard, IReadOnlyCollection <Card> communityCards, int smallBlind, int myMoney, int opponentStack, int currentPot, bool canCheck, string name) { this.PreviousRoundActions = previousRoundActions; this.CurrentGameStackStage = currentGameStackStage; this.RoundsActions = roundsActions; this.RoundType = roundType; this.FirstCard = firstCard; this.SecondCard = secondCard; this.CommunityCards = communityCards; this.SmallBlind = smallBlind; this.MyMoney = myMoney; this.OpponentStack = opponentStack; this.CurrentPot = currentPot; this.CanCheck = canCheck; this.Name = name; }
public void Bet(GameRoundType gameRoundType) { this.RoundBets.Clear(); var playerIndex = 0; if (gameRoundType == GameRoundType.PreFlop) { this.PlaceBlinds(); playerIndex = 2; } while (this.allPlayers.Count(x => x.PlayerMoney.InHand) >= 2 && this.allPlayers.Any(x => x.PlayerMoney.ShouldPlayInRound)) { var player = this.allPlayers[playerIndex % this.allPlayers.Count]; if (!player.PlayerMoney.InHand || !player.PlayerMoney.ShouldPlayInRound) { continue; } var maxMoneyPerPlayer = this.allPlayers.Max(x => x.PlayerMoney.CurrentRoundBet); TurnContext TurnContext = new TurnContext( (int)gameRoundType, //this.RoundBets, this.smallBlind, player.PlayerMoney.Money, this.Pot, player.PlayerMoney.CurrentRoundBet, maxMoneyPerPlayer); player.Connection.SendObject("TurnContext", TurnContext); action = null; while (action == null) { Thread.Sleep(200); } action = player.PlayerMoney.DoPlayerAction(action, maxMoneyPerPlayer); this.RoundBets.Add(new PlayerActionName(player.Name, action)); if (action.Type == (int)PlayerActionType.Raise) { foreach (var playerToUpdate in this.allPlayers) { playerToUpdate.PlayerMoney.ShouldPlayInRound = true; } } action = null; player.PlayerMoney.ShouldPlayInRound = false; playerIndex++; } this.ReturnMoneyInCaseOfAllIn(); }
protected double Increase(GameRoundType street, double step) { if (this.coefficientByStreets[street] < 1.0) { // reset this.coefficientByStreets[street] = 1.0; } this.coefficientByStreets[street] += step; return(this.coefficientByStreets[street]); }
public void Bet(GameRoundType gameRoundType) { this.RoundBets.Clear(); var playerIndex = 0; if (gameRoundType == GameRoundType.PreFlop) { this.PlaceBlinds(); playerIndex = 2; } while (this.allPlayers.Count(x => x.PlayerMoney.InHand) >= 2 && this.allPlayers.Any(x => x.PlayerMoney.ShouldPlayInRound)) { var player = this.allPlayers[playerIndex % this.allPlayers.Count]; if (!player.PlayerMoney.InHand || !player.PlayerMoney.ShouldPlayInRound) { continue; } var maxMoneyPerPlayer = this.allPlayers.Max(x => x.PlayerMoney.CurrentRoundBet); var action = player.GetTurn( new GetTurnContext( gameRoundType, this.RoundBets.AsReadOnly(), this.smallBlind, player.PlayerMoney.Money, this.Pot, player.PlayerMoney.CurrentRoundBet, maxMoneyPerPlayer)); action = player.PlayerMoney.DoPlayerAction(action, maxMoneyPerPlayer); this.RoundBets.Add(new PlayerActionAndName(player.Name, action)); if (action.Type == PlayerActionType.Raise) { // When raising, all players are required to do action afterwards in current round foreach (var playerToUpdate in this.allPlayers) { playerToUpdate.PlayerMoney.ShouldPlayInRound = true; } } player.PlayerMoney.ShouldPlayInRound = false; playerIndex++; } this.ReturnMoneyInCaseOfAllIn(); }
public StartRoundContext( GameRoundType roundType, IReadOnlyCollection <Card> communityCards, int moneyLeft, int currentPot, Pot currentMainPot, List <Pot> currentSidePots) { this.RoundType = roundType; this.CommunityCards = communityCards; this.MoneyLeft = moneyLeft; this.CurrentPot = currentPot; this.CurrentMainPot = currentMainPot; this.CurrentSidePots = currentSidePots; }
public override double CorrectionFactor(IStats currentPlayerStats, GameRoundType street) { if (currentPlayerStats.VPIP.Hands >= this.NumberOfHandsToStartCorrection) { if (currentPlayerStats.VPIP.Percentage > this.vpip.Percentage) { return(this.Decrease(0.25)); } else { return(this.Increase(0.05)); } } return(1.0); }
public GetTurnContext( GameRoundType roundType, IReadOnlyCollection <PlayerActionAndName> previousRoundActions, int smallBlind, int moneyLeft, int currentPot, int myMoneyInTheRound, int currentMaxBet) { this.RoundType = roundType; this.PreviousRoundActions = previousRoundActions; this.SmallBlind = smallBlind; this.MoneyLeft = moneyLeft; this.CurrentPot = currentPot; this.MyMoneyInTheRound = myMoneyInTheRound; this.CurrentMaxBet = currentMaxBet; }
public GetTurnContext( GameRoundType roundType, IReadOnlyCollection<PlayerActionAndName> previousActions, int smallBlind, int moneyLeft, int currentPot, int myMoneyInThePot, int maxMoneyPerPlayerInThePot) { this.RoundType = roundType; this.PreviousActions = previousActions; this.SmallBlind = smallBlind; this.MoneyLeft = moneyLeft; this.CurrentPot = currentPot; this.MyMoneyInThePot = myMoneyInThePot; this.MaxMoneyPerPlayerInThePot = maxMoneyPerPlayerInThePot; }
public override double CorrectionFactor(IStats currentPlayerStats, GameRoundType street) { if (currentPlayerStats.ThreeBet.Hands >= this.NumberOfHandsToStartCorrection) { if (currentPlayerStats.ThreeBet.IndicatorByStreets[GameRoundType.PreFlop].Percentage > this.threeBet.IndicatorByStreets[GameRoundType.PreFlop].Percentage) { return(this.Decrease(0.25)); } else { return(this.Increase(0.05)); } } return(1.0); }
protected double Decrease(GameRoundType street, double step) { if (this.coefficientByStreets[street] > 1.0) { // reset this.coefficientByStreets[street] = 1.0; } this.coefficientByStreets[street] -= step; if (this.coefficientByStreets[street] < 0) { this.coefficientByStreets[street] = 0; } return(this.coefficientByStreets[street]); }
public void Bet(GameRoundType gameRoundType) { var bets = new List <PlayerActionAndName>(); if (gameRoundType == GameRoundType.PreFlop) { // TODO: What if small blind is bigger than player's money? this.allPlayers[0].PlaceMoney(this.smallBlind); bets.Add(new PlayerActionAndName(this.allPlayers[0].Name, PlayerAction.Raise(this.smallBlind))); // TODO: What if big blind is bigger than player's money? this.allPlayers[1].PlaceMoney(this.smallBlind * 2); bets.Add(new PlayerActionAndName(this.allPlayers[1].Name, PlayerAction.Raise(this.smallBlind * 2))); } var playerIndex = 1; while (this.allPlayers.Count(x => x.InHand) >= 2 && this.allPlayers.Any(x => x.ShouldPlayInRound)) { playerIndex++; var player = this.allPlayers[playerIndex % this.allPlayers.Count]; if (!player.InHand) { continue; } var maxMoneyPerPlayer = this.allPlayers.Max(x => x.CurrentRoundBet); var action = player.GetTurn( new GetTurnContext( gameRoundType, bets.AsReadOnly(), this.smallBlind, player.Money, this.Pot, player.CurrentlyInPot, maxMoneyPerPlayer)); action = this.DoPlayerAction(player, action, maxMoneyPerPlayer); bets.Add(new PlayerActionAndName(player.Name, action)); player.ShouldPlayInRound = false; } }
private void PlayRound(GameRoundType gameRoundType, int communityCardsCount) { for (var i = 0; i < communityCardsCount; i++) { this.communityCards.Add(this.deck.GetNextCard()); } foreach (var player in this.players) { player.StartRound(new StartRoundContext(gameRoundType, this.communityCards.AsReadOnly(), player.Money, this.bettingLogic.Pot)); } this.bettingLogic.Bet(gameRoundType); foreach (var player in this.players) { player.EndRound(); } }
public override double CorrectionFactor(IStats currentPlayerStats, GameRoundType street) { if (currentPlayerStats.RFI.Hands >= this.NumberOfHandsToStartCorrection) { var currentPosition = currentPlayerStats.RFI.CurrentPosition; if (currentPlayerStats.RFI.IndicatorByPositions[currentPosition.Value].Percentage > this.rfi.IndicatorByPositions[currentPosition.Value].Percentage) { return(this.Decrease(currentPosition.Value, 0.25)); } else { return(this.Increase(currentPosition.Value, 0.1)); } } return(1.0); }
public void Bet(GameRoundType gameRoundType) { var bets = new List<PlayerActionAndName>(); if (gameRoundType == GameRoundType.PreFlop) { // TODO: What if small blind is bigger than player's money? this.allPlayers[0].PlaceMoney(this.smallBlind); bets.Add(new PlayerActionAndName(this.allPlayers[0].Name, PlayerAction.Raise(this.smallBlind))); // TODO: What if big blind is bigger than player's money? this.allPlayers[1].PlaceMoney(this.smallBlind * 2); bets.Add(new PlayerActionAndName(this.allPlayers[1].Name, PlayerAction.Raise(this.smallBlind * 2))); } var playerIndex = 1; while (this.allPlayers.Count(x => x.InHand) >= 2 && this.allPlayers.Any(x => x.ShouldPlayInRound)) { playerIndex++; var player = this.allPlayers[playerIndex % this.allPlayers.Count]; if (!player.InHand) { continue; } var maxMoneyPerPlayer = this.allPlayers.Max(x => x.CurrentRoundBet); var action = player.GetTurn( new GetTurnContext( gameRoundType, bets.AsReadOnly(), this.smallBlind, player.Money, this.Pot, player.CurrentlyInPot, maxMoneyPerPlayer)); action = this.DoPlayerAction(player, action, maxMoneyPerPlayer); bets.Add(new PlayerActionAndName(player.Name, action)); player.ShouldPlayInRound = false; } }
public IDecisionMaker GetDecisionMaker(GameRoundType gameRoundType) { switch (gameRoundType) { case GameRoundType.PreFlop: if (!this.factories.ContainsKey((int)gameRoundType)) { this.factories.Add((int)gameRoundType, new PreFlopDecisionMaker()); } return this.factories[(int)gameRoundType]; default: if (!this.factories.ContainsKey(DefaultId)) { this.factories.Add(DefaultId, new PostFlopDecisionMaker()); } return this.factories[DefaultId]; } }
public IDecisionMaker GetDecisionMaker(GameRoundType gameRoundType) { switch (gameRoundType) { case GameRoundType.PreFlop: if (!this.factories.ContainsKey((int)gameRoundType)) { this.factories.Add((int)gameRoundType, new PreFlopDecisionMaker()); } return(this.factories[(int)gameRoundType]); default: if (!this.factories.ContainsKey(DefaultId)) { this.factories.Add(DefaultId, new PostFlopDecisionMaker()); } return(this.factories[DefaultId]); } }
private void PlayRound(GameRoundType gameRoundType, int communityCardsCount) { for (var i = 0; i < communityCardsCount; i++) { this.communityCards.Add(this.deck.GetNextCard()); } foreach (var player in this.players) { waitPlayer = false; var startRoundContext = new StartRoundContext( gameRoundType, this.communityCards, player.PlayerMoney.Money, this.bettingLogic.Pot); player.StartRound(startRoundContext); player.Connection.SendObject("StartRoundContext", startRoundContext); while (!waitPlayer) { Thread.Sleep(200); } } this.bettingLogic.Bet(gameRoundType); foreach (var player in this.players) { waitPlayer = false; var endRoundContext = new EndRoundContext(this.bettingLogic.RoundBets); player.EndRound(endRoundContext); player.Connection.SendObject("EndRoundContext", endRoundContext); while (!waitPlayer) { Thread.Sleep(200); } } }
public abstract double CorrectionFactor(IStats currentPlayerStats, GameRoundType street);
// LassVegas method (slow, accurate). Calculate on every turn and get average of all the aproximate ods for the round to reducethe error. public float GetAverageOdds(GameRoundType roundType) { var predictions = this.enemyCardsPrediction; if (predictions == null) { predictions = this.enemyCardsPredictionWorstCase; } float ods; if (!(enemyAlwaysAllIn || enemyAlwaysRise) && predictions != null) { if (roundType == GameRoundType.Flop || roundType == GameRoundType.Turn) { // Approximation ods = HandPotentialValuation.GetHandPotentialMonteCarloApproximation3( this.FirstCard, this.SecondCard, this.CommunityCards, predictions, 250); } else { ods = HandStrengthValuation.HandStrengthMonteCarloApproximation2( this.FirstCard, this.SecondCard, this.CommunityCards, predictions, 500); // 500 passing } } else { if (roundType == GameRoundType.Flop || roundType == GameRoundType.Turn) { // Approximation ods = HandPotentialValuation.GetHandPotentialMonteCarloApproximation2( this.FirstCard, this.SecondCard, this.CommunityCards, 250); } else { ods = HandStrengthValuation.HandStrengthMonteCarloApproximation( this.FirstCard, this.SecondCard, this.CommunityCards, 500); // 500 passing } } oddsForThisRound.Add(ods); roundOdds = oddsForThisRound.Average(); return roundOdds; }
public void Bet(GameRoundType gameRoundType) { var bets = new List <PlayerActionAndName>(); if (gameRoundType == GameRoundType.PreFlop) { // TODO: What if small blind is bigger than player's money? this.Bet(this.allPlayers[0], this.smallBlind); bets.Add(new PlayerActionAndName(this.allPlayers[0].Name, PlayerAction.Raise(this.smallBlind))); // TODO: What if big blind is bigger than player's money? this.Bet(this.allPlayers[1], this.smallBlind * 2); bets.Add(new PlayerActionAndName(this.allPlayers[1].Name, PlayerAction.Raise(this.smallBlind * 2))); } var playerIndex = 1; while (this.allPlayers.Count(x => x.InHand) >= 2 && this.allPlayers.Any(x => x.ShouldPlayInRound)) { playerIndex++; var player = this.allPlayers[playerIndex % this.allPlayers.Count]; if (!player.InHand) { continue; } var maxMoneyPerPlayer = this.allPlayers.Max(x => x.CurrentlyInPot); var action = player.GetTurn( new GetTurnContext( gameRoundType, bets.AsReadOnly(), this.smallBlind, player.Money, this.Pot, maxMoneyPerPlayer)); bets.Add(new PlayerActionAndName(player.Name, action)); if (action.Type == PlayerActionType.Raise) { foreach (var playerToUpdate in this.allPlayers) { playerToUpdate.ShouldPlayInRound = true; } this.Bet(player, action.Money); } else if (action.Type == PlayerActionType.CheckCall) { player.ShouldPlayInRound = true; var amountToCall = this.allPlayers.Max(x => x.CurrentlyInPot) - player.CurrentlyInPot; this.Bet(player, amountToCall); } else //// PlayerActionType.Fold { player.InHand = false; } // TODO: Pot is splitted evenly - if %2 == 1 - first awarded takes 1 chip extra - (e.g. SB) player.ShouldPlayInRound = false; } InternalPlayer winner; if (this.allPlayers.Count(x => x.InHand) == 1) { winner = this.allPlayers.FirstOrDefault(x => x.InHand); } else { // TODO: Bigger card winner = this.allPlayers[0]; } winner.Money += this.Pot; }
/// <summary> /// <para>This method calculates chances of our hand to win and based on the results returns values, which to be used for decisionmaking</para> /// <para>Used methods to calculate chances:</para> /// <para>-> for pre-flop: uses the gap parameter and checkes wether we have High Card or a Pair</para> /// <para>-> for all other rounds: uses MonteCarlo algorythm on 250 game trials, which is with diff: (3 to 2.5)</para> /// </summary> /// <param name="ourCards"><c>string</c> that contains our cards <example>example: "2h 3h"</example></param> /// <param name="communityCards"><c>string</c> that contains the community cards <example>example: "Jh Qh 2d"</example></param> /// <param name="currentRound"><c>GameRoundType</c> is enum that informs us in which round are we currently playing <example>example: GameRoundType.PreFlop</example></param> /// <param name="gapBetweenOurCards"><c>int</c> that informs us what is the gap between the cards in our hand /// <example>example: If we have Jack and 8 -> gap = 2, /// If we have King and 6 -> gap = 6</example></param> /// <returns><c>Turn</c> object that holds the chance values for Fold, Call, Raise and AllIn</returns> /// <seealso cref="http://www.codeproject.com/Articles/19092/More-Texas-Holdem-Analysis-in-C-Part-2"/> public Turn DecideChanceForAction(string ourCards, string communityCards, GameRoundType currentRound, int gapBetweenOurCards) { var output = new Turn(); var ourHand = new Hand(ourCards, communityCards); int chance = 0; switch (currentRound) { case GameRoundType.PreFlop: if (gapBetweenOurCards >= 4) { this.Call++; this.Fold++; } else if (gapBetweenOurCards >= 2) { this.Raise++; this.Call++; } else { this.AllIn++; this.Raise++; } var handTypeValue = ourHand.HandTypeValue; switch (handTypeValue) { case Hand.HandTypes.HighCard: this.Raise++; this.Call++; break; case Hand.HandTypes.Pair: this.AllIn++; this.Raise++; this.Call++; break; default: this.Raise++; this.Call++; this.Fold++; break; } break; case GameRoundType.Flop: chance = MonteCarloAnalysis.WinOddsMonteCarlo(ourCards, communityCards); if (chance > 16 && chance <= 34) { this.Call++; this.Fold++; } else if (chance > 34 && chance <= 40) { this.Raise++; this.Call++; } else if (chance > 40 && chance <= 51) { this.AllIn++; this.Raise++; this.Call++; } else if (chance > 51) { this.AllIn++; this.Raise++; } else { this.Fold++; } break; case GameRoundType.Turn: chance = MonteCarloAnalysis.WinOddsMonteCarlo(ourCards, communityCards); if (chance > 18 && chance <= 34) { this.Call++; this.Fold++; } else if (chance > 34 && chance <= 41) { this.Raise++; this.Call++; } else if (chance > 41 && chance <= 55) { this.AllIn++; this.Raise++; this.Call++; } else if (chance > 55) { this.AllIn++; this.Raise++; } else { this.Fold++; } break; case GameRoundType.River: chance = MonteCarloAnalysis.WinOddsMonteCarlo(ourCards, communityCards); if (chance > 20 && chance <= 36) { this.Call++; this.Fold++; } else if (chance > 36 && chance <= 45) { this.Raise++; this.Call++; } else if (chance > 45 && chance <= 62) { this.AllIn++; this.Raise++; this.Call++; } else if (chance > 62) { this.AllIn++; this.Raise++; } else { this.Fold++; } break; } return output; }
public void Bet(GameRoundType gameRoundType) { this.RoundBets.Clear(); this.minRaise.Reset(); var playerIndex = gameRoundType == GameRoundType.PreFlop ? this.initialPlayerIndex : 1; if (gameRoundType == GameRoundType.PreFlop) { this.PlaceBlinds(); playerIndex = this.initialPlayerIndex + 2; } if (this.allPlayers.Count(x => x.PlayerMoney.ShouldPlayInRound) <= 1) { return; } while (this.allPlayers.Count(x => x.PlayerMoney.InHand) >= 2 && this.allPlayers.Any(x => x.PlayerMoney.ShouldPlayInRound)) { var player = this.allPlayers[playerIndex % this.allPlayers.Count]; if (player.PlayerMoney.Money <= 0) { // Players who are all-in are not involved in betting round player.PlayerMoney.ShouldPlayInRound = false; playerIndex++; continue; } if (!player.PlayerMoney.InHand || !player.PlayerMoney.ShouldPlayInRound) { if (player.PlayerMoney.InHand == player.PlayerMoney.ShouldPlayInRound) { playerIndex++; } continue; } var maxMoneyPerPlayer = this.allPlayers.Max(x => x.PlayerMoney.CurrentRoundBet); var action = player.GetTurn( new GetTurnContext( gameRoundType, this.RoundBets.AsReadOnly(), this.smallBlind, player.PlayerMoney.Money, this.Pot, player.PlayerMoney.CurrentRoundBet, maxMoneyPerPlayer, this.minRaise.Amount(player.Name), this.MainPot, this.SidePots)); action = player.PlayerMoney.DoPlayerAction(action, maxMoneyPerPlayer); this.RoundBets.Add(new PlayerActionAndName(player.Name, action)); if (action.Type == PlayerActionType.Raise) { // When raising, all players are required to do action afterwards in current round foreach (var playerToUpdate in this.allPlayers) { playerToUpdate.PlayerMoney.ShouldPlayInRound = playerToUpdate.PlayerMoney.InHand ? true : false; } } this.minRaise.Update(player.Name, maxMoneyPerPlayer, player.PlayerMoney.CurrentRoundBet); player.PlayerMoney.ShouldPlayInRound = false; playerIndex++; } if (this.allPlayers.Count == 2) { // works only for heads-up this.ReturnMoneyInCaseOfAllIn(); } else { this.ReturnMoneyInCaseUncalledBet(); } }
public EndHandContext(Dictionary <string, ICollection <Card> > showdownCards, int moneyLeft, GameRoundType lastGameRoundType) { this.ShowdownCards = showdownCards; this.MoneyLeft = moneyLeft; this.LastGameRoundType = lastGameRoundType; }
public EndRoundContext(IReadOnlyCollection <PlayerActionAndName> roundActions, GameRoundType completedRoundType) { this.RoundActions = roundActions; this.CompletedRoundType = completedRoundType; }
public PlayerActionAndName(string playerName, PlayerAction action, GameRoundType round) { this.PlayerName = playerName; this.Action = action; this.Round = round; }
public void Bet(GameRoundType gameRoundType) { var bets = new List<PlayerActionAndName>(); if (gameRoundType == GameRoundType.PreFlop) { // TODO: What if small blind is bigger than player's money? this.Bet(this.allPlayers[0], this.smallBlind); bets.Add(new PlayerActionAndName(this.allPlayers[0].Name, PlayerAction.Raise(this.smallBlind))); // TODO: What if big blind is bigger than player's money? this.Bet(this.allPlayers[1], this.smallBlind * 2); bets.Add(new PlayerActionAndName(this.allPlayers[1].Name, PlayerAction.Raise(this.smallBlind * 2))); } var playerIndex = 1; while (this.allPlayers.Count(x => x.InHand) >= 2 && this.allPlayers.Any(x => x.ShouldPlayInRound)) { playerIndex++; var player = this.allPlayers[playerIndex % this.allPlayers.Count]; if (!player.InHand) { continue; } var maxMoneyPerPlayer = this.allPlayers.Max(x => x.CurrentlyInPot); var action = player.GetTurn( new GetTurnContext( gameRoundType, bets.AsReadOnly(), this.smallBlind, player.Money, this.Pot, maxMoneyPerPlayer)); bets.Add(new PlayerActionAndName(player.Name, action)); if (action.Type == PlayerActionType.Raise) { foreach (var playerToUpdate in this.allPlayers) { playerToUpdate.ShouldPlayInRound = true; } this.Bet(player, action.Money); } else if (action.Type == PlayerActionType.CheckCall) { player.ShouldPlayInRound = true; var amountToCall = this.allPlayers.Max(x => x.CurrentlyInPot) - player.CurrentlyInPot; this.Bet(player, amountToCall); } else //// PlayerActionType.Fold { player.InHand = false; } // TODO: Pot is splitted evenly - if %2 == 1 - first awarded takes 1 chip extra - (e.g. SB) player.ShouldPlayInRound = false; } InternalPlayer winner; if (this.allPlayers.Count(x => x.InHand) == 1) { winner = this.allPlayers.FirstOrDefault(x => x.InHand); } else { // TODO: Bigger card winner = this.allPlayers[0]; } winner.Money += this.Pot; }
/// <summary> /// <para>This method calculates chances of our hand to win and based on the results returns values, which to be used for decisionmaking</para> /// <para>Used methods to calculate chances:</para> /// <para>-> for pre-flop: uses the gap parameter and checkes wether we have High Card or a Pair</para> /// <para>-> for all other rounds: uses MonteCarlo algorythm on 250 game trials, which is with diff: (3 to 2.5)</para> /// </summary> /// <param name="ourCards"><c>string</c> that contains our cards <example>example: "2h 3h"</example></param> /// <param name="communityCards"><c>string</c> that contains the community cards <example>example: "Jh Qh 2d"</example></param> /// <param name="currentRound"><c>GameRoundType</c> is enum that informs us in which round are we currently playing <example>example: GameRoundType.PreFlop</example></param> /// <param name="gapBetweenOurCards"><c>int</c> that informs us what is the gap between the cards in our hand /// <example>example: If we have Jack and 8 -> gap = 2, /// If we have King and 6 -> gap = 6</example></param> /// <returns><c>Turn</c> object that holds the chance values for Fold, Call, Raise and AllIn</returns> /// <seealso cref="http://www.codeproject.com/Articles/19092/More-Texas-Holdem-Analysis-in-C-Part-2"/> public Turn DecideChanceForAction(string ourCards, string communityCards, GameRoundType currentRound, int gapBetweenOurCards) { var output = new Turn(); var ourHand = new Hand(ourCards, communityCards); int chance = 0; switch (currentRound) { case GameRoundType.PreFlop: if (gapBetweenOurCards >= 4) { this.Call++; this.Fold++; } else if (gapBetweenOurCards >= 2) { this.Raise++; this.Call++; } else { this.AllIn++; this.Raise++; } var handTypeValue = ourHand.HandTypeValue; switch (handTypeValue) { case Hand.HandTypes.HighCard: this.Raise++; this.Call++; break; case Hand.HandTypes.Pair: this.AllIn++; this.Raise++; this.Call++; break; default: this.Raise++; this.Call++; this.Fold++; break; } break; case GameRoundType.Flop: chance = MonteCarloAnalysis.WinOddsMonteCarlo(ourCards, communityCards); if (chance > 16 && chance <= 34) { this.Call++; this.Fold++; } else if (chance > 34 && chance <= 40) { this.Raise++; this.Call++; } else if (chance > 40 && chance <= 51) { this.AllIn++; this.Raise++; this.Call++; } else if (chance > 51) { this.AllIn++; this.Raise++; } else { this.Fold++; } break; case GameRoundType.Turn: chance = MonteCarloAnalysis.WinOddsMonteCarlo(ourCards, communityCards); if (chance > 18 && chance <= 34) { this.Call++; this.Fold++; } else if (chance > 34 && chance <= 41) { this.Raise++; this.Call++; } else if (chance > 41 && chance <= 55) { this.AllIn++; this.Raise++; this.Call++; } else if (chance > 55) { this.AllIn++; this.Raise++; } else { this.Fold++; } break; case GameRoundType.River: chance = MonteCarloAnalysis.WinOddsMonteCarlo(ourCards, communityCards); if (chance > 20 && chance <= 36) { this.Call++; this.Fold++; } else if (chance > 36 && chance <= 45) { this.Raise++; this.Call++; } else if (chance > 45 && chance <= 62) { this.AllIn++; this.Raise++; this.Call++; } else if (chance > 62) { this.AllIn++; this.Raise++; } else { this.Fold++; } break; } return(output); }
private void PlayRound(GameRoundType gameRoundType, int communityCardsCount) { for (var i = 0; i < communityCardsCount; i++) { this.communityCards.Add(this.deck.GetNextCard()); } foreach (var player in this.players) { var startRoundContext = new StartRoundContext( gameRoundType, this.communityCards,//AsReadOnly() player.PlayerMoney.Money, this.bettingLogic.Pot); player.StartRound(startRoundContext); } this.bettingLogic.Bet(gameRoundType); foreach (var player in this.players) { var endRoundContext = new EndRoundContext(this.bettingLogic.RoundBets); player.EndRound(endRoundContext); } }
public override void StartRound(StartRoundContext context) { base.StartRound(context); this.currentRoundType = context.RoundType; }
public override void StartRound(StartRoundContext context) { this.aintiAIReverseLogickCoeficient = RandomProvider.Next(0, 100); this.currentRoundType = context.RoundType; if (context.MoneyLeft == 0) // || enemyMoney == 0 { return; } oddsForThisRound = new List<float>(); this.currentRoundType = context.RoundType; oddsForThisRound = new List<float>(); if (context.RoundType == GameRoundType.PreFlop) { roundOdds = HandStrengthValuation.PreFlopOdsLookupTable(this.FirstCard, this.SecondCard); } else { // 2 much overhead /*if (enemyCardsPrediction != null) { enemyCardsPrediction = EnemyPredictions.UpdateEnemyCardsGuess(enemyCardsPrediction, context.CommunityCards); }*/ this.GetAverageOdds(context.RoundType); } base.StartRound(context); }