private PlayerAction ReactionCausedByWeakHand(IGetTurnExtendedContext context, PlayerEconomy playerEconomy)
        {
            var investment = (int)playerEconomy.OptimalInvestment(context.CurrentPot);

            if (investment < context.MoneyToCall)
            {
                return(PlayerAction.Fold());
            }

            if (context.CanRaise)
            {
                if (investment >= context.MoneyToCall + context.MinRaise)
                {
                    if (context.CurrentPot * LowerWagerLimit <= investment && this.NeedAnRaiseToAdjustTheStats(context))
                    {
                        if (this.IsPush(investment - context.MoneyToCall, context))
                        {
                            // it's a very losing action
                            // return this.RaiseOrAllIn(int.MaxValue, context);
                        }
                        else
                        {
                            return(this.RaiseOrAllIn(investment - context.MoneyToCall, context));
                        }
                    }
                }
            }

            return(PlayerAction.CheckOrCall());
        }
        private PlayerAction ReactionCausedByBestHand(IGetTurnExtendedContext context, PlayerEconomy playerEconomy)
        {
            if (playerEconomy.TiedHandsWithHero > 0)
            {
                if (context.CanRaise && playerEconomy.HandsThatLoseToTheHero.Count > 0)
                {
                    if (this.NeedAnRaiseToAdjustTheStats(context))
                    {
                        return(this.ToValueBet(context, playerEconomy));
                    }
                }
            }
            else
            {
                if (context.CanRaise)
                {
                    if (this.NeedAnRaiseToAdjustTheStats(context))
                    {
                        return(this.ToValueBet(context, playerEconomy));
                    }
                }
            }

            return(PlayerAction.CheckOrCall());
        }
Пример #3
0
        private ICalculator Calculator(
            ICardAdapter pocket, IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards)
        {
            var holeCardsOfOpponentsWhoAreInHand = new List <ICardAdapter>();

            holeCardsOfOpponentsWhoAreInHand.Add(pocket);
            var deadCards = new List <Card>();

            foreach (var item in context.Opponents)
            {
                if (item.InHand)
                {
                    holeCardsOfOpponentsWhoAreInHand.Add(new Pocket(item.HoleCards));
                }
                else
                {
                    deadCards.AddRange(item.HoleCards);
                }
            }

            return(new Calculator(
                       holeCardsOfOpponentsWhoAreInHand,
                       deadCards,
                       communityCards.ToList()));
        }
Пример #4
0
        private PlayerAction ReactionToOpenRaiseOpportunity(IGetTurnExtendedContext context, StartingHand startingHand)
        {
            var currentPosition = context.CurrentStats.RFI.CurrentPosition;

            if (context.CurrentStats.RFI.IndicatorByPositions[currentPosition.Value].IsOpportunitiesToOpenThePot)
            {
                if (startingHand.IsPlayablePocket(
                        this.PlayingStyle.RFI.IndicatorByPositions[currentPosition.Value].Percentage
                        * this.rfiCorrection.CorrectionFactor(context.CurrentStats, context.RoundType)))
                {
                    return(this.ToRaise(context.MinRaise * 2, context));
                }
            }
            else if (startingHand.IsPlayablePocket(
                         this.PlayingStyle.PFR.Percentage * this.pfrCorrection.CorrectionFactor(context.CurrentStats, context.RoundType)))
            {
                if (context.CanRaise)
                {
                    var overWager = this.OverWager(context);
                    return(this.ToRaise((context.MinRaise * 2) + overWager, context));
                }
            }
            else if (startingHand.IsPlayablePocket(
                         this.PlayingStyle.VPIP.Percentage * this.vpipCorrection.CorrectionFactor(context.CurrentStats, context.RoundType)))
            {
                return(PlayerAction.CheckOrCall());
            }

            return(PlayerAction.Fold());
        }
Пример #5
0
        private int OverWager(IGetTurnExtendedContext context)
        {
            var beforeTheRaiser = context.PreviousRoundActions.Reverse().TakeWhile(p => p.Action.Type != PlayerActionType.Raise);
            var callers         = beforeTheRaiser.Count(p => p.Action.Type == PlayerActionType.CheckCall);

            return(callers * context.MoneyToCall);
        }
