Exemple #1
0
        def evaluate_rank(self, hand):
            """
            Return the rank amongst all possible 5-card hands of any kind
            using the best 5-card hand from the given 6-card hand.
            """
            if len(hand) != 7:
                raise self.HandLengthException("Only 7-card hands are supported by the Seven evaluator")
            
            # bh stands for binary hand, map to that representation
            card_to_binary = HandEvaluator.Seven.card_to_binary_lookup
            bh = map(card_to_binary, hand)
        
            # Use a lookup table to determine if it's a flush as with 6 cards
            flush_prime = reduce(mul, map(lambda card: (card >> 12) & 0xF, bh))
            flush_suit = False
            if flush_prime in LookupTables.Seven.prime_products_to_flush:
                flush_suit = LookupTables.Seven.prime_products_to_flush[flush_prime]
        
            # Now use ranks to determine hand via lookup
            odd_xor = reduce(__xor__, bh) >> 16
            even_xor = (reduce(__or__, bh) >> 16) ^ odd_xor

            if flush_suit:
                # There will be 0-2 cards not in the right suit
                even_popcount = PopCount.popcount(even_xor)
                if even_xor == 0:
                    # TODO: There might be a faster way?
                    bits = reduce(__or__, map(
                        lambda card: (card >> 16),
                        filter(
                            lambda card: (card >> 12) & 0xF == flush_suit, bh)))
                    return LookupTables.Seven.flush_rank_bits_to_rank[bits]
                else:
                    if even_popcount == 2:
                        return LookupTables.Seven.flush_rank_bits_to_rank[odd_xor | even_xor]
                    else:
                        bits = reduce(__or__, map(
                            lambda card: (card >> 16),
                            filter(
                                lambda card: (card >> 12) & 0xF == flush_suit, bh)))
                        return LookupTables.Seven.flush_rank_bits_to_rank[bits]
            
            # Odd-even XOR again, see Six.evaluate_rank for details
            # 7 is odd, so you have to have an odd number of bits in odd_xor
            # 7-0 => (1,1,1,1,1,1,1) - High card
            # 5-1 => (1,1,1,1,1,2) - Pair
            # 5-0 => (1,1,1,1,3) - Trips
            # 3-2 => (1,1,1,2,2) - Two pair
            # 3-1 => (1,1,1,4) or (1,1,3,2) - Quads or full house
            # 3-0 => (1,3,3) - Full house
            # 1-3 => (1,2,2,2) - Two pair
            # 1-2 => (1,2,4) or (3,2,2) - Quads or full house
            # 1-1 => (3,4) - Quads
            
            if even_xor == 0: # x-0                
                odd_popcount = PopCount.popcount(odd_xor)
                if odd_popcount == 7: # 7-0
                    return LookupTables.Seven.odd_xors_to_rank[odd_xor]
                else: # 5-0, 3-0
                    prime_product = reduce(mul, map(lambda card: card & 0xFF, bh))
                    return LookupTables.Seven.prime_products_to_rank[prime_product]
            else:
                odd_popcount = PopCount.popcount(odd_xor)
                if odd_popcount == 5: # 5-1
                    return LookupTables.Seven.even_xors_to_odd_xors_to_rank[even_xor][odd_xor]
                elif odd_popcount == 3:
                    even_popcount = PopCount.popcount(even_xor)
                    if even_popcount == 2: # 3-2
                        return LookupTables.Seven.even_xors_to_odd_xors_to_rank[even_xor][odd_xor]
                    else: # 3-1
                        prime_product = reduce(mul, map(lambda card: card & 0xFF, bh))
                        return LookupTables.Seven.prime_products_to_rank[prime_product]
                else:
                    even_popcount = PopCount.popcount(even_xor)
                    if even_popcount == 3: # 1-3
                        return LookupTables.Seven.even_xors_to_odd_xors_to_rank[even_xor][odd_xor]
                    elif even_popcount == 2: # 1-2
                        prime_product = reduce(mul, map(lambda card: card & 0xFF, bh))
                        return LookupTables.Seven.prime_products_to_rank[prime_product]
                    else: # 1-1
                        return LookupTables.Seven.even_xors_to_odd_xors_to_rank[even_xor][odd_xor]
