Esempio n. 1
0
def calculate_deuces(board_arg, hand_arg):
    """
    Calculates the Deuces score as well as its class (high card, pair, etc)
    :param board: list of string with len > 2
    :param hand: list of string with len = 2
    :return: Tuple of (deuces score, deuces class)
    """

    log.debug('Calculating Deuces of {} and {}'.format(board_arg, hand_arg))

    if input_type_checker(board_arg, hand_arg):
        # convert string to Card object
        board = list(map(lambda c: Card.new(c), board_arg))
        hand = list(map(lambda c: Card.new(c), hand_arg))

        evaluator = Evaluator()
        deuces_score = evaluator.evaluate(board, hand)
        deuces_class = evaluator.class_to_string(
            evaluator.get_rank_class(deuces_score))

        return (deuces_score, deuces_class)

    else:
        log.error('Please see documentation for list of valid input.')
        sys.exit(1)
Esempio n. 2
0
    def test_cards_numerical_value(self):
        """
        Each card has a unique numerical value
        :return:
        """

        card1 = Card.new('4h')
        card2 = Card.new('2s')

        self.assertEqual(card1, 270853)
        self.assertEqual(card2, 69634)
Esempio n. 3
0
def compute_win_percentage(board_arg, hand_arg):
    """
    Computes your winning percentage using a Monte Carlo Simulation
    :param board_arg: list of string with len > 2
    :param hand_arg: list of string with len = 2
    :return:
    """

    log.debug('Computing win percentage of {} and {}'.format(
        board_arg, hand_arg))
    board = []
    hand = []

    if input_type_checker(board_arg, hand_arg):
        # convert string to Card object
        board = list(map(lambda c: Card.new(c), board_arg))
        hand = list(map(lambda c: Card.new(c), hand_arg))

    simulation_count = 3000
    win_count = 0
    runs = 0

    evaluator = Evaluator()

    for sim in range(simulation_count):
        board_fill = 5 - len(board)

        simulate_board = board + draw_from_deck(board_fill, board + hand)
        simulate_hand = draw_from_deck(2, simulate_board + hand)

        my_score = evaluator.evaluate(simulate_board, hand)
        enemy_score = evaluator.evaluate(simulate_board, simulate_hand)

        if my_score < enemy_score:
            win_count += 1

        runs += 1

        log.debug('Your score: {} {} vs {} {}'.format(
            evaluator.class_to_string(evaluator.get_rank_class(my_score)),
            my_score,
            evaluator.class_to_string(evaluator.get_rank_class(enemy_score)),
            enemy_score))

    win_chance = win_count / float(runs)

    return win_chance
Esempio n. 4
0
    def _five(self, cards):
        """
        Performs an evalution given cards in integer form, mapping them to
        a rank in the range [1, 7462], with lower ranks being more powerful.

        Variant of Cactus Kev's 5 card evaluator, though I saved a lot of memory
        space using a hash table and condensing some of the calculations.
        """
        # if flush
        if cards[0] & cards[1] & cards[2] & cards[3] & cards[4] & 0xF000:
            handOR = (cards[0] | cards[1] | cards[2] | cards[3] | cards[4]) >> 16
            prime = Card.prime_product_from_rankbits(handOR)
            return self.table.flush_lookup[prime]

        # otherwise
        else:
            prime = Card.prime_product_from_hand(cards)
            return self.table.unsuited_lookup[prime]
Esempio n. 5
0
    def straight_and_highcards(self, straights, highcards):
        """
        Unique five card sets. Straights and highcards.

        Reuses bit sequences from flush calculations.
        """
        rank = LookupTable.MAX_FLUSH + 1

        for s in straights:
            prime_product = Card.prime_product_from_rankbits(s)
            self.unsuited_lookup[prime_product] = rank
            rank += 1

        rank = LookupTable.MAX_PAIR + 1
        for h in highcards:
            prime_product = Card.prime_product_from_rankbits(h)
            self.unsuited_lookup[prime_product] = rank
            rank += 1
Esempio n. 6
0
    def GetFullDeck():
        if Deck._FULL_DECK:
            return list(Deck._FULL_DECK)

        # create the standard 52 card deck
        for rank in Card.STR_RANKS:
            for suit, val in Card.CHAR_SUIT_TO_INT_SUIT.iteritems():
                Deck._FULL_DECK.append(Card.new(rank + suit))

        return list(Deck._FULL_DECK)
Esempio n. 7
0
    def test_evaluator(self):
        """
        Checks if the deuces score produced is correct
        :return:
        """

        board = [
            Card.new('4h'),
            Card.new('5h'),
            Card.new('8h'),
            Card.new('7h'),
            Card.new('9d')
        ]

        hand = [Card.new('2s'), Card.new('3s')]

        evaluator = Evaluator()
        deuces_score = evaluator.evaluate(board, hand)

        self.assertEqual(deuces_score, 7414)
Esempio n. 8
0
 def __str__(self):
     return Card.print_pretty_cards(self.cards)
Esempio n. 9
0
    def flushes(self):
        """
        Straight flushes and flushes.

        Lookup is done on 13 bit integer (2^13 > 7462):
        xxxbbbbb bbbbbbbb => integer hand index
        """

        # straight flushes in rank order
        straight_flushes = [
            7936,  # int('0b1111100000000', 2), # royal flush
            3968,  # int('0b111110000000', 2),
            1984,  # int('0b11111000000', 2),
            992,  # int('0b1111100000', 2),
            496,  # int('0b111110000', 2),
            248,  # int('0b11111000', 2),
            124,  # int('0b1111100', 2),
            62,  # int('0b111110', 2),
            31,  # int('0b11111', 2),
            4111  # int('0b1000000001111', 2) # 5 high
        ]

        # now we'll dynamically generate all the other
        # flushes (including straight flushes)
        flushes = []
        gen = self.get_lexographically_next_bit_sequence(int('0b11111', 2))

        # 1277 = number of high cards
        # 1277 + len(str_flushes) is number of hands with all cards unique rank
        for i in range(1277 + len(straight_flushes) -
                       1):  # we also iterate over SFs
            # pull the next flush pattern from our generator
            f = next(gen)

            # if this flush matches perfectly any
            # straight flush, do not add itø
            notSF = True
            for sf in straight_flushes:
                # if f XOR sf == 0, then bit pattern
                # is same, and we should not add
                if not f ^ sf:
                    notSF = False

            if notSF:
                flushes.append(f)

        # we started from the lowest straight pattern, now we want to start ranking from
        # the most powerful hands, so we reverse
        flushes.reverse()

        # now add to the lookup map:
        # start with straight flushes and the rank of 1
        # since theyit is the best hand in poker
        # rank 1 = Royal Flush!
        rank = 1
        for sf in straight_flushes:
            prime_product = Card.prime_product_from_rankbits(sf)
            self.flush_lookup[prime_product] = rank
            rank += 1

        # we start the counting for flushes on max full house, which
        # is the worst rank that a full house can have (2,2,2,3,3)
        rank = LookupTable.MAX_FULL_HOUSE + 1
        for f in flushes:
            prime_product = Card.prime_product_from_rankbits(f)
            self.flush_lookup[prime_product] = rank
            rank += 1

        # we can reuse these bit sequences for straights
        # and high cards since they are inherently related
        # and differ only by context
        self.straight_and_highcards(straight_flushes, flushes)