Пример #6
0
        public PlayerEconomy PlayerEconomy(
            ICardAdapter pocket, IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards)
        {
            var calculator  = this.Calculator(pocket, context, communityCards);
            var handEconomy = new HandEconomy(calculator);

            return(handEconomy.First(p => p.Hero.Pocket.Mask == pocket.Mask));
        }
Пример #7
0
 private PlayerAction ToRaise(int moneyToRaise, IGetTurnExtendedContext context)
 {
     if (this.IsPush(moneyToRaise, context))
     {
         return(this.RaiseOrAllIn(int.MaxValue, context));
     }
     else
     {
         return(this.RaiseOrAllIn(moneyToRaise, context));
     }
 }
Пример #8
0
 public PlayerAction RaiseOrAllIn(int moneyToRaise, IGetTurnExtendedContext context)
 {
     if (moneyToRaise >= context.MoneyLeft - context.MoneyToCall)
     {
         // All-In
         return(PlayerAction.Raise(context.MoneyLeft - context.MoneyToCall));
     }
     else
     {
         return(PlayerAction.Raise(moneyToRaise));
     }
 }
        private PlayerAction ReactionCausedByNutHand(IGetTurnExtendedContext context, PlayerEconomy playerEconomy)
        {
            if (context.CanRaise)
            {
                if (this.NeedAnRaiseToAdjustTheStats(context))
                {
                    return(this.ToValueBet(context, playerEconomy));
                }
            }

            return(PlayerAction.CheckOrCall());
        }
Пример #10
0
        private PlayerAction ReactionToFourBetOpportunity(
            IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards, StartingHand startingHand)
        {
            if (startingHand.IsPlayablePocket(
                    this.PlayingStyle.FourBet.IndicatorByStreets[GameRoundType.PreFlop].Percentage
                    * this.fourBetCorrection.CorrectionFactor(context.CurrentStats, context.RoundType)))
            {
                if (context.CanRaise)
                {
                    if ((double)context.MoneyToCall / (double)context.CurrentPot >= 0.6)
                    {
                        // opponent bet too much
                        // return this.ReactionToAHugeBetFromTheOpponent(context, communityCards, startingHand); Too expensive method.

                        var overWager = this.OverWager(context);
                        return(this.ToRaise((context.MinRaise * 3) + overWager, context));
                    }
                    else
                    {
                        var overWager = this.OverWager(context);
                        return(this.ToRaise((context.MinRaise * 3) + overWager, context));
                    }
                }
                else
                {
                    return(PlayerAction.CheckOrCall());
                }
            }
            else if (startingHand.IsPlayablePocket(this.PlayingStyle.ThreeBet.IndicatorByStreets[GameRoundType.PreFlop].Percentage))
            {
                if ((double)context.MoneyToCall / (double)context.CurrentPot >= 0.6)
                {
                    //var reaction = this.ReactionToAHugeBetFromTheOpponent(context, communityCards, startingHand);
                    //if (reaction.Type != PlayerActionType.Fold)
                    //{
                    //    return PlayerAction.CheckOrCall();
                    //}

                    return(PlayerAction.CheckOrCall());
                }
                else
                {
                    return(PlayerAction.CheckOrCall());
                }
            }

            return(PlayerAction.Fold());
        }
        public override PlayerAction OptimalAction(
            ICardAdapter pocket, IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards)
        {
            var playerEconomy = this.PlayerEconomy(pocket, context, communityCards);

            if (playerEconomy.NutHand)
            {
                return(this.ReactionCausedByNutHand(context, playerEconomy));
            }
            else if (playerEconomy.BestHand)
            {
                return(this.ReactionCausedByBestHand(context, playerEconomy));
            }
            else
            {
                return(this.ReactionCausedByWeakHand(context, playerEconomy));
            }
        }
        private bool NeedAnRaiseToAdjustTheStats(IGetTurnExtendedContext context)
        {
            if (context.CurrentStats.CBet.IndicatorByStreets[context.RoundType].IsOpportunity)
            {
                if (context.CurrentStats.CBet.IndicatorByStreets[context.RoundType].Percentage
                    < this.PlayingStyle.CBet.IndicatorByStreets[context.RoundType].Percentage)
                {
                    return(true);
                }
            }

            if (context.CurrentStats.AFq.IndicatorByStreets[context.RoundType].Percentage
                < this.PlayingStyle.AFq.IndicatorByStreets[context.RoundType].Percentage)
            {
                // adjust the current stats of AFq to match the style of the player's game
                return(true);
            }

            return(false);
        }
        private PlayerAction ToValueBet(IGetTurnExtendedContext context, PlayerEconomy playerEconomy)
        {
            double lowerLimit, upperLimit;

            if (playerEconomy.NutHand)
            {
                lowerLimit = LowerWagerLimit;
                upperLimit = 0.75;
            }
            else if (playerEconomy.BestHand)
            {
                lowerLimit = 0.5;
                upperLimit = 1.25;
            }
            else
            {
                lowerLimit = LowerWagerLimit;
                upperLimit = 1.25;
            }

            var min        = (int)(context.CurrentPot * lowerLimit) - context.MoneyToCall;
            var max        = (int)((context.CurrentPot + 1) * upperLimit) - context.MoneyToCall;
            var difference = max - min;

            min = min >= context.MinRaise ? min : context.MinRaise;
            max = max > min ? max : min + difference;

            var moneyToRaise = RandomProvider.Next(min, max);

            if (this.IsPush(moneyToRaise, context))
            {
                return(this.RaiseOrAllIn(int.MaxValue, context));
            }
            else
            {
                return(this.RaiseOrAllIn(moneyToRaise, context));
            }
        }
