def getHandStrength(hand, board, iters=1000):
    """
    Uses pbots calc library to get the hand strength of a given hand against a given board.
    hand: a list of 2 Card objects
    board: a list of Card objects (could be [] or contain up to 5 cards)
    
    With iters=500: 95% of data within 3.8% of actual
    With iters=1000: 95% of data within 2.7% of actual
    With iters=2000: 95% of data within 2.2% of actual
    With iters=4000: 95% of data within 1.7% of actual
    """
    if ((type(hand) == str) and (type(board) == str)):
        #print hand, board
        res = calc(hand+":xx", board, "", iters)

    else:
        assert len(board) <= 5, "Error: board must have 3-5 cards"
        assert (len(hand)==2), "Error: hand must contain exactly 2 cards"

        # the "xx" tells pbots_calc to compare hand against a random opponent hand
        handstr = convertSyntax(hand)+":xx"
        boardstr = convertSyntax(board)

        #note the empty "" parameter is telling pbots_calc not to remove any extra cards from the deck
        res = calc(handstr, boardstr, "", iters)
    
    return res.ev[0] # return the EV of our hand
def determineBestCardToKeep(hand, board, iters=1000, highcard_weight=0.03):
    """
    A helper function for determineDiscardFast().
    """
    originalHandStr = convertSyntax(hand)
    boardStr = convertSyntax(board)

    # create a neutral deck that does not contain any cards from the hand or board
    neutralDeck = []
    for card in FULL_DECK:
        if card in board or card in hand:
            continue
        else:
            neutralDeck.append(card)

    # can't let comparison card be within +/- of value of cards in the hand
    forbiddenRanks = [hand[0].rank, hand[1].rank, hand[0].rank-1, hand[1].rank-1, hand[0].rank+1, hand[1].rank+1]

    # shuffle so that we can pop random cards off of top
    shuffle(neutralDeck)

    # get two comparison cards that will be swapped
    cmpCard1 = neutralDeck.pop(0)

    # note: we make sure that these comparison cards are not the same rank as either card in our hand!
    while cmpCard1.rank in forbiddenRanks or cmpCard1.suit==hand[0].suit or cmpCard1.suit==hand[1].suit:
        cmpCard1 = neutralDeck.pop(0)

    cmpCard2 = neutralDeck.pop(0)
    while cmpCard2.rank in forbiddenRanks or cmpCard2.suit==hand[0].suit or cmpCard2.suit == hand[1].suit:
        cmpCard2 = neutralDeck.pop(0)

    # now we have 2 "neutral" comparison cards
    cmpCard1Str = convertSyntax(cmpCard1)
    cmpCard2Str = convertSyntax(cmpCard2)
    #print "Cmp Cards:", cmpCard1Str, cmpCard2Str

    # play [C_1, C1*] against [C_2, C2*]
    res1 = calc("%s%s:%s%s" % (originalHandStr[0:2], cmpCard1Str, originalHandStr[2:4], cmpCard2Str), boardStr, "", iters)
    # play [C_1, C2*] against [C_2, C1*]
    res2 = calc("%s%s:%s%s" % (originalHandStr[0:2], cmpCard2Str, originalHandStr[2:4], cmpCard1Str), boardStr, "", iters)

    # determine which card is stronger, and should be kept
    C1_scores = [res1.ev[0], res2.ev[0]] # the EVs for hands where we KEPT C1
    C2_scores = [res1.ev[1], res2.ev[1]] # the EVs for hands where we KEPT C2

    #print C1_scores
    #print C2_scores

    avgC1Score = mean(C1_scores) + highcard_weight * (hand[0].rank-hand[1].rank)
    avgC2Score = mean(C2_scores) + highcard_weight * (hand[1].rank-hand[0].rank)

    if avgC1Score > avgC2Score: # C1 is better to keep
        keepCard = 0
    else:
        keepCard = 1

    return keepCard
Example #3
0
 def setHandRankRiver(self):
     if self.numberOfOpponents == 2:
         r = pbots_calc.calc(''+self.currentHand+':xx:xx', self.currentBoard, '', 5000)
         if r:
             self.currentHandStrength = zip(r.hands, r.ev)[0][1]
     else:
         r = pbots_calc.calc(''+self.currentHand+':xx', self.currentBoard, '', 5000)
         if r:
             self.currentHandStrength = zip(r.hands, r.ev)[0][1]
def determineBestDiscard(hand, board, min_improvement=0.05, iters=100):
    """
    Given a hand and either a flop or turn board, returns whether the player should discard, and if so, which card they should choose.
    hand: a list of Card objects
    board: a list of Card objects
    """
    originalHandStr = convertSyntax(hand)+":xx"
    boardstr = convertSyntax(board)

    originalHandEV = calc(originalHandStr, boardstr, "", 1000).ev[0]

    swapFirstEVSum = 0
    swapSecondEVSum = 0
    numCards = 0

    for card in FULL_DECK:
        if card in board or card in hand:
            continue
        else:
            # increment
            numCards += 1

            cardstr = convertSyntax(card)

            # compare original hand to the hand made by replacing first card with CARD
            swapFirstStr = "%s%s%s" % (cardstr,originalHandStr[2:4],":xx")

            # compare original hand to the hand made by replacing second card with CARD
            swapSecondStr = "%s%s%s" % (originalHandStr[0:2],cardstr,":xx")

            # print("First:", swapFirstStr)
            # print("Second:", swapSecondStr)

            swap_first_res = calc(swapFirstStr, boardstr, "", iters)
            swap_second_res = calc(swapSecondStr, boardstr, "", iters)

            swapFirstEVSum += swap_first_res.ev[0]
            swapSecondEVSum += swap_second_res.ev[0]

    # calculate the average EV of swapping first and second when we play them against the original hand
    avgSwapFirstEV = float(swapFirstEVSum) / numCards
    avgSwapSecondEV = float(swapSecondEVSum) / numCards

    # if either swap increases EV by more than 5%
    if avgSwapFirstEV > originalHandEV+min_improvement or avgSwapSecondEV > originalHandEV+min_improvement:
        if avgSwapFirstEV > avgSwapSecondEV:
            return (True, 0, avgSwapFirstEV, originalHandEV)
        else:
            return (True, 1, avgSwapSecondEV, originalHandEV)
    else:
        return (False, None, 0, originalHandEV)
Example #5
0
    def get_best_action(self, received_packet, avail_actions = []):
        equity = None

        # determine if we are still in the same betting round to prevent raising to infinity problem
        if received_packet['num_boardcards'] == self.num_boardcards:
            self.is_new_round = False
        else: 
            self.is_new_round = True
            self.num_boardcards = received_packet['num_boardcards'] 

        if received_packet['num_active_players'] == 3:
            self.fold_thres = THREE_FOLD_THRES
            self.raise_thres = THREE_RAISE_THRES
            self.reraise_thres = THREE_RERAISE_THRES
            equity = pbots_calc.calc(':'.join([self.my_hand, 'xx', 'xx']), ''.join(received_packet['boardcards']), 
                "", ITER_TABLE[self.num_boardcards])
        else:
            self.fold_thres = TWO_FOLD_THRES
            self.raise_thres = TWO_RAISE_THRES
            self.reraise_thres = TWO_RERAISE_THRES
            equity = pbots_calc.calc(':'.join([self.my_hand, 'xx']), ''.join(received_packet['boardcards']), 
                "", ITER_TABLE[self.num_boardcards])

        equity = equity.ev[0]
        do_reraise = random.random() > self.reraise_thres

        if equity < self.fold_thres:
            # TODO: Implement bluffing / call here
            if CHECK in avail_actions:
                return CHECK
            return FOLD

        elif equity > self.raise_thres and (self.is_new_round or do_reraise): 
            winning_factor = ((equity - self.fold_thres) / (1 - self.fold_thres))**POWER
            if BET in avail_actions:
                amount = self.bet_handler(winning_factor)
                return BET + ":" + str(amount)
            elif RAISE in avail_actions:
                amount = self.raise_handler(winning_factor)
                return RAISE + ":" + str(amount)
        
        if CALL in avail_actions: 
            if self.should_call(equity):
                return CALL + ":" + str(self.call_amount)
            else:
                return FOLD

        return CHECK
