def get_bucket_number(hole_cards, community_cards=None):
    """	
	Evaluate handstrength base on Chen's Formula if only hole cards are drawn,
    because it values both hand potential as well as relative value of card rank.
    Otherwise, evaluate handstrength using Deuces Monte-carlo Look-up table.
    Divide the bucket with equal probability based on the number of buckets.
    Using the handstrength value drawn earlier, find the right bucket.
    
    :param hole_cards: List(str) in format of 'CA' for hole cards belong to the current player
    :param community_cards: List(str) in format of 'S3' for community cards   
    """
    if not community_cards:
        points = starting_hand_evaluator(hole_cards)
        bucket_number = int(
            math.ceil((points + 1.5) / 21.5 * constants.BUCKET_NUM) - 1)
    else:
        hole_cards = list(
            map(lambda x: DeucesCard.new(x[1] + x[0].lower()), hole_cards))
        community_cards = list(
            map(lambda x: DeucesCard.new(x[1] + x[0].lower()),
                community_cards))

        evaluator = DeucesEvaluator()
        five_cards_ranking = evaluator.evaluate(hole_cards, community_cards)
        strength = 1.0 - evaluator.get_five_card_rank_percentage(
            five_cards_ranking)
        bucket_number = int(math.ceil(strength * constants.BUCKET_NUM) - 1)

    return 0 if bucket_number == -1 else bucket_number
예제 #2
0
 def drawCardsAndDoRound(self, cardsToDraw):
     for player in self.playersInRound:
         self.playersBettedCurrentRound[player] = 0
     print("\n\nPot total is", self.pot)
     print("\n Flop:")
     self.board += self.deck.draw(cardsToDraw)
     Card.print_pretty_cards(self.board)
     if (len(self.getPlayersInRoundNotInAllIn()) > 1):
         self.doRound()
예제 #3
0
async def evaluateHand(whichServer):
    global table
    global hands
    global board
    global isRound
    global firstGame
    global players
    global pot
    finalBoard = []
    finalHands = []
    handWinner = []
    max = 100000
    eval = Evaluator()
    for card in board[whichServer]:
        temp1 = card[1].replace('10', 'T')
        temp2 = card[0].lower()
        temp3 = Card.new(temp1[0] + temp2[0])
        finalBoard.append(temp3)

    for p in table[whichServer]:
        for card in hands[whichServer][p]:
            temp1 = card[1].replace('10', 'T')
            temp2 = card[0].lower()
            temp3 = Card.new(temp1[0] + temp2[0])
            finalHands.append(temp3)

        valueOfHand = eval.evaluate(finalBoard, finalHands)

        if valueOfHand < max:
            max = valueOfHand
            handWinner = []
            handWinner.append(p)
        elif valueOfHand == max:
            handWinner.append(p)

        print(eval.evaluate(finalBoard, finalHands))
        finalHands = []

    pot[whichServer] /= len(handWinner)
    for winners in handWinner:
        players[whichServer][winners] += pot[whichServer]
        await bot.send_message(
            pokerChannel[whichServer], winners.display_name +
            " won the round! They won " + str(pot[whichServer]) +
            "$. Use command startPoker to start another one!")
    firstGame[whichServer] = 0
    pot[whichServer] = 0
    isRound[whichServer] = 0
예제 #4
0
    def _get_deuces_card(self, card):
        card_str = ""
        val = card % 13 + 1
        if val < 10 and val > 1:
            card_str = str(val)
        else:
            if val == 1:
                card_str = "A"
            if val == 10:
                card_str = "T"
            if val == 11:
                card_str = "J"
            if val == 12:
                card_str = "Q"
            if val == 13:
                card_str = "K"

        if card < 13:
            card_str += "h"
        elif card < 26:
            card_str += "d"
        elif card < 39:
            card_str += "s"
        else:
            card_str += "c"
        return Card.new(card_str)
