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));
        }
예제 #2
0
파일: Brain.cs 프로젝트: plutoday/TexasBot
        private PlayerRoundProfile GenerateNewProfile(Player player, PositionEnum heroPosition)
        {
            var profile = new PlayerRoundProfile()
            {
                Name         = player.Name,
                Position     = player.Position,
                PlayerStatus = PlayerStatusEnum.Unpolled,
                IsHero       = player.Position == heroPosition
            };

            if (!profile.IsHero)
            {
                profile.InPositionAgainstHero = profile.Position > heroPosition;
            }

            var range = new PlayerRange();

            range.Init(PlayerRangeGridStatusEnum.Neutral);

            profile.PlayerRange  = range;
            profile.PreflopRange = range;

            return(profile);
        }
예제 #3
0
파일: Brain.cs 프로젝트: plutoday/TexasBot
        private void UpdateProfile(PlayerRoundProfile profile, Player player, Round round, RoundSetup roundSetup)
        {
            Logger.Instance.Log($"Updating profile: name={player.Name}, position={player.Position}, stage={round.StageEnum}.");
            if (profile.PlayerStatus == PlayerStatusEnum.Folded || profile.PlayerStatus == PlayerStatusEnum.AllIned)
            {
                //Unnecessary to update
                Logger.Instance.Log($"Unnecessary to update profile: name={player.Name}, PlayerStatus={profile.PlayerStatus}, " +
                                    $"position={player.Position}, stage={round.StageEnum}.");
                return;
            }

            Logger.Instance.Log($"Before updating profile: isAlive={profile.IsAlive}, PlayerStatus={profile.PlayerStatus}, stackSize={profile.StackSize}");

            profile.StackSize = player.StackSize;

            Logger.Instance.Log($"After updating profile: isAlive={profile.IsAlive}, PlayerStatus={profile.PlayerStatus}, stackSize={profile.StackSize}");

            switch (round.StageEnum)
            {
            case StageEnum.Preflop:
                profile.PreflopDecisions    = new List <Decision>(round.PreflopMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.PreflopBet          = player.ChipsBetByStage[StageEnum.Preflop];
                profile.PreflopPlayerStatus = GetPlayerStreetStatus(profile.PreflopDecisions);
                var preflopLastRaiserName =
                    round.PreflopMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name;
                profile.IsPreflopRaiser = string.Equals(preflopLastRaiserName, profile.Name);
                break;

            case StageEnum.Flop:
                profile.FlopDecisions    = new List <Decision>(round.FlopMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.FlopBet          = player.ChipsBetByStage[StageEnum.Flop];
                profile.FlopPlayerStatus = GetPlayerStreetStatus(profile.FlopDecisions);
                var flopLastRaiserName =
                    round.FlopMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name;
                profile.IsFlopRaiser = string.Equals(flopLastRaiserName, profile.Name);
                break;

            case StageEnum.Turn:
                profile.TurnDecisions    = new List <Decision>(round.TurnMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.TurnBet          = player.ChipsBetByStage[StageEnum.Turn];
                profile.TurnPlayerStatus = GetPlayerStreetStatus(profile.TurnDecisions);
                var turnLastRaiserName =
                    round.TurnMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name;
                profile.IsTurnRaiser = string.Equals(turnLastRaiserName, profile.Name);
                break;

            case StageEnum.River:
                profile.RiverDecisions    = new List <Decision>(round.RiverMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.RiverBet          = player.ChipsBetByStage[StageEnum.River];
                profile.RiverPlayerStatus = GetPlayerStreetStatus(profile.RiverDecisions);
                var riverLastRaiserName =
                    round.RiverMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name;
                profile.IsRiverRaiser = string.Equals(riverLastRaiserName, profile.Name);
                break;
            }

            if (profile.IsHero)
            {
                //unnecessary to squeeze hero's range
                Logger.Instance.Log($"Unnecessary to update hero's profile. name={profile.Name}.");
                return;
            }

            if (round.AllMoves.Any(m => string.Equals(m.Player.Name, player.Name)))
            {
                Move lastMove = round.AllMoves.LastOrDefault(m => string.Equals(m.Player.Name, player.Name));

                if (lastMove != null && lastMove.Decision.DecisionType != DecisionType.Ante &&
                    lastMove.Decision.DecisionType != DecisionType.Fold)
                {
                    //squeeze player's range according to his last move
                    switch (lastMove.Stage)
                    {
                    case StageEnum.Preflop:
                        SqueezePreflopRange(round, profile, lastMove);
                        break;

                    case StageEnum.Flop:
                        SqueezeFlopRange(round, profile, lastMove, roundSetup);
                        break;

                    case StageEnum.Turn:
                        SqueezeTurnRange(round, profile, lastMove, roundSetup);
                        break;

                    case StageEnum.River:
                        SqueezeRiverRange(round, profile, lastMove, roundSetup);
                        break;
                    }
                }
            }
        }
예제 #4
0
 public PlayerRange GenerateInitialRange(PlayerRoundProfile profile)
 {
     return(GenerateSmallBlindInitialRange());
 }
예제 #5
0
        private void UpdateProfile(PlayerRoundProfile profile, Player player, Round round)
        {
            if (profile.IsAlive == false || profile.IsAllIn)
            {
                //Unnecessary to update
                return;
            }

            profile.IsAlive   = player.IsAlive;
            profile.IsAllIn   = player.IsAllIn;
            profile.StackSize = player.StackSize;

            switch (round.StageEnum)
            {
            case StageEnum.Preflop:
                profile.PreflopDecisions    = new List <Decision>(round.PreflopMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.PreflopBet          = player.ChipsBetByStage[StageEnum.Preflop];
                profile.PreflopPlayerStatus = GetPlayerStreetStatus(profile.PreflopDecisions);
                var preflopLastRaiserName =
                    round.PreflopMoves.Last(m => m.Decision.DecisionType.IsRaiseMove()).Player.Name;
                profile.IsPreflopRaiser = string.Equals(preflopLastRaiserName, profile.Name);
                break;

            case StageEnum.Flop:
                profile.FlopDecisions    = new List <Decision>(round.FlopMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.FlopBet          = player.ChipsBetByStage[StageEnum.Flop];
                profile.FlopPlayerStatus = GetPlayerStreetStatus(profile.FlopDecisions);
                var flopLastRaiserName =
                    round.FlopMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name;
                profile.IsFlopRaiser = string.Equals(flopLastRaiserName, profile.Name);
                break;

            case StageEnum.Turn:
                profile.TurnDecisions    = new List <Decision>(round.TurnMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.TurnBet          = player.ChipsBetByStage[StageEnum.Turn];
                profile.TurnPlayerStatus = GetPlayerStreetStatus(profile.TurnDecisions);
                var turnLastRaiserName =
                    round.TurnMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name;
                profile.IsTurnRaiser = string.Equals(turnLastRaiserName, profile.Name);
                break;

            case StageEnum.River:
                profile.RiverDecisions    = new List <Decision>(round.RiverMoves.Where(m => string.Equals(m.Player.Name, player.Name)).Select(m => m.Decision));
                profile.RiverBet          = player.ChipsBetByStage[StageEnum.River];
                profile.RiverPlayerStatus = GetPlayerStreetStatus(profile.RiverDecisions);
                var riverLastRaiserName =
                    round.RiverMoves.LastOrDefault(m => m.Decision.DecisionType.IsRaiseMove())?.Player.Name;
                profile.IsRiverRaiser = string.Equals(riverLastRaiserName, profile.Name);
                break;
            }

            if (profile.IsHero)
            {
                //unnecessary to squeeze hero's range
                return;
            }

            if (round.AllMoves.Any(m => string.Equals(m.Player.Name, player.Name)))
            {
                Move lastMove = round.AllMoves.LastOrDefault(m => string.Equals(m.Player.Name, player.Name));

                if (lastMove != null && lastMove.Decision.DecisionType != DecisionType.Ante &&
                    lastMove.Decision.DecisionType != DecisionType.Fold)
                {
                    //squeeze player's range according to his last move
                    switch (lastMove.Stage)
                    {
                    case StageEnum.Preflop:
                        SqueezePreflopRange(round, profile, lastMove);
                        break;

                    case StageEnum.Flop:
                        SqueezeFlopRange(round, profile, lastMove);
                        break;

                    case StageEnum.Turn:
                        SqueezeTurnRange(round, profile, lastMove);
                        break;

                    case StageEnum.River:
                        SqueezeRiverRange(round, profile, lastMove);
                        break;
                    }
                }
            }
        }
 /// <summary>
 /// 根據Board和Move是否match將一些Grid從PlayerRange中去掉
 /// </summary>
 /// <param name="preflopRange"></param>
 /// <param name="tester"></param>
 /// <param name="playerProfile"></param>
 public void EliminateGrids(PlayerRange preflopRange, Func <RangeGrid, BoardRangeGridStatusEnum> tester, PlayerRoundProfile playerProfile)
 {
     foreach (var playerRangeGrid in preflopRange.GetAliveGrids())
     {
         var outcome = tester(playerRangeGrid.Grid);
         if (!MoveMatchesOutcome(outcome, playerProfile))
         {
             playerRangeGrid.PlayerRangeGridStatus.RankWiseStatus = PlayerRangeGridStatusEnum.Excluded;
             //todo support suit
         }
     }
 }
예제 #7
0
파일: Utils.cs 프로젝트: plutoday/TexasBot
        /// <summary>
        /// See if villain could still possibly fold
        /// </summary>
        /// <param name="raiser"></param>
        /// <param name="hero"></param>
        /// <param name="villain"></param>
        /// <returns></returns>
        public static bool VillainFoldable(PlayerRoundProfile raiser, PlayerRoundProfile hero, PlayerRoundProfile villain)
        {
            if (!villain.IsAlive)
            {
                throw new InvalidOperationException();
            }

            if (villain.PlayerStatus == PlayerStatusEnum.AllIned)
            {
                return(false);
            }

            if (villain.Position == raiser.Position)
            {
                return(false);
            }

            PositionEnum position = raiser.Position;

            while (true)
            {
                //moving around
                position++;
                if (position == PositionEnum.Total)
                {
                    position = PositionEnum.SmallBlind;
                }

                //villain is in a later position to hero, foldable
                if (position == hero.Position)
                {
                    return(true);
                }

                //the villain is in an earlier position to hero, already called, not foldable
                if (position == villain.Position)
                {
                    return(false);
                }
            }
        }