Example #6
0
 def _calc(self, hands, board, dead, iters):
     key = (hands, board, dead, iters)
     if key in self.cache:
         return self.cache[key]
     strength = calc(hands, board, dead, iters).ev[0]
     self.cache[key] = strength
     return strength
Example #7
0
def index():
    if request.method == 'GET':
        return render_template('index.html')
    else:
        board = get_cards(request.form['board'])
        hole = get_cards(request.form['hole'], all=True)
        opponent = get_cards(request.form['opponent'], all=True)
        discard = get_cards(request.form['discard'])

        result = calc(hole + ":" + opponent, board, discard, 100000)

        if result is None:
            return render_template('index.html',
                                   result='fail',
                                   hole=hole,
                                   opponent=opponent,
                                   board=board,
                                   discard=discard)

        return render_template('index.html',
                               result='success',
                               evs=result.ev,
                               hole=hole,
                               opponent=opponent,
                               board=board,
                               discard=discard)
Example #8
0
 def bet(self, potSize, boardCards, lastActions, legalActions, timeBank):
     #LOCAL MACROS#
     CALC_ITERS = 1000
     
     #MAIN CODE#
     #Initial equity calculation
     hole_cards_str = self.to_str(self.holeCards) + ':xxx'
     board_cards_str = self.to_str(boardCards)
     discard_str = self.to_str(self.discards)
     e = calc(hole_cards_str, board_cards_str, discard_str, CALC_ITERS).ev[0]
              
     #Gathers variables for input into threshold and bet functions
     opponent = self.opponent
     button = self.button
     if len(boardCards) == 0: betting_round = 0
     else: betting_round = len(boardCards) - 2
     current_bet = self.normalize_bet(self.current_bet)
     r1, r2 = random(), random()
     
     print 'time:', timeBank
     print 'betting round:', betting_round
     print 'your_equity', e
     
     #Updates current opponent bet
     opponent.update_bet_sequence(potSize, self.current_bet, betting_round)
     
     #Applies threshold function
     if e < self.threshold_function(opponent, self.current_bet, button, betting_round, r1):
         return self.try_fold(legalActions)
     #If threshold is met, makes bet  
     else:
         bet_amount = self.denormalize_bet(self.bet_function(opponent, e, button, betting_round, r2))
         return self.try_bet(bet_amount, potSize, legalActions)
Example #9
0
    def add_hand_data_pt(self, hand, board, bet_seq, button):
        #LOCAL MACROS#
        CALC_ITERS = 1000
        POLY_DEGREE = 1

        #MAIN CODE#
        #Makes hand inut for equity calculation
        h = hand + ':xx'
        #For each betting phase with board cards
        for i in xrange(0,4):
            
            #Stores total bet made on that phase
            self.play_history[button][i]['bet'].append(bet_seq[i])
            
            #Stores equity of the hand that the opponent possesed at the time of the bet
            if i == 0: b = ''
            else: b = self.to_str(board[:3+i])
            d = ''
            e = calc(h,b,d,CALC_ITERS).ev[0]
            self.play_history[button][i]['equity'].append(e)
            #print '_____'
            #print 'PLAY_HISTORY', i, button, self.play_history[button][i]
            #print '_____'

            #Performs polynomial regression to determine the equity to bet function and a bet to equity function
            l1 = polyfit(self.play_history[button][i]['equity'], self.play_history[button][i]['bet'], POLY_DEGREE)
            for k in range(POLY_DEGREE + 1): l1[k] = float(l1[k])
            self.e_to_b_lib[button][i] = l1
            
            l2 = polyfit(self.play_history[button][i]['bet'], self.play_history[button][i]['equity'], POLY_DEGREE)
            for k in range(POLY_DEGREE + 1): l2[k] = float(l2[k])
            self.b_to_e_lib[button][i] = l2

            #Checks to see if equity threshold should change based on new betting evidence.
            if e < self.equity_floor_lib[button][i]: self.equity_floor_lib[button][i] = e
Example #10
0
def evaluator(request):
	try:
		# TODO: need to check if hand range (request body) is null, and also insert ALL hands for second range
		result = pbots_calc.calc(request.body + ":xx","","",1000000)
		if result:
			return HttpResponse(str(result))
		else:
			return HttpResponse("Error")
	except:
		return HttpResponse("Error")
Example #11
0
	def calculateEquityStat (self, name, hand, numActivePlayersBeforeFold, boardcards, iter):
		for i in range(len(numActivePlayersBeforeFold)):
			numBc = I_TO_NUM_BC[i]
			if numActivePlayersBeforeFold[i] == 2:
				eq = 0
				if numBc == 0:
					eq = self.equity_table_2[hand]
				else:
					eq = pbots_calc.calc(':'.join([hand, 'xx']), ''.join(boardcards[:numBc]), "", iter).ev[0]
				self.minEquityTwo[name][numBc] = min(eq, self.minEquityTwo[name][numBc])
				self.averageEquityTwo[name][numBc] = calcEWMA (self.alpha, eq, self.averageEquityTwo[name][numBc])
			elif numActivePlayersBeforeFold[i] == 3:
				eq = 0
				if i == 0:
					eq = self.equity_table_3[hand]
				else:
					eq = pbots_calc.calc(':'.join([hand, 'xx', 'xx']), ''.join(boardcards[:numBc]), "", iter).ev[0]
				self.minEquityThree[name][numBc] = min(eq, self.minEquityThree[name][numBc])
				self.averageEquityThree[name][numBc] = calcEWMA (self.alpha, eq, self.averageEquityThree[name][numBc])
def determineBestDiscardFast(hand, board, min_improvement=0.02, iters=100):
    """
    min_improvement: the EV % that swapping must increase our hand by in order to go for the swap

    Returns:
    -whether we should swap
    -if so, the index of the card in our hand we should swap (0 or 1)
    -the avg. EV of swapping that card
    -the original EV of our hand as is 
    """

    # if we were to keep a card, determine which one is best
    keepCard = determineBestCardToKeep(hand, board)
    #print "Playoff thinks we should discard:", 1-keepCard

    boardStr = convertSyntax(board)
    originalHandEV = calc("%s:xx" % convertSyntax(hand), boardStr, "", 1000).ev[0]

    numCards = 0
    swapEVSum = 0
    for card in FULL_DECK:
        if card in board or card in hand:
            continue
        else:
            # increment
            numCards += 1

            cardstr = convertSyntax(card)

            # remember, we want to KEEP our keepCard and swap the other card!!!
            swapStr = "%s%s%s" % (cardstr,convertSyntax(hand[keepCard]),":xx")
            swapRes = calc(swapStr, boardStr, "", iters)
            swapEVSum += swapRes.ev[0]

    # calculate the average EV of swapping the card besides our keepCard
    avgSwapEV = float(swapEVSum) / numCards

    # if either swap increases EV by more than 5%
    if avgSwapEV > originalHandEV + min_improvement:
        return (True, 1-keepCard, avgSwapEV, originalHandEV)
    else:
        return (False, None, 0, originalHandEV)
Example #13
0
 def _calc(self, hands, board, dead, iters):
     key = (hands, board, dead, iters)
     if key in self.cache:
         return self.cache[key]
     result = calc(hands, board, dead, iters)
     if result is not None:
         strength = result.ev[0]
         self.cache[key] = strength
     else:
         print "Warning: calc returned None"
         strength = 0.5
     return strength
def determine_winner(p0_hand, p1_hand, board):
	assert len(board) == FLOP_SIZE + TURN_SIZE + RIVER_SIZE, "Error: cannot determine winner on incomplete board"
	handStr = "%s:%s" % (convert_card_syntax(p0_hand), convert_card_syntax(p1_hand))
	boardStr = convert_card_syntax(board)

	res = pbots_calc.calc(handStr, boardStr, "", 1) # hand against board, no dead cards, 1 iteration
	if abs(res.ev[0] - 1.0) < 0.01:
		return 0 # player 0 wins
	elif abs(res.ev[1] - 1.0) < 0.01:
		return 1 # player 1 wins
	else:
		return 3 # represents a tie