예제 #5
0
    def calculateHand(self, hole_card, round_state):
        """ 
        Passes what's on table and in your hand to deuces,
        to calculate hand strength,
        if the flop hasnt been played yet, return -1
        """
        if (round_state["community_card"] == []):
            return -1

        board = list(
            map(lambda x: Card.new(x[-1] + x[0].lower()),
                round_state["community_card"]))

        hand = list(map(lambda x: Card.new(x[-1] + x[0].lower()), hole_card))
        evaluator = Evaluator()
        #Return as a fraction, lower is better
        return (evaluator.evaluate(board, hand) / 7462)
예제 #6
0
def create_cards(cards):

    # we want to return a list of Card objects, given the string label
    ret_cards = []
    for card in cards:
        ret_cards.append(Card.new(card))

    return ret_cards
예제 #7
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]
예제 #8
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
예제 #9
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]
예제 #10
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
예제 #11
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.items():
                Deck._FULL_DECK.append(Card.new(rank + suit))

        return list(Deck._FULL_DECK)
예제 #12
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)
예제 #13
0
    def _two(self, cards):
        """
        Pre-flop: 169 non-equivalent starting hands out of 1326 hands
        Ranks: Pairs, suited, unsuited. Plus if connectors. Ace always better
        Find index from self.startingHandRanks
        """
        card1, card2 = cards[0], cards[1]
        rank1, rank2 = Card.get_rank_int(card1), Card.get_rank_int(card2)
        firstRank, secondRank = max(rank1, rank2), min(rank1, rank2)

        cardString = str(Card.STR_RANKS[firstRank]) + str(
            Card.STR_RANKS[secondRank])
        if (firstRank != secondRank):
            #check if suited or not
            if (Card.get_suit_int(card1) == Card.get_suit_int(card2)):
                cardString += "s"
            else:
                cardString += "o"

        return self.startingHandRanks.index(cardString)
예제 #14
0
    def evaluate_hand(board, hand):
        if board is None or len(board) < 3:
            raise ValueError("Missing board cards")
        if hand is None or len(hand) < 2:
            raise ValueError("Missing hole cards")

        deuces_board = [Card.new(board[0]), Card.new(board[1]), Card.new(board[2]),
                        Card.new(board[3]), Card.new(board[4])]
        deuces_hand = [Card.new(hand[0]), Card.new(hand[1])]

        evaluator = Evaluator()
        score = evaluator.evaluate(deuces_board, deuces_hand)
        hand_rank = evaluator.get_rank_class(score)
        hand_rank_str = evaluator.class_to_string(hand_rank)

        return hand_rank_str, score
예제 #15
0
def flush_possible(full_board):
    """
    Computes whether or not a flush is possible with the cards in the board. 
    Args: 
        full_board: list of int (deuces cards). Despite its name, does not actually have to be a 5-card board (can be 3, 4, or 5 cards)
    """
    suits = [0, 0, 0, 0]
    suit_conversion = {'d': 0, 'c': 1, 'h': 2, 's': 3}
    num_conversion = {0: 'd', 1: 'c', 2: 'h', 3: 's'}
    for card in full_board:
        suits[suit_conversion[Card.int_to_str(card)[1]]] += 1

    suit_amax = argmax(suits)
    max_suits = suits[suit_amax]
    if max_suits >= 3:
        return num_conversion[suit_amax], 5 - max_suits
    else:
        return 'n', -1
예제 #16
0
def read_lookup_table(hole_cards, lookup_table):
    """
    Reads the preflop lookup table preflop_EHSs.txt.
    Args: 
        hole_cards: list of int (deuces cards)
        lookup_table: read from preflop_EHSs.txt
    Return:
        tuple (float, float): EHS, EHS^2
    """
    sorted_hole = sorted(hole_cards)
    sorted_hole.reverse()
    card_strings = [Card.int_to_str(card) for card in sorted_hole]

    if card_strings[0][1] != card_strings[1][1]:
        suited = False
    else:
        suited = True
    card_strings[0] = card_strings[0][0] + 'd'
    if suited:
        card_strings[1] = card_strings[1][0] + 'd'
    else:
        card_strings[1] = card_strings[1][0] + 's'
    card_strings = tuple(card_strings)
    return lookup_table[card_strings]
