/// <summary> /// Given a set of pocket cards and a set of board cards this function returns the odds of winning or tying for a player and a random opponent. /// </summary> /// <param name="pocketcards">Pocket cards in ASCII</param> /// <param name="boardcards">Board cards in ASCII</param> /// <param name="player">Player odds as doubles</param> /// <param name="opponent">Opponent odds as doubles</param> public static void HandPlayerOpponentOdds(string pocketcards, string boardcards, ref double[] player, ref double[] opponent) { HandPlayerOpponentOdds(Hand.ParseHand(pocketcards), Hand.ParseHand(boardcards), ref player, ref opponent); }
/// <summary> /// Used to calculate the wining information about each players hand. This function enumerates all /// possible remaining hands and tallies win, tie and losses for each player. This function typically takes /// well less than a second regardless of the number of players. /// </summary> /// <param name="pockets">Array of pocket hand string, one for each player</param> /// <param name="board">the board cards</param> /// <param name="dead">the dead cards</param> /// <param name="wins">An array of win tallies, one for each player</param> /// <param name="ties">An array of tie tallies, one for each player</param> /// <param name="losses">An array of losses tallies, one for each player</param> /// <param name="totalHands">The total number of hands enumarated.</param> public static void HandOdds(string[] pockets, string board, string dead, long[] wins, long[] ties, long[] losses, ref long totalHands) { ulong[] pocketmasks = new ulong[pockets.Length]; ulong[] pockethands = new ulong[pockets.Length]; int count = 0, bestcount; ulong boardmask = 0UL, deadcards_mask = 0UL, deadcards = Hand.ParseHand(dead, ref count); totalHands = 0; deadcards_mask |= deadcards; // Read pocket cards for (int i = 0; i < pockets.Length; i++) { count = 0; pocketmasks[i] = Hand.ParseHand(pockets[i], "", ref count); if (count != 2) { throw new ArgumentException("There must be two pocket cards."); // Must have 2 cards in each pocket card set. } deadcards_mask |= pocketmasks[i]; wins[i] = ties[i] = losses[i] = 0; } // Read board cards count = 0; boardmask = Hand.ParseHand("", board, ref count); #if DEBUG Debug.Assert(count >= 0 && count <= 5); // The board must have zero or more cards but no more than a total of 5 // Check pocket cards, board, and dead cards for duplicates if ((boardmask & deadcards) != 0) { throw new ArgumentException("Duplicate between cards dead cards and board"); } // Validate the input for (int i = 0; i < pockets.Length; i++) { for (int j = i + 1; j < pockets.Length; j++) { if ((pocketmasks[i] & pocketmasks[j]) != 0) { throw new ArgumentException("Duplicate pocket cards"); } } if ((pocketmasks[i] & boardmask) != 0) { throw new ArgumentException("Duplicate between cards pocket and board"); } if ((pocketmasks[i] & deadcards) != 0) { throw new ArgumentException("Duplicate between cards pocket and dead cards"); } } #endif // Iterate through all board possiblities that doesn't include any pocket cards. foreach (ulong boardhand in Hands(boardmask, deadcards_mask, 5)) { // Evaluate all hands and determine the best hand ulong bestpocket = Evaluate(pocketmasks[0] | boardhand, 7); pockethands[0] = bestpocket; bestcount = 1; for (int i = 1; i < pockets.Length; i++) { pockethands[i] = Evaluate(pocketmasks[i] | boardhand, 7); if (pockethands[i] > bestpocket) { bestpocket = pockethands[i]; bestcount = 1; } else if (pockethands[i] == bestpocket) { bestcount++; } } // Calculate wins/ties/loses for each pocket + board combination. for (int i = 0; i < pockets.Length; i++) { if (pockethands[i] == bestpocket) { if (bestcount > 1) { ties[i]++; } else { wins[i]++; } } else if (pockethands[i] < bestpocket) { losses[i]++; } } totalHands++; } }