Example #15
0
def generate_equity_points(combos_filepath):
    if os.path.isfile('./jsons/points.csv'):
        print(
            "DO NOT OVERWRITE points.csv, takes forever to generate. Proceeding."
        )
        return

    # Need the RANGE_TO_HANDS_MAP.json
    range_to_hands = json.load(open('./jsons/RANGE_TO_HANDS_MAP.json', 'r'))

    i = 0

    points = pd.DataFrame()

    for combos in pd.read_csv(combos_filepath, header=0, chunksize=500000):
        # FLAG: EMERGENCY DATA THINNING TO MEET DEADLINE
        combos = combos.sample(frac=0.1)

        print("Chunk: ", i)
        # Convert these to lists
        print("Converting to lists")
        combos['hand'] = combos.hand.apply(
            lambda x: [int(s) for s in x.strip('][').split(', ')])
        combos['board'] = combos.board.apply(
            lambda x: [int(s) for s in x.strip('][').split(', ')])

        # Convert these to strings
        print("Converting to strings")
        combos['hand'] = combos.hand.apply(
            lambda x: mechanics.convert_card_syntax(_map_integer_to_card(x)))
        combos['board'] = combos.board.apply(
            lambda x: mechanics.convert_card_syntax(_map_integer_to_card(x)))

        print("Calculating equities")
        p = pd.DataFrame()
        # For each hand/board combo, calculate equity of hand vs each of 8 ranges against the board to create an 8-D point. Add these 8-D points to a list)
        for j in range(8):
            # This line is a nested set of functions
            p['equity_%x' % j] = combos.apply(lambda row: int(100 * round(
                pbots_calc.calc(
                    row['hand'] + ":" + ",".join(range_to_hands[str(j)]), row[
                        'board'], "", 100).ev[0], 2)),
                                              axis=1)

        print("Writing")
        points.append(p)
        if i == 0:
            p.to_csv('./jsons/points.csv', mode='w', header=True)
        else:
            p.to_csv('./jsons/points.csv', mode='a', header=False)

        i += 1
Example #16
0
 def get_calc_hand_strength(self, cards, board_cards, discarded_cards):
     """
     Gets the effective hand strength of your cards at any stage of the game using the pbots_calc library.
     """
     if calc is not None:
         result = calc(''.join(cards) + ':xx', ''.join(board_cards),
                       ''.join(discarded_cards), 1000)
         if result is not None:
             strength = result.ev[0]
         else:
             strength = random.random()
     else:
         strength = random.random()
     return strength
Example #17
0
    def updateEquities(self):
        # consider num of active players
        # group by boolean profiles
        # find all combinations of boolean profiles
        # query equity calculator
        # generate full list
        if self.oppAProbDist == None:
            combinedList = self.oppBProbDist.distribution.keys()
        elif self.oppBProbDist == None:
            combinedList = self.oppAProbDist.distribution.keys()
        else:
            combinedList = list(set(list(self.oppAProbDist.distribution.keys()) + list(self.oppBProbDist.distribution.keys())))

        # without boolean check
        self.equities = {}
        for keyA in combinedList: # should be combined distribution
            eq = pbots_calc.calc([(self.holeCard1,self.holeCard2),keyA], self.boardCards, '', 1000).ev[0]
            self.equities[keyA] = eq
def abstract_hand_postflop(hand, board, nodes, range_to_hands):
    """
	Abstracts a NLH hand to one of 100 hand buckets, depending on the board
	@hand: a List of exactly 2 Card objects
	@board: a List of 3, 4, or 5 Card objects
	@nodes: a list of arrays representing centroid coordinates to abstract to
	@range_to_hands: a dictinoary that maps a range [0, 7] to the corresponding list of hands in that range

	Returns a number [0, 99] representing the cluster index of abstraction
	"""
    assert len(
        hand) == 2, "Error in abstraction: incorrectly formatted hand length"
    assert len(board) in [
        3, 4, 5
    ], "Error in abstraction: incorrectly formatted board length"

    # Get the sorted, string form of the hand
    sorted_cards = sort_cards(hand)
    hand_str = mechanics.convert_card_syntax(sorted_cards)

    # Abstract the board (i.e. sort the streets by rank then by suit).
    # Since we are using imperfect recall, we do not need to maintain distinction between streets.
    ordered_board = sorted(board, key=lambda c: (c.rank, c.suit))
    board_str = mechanics.convert_card_syntax(ordered_board)

    # Calculate equities to get 8_D point
    equities = [None] * 8
    for j in range(8):
        opp_hands = range_to_hands[str(j)]
        opp_hands_str = ",".join(opp_hands)
        equities[j] = int(100 * round(
            pbots_calc.calc(hand_str + ":" + opp_hands_str, board_str, "",
                            100000).ev[0], 2))

    equities = np.asarray(equities)

    def closest_node(node, nodes):
        nodes = np.asarray(nodes)
        dist_2 = np.sum((nodes - node)**2, axis=1)
        return np.argmin(dist_2)

    closest = closest_node(equities, nodes)

    return str(closest)
Example #19
0
def pbots_calc_clean(handlist,boardlist,discarded):
    
    # set for 100 Monte Carlo iterations 
    oddslist = str(pbots_calc.calc(handlist,boardlist,discarded,100))
    
    oddslist = list(oddslist)
    for char in oddslist:
        if char in ["[","]","(",")",","," "]:
            oddslist.remove(char)
    for char in oddslist:
        if char in ["[","]","(",")",","," "]:
            oddslist.remove(char)
    for char in oddslist:
        if char in ["[","]","(",")",","," "]:
            oddslist.remove(char)
    oddslist=''.join(oddslist)
    oddslist = oddslist.split("'")
    oddslist.remove('')
    return oddslist
Example #20
0
 def discard(self, potSize, boardCards, lastActions, legalActions, timeBank):
     #LOCAL MACROS#
     CALC_ITERS = 1000
     
     #MAIN CODE#
     #Seeks to keep the cards that afford the maximum equity against an arbitrary pair of cards
     #by computing the equity of 2 card subsets of hand
     print 'time:', timeBank
     v, l, discard = 0, list(self.holeCards), None
     for i in xrange(3):
         j = (i + 1) % 3
         k = (i + 2) % 3
         h = l[i] + l[j] + ':xx'
         b = self.to_str(boardCards)
         d = l[k]
         c = calc(h,b,d,CALC_ITERS)
         if c.ev[0] > v:
             discard = l[k]
     self.holeCards.remove(discard)
     self.discards.add(discard)
     return 'DISCARD:' + discard
def determineWinner(p1_hand, p2_hand, board):
    """
    Given a board with 5 cards, and two hands, determines the winner on the river.
    0: Player 1 wins
    1: Player 2 wins
    3: Players tie
    """
    assert len(board)==5, "Error: cannot determine winner on a board with less than 5 cards"
    handstr = "%s:%s" % (convertSyntax(p1_hand), convertSyntax(p2_hand))
    boardstr = convertSyntax(board)

    res = calc(handstr, boardstr, "", 1)

    if abs(res.ev[0]-1.0) < 0.01:
        return 0
    elif abs(res.ev[1]-1.0) < 0.01:
        return 1
    else:
        # print " ----------- Tie?--------------"
        # print "P1:%f P2: %f" % (res.ev[0], res.ev[1])
        return 3 # tie player
 def pbots_calc_clean(self,handlist,boardlist,discarded):
     
     # set for 10000 Monte Carlo iterations
     #d1 = datetime.now()
     oddslist = str(pbots_calc.calc(handlist,boardlist,discarded,10000))
     #d2 = datetime.now()
     #print d2-d1
     oddslist = list(oddslist)
     for char in oddslist:
         if char in ["[","]","(",")",","," "]:
             oddslist.remove(char)
     for char in oddslist:
         if char in ["[","]","(",")",","," "]:
             oddslist.remove(char)
     for char in oddslist:
         if char in ["[","]","(",")",","," "]:
             oddslist.remove(char)
     oddslist=''.join(oddslist)
     oddslist = oddslist.split("'")
     oddslist.remove('')
     return oddslist