예제 #17
0
 def __str__(self):
     return Card.print_pretty_cards(self.cards)
예제 #18
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)
예제 #19
0
 def __str__(self):
     return Card.print_pretty_cards(self.cards)
예제 #20
0
def to_deuces_intlist(L):
    return [Card.new(z) for z in pypoker_to_deuces_strlist(L)]
예제 #21
0
        st = PokerState()
        st.playerJustMoved = self.playerJustMoved
        st.deck = self.deck
        st.board = self.board
        st.player1 = self.player1
        st.player2 = self.player2
        return st

    def DoMove(self, move):
        """ Update a state by carrying out the given move.
            Must update playerJustMoved.
        """

        self.playerJustMoved = 3 - self.playerJustMoved

    def GetMoves(self):
        return ["aposta", "sai"]

    def GetResult(self, player1):
        p1 = self.evaluator.evaluate(self.player1, self.board)
        p2 = self.evaluator.evaluate(self.player2, self.board)
        if p1 < p2:
            return 1.0


board = [Card.new('Th'), Card.new('Kh'), Card.new('Qh'), Card.new('Jh')]
Card.print_pretty_cards(board)
p1 = [Card.new('8c'), Card.new('9c')]
e = Evaluator()

print e.evaluate(board, p1)
예제 #22
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)
예제 #23
0
from deuces.card import Card
from deuces.evaluator import Evaluator
from deuces.deck import Deck

# create a card
card = Card.new('Qh')

# create a board and hole cards
board = [Card.new('2h'), Card.new('2s'), Card.new('Jc')]
hand = [Card.new('Qs'), Card.new('Th')]

# pretty print cards to console
Card.print_pretty_cards(board + hand)

# create an evaluator
evaluator = Evaluator()

# and rank your hand
rank = evaluator.evaluate(board, hand)
print("Rank for your hand is: %d" % rank)

# or for random cards or games, create a deck
print("Dealing a new hand...")
deck = Deck()
board = deck.draw(5)
player1_hand = deck.draw(2)
player2_hand = deck.draw(2)

