public override PlayerAction GetTurn(GetTurnContext context)
        {
            #region Preflop
            if (context.RoundType == GameRoundType.PreFlop)
            {
                var handValue         = HandStrengthValuationBluffasaurus.PreFlop(this.FirstCard, this.SecondCard);
                var optimalValueCoeff = 2;

                var extreme    = 64 - optimalValueCoeff;
                var powerful   = 60 - optimalValueCoeff;
                var normal     = 55 - optimalValueCoeff;
                var weak       = 50 - (optimalValueCoeff * 2);
                var awful      = 43 - (optimalValueCoeff * 2);
                var lowerLimit = 40 - optimalValueCoeff;

                // if we are first to act on a small blind
                if (context.MoneyToCall == context.SmallBlind && context.CurrentPot == context.SmallBlind * 3)
                {
                    inPosition = true;

                    if (handValue >= extreme)
                    {
                        return(PlayerAction.Raise(context.SmallBlind * 20));
                    }
                    else if (handValue >= powerful)
                    {
                        return(PlayerAction.Raise(context.SmallBlind * 16));
                    }
                    else if (handValue >= normal)
                    {
                        return(PlayerAction.Raise(context.SmallBlind * 12));
                    }
                    else if (handValue >= awful) // that makes around 74% of all possible hands
                    {
                        // can be further optimized
                        if (context.SmallBlind > context.MoneyLeft / 50)
                        {
                            return(PlayerAction.CheckOrCall());
                        }

                        return(PlayerAction.Raise(context.SmallBlind * 10));
                    }
                    else if (handValue > lowerLimit && context.SmallBlind < context.MoneyLeft / 40)
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                    else
                    {
                        return(this.Fold());
                    }
                }
                else  // we are on big blind or opp has raised
                {
                    // opponent has not raised
                    if (context.MoneyToCall == 0)
                    {
                        if (handValue >= extreme) // cards like AA, KK, AKs
                        {
                            return(PlayerAction.Raise(context.SmallBlind * 20));
                        }
                        else if (handValue >= powerful)
                        {
                            return(PlayerAction.Raise(context.SmallBlind * 16));
                        }
                        else if (handValue >= awful) // that makes around 74% of all possible hands
                        {
                            // can be further optimized
                            if (context.SmallBlind > context.MoneyLeft / 50)
                            {
                                return(PlayerAction.CheckOrCall());
                            }

                            return(PlayerAction.Raise(context.SmallBlind * 6));
                        }
                        else
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                    }
                    else // opponent has raised
                    {
                        // if opp has raised a lot(has a very strong hand)
                        if (context.MoneyToCall > context.SmallBlind * 8 && context.MoneyToCall > 40)
                        {
                            if (handValue >= extreme) // cards like AA, KK, AKs
                            {
                                return(PlayerAction.Raise(context.SmallBlind * 16));
                            }
                            else if (handValue >= powerful)
                            {
                                // we have some more money and want to wait for a better shot
                                if (context.MoneyToCall > context.MoneyLeft / 4 && context.MoneyToCall > context.SmallBlind * 6)
                                {
                                    return(this.Fold());
                                }
                                else
                                {
                                    return(PlayerAction.CheckOrCall());
                                }
                            }
                            else
                            {
                                return(this.Fold());
                            }
                        }
                        else // opponent has not raised a lot
                        {
                            if (handValue >= extreme) // cards like AA, KK, AKs
                            {
                                return(PlayerAction.Raise(context.SmallBlind * 20));
                            }
                            else if (handValue >= powerful)
                            {
                                // if we have already raised enough this round
                                if (context.MyMoneyInTheRound > context.SmallBlind * 10)
                                {
                                    return(PlayerAction.CheckOrCall());
                                }
                                else
                                {
                                    return(PlayerAction.Raise(context.SmallBlind * 12));
                                }
                            }
                            else if (handValue >= normal)
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else if (handValue >= weak && (context.MoneyToCall <= 20 || context.MoneyToCall <= context.SmallBlind * 3))
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else if (handValue >= awful && (context.MoneyToCall <= 20 || context.MoneyToCall <= context.SmallBlind * 2))
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else
                            {
                                return(this.Fold());
                            }
                        }
                    }
                }
            }
            #endregion

            #region Flop
            else if (context.RoundType == GameRoundType.Flop)
            {
                var raiseCoeff = context.SmallBlind * 0;

                if (context.MoneyLeft == 0)
                {
                    return(PlayerAction.CheckOrCall());
                }

                var flopCardStrength = CardsStrengthEvaluation.RateCards
                                           (new List <Card> {
                    FirstCard, SecondCard, CommunityCards.ElementAt(0), CommunityCards.ElementAt(1), CommunityCards.ElementAt(2)
                });

                if (inPosition)
                {
                    if (flopCardStrength >= 2000)
                    {
                        return(PlayerAction.Raise(context.SmallBlind * 8 + raiseCoeff));
                    }
                    else if (flopCardStrength >= 1000)
                    {
                        var pairInfo = this.GetPairInfo();

                        if (pairInfo == 0)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            if (pairInfo >= 11)
                            {
                                return(PlayerAction.Raise(context.SmallBlind * 12 + raiseCoeff));
                            }
                            else
                            {
                                return(PlayerAction.Raise(context.SmallBlind * 8 + raiseCoeff));
                            }
                        }
                    }
                    else
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                }
                else
                {
                    // opponent has raised
                    if (context.MoneyToCall > 0)
                    {
                        // a lot
                        if (context.MoneyToCall > context.CurrentPot - context.MoneyToCall && context.MoneyToCall > 50)
                        {
                            if (flopCardStrength >= 3000)
                            {
                                return(PlayerAction.Raise(context.SmallBlind * 30 + raiseCoeff));
                            }
                            if (flopCardStrength >= 2000)
                            {
                                return(PlayerAction.Raise(context.SmallBlind * 10 + raiseCoeff));
                            }
                            else if (flopCardStrength >= 1000)
                            {
                                // is common pair logic
                                var pairInfo = this.GetPairInfo();

                                if (pairInfo == 0)
                                {
                                    return(this.Fold());
                                }
                                else
                                {
                                    // money are a lot and we fold
                                    if (context.MoneyToCall > context.MoneyLeft / 3 && context.MoneyLeft > 300)
                                    {
                                        return(this.Fold());
                                    }
                                    else
                                    {
                                        if (pairInfo >= 11)
                                        {
                                            return(PlayerAction.CheckOrCall());
                                        }
                                        else
                                        {
                                            return(this.Fold());
                                        }
                                    }
                                }
                            }
                            else
                            {
                                return(this.Fold());
                            }
                        }
                        else //not a lot
                        {
                            if (flopCardStrength >= 2000)
                            {
                                return(PlayerAction.Raise(context.SmallBlind * 8 + raiseCoeff));
                            }
                            else if (flopCardStrength >= 1000)
                            {
                                var pairInfo = this.GetPairInfo();

                                if (pairInfo == 0)
                                {
                                    return(PlayerAction.CheckOrCall());
                                }
                                else
                                {
                                    if (pairInfo >= 11)
                                    {
                                        return(PlayerAction.Raise(context.SmallBlind * 8 + raiseCoeff));
                                    }
                                    else
                                    {
                                        return(PlayerAction.CheckOrCall());
                                    }
                                }
                            }
                            else
                            {
                                if (context.MoneyToCall >= 20)
                                {
                                    return(this.Fold());
                                }
                                else
                                {
                                    return(PlayerAction.CheckOrCall());
                                }
                            }
                        }
                    }
                    else // opp has checked (has bad hand)
                    {
                        if (flopCardStrength >= 2000)
                        {
                            return(PlayerAction.Raise(context.SmallBlind * 8 + raiseCoeff));
                        }
                        else if (flopCardStrength >= 1000)
                        {
                            return(PlayerAction.Raise(context.SmallBlind * 16 + raiseCoeff));
                        }

                        return(PlayerAction.CheckOrCall());
                    }
                }
            }
            #endregion

            #region Turn
            else if (context.RoundType == GameRoundType.Turn || context.RoundType == GameRoundType.River)
            {
                if (context.RoundType == GameRoundType.River)
                {
                    inPosition = false;
                }

                if (context.MoneyLeft == 0)
                {
                    return(PlayerAction.CheckOrCall());
                }

                var flopCardStrength = CardsStrengthEvaluation.RateCards
                                           (new List <Card> {
                    FirstCard, SecondCard, CommunityCards.ElementAt(0), CommunityCards.ElementAt(1), CommunityCards.ElementAt(2)
                });

                if (flopCardStrength >= 2000)
                {
                    return(PlayerAction.Raise(context.CurrentPot));
                }
                else
                {
                    var hand = new List <Card>();
                    hand.Add(this.FirstCard);
                    hand.Add(this.SecondCard);

                    var ehs = EffectiveHandStrenghtCalculator.CalculateEHS(hand, this.CommunityCards);

                    if (ehs < 0.3)
                    {
                        if (context.MoneyToCall <= context.MoneyLeft / 200)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else if (ehs < 0.5)
                    {
                        if (context.MoneyToCall <= context.MoneyLeft / 40)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else if (ehs < 0.62)
                    {
                        var currentPot = context.CurrentPot;
                        int moneyToBet = (int)(currentPot * 0.55);

                        if (context.MoneyToCall == 0)
                        {
                            return(PlayerAction.Raise(moneyToBet));
                        }
                        else if (context.MoneyToCall < context.MoneyLeft / 20 || context.MoneyToCall < 50)
                        {
                            if (context.MoneyToCall < moneyToBet && context.MyMoneyInTheRound == 0)
                            {
                                return(PlayerAction.Raise(moneyToBet - context.MoneyToCall + 1));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else if (ehs < 0.75)
                    {
                        var currentPot = context.CurrentPot;
                        int moneyToBet = (int)(currentPot * 0.75);

                        if (context.MoneyToCall == 0)
                        {
                            return(PlayerAction.Raise(moneyToBet));
                        }
                        else if (context.MoneyToCall < context.MoneyLeft / 10 || context.MoneyToCall < 70) // TODO:
                        {
                            if (context.MoneyToCall < moneyToBet && context.MyMoneyInTheRound == 0)
                            {
                                return(PlayerAction.Raise(moneyToBet - context.MoneyToCall + 1));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else if (ehs < 0.85)
                    {
                        var currentPot = context.CurrentPot;
                        int moneyToBet = (int)(currentPot * 0.85);

                        if (context.MoneyToCall == 0)
                        {
                            if (moneyToBet < 50)
                            {
                                moneyToBet = 50;
                            }

                            return(PlayerAction.Raise(moneyToBet));
                        }
                        else if (context.MoneyToCall < context.MoneyLeft / 2 || context.MoneyToCall < 250)
                        {
                            if (context.MoneyToCall < moneyToBet && context.MyMoneyInTheRound == 0)
                            {
                                return(PlayerAction.Raise(moneyToBet - context.MoneyToCall + 1));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else
                    {
                        var currentPot = context.CurrentPot;
                        int moneyToBet = currentPot;
                        if (moneyToBet < 80)
                        {
                            moneyToBet = 80;
                        }

                        return(PlayerAction.Raise(moneyToBet));
                    }
                }
            }
            #endregion

            return(PlayerAction.CheckOrCall()); // It should never reach this point
        }
Example #2
0
        public override PlayerAction GetTurn(GetTurnContext context)
        {
            var bigBlind = context.SmallBlind * 2;

            #region Preflop
            if (context.RoundType == GameRoundType.PreFlop)
            {
                var handValue = HandStrengthValuationBluffasaurus.PreFlop(this.FirstCard, this.SecondCard);
                var agression = 0;

                var extreme  = 64 - agression;
                var powerful = 60 - agression;
                var normal   = 56 - agression; // top 40% of cards
                var weak     = 50 - agression;
                var awful    = 45 - agression; // 70% of the cards
                inPosition = true;

                // we are first to act on a small blind - we are not in position so we want to play around 70% of the cards and only raise around 40%
                if (context.MyMoneyInTheRound == context.SmallBlind)
                {
                    inPosition = false;

                    if (handValue >= extreme)
                    {
                        return(PlayerAction.Raise(bigBlind * 4));
                    }
                    else if (handValue >= powerful)
                    {
                        return(PlayerAction.Raise(bigBlind * 3));
                    }
                    else if (handValue >= normal)
                    {
                        return(PlayerAction.Raise(bigBlind * 1));
                    }
                    else if (handValue >= awful)
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                    else if (context.MoneyToCall < context.MoneyLeft / (double)100) // lets try our luck if it is cheap enough
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                    else
                    {
                        return(this.Fold());
                    }
                }
                else if (context.MyMoneyInTheRound == bigBlind && context.CurrentPot == context.SmallBlind * 3)  // we are to act on big blind
                {
                    // we are in position and opp has not raised on small blind (probably hasn't a great hand) - we should make him fold most of his hands and if he calls we must be able to defend
                    if (context.MoneyToCall == 0)
                    {
                        if (handValue >= extreme)
                        {
                            return(PlayerAction.Raise(bigBlind * 8));
                        }
                        else if (handValue >= powerful)
                        {
                            return(PlayerAction.Raise(bigBlind * 6));
                        }
                        else if (handValue >= normal)
                        {
                            return(PlayerAction.Raise(bigBlind * 4));
                        }
                        else if (handValue >= weak && bigBlind < context.MoneyLeft / (double)50) // we dont have a great hand either but we can make him sweat about it and we can always fold later
                        {
                            return(PlayerAction.Raise(bigBlind * 2));
                        }
                        else // that makes around 74% of all possible hands
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                    }
                    else // opp has raised out of position - we can three bet him TODO: check if this logic can be combined with below else
                    {
                        // opp has raised a lot - we should call him or raise only on our best cards
                        if (context.MoneyToCall >= bigBlind * 8 && context.MoneyToCall >= context.MoneyLeft / (double)25)
                        {
                            if (handValue >= extreme)
                            {
                                return(PlayerAction.Raise(context.MoneyToCall));
                            }
                            else if (handValue >= powerful)
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else // TODO: here we could open more hands if we know that our opp raises a lot on cheap hands
                            {
                                return(PlayerAction.Fold());
                            }
                        }
                        else if (context.MoneyToCall >= bigBlind * 4)
                        {
                            if (handValue >= powerful)
                            {
                                return(PlayerAction.Raise(context.MoneyToCall));
                            }
                            else if (handValue >= normal)
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else if (handValue >= weak && context.MoneyToCall < context.MoneyLeft / (double)30) // we dont have a great hand either but we can make him sweat about it and we can always fold later
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else // that makes around 74% of all possible hands
                            {
                                return(PlayerAction.Fold());
                            }
                        }
                        else // opp raised with less than 4 big blinds
                        {
                            if (handValue >= normal)
                            {
                                return(PlayerAction.Raise((int)(context.MoneyToCall * 2.5)));
                            }
                            else if (handValue >= weak && bigBlind < context.MoneyLeft / (double)30) // we dont have a great hand either but we can make him sweat about it and we can always fold later
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else if (handValue >= awful && context.MoneyToCall < bigBlind * 2) // that makes around 74% of all possible hands
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else
                            {
                                return(PlayerAction.Fold());
                            }
                        }
                    }
                }
                else // opp reraises us or we have checked on SB and he has raised
                {
                    if (handValue >= extreme)
                    {
                        return(PlayerAction.CheckOrCall());
                    }

                    // opp has raised a lot - we should call him or raise only on our best cards
                    if (context.MoneyToCall >= bigBlind * 8 && context.MoneyToCall >= context.MoneyLeft / (double)25)
                    {
                        if (handValue >= powerful)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else if (handValue >= normal && context.MyMoneyInTheRound > context.MoneyToCall * 2) // TODO: here we could open more hands if we know that our opp raises a lot on cheap hands
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(PlayerAction.Fold());
                        }
                    }
                    else if (context.MoneyToCall >= bigBlind * 4)
                    {
                        if (handValue >= normal)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else if (handValue >= weak && context.MyMoneyInTheRound > context.MoneyToCall * 2)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else // that makes around 74% of all possible hands
                        {
                            return(PlayerAction.Fold());
                        }
                    }
                    else // opp raised with less than 4 big blinds
                    {
                        if (handValue >= normal)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else if (handValue >= weak && context.MyMoneyInTheRound > context.MoneyToCall * 2)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else if (handValue >= awful && context.MoneyToCall < bigBlind * 2) // that makes around 74% of all possible hands
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(PlayerAction.Fold());
                        }
                    }
                }
            }
            #endregion

            #region Flop
            else if (context.RoundType == GameRoundType.Flop)
            {
                if (context.MoneyLeft == 0)
                {
                    return(PlayerAction.CheckOrCall());
                }

                var flopCardStrength = CardsStrengthEvaluation.RateCards
                                           (new List <Card> {
                    FirstCard, SecondCard, CommunityCards.ElementAt(0), CommunityCards.ElementAt(1), CommunityCards.ElementAt(2)
                });

                // we are first to act out of position
                if (context.MoneyToCall == 0 && !inPosition)
                {
                    if (flopCardStrength >= 4000)
                    {
                        return(PlayerAction.Raise(Math.Max(context.CurrentPot / 2, bigBlind * 4))); // we are 100% sure to win so we want to keep him in the game as long as possible
                    }
                    else if (flopCardStrength >= 3000)
                    {
                        // TODO: 3of a kind logic
                        var threeOfAKindWeHave = this.HowManyOfThreeOfAKindWeHave();
                        if (threeOfAKindWeHave == 2)
                        {
                            return(PlayerAction.Raise(Math.Max(context.CurrentPot / 2, bigBlind * 4)));
                        }
                        else
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                    }
                    if (flopCardStrength >= 2000)
                    {
                        if (!this.IsPairInCommunity())
                        {
                            return(PlayerAction.Raise(Math.Max(context.CurrentPot / 2, bigBlind * 4)));
                        }
                        else
                        {
                            if (this.HaveHighestKicker())
                            {
                                return(PlayerAction.Raise(Math.Max(context.CurrentPot / 3, bigBlind * 3)));
                            }
                            else
                            {
                                return(PlayerAction.Raise(Math.Max(context.CurrentPot / 4, bigBlind * 2)));
                            }
                        }
                    }
                    else if (flopCardStrength >= 1000)
                    {
                        var pairValue = this.GetPairValue();

                        if (pairValue == 0)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            if (this.IsHighestPair(pairValue)) // we have the highest pair possible
                            {
                                return(PlayerAction.Raise(Math.Max(context.CurrentPot / 2, bigBlind * 4)));
                            }
                            else
                            {
                                return(PlayerAction.Raise(Math.Max(context.CurrentPot / 3, bigBlind * 3)));
                            }
                        }
                    }
                    else
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                }
                else if (context.MyMoneyInTheRound == 0 && inPosition) // we are to act in position
                {
                    if (context.MoneyToCall == 0)                      // opp has checked
                    {
                        if (flopCardStrength >= 2000)
                        {
                            return(PlayerAction.Raise(Math.Max(context.CurrentPot / 2, bigBlind * 4)));
                        }
                        else if (flopCardStrength >= 1000)
                        {
                            var pairValue = this.GetPairValue();

                            if (pairValue != 0)
                            {
                                if (this.IsHighestPair(pairValue)) // we have the highest pair possible
                                {
                                    return(PlayerAction.Raise(Math.Max(context.CurrentPot, bigBlind * 8)));
                                }
                                else
                                {
                                    return(PlayerAction.Raise(Math.Max(context.CurrentPot / 2, bigBlind * 4)));
                                }
                            }
                        }

                        // we have nothing or pair is in community cards
                        if (this.HaveHighestKicker())
                        {
                            return(PlayerAction.Raise(Math.Max(context.CurrentPot / 4, bigBlind * 2)));
                        }
                        else
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                    }
                }

                // opp has raised

                // an awful lot
                if (context.MoneyToCall >= (context.CurrentPot - context.MoneyToCall) && context.MoneyToCall >= 60)
                {
                    if (flopCardStrength >= 4000)
                    {
                        return(PlayerAction.Raise(context.MoneyToCall));
                    }
                    else if (flopCardStrength >= 3000)
                    {
                        // TODO: 3of a kind logic
                        var threeOfAKindWeHave = this.HowManyOfThreeOfAKindWeHave();
                        if (threeOfAKindWeHave == 2)
                        {
                            return(PlayerAction.Raise(context.MoneyToCall));
                        }
                        else if (threeOfAKindWeHave == 1 || this.HaveHighestKicker())
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(PlayerAction.Fold());
                        }
                    }
                    if (flopCardStrength >= 2000)
                    {
                        if (!this.IsPairInCommunity())
                        {
                            return(PlayerAction.Raise(context.MoneyToCall));
                        }
                        else
                        {
                            if (this.HaveHighestKicker())
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                            else
                            {
                                return(PlayerAction.Fold());
                            }
                        }
                    }
                    else
                    {
                        return(this.Fold());
                    }
                }
                else if (context.MoneyToCall > (context.CurrentPot - context.MoneyToCall) / 2 && context.MoneyToCall >= 40) // opp has raised a reasonable amout
                {
                    if (flopCardStrength >= 4000)
                    {
                        return(PlayerAction.Raise(context.CurrentPot));
                    }
                    else if (flopCardStrength >= 3000)
                    {
                        // TODO: 3of a kind logic
                        var threeOfAKindWeHave = this.HowManyOfThreeOfAKindWeHave();
                        if (threeOfAKindWeHave == 2)
                        {
                            return(PlayerAction.Raise(context.CurrentPot));
                        }
                        else if (threeOfAKindWeHave == 1)
                        {
                            return(PlayerAction.Raise(context.CurrentPot / 2));
                        }
                        else if (this.HaveHighestKicker())
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(PlayerAction.Fold());
                        }
                    }
                    else if (flopCardStrength >= 2000)
                    {
                        if (!this.IsPairInCommunity())
                        {
                            return(PlayerAction.Raise(context.MoneyToCall));
                        }
                        else
                        {
                            var pairValue = this.GetPairValue();

                            if (this.IsHighestPair(pairValue))
                            {
                                return(PlayerAction.Raise(context.MoneyToCall));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                    }
                    else if (flopCardStrength >= 1000)
                    {
                        var pairValue = this.GetPairValue();

                        if (pairValue == 0)
                        {
                            return(this.Fold());
                        }

                        if (this.IsHighestPair(pairValue) || this.HaveHighestKicker())
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                    }

                    return(this.Fold());
                }
                else // opp has raised a little
                {
                    if (flopCardStrength >= 4000)
                    {
                        return(PlayerAction.Raise(context.MoneyToCall * 2));
                    }
                    else if (flopCardStrength >= 3000)
                    {
                        // TODO: 3of a kind logic
                        var threeOfAKindWeHave = this.HowManyOfThreeOfAKindWeHave();
                        if (threeOfAKindWeHave == 2)
                        {
                            return(PlayerAction.Raise(context.MoneyToCall * 2));
                        }
                        else if (threeOfAKindWeHave == 1)
                        {
                            return(PlayerAction.Raise(context.MoneyToCall));
                        }
                        else if (this.HaveHighestKicker())
                        {
                            return(PlayerAction.Raise(context.MoneyToCall));
                        }
                        else
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                    }
                    else if (flopCardStrength >= 2000)
                    {
                        if (!this.IsPairInCommunity())
                        {
                            return(PlayerAction.Raise(context.MoneyToCall * 2));
                        }
                        else
                        {
                            var pairValue = this.GetPairValue();

                            if (this.IsHighestPair(pairValue))
                            {
                                return(PlayerAction.Raise(context.MoneyToCall));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                    }
                    else if (flopCardStrength >= 1000)
                    {
                        var pairValue = this.GetPairValue();

                        if (pairValue == 0)
                        {
                            return(PlayerAction.CheckOrCall());
                        }

                        if (this.IsHighestPair(pairValue) || this.HaveHighestKicker())
                        {
                            return(PlayerAction.Raise(context.MoneyToCall / 2));
                        }
                    }

                    if (this.HaveHighestKicker())
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                    else
                    {
                        return(this.Fold());
                    }
                }
            }
            #endregion

            #region Turn
            else if (context.RoundType == GameRoundType.Turn || context.RoundType == GameRoundType.River)
            {
                if (context.MoneyLeft == 0)
                {
                    return(PlayerAction.CheckOrCall());
                }

                var flopCardStrength = CardsStrengthEvaluation.RateCards
                                           (new List <Card> {
                    FirstCard, SecondCard, CommunityCards.ElementAt(0), CommunityCards.ElementAt(1), CommunityCards.ElementAt(2)
                });

                var hand = new List <Card>();
                hand.Add(this.FirstCard);
                hand.Add(this.SecondCard);

                var ehs = EffectiveHandStrenghtCalculator.CalculateEHS(hand, this.CommunityCards);

                // we are first to act out of position - we should always add a little bit of pressure on our opp
                if (context.MoneyToCall == 0 && !inPosition)
                {
                    if (ehs < 0.3)
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                    if (ehs < 0.5)
                    {
                        if (this.HaveHighestKicker())
                        {
                            return(PlayerAction.Raise(context.CurrentPot / 5));
                        }
                        else
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                    }
                    else if (ehs < 0.63)
                    {
                        return(PlayerAction.Raise(context.CurrentPot / 4));
                    }
                    else if (ehs < 0.75)
                    {
                        return(PlayerAction.Raise(context.CurrentPot / 3));
                    }
                    else
                    {
                        return(PlayerAction.Raise(context.CurrentPot / 2));
                    }
                }
                else if (context.MyMoneyInTheRound == 0 && inPosition) // we are to act in position
                {
                    if (context.MoneyToCall == 0)                      // opp has checked
                    {
                        // he has nothing, but neither have we - we should try to bluff him most of the time, or atleast make him sweat for that money
                        if (ehs < 0.5)
                        {
                            // he has checked as first action previous round - he has nothing => we bluff
                            if (context.PreviousRoundActions.Where(x => x.PlayerName != this.Name).FirstOrDefault().Action == PlayerAction.CheckOrCall())
                            {
                                return(PlayerAction.Raise(context.CurrentPot)); // bluff - we are trying to make him fold
                            }

                            if (this.HaveHighestKicker())
                            {
                                return(PlayerAction.Raise(context.CurrentPot / 2)); // we are trying to make him fold
                            }
                            else
                            {
                                return(PlayerAction.Raise(context.CurrentPot / 5));
                            }
                        }
                        else if (ehs < 0.60)
                        {
                            return(PlayerAction.Raise(context.CurrentPot / 4));
                        }
                        else if (ehs < 0.70)
                        {
                            return(PlayerAction.Raise(context.CurrentPot / 2));
                        }
                        else
                        {
                            return(PlayerAction.Raise(context.CurrentPot / 3));
                        }
                    }
                }

                // opp has raised

                // an awful lot
                if (context.MoneyToCall >= (context.CurrentPot - context.MoneyToCall))
                {
                    if (ehs < 0.60)
                    {
                        return(this.Fold());
                    }
                    else if (ehs < 0.70)
                    {
                        if (context.MoneyToCall < context.MoneyLeft / 10 || context.MoneyToCall < 70)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else if (ehs < 0.85)
                    {
                        int moneyToBet = (int)(context.CurrentPot * 0.85);

                        if (context.MoneyToCall < context.MoneyLeft / 2 || context.MoneyToCall < 250)
                        {
                            if (context.MoneyToCall < moneyToBet && context.MyMoneyInTheRound == 0)
                            {
                                return(PlayerAction.Raise(moneyToBet - context.MoneyToCall + 1));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else
                    {
                        return(PlayerAction.Raise(context.MoneyToCall));
                    }
                }
                else if (context.MoneyToCall > (context.CurrentPot - context.MoneyToCall) / 2) // opp has raised a reasonable amout
                {
                    if (ehs < 0.50)
                    {
                        return(this.Fold());
                    }
                    else if (ehs < 0.60)
                    {
                        if (context.MoneyToCall < context.MoneyLeft / 10 || context.MoneyToCall < 70)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else if (ehs < 0.75)
                    {
                        int moneyToBet = (int)(context.CurrentPot * 0.75);

                        if (context.MoneyToCall < context.MoneyLeft / 2 || context.MoneyToCall < 250)
                        {
                            if (context.MoneyToCall < moneyToBet && context.MyMoneyInTheRound == 0)
                            {
                                return(PlayerAction.Raise(moneyToBet - context.MoneyToCall + 1));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else
                    {
                        return(PlayerAction.Raise(context.MoneyToCall));
                    }
                }
                else // opp has raised a little
                {
                    if (ehs < 0.40)
                    {
                        return(this.Fold());
                    }
                    else if (ehs < 0.50)
                    {
                        return(PlayerAction.CheckOrCall());
                    }
                    else if (ehs < 0.60)
                    {
                        if (context.MoneyToCall < context.MoneyLeft / 10 || context.MoneyToCall < 70)
                        {
                            return(PlayerAction.CheckOrCall());
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else if (ehs < 0.75)
                    {
                        int moneyToBet = (int)(context.CurrentPot * 0.85);

                        if (context.MoneyToCall < context.MoneyLeft / 2 || context.MoneyToCall < 250)
                        {
                            if (context.MoneyToCall < moneyToBet && context.MyMoneyInTheRound == 0)
                            {
                                return(PlayerAction.Raise(moneyToBet - context.MoneyToCall + 1));
                            }
                            else
                            {
                                return(PlayerAction.CheckOrCall());
                            }
                        }
                        else
                        {
                            return(this.Fold());
                        }
                    }
                    else
                    {
                        return(PlayerAction.Raise(context.CurrentPot / 2));
                    }
                }
            }
            #endregion

            return(PlayerAction.CheckOrCall()); // It should never reach this point
        }