Created
September 17, 2014 16:28
-
-
Save peterskipper/961268561660566ae293 to your computer and use it in GitHub Desktop.
A simple program to calculate exact pot odds in Texas Hold'em poker, and use them to determine mathematically when to call or fold
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Evaluate Poker Hands at the flop in Texas Hold'em | |
import collections | |
#Some Constants | |
VALUES = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"] | |
SUITS = ["s","h","d","c"] | |
HIGH_STRAIGHT = ["10", "J", "Q", "K", "A"] | |
#Helper function to check input | |
def check_card(card): | |
if len(card) > 3: | |
print "Your response should have only 2-3 characters" | |
return False | |
elif len(card) == 3: | |
if card[0] == "1" and card[1] == "0" and card[2] in SUITS: | |
return True | |
else: | |
return False | |
elif card[0] not in VALUES: | |
print "The first character must be a value, A-K" | |
return False | |
elif card[1] not in SUITS: | |
print "The second character must be a lower case suit: s, h, d or c" | |
return False | |
else: | |
return True | |
#Input 2 hole cards and flop | |
hand = [] | |
prompts = ["Enter 1st Hole Card: ", "Enter 2nd Hole Card: ", "Enter 1st Flop Card: ", "Enter 2nd Flop Card: ", "Enter 3rd Flop Card: "] | |
print "Enter the cards in your hand.\nUse a capital letter for the value, followed by a lower-case letter for the suit.\nFor example, to enter the Jack of Hearts, type Jh" | |
card_index = 0 | |
while card_index < 5: | |
resp = list(raw_input(prompts[card_index])) | |
while not check_card(resp): | |
resp = list(raw_input(prompts[card_index])) | |
if len(resp) == 3: #Deal with 10 | |
temp = ["10", resp[2]] | |
resp = temp | |
hand.append(resp) | |
card_index += 1 | |
#hand to dict(s) | |
def hand_to_dict(hand, value_dict, suit_dict): | |
for card in hand: | |
value_dict[card[0]] += 1 | |
suit_dict[card[1]] += 1 | |
value_dict = collections.defaultdict(int) | |
suit_dict = collections.defaultdict(int) | |
hand_to_dict(hand, value_dict, suit_dict) | |
#Check for already existing high hand | |
def high_hand(value_dict, suit_dict): | |
straight, flush = False, False | |
if len(value_dict) == 2: | |
if 4 in value_dict.values(): | |
print "You already have Four of a Kind. Bet Away!" | |
return True | |
else: | |
print "You already have a Full House. Bet Away!" | |
return True | |
elif len(value_dict) == 5: | |
if 5 in suit_dict.values(): | |
flush = True | |
min_val = min([VALUES.index(val) for val in value_dict]) | |
max_val = max([VALUES.index(val) for val in value_dict]) | |
if max_val - min_val == 4: | |
straight = True | |
if set(value_dict.keys()) == set(HIGH_STRAIGHT): | |
straight = True | |
if straight and flush: | |
print "You already have a Straight Flush. Bet Away!" | |
return True | |
elif flush: | |
print "You already have a Flush. Bet Away!" | |
return True | |
elif straight: | |
print "You already have a Straight. Bet Away!" | |
return True | |
else: | |
return False | |
else: | |
return False | |
#outs are the poker term for cards that would complete | |
#a highly competitive hand, i.e. a straight or higher | |
def check_outs(): | |
outs = 0 | |
#Check for Three of a Kind | |
if 3 in value_dict.values(): # Already have 3 of a kind | |
outs += 7 #one out for Four of a Kind, six more for Full House | |
#Check for Two Pair | |
if len(value_dict) == 3 and 3 not in value_dict.values(): | |
outs += 4 #four Full House outs | |
#Flushes, Straights or both | |
inside_straight, open_ended_straight, flush = 0, 0, 0 | |
#Check for Flush outs | |
if 4 in suit_dict.values(): #Already have 4 of same suit | |
outs += 9 | |
flush += 1 | |
#Check for Straight outs | |
if len(value_dict) >= 4: #need at least 4 values for a straight draw | |
for i in range(5): | |
temp_hand = hand[0:i] + hand[i+1:] # Leave one card out. The other 4 must be close in value for a straight draw | |
temp_value_dict = collections.defaultdict(int) | |
temp_suit_dict = collections.defaultdict(int) | |
hand_to_dict(temp_hand,temp_value_dict,temp_suit_dict) | |
min_val = min([VALUES.index(val) for val in temp_value_dict]) | |
max_val = max([VALUES.index(val) for val in temp_value_dict]) | |
diff = max_val - min_val | |
if diff == 3: #open-ended straight draw | |
outs += 8 | |
open_ended_straight += 1 | |
elif diff == 4: #inside straight draw | |
outs += 4 | |
inside_straight += 1 | |
#check for high straight | |
elif set(temp_value_dict.keys()) <= set(HIGH_STRAIGHT): | |
outs += 4 | |
inside_straight += 1 | |
#Adjust outs for Straight AND Flush draws to avoid double counting | |
if inside_straight and flush: | |
outs -= 1*inside_straight | |
if open_ended_straight and flush: | |
outs -= 2*open_ended_straight | |
return outs | |
#Results: helper func for output below | |
def results(outs, success_prob, max_bet): | |
print "You have " + str(outs) + " outs to make a Straight or better hand." | |
print "Your probability of making your hand is " + str(round(success_prob,3)) | |
print "According to pot odds, call a maximum bet of " + str(round(max_bet,2)) + " to stay in the game." | |
if not high_hand(value_dict, suit_dict): | |
#Input Pot Size | |
pot = float(raw_input("How large is the pot? ")) | |
outs = check_outs() | |
#Calculate prob of a high hand (Straight or Better) | |
success_prob = 1 - ( (47.0-outs)/47.0 * (46.0-outs)/46.0 ) | |
max_bet = (pot * success_prob) / (1 - success_prob) | |
#Sanity Check | |
if success_prob == 0: | |
print "You have zero outs to make a Straight or better hand." | |
print "You should fold" | |
else: | |
#Results: Turn card | |
results(outs, success_prob, max_bet) | |
#Results: River card | |
choice = "?" | |
while choice != 'Y' and choice != 'N': | |
choice = raw_input("Did you make your hand (type Y or N)? ") | |
if choice == 'Y': | |
print "Awesome! Bet away." | |
if choice == 'N': | |
pot = float(raw_input("How large is the pot now? ")) | |
success_prob = 1 - ( (46.0-outs)/46.0) | |
max_bet = (pot * success_prob) / (1 - success_prob) | |
results(outs, success_prob, max_bet) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment