private Decision MakeCallDecision(RiverDecisionContext context) { List <VillainProbabilityResult> probabilityResults = context.AliveVillains.Select(villain => _probabilityCalculator.Calculate(context.HeroHoles, villain, Common.Utils.VillainFoldable(context.RiverRaiser, context.Hero, villain))).ToList(); List <List <ProbabilityTuple> > tupleLists = Common.Utils.EnumerateProbabilities(0, probabilityResults).ToList(); foreach (var tupleList in tupleLists) { Logger.Instance.Log($"{string.Join(";", tupleList.Select(t => $"{t.VillainName}-{t.ProbabilityCategory}-{t.Probability}"))}"); } int callSize = context.RiverRaiser.RiverBet - context.Hero.RiverBet; int potSize = context.CurrentPotSize; double ev = tupleLists.Sum(tupleList => Common.Utils.CalculateEv(tupleList, callSize, potSize)); Logger.Instance.Log($"{callSize} to call a pot of size {potSize}, ev={ev}"); if (Common.Utils.EvProfitable(ev, potSize, callSize)) { Logger.Instance.Log($"Profitable, calling"); return(new Decision(DecisionType.Call, callSize)); } Logger.Instance.Log($"Not profitable, folding"); return(new Decision(DecisionType.Fold, 0)); }
public static RiverDecisionContext GenerateRiverDecisionContext(Round round, List <PlayerRoundProfile> playerProfiles) { var hero = round.Players.First(round.IsMe); var context = new RiverDecisionContext() { BigBlindSize = round.BigBlindSize, CurrentPotSize = round.CurrentPotSize, RiverBoard = new RiverBoard(new TurnBoard(new FlopBoard(round.Flop1, round.Flop2, round.Flop3), round.Turn), round.River), Players = playerProfiles, HeroName = hero.Name, IsHeadsUp = round.Players.Count(p => p.IsAlive) == 2, HeroHoles = new HoldingHoles(round.Hole1, round.Hole2), PreflopRaiserName = round.PreflopRaiser.Name, FlopRaiserName = round.FlopMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name, TurnRaiserName = round.TurnMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name, RiverRaiserName = round.RiverMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name, IsRaised = round.RiverMoves.Any(m => m.Decision.DecisionType.IsRaiseMove()), }; if (context.IsHeadsUp) { context.HeadsUpVillainName = round.Players.First(p => p.IsAlive && !round.IsMe(p)).Name; } return(context); }
public Decision MakeDecision(RiverDecisionContext context) { List <VillainProbabilityResult> probabilityResults = context.AliveVillains.Select(villain => _probabilityCalculator.Calculate(context.HeroHoles, villain)).ToList(); List <List <ProbabilityTuple> > tupleLists = Common.Utils.EnumerateProbabilities(0, probabilityResults).ToList(); foreach (var tupleList in tupleLists) { Logger.Instance.Log($"{string.Join(";", tupleList.Select(t => $"{t.VillainName}-{t.ProbabilityCategory}-{t.Probability}"))}"); } int betSize = Common.Utils.GetBetSize(context.CurrentPotSize); int potSize = context.CurrentPotSize; double ev = tupleLists.Sum(tupleList => Common.Utils.CalculateEv(tupleList, betSize, potSize)); Logger.Instance.Log($"{betSize} to bet a pot of size {potSize}, ev={ev}"); if (Common.Utils.EvProfitable(ev, potSize, betSize)) { return(new Decision(DecisionType.Raise, betSize)); } return(new Decision(DecisionType.Check, 0)); }
public Decision MakeDecision(RiverDecisionContext context) { if (!_initialized) { Init(context); } if (context.IsHeadsUp) { if (context.IsRaised) { return(_callingStrategy.MakeDecision(context)); } else { return(_bettingStrategy.MakeDecision(context)); } } else { if (context.IsRaised) { return(_multiwayCallingStrategy.MakeDecision(context)); } else { return(_multiwayBettingStrategy.MakeDecision(context)); } } }
private void Init(RiverDecisionContext context) { _bettingStrategy = new HeadsupRiverBettingStrategy(context.RiverBoard, context.HeroHoles); _callingStrategy = new HeadsupRiverCallingStrategy(); _multiwayBettingStrategy = new MultiwayRiverBettingStrategy(context.RiverBoard, context.HeroHoles); _multiwayCallingStrategy = new MultiwayRiverCallingStrategy(context.RiverBoard, context.HeroHoles); _initialized = true; }
public Decision MakeDecision(RiverDecisionContext context) { var probabilityResult = _probabilityCalculator.Calculate(context.HeroHoles, context.HeadsUpVillain); int betSize = Common.Utils.GetBetSize(context.CurrentPotSize); int potSize = context.CurrentPotSize; var ev = probabilityResult.Probabilities[ProbabilityEnum.Fold] * potSize + probabilityResult.Probabilities[ProbabilityEnum.CallLose] * (potSize + betSize) - probabilityResult.Probabilities[ProbabilityEnum.CallWin] * betSize + probabilityResult.Probabilities[ProbabilityEnum.CallTie] * (potSize + betSize) / 2; if (Common.Utils.EvProfitable(ev, potSize, betSize)) { return(new Decision(DecisionType.Raise, betSize)); } return(new Decision(DecisionType.Check, 0)); }
private Decision MakeCallDecision(RiverDecisionContext context) { int chipsToCall = context.RiverRaiser.RiverBet - context.Hero.RiverBet; double potOdds = (double)chipsToCall / (context.CurrentPotSize + chipsToCall); var raiserRange = context.RiverRaiser.RiverRange; var equityCalculator = new EquityCalculator(new RiverFiveCardsEnumerator(context.RiverBoard)); var equity = equityCalculator.CalculateEquity(context.HeroHoles, raiserRange); Logger.Instance.Log($"Pot odds is {potOdds}, hero's equity is {equity} against raiser {context.RiverRaiser.Position}-{context.RiverRaiserName}'s range: {raiserRange.ToString()}"); if (equity <= potOdds) { Logger.Instance.Log($"Fold"); return(new Decision(DecisionType.Fold, 0)); } Logger.Instance.Log($"Call {chipsToCall} chips"); return(new Decision(DecisionType.Call, chipsToCall)); //todo: implement the reraise logic }
public Decision MakeDecision(RiverDecisionContext context) { var decision = MakeReraiseDecision(context) ?? MakeCallDecision(context); return(decision); }
private Decision MakeReraiseDecision(RiverDecisionContext context) { //todo: implement the reraise logic return(null); }