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
def __init__(self): self.playerJustMoved = 2 self.deck = Deck() self.board = self.deck.draw(3) self.player1 = self.deck.draw(2) self.player2 = self.deck.draw(2) self.evaluator = Evaluator()
def __init__(self): self.ALL_CARDS = np.array([i for i in range(52)]) self.hands = [] self.flop = (-1, -1, -1) self.turn = -1 self.river = -1 self.eval = Evaluator()
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
class PokerState: def __init__(self): self.playerJustMoved = 2 self.deck = Deck() self.board = self.deck.draw(3) self.player1 = self.deck.draw(2) self.player2 = self.deck.draw(2) self.evaluator = Evaluator() def Clone(self): 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
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
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)
class poker_engine(): def __init__(self): self.ALL_CARDS = np.array([i for i in range(52)]) self.hands = [] self.flop = (-1, -1, -1) self.turn = -1 self.river = -1 self.eval = Evaluator() def init_game_for(self, num_players): total_cards_in_use = num_players * 2 + 5 cards = np.random.choice(self.ALL_CARDS, total_cards_in_use, replace=False) self.hands = [] for i in range(num_players): self.hands.append((cards[i * 2], cards[i * 2 + 1])) self.river = cards[-1] self.turn = cards[-2] self.flop = (cards[-3], cards[-4], cards[-5]) def get_hand_for_player(self, i): return self.hands[i] 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) def str_to_card(self, s): val = s[0] card = 0 if val == "a": card = 0 elif val == "t": card = 9 elif val == "j": card = 10 elif val == "q": card = 11 elif val == "k": card = 12 else: card = int(val) - 1 suit = s[1] if suit == "d": card += 13 if suit == "s": card += 26 if suit == "c": card += 39 return card def get_winner(self, folded): board = [self._get_deuces_card(i) for i in self.flop] board.append(self._get_deuces_card(self.turn)) board.append(self._get_deuces_card(self.river)) hands = [[ self._get_deuces_card(self.hands[h][0]), self._get_deuces_card(self.hands[h][1]) ] for h in range(len(self.hands)) if h not in folded] scores = [self.eval.evaluate(h, board) for h in hands] winner = np.argmin(scores) return winner
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)
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 __init__(self, smallBlind=1): self.deck = Deck() self.players = [] self.smallBlind = smallBlind self.bigBlind = self.smallBlind * 2 self.evaluator = Evaluator()
class Game: def __init__(self, smallBlind=1): self.deck = Deck() self.players = [] self.smallBlind = smallBlind self.bigBlind = self.smallBlind * 2 self.evaluator = Evaluator() def runGame(self): self.dealerPosition = randint(0, len(self.players)) round = 0 while len(self.players) > 1: self.runRound(round) self.removePlayerIfBankrupt() round += 1 def runRound(self, round): self.resetGame(round) self.makePlayersPayBlinds() self.doRound(self.bigBlind, True) if (self.moreThanOnePlayerInRound()): self.drawCardsAndDoRound(3) if (self.moreThanOnePlayerInRound()): self.drawCardsAndDoRound(1) if (self.moreThanOnePlayerInRound()): self.drawCardsAndDoRound(1) self.makeWinner() def removePlayerIfBankrupt(self): newPlayers = [] for player in self.players: if player.stack >= self.bigBlind: newPlayers.append(player) self.players = newPlayers def getPlayersInRoundNotInAllIn(self): return [ player for player in self.playersInRound if player not in self.playerIsAllIn ] def moreThanOnePlayerInRound(self): return len(self.playersInRound) > 1 def resetGame(self, round): print("\n\n\n ROUND", str(round + 1), "\n\n\n") self.startNewRound() self.board = [] for player in self.players: player.print() print("dealer is " + str(self.players[self.dealerPosition].name)) self.pot = 0 self.playersInRound = [] self.playersBettedCurrentRound = {} self.playerIsAllIn = set() def increaseDealerPosition(self): self.dealerPosition = (self.dealerPosition + 1) % len(self.players) 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() def makeWinner(self): # Todo: side pot if someone is all-in winner = None lowestScore = 999999 for player in self.playersInRound: score = self.evaluator.evaluate(player.getHand(), self.board) if (score < lowestScore): winner = player lowestScore = score + 0 winner.stack += self.pot print("\n\nWinner is:", winner.name, " with +", self.pot, "in pot.\n\n") self.pot = 0 def addPlayerToGame(self, player): self.players.append(player) def startNewRound(self): self.increaseDealerPosition() self.deck.shuffle() self.dealCardsToPlayers() def doRound(self, roundValue=0, preflop=False): self.roundValue = roundValue roundNr = 0 while True: for i in range(len(self.players)): i += self.dealerPosition + preflop * 3 i = i % len(self.players) player = self.players[i] if (player in self.playersInRound): if (roundNr != 0 and self.allBettedTheSame() or not self.moreThanOnePlayerInRound()): return betAmount = player.doAction( self, self.playersBettedCurrentRound[player]) self.doPlayerAction(player, betAmount) roundNr += 1 def makePlayersPayBlinds(self): for player in self.players: if (player.stack > self.smallBlind): self.playersBettedCurrentRound[player] = 0 self.playersInRound.append(player) smallBlindPLayer = self.players[(self.dealerPosition + 1) % len(self.players)] bigBlindPLayer = self.players[(self.dealerPosition + 2) % len(self.players)] self.makePlayerBet(smallBlindPLayer, self.smallBlind) self.makePlayerBet(bigBlindPLayer, self.bigBlind) def makePlayerBet(self, player, amount): actualBet = player.bet(amount) self.playersBettedCurrentRound[player] += actualBet self.pot += actualBet return actualBet def allBettedTheSame(self): playersToCheck = [ player for player in self.playersBettedCurrentRound.keys() if player not in self.playerIsAllIn ] if (len(playersToCheck) > 0): firstVal = float(self.playersBettedCurrentRound[playersToCheck[0]]) for player in playersToCheck: if (float(self.playersBettedCurrentRound[player]) != firstVal): return False return True def doPlayerAction(self, player, betAmount): if (betAmount == -1): self.playersBettedCurrentRound.pop(player, None) self.playersInRound.remove(player) print(player.name, "folded.") elif (betAmount > 0): self.makePlayerBet(player, betAmount) self.roundValue = max(self.roundValue, self.playersBettedCurrentRound[player]) self.updateAllInPlayerList(player) print(player.name, "in with", self.playersBettedCurrentRound[player], "in this round") def updateAllInPlayerList(self, player): if (player.stack == 0): self.playerIsAllIn.add(player) def dealCardsToPlayers(self): for i in range(self.dealerPosition, len(self.players) + self.dealerPosition): index = i % len(self.players) player = self.players[index] card1 = self.deck.draw()[0] card2 = self.deck.draw()[0] player.giveCards(card1, card2)
from __future__ import division from __future__ import print_function import random from collections import defaultdict, Counter from itertools import combinations from subprocess import call from deuces import Card from deuces.deck import Deck from deuces.evaluator import Evaluator evaluator = Evaluator() # class Outcome: # def __init__(self): # self.occurrences = 0 # self.probability = None # self.relations = { # 'wins_to': list(), # 'loses_to': list(), # 'ties_to': list(), # } # # def get_most_likely(self): # return # # # class ResultSet: # def __init__(self): # self.outcomes = defaultdict(Outcome)
deck = Deck() boards = [] hands = [] for i in range(n): boards.append(deck.draw(m)) hands.append(deck.draw(2)) deck.shuffle() return boards, hands n = 10000 cumtime = 0.0 evaluator = Evaluator() boards, hands = setup(n, 5) for i in range(len(boards)): start = time.time() evaluator.evaluate(boards[i], hands[i]) cumtime += (time.time() - start) avg = float(cumtime / n) print("7 card evaluation:") print("[*] Deuces: Average time per evaluation: %f" % avg) print("[*] Decues: Evaluations per second = %f" % (1.0 / avg)) ### cumtime = 0.0 boards, hands = setup(n, 4)
def create_alsm(self): # the table containing all ranks where the Ace could be in a straight, depending on the lowest card # we'll call it, ace-low-straight-map # this will be the mapping: # A3456 -> 23456 # A4567 -> 34567 # A5678 -> 45678 # A6789 -> 56789 # A789T -> 6789T # A89TJ -> 789TJ # A9TJQ -> 89TJQ # However, we should obtain the rank of the hands through calculation, # rather than store their values evaluator = Evaluator() offsuit_A3456_rank = evaluator.evaluate(create_cards(["Ah","3h","4h","5h","6h"]),[]) offsuit_A4567_rank = evaluator.evaluate(create_cards(["Ah","4h","5h","6h","7h"]),[]) offsuit_A5678_rank = evaluator.evaluate(create_cards(["Ah","5h","6h","7h","8h"]),[]) offsuit_A6789_rank = evaluator.evaluate(create_cards(["Ah","6h","7h","8h","9h"]),[]) offsuit_A789T_rank = evaluator.evaluate(create_cards(["Ah","7h","8h","9h","Th"]),[]) offsuit_A89TJ_rank = evaluator.evaluate(create_cards(["Ah","8h","9h","Th","Jh"]),[]) offsuit_A9TJQ_rank = evaluator.evaluate(create_cards(["Ah","9h","Th","Jh","Qh"]),[]) offsuit_23456_rank = evaluator.evaluate(create_cards(["2h","3h","4h","5h","6h"]),[]) offsuit_34567_rank = evaluator.evaluate(create_cards(["3h","4h","5h","6h","7h"]),[]) offsuit_45678_rank = evaluator.evaluate(create_cards(["4h","5h","6h","7h","8h"]),[]) offsuit_56789_rank = evaluator.evaluate(create_cards(["5h","6h","7h","8h","9h"]),[]) offsuit_6789T_rank = evaluator.evaluate(create_cards(["6h","7h","8h","9h","Th"]),[]) offsuit_789TJ_rank = evaluator.evaluate(create_cards(["7h","8h","9h","Th","Jh"]),[]) offsuit_89TJQ_rank = evaluator.evaluate(create_cards(["8h","9h","Th","Jh","Qh"]),[]) onsuit_A3456_rank = evaluator.evaluate(create_cards(["Ah","3h","4h","5h","6c"]),[]) onsuit_A4567_rank = evaluator.evaluate(create_cards(["Ah","4h","5h","6h","7c"]),[]) onsuit_A5678_rank = evaluator.evaluate(create_cards(["Ah","5h","6h","7h","8c"]),[]) onsuit_A6789_rank = evaluator.evaluate(create_cards(["Ah","6h","7h","8h","9c"]),[]) onsuit_A789T_rank = evaluator.evaluate(create_cards(["Ah","7h","8h","9h","Tc"]),[]) onsuit_A89TJ_rank = evaluator.evaluate(create_cards(["Ah","8h","9h","Th","Jc"]),[]) onsuit_A9TJQ_rank = evaluator.evaluate(create_cards(["Ah","9h","Th","Jh","Qc"]),[]) onsuit_23456_rank = evaluator.evaluate(create_cards(["2h","3h","4h","5h","6c"]),[]) onsuit_34567_rank = evaluator.evaluate(create_cards(["3h","4h","5h","6h","7c"]),[]) onsuit_45678_rank = evaluator.evaluate(create_cards(["4h","5h","6h","7h","8c"]),[]) onsuit_56789_rank = evaluator.evaluate(create_cards(["5h","6h","7h","8h","9c"]),[]) onsuit_6789T_rank = evaluator.evaluate(create_cards(["6h","7h","8h","9h","Tc"]),[]) onsuit_789TJ_rank = evaluator.evaluate(create_cards(["7h","8h","9h","Th","Jc"]),[]) onsuit_89TJQ_rank = evaluator.evaluate(create_cards(["8h","9h","Th","Jh","Qc"]),[]) # the dictionary defining the necessary mappings, # ace-low-straight-map alsm = { (offsuit_A3456_rank,3) : offsuit_23456_rank, (offsuit_A4567_rank,4) : offsuit_34567_rank, (offsuit_A5678_rank,5) : offsuit_45678_rank, (offsuit_A6789_rank,6) : offsuit_56789_rank, (offsuit_A789T_rank,7) : offsuit_6789T_rank, (offsuit_A89TJ_rank,8) : offsuit_789TJ_rank, (offsuit_A9TJQ_rank,9) : offsuit_89TJQ_rank, (onsuit_A3456_rank,3) : onsuit_23456_rank, (onsuit_A4567_rank,4) : onsuit_34567_rank, (onsuit_A5678_rank,5) : onsuit_45678_rank, (onsuit_A6789_rank,6) : onsuit_56789_rank, (onsuit_A789T_rank,7) : onsuit_6789T_rank, (onsuit_A89TJ_rank,8) : onsuit_789TJ_rank, (onsuit_A9TJQ_rank,9) : onsuit_89TJQ_rank } return alsm
deck = Deck() 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')]
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