예제 #1
0
        static void Main(string[] args)
        {
            var dataProvider = new DataProvider();
            var comparer     = new HandComparer();
            var calculator   = new RankCalculator();

            if (args.Length > 0)
            {
                if (File.Exists(args[0]))
                {
                    dataProvider.InputFile = args[0];
                }
                else
                {
                    Console.WriteLine("ERROR: File does not exist. This application takes a single parameter of an input text file.");
                    return;
                }
            }
            else
            {
                var tempPath = dataProvider.GetApplicationRoot();
                dataProvider.InputFile = tempPath + @"\\AppData\\testData.txt";
            }

            var showdownApp = new ShowDownApp(dataProvider, calculator, comparer);

            showdownApp.Run();
        }
예제 #2
0
        public void QuickCalculate(WinEquity equity, List <Hand> hands, Hand table, int needToOpen, int calculationCount = 1000)
        {
            var         startPosition = 5 - needToOpen;
            Queue <int> cardIdQueue   = new Queue <int>();
            Random      rand          = new Random();

            for (int i = 0; i < calculationCount; i++)
            {
                for (int j = 0; j < needToOpen; j++)
                {
                    int nmb;
                    do
                    {
                        nmb = rand.Next(0, _cards.Count);
                    }while (cardIdQueue.Contains(nmb));
                    cardIdQueue.Enqueue(nmb);
                }

                for (int j = startPosition; j < 5; j++)
                {
                    table.Cards[j].Edit(_cards[cardIdQueue.Dequeue()]);
                }

                var result = HandComparer.CompareFullHands(hands.Select(p => p.Copy()).ToList(), table);
                equity.ProcessResult(result);
            }
        }
예제 #3
0
        public void NotAllowEmptyPokerHandList()
        {
            HandComparer sut = new HandComparer();
            //empty list
            var list = new List <PokerHandDto>();

            Assert.Throws <ArgumentException>(() => sut.GetWinningHand(list));
        }
예제 #4
0
파일: Poker.cs 프로젝트: stefc/exercism.io
 private static Option <Hands> GetResult(this IEnumerable <Separation> matches, HandComparer comparer)
 => matches.Any() ? Some <Hands>(matches
                                 .GroupBy(match => match.SameRank, comparer)
                                 .OrderBy(grp => grp.Key, comparer).FirstOrDefault()
                                 .GroupBy(match => match.Kickers, comparer)
                                 .OrderBy(grp => grp.Key, comparer).FirstOrDefault()
                                 .Select(match => match.Origin)
                                 .ToArray())
         : None;
예제 #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PokerHandsService"/> class.
 /// </summary>
 /// <param name="pokerHandsRepository">The poker hands repository.</param>
 /// <param name="mapper">The mapper.</param>
 /// <exception cref="ArgumentNullException">pokerHandsRepository</exception>
 /// <exception cref="ArgumentNullException">mapper</exception>
 public PokerHandsService(IPokerHandsRepository pokerHandsRepository,
                          IMapper mapper)
 {
     _pokerHandsRepository = pokerHandsRepository ??
                             throw new ArgumentNullException(nameof(pokerHandsRepository));
     _mapper = mapper ??
               throw new ArgumentNullException(nameof(mapper));
     _handTypeCalculator = new HandTypeCalculator();
     _handComparer       = new HandComparer();
 }
예제 #6
0
        static void Main(string[] args)
        {
            var table = new Hand(0);
            //.AddCard(new Card(CardValues.Two, CardSuits.Diamonds))
            //.AddCard(new Card(CardValues.Seven, CardSuits.Clubs))
            //.AddCard(new Card(CardValues.Four, CardSuits.Diamonds))
            //.AddCard(new Card(CardValues.Ace, CardSuits.Diamonds))
            //.AddCard(new Card(CardValues.Two, CardSuits.Hearts));

            var firstHand = new Hand(1)
                            .AddCard(new Card(CardValues.Six, CardSuits.Diamonds))
                            .AddCard(new Card(CardValues.Six, CardSuits.Spades));

            var secondHand = new Hand(2)
                             .AddCard(new Card(CardValues.Eight, CardSuits.Diamonds))
                             .AddCard(new Card(CardValues.Queen, CardSuits.Spades));

            var hands = new List <Hand>
            {
                firstHand,
                secondHand
            };

            #region timer
            //var timer = new Stopwatch();
            //timer.Start();
            #endregion

            for (int i = 0; i <= 10; i++)
            {
                var equity = HandComparer.GetWinEquity(hands.Copy(), table.Copy(), i != 10);

                #region timer
                //timer.Stop();
                #endregion

                foreach (var player in equity.Win)
                {
                    Console.WriteLine($"Player #{player.PlayerId} : {Math.Round((double)player.Wins / equity.Count * 100, 1)}%  [{player.Wins} out(s)]");
                }
                Console.WriteLine($"Draw      : {Math.Round((double)equity.Draw / equity.Count * 100, 1)}%   [{equity.Count - equity.Win.Select(p => p.Wins).Sum()} out(s)]");
                Console.WriteLine($"Total count : {equity.Count}");

                Console.WriteLine($"{Environment.NewLine}----------------------------------------------------------------{Environment.NewLine}");
            }

            #region timer
            //Console.WriteLine($"{Environment.NewLine}Calculation takes {timer.ElapsedMilliseconds} ms.");
            #endregion

            Console.ReadKey();
        }
