| 1 | from games import deck |
|---|
| 2 | |
|---|
| 3 | HAND_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 | |
|---|
| 13 | def 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 |
|---|
| 39 | def 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 |
|---|
| 47 | def 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 |
|---|
| 56 | def 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 |
|---|
| 65 | def 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 |
|---|
| 76 | def 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 |
|---|
| 88 | def 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 | |
|---|
| 127 | def 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 | |
|---|