print("The board:")
Card.print_pretty_cards(board)
    def GenerateMultipliers(self,
                            hands,
                            hand_values,
                            num_players=4,
                            data_dir=None):
        """
        Generates an array full of multipliers used to calculate the results of gameplay
        
        hands =         Array of hands (rounds*all_hands_per_round, 3) with format:
                        [[dealer_Cards], [player1_cards], [player2_cards], [player3_cards], ...]
            
        hand_values =   Array of the associated hand ranks returned from evaluate_hands
        
        num_players =   Number of players per round (excluding the player/dealer)
        
        
        Returns array of multipliers (num_rounds,num_players,4) specifying the following for each hand:

            multipliers[round,hand,0]:    Play multiplier -- determines whether hand should be played
                                                             and whether it wins, loses, or pushes
                                                             (1 = win, -1 = loss, 0 = no play or push)
                                                            
            multipliers[round,hand,1]:    Ante multiplier -- 0 = ante pushes, 1 = ante wins, -1 = ante loses
            
            multipliers[round,hand,2]:    Pair Plus multiplier -- -1 if Pair Plus loses, otherwise the bonus multiple
            
            multipliers[round,hand,3]:    6-Card Multiplier -- -1 if 6-Card bonus loses, otherwise the bonus multiple
        """

        if data_dir is None:
            data_dir = self.tmp_dir

        all_hands = num_players + 1
        num_rounds = len(hands) / all_hands

        multipliers = np.memmap(path.join(data_dir, 'multipliers'),
                                dtype='int32',
                                mode='w+',
                                shape=(num_rounds, num_players, 4))

        play_multipliers = multipliers[:, :, 0]
        ante_multipliers = multipliers[:, :, 1]
        pair_plus_multipliers = multipliers[:, :, 2]
        six_card_multipliers = multipliers[:, :, 3]

        #group hand values into sets of 1 dealer hand + related player hands
        #Split the dealer values into one group and player values into another
        splittable_values = hand_values.reshape(-1, all_hands)
        dealer_values = splittable_values.T[0].reshape(-1, 1)
        player_values = splittable_values.T[1:].T

        #Lower valued hands beat higher valued hands
        #Win_lose = -1 for player hands that lose, 1 for wins, and 0 for ties
        win_lose = np.memmap(path.join(data_dir, 'win_lose'),
                             dtype='int32',
                             mode='w+',
                             shape=(num_rounds, num_players))
        win_lose[:] = np.copysign(1, dealer_values - player_values)

        #Hand and card ranks needed to determine when play bet should be made for each hand
        #The suits are arbitrary as long as these are unsuited hands
        ACE_HIGH = self.evaluate_hand(Card.hand_to_binary(['Ac', '2d', '4d']))
        KING_HIGH = self.evaluate_hand(Card.hand_to_binary(['Kc', '2d', '3d']))
        QUEEN_HIGH = self.evaluate_hand(Card.hand_to_binary(['Qc', '2d',
                                                             '3d']))
        ACE = Card.get_rank_int(Card.new('Ac'))
        KING = Card.get_rank_int(Card.new('Kc'))
        QUEEN = Card.get_rank_int(Card.new('Qc'))

        #In each round, one dealer card is dealt face up
        #Here we build an array view containing the first dealer card for each round as our face up card
        #hands.reshape(1,-1)[0] is equivalent to hands.flatten() without copying into a new array

        dealer_face_up = hands.reshape(1,
                                       -1)[0][0::all_hands * 3].reshape(-1, 1)

        #Face up dealer cards are converted to int ranks
        #face_up_rank = (dealer_face_up>>8)&0xFF

        #Hand plays based on House Way:
        #    Always play A high or better
        #    Play K high if dealer face up card is K or worse
        #    Play Q high if dealer face up card is Q or worse
        #    Never play hands less than Q high

        #Play the hand = 1, don't play = 0

        play_multipliers[:] = np.where(
            player_values <= ACE_HIGH, 1,
            np.where(
                player_values <= KING_HIGH,
                np.where((dealer_face_up >> 8) & 0xF < ACE, 1, 0),
                np.where(player_values <= QUEEN_HIGH,
                         np.where((dealer_face_up >> 8) & 0xF < KING, 1, 0),
                         0)))

        #Pair Plus bonus loses (-1) when a player's hand is less than a pair
        #Otherwise it pays a multiple of the bet depending on the hand strength for pairs and better
        #The bet plays independently of the hand winning or losing,
        #but if the player does not make a play bet, the Pair Plus bonus is forfeit (-1)

        #Pay chart
        #    Worse than one pair:  -1
        #    Pair: 1x
        #    Flush: 3x
        #    Straight: 6x
        #    Straight flush: 30x
        #    Royal flush: 50x

        pair_plus_multipliers[:] = np.where(
            play_multipliers == 0, -1,
            np.where(
                player_values > self.tc_lookup.MAX_PAIR, -1,
                np.where(
                    player_values > self.tc_lookup.MAX_FLUSH, 1,
                    np.where(
                        player_values > self.tc_lookup.MAX_STRAIGHT, 3,
                        np.where(
                            player_values > self.tc_lookup.MAX_TRIPS, 6,
                            np.where(
                                player_values >
                                self.tc_lookup.MAX_STRAIGHT_FLUSH, 30,
                                np.where(player_values > 1, 40, 50)))))))

        #Calculate Ante wins/losses
        #If a play bet is not made, ante loses (-1) automatically
        #If a play bet is made:
        #    Hand wins:  ante wins (+1)
        #    Hand loses: ante loses (-1) if dealer has Q high or better, otherwise pushes (0)

        ante_multipliers[:] = np.where(
            play_multipliers == 0, -1,
            np.where(win_lose > -1, win_lose,
                     np.where(dealer_values <= QUEEN_HIGH, -1, 0)))

        #Calculate Play wins/losses
        #We need to do this after calculating the Pair Plus bonus
        #so we don't confuse ties with forfeit hands
        #If the dealer hand is worse than Q high, the Play bet pushes (0)

        play_multipliers[:] = np.where(dealer_values <= QUEEN_HIGH,
                                       play_multipliers * win_lose, 0)

        del win_lose

        #Now we need to compute the 6-card bonuses
        #These are based on the best 5-card hand that can be made from the player's 3 card and the dealer's 3

        #The first out of each group of hands is the dealer hand for that group
        #The rest are the player hands
        #we want groups like: [dcard1, dcard2, dcard3, pcard1, pcard2, pcard3]
        #to pass to deuces' hand evaluator
        #This requires some slicing arobatics to avoid building new arrays

        #Hands are arranged by round such as dealer_cards, player1_cards, player2_cards, etc.
        #Then stepped slices are taken and truncated to form slices for each combo of dealer and player cards

        #eg. If hands = [D01, D02, D03, Pa1, Pa2, Pa3, Pb1, Pb2, Pb3,
        #                D11, D12, D13, Pc1, Pc2, Pc3, Pd1, Pd2, Pd3]
        #
        #Then eval_hands[0] = [[D01, D02, D03, Pa1, Pa2, Pa3],
        #                      [D11, D12, D13, Pc1, Pc2, Pc3]]
        #
        #     eval_hands[1] = [[D01, D02, D03, Pb1, Pb2, Pb3],
        #                      [D11, D12, D13, Pd1, Pd2, Pd3]]

        eval_hands = [
            hands.reshape(-1, all_hands, 3)[:, ::i + 1][:, :2].reshape(-1, 6)
            for i in xrange(num_players)
        ]

        #calculate 6card bonuses
        evaluator = Evaluator()

        #This is the main bottleneck in the simulator
        #The only real way to resolve it is to rebuild the deuces library's
        #hand evaluator to process arrays of hands rather than one at a time,
        #which is currently beyond the scope of this project

        for i in xrange(num_players):
            six_card_multipliers[:, i] = np.apply_along_axis(
                evaluator._six, 1, eval_hands[i])

        #Map hand values to bonus payouts

        SC_MAX_STRAIGHT_FLUSH = evaluator.table.MAX_STRAIGHT_FLUSH
        SC_MAX_QUADS = evaluator.table.MAX_FOUR_OF_A_KIND
        SC_MAX_FULL_HOUSE = evaluator.table.MAX_FULL_HOUSE
        SC_MAX_FLUSH = evaluator.table.MAX_FLUSH
        SC_MAX_STRAIGHT = evaluator.table.MAX_STRAIGHT
        SC_MAX_TRIPS = evaluator.table.MAX_THREE_OF_A_KIND

        #6-Card Bonus Payout table
        #Worse than trips  -1
        #Trips              5
        #Straight           10
        #Flush              15
        #Full House         25
        #Quads              50
        #Straight Flush     200
        #Royal Flush        1000

        six_card_multipliers[:] = np.where(
            six_card_multipliers > SC_MAX_TRIPS, -1,
            np.where(
                six_card_multipliers > SC_MAX_STRAIGHT, 5,
                np.where(
                    six_card_multipliers > SC_MAX_FLUSH, 10,
                    np.where(
                        six_card_multipliers > SC_MAX_FULL_HOUSE, 15,
                        np.where(
                            six_card_multipliers > SC_MAX_QUADS, 25,
                            np.where(
                                six_card_multipliers > SC_MAX_STRAIGHT_FLUSH,
                                50,
                                np.where(six_card_multipliers > 1, 200,
                                         1000)))))))

        return multipliers