예제 #7
0
        public void GetWinningHand_SingleHand_PhilWins()
        {
            var testHandCalc = new HandComparer();
            var testPokHand1 = CreateTestPokerHandDto("Phil Hellmuth", "Straight Flush", "AH", "KH", "10H", "JH", "QH");

            string expectedWinnerName = "Phil Hellmuth";

            var pokerHandReturned = testHandCalc.GetWinningHand(new List <PokerHandDto> {
                testPokHand1
            });

            Assert.Single(pokerHandReturned);
            Assert.Equal(expectedWinnerName, pokerHandReturned.FirstOrDefault().PlayerName);
        }
예제 #8
0
        public void GetWinningHand_BoatVsBoat_PhilWins()
        {
            var testHandCalc = new HandComparer();
            var testPokHand1 = CreateTestPokerHandDto("Daniel Negranu", "Full House", "2D", "7H", "2H", "7D", "2D");
            var testPokHand2 = CreateTestPokerHandDto("Phil Hellmuth", "Full House", "KS", "9C", "KD", "9D", "KC");

            string expectedWinnerName1 = "Phil Hellmuth";

            var pokerHandReturned = testHandCalc.GetWinningHand(new List <PokerHandDto> {
                testPokHand1, testPokHand2
            });

            Assert.Single(pokerHandReturned);
            Assert.Equal(expectedWinnerName1, pokerHandReturned[0].PlayerName);
        }
예제 #9
0
        public void GetWinningHand_StraightFlushVsStraighFlushVsStraightFlushDifferent_PhilWins()
        {
            var testHandCalc = new HandComparer();
            var testPokHand1 = CreateTestPokerHandDto("Daniel Negranu", "Straight Flush", "2H", "6H", "3H", "4H", "5H");
            var testPokHand2 = CreateTestPokerHandDto("Phil Hellmuth", "Straight Flush", "AH", "KH", "10H", "JH", "QH");
            var testPokHand3 = CreateTestPokerHandDto("Tony G", "Straight Flush", "8D", "6D", "7D", "9D", "10D");

            string expectedWinnerName = "Phil Hellmuth";

            var pokerHandReturned = testHandCalc.GetWinningHand(new List <PokerHandDto> {
                testPokHand1, testPokHand2, testPokHand3
            });

            Assert.Single(pokerHandReturned);
            Assert.Equal(expectedWinnerName, pokerHandReturned.FirstOrDefault().PlayerName);
        }
예제 #10
0
        public void GetWinningHand_TwoPairVsTwoPairVsTwoPair_PhilWins()
        {
            var testHandCalc = new HandComparer();
            var testPokHand1 = CreateTestPokerHandDto("Tony G", "Two Pair", "2D", "7H", "2H", "7D", "5D");
            var testPokHand2 = CreateTestPokerHandDto("Phil Hellmuth", "Two Pair", "KD", "KH", "JH", "AC", "AH");
            var testPokHand3 = CreateTestPokerHandDto("Daniel Negranu", "Two Pair", "AD", "KS", "KC", "10D", "AC");

            string expectedWinnerName1 = "Phil Hellmuth";

            var pokerHandReturned = testHandCalc.GetWinningHand(new List <PokerHandDto> {
                testPokHand1, testPokHand2
            });

            Assert.Single(pokerHandReturned);
            Assert.Equal(expectedWinnerName1, pokerHandReturned[0].PlayerName);
        }
