/// <summary>Calculates the winning change of a hand.</summary> public static PokerHandOutcome Calculate(Cards hand, Cards table, MT19937Generator rnd, int runs = 1000) { UInt64Cards[] tblSub = null; var tAdd = 5 - table.Count; var uhnd = UInt64Cards.Create(hand); var utbl = UInt64Cards.Create(table); var dead = uhnd.Combine(utbl); var ownSub = uhnd.GetHandSubsets(); var w = 0; var d = 0; var l = 0; if (tAdd == 0) { tblSub = utbl.GetTableSubsets(); } for (var i = 0; i < runs; i++) { var tbl = utbl; if (tAdd > 0) { tbl = tbl.Combine(UInt64Cards.GetRandom(dead, tAdd, rnd)); tblSub = tbl.GetTableSubsets(); } var uopp = UInt64Cards.GetRandom(dead.Combine(tbl), 4, rnd); var oppSub = uopp.GetHandSubsets(); var c = UInt32PokerHand.Compare(ownSub, oppSub, tblSub); if (c > 0) { w++; } else if (c < 0) { l++; } else { d++; } } return(new PokerHandOutcome(w, d, l)); }
/// <summary>Gets the score of a the cards.</summary> public UInt32PokerHand GetScore() { #if DEBUG if (this.Count != 5) { throw new InvalidOperationException("The number of cards is not 5."); } #endif uint rankX, mask1, mask2, mask3, mask4; var sd = CardMask(mask, CardSuit.Diamonds); var sc = CardMask(mask, CardSuit.Clubs); var sh = CardMask(mask, CardSuit.Hearts); var ss = CardMask(mask, CardSuit.Spades); var mask5 = sc | sd | sh | ss; var mask5Count = Bits.Count(mask5); switch (mask5Count) { // FourOfAKind or FullHouse case 2: mask4 = sh & sd & sc & ss; if (mask4 != 0) { rankX = GetSingleValue(mask4) | (mask5 ^ mask4); return(UInt32PokerHand.Create(PokerHandType.FourOfAKind, rankX)); } else { mask3 = ((sc & sd) | (sh & ss)) & ((sc & sh) | (sd & ss)); rankX = GetSingleValue(mask3) | (mask5 ^ mask3); return(UInt32PokerHand.Create(PokerHandType.FullHouse, rankX)); } // Three of a kind, or two pair. case 3: mask2 = mask5 ^ (sc ^ sd ^ sh ^ ss); if (mask2 != 0) { rankX = mask2 << 4; mask1 = mask5 ^ mask2; rankX |= GetSingleValue(mask1) >> 13; return(UInt32PokerHand.Create(PokerHandType.TwoPair, rankX)); } else { mask3 = ((sc & sd) | (sh & ss)) & ((sc & sh) | (sd & ss)); rankX = GetSingleValue(mask3) | (mask5 ^ mask3); return(UInt32PokerHand.Create(PokerHandType.ThreeOfAKind, rankX)); } // One pair. case 4: mask2 = mask5 ^ (sc ^ sd ^ sh ^ ss); rankX = GetSingleValue(mask2) | (mask5 ^ mask2); return(UInt32PokerHand.Create(PokerHandType.OnePair, rankX)); // Straight and or flush, or high card. case 5: default: rankX = GetStraightValue(mask5); if (rankX != 0) { return(UInt32PokerHand.Create(IsFlush ? PokerHandType.StraightFlush : PokerHandType.Straight, rankX)); } if (IsFlush) { return(UInt32PokerHand.Create(PokerHandType.Flush, mask5)); } return(UInt32PokerHand.Create(PokerHandType.HighCard, mask5)); } }