예제 #25
0
    for card in hole_card + board:
        deck.remove_card(card)
    board_full = board + deck.draw(5 - len(board))
    opponents_hole = [deck.draw(2) for i in range(nb_player - 1)
                      ]  #[unused_cards[2 * i:2 * i + 2]
    opponents_score = [
        evaluator.evaluate(board_full, hole) for hole in opponents_hole
    ]  #[HandEvaluator.eval_hand(hole, community_card) for hole in opponents_hole]
    my_score = evaluator.evaluate(
        board_full,
        hole_card)  #HandEvaluator.eval_hand(hole_card, community_card)
    return 1 if my_score < min(opponents_score) else 0


evaluator = Evaluator()
hole_card = [Card.new('9s'), Card.new('Ks')]
board = [Card.new('8d'), Card.new('Ah'), Card.new('Kh')]
nb_players = 6
nb_simulations = 10000

time_1 = time.time()
hand_equity = deuces_estimate_win_rate(nb_simulations, nb_players, hole_card,
                                       board)
print("The equity is: " + str(hand_equity * 100) + "%")
time_2 = time.time()
print("The total time taken is: " + str((time_2 - time_1) * 1000) + " [ms]")

### Getting evals/s
evaluator = Evaluator()
hole_card = [Card.new('9s'), Card.new('Ks')]
board_full = [
예제 #26
0
 def print(self):
     print(self.name + "(chips=" + str(self.stack) + "):")
     Card.print_pretty_card(self.card1)
     Card.print_pretty_card(self.card2)
예제 #27
0
def all_evaluation(full_board, evaluator):
    """
    Efficient evaluation of all possible hands on a board.
    Args:
        full_board: list of int (deuces cards). Despite its name, does not actually have to be a 5-card board (can be 3, 4, or 5 cards)
        evaluator: deuces Evaluator object 
    Returns: 
        dict of deuces cards with evaluations
    """

    all_hands = {}
    fp = flush_possible(full_board)
    ranks = ['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2']
    suits = ['s', 'c', 'd', 'h']
    equivalent_lists = []

    if fp[0] == 'n' or fp[1] == 2:
        for rank in ranks:
            this_rank = []
            for suit in suits:
                card = Card.new(rank + suit)
                if card not in full_board:
                    this_rank.append(card)
            equivalent_lists.append(this_rank)
    elif fp[1] <= 1:  #where all cards with the same rank not of the flush suit are indistinct
        altered_suits = deepcopy(suits)
        altered_suits.remove(fp[0])
        for rank in ranks:
            this_rank = []
            for suit in altered_suits:
                card = Card.new(rank + suit)
                if card not in full_board:
                    this_rank.append(card)
            equivalent_lists.append(this_rank)

            card_of_suit = Card.new(rank + fp[0])
            if card_of_suit not in full_board:
                equivalent_lists.append([card_of_suit])

    combos = combinations_with_replacement(equivalent_lists, 2)

    if fp[1] == 2:
        for combo in combos:
            for equivalent_x in combo[0]:
                for equivalent_y in combo[1]:
                    if equivalent_x != equivalent_y and (
                            Card.int_to_str(equivalent_x)[1] !=
                            Card.int_to_str(equivalent_y)[1]):
                        evaluation_most = evaluator.evaluate(
                            full_board, [equivalent_x, equivalent_y])
                        break

            for equivalent_x in combo[0]:
                for equivalent_y in combo[1]:
                    if equivalent_x != equivalent_y and (
                            Card.int_to_str(equivalent_x)[1] !=
                            Card.int_to_str(equivalent_y)[1]):
                        all_hands[tuple(sorted([equivalent_x, equivalent_y
                                                ]))] = evaluation_most
                    elif equivalent_x != equivalent_y and (
                            Card.int_to_str(equivalent_x)[1]
                            == Card.int_to_str(equivalent_y)[1]):
                        special_evaluation = evaluator.evaluate(
                            full_board, [equivalent_x, equivalent_y])
                        all_hands[tuple(sorted([equivalent_x, equivalent_y
                                                ]))] = special_evaluation

    else:
        for combo in combos:
            for equivalent_x in combo[0]:
                for equivalent_y in combo[1]:
                    if equivalent_x != equivalent_y:
                        evaluation = evaluator.evaluate(
                            full_board, [equivalent_x, equivalent_y])
                        break
            for equivalent_x in combo[0]:
                for equivalent_y in combo[1]:
                    if equivalent_x != equivalent_y:
                        all_hands[tuple(sorted([equivalent_x,
                                                equivalent_y]))] = evaluation

    return all_hands