예제 #11
0
        public void GetWinningHand_HighCardVsHighCardVsHighCard_TonyWins()
        {
            var testHandCalc = new HandComparer();
            var testPokHand1 = CreateTestPokerHandDto("Daniel Negranu", "High Card", "2D", "7H", "6H", "QS", "4H");
            var testPokHand2 = CreateTestPokerHandDto("Phil Hellmuth", "High Card", "2S", "7C", "6S", "QD", "4C");
            var testPokHand3 = CreateTestPokerHandDto("Tony G", "High Card", "3H", "7D", "6D", "QC", "4S");


            string expectedWinnerName1 = "Tony G";

            var pokerHandReturned = testHandCalc.GetWinningHand(new List <PokerHandDto> {
                testPokHand1, testPokHand2, testPokHand3
            });

            Assert.Single(pokerHandReturned);
            Assert.Equal(expectedWinnerName1, pokerHandReturned.FirstOrDefault().PlayerName);
        }
예제 #12
0
        public void GetWinningHand_HighCardVsHighCardVsHighCard_TwoWayChopPhilAndTony()
        {
            var testHandCalc = new HandComparer();
            var testPokHand1 = CreateTestPokerHandDto("Daniel Negranu", "High Card", "2D", "7H", "6H", "10D", "4H");
            var testPokHand2 = CreateTestPokerHandDto("Phil Hellmuth", "High Card", "2S", "7C", "6S", "QD", "4C");
            var testPokHand3 = CreateTestPokerHandDto("Tony G", "High Card", "2H", "7D", "6D", "QC", "4S");

            string expectedWinnerName1 = "Phil Hellmuth";
            string expectedWinnerName2 = "Tony G";

            var pokerHandReturned = testHandCalc.GetWinningHand(new List <PokerHandDto> {
                testPokHand1, testPokHand2, testPokHand3
            });

            Assert.Equal(2, pokerHandReturned.Count());
            Assert.Equal(expectedWinnerName1, pokerHandReturned[0].PlayerName);
            Assert.Equal(expectedWinnerName2, pokerHandReturned[1].PlayerName);
        }
예제 #13
0
        public void Interate(WinEquity equity, List <Hand> hands, Hand table, int needToOpen, int current = 0, int startCard = 0)
        {
            var currentPosition = 5 - needToOpen + current;

            foreach (var card in GetCards(currentPosition, startCard))
            {
                table.Cards[currentPosition].Edit(card);

                if (needToOpen == current + 1)
                {
                    var result = HandComparer.CompareFullHands(hands.Select(p => p.Copy()).ToList(), table);
                    equity.ProcessResult(result);
                }
                else
                {
                    Interate(equity, hands, table, needToOpen, current + 1, card.Position + 1);
                }
            }
        }
예제 #14
0
        public void WhenHighCardThenHigherWins()
        {
            var handComparer = new HandComparer();

            int result = handComparer.Compare(
                new [] { "2C", "AC", "1C", "3C", "KC" },
                new [] { "2C", "KC", "1C", "3C", "QC" });

            Assert.AreEqual(1, result);


            result = handComparer.Compare(
                new[] { "1C", "2C", "6C", "4C", "5C" },
                new[] { "7H", "1H", "2H", "3H", "4H" });
            Assert.AreEqual(-1, result);

            result = handComparer.Compare(
                new[] { "1C", "2C", "3C", "4C", "7C" },
                new[] { "7H", "1H", "2H", "3H", "4H" });
            Assert.AreEqual(0, result);
        }
예제 #15
0
        public void WhenPairThenHigherWins()
        {
            var handComparer = new HandComparer();

            int result = handComparer.Compare(
                new[] { "2C", "AC", "1C", "3C", "KC" },
                new[] { "2H", "2S", "1H", "3H", "QH" });

            Assert.AreEqual(-1, result);


            result = handComparer.Compare(
                new[] { "2C", "2D", "6C", "4C", "5C" },
                new[] { "TH", "TS", "2H", "3H", "4H" });
            Assert.AreEqual(-1, result);

            result = handComparer.Compare(
                new[] { "AC", "AD", "3C", "4C", "7C" },
                new[] { "AH", "AS", "2H", "3H", "4H" });
            Assert.AreEqual(1, result);
        }
