public StartRoundContext(GameRoundType roundType, IReadOnlyCollection<Card> communityCards, int moneyLeft, int currentPot)
 {
     this.RoundType = roundType;
     this.CommunityCards = communityCards;
     this.MoneyLeft = moneyLeft;
     this.CurrentPot = currentPot;
 }
示例#2
0
 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;
 }
示例#5
0
        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);
            }
        }
示例#6
0
 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;
 }
示例#8
0
        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();
        }
示例#11
0
        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);
        }
示例#14
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();
            }
        }
示例#20
0
        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;
            }
        }
示例#23
0
        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];
            }
        }
示例#24
0
        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]);
            }
        }
示例#25
0
        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;
        }
示例#28
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.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;
        }
示例#29
0
        /// <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;
        }
示例#35
0
        /// <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);
        }