Пример #14
0
        public override PlayerAction OptimalAction(
            ICardAdapter pocket, IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards)
        {
            var startingHand = new StartingHand(pocket);

            if (context.CurrentStats.FourBet.IndicatorByStreets[context.RoundType].IsOpportunity)
            {
                return(this.ReactionToFourBetOpportunity(context, communityCards, startingHand));
            }
            else if (context.CurrentStats.ThreeBet.IndicatorByStreets[context.RoundType].IsOpportunity)
            {
                return(this.ReactionToThreeBetOpportunity(context, communityCards, startingHand));
            }
            else if (context.PreviousRoundActions.Count(x => x.Action.Type == PlayerActionType.Raise) == 0)
            {
                return(this.ReactionToOpenRaiseOpportunity(context, startingHand));
            }
            else
            {
                // faced with four bet and more
                return(this.ReactionToFourBetOpportunity(context, communityCards, startingHand));
            }
        }
Пример #15
0
        private PlayerAction ReactionToAHugeBetFromTheOpponent(
            IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards, StartingHand startingHand)
        {
            var playerEconomy = this.PlayerEconomy(startingHand.Pocket, context, communityCards);
            var investment    = (int)playerEconomy.NeutralEVInvestment(context.CurrentPot);

            if (playerEconomy.BestHand)
            {
                if (!this.IsInPosition(context) || context.Opponents.Where(p => p.InHand).Count() > 1)
                {
                    var overWager = this.OverWager(context);
                    return(this.ToRaise((context.MinRaise * 3) + overWager, context));
                }
                else
                {
                    return(PlayerAction.CheckOrCall());
                }
            }
            else if (investment >= context.MoneyToCall)
            {
                if (context.CanRaise)
                {
                    if (investment >= context.MoneyToCall + context.MinRaise)
                    {
                        return(this.ToRaise(investment - context.MoneyToCall, context));
                    }
                }

                return(PlayerAction.CheckOrCall());
            }
            else if (startingHand.IsPremiumHand)
            {
                return(PlayerAction.CheckOrCall());
            }

            return(PlayerAction.Fold());
        }
Пример #16
0
 public abstract PlayerAction OptimalAction(
     ICardAdapter pocket, IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards);
Пример #17
0
 public bool IsPush(int moneyToRaise, IGetTurnExtendedContext context)
 {
     return((double)(context.MoneyLeft - moneyToRaise) / (double)(moneyToRaise + context.CurrentPot) <= 0.5);
 }
Пример #18
0
 public bool IsInPosition(IGetTurnExtendedContext context)
 {
     return(!context.Opponents.Any(x => x.InHand && x.ActionPriority > 0));
 }