Example #23
0
def test3():
    range_to_hands = json.load(open('./jsons/RANGE_TO_HANDS_MAP.json', 'r'))

    combos = [['AdKs', 'TsJs4d'], ['ThJd', 'TsJs4d'], ['Qs8c', 'TsJs4d'],
              ['Jc3d', 'TsJs4d']]

    points = []
    for combo in combos:
        equities = [None] * 8
        hand_str = combo[0]
        board_str = combo[1]
        for j in range(8):
            opp_hands = range_to_hands[str(j)]
            opp_hands_str = ",".join(opp_hands)
            equities[j] = int(100 * round(
                pbots_calc.calc(hand_str + ":" + opp_hands_str, board_str, "",
                                100000).ev[0], 2))
        points.append(equities)
    points_matrix = np.matrix(points)
    print(points_matrix)
    print(type(points_matrix))

    kmeans = KMeans(n_clusters=2).fit(points_matrix)
    print(type(kmeans.cluster_centers_))
# pbots_calc is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# pbots_calc in a file in teh toplevel directory called "GPLv3".  If not, see
# <http://www.gnu.org/licenses/>.
#

import pbots_calc
import sys
"""
Simple command line tool for equity calculations. Demonstrates how to use the
pbots_calc library python wrapper.
"""

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("usage: %s hand1:hand2:hand... [board [dead]]" % sys.argv[0])
        sys.exit(0)
    board = ""
    dead = ""
    if len(sys.argv) >= 3:
        board = sys.argv[2]
        if len(sys.argv) >= 4:
            sys.argv[3]
    argument = sys.argv[1]
    r = pbots_calc.calc(argument, board, dead, 1000000)
    if r:
        print(set(zip(r.hands, r.ev)))
Example #25
0
def index(request):
	r = pbots_calc.calc("ATs:89s","","",1000000)
	if r:
		return HttpResponse(str(r))
	else:
		return HttpResponse("error")
Example #26
0
    def get_action(self,
                   game,
                   round,
                   pot,
                   cards,
                   board_cards,
                   legal_moves,
                   cost_func,
                   move_history,
                   time_left,
                   min_amount=None,
                   max_amount=None):
        '''
        Where the magic happens - your code should implement this function.
        Called any time the server needs an action from your bot.

        Arguments:
        game: the pokerbots.Game object.
        round: the pokerbots.Round object.
        pot: the pokerbots.Pot object.
        cards: an array of your cards, in common format.
        board_cards: an array of cards on the board. This list has length 0, 3, 4, or 5.
        legal_moves: a set of the move classes that are legal to make.
        cost_func: a function that takes a move, and returns additional cost of that move. Your returned move will raise your pot.contribution by this amount.
        move_history: a list of moves that have occurred during this round so far, earliest moves first.
        time_left: a float of the number of seconds your bot has remaining in this match (not round).
        min_amount: if BetAction or RaiseAction is valid, the smallest amount you can bet or raise to (i.e. the smallest you can increase your pip).
        max_amount: if BetAction or RaiseAction is valid, the largest amount you can bet or raise to (i.e. the largest you can increase your pip).
        '''

        if self.check_player and round.hand_num == 1:
            self.check_player = False
            if len(move_history) % 2 == 0:
                self.opp = 'B'
            else:
                self.opp = 'A'
            print("we think opponent is player " + self.opp)

        last_move = move_history[-1]
        if last_move == 'CHECK:' + self.opp:
            self.opp_check += 1
            # print(last_move + ", opponent check count = " + str(self.opp_check))

        if self.stop and FoldAction in legal_moves:
            return FoldAction()
        elif self.stop and CheckAction in legal_moves:
            return CheckAction()

        if round.hand_num == 50:
            if self.fold_before_flop > 15:
                self.opp_bluff_before_flop = True
                print("over 15 self.fold_before_flop")
            if self.fold_before_turn > 20:
                self.opp_bluff_before_turn = True
                print("over 15 self.fold_before_turn")

        if calc is not None:
            result = calc(''.join(cards) + ':xx', ''.join(board_cards),
                          ''.join(self.discarded_cards), 1000)
            if result is not None:
                strength = result.ev[0]
            else:
                print "Warning: calc returned None"
                strength = random.random()
        else:
            strength = random.random()
        #sophia

        # anti bluff block

        if min_amount == 160:
            strength = 0.95
            if CallAction in legal_moves:
                return CallAction()

        if len(board_cards) == 5 and FoldAction in legal_moves:
            # check if last move was opponent bet
            last_move = move_history[-1]
            if "BET" in last_move and last_move[-1] == self.opp:
                if len(self.opp_river_bet) > 3:
                    if round.hand_num < 400:
                        best_fit = stats.linregress(
                            np.array(self.opp_river_bet),
                            np.array(self.opp_river_strength))
                        self.slope = best_fit[0]
                        self.intercept = best_fit[1]

                    self.predicted_strength = min(
                        1,
                        int(last_move.split(':')[1]) * self.slope +
                        self.intercept)
                    print("slope = " + str(self.slope) + ", intercept = " +
                          str(self.intercept))
                    print("predicted strength: " +
                          str(self.predicted_strength))
                    print("our strength: " + str(strength))
                    if self.predicted_strength >= strength + 0.05:
                        print("folded bc opponent's bet indicates stronger")
                        if round.hand_num <= 20:
                            if min_amount <= 60:
                                self.fold += 1
                        return FoldAction()

        if ExchangeAction in legal_moves and self.exchange_count < 3 and len(
                board_cards) >= 3:  # decision to exchange
            # exchange logic
            # if we exchange, we should update self.discarded_cards
            exchange_cost = cost_func(ExchangeAction())
            exchange_ev = 0.6 * pot.opponent_total - 0.4 * (pot.total +
                                                            exchange_cost)
            check_ev = strength * pot.opponent_total - (1. -
                                                        strength) * pot.total
            if exchange_ev > check_ev and len(
                    board_cards
            ) > 3 and strength <= 0.75:  # exchanging is worth it
                self.discarded_cards |= set(
                    cards)  # keep track of the cards we discarded
                self.exchange_count += 1
                return ExchangeAction()
            return CheckAction()

        if self.fold >= 11 and len(board_cards) == 3 and min_amount <= 40:
            if CallAction in legal_moves:
                print("antibluff 1")
                return CallAction()
        if self.fold >= 11 and len(board_cards) == 4 and min_amount <= 50:
            if CallAction in legal_moves:
                print("antibluff 1")
                return CallAction()
        if self.fold >= 11 and len(board_cards) == 5 and min_amount <= 60:
            if CallAction in legal_moves:
                print("antibluff 1")
                return CallAction()

        if len(board_cards) == 0 and strength * 0.5 > random.random():
            if RaiseAction in legal_moves and min_amount < 10:
                raise_amt = min_amount + 5 * (random.random())
                raise_amt = max(raise_amt, min_amount)
                raise_amt = min(raise_amt, max_amount)
                return RaiseAction(raise_amt)

        if len(board_cards) == 3 and strength * 0.5 > random.random():
            if RaiseAction in legal_moves and min_amount < 10:
                raise_amt = min_amount + 5 * (random.random())
                raise_amt = max(raise_amt, min_amount)
                raise_amt = min(raise_amt, max_amount)
                return RaiseAction(raise_amt)

        if not (ExchangeAction in legal_moves and self.exchange_count < 3
                and len(board_cards) >= 3
                ):  # decision to commit resources to the pot

            continue_cost = cost_func(
                CallAction()) if CallAction in legal_moves else cost_func(
                    CheckAction())
            # figure out how to raise the stakes
            commit_amount = 0
            if len(board_cards) == 0:
                commit_amount = int(pot.pip + continue_cost +
                                    (strength * random.random()) *
                                    (pot.grand_total + continue_cost))
            elif len(board_cards) == 3:
                commit_amount = int(pot.pip + continue_cost +
                                    (1.5 * strength * random.random()) *
                                    (pot.grand_total + continue_cost))
            elif len(board_cards) == 4:  # should be between 0.5 and 0.75
                commit_amount = int(pot.pip + continue_cost +
                                    (2 * strength * random.random()) *
                                    (pot.grand_total + continue_cost))
            elif len(board_cards) == 5:
                commit_amount = int(pot.pip + continue_cost +
                                    (2.25 * strength * random.random()) *
                                    (pot.grand_total + continue_cost))
            if min_amount is not None:
                commit_amount = max(commit_amount, min_amount)
                commit_amount = min(commit_amount, max_amount)

            if continue_cost == 0:
                if BetAction in legal_moves and strength > 0.95 and len(
                        board_cards) >= 4:
                    commit_action = BetAction(max_amount)
                else:
                    commit_action = CheckAction()

            if continue_cost > 0:
                if len(board_cards) != 0:  #1
                    self.num_of_bets += 1
                if self.num_of_bets == 2 and strength < 0.9:  #2
                    strength -= 0.03
                if self.num_of_bets == 3 and strength < 0.9:  #3
                    strength -= 0.05
                if continue_cost > 20 and strength < 1:  #4.1
                    strength -= 0.05
                    if strength < 0.8 and len(board_cards) >= 4:  #4.2
                        strength -= 0.05
                if continue_cost > 50 and strength < 0.95:  #5
                    strength -= 0.11
                if pot.opponent_num_exchanges > 0:  #6
                    strength -= 0.05
                if continue_cost < 5 and len(board_cards) == 5:  #7
                    strength += 0.1

                if continue_cost > 0:
                    if RaiseAction in legal_moves and len(
                            board_cards) == 5 and strength >= 0.95:
                        commit_action = RaiseAction(commit_amount)
                    elif CallAction in legal_moves:  # we are contemplating an all-in call
                        commit_action = CallAction()
                    else:  # only legal action
                        return CheckAction()

                pot_odds = float(continue_cost) / (pot.grand_total +
                                                   continue_cost) + 0.1
                if len(board_cards) == 0 and strength > 0.5:
                    return commit_action
                if strength >= pot_odds or (self.opp_bluff_before_turn
                                            and len(board_cards) == 3) or (
                                                (len(board_cards) == 0) and
                                                self.opp_bluff_before_flop):
                    if strength >= 0.7:  # commit more sometimes
                        return commit_action
                    last_move = move_history[-1]
                    if 'BET' in last_move and len(
                            board_cards) == 3 and last_move[-1] == self.opp:
                        if int(last_move.split(':')
                               [1]) > 300 and FoldAction in legal_moves:
                            print(last_move)
                            print('sophia flop all in fold')
                            if round.hand_num <= 20:
                                if min_amount <= 60:
                                    self.fold += 1
                            return FoldAction()
                    return CallAction()
                else:  # staying in the game has negative EV
                    if round.hand_num <= 20:
                        if min_amount <= 60:
                            self.fold += 1
                            print("hand" + str(round.hand_num) + ": " +
                                  str(self.fold))
                    return FoldAction()

            elif continue_cost == 0:
                if len(board_cards) == 3:
                    strength += 0.02
                if len(board_cards) == 4:
                    strength += 0.05
                if len(board_cards) == 5:
                    strength += 0.1
                if self.opp_check >= 3 and strength > 0.6 and pot.grand_total >= 10 and pot.grand_total <= 20:
                    return commit_action
                if self.opp_check > 4:
                    strength += 0.1
                if strength >= 0.6 and BetAction in legal_moves or RaiseAction in legal_moves:  # commit more sometimes
                    return commit_action
                elif BetAction in legal_moves or RaiseAction in legal_moves and random.random(
                ) < strength:  # balance bluffs with value bets
                    return commit_action
                return CheckAction()

        if self.fold >= 11 and len(board_cards) >= 3 and min_amount <= 40:
            if CallAction in legal_moves:
                print("antibluff 2")
                return CallAction()

        if CheckAction in legal_moves:
            return CheckAction()
        elif CallAction in legal_moves and strength >= 0.7:
            return CallAction()
        elif FoldAction in legal_moves:
            if round.hand_num <= 20:
                if min_amount <= 60:
                    self.fold += 1
                    print("hand" + str(round.hand_num) + ": " + str(self.fold))
            return FoldAction()
