public static GeneralGameTypeEnum ParseGameType(this GeneralGameTypeEnum value, HandHistories.Objects.GameDescription.GameType gameType)
        {
            switch (gameType)
            {
            case HandHistories.Objects.GameDescription.GameType.CapPotLimitOmaha:
            case HandHistories.Objects.GameDescription.GameType.PotLimitOmaha:
            case HandHistories.Objects.GameDescription.GameType.FiveCardPotLimitOmaha:
            case HandHistories.Objects.GameDescription.GameType.NoLimitOmaha:
            case HandHistories.Objects.GameDescription.GameType.FixedLimitOmaha:
                return(GeneralGameTypeEnum.Omaha);

            case HandHistories.Objects.GameDescription.GameType.PotLimitOmahaHiLo:
            case HandHistories.Objects.GameDescription.GameType.FiveCardPotLimitOmahaHiLo:
            case HandHistories.Objects.GameDescription.GameType.NoLimitOmahaHiLo:
            case HandHistories.Objects.GameDescription.GameType.FixedLimitOmahaHiLo:
                return(GeneralGameTypeEnum.OmahaHiLo);

            case HandHistories.Objects.GameDescription.GameType.CapNoLimitHoldem:
            case HandHistories.Objects.GameDescription.GameType.PotLimitHoldem:
            case HandHistories.Objects.GameDescription.GameType.NoLimitHoldem:
            case HandHistories.Objects.GameDescription.GameType.FixedLimitHoldem:
            case HandHistories.Objects.GameDescription.GameType.Unknown:
            case HandHistories.Objects.GameDescription.GameType.SpreadLimitHoldem:
            case HandHistories.Objects.GameDescription.GameType.Any:
            default:
                return(GeneralGameTypeEnum.Holdem);
            }
        }
Example #2
0
        public Dictionary <string, EquityData> CalculateEquity(HandHistory handHistory)
        {
            var sw = new Stopwatch();

            sw.Start();

            if (handHistory == null)
            {
                throw new ArgumentNullException(nameof(handHistory));
            }

            var result = new Dictionary <string, EquityData>();

            if (handHistory.HandActions == null)
            {
                return(result);
            }

            var equityPlayers = GetEquityPlayers(handHistory);

            var pots = BuildPots(equityPlayers);

            // if there is no pots except main pot do nothing
            if (pots.Count == 0)
            {
                return(result);
            }

            // intialize equity for all plaeyers
            equityPlayers.ForEach(p => p.Equity = new decimal[pots.Count]);

            var gameType = new GeneralGameTypeEnum().ParseGameType(handHistory.GameDescription.GameType);

            CalculatePotEquity(pots, handHistory, gameType);
            CalculatePotRakes(pots, handHistory);

            pots.ForEach(pot => CalculateEvDiff(pot, handHistory, gameType));

            result = equityPlayers.Select(x => new EquityData
            {
                Equity     = x.Equity[0],
                EVDiff     = x.EvDiff,
                PlayerName = x.Name
            }).ToDictionary(x => x.PlayerName);

            sw.Stop();

            if (sw.ElapsedMilliseconds > 5000)
            {
                LogProvider.Log.Info($"Hand #{handHistory.HandId} was processed too slow (>5s) because of EquityCalculations");
            }

            return(result);
        }
Example #3
0
        /// <summary>
        /// Calculates EV Diff for the players involved into the specified pots
        /// </summary>
        /// <param name="pot">Pots to calculate EV diff</param>
        /// <param name="handHistory">Hand history</param>
        /// <param name="gameType">Type of game</param>
        private void CalculateEvDiff(EquityPot pot, HandHistory handHistory, GeneralGameTypeEnum gameType)
        {
            if (pot.Players
                .Where(x => x.HoleCards != null)
                .Count() < 2)
            {
                return;
            }

            var pokerEvaluator = ServiceLocator.Current.GetInstance <IPokerEvaluator>(gameType.ToString());

            pokerEvaluator.SetCardsOnTable(handHistory.CommunityCards);

            pot.Players
            .Where(x => x.HoleCards != null)
            .ForEach(x => pokerEvaluator.SetPlayerCards(x.Seat, x.HoleCards));

            var winners = pokerEvaluator.GetWinners();

            if (winners.Lo == null || winners.Lo.IsNullOrEmpty())
            {
                CalculateEvDiffByPot(pot, handHistory, winners.Hi.ToList());
                return;
            }

            var splitPot = new EquityPot
            {
                Index           = pot.Index,
                Players         = pot.Players,
                PlayersPutInPot = pot.PlayersPutInPot,
                Pot             = pot.Pot / 2,
                Rake            = pot.Rake / 2,
                Street          = pot.Street
            };

            CalculateEvDiffByPot(splitPot, handHistory, winners.Hi.ToList());
            CalculateEvDiffByPot(splitPot, handHistory, winners.Lo.ToList());
        }
