Spaces:
Sleeping
Sleeping
| import poker_functions as p | |
| from fractions import Fraction | |
| from collections import Counter | |
| class Player: | |
| def __init__(self, number, cards=[]): | |
| if len(cards) > 0: | |
| cards = p.make_card(cards) | |
| else: | |
| cards = [] | |
| self.number = number | |
| self.cards = cards | |
| self.hand = None | |
| self.starting_cards = None | |
| self.wins = 0 | |
| def __str__(self): | |
| return "player_" + str(self.number) | |
| def dedup(board): | |
| duplicate = False | |
| c = Counter(board) | |
| for card in board: | |
| if c[card] > 1: | |
| duplicate = True | |
| return duplicate | |
| return duplicate | |
| def validate_card(check): | |
| """Detect invalid cards in a passed collection""" | |
| valid = True | |
| deck = p.generate_deck() | |
| valid_cards = [card.name for card in deck] | |
| for card in check: | |
| if card not in valid_cards: | |
| valid = False | |
| return valid | |
| return valid | |
| def convert_and_update(deck, cards): | |
| if len(cards) == 0: | |
| return deck, cards | |
| else: | |
| cards = p.make_card(cards) | |
| for card in cards: | |
| deck.update_deck(card) | |
| return deck, cards | |
| ##### SIMULATIONS ##### | |
| def evaluate_hand(hole_cards, flop=[], turn=[], river=[]): | |
| board = flop + turn + river | |
| hand = None | |
| if len(hole_cards + board) < 5: | |
| return hand | |
| else: | |
| for func in p.HAND_REGISTRY: | |
| func = func(hole_cards, board) | |
| if not func: | |
| continue | |
| else: | |
| return func | |
| def score_game(contestants): | |
| # TODO make this more elegant by functionizing repeated code. | |
| """Application will determine the highest hand, including low and kicker for each player in player_list""" | |
| high = ['flush', 'straight', 'straight_flush'] | |
| kick = ['4ok'] | |
| hi_lo = ['boat'] | |
| hi_lo_kick = ['2pair', 'hc', '3ok', 'pair'] | |
| high_hand = max(contestants, key=lambda x: x.hand.hand_value) # contestant with highest hand | |
| same_high_hand = [player for player in contestants if player.hand.hand_value == high_hand.hand.hand_value] | |
| if len(same_high_hand) == 1: | |
| same_high_hand[0].wins += 1 | |
| return contestants | |
| elif high_hand.hand.type in high: | |
| high_card = max(same_high_hand, key=lambda x: x.hand.high_value) | |
| same_high_card = [player for player in same_high_hand if player.hand.high_value == high_card.hand.high_value] | |
| if len(same_high_card) == 1: | |
| high_card.wins += 1 | |
| return contestants | |
| else: | |
| return contestants | |
| elif high_hand.hand.type in hi_lo: | |
| over = max(same_high_hand, key=lambda x: x.hand.high_value) # Highest pair in hand | |
| same_over = [player for player in same_high_hand if player.hand.high_value == over.hand.high_value] | |
| if len(same_over) == 1: | |
| over.wins += 1 | |
| return contestants | |
| else: | |
| under = max(same_over, key=lambda x: x.hand.low_value) # lowest pair in hand | |
| same_under = [player for player in same_over if player.hand.low_value == under.hand.low_value] | |
| if len(same_under) == 1: | |
| under.wins += 1 | |
| return contestants | |
| else: | |
| return contestants | |
| elif high_hand.hand.type in hi_lo_kick: | |
| over = max(same_high_hand, key=lambda x: x.hand.high_value) # Highest pair in hand | |
| same_over = [player for player in same_high_hand if player.hand.high_value == over.hand.high_value] | |
| if len(same_over) == 1: | |
| over.wins += 1 | |
| return contestants | |
| else: | |
| under = max(same_over, key=lambda x: x.hand.low_value) # lowest pair in hand | |
| same_under = [player for player in same_over if player.hand.low_value == under.hand.low_value] | |
| if len(same_under) == 1: | |
| under.wins += 1 | |
| return contestants | |
| else: | |
| kicker = max(same_under, key=lambda x: x.hand.kicker) | |
| same_kicker = [player for player in same_under if player.hand.kicker == kicker.hand.kicker] | |
| if len(same_kicker) == 1: | |
| kicker.wins += 1 | |
| return contestants | |
| else: | |
| return contestants | |
| elif high_hand.hand.type in kick: | |
| low_val = max(same_high_hand, key=lambda x: x.hand.low_value) | |
| same_low_val = [player for player in same_high_hand if player.hand.low_value == low_val.hand.low_value] | |
| if len(same_low_val) == 1: | |
| low_val.wins += 1 | |
| return contestants | |
| else: | |
| return contestants | |
| def simulation_one_player(hole, flop=None, turn=None, river=None, sims=100000): | |
| if flop is None: | |
| flop = [] | |
| if turn is None: | |
| turn = [] | |
| if river is None: | |
| river = [] | |
| full_board = 7 # number of cards required to run sim | |
| passed_cards = len(hole) + len(flop) + len(turn) + len(river) | |
| passed_flop = list(flop) | |
| high_cards = 0 | |
| pairs = 0 | |
| two_pairs = 0 | |
| trips = 0 | |
| straights = 0 | |
| flushes = 0 | |
| boats = 0 | |
| quads = 0 | |
| straight_flushes = 0 | |
| invalid = 0 | |
| for i in range(sims): | |
| deck = p.generate_deck() | |
| deck, hole = convert_and_update(deck, hole) | |
| deck, flop = convert_and_update(deck, flop) | |
| deck, turn = convert_and_update(deck, turn) | |
| deck, river = convert_and_update(deck, river) | |
| j = full_board - passed_cards | |
| for _ in range(j): | |
| deal, deck = deck.deal_card() | |
| flop.append(deal) # Adding to flop because it shouldn't matter, will revert flop back at end of loop | |
| hand = evaluate_hand(hole, flop, turn, river) | |
| if hand.type == '2pair': | |
| two_pairs += 1 | |
| elif hand.type == '3ok': | |
| trips += 1 | |
| elif hand.type == '4ok': | |
| quads += 1 | |
| elif hand.type == 'boat': | |
| boats += 1 | |
| elif hand.type == 'flush': | |
| flushes += 1 | |
| elif hand.type == 'hc': | |
| high_cards += 1 | |
| elif hand.type == 'pair': | |
| pairs += 1 | |
| elif hand.type == 'straight': | |
| straights += 1 | |
| elif hand.type == 'straight_flush': | |
| straight_flushes += 1 | |
| else: | |
| invalid += 1 | |
| i += 1 | |
| flop = list(passed_flop) | |
| return sims, high_cards, pairs, two_pairs, trips, straights, flushes, boats, quads, straight_flushes | |
| def simulation_multiplayer(hole_one, hole_two=[], hole_three=[], hole_four=[], hole_five=[], hole_six=[], | |
| flop = [], turn = [], river = [], opponents=2, sims=10000): | |
| contestant_hands = [hole_one, hole_two, hole_three, hole_four, hole_five, hole_six] | |
| contestants = [] | |
| flop = p.make_card(flop) | |
| turn = p.make_card(turn) | |
| river = p.make_card(river) | |
| passed_flop_stable = [card for card in flop] | |
| for n in range(opponents): | |
| player_name = 'opponent' + str(n+1) | |
| player_name = Player(n, contestant_hands[n]) | |
| contestants.append(player_name) | |
| i = 0 | |
| passed_board = len(flop) + len(turn) + len(river) | |
| full_board = 5 | |
| k = full_board - passed_board | |
| for i in range(sims): | |
| deck = p.generate_deck() | |
| for contestant in contestants: # TODO move assigning Player.starting_cards to init | |
| if len(contestant.cards) == 2: | |
| contestant.starting_cards = True | |
| for card in contestant.cards: | |
| deck.update_deck(card) # remove known hole cards from deck | |
| else: | |
| contestant.starting_cards = False | |
| hole_cards = [] | |
| for j in range(2): | |
| deal, deck = deck.deal_card() | |
| hole_cards.append(deal) | |
| contestant.cards = hole_cards # assign new hole cards if not passed | |
| for l in range(k): # complete the board as needed | |
| deal, deck = deck.deal_card() | |
| flop.append(deal) | |
| for contestant in contestants: | |
| hand = evaluate_hand(contestant.cards, flop, turn, river) | |
| contestant.hand = hand | |
| # Compare hand values in contestants | |
| contestants = score_game(contestants) | |
| i += 1 | |
| # Revert to starting state | |
| flop = [card for card in passed_flop_stable] | |
| for contestant in contestants: | |
| if contestant.starting_cards is False: | |
| contestant.cards = [] | |
| hole_cards = [] | |
| return contestants | |
| # TODO for single and mult: find and return most likely hand. Return number of outs and odds. | |
| ##### MATH ##### | |
| def percent(hits, sims): | |
| percent = round((hits / sims) * 100,0) | |
| return percent | |
| def ratio(hits, sims): | |
| """Return a ratio (e.g. 3:5) for two input numbers""" | |
| percent = round((hits / sims),2) | |
| fraction = str(Fraction(percent).limit_denominator()) | |
| fraction = fraction.replace('/', ':') | |
| return fraction | |
| ##### REFERENCE ##### | |
| outs = {'1':('46:1','45:1',"22:1"), | |
| '2':('22:1','22:1','11:1'), | |
| '3':('15:1', '14:1', '7:1'), | |
| '4':('11:1','10:1','5:1'), | |
| '5':('8.5:1', '8:1','4:1'), | |
| '6':('7:1','7:1','3:1'), | |
| '7':('6:1','6:1','2.5:1'), | |
| '8':('5:1','5:1','2.5:1'), | |
| '9':('4:1','4:1','2:1'), | |
| '10':('3.5:1','3.5:1','1.5:1'), | |
| '11':('3.3:1','3.2:1','1.5:1'), | |
| '12':('3:1','3:1','1.2:1'), | |
| } | |
| rank_value = p.rank_value |