Example #27
0
    def handle_round_over(self, game, round, pot, cards, opponent_cards,
                          board_cards, result, new_bankroll,
                          new_opponent_bankroll, move_history):
        '''
        Called when a round ends. Called Game.num_rounds times.

        Arguments:
        game: the pokerbots.Game object.
        round: the pokerbots.Round object.
        pot: the pokerbots.Pot object.
        cards: the cards you held when the round ended.
        opponent_cards: the cards your opponent held when the round ended, or None if they never showed.
        board_cards: the cards on the board when the round ended.
        result: 'win', 'loss' or 'tie'
        new_bankroll: your total bankroll at the end of this round.
        new_opponent_bankroll: your opponent's total bankroll at the end of this round.
        move_history: a list of moves that occurred during this round, earliest moves first.

        Returns:
        Nothing.
        '''

        self.num_of_bets = 0

        if new_bankroll > (1000 - round.hand_num) * 1.5 + 10:
            self.stop = True

        self.games[result] += 1
        if round.hand_num <= 50:
            flop = False
            turn = False
            for moves in move_history:
                if "FLOP" in moves:
                    flop = True
                if "TURN" in moves:
                    turn = True

                if self.opp == 'B':
                    if moves == "FOLD:A":
                        if not flop:
                            self.fold_before_flop += 1
                        elif not turn:
                            self.fold_before_turn += 1
                    if moves == "FOLD:" + self.opp:
                        if not flop:
                            self.bluff_before_flop += 1
                        elif not turn:
                            self.bluff_before_turn += 1
                else:  # self.opp == 'A'
                    if moves == "FOLD:B":
                        if not flop:
                            self.fold_before_flop += 1
                        elif not turn:
                            self.fold_before_turn += 1
                    if moves == "FOLD:A":
                        if not flop:
                            self.bluff_before_flop += 1
                        elif not turn:
                            self.bluff_before_turn += 1
        # print(self.fold_before_flop, self.fold_before_turn, self.bluff_before_turn, self.bluff_before_flop)

        # save info on how much B bet and the strength of their hand

        if len(
                board_cards
        ) == 5 and opponent_cards != None:  # make sure after river and opponent revealed cards
            # iterate through move history to look for opponent's first bet after river
            river = False
            for element in move_history:
                if "RIVER" in element:
                    river = True

                if river and "BET" in element:  # only look at moves that are bets after river
                    # move is in the form "BET:bet_amt:player" so cut first four chars of move and splice the rest by the colon
                    info = element[4:].split(':')
                    if info[1] == self.opp:  # only care about B's bet
                        # add key info[0] with value strength of opponent_cards
                        if calc is not None:
                            opp_result = calc(''.join(opponent_cards) + ':xx',
                                              ''.join(board_cards), '', 1000)
                            self.opp_river_bet.append(int(info[0]))
                            self.opp_river_strength.append(opp_result.ev[0])
                        else:
                            opp_result = random.random()
Example #28
0
# pbots_calc is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# pbots_calc in a file in teh toplevel directory called "GPLv3".  If not, see
# <http://www.gnu.org/licenses/>.
#

import pbots_calc
import sys
"""
Simple command line tool for equity calculations. Demonstrates how to use the
pbots_calc library python wrapper.
"""

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print "usage: %s hand1:hand2:hand... [board [dead]]" % sys.argv[0]
        sys.exit(0)
    board = ""
    dead = ""
    if len(sys.argv) >= 3:
        board = sys.argv[2]
        if len(sys.argv) >= 4:
            dead = sys.argv[3]

    r = pbots_calc.calc(sys.argv[1], board, dead, 1000000)
    if r:
        print zip(r.hands, r.ev)
