root/games/holdem/hand.py

Revision 47, 4.7 KB (checked in by mike, 4 years ago)

refactoring packages

Line 
1from games import deck
2
3HAND_ORDERS = [ "high_card",
4                "pair",
5                "two_pair",
6                "three_of_a_kind",
7                "straight",
8                "flush",
9                "full_house",
10                "four_of_a_kind",
11                "straight_flush" ]
12
13def format_hand(hand):
14    #TODO add Ace support
15    kickers  = [deck.CARDS[c] for c in hand[1] if c >= 0]
16    name = HAND_ORDERS[hand[0]]
17    if name == "high_card":
18        return "high card (%s) with kickers (%s)" % (kickers.pop(0),kickers)
19    elif name == "pair":
20        return "pair of (%s)'s with kickers (%s)" % (kickers.pop(0),kickers)
21    elif name == "two_pair":
22        return "two pair of (%s)'s and (%s)'s with kickers (%s)" % (kickers.pop(0),kickers.pop(0),kickers)
23    elif name == "four_of_a_kind":
24        return "four of a kind (%s) with kickers (%s)" % (kickers.pop(0),kickers)
25    elif name == "three_of_a_kind":
26        return "three of a kind (%s) with kickers (%s)" % (kickers.pop(0),kickers)
27    elif name == "flush":
28        return "flush with high card (%s)" % (kickers.pop(0))
29    elif name == "straight_flush":
30        return "straight flush with high card (%s)" % (kickers.pop(0))
31    elif name == "straight":
32        return "straight with high card (%s)" % (kickers.pop(0))
33    elif name == "full_house":
34        return "full house with (%s) over (%s)" % (kickers.pop(0),kickers.pop(0))
35    else: return "???"
36
37
38#input all 7 cards
39def best_hand(cards):
40    all_poosible_hands = list(combNoReplace(cards,5))
41    for h in all_poosible_hands: h.sort( cmp = lambda a,b: cmp(b,a) )
42    pos_hands = [judge_hand(h) for h in all_poosible_hands]
43    return max(pos_hands)
44   
45
46#returns the best combination for the 5 cards
47def judge_hand(cards):
48    ret = is_straight_flush(cards)
49    if not ret: ret = is_n_kinds([a for (a,b) in cards])
50    #replace the text with a value
51    return (HAND_ORDERS.index(ret[0]), ret[1])
52
53
54#for all these functions, make sure cards are sorted DESCENDING!!!!
55#will return flush, straight or straight_flush
56def is_straight_flush(cards):
57    ret1 = is_flush(cards)
58    ret2 = is_straight(cards)
59    if ret1 and ret2: return ("straight_flush", [cards[0][0]])
60    elif ret1: return ret1
61    elif ret2: return ret2
62    else: return None
63
64#we don't need to call this except from is_straight_flush
65def is_flush(cards):
66    last=cards[0][1]
67    flush = True
68    for (a,b) in cards[1:]:
69        if b != last:
70            flush = False
71            break
72    if flush: return ("flush", [cards[0][0]]) #return highest card
73    else: return None
74
75#only is_straight_flush needs to call this
76def is_straight(cards):
77    last=cards[0][0]
78    straight = True
79    for (a,b) in cards[1:]:
80        if a != last-1:
81            straight = False
82            break
83        last = a
84    if straight: return ("straight", [cards[0][0]]) #return highest card
85    else: return None
86
87#input: only a list of the card vals.  No suits please
88def is_n_kinds(card_vals):
89    highest_n = 1   #greatest num in a row
90    current_n = 1
91    highest_card = card_vals[0]  #highest card for greatest num in a row
92    last = card_vals[0]
93    for a in card_vals[1:]:
94        if a == last:
95            current_n += 1
96            if current_n > highest_n:
97                highest_n = current_n
98                highest_card = a
99        else:
100            last = a
101            current_n = 1
102    if highest_n == 1: return ("high_card",card_vals)
103    #check for full house
104    elif highest_n == 2:
105        whats_left = [x for x in card_vals if x != highest_card]
106        #this is the hand withotu the pairs
107        #now check if it's two pair
108        if len(whats_left) >= 2:
109            ret = is_n_kinds(whats_left)
110            #if the subset is a pair then this is a two pair
111            if ret[0] == "pair": return ("two_pair",[highest_card]+ret[1])
112        return ("pair",[highest_card]+whats_left)
113    elif highest_n == 3:
114        whats_left = [x for x in card_vals if x != highest_card]
115        #now check if it's a full house
116        if len(whats_left) >= 2:
117            ret = is_n_kinds(whats_left)
118            if ret[0] == "pair": return ("full_house",[highest_card]+ret[1]) 
119        #well, it's just a 3 of a kind then
120        return ("three_of_a_kind",[highest_card]+whats_left)
121    elif highest_n == 4:
122        whats_left = [x for x in card_vals if x != highest_card]
123        return ("four_of_a_kind",[highest_card]+whats_left)
124    #we shouldn't get to this point
125    assert(False)
126
127def combNoReplace(cards, n):
128    if n==0: yield []
129    else:
130        for i in xrange(len(cards)-n+1):
131            for cc in combNoReplace(cards[i+1:],n-1):
132                #Aces can have 2 values
133                if cards[i]==deck.CARDS.index("A"): yield [-1]+cc
134                yield [cards[i]]+cc
135
Note: See TracBrowser for help on using the browser.