Example #4
0
        private void UpdatePlayersEquityWin(ReplayerTableState state)
        {
            if (state == null)
            {
                return;
            }

            //preparing for formula Card on the Board in dependence of street in current state
            switch (state.CurrentAction.Street)
            {
            case Street.Preflop:
                CurrentBoard      = new Card[] { };
                CurrentBoardCards = string.Empty;
                break;

            case Street.Flop:
                CurrentBoard      = CurrentGame.CommunityCards.Take(3).ToArray();
                CurrentBoardCards = new string(CurrentGame.CommunityCardsString.Take(6).ToArray());
                break;

            case Street.Turn:
                CurrentBoard      = CurrentGame.CommunityCards.Take(4).ToArray();
                CurrentBoardCards = new string(CurrentGame.CommunityCardsString.Take(8).ToArray());
                break;

            case Street.River:
                CurrentBoard      = CurrentGame.CommunityCards.ToArray();
                CurrentBoardCards = CurrentGame.CommunityCardsString;
                break;

            case Street.Showdown:
                CurrentBoard      = CurrentGame.CommunityCards.ToArray();
                CurrentBoardCards = CurrentGame.CommunityCardsString;
                break;

            case Street.Summary:
                CurrentBoard      = CurrentGame.CommunityCards.ToArray();
                CurrentBoardCards = CurrentGame.CommunityCardsString;
                break;
            }

            // finding all players having hole cards
            ActivePlayerHasHoleCard = CurrentGame.Players.Where(pl => pl.hasHoleCards).ToList();

            // searching for dead cards and removing this player from list of ActivePlayerHasHoleCard
            ActivePlayerHasHoleCardFolded = new List <Player>();

            AllDeadCards.Clear();

            foreach (ReplayerTableState replayerTableState in TableStateList)
            {
                Player playerInTableState = CurrentGame.Players.FirstOrDefault(x => x.PlayerName == replayerTableState.CurrentAction.PlayerName);

                if (playerInTableState != null &&
                    TableStateList.IndexOf(replayerTableState) <= TableStateList.IndexOf(state) &&
                    replayerTableState.CurrentAction.IsFold &&
                    playerInTableState.hasHoleCards)
                {
                    ActivePlayerHasHoleCardFolded.Add(playerInTableState);
                    ActivePlayerHasHoleCard.Remove(playerInTableState);
                    AllDeadCards.Add(playerInTableState.HoleCards);
                    AllDeadCardsString += playerInTableState.Cards;
                }
            }

            var equitySolver = ServiceLocator.Current.GetInstance <IEquitySolver>();

            var gameType = new GeneralGameTypeEnum().ParseGameType(CurrentGame.GameDescription.GameType);

            var isShortDeck = CurrentGame.GameDescription.TableTypeDescriptors.Contains(HandHistories.Objects.GameDescription.TableTypeDescription.ShortDeck);

            var equitySolverParams = new EquitySolverParams
            {
                PlayersCards = ActivePlayerHasHoleCard.Select(x => x.HoleCards).ToArray(),
                BoardCards   = CurrentBoard,
                Dead         = isShortDeck ?
                               AllDeadCards
                               .Distinct(new LambdaComparer <HoleCards>((x, y) => x.ToString().Equals(y.ToString())))
                               .SelectMany(x => x)
                               .Concat(CardGroup.GetDeadCardsForHoldem6Plus())
                               .ToArray() :
                               AllDeadCards
                               .Distinct(new LambdaComparer <HoleCards>((x, y) => x.ToString().Equals(y.ToString())))
                               .SelectMany(x => x)
                               .ToArray(),
                GameType = gameType
            };

            var equities = equitySolver.CalculateEquity(equitySolverParams)
                           .Select(x => Math.Round((decimal)x.Equity * 100, 2))
                           .ToArray();

            // updating states in replayer view
            if (equities != null)
            {
                RefreshBoard(equities, state.CurrentStreet);
            }

            //case of last state. Needed for All-in before River for some cases
            if (TableStateList.IndexOf(state) + 1 == TableStateList.Count &&
                equities != null)
            {
                // updating states in replayer view
                RefreshBoard(equities, Street.Preflop);
            }
        }