Example #29
0
    def get_best_action(self, received_packet, avail_actions = []):
        equity = None

        # set thresholds
        # if not self.one_out:
        #     self.fold_thres = THREE_FOLD_THRES_TABLE[self.num_boardcards]
        #     self.raise_thres = THREE_RAISE_THRES_TABLE[self.num_boardcards]
        #     self.opp_fold_thres = THREE_opp_fold_thres
        # else:
        #     self.fold_thres = TWO_FOLD_THRES_TABLE[self.num_boardcards]
        #     self.raise_thres = TWO_RAISE_THRES_TABLE[self.num_boardcards]
        #     self.opp_fold_thres = TWO_opp_fold_thres

        # see if we could use precomputed equity

        if self.num_active_players == 2 or self.one_folded == True:
            self.fold_thres = TWO_FOLD_THRES_TABLE[self.num_boardcards]
            self.raise_thres = TWO_RAISE_THRES_TABLE[self.num_boardcards]
            self.opp_fold_thres = self.STATS.getFoldPercent(self.guy_active)
            if self.num_boardcards == 0:
                equity = self.equity_table_2[self.my_hand]
            else:
                equity = pbots_calc.calc(':'.join([self.my_hand, 'xx']), ''.join(received_packet['boardcards']), 
                    "", self.monte_carlo_iter)
                equity = equity.ev[0]
        else:
            self.fold_thres = THREE_FOLD_THRES_TABLE[self.num_boardcards]
            self.raise_thres = THREE_RAISE_THRES_TABLE[self.num_boardcards]
            self.opp_fold_thres = self.opp1_skill * self.STATS.getFoldPercent(self.opponent_1_name) + self.opp2_skill * self.STATS.getFoldPercent(self.opponent_2_name) 
            if self.num_boardcards == 0:
                equity = self.equity_table_3[self.my_hand]
            else:
                equity = pbots_calc.calc(':'.join([self.my_hand, 'xx', 'xx']), ''.join(received_packet['boardcards']), 
                    "", self.monte_carlo_iter)
                equity = equity.ev[0]



        do_reraise = random.random() < self.opp_fold_thres

        # print 'FOLD T: ' + str(self.opp_fold_thres) 
        # print 'EQUITY: ' + str(equity)

        own_a_lot_of_chips = self.my_stacksize > LOTS_OF_CHIPS
        winning_factor = ((equity - self.fold_thres) / (1 - self.fold_thres))**POWER

        # TODO: Raise a little if they checked last turn

        # if equity < self.fold_thres and ((own_a_lot_of_chips != True) or (self.num_boardcards != 0)):
        #     # TODO: Implement bluffing / call here
        #     if CHECK in avail_actions:
        #         # bet a little bit if possible to exploit bots who fold to small raises: (but dont do this all the time)
        #         # if BET in avail_actions and self.my_stacksize > BET_SMALL_LIKELIHOOD[self.num_boardcards]:
        #         if False:
        #             random_nig = random.random()
        #             # foldPerc = 0.0
        #             # for name in self.opp_dict:
        #             #     if self.opp_dict[name].status == ACTIVE:
        #             #         foldPerc += self.STATS.foldPercentage[name]
        #             # if not self.one_folded:
        #             #     foldPerc = foldPerc / 2
        #             if random_nig < self.opp_fold_thres:
        #                 print "MINBET: " + str(self.minBet)
        #                 return BET + ":" + str(self.minBet)
        #         return CHECK
        #     return FOLD


        # Subroutines we use to make our lives easier:
        #####################################################################################################
        def do_call ():
            if self.should_call(equity):
                self.highestRaiseAmtThisRnd = self.call_amount
                return CALL + ":" + str(self.call_amount)
            else:
                return FOLD

        def do_raise_preflop ():
            if self.my_hand in self.boss_class1:
                if self.lastRaiser in [TYPE_STA] and self.my_stacksize > SUFFICIENT_CHIPS:
                    return CALL + ":" + str(self.call_amount)
                # raise a lot
                self.highestRaiseAmtThisRnd = self.maxRaise
                return RAISE + ":" + str(self.maxRaise)
            elif self.my_hand in self.boss_class2:
                if self.num_active_players == 3 and self.one_folded == False:
                    if (self.opp_dict[self.opponent_1_name].playerType not in [TYPE_STA, TYPE_TA, TYPE_LP]) and \
                        (self.opp_dict[self.opponent_2_name].playerType not in [TYPE_STA, TYPE_TA, TYPE_LP]):
                        # raise a lot
                        self.highestRaiseAmtThisRnd = self.maxRaise
                        return RAISE + ":" + str(self.maxRaise)
                    else:
                        self.highestRaiseAmtThisRnd = self.maxRaise
                        return RAISE + ":" + str(self.minRaise)
                elif self.opp_dict[self.guy_active].playerType not in [TYPE_STA, TYPE_TA, TYPE_LP]:
                    # raise a lot
                    self.highestRaiseAmtThisRnd = self.maxRaise
                    return RAISE + ":" + str(self.maxRaise)
                else:
                    self.highestRaiseAmtThisRnd = self.minRaise
                    return RAISE + ":" + str(self.minRaise)
            # bet a little in general
            self.highestRaiseAmtThisRnd = self.minRaise
            return RAISE + ":" + str(self.minRaise)

        def do_call_preflop ():
            raiserType = self.opp_dict[self.lastRaiser].playerType
            if raiserType in [TYPE_STA, TYPE_TA, TYPE_LP]:
                if self.my_hand in self.boss_class1:
                    return do_call()
                else:
                    # do not engage
                    return FOLD
            elif raiserType != TYPE_LA:
                if self.my_hand in self.boss_class1 or self.my_hand in self.boss_class2:
                    return do_call()
                else:
                    return FOLD
            else:
                return do_call()
        #####################################################################################################



        if equity < self.fold_thres:
            if self.isPreflop:
                if self.handPosition == BUTTON:
                    if self.opp_dict[self.opponent_1_name].playerType == TYPE_LA or self.opp_dict[self.opponent_2_name].playerType == TYPE_LA:
                        if (self.fold_thres - equity) < TOLERANCE_FOR_LA:
                            if CALL in avail_actions:
                                if self.call_amount == self.bigBlind and RAISE in avail_actions:
                                    self.highestRaiseAmtThisRnd = self.minRaise
                                    return RAISE + ":" + str(self.minRaise)
                return FOLD

            if BET in avail_actions and self.minBet <= self.bigBlind:
                if self.oppCheckedThisRound:
                    random_nig = random.random()
                    if random_nig < self.opp_fold_thres:
                        # print "MINBET: " + str(self.minBet)
                        self.highestRaiseAmtThisRnd = self.minBet
                        return BET + ":" + str(self.minBet)
            if CHECK in avail_actions:
                return CHECK
            if CALL in avail_actions:
                # if relatively smalll:
                if self.inc_call_amount <= self.bigBlind or \
                    (self.isPreflop == False and (self.inc_call_amount < 2 * self.bigBlind or self.inc_call_amount < 0.07 * self.potsize)):
                    return do_call()
            return FOLD



        # elif equity > self.raise_thres and (self.is_new_round or do_reraise): 
        elif equity > self.raise_thres:
            if self.isPreflop: # fun time!
                if self.handPosition == BUTTON:
                    if self.opp_dict[self.opponent_1_name].playerType == TYPE_LA or self.opp_dict[self.opponent_2_name].playerType == TYPE_LA:
                        if self.num_active_players == 2 or self.one_folded:
                            if self.opp_dict[self.guy_active].playerType == TYPE_LA:
                                # n***a will handle raising
                                return do_call()
                        else:
                            # n****s will handle the raising for us
                            return do_call()
                    if CALL in avail_actions:
                        if self.potsize > 5 * self.bigBlind:
                            return do_call_preflop()
                        else:
                            if RAISE in avail_actions:
                                return do_raise_preflop()
                            else:
                                return do_call_preflop()

                elif self.handPosition == BB:
                    if CALL in avail_actions: # someone raised
                        return do_call_preflop()
                    elif RAISE in avail_actions and self.potsize < 7:
                        return do_raise_preflop()
                    return CHECK

                elif self.handPosition == SB:
                    if CALL in avail_actions: 
                        if self.call_amount == self.bigBlind and RAISE in avail_actions:
                            return do_raise_preflop()
                        else: # someone raised
                            return do_call_preflop()

            else: 
                if BET in avail_actions:
                    amount = self.bet_handler(winning_factor)
                    return BET + ":" + str(amount)
                elif RAISE in avail_actions and do_reraise:
                    # if they raise a little, either counter raise or call
                    if self.should_call(equity):
                        amount = self.raise_handler(winning_factor)
                        return RAISE + ":" + str(amount)
                    else:
                        return FOLD


        # not in very good equity range
        if CHECK in avail_actions or BET in avail_actions:
            if self.oppCheckedThisRound:
                random_nig = random.random()
                if random_nig < self.opp_fold_thres:
                    # print "MINBET: " + str(self.minBet * 4)
                    self.highestRaiseAmtThisRnd = self.minBet * 4
                    return BET + ":" + str(self.minBet * 4)




        if CALL in avail_actions:
            # TODO: do preflop logic here
            if self.isPreflop:
                if self.handPosition == BUTTON or (self.handPosition == SB and self.num_active_players == 2):
                    if self.opp_dict[self.guy_active].playerType == TYPE_LA:
                        # n***a will handle raising
                        return do_call()
                    if self.potsize > 5 * self.bigBlind:
                        return do_call_preflop()
                    else:
                        if RAISE in avail_actions:
                            return do_raise_preflop()
                        else:
                            return do_call_preflop()
                elif self.handPosition == SB:
                    if self.call_amount == self.bigBlind:
                        return do_call()
                    else: # someone raised
                        return FOLD
                elif self.handPosition == BB:
                    # someone raised
                    if self.potsize <= 3 * self.bigBlind:
                        return do_call_preflop()
                    return FOLD

            else:
                return do_call ()

            # return do_call()

        # if CHECK in avail_actions:
        #     random_nig = random.random()
        #     if random_nig < self.opp_fold_thres:
        #         print "MINBET: " + str(self.minBet)
        #         return BET + ":" + str(self.minBet)

        return CHECK
