def calculate_hand_strength(current_hole_cards, board_cards, full_deck): """ Implemented as described in the page 21 of the thesis in: http://poker.cs.ualberta.ca/publications/davidson.msc.pdf """ our_cards = current_hole_cards + board_cards our_cards_set = frozenset(our_cards) if len(our_cards_set) == 2: return STRENGTH_TABLE_FOR_2_CARDS[our_cards_set] else: pokereval = PokerEval() ahead = 0.0 tied = 0.0 behind = 0.0 our_rank = pokereval.evaln(our_cards) # considers all two card combinations of the remaining cards deck = list(full_deck) for card in our_cards: if card not in deck: print "Warning! Card not in deck: "+str(card)+", current_hole_cards: "+str(current_hole_cards)+", board_cards: "+str(board_cards) deck.remove(card) opponent_cards_combinations = itertools.combinations(deck, 2) for opponent_card1, opponent_card2 in opponent_cards_combinations: opponent_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board_cards) if our_rank > opponent_rank: ahead += 1.0 elif our_rank == opponent_rank: tied += 1.0 else: behind += 1.0 hand_strength = (ahead + tied/2.0) / (ahead + tied + behind) return hand_strength
def __init__(self, protocol, avatar, table_info): self.protocol = protocol self.id = table_info.get('id', 0) self.seat = table_info.get('player_seated', -1) self.seats = [0] * table_info.get('seats', 10) if self.seat != -1: self.seats[self.seat] = avatar.serial assert avatar.seat == self.seat, "as %s, ss %s" % (avatar.seat, self.seat) self.name = table_info.get('name', 'unnamed') self.betting_structure = table_info['betting_structure'] blinds, buy_ins, limit = table_info['betting_structure'].split('_') min_buy_in, max_buy_in = buy_ins.split('-') small, big = blinds.split('-') self.max_buy_in = int(max_buy_in) * 100 self.min_buy_in = int(min_buy_in) * 100 self.big_blind = int(big) * 100 self.small_blind = int(small) * 100 self.players = {avatar.serial: avatar} self.avatar = avatar self._serial_and_game_id = dict(serial=avatar.serial, game_id=self.id) self._eval = PokerEval() self.reset() self._game_state = GAME_STATE_NULL
def getValue(self, card): value = None if type(card) is str: poker_eval = PokerEval() try: value = poker_eval.string2card(card) except RuntimeError: raise UserWarning, "Invalid card %s" %(card) else: if card != PokerCards.NOCARD: value = card & PokerCards.VALUE_CARD_MASK if (value < 0) or (value >= PokerCards.NB_CARD): raise UserWarning, "Invalid card %s" %(card) value = card return value
def getValue(self, card): value = None if type(card) is str: poker_eval = PokerEval() try: value = poker_eval.string2card(card) except RuntimeError: raise UserWarning, "Invalid card %s" % (card) else: if card != PokerCards.NOCARD: value = card & PokerCards.VALUE_CARD_MASK if (value < 0) or (value >= PokerCards.NB_CARD): raise UserWarning, "Invalid card %s" % (card) value = card return value
def __init__(self, protocol, avatar, table_info): self.protocol = protocol self.id = table_info.get('id', 0) self.seat = table_info.get('player_seated', -1) self.seats = [0] * table_info.get('seats', 10) if self.seat != -1: self.seats[self.seat] = avatar.serial assert avatar.seat == self.seat, "as %s, ss %s" % (avatar.seat, self.seat) self.name = table_info.get('name', 'unnamed') self.betting_structure = table_info['betting_structure'] blinds, buy_ins, limit = table_info['betting_structure'].split('_') min_buy_in, max_buy_in = buy_ins.split('-') small, big = blinds.split('-') self.max_buy_in = int(max_buy_in)*100 self.min_buy_in = int(min_buy_in)*100 self.big_blind = int(big)*100 self.small_blind = int(small)*100 self.players = {avatar.serial: avatar} self.avatar = avatar self._serial_and_game_id = dict(serial=avatar.serial, game_id=self.id) self._eval = PokerEval() self.reset() self._game_state = GAME_STATE_NULL
def __init__(self): """This is a very simple player that demonstrates the API and is a good template for getting started """ # my name self.name = "theBostonDerby" self.reset(False,[]) # game state variables -- these are updated by the engine which # own internal representation. so if you modify them, they'll just # be reset. we recommend leaving their init as is self.hand = None self.stack = None self.pip = None self.button = None self.opponent = None self.bb = None self.sb = None self.hands_played = None self.last_hand = 0 self.board = None self.legal = None self.actions = None self.last = None self.pot = None self.ev_calc = PokerEval() self.ev = 0 self.bound = 0 self.bot = BaseBot() self.LOW = .02 self.MID = .08 self.HIGH = .15
def __init__(self): self.hand_groups = { "A":["AA", "AKs", "KK"], "B":["AK", "QQ"], "C":["JJ", "TT"], "D":["AQs", "AQ", "AJs", "99", "88"], "E":["AJ","ATs","KQs", "77","66","55"], "F":["AT","KQ","KJs","QJs","44","33","22"], "G":["A9s","A8s","A7s","A6s","A5s","A4s","A3s","A2s","KTs","QTs","JTs","J9s","T9s","98s"], "H":["KJ","KT","QJ","J8s","T8s","87s","76s"] } self.hand_values = {"A":13,"K":12,"Q":11,"J":10, "T":9,"9":8,"8":7,"7":6,"6":5,"5":4,"4":3,"3":2,"2":1} self.odds_map = { "flop":{1:0.045,2:0.088,3:0.13,4:0.172,5:0.212,6:0.252,7:0.29,8:0.327,9:0.364,10:0.399,11:0.433,12:0.467,13:0.499,14:0.53,15:0.561,16:0.59,17:0.618}, "turn":{1:0.023,2:0.045,3:0.68,4:0.091,5:0.114,6:0.136,7:0.159,8:0.182,9:0.205,10:0.227,11:0.25,12:0.273,13:0.295,14:0.318,15:0.341,16:0.364,17:0.386} } self.eval = PokerEval()
def __init__(self, pname): self.history = [{}, {}, {}, {}] for a in range(4): # [BET,CALL,CHECK,RAISE]: for s in range(4): self.history[s][a] = [] self.pname = pname self.pokereval = PokerEval() self.showStats = {}
def __init__(self, had_values, hand, board): self.eval = PokerEval() self.hand_values = { "A": 13, "K": 12, "Q": 11, "J": 10, "T": 9, "9": 8, "8": 7, "7": 6, "6": 5, "5": 4, "4": 3, "3": 2, "2": 1 } self.hand = hand self.board = board
def calculate_hand_strength(current_hole_cards, board_cards, full_deck): """ Implemented as described in the page 21 of the thesis in: http://poker.cs.ualberta.ca/publications/davidson.msc.pdf """ our_cards = current_hole_cards + board_cards our_cards_set = frozenset(our_cards) if len(our_cards_set) == 2: return STRENGTH_TABLE_FOR_2_CARDS[our_cards_set] else: pokereval = PokerEval() ahead = 0.0 tied = 0.0 behind = 0.0 our_rank = pokereval.evaln(our_cards) # considers all two card combinations of the remaining cards deck = list(full_deck) for card in our_cards: if card not in deck: print "Warning! Card not in deck: " + str( card) + ", current_hole_cards: " + str( current_hole_cards) + ", board_cards: " + str( board_cards) deck.remove(card) opponent_cards_combinations = itertools.combinations(deck, 2) for opponent_card1, opponent_card2 in opponent_cards_combinations: opponent_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board_cards) if our_rank > opponent_rank: ahead += 1.0 elif our_rank == opponent_rank: tied += 1.0 else: behind += 1.0 hand_strength = (ahead + tied / 2.0) / (ahead + tied + behind) return hand_strength
class EvalDraws: def __init__(self, had_values, hand, board): self.eval = PokerEval() self.hand_values = {"A":13,"K":12,"Q":11,"J":10, "T":9,"9":8,"8":7,"7":6,"6":5,"5":4,"4":3,"3":2,"2":1} self.hand = hand self.board = board def convertHandValue(self, cards): deck = [] for card in cards: deck.append(self.hand_values[card[0]]) return sorted(deck) def lookForDraws(self): h = self.hand.split(" ") b = self.board.split(" ") cards = h + b has_flush = self.lookForFlushDraw(cards) if has_flush != False: return has_flush has_straight = self.lookForStraightDraw(cards, False) if has_straight != False: return has_straight return False def lookForFlushDraw(self, cards): suits = {"s":0,"c":0,"h":0,"d":0} for card in cards: if card != "__": suits[card[1]] += 1 for suit in suits: if suits[suit] > 3: has_straight = self.lookForStraightDraw(cards, True) if has_straight != False: return "%s%s" %(has_straight, "Flush") return "FlushDraw" return False def lookForStraightDraw(self, cards, flush = False): if flush != False: deck = sorted(self.eval.string2card(cards)) else: deck = self.convertHandValue(cards) for k,v in enumerate(deck): max_len = 3 if (k + max_len) < len(deck) : my_range = range(v, (v + (max_len + 1))) if deck[k+max_len] == my_range[len(my_range) - 1]: return "OpenEndedStraight" elif deck[k+max_len] == ((my_range[len(my_range) - 1] +1) or (my_range[len(my_range) - 1] - 1)): return "GutShotStraight" return False
def __init__(self): """This is a very simple player that demonstrates the API and is a good template for getting started """ # my name self.name = "theBostonDerby" self.restart() # game state variables -- these are updated by the engine which # own internal representation. so if you modify them, they'll just # be reset. we recommend leaving their init as is self.hand = None self.stack = None self.pip = None self.button = None self.opponent = None self.bb = None self.sb = None self.hands_played = None self.opp_last_stack = self.stack self.board = None self.legal = None self.actions = None self.last = None self.pot = None self.ev_calc = PokerEval() self.ev = 0 self.bot = None self.unlimited = True self.low_chip_bot = None self.high_chip_bot = None self.bot_to_use = None self.last_name = "" self.last_hand = 0 self.my_stack = 400 self.opp_stack = 400 if hasattr(self,"bots"): for b in self.bots: b.losses = 0 b.games_played = 0 self.bot = self.bots[0] self.index = 0 else: self.bots = None
def GET(self): input = web.input() web.header("Content-Type", "text/plain") defaultParams = { "game": "holdem", "pockets": [], "board": [], "dead": [], "iterations": 10000 } kwargs = defaultParams jsonp = None for key in input: value = input[key] if key == "jsoncallback": jsonp = value elif key in ["game", "pockets", "board", "dead", "iterations"]: kwargs[key] = json.read(value) cards = [] for pocket in kwargs["pockets"]: cards.extend(pocket) cards.extend(kwargs["board"]) cards.extend(kwargs["dead"]) duplicate = set( filter(lambda card: (card != "__" and cards.count(card) > 1), cards)) if len(duplicate) > 0: poker_eval_result = { "error": "duplicate cards: %s" % string.join(duplicate) } else: params = apply_game_params(**kwargs) try: poker_eval_result = PokerEval().poker_eval(**params) except Exception, e: poker_eval_result = {"error": str(e)}
import eval7 # https://pypi.org/project/eval7/ from pprint import pprint import sys import datetime sys.path.insert(0, ".") sys.path.insert(0, ".libs") from pokereval import PokerEval from tqdm import tqdm import traceback from operator import add pokereval = PokerEval() ''' full flop: 52*51*50/6 = 22,100 rainbow : 2197(given three color) * 4 (C1,4) = 8788 39% TwoColor: 2*(13*12/2)*13* 6 (C2,4) = 12168 55% OneColor: 13*12*11/6 * 4 (C1,4) = 1144 5.2% ''' # hr1 3-bet for value # hr2 3-bet for lesser value # hr3 for call hr1 = eval7.HandRange("TT+, AQ+, KQ+") # 78 combo hr2 = eval7.HandRange("77+, A9+, KT+, QT+, JT, T9s, 98s, 87s, 76s, 65s") hr3 = eval7.HandRange( "22+, A7o+, KT+, QT+, JT, T9, 98s, 87s, 76s, 65s, A2s+, K9s, K8s, Q9s, Q8s, \ 64s, 75s, 86s, 97s, T8s, J9s")
class Strategy: def __init__(self): self.pokereval = PokerEval() self.handRank = None def evaluateOdds(self, game): self.evaluatePocketCards3(game) self.evalHand(game) #raise NotImplementedError("evaluateOdds not implemented in subclass") def getMove(self, game): raise NotImplementedError("getMove not implemented in subclass") def evaluatePocketCards2(self, game): return TwoPocketLookup.evalPocket(game.holeCard1, game.holeCard2) def evaluatePocketCards3(self, game): return ThreePocketLookup.evalPocket(game.holeCard1, game.holeCard2) def evalHand(self, game, oppEvs = {}): hand = [game.holeCard1.stringValue, game.holeCard2.stringValue] if game.street==PREFLOP: if game.activePlayers == 2: ev = self.evaluatePocketCards2(game) print "TWO PLAYER UNKNOWN OPP EV: ", ev #determine which player is still in if game.leftOpp.active == 1: p = game.leftOpp else: p = game.rightOpp #get their range of hands if p.name in oppEvs.keys(): pEV = oppEvs[p.name] if pEV[0] != -1: p.handRange = reduce(lambda x,y:x+y, TwoPocketLookup.lookupvalue[max([int(pEV[0]-pEV[1]),0]):min([int(pEV[0]+pEV[1]+1),1000])]) if len(p.handRange) == 0: p.handRange = [(255,255)] wins = 0 iters = ITERATIONS/len(p.handRange) num_hands = 0 for h in p.handRange: ev = self.pokereval.poker_eval(game="holdem",pockets=[hand,list(h)],dead=[],board=game.boardCards,iterations=iters) wins += ev['eval'][0]['winhi']+ev['eval'][0]['tiehi']/2.0 num_hands+=1 ev = 1000 * wins/float(num_hands*iters) print "TWO PLAYER EDUCATED EV:", ev else: #3 active players ev = self.evaluatePocketCards3(game) print "THREE PLAYER UNKNOWN OPP EV: ", ev game.leftOpp.handRange = [(255,255)] game.rightOpp.handRange = [(255,255)] if game.leftOpp.name in oppEvs.keys(): pEV = oppEvs[game.leftOpp.name] if pEV[0] != -1: game.leftOpp.handRange = reduce(lambda x,y:x+y, ThreePocketLookup.lookupvalue[max([int(pEV[0]-pEV[1]),0]):min([int(pEV[0]+pEV[1]+1),1000])]) if game.rightOpp.name in oppEvs.keys(): pEV = oppEvs[game.rightOpp.name] if pEV[0] != -1: game.rightOpp.handRange = reduce(lambda x,y:x+y, ThreePocketLookup.lookupvalue[max([int(pEV[0]-pEV[1]),0]):min([int(pEV[0]+pEV[1]+1),1000])]) if game.leftOpp.handRange !=[(255,255)] or game.rightOpp.handRange !=[(255,255)]: wins = 0 samples = 3000 num_hands = 0 iters = ITERATIONS/samples for i in range(samples): p1 = list(random.choice(game.leftOpp.handRange)) p2 = list(random.choice(game.rightOpp.handRange)) pockets = [hand,p1,p2] ev = self.pokereval.poker_eval(game="holdem",pockets=pockets,dead=[],board=game.boardCards,iterations=iters) wins += ev['eval'][0]['winhi'] + ev['eval'][0]['tiehi']/2.0 num_hands += 1 ev = 1000 * wins/float(num_hands*iters) print "THREE PLAYER EDUCATED EV: ", ev else: #post-flop if game.activePlayers == 3: # wins = 0 # wins1 = 0 # wins2 = 0 # samples = 3000 # num_hands = 0 # num_hands1 = 0 # num_hands2 = 0 # iters = ITERATIONS/samples # for i in range(samples): # #get random pockets from both players # p1 = list(game.leftOpp.handRange[random.randrange(len(game.leftOpp.handRange))]) # p2 = list(game.rightOpp.handRange[random.randrange(len(game.rightOpp.handRange))]) # pockets = [hand,p1,p2] # ev = self.pokereval.poker_eval(game="holdem",pockets=pockets,dead=[],board=game.boardCards,iterations=iters) # tempWins1 = ev['eval'][1]['winhi'] + ev['eval'][1]['tiehi']/2.0 # tempWins2 = ev['eval'][2]['winhi'] + ev['eval'][2]['tiehi']/2.0 # tempEV1 = 1000*tempWins1/iters # tempEV2 = 1000*tempWins2/iters # #check if opponent calculated evs are within their predicted evs by the archive # if game.leftOpp.name in oppEvs.keys(): # if tempEV1 > (oppEvs[game.leftOpp.name][0] - oppEvs[game.leftOpp.name][1]) and tempEV1 < (oppEvs[game.leftOpp.name][0] + oppEvs[game.leftOpp.name][1]): # wins1 += tempWins1 # num_hands1 += 1 # else: # wins1 += tempWins1 # num_hands1 += 1 # if game.rightOpp.name in oppEvs.keys(): # if tempEV2 > (oppEvs[game.rightOpp.name][0] - oppEvs[game.rightOpp.name][1]) and tempEV2 < (oppEvs[game.rightOpp.name][0] + oppEvs[game.rightOpp.name][1]): # wins2 += tempWins2 # num_hands2 += 1 # else: # wins2 += tempWins2 # num_hands2 += 1 # wins += ev['eval'][0]['winhi'] + ev['eval'][0]['tiehi']/2.0 # num_hands += 1 # ev = 1000*wins/float(num_hands*iters) # if num_hands1 > 0: # ev1 = 1000*wins1/float(num_hands1*iters) # else: # ev1 = -1 # if num_hands2 >0: # ev2 = 1000*wins2/float(num_hands2*iters) # else: # ev2 = -1 # # ###unused except for printing # naiveEV = self.pokereval.poker_eval(game="holdem",pockets=[hand,[255,255],[255,255]],dead=[],board=game.boardCards,iterations = ITERATIONS) # naiveEV = 1000*(naiveEV['eval'][0]['winhi'] + naiveEV['eval'][0]['tiehi']/2.0)/float(ITERATIONS) # print "OPPEV KEYS:", oppEvs.keys(), "left:", game.leftOpp.name, "right", game.rightOpp.name # if game.leftOpp.name in oppEvs.keys(): # LEV = oppEvs[game.leftOpp.name] # else: # LEV = -1 # if game.rightOpp.name in oppEvs.keys(): # REV = oppEvs[game.rightOpp.name] # else: # REV = -1 # ### # # # print "THREE PLAYERS:" # print "My naive ev:", naiveEV, " educated ev:", ev # print game.leftOpp.name, " ev:", LEV, " educated ev:", ev1 # print game.rightOpp.name, " ev:", REV, " educated ev:", ev2 pockets = [hand,[255,255],[255,255]] elif game.activePlayers == 2: # if game.leftOpp.active == 1: # p = game.leftOpp # else: # p = game.rightOpp # ## if p.handRange != [(255,255)]: # wins = 0 # wins1 = 0 # samples = 1000 # num_hands = 0 # num_hands1 = 0 # iters = ITERATIONS/samples # for i in range(samples): # if len(p.handRange)>1: # p1 = list(p.handRange[random.randrange(len(p.handRange))]) # pockets = [[255,255],p1] # ev = self.pokereval.poker_eval(game="holdem",pockets=pockets,dead=[],board=game.boardCards,iterations=iters) # tempWins1 = ev['eval'][1]['winhi'] + ev['eval'][1]['tiehi']/2.0 # tempEV1 = 1000 * tempWins1/float(iters) # #check if those possible cards in hand range give an EV that is in range we expect from history # if p.name in oppEvs.keys(): # if oppEvs[p.name][0] != -1: # if tempEV1 > (oppEvs[p.name][0] - oppEvs[p.name][1]) and tempEV1 < (oppEvs[p.name][0] + oppEvs[p.name][1]): # wins1 += tempWins1 # num_hands1 += 1 # else: # wins1 += tempWins1 # num_hands1 += 1 # print "REMOVING ELEMNT", p1 # p.handRange.remove((p1[0],p1[1])) # #update our EV # pockets = [hand, p1] # ev = self.pokereval.poker_eval(game="holdem",pockets=pockets,dead=[],board=game.boardCards,iterations=iters) # wins += ev['eval'][0]['winhi'] + ev['eval'][0]['tiehi']/2.0 # num_hands += 1 # ev = 1000*wins/float(num_hands*iters) # if num_hands1 > 0: # ev1 = 1000*wins1/float(num_hands1*iters) # else: # ev1 = -1 ## # ###only used in printing # naiveEV = self.pokereval.poker_eval(game="holdem",pockets=[hand,[255,255]],dead=[],board=game.boardCards,iterations = ITERATIONS) # naiveEV = 1000*(naiveEV['eval'][0]['winhi'] + naiveEV['eval'][0]['tiehi']/2.0)/float(ITERATIONS) # if p.name in oppEvs.keys(): # PEV = oppEvs[p.name] # else: # PEV = -1 # # print "TWO PLAYERS:" # print "my naive ev:", naiveEV, " educated ev:", ev # print p.name, " ev:", PEV, " educated ev:", ev1 # print "gameboard", game.boardCards # # else: pockets = [hand,[255,255]] else: # shouldn't get here, but just in case print "Only 1 active player! EV is 1" return 1000 ev = self.pokereval.poker_eval(game="holdem", pockets = pockets, dead=[], board=game.boardCards, iterations = ITERATIONS)['eval'][0]['ev'] # print "HAND", hand, "BOARD", board, "EV", ev return ev #Bet or raise the minimum amount, or times some multiplier # If min raise amount is to raise to 4, multiplier of 3 says to raise to # 3*4=12 def pushMin(self, game, m=1): move = Move(CALL) for la in game.legalActions: if la[0] == "BET": return Move(BET, min(game.me.getAllIn(),int(la[1])*m)) if la[0] == "RAISE": return Move(RAISE, min(game.me.getAllIn(),int(la[1])*m)) ## print "PUSH MIN MOVE:", move return move ##If can check, then check. Otherwise call up to m def maxRisk(self, game, m): if "CHECK" in [la[0] for la in game.legalActions]: return Move(CHECK) if game.lastBet <= m: return Move(CALL) return Move(FOLD) def betPot(self, game, m): move = Move(CALL) amt = min(game.me.getAllIn(),m*(game.pot + game.leftOpp.pip + game.rightOpp.pip + game.me.pip)) for la in game.legalActions: if la[0] == "BET": return Move(BET, amt) if la[0] == "RAISE": return Move(RAISE, amt) ## print "PUSH MIN MOVE:", move return move def raiseBet(self, game, m): move = Move(CALL) highpip2 = sorted([game.me.pip, game.leftOpp.pip, game.rightOpp.pip])[1] amt = 3*(game.lastBet-highpip2) amt = max(game.pot, amt) amt = min(game.me.getAllIn(),m*amt) for la in game.legalActions: if la[0] == "RAISE": return Move(RAISE, amt) return move
def __init__(self): self.pokereval = PokerEval() self.handRank = None
# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. # # http://gna.org/support/?1823 # import sys sys.path.insert(0, ".") sys.path.insert(0, ".libs") from pokereval import PokerEval pokereval = PokerEval() result = pokereval.poker_eval(game="holdem", fill_pockets=1, pockets=[["As", "3s"], ["__", "__"]], dead=[], board=["Ad", "Qs", "2c", "Ac", "Kc"]) assert result == { 'info': (990, 0, 1), 'eval': [{ 'winlo': 0, 'tielo': 0, 'winhi': 877, 'scoop': 877, 'loselo': 0, 'ev': 903,
class TheBostonDerby: def __init__(self): """This is a very simple player that demonstrates the API and is a good template for getting started """ # my name self.name = "theBostonDerby" self.restart() # game state variables -- these are updated by the engine which # own internal representation. so if you modify them, they'll just # be reset. we recommend leaving their init as is self.hand = None self.stack = None self.pip = None self.button = None self.opponent = None self.bb = None self.sb = None self.hands_played = None self.opp_last_stack = self.stack self.board = None self.legal = None self.actions = None self.last = None self.pot = None self.ev_calc = PokerEval() self.ev = 0 self.bot = None self.unlimited = True self.low_chip_bot = None self.high_chip_bot = None self.bot_to_use = None self.last_name = "" self.last_hand = 0 self.my_stack = 400 self.opp_stack = 400 if hasattr(self,"bots"): for b in self.bots: b.losses = 0 b.games_played = 0 self.bot = self.bots[0] self.index = 0 else: self.bots = None def reset(self, won, last_hand): """Reset accepts a boolean indicating whether you won a match and provides the last hand if you want to update any statistics from it """ #print "game over", last_hand self.calculate_stats(last_hand) self.last_hand = 0 self.my_stack = 400 self.opp_stack = 400 if self.bots: self.bot.losses += not won self.bot.games_played += 1 #print self.bot.losses if (self.bot.games_played < 6 and self.bot.losses > 2) or (self.bot.games_played >= 6 and self.bot.losses/float(self.bot.games_played) > .5): self.index += 1 #print self.index if self.index >= len(self.bots): self.index = 0 self.bots = sorted(self.bots,key=lambda x:x.losses) #print [(b.name,b.losses) for b in self.bots] self.bot = self.bots[self.index] #print "using bot", self.bot.name def restart(self): self.my_stats = { 'hands':0, '^VPIP':[0,0,0,0], 'VPIP':[0,0,0,0], # amount voluntarily placed in pot '^INCR':[0,0,0,0], 'INCR':[0,0,0,0], # frequency of raises '^AF':0, '_AF':0, 'AF':0, # aggression frequency = (bets + raises)/(checks + calls) #pre flop '^ST':0, 'ST':0, # steals = how often he raises when has first action '^LMP':0, 'LMP':0, # how often opponent calls '_3B':0, '^FBB':0, 'FBB':0, # how often, after small blind raises, big blind folds '^3B':0, '3B':0, # how often, after small blind raises, big blind raises '_4B':0, '^F3B':0, 'F3B':0, # how often, after small blind raises and then big blind raises, small blind folds '^4B':0, '4B':0, # how often, the small bind raises in above circumstances '_F4B':0, '^F4B':0, 'F4B':0, #how often big blind folds to 4B #flop '_COB':0, '^COB':0, 'COB':0, # continuation bet = how often betting after betting/raising on preflop '_FCOB':0, '^FCOB':0, 'FCOB':0, # how often opp folds to a continuation bet #turn '_2COB':0, '^2COB':0, '2COB':0, # how often opp cb twice, once on flop and once on turn '_F2COB':0, '^F2COB':0, 'F2COB':0, # how often opp folds to 2nd continuation bet. '_CHBR':[0,0,0,0], '^CHBR':[0,0,0,0], 'CHBR':[0,0,0,0], # how often opp check raises '^HAI':0, 'HAI':0, # percent hands won by going all in '^HPFBB':0, #number of hands that go to the flop as BB 'HPFBB':0, '^HPFSB':0, #number of hands that go to the flop as SB 'HPFSB':0, '^HPT':0, #number of hands that go to the turn 'HPT':0, '^HPR':0, #number of hands that go to the river 'HPR':0 } self.opp_stats = self.my_stats.copy() self.opp_stats['^VPIP'] = [0,0,0,0] self.opp_stats['VPIP'] = [0,0,0,0] self.opp_stats['^INCR'] = [0,0,0,0] self.opp_stats['INCR'] = [0,0,0,0] self.opp_stats['_CHBR'] = [0,0,0,0] self.opp_stats['^CHBR'] = [0,0,0,0] self.opp_stats['CHBR'] = [0,0,0,0] self.opp_hand = 100.0 self.hands_played_against = 0 self.cory_stats = {'^A':0, 'A':0, '^W':0, 'W':0, '^C':0, 'C':0} def card2str(self, c): return c.__str__() def calculate_ev(self): #print self.board if not self.board.flop(): suited = self.hand[0].suit != self.hand[1].suit #0 means suited, 1 means not if self.hand[0].rank > self.hand[1].rank: card_2,card_1 = self.hand else: card_1,card_2 = self.hand #print "looking up (%d,%d,%d)" % (card_1.rank-2,card_2.rank-card_1.rank,suited) ev = 100.0 - lookuphand[card_1.rank-2][card_2.rank-card_1.rank][suited] else: board = [self.card2str(c) for c in self.board.flop()] my_hand = [self.card2str(c) for c in self.hand] dead = my_hand if self.board.river(): board += [self.card2str(self.board.turn()), self.card2str(self.board.river())] dead += board[:] elif self.board.turn(): board += [self.card2str(self.board.turn()), '__'] dead += board[:-1] else: board += ['__','__'] dead += board[:-2] #self.opp_hand == 100.0 if self.opp_hand == 100.0: ev = self.ev_calc.poker_eval(game="holdem",pockets=[[self.card2str(c) for c in self.hand],['__','__']],dead=[],board=board,iterations=1000) ev = ev['eval'][0]['ev']/10.0 else: hands = reduce(lambda x,y:x+y, lookupvalue[:int(self.opp_hand*10)]) wins = 0 iters = 30 num_hands = 0 for hand in hands: if hand[0] in dead or hand[1] in dead: continue ev = self.ev_calc.poker_eval(game="holdem",pockets=[my_hand,list(hand)],dead=[],board=board,iterations=iters) wins += ev['eval'][0]['winhi']+ev['eval'][0]['tiehi']/2.0 num_hands += 1 ev = wins/float(num_hands*iters) self.ev = ev/100.0 def classify(self, act): action = None if isinstance(act, Post): action = POST elif isinstance(act, Check): action = CHECK elif isinstance(act, Bet): action = BET elif isinstance(act, Raise): action = RAISE elif isinstance(act, Fold): action = FOLD elif isinstance(act, Call): action = CALL elif isinstance(act, Show): action = SHOW elif isinstance(act, Deal): action = DEAL elif isinstance(act, Won): action = WON else : if DEBUG: print "umm, unknown action taken!", act return action def calculate_stats(self,last): #parse all actions in previous hand into useful information if DEBUG: print "calculating stats for hand: ", last if len(last) < 3: #print "umm, short hand?!", last return tallies = {'raises':0, 'bets':0, 'folds':0, 'calls':0, 'checks':0, 'pip':0} my_actions = dict(zip(range(4),[tallies.copy() for x in range(4)])) opp_actions = dict(zip(range(4),[tallies.copy() for x in range(4)])) hand = deque(last[:]) act = hand.popleft() #first action is always sb posting their blind if act[0] == self.name: my_actions['position'] = True #position = 1 means sb, 0 means BB opp_actions['position'] = False #if i'm not small blind, opp must be my_actions[0]['pip'] = act[1].amount opp_actions[0]['pip'] = 2 * act[1].amount else: my_actions['position'] = False #position = 1 means sb, 0 means BB opp_actions['position'] = True #if i'm not small blind, opp must be opp_actions[0]['pip'] = act[1].amount my_actions[0]['pip'] = 2 * act[1].amount act = hand.pop() my_actions['won'] = act[0] == self.name opp_actions['won'] = not my_actions['won'] won_amount = act[1].amount/2.0 this_hand = {self.name:my_actions, self.opponent['name']:opp_actions, 'steal':False, 'limp':False} hand.popleft() # second action is always bb posting, and is useless street = 0 #0 is preflop, 1 is flop, 2 is turn and 3 is river first = True pot = 0 pip = {self.name:0, self.opponent['name']:0} while len(hand) > 0 : act = hand.popleft() #print "parsing action: ",act if act[0] == 'Dealer': #then this action corresponds to changing street street += 1 if street == 1: if opp_actions['position']: self.opp_stats['^HPFSB'] += 1 else: self.opp_stats['^HPFBB'] += 1 elif street == 2: self.opp_stats['^HPT'] += 1 elif street == 3: self.opp_stats['^HPR'] += 1 continue #print "on street: ", street action = self.classify(act[1]) if first: first = False if action == RAISE: this_hand['steal'] = True elif action == CALL: this_hand['limp'] = True if act[0] in [self.name, self.opponent['name']]: if action == RAISE: this_hand[act[0]][street]['raises'] += 1 this_hand[act[0]][street]['pip'] = act[1].amount elif action == CHECK: this_hand[act[0]][street]['checks'] += 1 elif action == CALL: this_hand[act[0]][street]['calls'] += 1 this_hand[act[0]][street]['pip'] = this_hand[self.name if act[0] == self.opponent['name'] else self.opponent['name']][street]['pip'] elif action == FOLD: this_hand[act[0]][street]['folds'] += 1 if street == 0 and act[0] == self.name: if opp_actions['position']: self.opp_stats['^HPFSB'] += 1 else: self.opp_stats['^HPFBB'] += 1 elif action == BET: this_hand[act[0]][street]['bets'] += 1 if street == FLOP and act[0] == self.opponent['name']: pot = sum([my_actions[x]['pip'] for x in range(4)])+sum([opp_actions[x]['pip'] for x in range(4)]) if act[1].amount < .5*pot: self.cory_stats['^W'] += 5 elif act[1].amount > pot: self.cory_stats['^A'] += 10 if my_actions['position']: #he's BB self.cory_stats['^A'] += 5 this_hand[act[0]][street]['pip'] = act[1].amount elif DEBUG: print "unknown player: ",act[0] #update relevant statistics #print "tallied up my actions",my_actions #print "tallied up opp actions",opp_actions self.my_stats['hands'] += 1 self.opp_stats['hands'] += 1 if opp_actions['won']: hand = last[:] hand.pop() act = hand.pop() while act[0] != self.opponent['name'] or isinstance(act[1],Show) or isinstance(act[1],Won): act= hand.pop() action = self.classify(act[1]) if action == RAISE: self.cory_stats['^A'] += 20 if action in [BET, RAISE, CALL]: if act[1].amount >= min(self.opp_stack,self.my_stack): self.cory_stats['^A'] += 10 self.opp_stats['^HAI'] +=1 else: self.cory_stats['^C'] += 20 if my_actions['won']: self.my_stack += won_amount self.opp_stack -= won_amount else: self.my_stack -= won_amount self.opp_stack += won_amount self.update_stats(self.opp_stats, my_actions, opp_actions, this_hand['steal'], this_hand['limp']) self.update_stats(self.my_stats, opp_actions, my_actions, this_hand['steal'], this_hand['limp']) self.calc_cory(self.cory_stats, my_actions, opp_actions, this_hand['steal'], this_hand['limp']) def calc_cory(self, stats, me, opp, steal, limp): stats['^A'] += 5*sum([opp[x][y] for x in range(4) for y in ['bets', 'raises']]) stats['^A'] += 10*sum([max(opp[x]['raises']-1,0) for x in range(4)]) stats['^C'] += 5*sum([opp[x][y] for x in range(4) for y in ['bets', 'raises', 'calls']]) stats['^C'] += 10*sum([opp[x]['calls']>0 for x in range(4) if opp[x]['raises']>0]) stats['^W'] += 5*(limp and opp['position']) stats['^W'] += 3*(opp[PREFLOP]['folds']>0) stats['^W'] += 5*(sum([opp[x]['folds'] for x in [FLOP,TURN,RIVER]])>0) stats['^A'] += 20*sum([1 for x in [FLOP,TURN,RIVER] if opp[x]['checks']>0 and me[x]['bets'] >0 and opp[x]['raises']>0]) stats['A'] = stats['^A']/float(self.opp_stats['hands']) stats['C'] = stats['^C']/float(self.opp_stats['hands']) stats['W'] = stats['^W']/float(self.opp_stats['hands']) def new_hand(self): return def update_stats(self,stats,me,opp,steal,limp): this_hand = {} vpip_den = [stats['hands'], stats['^HPFBB']+stats['^HPFSB'], stats['^HPT'], stats['^HPR']] for street in range(4): if opp[street]['raises'] or opp[street]['bets'] or opp[street]['calls']: stats['^VPIP'][street] += 1 if opp[street]['raises']: stats['^INCR'][street] += 1 stats['VPIP'][street] = stats['^VPIP'][street]/float(vpip_den[street]) if (vpip_den[street] and vpip_den[street] >0) else None stats['INCR'][street] = stats['^INCR'][street]/float(vpip_den[street]) if (vpip_den[street] and vpip_den[street] >0) else None this_hand['^AF'] = sum([opp[x]['raises'] + opp[x]['bets'] for x in [FLOP, TURN, RIVER]]) this_hand['_AF'] = sum([opp[x]['calls'] for x in [FLOP, TURN, RIVER]]) #PREFLOP this_hand['^ST'] = steal and opp['position'] this_hand['^LMP']= limp and opp['position'] this_hand['_3B'] = steal and not opp['position'] this_hand['^FBB']= this_hand['_3B'] and opp[0]['folds'] and opp[0]['raises'] == 0 this_hand['^3B'] = this_hand['_3B'] and opp[0]['raises'] > 0 this_hand['_4B'] = this_hand['^ST'] and me[0]['raises'] > 0 this_hand['^F3B']= this_hand['_4B'] and opp[0]['folds'] and opp[0]['raises'] == 1 this_hand['^4B'] = this_hand['_4B'] and opp[0]['raises'] >= 2 this_hand['_F4B']= this_hand['^3B'] and me[0]['raises'] >= 2 this_hand['^F4B']= this_hand['_F4B']and opp[0]['folds'] and opp[0]['raises'] == 1 #FLOP this_hand['_COB'] = opp['position'] and opp[0]['raises'] > 0 and me[0]['calls']>0 and me[1]['checks']>0 this_hand['^COB'] = this_hand['_COB'] and opp[1]['bets'] > 0 this_hand['_FCOB']= not opp['position'] and me[0]['raises']>0 and opp[0]['calls']>0 and opp[1]['checks']>0 and me[1]['bets']>0 this_hand['^FCOB']= this_hand['_FCOB'] and opp[1]['folds']>0 #TURN this_hand['_2COB'] = this_hand['^COB'] and me[2]['checks']>0 this_hand['^2COB'] = this_hand['_2COB'] and opp[2]['bets']>0 this_hand['_F2COB']= this_hand['_FCOB'] and me[2]['bets']>0 this_hand['^F2COB']= this_hand['_F2COB'] and opp[2]['folds']>0 this_hand['_CHBR'] = [0,0,0,0] this_hand['^CHBR'] = [0,0,0,0] #POSTFLOP for street in [FLOP, TURN, RIVER]: this_hand['_CHBR'][street] = opp[street]['checks']>0 and me[street]['bets'] >0 this_hand['^CHBR'][street] = this_hand['_CHBR'][street] and opp[street]['raises']>0 #print "and for this hand, here are our stats:" #print this_hand for stat in stats.keys(): if this_hand.has_key(stat) and isinstance(this_hand[stat],int): stats[stat] += this_hand[stat] stats['AF'] = stats['^AF']/float(stats['_AF']) if stats['_AF'] else None stats['ST'] = stats['^ST']/float(stats['hands']) * 2.0 stats['LMP'] = stats['^LMP']/float(stats['hands']) * 2.0 stats['FBB'] = stats['^FBB']/float(stats['_3B']) if stats['_3B'] else None stats['3B'] = stats['^3B']/float(stats['_3B']) if stats['_3B'] else None stats['F3B'] = stats['^F3B']/float(stats['_4B']) if stats['_4B'] else None stats['4B'] = stats['^4B']/float(stats['_4B']) if stats['_4B'] else None stats['F4B'] = stats['^F4B']/float(stats['_F4B']) if stats['_F4B'] else None stats['COB'] = stats['^COB']/float(stats['_COB']) if stats['_COB'] else None stats['FCOB'] = stats['^FCOB']/float(stats['_FCOB']) if stats['_FCOB'] else None stats['2COB'] = stats['^2COB']/float(stats['_2COB']) if stats['_2COB'] else None stats['F2COB'] = stats['^F2COB']/float(stats['_F2COB']) if stats['_F2COB'] else None stats['HAI'] = stats['^HAI']/float(stats['hands']) stats['HPFBB'] = stats['^HPFBB']/float(stats['hands']) * 2.0 stats['HPFSB'] = stats['^HPFSB']/float(stats['hands']) * 2.0 stats['HPT'] = stats['^HPT']/float(stats['^HPFBB']+stats['^HPFSB']) if (stats['^HPFBB'] > 0 or stats['^HPFSB'] > 0) else None stats['HPR'] = stats['^HPR']/float(stats['^HPT']) if stats['^HPT'] else None for street in [FLOP, TURN, RIVER]: stats['_CHBR'][street] += this_hand['_CHBR'][street] stats['^CHBR'][street] += this_hand['^CHBR'][street] stats['CHBR'][street] = stats['^CHBR'][street]/float(stats['_CHBR'][street]) if stats['_CHBR'][street] else None def respond(self): #print self.opp_stats if self.hands_played == 0: self.bot_to_use = self.bot if self.last_name != self.opponent['name']: self.last_name = self.opponent['name'] self.restart() if self.bots: for b in self.bots: b.losses = 0 self.bot = self.bots[0] self.index = 0 if DEBUG: print self.name if DEBUG: print self.hands_played, self.last_hand, self.hands_played_against, self.hand, self.board if DEBUG: print self.actions, self.opponent if DEBUG: print self.legal self.calculate_ev() if DEBUG: print "ev=%d, pot=%d" % (self.ev*100, self.pot) if self.hands_played != self.last_hand and self.hands_played: if self.hands_played > self.last_hand: self.hands_played_against += self.hands_played - self.last_hand else: self.hands_played_against += 1 if self.hands_played >= self.last_hand + 2: #if we missed one self.calculate_stats(self.last[0]) self.calculate_stats(self.last[1]) self.last_hand = self.hands_played self.opp_hand = 100.0 self.opp_last_stack = self.opponent['stack'] + self.opponent['pip'] #self.bot.new_hand() #notify our bot of new hand if self.low_chip_bot or self.high_chip_bot: if self.low_chip_bot and self.stack + self.pip < 75: if self.low_chip_bot != self.bot_to_use: if DEBUG: print "using low stack bot" self.bot_to_use = self.low_chip_bot elif self.high_chip_bot and self.stack + self.pip > 600: if self.high_chip_bot != self.bot_to_use: if DEBUG: print "using high stack bot" self.bot_to_use = self.high_chip_bot else: if self.bot != self.bot_to_use: if DEBUG: print "using normal bot" self.bot_to_use = self.bot if not self.bot_to_use: self.bot_to_use = self.bot if DEBUG: print self.opp_stats if DEBUG: print self.opp_stack, self.my_stack if DEBUG: raw_input() action = self.bot_to_use.respond(self) if DEBUG: print "and ourbot sees action of", action return action
class PokerHandEval: def __init__(self): self.hand_groups = { "A":["AA", "AKs", "KK"], "B":["AK", "QQ"], "C":["JJ", "TT"], "D":["AQs", "AQ", "AJs", "99", "88"], "E":["AJ","ATs","KQs", "77","66","55"], "F":["AT","KQ","KJs","QJs","44","33","22"], "G":["A9s","A8s","A7s","A6s","A5s","A4s","A3s","A2s","KTs","QTs","JTs","J9s","T9s","98s"], "H":["KJ","KT","QJ","J8s","T8s","87s","76s"] } self.hand_values = {"A":13,"K":12,"Q":11,"J":10, "T":9,"9":8,"8":7,"7":6,"6":5,"5":4,"4":3,"3":2,"2":1} self.odds_map = { "flop":{1:0.045,2:0.088,3:0.13,4:0.172,5:0.212,6:0.252,7:0.29,8:0.327,9:0.364,10:0.399,11:0.433,12:0.467,13:0.499,14:0.53,15:0.561,16:0.59,17:0.618}, "turn":{1:0.023,2:0.045,3:0.68,4:0.091,5:0.114,6:0.136,7:0.159,8:0.182,9:0.205,10:0.227,11:0.25,12:0.273,13:0.295,14:0.318,15:0.341,16:0.364,17:0.386} } self.eval = PokerEval() def prepareHand(self, hand): h = hand.split(" ") if self.hand_values[h[1][0]] > self.hand_values[h[0][0]]: self.hand = "%s%s" % (h[1][0],h[0][0]) else: self.hand = "%s%s" % (h[0][0],h[1][0]) if h[0][1] == h[1][1]: self.hand += "s" def getHandGroup(self): for group in self.hand_groups: if self.hand in self.hand_groups[group]: return group return False def getHandValue(self, game, serial): hand = game.getHandAsString(serial) board = game.getBoardAsString() board_list = board.split(" ") if len(board_list) < 5: for i in range(len(board_list), 5): board_list.append("__") hand_list = hand.split(" ") cards = hand_list + board_list return self.eval.best_hand("hi", self.eval.string2card(cards), [] ) def parseHistory(self, hist): self.round_action = {} self.action2serials = { "call":[], "raise":[], "fold":[] } self.serial2action = {} ret = "" for event in hist: type = event[0] if type in ["fold","check","call","raise"]: if len(event) == 3: (action, serial, amount) = event else: (action,serial) = event amount = False ret = "action: %s, serial:%d" % (action, serial) if amount: ret += ", amount = %d" % amount self.round_action[serial] = [action, amount] else: self.round_action[serial] = [action] self.serial2action[serial] = action if action in self.action2serials.keys(): if not serial in self.action2serials[action]: self.action2serials[action].append(serial) def getPosition(self, game, serial): me = game.serial2player[serial] players = game.serialsAllSorted() for player in players: user = game.serial2player[player] user_positions = {} player_seats = {} i=1 for p in game.serialsAllSorted(): user = game.serial2player[p] player_seats[user.seat] = p max_seat = len(player_seats) early = max_seat / 3 middle = early * 2 self.my_seat = me.seat self.serial2position = {} self.position2serials = { "early":[], "middle":[], "late":[] } for p in player_seats.keys(): player_serial = player_seats[p] if i <= early: position = "early" elif i >= (early + 1) and i <= middle: position = "middle" else: position = "late" if not player_serial in self.serial2position.keys(): self.serial2position[player_serial] = position if not player_serial in self.position2serials[position]: self.position2serials[position].append(player_serial) if p == self.my_seat: self.position = position i += 1
import sys sys.path.insert(0, ".") sys.path.insert(0, ".libs") from pokereval import PokerEval from random import shuffle card1 = sys.argv[1] card2 = sys.argv[2] players = int(sys.argv[3]) iterations = int(sys.argv[4]) wins = 0 pe = PokerEval() for iter in range(0,iterations): #generate a deck deck = ['Ac', '2c', '3c', '4c', '5c', '6c', '7c', '8c', '9c', 'Tc', 'Jc', 'Qc', 'Kc', 'Ad', '2d', '3d', '4d', '5d', '6d', '7d', '8d', '9d', 'Td', 'Jd', 'Qd', 'Kd', 'Ah', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', 'Th', 'Jh', 'Qh', 'Kh', 'As', '2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', 'Ts', 'Js', 'Qs', 'Ks'] shuffle(deck) #add all players to 'pockets' pockets = [] for i in range(0,players): pockets.append([]) # Your cards
# c = copas # s = espadas # h = paus # d = ouros # Values: # 2 .. 9 # T = 10 # J, Q, K, A # Unknown = __ import timeit from pokereval import PokerEval __author__ = 'gogo40' pe = PokerEval() ranks_ = ["h", "c", "d", "s"] game_ = "holdem" iterations_ = 5000000 dead_ = [] ####################################### # h_power calculator def h_power_calc(result_): total_ = 0.0 ev_ = [] for r in result_['eval']: v = float(r['ev'])
# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. # # http://gna.org/support/?1823 # import sys sys.path.insert(0, ".") sys.path.insert(0, ".libs") from pokereval import PokerEval pokereval = PokerEval() result = pokereval.poker_eval( game="holdem", fill_pockets=1, pockets=[["As", "3s"], ["__", "__"]], dead=[], board=["Ad", "Qs", "2c", "Ac", "Kc"] ) assert result == { "info": (990, 0, 1), "eval": [ {"winlo": 0, "tielo": 0, "winhi": 877, "scoop": 877, "loselo": 0, "ev": 903, "losehi": 78, "tiehi": 35}, {"winlo": 0, "tielo": 0, "winhi": 78, "scoop": 78, "loselo": 0, "ev": 96, "losehi": 877, "tiehi": 35}, ], } result = pokereval.poker_eval( game="omaha8", fill_pockets=1,
#!/usr/bin/python from pokereval import PokerEval p = PokerEval() contador = 0 with open('./p054_poker.txt') as archivo: for juego in archivo: cartas = juego.rstrip().lower().split(' ') mano_a, mano_b = cartas[:5], cartas[5:] if p.evaln(mano_a) > p.evaln(mano_b): contador += 1 print contador
class Table(object): def __init__(self, protocol, avatar, table_info): self.protocol = protocol self.id = table_info.get('id', 0) self.seat = table_info.get('player_seated', -1) self.seats = [0] * table_info.get('seats', 10) if self.seat != -1: self.seats[self.seat] = avatar.serial assert avatar.seat == self.seat, "as %s, ss %s" % (avatar.seat, self.seat) self.name = table_info.get('name', 'unnamed') self.betting_structure = table_info['betting_structure'] blinds, buy_ins, limit = table_info['betting_structure'].split('_') min_buy_in, max_buy_in = buy_ins.split('-') small, big = blinds.split('-') self.max_buy_in = int(max_buy_in) * 100 self.min_buy_in = int(min_buy_in) * 100 self.big_blind = int(big) * 100 self.small_blind = int(small) * 100 self.players = {avatar.serial: avatar} self.avatar = avatar self._serial_and_game_id = dict(serial=avatar.serial, game_id=self.id) self._eval = PokerEval() self.reset() self._game_state = GAME_STATE_NULL def reset(self): """reseting game states for a new hand""" self.board_cards = [] self.position = -1 self._reset_players() def getBoardCards(self): """return a list of board games""" return list(map(lambda x: x & 63, self.board_cards)) def getAvatarInfo(self): """return a string of usefull information about the avatar""" return ", ".join(self._get_avatar_info()) def isInPosition(self, serial): """returs true if player with serial is in position""" return serial in self.in_game and self.position == self.in_game.index( serial) def logIt(self, astr, prefix=" [D] "): """a little helper function to log output""" self.protocol.logIt(astr, prefix=prefix) def updateSeats(self, seats): """update seat information""" for index, (old, new) in enumerate(zip(self.seats, seats)): if old == 0 and new != 0: self.addPlayer(index, new) elif old != 0 and new == 0: self.removePlayer(index) elif old != new: self.removePlayer(index) self.addPlayer(index, new) self.logIt("warning idx %s, old %s, new %s" % (index, old, new)) def addPlayer(self, index, serial): """Add player to this table""" self.seats[index] = serial # Request more information about this player if serial == self.avatar.serial: self.players[index] = self.avatar else: self.protocol.sendPacket( networkpackets.PacketPokerGetUserInfo(serial=serial)) def removePlayer(self, index): """remove player from this table""" serial = self.seats[index] self.seats[index] = 0 if serial in self.players: del self.players[serial] def updatePlayer(self, player_info): """update general palyer information (we requested them in addPlayer)""" player = self._get_or_create_player(**player_info) player.update(player_info) def updatePlayerChips(self, serial, chips, bet): """update players chips""" player = self._get_or_create_player(serial=serial) return player.updateChips(chips, bet) def updatePlayerCards(self, serial, cards): """update players cards""" player = self._get_player(serial) player.updateCards(cards) def rebuy(self, serial, amount): """update money state of player because a rebuy happend""" player = self._get_player(serial) player.rebuy(amount) def _reset_players(self): """reset player states""" for player in self.players.values(): player.reset() def highestBetNotFold(self): """returns the highest bet of all players that are not fold""" return max([0] + [ p._bet for p in self.players.values() if p.serial in self.in_game and p.notFold() ]) def inSmallBlindPosition(self): """returns True if the player in position is in small_blind position""" return len(self.in_game) > 0 and ((self.dealer + 1) % len(self.in_game)) == self.position def bigBlind(self): """returns the big_blind of the current table""" return self.big_blind or 0 def doBuyIn(self): """actually request a buy_in""" self.protocol.sendPacket( networkpackets.PacketPokerBuyIn(amount=self.max_buy_in, **self._serial_and_game_id)) self.protocol.sendPacket( networkpackets.PacketPokerAutoBlindAnte( **self._serial_and_game_id)) def doRebuy(self, amount): """actually request a rebuy""" self.protocol.sendPacket( networkpackets.PacketPokerRebuy(amount=amount, **self._serial_and_game_id)) def doSit(self): """actually request a sit""" self.protocol.sendPacket( networkpackets.PacketPokerSit(**self._serial_and_game_id)) def doSitOut(self): """actually request a sitout""" self.protocol.sendPacket( networkpackets.PacketPokerSitOut(**self._serial_and_game_id)) def doQuit(self): """actually request a table quit""" self.protocol.sendPacket( networkpackets.PacketPokerTableQuit(**self._serial_and_game_id)) def doFold(self): """actually request a fold""" self.protocol.sendPacket( networkpackets.PacketPokerFold(**self._serial_and_game_id)) def doCheck(self): """actually request a check""" self.protocol.sendPacket( networkpackets.PacketPokerCheck(**self._serial_and_game_id)) def doCall(self): """actually request a call""" self.protocol.sendPacket( networkpackets.PacketPokerCall(**self._serial_and_game_id)) def doAllIn(self): """actually raise all chips""" self.doRaise(self.avatar.getChips()) def doRaise(self, amount): """ actually request a raise by a given amount. WARNING: If the amount you requested is too low, the raise will be accepted but the minimum amount to raise will be used instead. You will be informend about the amount that is used to raise. """ self.protocol.sendPacket( networkpackets.PacketPokerRaise(amount=amount, **self._serial_and_game_id)) def explain(self, packet, state): """packets that might be interesting for the game will be handled here""" def handlePacketPokerBuyInLimits(packet): self.max_buy_in = packet.max self.min_buy_in = packet.min def handlePacketPokerSeats(packet): return self.updateSeats(packet.seats) def handlePacketPokerPlayerInfo(packet): self.updatePlayer(packet.__dict__) def handlePacketPokerPlayerChips(packet): return self.updatePlayerChips(packet.serial, chips=packet.money, bet=packet.bet) def handlePacketPokerPlayerArrive(packet): self.updatePlayer(packet.__dict__) def handlePacketPokerPlayerLeave(packet): self.removePlayer(packet.seat) def handlePacketPokerSit(packet): self._get_player(packet.serial).sit() def handlePacketPokerSitOut(packet): self._get_player(packet.serial).sitOut() def handlePacketPokerRebuy(packet): assert self.id == packet.game_id self.rebuy(packet.serial, packet.amount) def handlePacketPokerInGame(packet): assert self.id == packet.game_id self.in_game = packet.players def handlePacketPokerPosition(packet): assert self.id == packet.game_id self.position = packet.position def handlePacketPokerStart(packet): assert self.id == packet.game_id self.reset() self.hand_serial = packet.hand_serial def handlePacketPokerDealer(packet): assert self.id == packet.game_id # assert self.dealer == packet.previous_dealer self.dealer = packet.dealer def handlePacketPokerPlayerCards(packet): self.updatePlayerCards(packet.serial, packet.cards) if packet.serial == self.avatar.serial: self.logIt("You got %r" % self._cards_to_string(packet.cards)) def handlePacketPokerBoardCards(packet): self.board_cards = packet.cards def handlePacketPokerRaise(packet): self._get_player(packet.serial).bet(packet.amount) def handlePacketPokerCall(packet): player = self._get_player(packet.serial) highestbet = self.highestBetNotFold() bigb = self.bigBlind( ) if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition( ) else 0 # import rpdb2; rpdb2.start_embedded_debugger("haha") self.logIt("%r, %r" % (highestbet, bigb)) amount = min(max(highestbet, bigb) - player._bet, player.money) player.bet(amount) def handlePacketPokerState(packet): self._game_state = packet.string def handlePacketPokerBlind(packet): self._get_player(packet.serial).bet(packet.amount) try: handle = locals()["handle" + packet.__class__.__name__] return handle(packet) except KeyError: # self.logIt(" explain cant handle : %r" % packet.__class__.__name__) return True except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() self.logIt(packet.__class__.__name__, prefix=" EEE handle failed: ") for exline in traceback.format_exception(exc_type, exc_value, exc_traceback): for line in exline.split('\n'): self.logIt(str(line), prefix=" EEE ") def _cards_to_string(self, cards): """return a string for cards in a human readable way""" return repr(self._eval.card2string(map(lambda x: x & 63, cards)))\ #.lower().replace("h", u"\u2761").replace("s", u"\u2660").replace("c", u"\u2663").replace("d", u"\u2662") def _get_or_create_player(self, serial, seat=None, **player_info): """returns the player with the serial, the player will be created if it does not exist yet""" # serial = player_info['serial'] # seat = player_info['seat'] if seat and self.seats[seat] != 0 and serial != self.seats[seat]: self.logIt("%s is allready on seat %s, cleared" % (self.seats[seat], seat)) del self.players[self.seats[seat]] self.seats[seat] = serial if serial not in self.players: self.players[serial] = Player(serial=serial, seat=seat, **player_info) return self.players[serial] def _get_player(self, serial): """returns the player, raises an IndexError if it does not exist""" return self.players[serial] def _log_players(self): """ log player informations """ self.logIt("Players:") for player in self.players.itervalues(): self.logIt(player._player_info()) self.logIt("") def getDebugLines(self): """returns a list of debug lines (yellow box)""" return self._get_table_info() + self._get_avatar_info( ) + self._get_player_info() @catcher def _get_table_info(self): """returns a list of table informations""" highestbet = self.highestBetNotFold(), bigb = self.bigBlind( ) if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition( ) else 0 return [ "blinds: small:%r big:%r" % (self.small_blind, self.big_blind), "buy_ins: min:%r max:%r" % (self.min_buy_in, self.max_buy_in), "bs: %r" % self.betting_structure, "highestbet = %r" % highestbet, "bigb = %r" % bigb, ] @catcher def _get_player_info(self): """returns a list with player informations for all players""" return [player._player_info() for player in self.players.values()] @catcher def _get_avatar_info(self): """returns informations of the avatar that is currently logged in""" retvals = [] if self.avatar.cards: retvals.append("hand: " + self._cards_to_string(self.avatar.cards)) if self.board_cards: retvals.append("board: " + self._cards_to_string(self.board_cards)) if self.avatar.cards: best_hand = self._eval.best_hand( "hi", self.avatar.getCards() + self.getBoardCards()) desc = best_hand.pop(0) retvals.append("%s: %s" % (desc, self._cards_to_string(best_hand))) return retvals
from flask import Flask, request, jsonify from pokereval import PokerEval GAME = 'holdem' ITERATIONS = 20000 app = Flask(__name__) pe = PokerEval() @app.route('/', methods=['POST', 'GET']) def index(): app.logger.info('index route') if request.method == 'POST': data = request.get_json() app.logger.info('request {}'.format(data)) equities = pe.poker_eval(iterations=ITERATIONS, game=GAME, **data) app.logger.info('equities {}'.format(equities)) return jsonify(equities) return 'https://github.com/minmax/pypoker-eval' app.run(host='0.0.0.0', port=5000, debug=True)
class HandEvaluator: evaluator = PokerEval() preflop_win_percentages_suited = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0, 0.3598, 0.3682, 0.3784, 0.3766, 0.3814, 0.4026, 0.4241, 0.4484, 0.4738, 0.5017, 0.532, 0.5737 ], [ 0, 0, 0.3598, 0, 0.3863, 0.3968, 0.3953, 0.4003, 0.4087, 0.4325, 0.4568, 0.4823, 0.5101, 0.5405, 0.5821 ], [ 0, 0, 0.3682, 0.3863, 0, 0.4145, 0.4133, 0.4184, 0.427, 0.4385, 0.4653, 0.4906, 0.5185, 0.5488, 0.5903 ], [ 0, 0, 0.3784, 0.3968, 0.4145, 0, 0.4313, 0.4367, 0.4454, 0.4572, 0.4721, 0.4999, 0.5276, 0.5579, 0.5992 ], [ 0, 0, 0.3766, 0.3953, 0.4133, 0.4313, 0, 0.4536, 0.4623, 0.4742, 0.4894, 0.506, 0.536, 0.5664, 0.599 ], [ 0, 0, 0.3814, 0.4003, 0.4184, 0.4367, 0.4536, 0, 0.4793, 0.4912, 0.5064, 0.5232, 0.543, 0.5753, 0.6098 ], [ 0, 0, 0.4026, 0.4087, 0.427, 0.4454, 0.4623, 0.4793, 0, 0.5079, 0.5233, 0.5401, 0.5601, 0.5831, 0.6194 ], [ 0, 0, 0.4241, 0.4325, 0.4385, 0.4572, 0.4742, 0.4912, 0.5079, 0, 0.5402, 0.5566, 0.5766, 0.5998, 0.6277 ], [ 0, 0, 0.4484, 0.4568, 0.4653, 0.4721, 0.4894, 0.5064, 0.5233, 0.5402, 0, 0.5752, 0.5947, 0.6178, 0.6459 ], [ 0, 0, 0.4738, 0.4823, 0.4906, 0.4999, 0.506, 0.5232, 0.5401, 0.5566, 0.5752, 0, 0.6026, 0.6256, 0.6539 ], [ 0, 0, 0.5017, 0.5101, 0.5185, 0.5276, 0.536, 0.543, 0.5601, 0.5766, 0.5947, 0.6026, 0, 0.6339, 0.6621 ], [ 0, 0, 0.532, 0.5405, 0.5488, 0.5579, 0.5664, 0.5753, 0.5831, 0.5998, 0.6178, 0.6256, 0.6339, 0, 0.6704 ], [ 0, 0, 0.5737, 0.5821, 0.5903, 0.5992, 0.599, 0.6098, 0.6194, 0.6277, 0.6459, 0.6539, 0.6621, 0.6704, 0 ] ] preflop_win_percentages_unsuited = [ [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [ 0, 0, 0.5033, 0.3229, 0.3319, 0.3428, 0.3406, 0.3458, 0.3682, 0.3909, 0.4165, 0.4434, 0.4729, 0.5051, 0.5492 ], [ 0, 0, 0.3229, 0.5368, 0.3514, 0.3625, 0.3607, 0.3659, 0.3747, 0.4001, 0.4259, 0.4527, 0.4821, 0.5142, 0.5584 ], [ 0, 0, 0.3319, 0.3514, 0.5702, 0.3815, 0.3801, 0.3854, 0.3944, 0.4067, 0.4349, 0.4618, 0.4912, 0.5232, 0.5672 ], [ 0, 0, 0.3428, 0.3625, 0.3815, 0.6032, 0.3994, 0.4051, 0.4143, 0.4266, 0.4424, 0.4717, 0.5011, 0.5331, 0.5769 ], [ 0, 0, 0.3406, 0.3607, 0.3801, 0.3994, 0.6328, 0.4232, 0.4323, 0.4449, 0.4608, 0.4784, 0.5102, 0.5421, 0.5768 ], [ 0, 0, 0.3458, 0.3659, 0.3854, 0.4051, 0.4232, 0.6623, 0.4505, 0.463, 0.479, 0.4968, 0.5176, 0.5518, 0.5883 ], [ 0, 0, 0.3682, 0.3747, 0.3944, 0.4143, 0.4323, 0.4505, 0.6915, 0.4809, 0.4971, 0.5149, 0.536, 0.5602, 0.5986 ], [ 0, 0, 0.3909, 0.4001, 0.4067, 0.4266, 0.4449, 0.463, 0.4809, 0.7205, 0.5153, 0.5324, 0.5536, 0.578, 0.6076 ], [ 0, 0, 0.4165, 0.4259, 0.4349, 0.4424, 0.4608, 0.479, 0.4971, 0.5153, 0.7501, 0.5524, 0.5728, 0.5973, 0.6271 ], [ 0, 0, 0.4434, 0.4527, 0.4618, 0.4717, 0.4784, 0.4968, 0.5149, 0.5324, 0.5524, 0.7747, 0.5813, 0.6057, 0.6355 ], [ 0, 0, 0.4729, 0.4821, 0.4912, 0.5011, 0.5102, 0.5176, 0.536, 0.5536, 0.5728, 0.5813, 0.7992, 0.6145, 0.6442 ], [ 0, 0, 0.5051, 0.5142, 0.5232, 0.5331, 0.5421, 0.5518, 0.5602, 0.578, 0.5973, 0.6057, 0.6145, 0.8239, 0.6531 ], [ 0, 0, 0.5492, 0.5584, 0.5672, 0.5769, 0.5768, 0.5883, 0.5986, 0.6076, 0.6271, 0.6355, 0.6442, 0.6531, 0.852 ] ] def card_to_str(card): """ Convert this card to a string or number for pypoker-eval. Note that I don't check whether you passed a Card or the right string format! """ # NOT str! Could be unicode if isinstance(card, basestring): return card return card.__str__() def str_to_card(card_string): """ Convert this string to a pokerbots.engine.game.Card instance. Note that I don't check whether or not you passed the right format! """ if isinstance(card_string, Card): return card rank_str = card_string[0].lower() suit_str = card_string[1].lower() rank = 2 suit = 1 if rank_str == "t": rank = 10 elif rank_str == "j": rank = 11 elif rank_str == "q": rank = 12 elif rank_str == "k": rank = 13 elif rank_str == "a": rank = 14 if suit_str == "s": suit = 1 elif suit_str == "h": suit = 2 elif suit_str == "d": suit = 3 elif suit_str == "c": suit = 4 return Card(rank, suit) def evaluate_hand(hand, board=[], iterations=1000): """ Return winning percentage of your hand, with ties counted as 0.5 Includes Monte-Carlo simulation of running the board. Includes trying all possible opponent hands. Arguments: hand: your hand board: the board if any iterations: number of times to simulate """ # If the board is determined, there's only 990 hands to run, # so run them all if len(board) == 5: # convert to pypoker-eval format hand = map(HandEvaluator.card_to_str, hand) board = map(HandEvaluator.card_to_str, board) poker_eval_result = HandEvaluator.evaluator.poker_eval( game="holdem", pockets=[hand, [255, 255]], dead=[], board=board) elif len(board) == 0: # Use a lookup table, because this has been done before if hand[0].suit == hand[1].suit: return HandEvaluator.preflop_win_percentages_suited[ hand[0].rank][hand[1].rank] else: return HandEvaluator.preflop_win_percentages_unsuited[ hand[0].rank][hand[1].rank] else: hand = map(HandEvaluator.card_to_str, hand) board = map(HandEvaluator.card_to_str, board) # Fill the rest of the board with 255s (unknown card) for i in xrange(5 - len(board)): board.append(255) poker_eval_result = HandEvaluator.evaluator.poker_eval( game="holdem", pockets=[hand, [255, 255]], dead=[], board=board, iterations=iterations) # Ok, we have stats. Calculate win pct, with ties as 0.5 weight return (poker_eval_result['eval'][0]['winhi'] + \ 0.5 * poker_eval_result['eval'][0]['tiehi']) / \ float(poker_eval_result['info'][0]) card_to_str = staticmethod(card_to_str) str_to_card = staticmethod(str_to_card) evaluate_hand = staticmethod(evaluate_hand)
# # Authors: # Loic Dachary <*****@*****.**> # # import sys sys.path.insert(0, ".") sys.path.insert(0, ".libs") from pokereval import PokerEval iterations_low = 100000 iterations_high = 200000 pokereval = PokerEval() if pokereval.best_hand_value("hi", ["Ah", "Ad", "As", "Kh", "Ks"]) != 101494784: sys.exit(1) if pokereval.string2card("2h") != 0: sys.exit(1) print "" pockets = [["As", "Ad", "Ac", "Tc", "Ts", "2d", "5c"], ["Js", "Jc", "7s", "8c", "8d", "3c", "3h"], [255, 255]] print "stud7 (1) result = %s\n" % pokereval.winners( game="7stud", pockets=pockets, dead=[], board=[]) pockets = [[22, 18, 21, 3, 41, 1, 30], [39, 255, 255, 15, 13, 17, 255]]
class PokerHandEval: def __init__(self): self.hand_groups = { "A": ["AA", "AKs", "KK"], "B": ["AK", "QQ"], "C": ["JJ", "TT"], "D": ["AQs", "AQ", "AJs", "99", "88"], "E": ["AJ", "ATs", "KQs", "77", "66", "55"], "F": ["AT", "KQ", "KJs", "QJs", "44", "33", "22"], "G": [ "A9s", "A8s", "A7s", "A6s", "A5s", "A4s", "A3s", "A2s", "KTs", "QTs", "JTs", "J9s", "T9s", "98s" ], "H": ["KJ", "KT", "QJ", "J8s", "T8s", "87s", "76s"] } self.hand_values = { "A": 13, "K": 12, "Q": 11, "J": 10, "T": 9, "9": 8, "8": 7, "7": 6, "6": 5, "5": 4, "4": 3, "3": 2, "2": 1 } self.odds_map = { "flop": { 1: 0.045, 2: 0.088, 3: 0.13, 4: 0.172, 5: 0.212, 6: 0.252, 7: 0.29, 8: 0.327, 9: 0.364, 10: 0.399, 11: 0.433, 12: 0.467, 13: 0.499, 14: 0.53, 15: 0.561, 16: 0.59, 17: 0.618 }, "turn": { 1: 0.023, 2: 0.045, 3: 0.68, 4: 0.091, 5: 0.114, 6: 0.136, 7: 0.159, 8: 0.182, 9: 0.205, 10: 0.227, 11: 0.25, 12: 0.273, 13: 0.295, 14: 0.318, 15: 0.341, 16: 0.364, 17: 0.386 } } self.eval = PokerEval() def prepareHand(self, hand): h = hand.split(" ") if self.hand_values[h[1][0]] > self.hand_values[h[0][0]]: self.hand = "%s%s" % (h[1][0], h[0][0]) else: self.hand = "%s%s" % (h[0][0], h[1][0]) if h[0][1] == h[1][1]: self.hand += "s" def getHandGroup(self): for group in self.hand_groups: if self.hand in self.hand_groups[group]: return group return False def getHandValue(self, game, serial): hand = game.getHandAsString(serial) board = game.getBoardAsString() board_list = board.split(" ") if len(board_list) < 5: for i in range(len(board_list), 5): board_list.append("__") hand_list = hand.split(" ") cards = hand_list + board_list return self.eval.best_hand("hi", self.eval.string2card(cards), []) def parseHistory(self, hist): self.round_action = {} self.action2serials = {"call": [], "raise": [], "fold": []} self.serial2action = {} ret = "" for event in hist: type = event[0] if type in ["fold", "check", "call", "raise"]: if len(event) == 3: (action, serial, amount) = event else: (action, serial) = event amount = False ret = "action: %s, serial:%d" % (action, serial) if amount: ret += ", amount = %d" % amount self.round_action[serial] = [action, amount] else: self.round_action[serial] = [action] self.serial2action[serial] = action if action in self.action2serials.keys(): if not serial in self.action2serials[action]: self.action2serials[action].append(serial) def getPosition(self, game, serial): me = game.serial2player[serial] players = game.serialsAllSorted() for player in players: user = game.serial2player[player] user_positions = {} player_seats = {} i = 1 for p in game.serialsAllSorted(): user = game.serial2player[p] player_seats[user.seat] = p max_seat = len(player_seats) early = max_seat / 3 middle = early * 2 self.my_seat = me.seat self.serial2position = {} self.position2serials = {"early": [], "middle": [], "late": []} for p in player_seats.keys(): player_serial = player_seats[p] if i <= early: position = "early" elif i >= (early + 1) and i <= middle: position = "middle" else: position = "late" if not player_serial in self.serial2position.keys(): self.serial2position[player_serial] = position if not player_serial in self.position2serials[position]: self.position2serials[position].append(player_serial) if p == self.my_seat: self.position = position i += 1
class Table(object): def __init__(self, protocol, avatar, table_info): self.protocol = protocol self.id = table_info.get('id', 0) self.seat = table_info.get('player_seated', -1) self.seats = [0] * table_info.get('seats', 10) if self.seat != -1: self.seats[self.seat] = avatar.serial assert avatar.seat == self.seat, "as %s, ss %s" % (avatar.seat, self.seat) self.name = table_info.get('name', 'unnamed') self.betting_structure = table_info['betting_structure'] blinds, buy_ins, limit = table_info['betting_structure'].split('_') min_buy_in, max_buy_in = buy_ins.split('-') small, big = blinds.split('-') self.max_buy_in = int(max_buy_in)*100 self.min_buy_in = int(min_buy_in)*100 self.big_blind = int(big)*100 self.small_blind = int(small)*100 self.players = {avatar.serial: avatar} self.avatar = avatar self._serial_and_game_id = dict(serial=avatar.serial, game_id=self.id) self._eval = PokerEval() self.reset() self._game_state = GAME_STATE_NULL def reset(self): """reseting game states for a new hand""" self.board_cards = [] self.position = -1 self._reset_players() def getBoardCards(self): """return a list of board games""" return list(map(lambda x:x&63, self.board_cards)) def getAvatarInfo(self): """return a string of usefull information about the avatar""" return ", ".join(self._get_avatar_info()) def isInPosition(self, serial): """returs true if player with serial is in position""" return serial in self.in_game and self.position == self.in_game.index(serial) def logIt(self, astr, prefix=" [D] "): """a little helper function to log output""" self.protocol.logIt(astr, prefix=prefix) def updateSeats(self, seats): """update seat information""" for index, (old, new) in enumerate(zip(self.seats, seats)): if old == 0 and new != 0: self.addPlayer(index, new) elif old != 0 and new == 0: self.removePlayer(index) elif old != new: self.removePlayer(index) self.addPlayer(index, new) self.logIt("warning idx %s, old %s, new %s" % (index, old, new)) def addPlayer(self, index, serial): """Add player to this table""" self.seats[index] = serial # Request more information about this player if serial == self.avatar.serial: self.players[index] = self.avatar else: self.protocol.sendPacket(networkpackets.PacketPokerGetUserInfo(serial=serial)) def removePlayer(self, index): """remove player from this table""" serial = self.seats[index] self.seats[index]=0 if serial in self.players: del self.players[serial] def updatePlayer(self, player_info): """update general palyer information (we requested them in addPlayer)""" player = self._get_or_create_player(**player_info) player.update(player_info) def updatePlayerChips(self, serial, chips, bet): """update players chips""" player = self._get_or_create_player(serial=serial) return player.updateChips(chips, bet) def updatePlayerCards(self, serial, cards): """update players cards""" player = self._get_player(serial) player.updateCards(cards) def rebuy(self, serial, amount): """update money state of player because a rebuy happend""" player = self._get_player(serial) player.rebuy(amount) def _reset_players(self): """reset player states""" for player in self.players.values(): player.reset() def highestBetNotFold(self): """returns the highest bet of all players that are not fold""" return max([0]+[p._bet for p in self.players.values() if p.serial in self.in_game and p.notFold()]) def inSmallBlindPosition(self): """returns True if the player in position is in small_blind position""" return len(self.in_game) > 0 and ((self.dealer + 1) % len(self.in_game)) == self.position def bigBlind(self): """returns the big_blind of the current table""" return self.big_blind or 0 def doBuyIn(self): """actually request a buy_in""" self.protocol.sendPacket(networkpackets.PacketPokerBuyIn(amount=self.max_buy_in, **self._serial_and_game_id)) self.protocol.sendPacket(networkpackets.PacketPokerAutoBlindAnte(**self._serial_and_game_id)) def doRebuy(self, amount): """actually request a rebuy""" self.protocol.sendPacket(networkpackets.PacketPokerRebuy(amount=amount, **self._serial_and_game_id)) def doSit(self): """actually request a sit""" self.protocol.sendPacket(networkpackets.PacketPokerSit(**self._serial_and_game_id)) def doSitOut(self): """actually request a sitout""" self.protocol.sendPacket(networkpackets.PacketPokerSitOut(**self._serial_and_game_id)) def doQuit(self): """actually request a table quit""" self.protocol.sendPacket(networkpackets.PacketPokerTableQuit(**self._serial_and_game_id)) def doFold(self): """actually request a fold""" self.protocol.sendPacket(networkpackets.PacketPokerFold(**self._serial_and_game_id)) def doCheck(self): """actually request a check""" self.protocol.sendPacket(networkpackets.PacketPokerCheck(**self._serial_and_game_id)) def doCall(self): """actually request a call""" self.protocol.sendPacket(networkpackets.PacketPokerCall(**self._serial_and_game_id)) def doAllIn(self): """actually raise all chips""" self.doRaise(self.avatar.getChips()) def doRaise(self, amount): """ actually request a raise by a given amount. WARNING: If the amount you requested is too low, the raise will be accepted but the minimum amount to raise will be used instead. You will be informend about the amount that is used to raise. """ self.protocol.sendPacket(networkpackets.PacketPokerRaise(amount=amount, **self._serial_and_game_id)) def explain(self, packet, state): """packets that might be interesting for the game will be handled here""" def handlePacketPokerBuyInLimits(packet): self.max_buy_in = packet.max self.min_buy_in = packet.min def handlePacketPokerSeats(packet): return self.updateSeats(packet.seats) def handlePacketPokerPlayerInfo(packet): self.updatePlayer(packet.__dict__) def handlePacketPokerPlayerChips(packet): return self.updatePlayerChips(packet.serial, chips=packet.money, bet=packet.bet) def handlePacketPokerPlayerArrive(packet): self.updatePlayer(packet.__dict__) def handlePacketPokerPlayerLeave(packet): self.removePlayer(packet.seat) def handlePacketPokerSit(packet): self._get_player(packet.serial).sit() def handlePacketPokerSitOut(packet): self._get_player(packet.serial).sitOut() def handlePacketPokerRebuy(packet): assert self.id == packet.game_id self.rebuy(packet.serial, packet.amount) def handlePacketPokerInGame(packet): assert self.id == packet.game_id self.in_game = packet.players def handlePacketPokerPosition(packet): assert self.id == packet.game_id self.position = packet.position def handlePacketPokerStart(packet): assert self.id == packet.game_id self.reset() self.hand_serial = packet.hand_serial def handlePacketPokerDealer(packet): assert self.id == packet.game_id # assert self.dealer == packet.previous_dealer self.dealer = packet.dealer def handlePacketPokerPlayerCards(packet): self.updatePlayerCards(packet.serial, packet.cards) if packet.serial == self.avatar.serial: self.logIt("You got %r" % self._cards_to_string(packet.cards)) def handlePacketPokerBoardCards(packet): self.board_cards = packet.cards def handlePacketPokerRaise(packet): self._get_player(packet.serial).bet(packet.amount) def handlePacketPokerCall(packet): player = self._get_player(packet.serial) highestbet = self.highestBetNotFold() bigb =self.bigBlind() if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition() else 0 # import rpdb2; rpdb2.start_embedded_debugger("haha") self.logIt("%r, %r" % (highestbet,bigb)) amount = min( max(highestbet,bigb) - player._bet, player.money ) player.bet(amount) def handlePacketPokerState(packet): self._game_state = packet.string def handlePacketPokerBlind(packet): self._get_player(packet.serial).bet(packet.amount) try: handle = locals()["handle"+packet.__class__.__name__] return handle(packet) except KeyError: # self.logIt(" explain cant handle : %r" % packet.__class__.__name__) return True except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() self.logIt(packet.__class__.__name__, prefix=" EEE handle failed: ") for exline in traceback.format_exception(exc_type, exc_value, exc_traceback): for line in exline.split('\n'): self.logIt(str(line), prefix=" EEE ") def _cards_to_string(self, cards): """return a string for cards in a human readable way""" return repr(self._eval.card2string(map(lambda x: x & 63, cards)))\ #.lower().replace("h", u"\u2761").replace("s", u"\u2660").replace("c", u"\u2663").replace("d", u"\u2662") def _get_or_create_player(self, serial, seat=None, **player_info): """returns the player with the serial, the player will be created if it does not exist yet""" # serial = player_info['serial'] # seat = player_info['seat'] if seat and self.seats[seat] != 0 and serial != self.seats[seat]: self.logIt("%s is allready on seat %s, cleared" % (self.seats[seat], seat)) del self.players[self.seats[seat]] self.seats[seat] = serial if serial not in self.players: self.players[serial] = Player(serial=serial, seat=seat, **player_info) return self.players[serial] def _get_player(self, serial): """returns the player, raises an IndexError if it does not exist""" return self.players[serial] def _log_players(self): """ log player informations """ self.logIt("Players:") for player in self.players.itervalues(): self.logIt(player._player_info()) self.logIt("") def getDebugLines(self): """returns a list of debug lines (yellow box)""" return self._get_table_info() + self._get_avatar_info() + self._get_player_info() @catcher def _get_table_info(self): """returns a list of table informations""" highestbet = self.highestBetNotFold(), bigb =self.bigBlind() if self._game_state == GAME_STATE_PRE_FLOP and not self.inSmallBlindPosition() else 0 return ["blinds: small:%r big:%r" % (self.small_blind, self.big_blind), "buy_ins: min:%r max:%r" % (self.min_buy_in, self.max_buy_in), "bs: %r" % self.betting_structure, "highestbet = %r" % highestbet, "bigb = %r" % bigb,] @catcher def _get_player_info(self): """returns a list with player informations for all players""" return [player._player_info() for player in self.players.values()] @catcher def _get_avatar_info(self): """returns informations of the avatar that is currently logged in""" retvals = [] if self.avatar.cards: retvals.append("hand: " + self._cards_to_string(self.avatar.cards)) if self.board_cards: retvals.append("board: " + self._cards_to_string(self.board_cards)) if self.avatar.cards: best_hand = self._eval.best_hand("hi", self.avatar.getCards() + self.getBoardCards()) desc = best_hand.pop(0) retvals.append("%s: %s" % (desc, self._cards_to_string(best_hand))) return retvals
def calculate_hand_potential_without_heuristics(current_hole_cards, board_cards, round_id, full_deck): """ Implemented as described in the page 23 of the thesis in: http://poker.cs.ualberta.ca/publications/davidson.msc.pdf """ our_cards = current_hole_cards + board_cards out_cards_set = frozenset(our_cards) # hand potential array, each index represents ahead, tied, and behind ahead = 0 tied = 1 behind = 2 hp = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] hp_total = [0.0, 0.0, 0.0] total = 0.0 pokereval = PokerEval() our_rank = pokereval.evaln(our_cards) # considers all two card combinations of the remaining cards for the opponent opponent_cards_combinations = list(itertools.combinations( full_deck, 2)) indices = [] for index, cards in enumerate(opponent_cards_combinations): card1, card2 = cards if card1 in our_cards or card2 in our_cards: indices.append(index) for index in reversed(indices): opponent_cards_combinations.pop(index) for opponent_card1, opponent_card2 in opponent_cards_combinations: opponent_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board_cards) if our_rank > opponent_rank: index = ahead elif our_rank == opponent_rank: index = tied else: index = behind # hp_total[index] += 1.0 # original version # all possible board cards to come deck = list(full_deck) dealt_card = current_hole_cards + board_cards + [ opponent_card1 ] + [opponent_card2] deck_without_dealt_cards = [ card for card in deck if card not in dealt_card ] if round_id == 1: # flop cards_combinations = list( itertools.combinations(deck_without_dealt_cards, 2)) # cards_combinations = random.sample(cards_combinations, int(len(cards_combinations)*0.2)) for turn, river in cards_combinations: # final 5-card board board = board_cards + [turn] + [river] our_future_rank = pokereval.evaln(current_hole_cards + board) opponent_future_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board) if our_future_rank > opponent_future_rank: hp[index][ahead] += 1.0 elif our_future_rank == opponent_future_rank: hp[index][tied] += 1.0 else: hp[index][behind] += 1.0 total += 1.0 hp_total[index] += 1.0 # new version else: # turn # cards = random.sample(deck_without_dealt_cards, int(len(deck_without_dealt_cards)*0.75)) cards = deck_without_dealt_cards for river in cards: # final 5-card board board = board_cards + [river] our_future_rank = pokereval.evaln(current_hole_cards + board) opponent_future_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board) if our_future_rank > opponent_future_rank: hp[index][ahead] += 1.0 elif our_future_rank == opponent_future_rank: hp[index][tied] += 1.0 else: hp[index][behind] += 1.0 total += 1.0 hp_total[index] += 1.0 # new version # the original formula: # ppot = (hp[behind][ahead] + hp[behind][tied]/2.0 + hp[tied][ahead]/2.0) / (hp_total[behind] + hp_total[tied]/2.0) # npot = (hp[ahead][behind] + hp[tied][behind]/2.0 + hp[ahead][tied]/2.0) / (hp_total[ahead] + hp_total[tied]/2.0) # ppot: were behind but moved ahead: cant use the original hp_total, because the result isnt normalzied and because it dont work for the heuristics # added hp[ahead][ahead] so already good hands wouldnt be given a below average potential ppot = (hp[ahead][ahead] + hp[behind][ahead] + hp[behind][tied] / 2.0 + hp[tied][ahead]) / (hp_total[behind] * 1.5 + hp_total[tied] * 1.0 + hp_total[ahead] * 1.0) # npot: were ahead but fell behind # npot = ((hp[ahead][behind]/total)*2.0 + (hp[ahead][tied]/total)*1.0 + (hp[tied][behind]/total)*1.0)/4.0 return ppot
def __init__(self, had_values, hand, board): self.eval = PokerEval() self.hand_values = {"A":13,"K":12,"Q":11,"J":10, "T":9,"9":8,"8":7,"7":6,"6":5,"5":4,"4":3,"3":2,"2":1} self.hand = hand self.board = board
''' Created on 11 mai 2012 @author: Askylh ''' from pokereval import PokerEval Peval = PokerEval() iteration=100000 ev = Peval.poker_eval(game='holdem', pockets=[["tc", "ts"], ["kd", "ad"]], board=["__", "__", "__", "__", "__"], iterations=iteration) print ev['eval']
# # Authors: # Loic Dachary <*****@*****.**> # # import sys sys.path.insert(0, ".") sys.path.insert(0, ".libs") from pokereval import PokerEval iterations_low = 100000 iterations_high = 200000 pokereval = PokerEval() if pokereval.best_hand_value("hi", ["Ah", "Ad", "As", "Kh", "Ks"]) != 101494784: sys.exit(1) if pokereval.string2card("2h") != 0: sys.exit(1) print "" pockets = [["As", "Ad", "Ac", "Tc", "Ts", "2d", "5c"], ["Js", "Jc", "7s", "8c", "8d", "3c", "3h"], [255, 255]] print "stud7 (1) result = %s\n" % pokereval.winners(game="7stud", pockets=pockets, dead=[], board=[]) pockets = [[22, 18, 21, 3, 41, 1, 30], [39, 255, 255, 15, 13, 17, 255]] print "stud7 (2) result = %s\n" % pokereval.winners(game="7stud", pockets=pockets, dead=[], board=[]) print [j + i + "/%d" % pokereval.string2card(j + i) for i in "hdcs" for j in "23456789TJQKA"]
def calculate_hand_potential_without_heuristics(current_hole_cards, board_cards, round_id, full_deck): """ Implemented as described in the page 23 of the thesis in: http://poker.cs.ualberta.ca/publications/davidson.msc.pdf """ our_cards = current_hole_cards + board_cards out_cards_set = frozenset(our_cards) # hand potential array, each index represents ahead, tied, and behind ahead = 0 tied = 1 behind = 2 hp = [[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]] hp_total = [0.0, 0.0, 0.0] total = 0.0 pokereval = PokerEval() our_rank = pokereval.evaln(our_cards) # considers all two card combinations of the remaining cards for the opponent opponent_cards_combinations = list(itertools.combinations(full_deck, 2)) indices = [] for index, cards in enumerate(opponent_cards_combinations): card1, card2 = cards if card1 in our_cards or card2 in our_cards: indices.append(index) for index in reversed(indices): opponent_cards_combinations.pop(index) for opponent_card1, opponent_card2 in opponent_cards_combinations: opponent_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board_cards) if our_rank > opponent_rank: index = ahead elif our_rank == opponent_rank: index = tied else: index = behind # hp_total[index] += 1.0 # original version # all possible board cards to come deck = list(full_deck) dealt_card = current_hole_cards + board_cards + [opponent_card1] + [opponent_card2] deck_without_dealt_cards = [card for card in deck if card not in dealt_card] if round_id == 1: # flop cards_combinations = list(itertools.combinations(deck_without_dealt_cards, 2)) # cards_combinations = random.sample(cards_combinations, int(len(cards_combinations)*0.2)) for turn, river in cards_combinations: # final 5-card board board = board_cards + [turn] + [river] our_future_rank = pokereval.evaln(current_hole_cards + board) opponent_future_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board) if our_future_rank > opponent_future_rank: hp[index][ahead] += 1.0 elif our_future_rank == opponent_future_rank: hp[index][tied] += 1.0 else: hp[index][behind] += 1.0 total += 1.0 hp_total[index] += 1.0 # new version else: # turn # cards = random.sample(deck_without_dealt_cards, int(len(deck_without_dealt_cards)*0.75)) cards = deck_without_dealt_cards for river in cards: # final 5-card board board = board_cards + [river] our_future_rank = pokereval.evaln(current_hole_cards + board) opponent_future_rank = pokereval.evaln([opponent_card1] + [opponent_card2] + board) if our_future_rank > opponent_future_rank: hp[index][ahead] += 1.0 elif our_future_rank == opponent_future_rank: hp[index][tied] += 1.0 else: hp[index][behind] += 1.0 total += 1.0 hp_total[index] += 1.0 # new version # the original formula: # ppot = (hp[behind][ahead] + hp[behind][tied]/2.0 + hp[tied][ahead]/2.0) / (hp_total[behind] + hp_total[tied]/2.0) # npot = (hp[ahead][behind] + hp[tied][behind]/2.0 + hp[ahead][tied]/2.0) / (hp_total[ahead] + hp_total[tied]/2.0) # ppot: were behind but moved ahead: cant use the original hp_total, because the result isnt normalzied and because it dont work for the heuristics # added hp[ahead][ahead] so already good hands wouldnt be given a below average potential ppot = (hp[ahead][ahead] + hp[behind][ahead] + hp[behind][tied]/2.0 + hp[tied][ahead]) / (hp_total[behind]*1.5 + hp_total[tied]*1.0 + hp_total[ahead]*1.0) # npot: were ahead but fell behind # npot = ((hp[ahead][behind]/total)*2.0 + (hp[ahead][tied]/total)*1.0 + (hp[tied][behind]/total)*1.0)/4.0 return ppot
(727,207) ) ) op_card_pos = ( (187,120), (112,211), (182,284), (598,285), (682,212), (608,122) ) once = True i = 1 pokereval = PokerEval() while (once or loop): board=list() pocket=list() #Get screenshot of whole table w = gtk.gdk.get_default_root_window() screen = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB,False,8,795,548) screen = screen.get_from_drawable(w,w.get_colormap(),0,48,0,0,795,548) #src_x,src_y,dest_x,dest_y,width,height #Get Community Cards for p in comm_cards_pos: card = card_at_pos(p,screen) if card != None: board.append(card)
class MatchHistory: def __init__(self, pname): self.history = [{}, {}, {}, {}] for a in range(4): # [BET,CALL,CHECK,RAISE]: for s in range(4): self.history[s][a] = [] self.pname = pname self.pokereval = PokerEval() self.showStats = {} def reset(self): return def update(self, game): self.showStats = [] for action in game.hand.actions: if action.type == SHOW and action.player == self.pname: self.showStats = [[action.showCard1, action.showCard2], [0, 0]] if len(self.showStats) > 0: self.computeNewEntries(game) def computeNewEntries(self, game): playerHand = self.showStats[0] ev2 = TwoPocketLookup.evalPocket(Card(playerHand[0]), Card(playerHand[1])) ev3 = ThreePocketLookup.evalPocket(Card(playerHand[0]), Card(playerHand[1])) self.showStats[1] = [ev2, ev3] street = 0 b = [255] * 5 for action in game.hand.actions: if action.type == DEAL: street += 1 if street == FLOP: # FLOP b[:3] = game.boardCards[:3] elif street == TURN: # TURN b[:4] = game.boardCards[:4] elif street == RIVER: # RIVER b = game.boardCards playerHand = self.showStats[0] pockets = [playerHand, [255, 255], [255, 255]] ev3 = self.pokereval.poker_eval( game="holdem", pockets=pockets, dead=[], board=b, iterations=ITERATIONS )["eval"][0]["ev"] ev2 = self.pokereval.poker_eval( game="holdem", pockets=pockets[:2], dead=[], board=b, iterations=ITERATIONS )["eval"][0]["ev"] self.showStats[1] = [ev2, ev3] elif action.player == self.pname and action.type != POST and action.type in game.hand.trackedActions: act = action.copy() act.ev = self.showStats[1] self.history[street][action.type].append(act) def __repr__(self): ret = "MATCH HISTORY\n" ret += "PLAYER " + self.pname + "\n" for s in range(4): ret += " STREET " + str(s) + "\n" for a in self.history[s].keys(): ret += " ACTION " + ACTION_TYPES[a] + "\n" for i in range(len(self.history[s][a])): act = self.history[s][a][i] ret += " [" ret += "TYPE: " + ACTION_TYPES[act.type] + ", " ret += "AMOUNT: " + str(act.amount) + ", " ret += "POT AMOUNT: " + str(act.potAmount) + ", " ret += "BET AMOUNT: " + str(act.betAmount) + ", " ret += "EV: " + str(act.ev[0]) + " " + str(act.ev[1]) + " ]\n" return ret[:-1] def averageStrength(self, game, action, amountType): sum = 0 sum2 = 0 numMatches = 0 amountDiffs = [] # list of action values [(action, actionAmount, abs(amount-actionAmount) diffBound = max(7, 0.15 * action.amount) # print self.history.keys() ##Need to comment out if action.type not in self.history[action.street].keys(): # print "ACTION TYPE IN AVERAGE STRENGTH", action.type return [-1, 1000] actions = self.history[action.street][action.type] for a in actions: ev = a.ev[game.activePlayers - 2] if amountType == POTAMOUNT: if a.potAmount == action.potAmount: sum += ev sum2 += ev * ev numMatches += 1 else: amountDiffs += [(a, a.potAmount, abs(a.potAmount - action.potAmount))] elif amountType == BETAMOUNT: if a.betAmount == action.betAmount: sum += ev sum2 += ev * ev numMatches += 1 else: amountDiffs += [(a, a.betAmount, abs(a.betAmount - action.betAmount))] else: if a.amount == action.amount: sum += ev numMatches += 1 sum2 += ev * ev else: diff = abs(a.amount - action.amount) # only use actions within a certain range to calculate average/std values if diff <= diffBound: amountDiffs += [(a, a.amount, diff)] if numMatches < 3: # sort the amountDiffs by the difference in amount from the desired amount amountDiffs = sorted(amountDiffs, key=lambda x: x[2]) minDiff = 0 for amt in amountDiffs: ev = amt[0].ev[game.activePlayers - 2] if amt[2] != minDiff: minDiff = amt[2] if numMatches >= 3: mean = float(sum) / numMatches std = sqrt((sum2 * numMatches - (sum * sum)) / float(numMatches * (numMatches - 1))) return [mean, std] sum += ev numMatches += 1 sum2 += ev * ev return [-1, 1000] mean = float(sum) / numMatches std = sqrt((sum2 * numMatches - (sum * sum)) / float(numMatches * (numMatches - 1))) return [mean, std]
# Loic Dachary <*****@*****.**> # Henry Precheur <*****@*****.**> (2004) # import unittest, sys from os import path TESTS_PATH = path.dirname(path.realpath(__file__)) sys.path.insert(0, path.join(TESTS_PATH, "..")) from pokereval import PokerEval from pokerengine import pokergame from pokerengine.pokergame import PokerGameServer from pokerengine.pokercards import PokerCards poker_eval = PokerEval() _initial_money = 1000 class TestAllIn(unittest.TestCase): def setUp(self, variant, betting): self.game = PokerGameServer("poker.%s.xml", [path.join(TESTS_PATH, '../conf')]) self.game.setVariant(variant) self.game.setBettingStructure(betting) def bestWithStrings(self, side, serial): (value, cards) = self.game.bestHand(side, serial) return (cards[0], self.game.eval.card2string(cards[1:])) def tearDown(self): del self.game
class TheBostonDerbyOld: def __init__(self): """This is a very simple player that demonstrates the API and is a good template for getting started """ # my name self.name = "theBostonDerby" self.reset(False,[]) # game state variables -- these are updated by the engine which # own internal representation. so if you modify them, they'll just # be reset. we recommend leaving their init as is self.hand = None self.stack = None self.pip = None self.button = None self.opponent = None self.bb = None self.sb = None self.hands_played = None self.last_hand = 0 self.board = None self.legal = None self.actions = None self.last = None self.pot = None self.ev_calc = PokerEval() self.ev = 0 self.bound = 0 self.bot = BaseBot() self.LOW = .02 self.MID = .08 self.HIGH = .15 def reset(self, won, last_hand): """Reset accepts a boolean indicating whether you won a match and provides the last hand if you want to update any statistics from it """ self.my_stats = { 'hands':0, '^VPIP':[0,0,0,0], 'VPIP':[0,0,0,0], # amount voluntarily placed in pot '^INCR':[0,0,0,0], 'INCR':[0,0,0,0], # frequency of raises '^AF':0, '_AF':0, 'AF':0, # aggression frequency = (bets + raises)/(checks + calls) #pre flop '^ST':0, 'ST':0, # steals = how often he raises when has first action '^LMP':0, 'LMP':0, # how often opponent calls '_3B':0, '^FBB':0, 'FBB':0, # how often, after small blind raises, big blind folds '^3B':0, '3B':0, # how often, after small blind raises, big blind raises '_4B':0, '^F3B':0, 'F3B':0, # how often, after small blind raises and then big blind raises, small blind folds '^4B':0, '4B':0, # how often, the small bind raises in above circumstances '_F4B':0, '^F4B':0, 'F4B':0, #how often big blind folds to 4B #flop '_COB':0, '^COB':0, 'COB':0, # continuation bet = how often betting after betting/raising on preflop '_FCOB':0, '^FCOB':0, 'FCOB':0, # how often opp folds to a continuation bet #turn '_2COB':0, '^2COB':0, '2COB':0, # how often opp cb twice, once on flop and once on turn '_F2COB':0, '^F2COB':0, 'F2COB':0, # how often opp folds to 2nd continuation bet. '_CHBR':[0,0,0,0], '^CHBR':[0,0,0,0], 'CHBR':[0,0,0,0], # how often opp check raises } self.opp_stats = self.my_stats.copy() self.opp_stats['^VPIP'] = [0,0,0,0] self.opp_stats['VPIP'] = [0,0,0,0] self.opp_stats['^INCR'] = [0,0,0,0] self.opp_stats['INCR'] = [0,0,0,0] self.opp_stats['_CHBR'] = [0,0,0,0] self.opp_stats['^CHBR'] = [0,0,0,0] self.opp_stats['CHBR'] = [0,0,0,0] self.last = None self.opp_hand = 100.0 self.cory_stats = {'A':0, 'W':0, 'C':0} def card2str(self, c): return c.__str__() def calculate_ev(self): #print self.board if not self.board.flop(): suited = self.hand[0].suit != self.hand[1].suit #0 means suited, 1 means not if self.hand[0].rank > self.hand[1].rank: card_2,card_1 = self.hand else: card_1,card_2 = self.hand #print "looking up (%d,%d,%d)" % (card_1.rank-2,card_2.rank-card_1.rank,suited) ev = 100.0 - lookuphand[card_1.rank-2][card_2.rank-card_1.rank][suited] else: board = [self.card2str(c) for c in self.board.flop()] my_hand = [self.card2str(c) for c in self.hand] dead = my_hand if self.board.river(): board += [self.card2str(self.board.turn()), self.card2str(self.board.river())] dead += board[:] elif self.board.turn(): board += [self.card2str(self.board.turn()), '__'] dead += board[:-1] else: board += ['__','__'] dead += board[:-2] if self.opp_hand == 100.0: ev = self.ev_calc.poker_eval(game="holdem",pockets=[[self.card2str(c) for c in self.hand],['__','__']],dead=[],board=board,iterations=1000) ev = ev['eval'][0]['ev']/10.0 else: hands = reduce(lambda x,y:x+y, lookupvalue[:int(self.opp_hand*10)]) wins = 0 iters = 30 num_hands = 0 for hand in hands: if hand[0] in dead or hand[1] in dead: continue ev = self.ev_calc.poker_eval(game="holdem",pockets=[my_hand,list(hand)],dead=[],board=board,iterations=iters) wins += ev['eval'][0]['winhi']+ev['eval'][0]['tiehi']/2.0 num_hands += 1 ev = wins/float(num_hands*iters) self.ev = ev/100.0 def hand_confidence(self): stack_size = self.stack + self.pip self.bound = stack_size if not self.board.flop(): if stack_size < 30*self.bb: if self.ev < .7: #if small stack, and not one of best hands self.bound = 0 # fold else: self.bound = -1 else: if self.ev > .9:# or (self.stats['pfhb'] > 0.25 and self.hands_played > 12): self.bound = stack_size elif self.ev > .8: self.bound = int(.1 * stack_size) elif self.ev > .5: self.bound = 2 * self.bb else: self.bound = self.bb else: if self.ev < .33: self.bound = min(int(max(self.pot*self.ev/(1-3*self.ev),0)),stack_size) def classify(self, act): action = None if isinstance(act, Post): action = POST elif isinstance(act, Check): action = CHECK elif isinstance(act, Bet): action = BET elif isinstance(act, Raise): action = RAISE elif isinstance(act, Fold): action = FOLD elif isinstance(act, Call): action = CALL elif isinstance(act, Show): action = SHOW elif isinstance(act, Deal): action = DEAL elif isinstance(act, Won): action = WON else : print "umm, unknown action taken!", act return action def calculate_stats(self,last): #parse all actions in previous hand into useful information if DEBUG: print "calculating stats for hand: ", last tallies = {'raises':0, 'bets':0, 'folds':0, 'calls':0, 'checks':0} my_actions = dict(zip(range(4),[tallies.copy() for x in range(4)])) opp_actions = dict(zip(range(4),[tallies.copy() for x in range(4)])) hand = deque(last[:]) act = hand.popleft() #first action is always sb posting their blind my_actions['position'] = act[0] == self.name #position = 1 means sb, 0 means BB opp_actions['position'] = not my_actions['position'] #if i'm not small blind, opp must be act = hand.pop() my_actions['won'] = act[0] == self.name opp_actions['won'] = not my_actions['won'] this_hand = {self.name:my_actions, self.opponent['name']:opp_actions, 'steal':False, 'limp':False} hand.popleft() # second action is always bb posting, and is useless street = 0 #0 is preflop, 1 is flop, 2 is turn and 3 is river first = True while len(hand) > 0 : act = hand.popleft() if act[0] == 'Dealer': #then this action corresponds to changing street street += 1 continue action = self.classify(act[1]) if first: first = False if action == RAISE: this_hand['steal'] = True elif action == CALL: this_hand['limp'] = True if act[0] in [self.name, self.opponent['name']]: if action == RAISE: this_hand[act[0]][street]['raises'] += 1 elif action == CHECK: this_hand[act[0]][street]['checks'] += 1 elif action == CALL: this_hand[act[0]][street]['calls'] += 1 elif action == FOLD: this_hand[act[0]][street]['folds'] += 1 elif action == BET: this_hand[act[0]][street]['bets'] += 1 else: print "unknown player: ",act[0] self.my_stats['hands'] += 1 self.opp_stats['hands'] += 1 self.update_stats(self.opp_stats, my_actions, opp_actions, this_hand['steal'], this_hand['limp']) self.update_stats(self.my_stats, opp_actions, my_actions, this_hand['steal'], this_hand['limp']) self.calc_cory(self.cory_stats, my_actions, opp_actions, this_hand['steal'], this_hand['limp']) if opp_actions['won']: hand = last[:] act = hand.pop() while act[0] != self.opponent['name']: act= hand.pop() action = self.classify(act[1]) if action == RAISE: self.cory_stats['A'] += 20 elif action == BET or action == CALL: if action.amount == self.opponent['stack']+self.opponent['pip']: self.cory_stats['A'] += 10 else: self.cory_stats['C'] += 20 def calc_cory(self, stats, me, opp, steal, limp): stats['A'] += 5*sum([opp[x][y] for x in range(4) for y in ['bets', 'raises']]) stats['A'] += 10*sum([opp[x]['raises']-1 for x in range(4)]) stats['C'] += 5*sum([opp[x][y] for x in range(4) for y in ['bets', 'raises', 'calls']]) stats['C'] += 10*sum([opp[x]['calls']>0 for x in range(4) if opp[x]['raises']>0]) stats['W'] += 5*(limp and opp['position']) stats['W'] += 3*(opp[PREFLOP]['folds']>0) stats['W'] += 5*(sum([opp[x]['folds'] for x in [FLOP,TURN,RIVER]])>0) stats['A'] += 20*sum([1 for x in [FLOP,TURN,RIVER] if opp[x]['checks']>0 and me[x]['bets'] >0 and opp[x]['raises']>0]) def update_stats(self,stats,me,opp,steal,limp): this_hand = {} for street in range(4): if opp[street]['raises'] or opp[street]['bets'] or opp[street]['calls']: stats['^VPIP'][street] += 1 if opp[street]['raises']: stats['^INCR'][street] += 1 stats['VPIP'][street] = stats['^VPIP'][street]/float(stats['hands']) stats['INCR'][street] = stats['^INCR'][street]/float(stats['hands']) this_hand['^AF'] = sum([opp[x]['raises'] + opp[x]['bets'] for x in [FLOP, TURN, RIVER]]) this_hand['_AF'] = sum([opp[x]['calls'] for x in [FLOP, TURN, RIVER]]) #PREFLOP this_hand['^ST'] = steal and opp['position'] this_hand['^LMP']= limp and opp['position'] this_hand['_3B'] = steal and not opp['position'] this_hand['^FBB']= this_hand['_3B'] and opp[0]['folds'] and opp[0]['raises'] == 0 this_hand['^3B'] = this_hand['_3B'] and opp[0]['raises'] > 0 this_hand['_4B'] = this_hand['^ST'] and me[0]['raises'] > 0 this_hand['^F3B']= this_hand['_4B'] and opp[0]['folds'] and opp[0]['raises'] == 1 this_hand['^4B'] = this_hand['_4B'] and opp[0]['raises'] >= 2 this_hand['_F4B']= this_hand['^3B'] and me[0]['raises'] >= 2 this_hand['^F4B']= this_hand['_F4B']and opp[0]['folds'] and opp[0]['raises'] == 1 #FLOP this_hand['_COB'] = opp['position'] and opp[0]['raises'] > 0 and me[0]['calls']>0 and me[1]['checks']>0 this_hand['^COB'] = this_hand['_COB'] and opp[1]['bets'] > 0 this_hand['_FCOB']= not opp['position'] and me[0]['raises']>0 and opp[0]['calls']>0 and opp[1]['checks']>0 and me[1]['bets']>0 this_hand['^FCOB']= this_hand['_FCOB'] and opp[1]['folds']>0 #TURN this_hand['_2COB'] = this_hand['^COB'] and me[2]['checks']>0 this_hand['^2COB'] = this_hand['_2COB'] and opp[2]['bets']>0 this_hand['_F2COB']= this_hand['_FCOB'] and me[2]['bets']>0 this_hand['^F2COB']= this_hand['_F2COB'] and opp[2]['folds']>0 this_hand['_CHBR'] = [0,0,0,0] this_hand['^CHBR'] = [0,0,0,0] #POSTFLOP for street in [FLOP, TURN, RIVER]: this_hand['_CHBR'][street] = opp[street]['checks']>0 and me[street]['bets'] >0 this_hand['^CHBR'][street] = this_hand['_CHBR'][street] and opp[street]['raises']>0 for stat in stats.keys(): if this_hand.has_key(stat) and isinstance(this_hand[stat],int): stats[stat] += this_hand[stat] stats['AF'] = stats['^AF']/float(stats['_AF']) if stats['_AF'] else None stats['ST'] = stats['^ST']/float(stats['hands']) stats['LMP'] = stats['^LMP']/float(stats['hands']) stats['FBB'] = stats['^FBB']/float(stats['_3B']) if stats['_3B'] else None stats['3B'] = stats['^3B']/float(stats['_3B']) if stats['_3B'] else None stats['F3B'] = stats['^F3B']/float(stats['_4B']) if stats['_4B'] else None stats['4B'] = stats['^4B']/float(stats['_4B']) if stats['_4B'] else None stats['F4B'] = stats['^F4B']/float(stats['_F4B']) if stats['_F4B'] else None stats['COB'] = stats['^COB']/float(stats['_COB']) if stats['_COB'] else None stats['FCOB'] = stats['^FCOB']/float(stats['_FCOB']) if stats['_FCOB'] else None stats['2COB'] = stats['^2COB']/float(stats['_2COB']) if stats['_2COB'] else None stats['F2COB'] = stats['^F2COB']/float(stats['_F2COB']) if stats['_F2COB'] else None for street in [FLOP, TURN, RIVER]: stats['_CHBR'][street] += this_hand['_CHBR'][street] stats['^CHBR'][street] += this_hand['^CHBR'][street] stats['CHBR'][street] = stats['^CHBR'][street]/float(stats['_CHBR'][street]) if stats['_CHBR'][street] else None def respond(self): if DEBUG: print self.name if DEBUG: print self.hands_played, self.last_hand, self.hand, self.board if DEBUG: print self.actions, self.opponent self.calculate_ev() self.hand_confidence() if DEBUG: print "ev=%d, pot=%d, bound=%d" % (self.ev*100, self.pot, self.bound) if self.hands_played != self.last_hand and self.hands_played: if self.hands_played == self.last_hand + 2: #if we missed one self.calculate_stats(self.last[0]) self.calculate_stats(self.last[1]) self.last_hand = self.hands_played self.bot.new_hand() #notify our bot of new hand if DEBUG: print self.opp_stats if DEBUG: raw_input() if self.board.flop(): last_act = self.actions[-1] last_action = self.classify(last_act[1]) if last_action == BET: if last_act[1].amount < .5*self.pot: self.cory_stats['W'] += 5 elif last_act[1].amount > self.pot: self.cory_stats['A'] += 10 if self.button: #he's BB self.cory_stats['A'] += 5 action = self.bot.respond(self) return action