import card reload(card) def hand_rank(table, pocket): """determines the ranking of pocket cards, given table cards, returns a probability score""" assert len(pocket) == 2, "Pocket must be a list of two Cards" deck = card.Deck() count = 1 win = 1 for c in deck: if card_in(table, c) or card_in(pocket, c): continue for j in deck: if eq_card(c,j) or card_in(table,j) or card_in(pocket,j): continue else: otherhand = [c,j] otherhand.extend(table) otherhand.sort() thishand = [] thishand.extend(pocket) thishand.extend(table) thishand.sort() winning = compare_hands(thishand, otherhand) if winning == thishand: win += 1 count += 1 return (float(win)/float(count)) def compare_hands(hand1, hand2): """compares two hands and returns the greater of the two""" rank1,rank2 = _rank(hand1), _rank(hand2) if rank1[0] > rank2[0]: return hand1 elif rank2[0] > rank1[0]: return hand2 elif rank1[0] == rank2[0]: return _compare_eq_hands(hand1,hand2) def _compare_eq_hands(hand1, hand2): """compares two hands of equal type and returns the greater of the two""" rank1, rank2 = _rank(hand1), _rank(hand2) assert rank1[1] == rank2[1], "Input are not equivalent hands" hasfunc = rank1[1] if rank1[0] == rank2[0]: # same hand res1, res2 = hasfunc(hand1), hasfunc(hand2) res1.sort() res2.sort() if hasfunc is has_full_house: # adjust for full house res1, res2 = has_three_of_a_kind(hand1), has_three_of_a_kind(hand2) if res1[-1] > res2[-1]: return hand1 elif res2[-1] > res1[-1]: return hand2 else: return _tie_breaker(hand1, hand2) # resort to kickers def card_in(listx, card): """returns True if listx is in card, False otherwise""" for x in listx: if eq_card(card, x): return True return False def eq_card(card1, card2): """returns True if card1 is same as card2 (by suit, value), False otherwise""" return card1.face() == card2.face() and card1.suit() == card2.suit() def _rank(hand): """given a hand, computes the hand's relative strength and the function used to determine that hand""" hand.sort() sf = has_straight_flush(hand) if sf: return 10,has_straight_flush fk = has_four_of_a_kind(hand) if fk: return 9,has_four_of_a_kind fh = has_full_house(hand) if fh: return 8,has_full_house fl = has_flush(hand) if fl: return 7,has_flush st = has_straight(hand) if st: return 6,has_straight tk = has_three_of_a_kind(hand) if tk: return 5,has_three_of_a_kind tp = has_two_pair(hand) if tp: return 4,has_two_pair pa = has_pair(hand) if pa: return 3,has_pair return 0,has_high_card def _tie_breaker(hand1, hand2): """returns the winning hand in a tie via kickers""" assert len(hand1) == len(hand2), "Unequivalent size hands in tie-breaking" hand1.sort() hand2.sort() for l in range(1,len(hand1)): if hand1[-l] > hand2[-l]: return hand1 elif hand1[-l] < hand2[-l]: return hand2 return None def _find_pair(hand, card, startpos): """finds the Cards that matches card in value, starting at startpos (inclusive). returns list of matching Cards""" matches = [] for h in range(startpos, len(hand)): if hand[h] == card: matches.append(hand[h]) return matches def _has_x_pair(hand, x): """returns the first cards that determine a pair of x - may not return the highest or most prolific pair! hand -- list of Cards x -- type of pair (2, 3, 4)""" for c in hand: matches = [c] match = _find_pair(hand, c, hand.index(c)+1) if match != None: matches.extend(match) if len(matches) >= x: return matches return None def _card_xor(remove, hand): """takes out all Cards from hand in remove, and returns that""" newhand = [] for x in hand: add = True for j in remove: if x.suit() == j.suit() and x.face() == j.face(): add = False break if add: newhand.append(x) return newhand def has_pair(hand): """returns the cards that determine a pair""" return _has_x_pair(hand, 2) def has_two_pair(hand): """returns the cards that determine two-pair""" pair1 = has_pair(hand) if pair1: xorhand = _card_xor(pair1, hand) pair2 = has_pair(xorhand) if pair2: pair1.extend(pair2) return pair1 return None def has_three_of_a_kind(hand): """returns the cards the determine a three-of-a-kind""" return _has_x_pair(hand, 3) def has_full_house(hand): """returns the cards that determine a full house""" threekind = _has_x_pair(hand, 3) if threekind: xorhand = _card_xor(threekind, hand) pair = has_pair(xorhand) if pair: threekind.extend(pair) return threekind return None def has_straight(hand): """returns the cards that determine a straight""" hand.sort() allstraights = [] for r in range(2, 15): firstsearch = 0 lastsearch = 5 straight = True strhand = [] if r == 2: # lowest straight - check for aces temp = card.Card(14,1) # temp ace if temp in hand: strhand.append(hand[hand.index(temp)]) lastsearch = 4 for n in range(firstsearch,lastsearch): val = r + n temp = card.Card(val,1) # temp card for searching if not temp in hand: straight = False elif temp in hand: strhand.append(hand[hand.index(temp)]) if straight: allstraights.append(strhand) if len(allstraights) == 0: return None elif len(allstraights) == 1: return allstraights[0] elif len(allstraights) > 1: allstraights.sort() return allstraights[-1] def has_flush(hand): """ returns the cards that determine a flush""" for x in range(1,5): flushhand = [] for c in hand: if c.suit() == card.SUIT_DICT[x]: flushhand.append(c) if len(flushhand) > 4: return flushhand return None def has_high_card(hand): """returns the highest card in a hand""" hand.sort() return [hand[-1]] def has_straight_flush(hand): """returns the cards that constitute a straight flush""" flush = has_flush(hand) if flush: return has_straight(flush) return None def has_four_of_a_kind(hand): """returns cards that determine a four-of-a-kind""" return _has_x_pair(hand, 4)