Example #30
0
import pbots_calc

suits = ['h', 's', 'd', 'c']
numbers = ['2', '3', '4', '5', '6', '7', '8', '9', 't', 'j', 'q', 'k', 'a']
cards = []

for i in range(4):
	for j in range(13):
		cards.append(numbers[j] + suits[i])

for c1 in range(52):
	for c2 in range(51 - c1):
		c2 += c1 + 1
		for c3 in range(51 - c2):
			c3 += c2 + 1
			
			hand = cards[c1] + cards[c2] + cards[c3]
			equity = pbots_calc.calc(hand + ":xxx", '', '', 10000).ev[0]
			print hand + "=" + str(equity)
Example #31
0
def test():
	board = ""
	dead = ""
	r = pbots_calc.calc("4qo:jts+", "", "", 1000000)
	if r:
		print(list(zip(r.hands, r.ev)))
Example #32
0
import numpy as np

from pbots_calc import calc

RANKS = list('23456789TJQKA')
SUITS = list('cdhs')
DECK = [r + s for r in RANKS for s in SUITS]

preflop_strengths = []
for _ in range(100000):
    np.random.shuffle(DECK)
    preflop_strengths.append(calc(''.join(DECK[:2]) + ':xx', '', '', 1300).ev[0])
preflop = np.percentile(preflop_strengths, np.arange(1, 100))
np.savetxt('preflop.csv', preflop, delimiter=',')
Example #33
0
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# pbots_calc in a file in teh toplevel directory called "GPLv3".  If not, see
# <http://www.gnu.org/licenses/>.
#

import pbots_calc
import sys

"""
Simple command line tool for equity calculations. Demonstrates how to use the
pbots_calc library python wrapper.
"""

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print "usage: %s hand1:hand2:hand... [board [dead]]" % sys.argv[0]
        sys.exit(0)
    board = ""
    dead = ""
    if len(sys.argv) >= 3:
        board = sys.argv[2]
        if len(sys.argv) >=4:
            dead = sys.argv[3]

    r = pbots_calc.calc(sys.argv[1], board, dead, 1000000)
    if r:
        print zip(r.hands, r.ev)
