private List <Card> GetCards(FlopBoard flopBoard, HoldingHoles heroHoles) { return(new List <Card>() { flopBoard.Flop1, flopBoard.Flop2, flopBoard.Flop3, heroHoles.Hole1, heroHoles.Hole2 }); }
/// <summary> /// PK on a board that has at least three cards of the same suit /// </summary> /// <param name="heroHoles"></param> /// <param name="villainGrid"></param> /// <param name="fullBoard"></param> /// <param name="suit"></param> /// <returns></returns> private PkResult PkOnSuitedBoard(HoldingHoles heroHoles, PlayerRangePkGrid villainGrid, List <Card> fullBoard, SuitEnum suit) { var heroOffsuitRanks = fullBoard.Select(c => c.Rank).ToList(); heroOffsuitRanks.Add(heroHoles.Hole1.Rank); heroOffsuitRanks.Add(heroHoles.Hole2.Rank); var heroSuitedRanks = fullBoard.Where(c => c.Suit == suit).Select(c => c.Rank).ToList(); if (heroHoles.Hole1.Suit == suit) { heroSuitedRanks.Add(heroHoles.Hole1.Rank); } if (heroHoles.Hole2.Suit == suit) { heroSuitedRanks.Add(heroHoles.Hole2.Rank); } var heroOffsuitHand = _offsuitHandFinder.FindBestHand(heroOffsuitRanks); var heroSuitedHand = _suitedHandFinder.FindBestHand(heroSuitedRanks); IHand heroBestHand = heroSuitedHand == null ? heroOffsuitHand : (heroSuitedHand.CompareTo(heroOffsuitHand) > 0 ? heroSuitedHand : heroOffsuitHand); var pkResult = PkHeroHandOnSuitedBoard(heroBestHand, villainGrid, fullBoard, suit); return(pkResult); }
private PkResult PkV2(HoldingHoles heroHoles, PlayerRangePkGrid villainGrid, List <Card> fullBoard) { var pkResult = new PkResult(); SuitEnum suit; int suitedCount; var boardSuited = FullBoardHasThreeSuitedCards(fullBoard, out suit, out suitedCount); IHand bestHeroHand = boardSuited ? FindBestHand(heroHoles, fullBoard, suit) : FindBestOffsuitHand(heroHoles, fullBoard); foreach (var villainHoles in _holesEnumerator(villainGrid)) { IHand bestVillainHand = boardSuited ? FindBestHand(villainHoles, fullBoard, suit) : FindBestOffsuitHand(villainHoles, fullBoard); var pk = bestHeroHand.CompareTo(bestVillainHand); if (pk == 0) { pkResult.TiedScenariosCount++; } else if (pk < 0) { pkResult.VillainWinScenariosCount++; } else if (pk > 0) { pkResult.HeroWinScenariosCount++; } } return(pkResult); }
/// <summary> /// PK on a board which doesn't have more than two cards of any suit /// </summary> /// <param name="heroHoles"></param> /// <param name="villainGrid"></param> /// <param name="fullBoard"></param> /// <returns></returns> private PkResult PkOffsuit(HoldingHoles heroHoles, PlayerRangePkGrid villainGrid, List <Card> fullBoard) { var heroRanks = fullBoard.Select(c => c.Rank).ToList(); heroRanks.Add(heroHoles.Hole1.Rank); heroRanks.Add(heroHoles.Hole2.Rank); var heroHand = _offsuitHandFinder.FindBestHand(heroRanks); var villainRanks = fullBoard.Select(c => c.Rank).ToList(); villainRanks.Add(villainGrid.Grid.HighRank); villainRanks.Add(villainGrid.Grid.LowRank); var villainHand = _offsuitHandFinder.FindBestHand(villainRanks); var pk = heroHand.CompareTo(villainHand); if (pk > 0) { return(new PkResult(villainGrid.Grid.AvailableRankCombCount, 0, 0, 0)); } else if (pk == 0) { return(new PkResult(0, 0, villainGrid.Grid.AvailableRankCombCount, 0)); } else { return(new PkResult(0, villainGrid.Grid.AvailableRankCombCount, 0, 0)); } }
private PkResult Pk(HoldingHoles heroHoles, PlayerRangePkGrid villainGrid) { var pkResult = new PkResult(); foreach (var fiveCards in _fiveCardsEnumerator.Invoke()) { if (ConflictsWithVillainGrid(fiveCards, villainGrid.Grid)) { continue; } var conflictCards = new List <Card>(fiveCards); conflictCards.Add(heroHoles.Hole1); conflictCards.Add(heroHoles.Hole2); villainGrid.Grid.EliminateConflicts(conflictCards); var turnRiverPkResult = PkV2(heroHoles, villainGrid, fiveCards); pkResult.Add(turnRiverPkResult); } return(pkResult); }
public double CalculateEquity(HoldingHoles heroHoles, PlayerRange villainRange) { var pkStage = new PkStage(_fiveCardsEnumerator.Enumerate, Utils.EnumerateAvailableHoles); var pkResult = pkStage.Pk(heroHoles, villainRange.CloneToPkRange()); return((double)pkResult.HeroWinScenariosCount / (pkResult.HeroWinScenariosCount + pkResult.VillainWinScenariosCount + pkResult.TiedScenariosCount)); }
private IHand FindBestOffsuitHand(HoldingHoles holes, List <Card> fullBoard) { var ranks = fullBoard.Select(c => c.Rank).ToList(); ranks.Add(holes.Hole1.Rank); ranks.Add(holes.Hole2.Rank); return(_offsuitHandFinder.FindBestHand(ranks)); }
public HeadsupRiverBettingStrategy(RiverBoard riverBoard, HoldingHoles heroHoles) { _riverBoard = riverBoard; _riverFolder = new RiverFolder(); _probabilityCalculator = new VillainProbabilityCalculator( grid => _riverFolder.ShouldAGridFoldToBoardByRank(grid, _riverBoard), grid => _riverFolder.ShouldAGridFoldToBoardBySuit(grid, _riverBoard, heroHoles), () => DumbEnumerate(_riverBoard)); }
private IHand FindBestHand(HoldingHoles holes, List <Card> fullBoard, SuitEnum suit) { var bestOffsuitHand = FindBestOffsuitHand(holes, fullBoard); var bestSuitedHand = FindBestSuitedHand(holes, fullBoard, suit); return(bestSuitedHand == null ? bestOffsuitHand : (bestSuitedHand.CompareTo(bestOffsuitHand) > 0 ? bestSuitedHand : bestOffsuitHand)); }
private List <Card> GetCards(TurnBoard turnBoard, HoldingHoles heroHoles) { var flopBoard = turnBoard.FlopBoard; return(new List <Card>() { flopBoard.Flop1, flopBoard.Flop2, flopBoard.Flop3, turnBoard.TurnCard, heroHoles.Hole1, heroHoles.Hole2 }); }
private List <Card> GetCards(RiverBoard riverBoard, HoldingHoles heroHoles) { var flopBoard = riverBoard.TurnBoard.FlopBoard; var turnBoard = riverBoard.TurnBoard; return(new List <Card>() { flopBoard.Flop1, flopBoard.Flop2, flopBoard.Flop3, turnBoard.TurnCard, riverBoard.River, heroHoles.Hole1, heroHoles.Hole2 }); }
public MultiwayRiverCallingStrategy(RiverBoard riverBoard, HoldingHoles heroHoles) { _riverBoard = riverBoard; _riverFolder = new RiverFolder(); var fiveCardsEnumerator = new RiverFiveCardsEnumerator(riverBoard); _probabilityCalculator = new VillainProbabilityCalculator( grid => _riverFolder.ShouldAGridFoldToBoardByRank(grid, _riverBoard), grid => _riverFolder.ShouldAGridFoldToBoardBySuit(grid, _riverBoard, heroHoles), fiveCardsEnumerator.Enumerate); }
public TurnMultiwayCallingStrategy(TurnBoard turnBoard, HoldingHoles heroHoles) { _turnBoard = turnBoard; _turnFolder = new TurnFolder(); var fiveCardsEnumerator = new TurnFiveCardsEnumerator(turnBoard, heroHoles); _probabilityCalculator = new VillainProbabilityCalculator( grid => _turnFolder.ShouldAGridFoldToBoardByRank(grid, _turnBoard), grid => _turnFolder.ShouldAGridFoldToBoardBySuit(grid, _turnBoard, heroHoles), fiveCardsEnumerator.Enumerate); }
public FlopHeadsUpBettingStrategy(FlopBoard flopBoard, HoldingHoles heroHoles) { _flopBoard = flopBoard; _flopFolder = new FlopFolder(); var enumerator = new FlopFiveCardsEnumerator(_flopBoard, heroHoles); _probabilityCalculator = new VillainProbabilityCalculator( grid => _flopFolder.ShouldAGridFoldToBoardByRank(grid, _flopBoard), grid => _flopFolder.ShouldAGridFoldToBoardBySuit(grid, _flopBoard, heroHoles), enumerator.Enumerate); }
public bool CanBetForValue(BoardStatus boardStatus, HoldingHoles heroHoles, HoldingHoles villainHoles) { if (BettingUtils.CompareHoles(heroHoles, villainHoles, boardStatus) <= 0) { //It's not a value bet if hero's hand is worse than villain's return(false); } var heroRange = BettingUtils.GetVillainGuessOnHeroRange(); var villainEquity = _equityCalculator.CalculateEquityAgainstARange(villainHoles, heroRange, boardStatus); return(BettingUtils.VillainIsWillingToCall(villainEquity, _potOddsToBet) == true); }
/// <summary> /// Don't call this method if the board is not scary enough for bluffing /// or the position/number of alive players doesn't allow a bluffing play /// Check those condition prior to calling this method. /// </summary> /// <param name="boardStatus"></param> /// <param name="heroHoles"></param> /// <param name="villainHoles"></param> /// <returns></returns> public bool CanBluff(BoardStatus boardStatus, HoldingHoles heroHoles, HoldingHoles villainHoles) { if (BettingUtils.CompareHoles(heroHoles, villainHoles, boardStatus) > 0) { //It's not a bluff bet with a better hand than villain's return(false); } var heroRange = BettingUtils.GetVillainGuessOnHeroRange(); var villainEquity = _equityCalculator.CalculateEquityAgainstARange(villainHoles, heroRange, boardStatus); return(BettingUtils.VillainIsWillingToCall(villainEquity, _potOddsToBluff) == false); }
public PkResult Pk(HoldingHoles heroHoles, VillainPkRange villainRange) { var pkResult = new PkResult(); Parallel.ForEach(villainRange.Grids.EnumerateMultiDimensionalArray(), playerGrid => { var gridPkResult = Pk(heroHoles, playerGrid); Logger.Instance.Log($"Pk finished between heroHoles {heroHoles.Hole1.GetStringForCard() + heroHoles.Hole2.GetStringForCard()}" + $" and {playerGrid.Grid}, result is {gridPkResult}"); pkResult.Add(gridPkResult); }); return(pkResult); }
private PkResult Pk(HoldingHoles heroHoles, PlayerRangePkGrid pkGrid, List <Card> fullBoard) { SuitEnum suit; int suitedCount; if (FullBoardHasThreeSuitedCards(fullBoard, out suit, out suitedCount)) { return(PkOnSuitedBoard(heroHoles, pkGrid, fullBoard, suit)); } else { return(PkOffsuit(heroHoles, pkGrid, fullBoard)); } }
private IHand FindBestSuitedHand(HoldingHoles holes, List <Card> fullBoard, SuitEnum suit) { var suitedRanks = fullBoard.Where(c => c.Suit == suit).Select(c => c.Rank).ToList(); if (holes.Hole1.Suit == suit) { suitedRanks.Add(holes.Hole1.Rank); } if (holes.Hole2.Suit == suit) { suitedRanks.Add(holes.Hole2.Rank); } return(_suitedHandFinder.FindBestHand(suitedRanks)); }
public double CalculateEquityAgainstARange(HoldingHoles heroHoles, PlayerRange villainPlayerRange, BoardStatus boardStatus) { var villainGrids = villainPlayerRange.GetAliveGrids(); int numOfCombos = 0; double equitySum = 0; foreach (var villainGrid in villainGrids) { foreach (var villainHoles in villainGrid.Grid.EnumerateAllCombos()) { var handEquity = CalculateEquityAgainstGrid(heroHoles, villainHoles, boardStatus); equitySum += handEquity * villainGrid.Grid.PossibleCount; numOfCombos += villainGrid.Grid.PossibleCount; } } return(equitySum / numOfCombos); }
public HolesCompareResult(HoldingHoles heroHoles, HoldingHoles villainHoles, BoardStatus boardStatus) { HeroHoles = heroHoles; VillainHoles = villainHoles; HeroOuts = new List <Card>(); VillainOuts = new List <Card>(); if (boardStatus.Turn == null) { CompareOnFlop(); } else if (boardStatus.River == null) { CompareOnTurn(); } else { CompareOnRiver(); } }
public VillainProbabilityResult Calculate(HoldingHoles heroHoles, PlayerRoundProfile villainProfile, bool considerFolding = true) { var pkStage = new PkStage(_enumerate, Utils.EnumerateUnfoldedHoles); var villainRange = villainProfile.PlayerRange.CloneToPkRange(); var aliveRanges = villainRange.GetAliveGrids(); int foldCombos = 0, totalCombos = 0; foreach (var playerGrid in aliveRanges) { if (considerFolding) { SetFoldToBoard(playerGrid); foldCombos += playerGrid.FoldCombCount; } totalCombos += playerGrid.AvailableCombCount; } double villainFoldP = (double)foldCombos / totalCombos; double villainCallP = 1 - villainFoldP; var pkResult = pkStage.Pk(heroHoles, villainRange); int totalGrids = pkResult.HeroWinScenariosCount + pkResult.TiedScenariosCount + pkResult.VillainWinScenariosCount + pkResult.VillainFoldCount; double villainCallWinP = villainCallP * pkResult.VillainWinScenariosCount / totalGrids; double villainCallLoseP = villainCallP * pkResult.HeroWinScenariosCount / totalGrids; double tieP = villainCallP * pkResult.TiedScenariosCount / totalGrids; return(new VillainProbabilityResult(new Dictionary <ProbabilityEnum, double>() { { ProbabilityEnum.Fold, villainFoldP }, { ProbabilityEnum.CallWin, villainCallWinP }, { ProbabilityEnum.CallTie, tieP }, { ProbabilityEnum.CallLose, villainCallLoseP } }, villainProfile.Name)); }
public BoardHandTypeEnum DetectBoardHand(BoardStatus boardStatus, HoldingHoles holes) { var boardCards = new List <Card>() { boardStatus.Flop1, boardStatus.Flop2, boardStatus.Flop3 }; if (boardStatus.Turn != null) { boardCards.Add(boardStatus.Turn); } if (boardStatus.River != null) { boardCards.Add(boardStatus.River); } var holesCards = new List <Card>() { holes.Hole1, holes.Hole2 }; return(DetectBoardHand(boardCards, holesCards)); }
public Decision MakeDecision(PreflopStatusSummary statusSummary, HoldingHoles holes) { Logger.Instance.Log($"ChartPreflopStrategy to make decision. HeroHoles={holes.Hole1.GetStringForCard()},{holes.Hole2.GetStringForCard()}"); var raiseMoves = FilterRaiseMoves(statusSummary.PreflopRaiseMoves, p => p.Name == statusSummary.Me.Name); Logger.Instance.Log($"Filtered raise moves: {string.Join("/", raiseMoves.Select(m => m.GetStringForMove()))}"); var grid = new RangeGrid(holes); if (raiseMoves.Count == 0) { return(GetDecisionOnUnraisedPot(statusSummary, grid)); } if (raiseMoves.Count == 1) { return(GetDecisionAgainstOpenRaise(statusSummary, grid, raiseMoves[0].Player.Position)); } if (raiseMoves.Count == 2) { return(GetDecisionAgainstThreeBet(statusSummary, grid, raiseMoves[1].Player.Position)); } if (raiseMoves.Count == 3) { return(GetDecisionAgainstFourBet(statusSummary, grid, raiseMoves[2].Player.Position)); } if (raiseMoves.Count == 4) { return(GetDecisionAgainstFiveBet(statusSummary, grid, raiseMoves[3].Player.Position)); } throw new NotSupportedException(); }
public double CalculateEquityAgainstGrid(HoldingHoles heroHoles, HoldingHoles villainHoles, BoardStatus boardStatus) { var boards = boardStatus.GenerateAllPossibleBoards(new List <Card>() { heroHoles.Hole1, heroHoles.Hole2, villainHoles.Hole1, villainHoles.Hole2 }); double heroWin = 0, villainWin = 0; foreach (var board in boards) { var heroSeven = new SevenCardsHand(heroHoles.Hole1, heroHoles.Hole2, board.Flop1, board.Flop2, board.Flop3, board.Turn, board.River); var villainSeven = new SevenCardsHand(villainHoles.Hole1, villainHoles.Hole2, board.Flop1, board.Flop2, board.Flop3, board.Turn, board.River); var heroFive = BettingUtils.FindBestFive(heroSeven); var villainFive = BettingUtils.FindBestFive(villainSeven); int heroScore = BettingUtils.GetScoreForFiveCardHand(heroFive); int villainScore = BettingUtils.GetScoreForFiveCardHand(villainFive); if (heroScore > villainScore) { heroWin++; } else { villainWin++; } } return(heroWin / (heroWin + villainWin)); }
private PlayerRange SqueezeOnCheck(PlayerRange previousRange, Move lastMove, int bigBlindSize, FlopBoard flopBoard, HoldingHoles heroHoles) { return(_playerRangeSqueezer.Squeeze(previousRange, grid => TestGrid(flopBoard, grid), TestOutcomeOnCheck, GetCards(flopBoard, heroHoles))); }
public static double CompareHoles(HoldingHoles holes1, HoldingHoles holes2, BoardStatus boardStatus) { var compareResult = new HolesCompareResult(holes1, holes2, boardStatus); throw new NotImplementedException(); }
public Decision GetPreflopDecision(PreflopStatusSummary statusSummary, HoldingHoles heroHoles) { return(_preflopStrategy.MakeDecision(statusSummary, GetStartingHand(heroHoles.Hole1, heroHoles.Hole2))); }
public Dictionary <Tuple <SuitEnum, SuitEnum>, bool> ShouldAGridFoldToBoardBySuit(RangeGrid grid, FlopBoard flopBoard, HoldingHoles heroHoles) { var conflictCards = new List <Card>() { heroHoles.Hole1, heroHoles.Hole2, flopBoard.Flop1, flopBoard.Flop2, flopBoard.Flop3 }; grid.EliminateConflicts(conflictCards); switch (flopBoard.SuitTexture) { case FlopBoardSuitTextureEnum.SuitedThree: return(new SuitedThreeSuitTexture(flopBoard).ShouldAGridFoldToBet(grid)); case FlopBoardSuitTextureEnum.SuitedTwo: return(new SuitedTwoSuitTexture(flopBoard).ShouldAGridFoldToBet(grid)); case FlopBoardSuitTextureEnum.Rainbow: return(new RainbowSuitTexture().ShouldAGridFoldToBet(grid)); default: throw new InvalidOperationException(); } }
public double CalculateEquityAgainstARange(HoldingHoles heroHoles, PlayerRange villainPlayerRange, BoardSpectrum boardSpectrum) { var heroEquityAgainstVillainRange = boardSpectrum.GetEquity(heroHoles); return(heroEquityAgainstVillainRange); }