예제 #16
0
        private void showDown(Player smallBlindPlayer, Player bigBlindPlayer, PlayedHandEntity playedHand)
        {
            HandComparison comparison = HandComparer.Compare(smallBlindPlayer.HoleCards, bigBlindPlayer.HoleCards, Board);

            switch (comparison)
            {
            case HandComparison.None:
                //no winner is determined = split pot
                break;

            case HandComparison.Player1Won:
                playedHand.WinnerId = smallBlindPlayer.Id;
                break;

            case HandComparison.Player2Won:
                playedHand.WinnerId = bigBlindPlayer.Id;
                break;
            }

            playedHand.AmountWon = PotSize / 2;
            playedHand.PotSize   = PotSize;
            this.Phase           = GamePhase.Showdown;
        }
        /// <summary>
        /// Traverses the sub tree of the passed hand buckets recursively. Calculates and then backpropagates the counter factual regret for each node.
        /// </summary>
        /// <param name="gameState"></param>
        /// <param name="handBuckets"></param>
        /// <param name="actions"></param>
        /// <param name="probabilityPlayer1">probability of player 1 to reach this node</param>
        /// <param name="probabilityPlayer2">probability of player 2 to reach this node</param>
        /// <returns></returns>
        private float CalculateCounterFactualRegret(HeadsUpGameState gameState, byte[] handBuckets, List <ActionBucket> actions, float probabilityPlayer1, float probabilityPlayer2)
        {
            int plays       = actions.Count;
            int playerIndex = plays % 2;

            var          newState   = gameState.GetCopy();
            ActionBucket lastAction = ActionBucket.None;

            if (actions.Count > 0)
            {
                lastAction = actions[plays - 1];
            }
            ActionBucket secondLastAction = ActionBucket.None;

            if (actions.Count > 1)
            {
                secondLastAction = actions[plays - 2];
            }

            bool nextActionCallEnabled = true;
            bool phaseChanged          = false;

            //the last actions determine whether the next phase has to be set or whether the game (i.e. the recursion) ends
            switch (lastAction)
            {
            case ActionBucket.Pass:
                if (secondLastAction == ActionBucket.LowBet ||
                    secondLastAction == ActionBucket.HighBet ||
                    secondLastAction == ActionBucket.MediumBet)
                {
                    int payoff = (newState.PotSize - newState.AmountToCall) / 2;
                    return((playerIndex == 0) ? payoff : -payoff);
                }

                switch (secondLastAction)
                {
                case ActionBucket.None:
                    return((playerIndex == 0) ? HeadsupGame.SmallBlindSize : -HeadsupGame.SmallBlindSize);

                case ActionBucket.Call:
                    newState.SetNextPhase(newState.Phase);
                    phaseChanged = true;
                    break;

                case ActionBucket.Pass:
                    //check if last pass count is dividable by 2 (then it's a new phase)
                    int lastActionPassCount = 0;
                    for (int i = actions.Count - 1; i >= 0; i--)
                    {
                        if (actions[i] == ActionBucket.Pass)
                        {
                            lastActionPassCount++;
                        }
                        else
                        {
                            //special case: if it's first round, call pass results in ending the round
                            if ((actions[i] == ActionBucket.Call && i == 0) &&
                                actions.Count > 2 && actions[i + 1] == ActionBucket.Pass)
                            {
                                lastActionPassCount--;
                            }
                            break;
                        }
                    }

                    if (lastActionPassCount % 2 == 0)
                    {
                        newState.SetNextPhase(newState.Phase);
                        phaseChanged = true;
                    }
                    break;
                }
                nextActionCallEnabled = false;
                break;

            case ActionBucket.Call:
                newState.PotSize     += newState.AmountToCall;
                newState.AmountToCall = 0;
                //special case for first round: big blind needs to check or bet
                if (actions.Count == 1)
                {
                    nextActionCallEnabled = false;
                }
                else
                {
                    newState.SetNextPhase(newState.Phase);
                    phaseChanged = true;
                }
                break;

            case ActionBucket.HighBet:
            case ActionBucket.MediumBet:
            case ActionBucket.LowBet:
                int betSize = 0;
                if (newState.AmountToCall > 0 && newState.AmountToCall == HeadsupGame.SmallBlindSize)
                {
                    //exception: first round
                    newState.PotSize += HeadsupGame.SmallBlindSize;
                }

                int lastActionLowBetCount = 0;
                for (int i = actions.Count - 1; i >= 0; i--)
                {
                    if (actions[i] == ActionBucket.LowBet)
                    {
                        lastActionLowBetCount++;
                    }
                    else
                    {
                        break;
                    }
                }

                betSize = ActionAbstracter.GetBetSize(lastAction, newState.AmountToCall, newState.PotSize);
                if (betSize > 0)
                {
                    newState.AmountToCall = betSize;
                    newState.PotSize     += betSize;
                    if (newState.PotSize >= HeadsupGame.StackSize * 2)
                    {
                        phaseChanged   = true;
                        newState.Phase = GamePhase.Showdown;
                    }
                }
                else
                {
                    phaseChanged   = true;
                    newState.Phase = GamePhase.Showdown;
                }
                break;
            }

            //if the phase has changed, the next event has to occur (e.g. adding a card to the current board)
            if (phaseChanged)
            {
                if (newState.Phase == GamePhase.Showdown)
                {
                    int payoff         = newState.PotSize / 2;
                    var handComparison = HandComparer.Compare(newState.Player1HoleCards, newState.Player2HoleCards, newState.Board);
                    switch (handComparison)
                    {
                    case HandComparison.None:
                        return(0);

                    case HandComparison.Player1Won:
                        return((playerIndex == 0) ? payoff : -payoff);

                    case HandComparison.Player2Won:
                        return((playerIndex == 0) ? -payoff : payoff);
                    }
                }
                else
                {
                    nextActionCallEnabled = false;

                    List <Card> currentBoard = null;
                    switch (newState.Phase)
                    {
                    case GamePhase.Flop:
                        currentBoard = gameState.Board.Take(3).ToList();
                        break;

                    case GamePhase.Turn:
                        currentBoard = gameState.Board.Take(4).ToList();
                        break;

                    case GamePhase.River:
                        currentBoard = gameState.Board;
                        break;
                    }

                    //evaluate new hand buckets
                    byte bucket1 = (byte)HandStrengthAbstracter.MapToBucket(currentBoard, newState.Player1HoleCards);
                    byte bucket2 = (byte)HandStrengthAbstracter.MapToBucket(currentBoard, newState.Player2HoleCards);
                    handBuckets = new byte[] { bucket1, bucket2 };
                }
            }

            var infoSet = new InformationSet <ActionBucket>()
            {
                CardBucket    = handBuckets[playerIndex],
                ActionHistory = actions
            };

            int numberOfActions = Settings.NumberOfActions;

            if (!nextActionCallEnabled)
            {
                numberOfActions = Settings.NumberOfActions - 1;
            }

            RegretGameNode <ActionBucket> node = null;
            long hash = infoSet.GetLongHashCode();

            //checks if the current information set already exists in O(1)
            if (!GameNodes.TryGetValue(hash, out node))
            {
                node         = new RegretGameNode <ActionBucket>(numberOfActions);
                node.InfoSet = infoSet;
                GameNodes.Add(hash, node);
            }

            //gets the strategy of the current player
            var strategy = node.calculateStrategy(playerIndex == 0 ? probabilityPlayer1 : probabilityPlayer2);

            // initialise utilities  with zeros
            var utilities = new List <float>(numberOfActions);

            for (int i = 0; i < numberOfActions; i++)
            {
                utilities.Add(0);
            }

            float nodeUtility = 0;
            int   index       = 0;

            // traverse the tree further down with a breadth first search
            foreach (ActionBucket nextAction in Enum.GetValues(typeof(ActionBucket)))
            {
                //skip illegal actions
                if (nextAction == ActionBucket.None)
                {
                    continue;
                }
                if (nextAction == ActionBucket.Call && !nextActionCallEnabled)
                {
                    continue;
                }

                var nextHistory = new List <ActionBucket>();
                nextHistory.AddRange(actions.ToArray());
                nextHistory.Add(nextAction);

                utilities[index] = playerIndex == 0
                    ? -CalculateCounterFactualRegret(newState, handBuckets, nextHistory, probabilityPlayer1 * strategy[index], probabilityPlayer2)
                   : -CalculateCounterFactualRegret(newState, handBuckets, nextHistory, probabilityPlayer1, probabilityPlayer2 * strategy[index]);

                //accumulate the utility of the sub branches
                nodeUtility += strategy[index] * utilities[index];
                index++;
            }

            for (int i = 0; i < numberOfActions; i++)
            {
                //calculate the regret
                float regret = utilities[i] - nodeUtility;
                //calculate the regret sum based on the current player
                node.RegretSum[i] += (playerIndex == 0 ? probabilityPlayer2 : probabilityPlayer1) * regret;
            }

            return(nodeUtility);
        }
예제 #18
0
        public void NotAllowNullPokerHandList()
        {
            HandComparer sut = new HandComparer();

            Assert.Throws <ArgumentNullException>("hands", () => sut.GetWinningHand(null));
        }
예제 #19
0
        public void CreateHandComparer()
        {
            HandComparer sut = new HandComparer();

            Assert.IsType <HandComparer>(sut);
        }