Example #34
0
    def get_action(self,
                   game,
                   round,
                   pot,
                   cards,
                   board_cards,
                   legal_moves,
                   cost_func,
                   move_history,
                   time_left,
                   min_amount=None,
                   max_amount=None):
        '''
        Where the magic happens - your code should implement this function.
        Called any time the server needs an action from your bot.

        Arguments:
        game: the pokerbots.Game object.
        round: the pokerbots.Round object.
        pot: the pokerbots.Pot object.
        cards: an array of your cards, in common format.
        board_cards: an array of cards on the board. This list has len 0, 3, 4, or 5.
        legal_moves: a set of the move classes that are legal to make.
        cost_func: a function that takes a move, and returns additional cost of that move. Your returned move will raise your pot.contribution by this amount.
        move_history: a list of moves that have occurred during this round so far, earliest moves first.
        time_left: a float of the number of seconds your bot has remaining in this match (not round).
        min_amount: if BetAction or RaiseAction is valid, the smallest amount you can bet or raise to (i.e. the smallest you can increase your pip).
        max_amount: if BetAction or RaiseAction is valid, the largest amount you can bet or raise to (i.e. the largest you can increase your pip).
        '''
        print time_left
        if len(self.opp_range_all) == 1326:
            self.removeSeenFromOppRange(cards)
        while (self.moves < len(move_history)):
            self.handleMove(move_history[self.moves], game, board_cards)
            self.moves += 1

        if calc is not None:
            result = calc(''.join(cards) + ':' + ','.join(self.opp_range),
                          ''.join(board_cards), ''.join(self.discarded_cards),
                          1000)
            if result is not None:
                strength = result.ev[0]
            else:
                print "Warning: calc returned None"
                strength = random.random()
        else:
            strength = random.random()

        margin = game.big_blind / 2.0 + 1.0
        if round.bankroll > 0: margin *= 1
        elif round.bankroll < 0: margin *= -1
        else: margin *= 0
        bb_per_hand_ahead = (round.bankroll - margin) / (game.num_hands -
                                                         round.hand_num + 1.0)
        aggression_factor = min(
            max((1.5 - bb_per_hand_ahead) / 3.0 + np.random.normal(0.0, 0.05),
                0.0), 1.0)  # 0 no aggression, 1 full aggression

        if ExchangeAction in legal_moves:  # decision to exchange
            # exchange logic
            # if we exchange, we should update self.discarded_cards
            if len(board_cards) == 0:
                return CheckAction()  # Never exchange pre-flop

            exchange_cost = cost_func(ExchangeAction())
            outs = 0
            if len(board_cards) == 4 and (aggression_factor > 0.5
                                          or strength < 0.4):
                flush_outs = checkFlushDraw(cards, board_cards,
                                            self.discarded_cards)
                straight_outs = checkStraightDraw(cards, board_cards,
                                                  self.discarded_cards)
                threekind_outs = check3ofKindDraw(cards, board_cards,
                                                  self.discarded_cards)

                if flush_outs > 0:
                    outs = flush_outs
                elif not straight_outs > 0 and not flush_outs == -2:
                    outs = straight_outs
                elif not threekind_outs > 0 and not flush_outs == -2 and not straight_outs == -2:
                    outs = threekind_outs

            if not outs == 0:
                stack_rem = game.round_stack - pot.total
                exchange_cost_cum = 0
                prob_no_hit_cum = 1.0
                j = 1
                while (stack_rem >= ((2**j) - 1) * exchange_cost):
                    cards_rem = 52 - len(cards) - len(board_cards) - len(
                        self.discarded_cards) - 2 * (j - 1)
                    exchange_cost_cum += prob_no_hit_cum * (2**(
                        j - 1)) * exchange_cost
                    prob_no_hit_cum *= (1.0 - outs * 1.0 / cards_rem) * (
                        1.0 - outs * 1.0 / (cards_rem - 1.0))
                    j += 1
                exchange_ev = pot.grand_total * (
                    1 - prob_no_hit_cum) - prob_no_hit_cum * exchange_cost_cum
                check_ev = strength * pot.grand_total
                if exchange_ev > check_ev:  # exchanging is worth it
                    self.discarded_cards |= set(
                        cards)  # keep track of the cards we discarded
                    print "EXCHANGE TO HIT DRAW"
                    return ExchangeAction()

            strength_exchange = calc(
                'xx:' + ','.join(self.opp_range), ''.join(board_cards),
                ''.join(self.discarded_cards) + ''.join(cards), 1000).ev[0]
            exchange_ev = strength_exchange * (pot.grand_total +
                                               exchange_cost) - exchange_cost
            check_ev = strength * pot.grand_total
            if exchange_ev > check_ev:  # exchanging is worth it
                self.discarded_cards |= set(
                    cards)  # keep track of the cards we discarded
                return ExchangeAction()
            return CheckAction()
        else:  # decision to commit resources to the pot
            if bb_per_hand_ahead > 1.5:
                if not self.check_fold:
                    print 'WIN SECURE. START CHECK FOLDING. ROUND #' + str(
                        round.hand_num)
                self.check_fold = True
                if CheckAction in legal_moves: return CheckAction()
                else: return FoldAction()

            continue_cost = cost_func(
                CallAction()) if CallAction in legal_moves else cost_func(
                    CheckAction())
            # figure out how to raise the stakes
            if aggression_factor < 0.25:
                commit_amount = int(pot.pip + continue_cost +
                                    4 * math.sqrt(max(strength - 0.6, 0.0)) *
                                    aggression_factor *
                                    (pot.grand_total + continue_cost))
            elif aggression_factor > 0.6:
                commit_amount = int(pot.pip + continue_cost + 2 *
                                    math.sqrt(strength) * aggression_factor *
                                    (pot.grand_total + continue_cost))
            else:
                commit_amount = int(pot.pip + continue_cost +
                                    2 * math.sqrt(max(strength - 0.3, 0.0)) *
                                    aggression_factor *
                                    (pot.grand_total + continue_cost))

            if min_amount is not None:
                commit_amount = max(commit_amount, min_amount)
            if max_amount is not None:
                commit_amount = min(commit_amount, max_amount)

            if RaiseAction in legal_moves:
                commit_action = RaiseAction(commit_amount)
            elif BetAction in legal_moves:
                commit_action = BetAction(commit_amount)
            elif CallAction in legal_moves:  # we are contemplating an all-in call
                commit_action = CallAction()
            else:  # only legal action
                return CheckAction()

            if continue_cost > 0:  # our opponent has raised the stakes
                print strength
                if continue_cost > 1 and strength < 1:  # tight-aggressive playstyle
                    strength -= (max(
                        min(
                            0.75, continue_cost * 1.0 /
                            (pot.grand_total - continue_cost)), 0.25
                    ) - 0.25) * max(
                        min(
                            -1.212 * aggression_factor**2 +
                            0.5152 * aggression_factor + 0.5455, 0.6), 0.25
                    )  # intimidation factor                    print strength
                # calculate pot odds: is it worth it to stay in the game?
                pot_odds = float(continue_cost) / (pot.grand_total +
                                                   continue_cost)
                if strength >= pot_odds:  # staying in the game has positive EV
                    if len(
                            board_cards
                    ) == 0 and continue_cost > 1 and strength < 0.8 * max(
                            min(1.0 - aggression_factor, 0.5), 0.8):
                        return FoldAction()
                    if strength > 1.15 - aggression_factor and 2 * random.random(
                    ) * (1.0 - aggression_factor
                         ) < strength:  # commit more sometimes
                        print[strength, aggression_factor]
                        return commit_action
                    return CallAction()
                else:  # staying in the game has negative EV
                    return FoldAction()

            elif continue_cost == 0:
                if len(board_cards) == 0:
                    if 2 * 0.63 * np.random.normal(1.0, 0.1) * (
                            1.0 - aggression_factor
                    ) < strength:  # balance bluffs with value bets
                        return commit_action
                else:
                    if np.random.normal(1.0, 0.2) * (
                            1.0 - aggression_factor
                    ) < strength:  # balance bluffs with value bets
                        return commit_action
                return CheckAction()

        # Default to checkcall
        if CallAction in legal_moves:
            return CallAction()
        else:
            return CheckAction()
                            1, 4)] and vals_dict[card4[0]] >= vals_dict[c[0]]
                        and not c in [card1, card2, card3, card4]
                ]:
                    card_keys5.append(card1 + card2 + card3 + card4 + card5)

print len(card_keys5)

probdict = {}

start_time = time.time()

i = 0

for key in card_keys5:
    cards = key[0:4].replace('a', 's').replace('b',
                                               'h')  # c maps to c, d maps to d
    board_cards = key[4:10].replace('a', 's').replace(
        'b', 'h')  # c maps to c, d maps to d
    probdict[key] = calc(cards + ':xx', board_cards, '', 1000).ev[0]
    i += 1
    if i % int(len(card_keys5) * 0.005) == 0:
        print str(
            i * 100.0 /
            len(card_keys5)) + '% complete. Estimated time remaining: ' + str(
                (len(card_keys5) - i) * ((time.time() - start_time) / i) *
                (1 / 60.0)) + ' minutes'

pickle.dump(probdict, open("postflop_odds.pkl", "wb"))

#print hand_list
#len(set([card1[1],card2[1]]))+1
Example #36
0
    def get_best_action(self, received_packet, avail_actions = []):
        equity = None

        # determine if we are still in the same betting round to prevent raising to infinity problem
        if received_packet['num_boardcards'] == self.num_boardcards:
            self.is_new_round = False
        else: 
            self.is_new_round = True
        self.num_boardcards = received_packet['num_boardcards'] 

        # set thresholds
        # if not self.one_out:
        #     self.fold_thres = THREE_FOLD_THRES_TABLE[self.num_boardcards]
        #     self.raise_thres = THREE_RAISE_THRES_TABLE[self.num_boardcards]
        #     self.reraise_thres = THREE_RERAISE_THRES
        # else:
        #     self.fold_thres = TWO_FOLD_THRES_TABLE[self.num_boardcards]
        #     self.raise_thres = TWO_RAISE_THRES_TABLE[self.num_boardcards]
        #     self.reraise_thres = TWO_RERAISE_THRES

        # see if we could use precomputed equity

        if self.num_active_players == 2 or self.one_folded == True:
            self.fold_thres = TWO_FOLD_THRES_TABLE[self.num_boardcards]
            self.raise_thres = TWO_RAISE_THRES_TABLE[self.num_boardcards]
            self.reraise_thres = TWO_RERAISE_THRES
            if self.num_boardcards == 0:
                equity = self.equity_table_2[self.my_hand]
            else:
                equity = pbots_calc.calc(':'.join([self.my_hand, 'xx']), ''.join(received_packet['boardcards']), 
                    "", self.monte_carlo_iter)
                equity = equity.ev[0]
        else:
            self.fold_thres = THREE_FOLD_THRES_TABLE[self.num_boardcards]
            self.raise_thres = THREE_RAISE_THRES_TABLE[self.num_boardcards]
            self.reraise_thres = THREE_RERAISE_THRES
            if self.num_boardcards == 0:
                equity = self.equity_table_3[self.my_hand]
            else:
                equity = pbots_calc.calc(':'.join([self.my_hand, 'xx', 'xx']), ''.join(received_packet['boardcards']), 
                    "", self.monte_carlo_iter)
                equity = equity.ev[0]



        do_reraise = random.random() > self.reraise_thres

        print 'EQUITY: ' + str(equity)

        if equity < self.fold_thres:
            # TODO: Implement bluffing / call here
            if CHECK in avail_actions:
                return CHECK
            return FOLD

        elif equity > self.raise_thres and (self.is_new_round or do_reraise): 
            winning_factor = ((equity - self.fold_thres) / (1 - self.fold_thres))**POWER
            if BET in avail_actions:
                amount = self.bet_handler(winning_factor)
                return BET + ":" + str(amount)
            elif RAISE in avail_actions:
                amount = self.raise_handler(winning_factor)
                return RAISE + ":" + str(amount)
        
        if CALL in avail_actions: 
            if self.should_call(equity):
                return CALL + ":" + str(self.call_amount)
            else:
                return FOLD

        return CHECK