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(); }
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); } }
public void NotAllowEmptyPokerHandList() { HandComparer sut = new HandComparer(); //empty list var list = new List <PokerHandDto>(); Assert.Throws <ArgumentException>(() => sut.GetWinningHand(list)); }
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;
/// <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(); }
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(); }
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); }
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); }
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); }
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); }
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); }
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); }
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); } } }
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); }
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); }
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); }
public void NotAllowNullPokerHandList() { HandComparer sut = new HandComparer(); Assert.Throws <ArgumentNullException>("hands", () => sut.GetWinningHand(null)); }
public void CreateHandComparer() { HandComparer sut = new HandComparer(); Assert.IsType <HandComparer>(sut); }