def _rankFiveCardHand(cls, cards): """Get rank of five cards. This method is more efficient than _getRankSixPlusCards().""" cards.sort(reverse=True) isFlush = cards.sameSuit() straightRank = cls._isStraight(cards) # Do we have a straight flush? if (straightRank and isFlush): return PokerRank.straightFlush(straightRank) # Check for four of a kind if (cards[0].rank == cards[1].rank == cards[2].rank == cards[3].rank): return PokerRank.quads(cards[0].rank, cards[4:]) if (cards[1].rank == cards[2].rank == cards[3].rank == cards[4].rank): return PokerRank.quads(cards[1].rank, cards[0:1]) # Check for full house # -First two and last two cards must match each other # -Then middle card either matches first two cards # or last two cards if ((cards[0].rank == cards[1].rank) and (cards[3].rank == cards[4].rank)): if (cards[2].rank == cards[0].rank): # XXXYY return PokerRank.fullHouse(cards[0].rank, cards[3].rank) elif (cards[2].rank == cards[3].rank): # XXYYY return PokerRank.fullHouse(cards[2].rank, cards[0].rank) # Check for flush, which we've already done if isFlush: return PokerRank.flush(cards[0].rank, cards[1:]) # Check for Straight, which we've already done if straightRank: return PokerRank.straight(straightRank) # Check for trips if ((cards[0].rank == cards[1].rank == cards[2].rank) or (cards[1].rank == cards[2].rank == cards[3].rank) or (cards[2].rank == cards[3].rank == cards[4].rank)): # cards[2] will always be one of the trips primaryRank = cards[2].rank cards.removeRank(primaryRank) return PokerRank.trips(primaryRank, cards) # Check for two pair # At this point we know we don't have trips, so can optimize some if (cards[0].rank == cards[1].rank): if (cards[2].rank == cards[3].rank): return PokerRank.twoPair(cards[0].rank, cards[2].rank, cards[4:]) if (cards[3].rank == cards[4].rank): return PokerRank.twoPair(cards[0].rank, cards[3].rank, cards[2:3]) elif ((cards[1].rank == cards[2].rank) and (cards[3].rank == cards[4].rank)): return PokerRank.twoPair(cards[1].rank, cards[3].rank, cards[0:1]) # Check for a pair # At this point we know we don't have two pair or trips foundPair = False for index in range(4): if cards[index].rank == cards[index+1].rank: foundPair = True break if foundPair: pairRank = cards[index].rank del cards[index:index+2] return PokerRank.pair(pairRank, cards) # Just a high card return PokerRank.highCard(cards[0].rank, cards[1:])
def _rankSixOrSevenCardHand(cls, cards): """Given a set of 6 or 7 cards, return a PokerRank for its best hand. Will work for 5 cards, but is less efficient than _rankFiveCardHand().""" if len(cards) > 7: raise ValueError("Hand has too many cards (%d > 7)" % len(cards)) if len(cards) < 5: raise ValueError("Hand has too few cards (%d < 5)" % len(cards)) # Array of bitfields of cards by suit suitedBitFields = cls._handToSuitedBitFields(cards) # Check for straight-flush highRank = None for suit in Suit.suits: rank = cls._hasStraight(suitedBitFields[suit]) if rank and ((highRank is None) or (rank > highRank)): highRank = rank if highRank is not None: return PokerRank.straightFlush(highRank) # Get bitfields representing singletons, pairs, trips and quads (singletonsBitField, pairsBitField, tripsBitField, quadsBitField) = cls._suitedBitFieldsToRankedBitFields(suitedBitFields) # Single bitfield with all four suits merged for kickers and straights bitfield = (suitedBitFields[Suit.CLUBS] | suitedBitFields[Suit.DIAMONDS] | suitedBitFields[Suit.HEARTS] | suitedBitFields[Suit.SPADES]) # Check for quads if quadsBitField.setCount() > 0: rank = quadsBitField.highestSet() # Highest remaining card is our kicker kickerRank = bitfield.filterBits(rank).highestSet() return PokerRank.quads(rank, [kickerRank]) # Check for full house if ((tripsBitField > 0) & (pairsBitField > 0)): return PokerRank.fullHouse(tripsBitField.highestSet(), pairsBitField.highestSet()) # Check for flush flushBitField = None for suit in Suit.suits: if suitedBitFields[suit].setCount() >= 5: if ((flushBitField is None) or (suitedBitFields[suit] > flushBitField)): flushBitField = suitedBitFields[suit] if flushBitField: rank = flushBitField.highestSet() kickers = flushBitField.filterBits(rank).highestNSet(4) return PokerRank.flush(rank, kickers) # Check for straight # We don't care about suit anymore so can just operate on bitfield rank = cls._hasStraight(bitfield) if rank: return PokerRank.straight(rank) # Check for trips if (tripsBitField > 0): rank = tripsBitField.highestSet() kickers = bitfield.filterBits(rank).highestNSet(2) kickers = bitfield.highestNSet(2) return PokerRank.trips(rank, kickers) # Check for two pair if (pairsBitField.setCount() > 1): ranks = pairsBitField.highestNSet(2) kickers = bitfield.filterBits(ranks[0], ranks[1]) kicker = kickers.highestSet() return PokerRank.twoPair(ranks[0], ranks[1], [kicker]) # Check for pair if (pairsBitField > 0): rank = pairsBitField.highestSet() kickers = bitfield.filterBits(rank).highestNSet(3) return PokerRank.pair(rank, kickers) # High card highCard = bitfield.highestSet() kickers = bitfield.filterBits(highCard).highestNSet(4) return PokerRank.highCard(highCard, kickers)