Exemple #2
0
 def evaluate_rank(self, hand):
     """
     Return the rank amongst all possible 5-card hands of any kind
     using the best 5-card hand from the given 6-card hand.
     """
     if len(hand) != 6:
         raise self.HandLengthException("Only 6-card hands are supported by the Six evaluator")
     
     # bh stands for binary hand, map to that representation
     card_to_binary = HandEvaluator.Six.card_to_binary_lookup
     bh = map(card_to_binary, hand)
 
     # We can determine if it's a flush using a lookup table.
     # Basically use prime number trick but map to bool instead of rank
     # Once you have a flush, there is no other higher hand you can make
     # except straight flush, so just need to determine the highest flush
     flush_prime = reduce(mul, map(lambda card: (card >> 12) & 0xF, bh))
     flush_suit = False
     if flush_prime in LookupTables.Six.prime_products_to_flush:
         flush_suit = LookupTables.Six.prime_products_to_flush[flush_prime]
 
     # Now use ranks to determine hand via lookup
     odd_xor = reduce(__xor__, bh) >> 16
     even_xor = (reduce(__or__, bh) >> 16) ^ odd_xor
     # If you have a flush, use odd_xor to find the rank
     # That value will have either 4 or 5 bits
     if flush_suit:
         if even_xor == 0:
             # There might be 0 or 1 cards in the wrong suit, so filter
             # TODO: There might be a faster way?
             bits = reduce(__or__, map(
                 lambda card: (card >> 16),
                 filter(
                     lambda card: (card >> 12) & 0xF == flush_suit, bh)))
             return LookupTables.Six.flush_rank_bits_to_rank[bits]
         else:
             # you have a pair, one card in the flush suit,
             # so just use the ranks you have by or'ing the two
             return LookupTables.Six.flush_rank_bits_to_rank[odd_xor | even_xor]
 
     # Otherwise, get ready for a wild ride:
 
     # Can determine this by using 2 XORs to reduce the size of the
     # lookup. You have an even number of cards, so any odd_xor with
     # an odd number of bits set is not possible.
     # Possibilities are odd-even:
     # 6-0 => High card or straight (1,1,1,1,1,1)
     #   Look up by odd_xor
     # 4-1 => Pair (1,1,1,1,2)
     #   Look up by even_xor (which pair) then odd_xor (which set of kickers)
     # 4-0 => Trips (1,1,1,3)
     #   Don't know which one is the triple, use prime product of ranks
     # 2-2 => Two pair (1,1,2,2)
     #   Look up by odd_xor then even_xor (or vice-versa)
     # 2-1 => Four of a kind (1,1,4) or full house (1,3,2)
     #   Look up by prime product
     # 2-0 => Full house using 2 trips (3,3)
     #   Look up by odd_xor
     # 0-3 => Three pairs (2,2,2)
     #   Look up by even_xor
     # 0-2 => Four of a kind with pair (2,4)
     #   Look up by prime product
 
     # Any time you can't disambiguate 2/4 or 1/3, use primes.
     # We also assume you can count bits or determine a power of two.
     # (see PopCount class.)
     
     if even_xor == 0: # x-0
         odd_popcount = PopCount.popcount(odd_xor)
         if odd_popcount == 4: # 4-0
             prime_product = reduce(mul, map(lambda card: card & 0xFF, bh))
             return LookupTables.Six.prime_products_to_rank[prime_product]
         else: # 6-0, 2-0
             return LookupTables.Six.odd_xors_to_rank[odd_xor]
     elif odd_xor == 0: # 0-x
         even_popcount = PopCount.popcount(even_xor)
         if even_popcount == 2: # 0-2
             prime_product = reduce(mul, map(lambda card: card & 0xFF, bh))
             return LookupTables.Six.prime_products_to_rank[prime_product]
         else: # 0-3
             return LookupTables.Six.even_xors_to_rank[even_xor]
     else: # odd_popcount is 4 or 2
         odd_popcount = PopCount.popcount(odd_xor)
         if odd_popcount == 4: # 4-1
             return LookupTables.Six.even_xors_to_odd_xors_to_rank[even_xor][odd_xor]
         else: # 2-x
             even_popcount = PopCount.popcount(even_xor)
             if even_popcount == 2: # 2-2
                 return LookupTables.Six.even_xors_to_odd_xors_to_rank[even_xor][odd_xor]
             else: # 2-1
                 prime_product = reduce(mul, map(lambda card: card & 0xFF, bh))
                 return LookupTables.Six.prime_products_to_rank[prime_product]