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()); }
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())); }
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()); }
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); }
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)); }
private PlayerAction ToRaise(int moneyToRaise, IGetTurnExtendedContext context) { if (this.IsPush(moneyToRaise, context)) { return(this.RaiseOrAllIn(int.MaxValue, context)); } else { return(this.RaiseOrAllIn(moneyToRaise, context)); } }
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()); }
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)); } }
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)); } }
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()); }
public abstract PlayerAction OptimalAction( ICardAdapter pocket, IGetTurnExtendedContext context, IReadOnlyCollection <Card> communityCards);
public bool IsPush(int moneyToRaise, IGetTurnExtendedContext context) { return((double)(context.MoneyLeft - moneyToRaise) / (double)(moneyToRaise + context.CurrentPot) <= 0.5); }
public bool IsInPosition(IGetTurnExtendedContext context) { return(!context.Opponents.Any(x => x.InHand && x.ActionPriority > 0)); }