Example #5
0
        private void CalculateEquity(List <EquityPlayer> players, Street street, BoardCards boardCards, HandHistories.Objects.Cards.Card[] dead, GeneralGameTypeEnum gameType, int potIndex)
        {
            var equitySolverParams = new EquitySolverParams
            {
                PlayersCards = players.Select(x => x.HoleCards).ToArray(),
                BoardCards   = boardCards.ToArray(),
                Dead         = dead,
                GameType     = gameType
            };

            var equity = CalculateEquity(equitySolverParams);

            for (var i = 0; i < players.Count; i++)
            {
                players[i].Equity[potIndex] = (decimal)equity[i].Equity;
            }
        }
Example #6
0
        /// <summary>
        /// Calculates equity for the specified player if possible
        /// </summary>
        /// <param name="equityPlayers">Players to calculate equity</param>
        /// <param name="handHistory">Hand history</param>
        private void CalculateEquity(List <EquityPlayer> equityPlayers, List <EquityPlayer> mainPotPlayers, HandHistory handHistory, GeneralGameTypeEnum gameType, int potIndex)
        {
            var playersByName = handHistory.Players
                                .GroupBy(x => x.PlayerName)
                                .ToDictionary(x => x.Key, x => x.FirstOrDefault());

            // equity can be calculated only for player who didn't fold, whose last action was before river, whose hole cards are known
            var eligibleEquityPlayers = equityPlayers
                                        .Where(x => x.LastAction.Street != Street.River &&
                                               !x.LastAction.IsFold &&
                                               playersByName.ContainsKey(x.Name) && playersByName[x.Name].hasHoleCards)
                                        .ToList();

            // equity can't be calculated for single player
            if (eligibleEquityPlayers.Count < 2)
            {
                return;
            }

            // set known hole cards
            eligibleEquityPlayers.ForEach(p => p.HoleCards = playersByName[p.Name].HoleCards);

            try
            {
                var street = eligibleEquityPlayers.Select(x => x.LastAction.Street).Distinct().Max();

                var boardCards = CardHelper.IsStreetAvailable(handHistory.CommunityCards.ToString(), street)
                     ? handHistory.CommunityCards.GetBoardOnStreet(street)
                     : handHistory.CommunityCards;

                var deadCards = mainPotPlayers.Except(equityPlayers).Where(x => x.HoleCards != null).SelectMany(x => x.HoleCards).ToArray();

                if (handHistory.GameDescription.TableType.Contains(HandHistories.Objects.GameDescription.TableTypeDescription.ShortDeck))
                {
                    deadCards = deadCards.Concat(CardGroup.GetDeadCardsForHoldem6Plus()).ToArray();
                }

                if (pokerEvalLibLoaded)
                {
                    CalculateEquity(eligibleEquityPlayers, street, boardCards, deadCards, gameType, potIndex);
                }
                else if (gameType == GeneralGameTypeEnum.Holdem)
                {
                    CalculateHoldemEquity(eligibleEquityPlayers, street, boardCards, deadCards, potIndex);
                }
                else
                {
                    CalculateOmahaEquity(eligibleEquityPlayers, street, boardCards, gameType == GeneralGameTypeEnum.OmahaHiLo, potIndex);
                }
            }
            catch (Exception e)
            {
                LogProvider.Log.Error(this, $"Could not calculate equity for hand #{handHistory.HandId}", e);
            }
        }
Example #7
0
        private void CalculatePotEquity(List <EquityPot> pots, HandHistory handHistory, GeneralGameTypeEnum gameType)
        {
            var mainPotPlayers = pots[0].Players;

            for (var potIndex = 0; potIndex < pots.Count; potIndex++)
            {
                CalculateEquity(pots[potIndex].Players, mainPotPlayers, handHistory, gameType, potIndex);
            }
        }