Skip to content

Instantly share code, notes, and snippets.

@peterskipper
Created September 17, 2014 16:28
Show Gist options
  • Save peterskipper/961268561660566ae293 to your computer and use it in GitHub Desktop.
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
#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