def get_result(cards: FullDeal, game: GameView) -> Result: hand_results: List[EvaluationResult] = [] remained_in_hand: List[bool] = [] # A showdown requires more than 1 player at the end of the hand. went_to_showdown: List[bool] = [] for player_index in range(game.num_players()): hole_cards = cards.hole_cards[player_index] board = cards.board eval_result: EvaluationResult = evaluate_hand(hole_cards, board) hand_results.append(eval_result) remained_in_hand.append(not game.is_folded()[player_index]) went_to_showdown.append( not game.is_folded()[player_index] and sum( not folded for idx, folded in enumerate(game.is_folded()) if idx != player_index ) > 0 ) final_hands: Dict[int, EvaluationResult] = { idx: hand for idx, hand in enumerate(hand_results) if remained_in_hand[idx] } winning_players: Set[int] = get_winning_players(final_hands) won_hand: List[bool] = [ player_index in winning_players for player_index in range(game.num_players()) ] pot_per_winning_player: Dict[int, int] = get_pot_payouts( get_ranked_hand_groups(final_hands), game.amount_added_total() ) earned_from_pot: List[int] = [ pot_per_winning_player.get(i, 0) for i in range(game.num_players()) ] profit_per_player: List[int] = [ earned_from_pot[i] - amount_added for i, amount_added in enumerate(game.amount_added_total()) ] return Result( won_hand=won_hand, hand_results=hand_results, went_to_showdown=went_to_showdown, remained_in_hand=remained_in_hand, earned_from_pot=earned_from_pot, profits=profit_per_player, )
def sanity_tests() -> None: # Order doesn't matter assert evaluate_hand(mkhand("7d8s"), Board(flop=mkflop("5h6cJs"))) == evaluate_hand( mkhand("5hJs"), Board(flop=mkflop("7d8s6c"))) # Suits don't matter for non-flushes assert evaluate_hand(mkhand("7d8s"), Board(flop=mkflop("5h6cJs"))) == evaluate_hand( mkhand("7c8h"), Board(flop=mkflop("5h6cJs"))) # Kickers all the way down matter assert evaluate_hand(mkhand("7d8s"), Board(flop=mkflop("AdAcJs"))) > evaluate_hand( mkhand("8s6h"), Board(flop=mkflop("AdAcJs")))
def make_player_states(player_index: int, game: GameView, hole_cards: HoleCards, board: Board) -> List[PlayerState]: player_states = [] street_cache: Dict[Street, PlayerState] = {} for i in iter_game_states(game): game_view = game.view(i) is_player_turn = game_view.current_player() == player_index # We don't set the rest of the values for non-current-players if not is_player_turn: player_states.append( PlayerState( is_current_player=False, current_player_offset=(game_view.current_player() - player_index), )) continue street = game_view.street() # These values don't vary by street, so we cache them if street in street_cache: player_states.append(street_cache[street]) continue if game_view.street() == Street.PREFLOP: player_state = PlayerState(is_current_player=True, current_player_offset=0) else: current_board = board.at_street(game_view.street()) hand_eval = evaluate_hand(hole_cards, current_board) hand_features = pyholdthem.make_hand_features_from_indices( hole_cards.index(), [c.index() for c in current_board.cards()], 1000) player_state = PlayerState( is_current_player=True, current_player_offset=0, current_hand_type=hand_eval.hand_type.value, frac_better_hands=hand_features.frac_better_hands, frac_tied_hands=hand_features.frac_tied_hands, frac_worse_hands=hand_features.frac_worse_hands, win_odds=hand_features.win_odds, tie_odds=hand_features.tie_odds, lose_odds=hand_features.lose_odds, win_odds_vs_better=hand_features.win_odds_vs_better, tie_odds_vs_better=hand_features.tie_odds_vs_better, lose_odds_vs_better=hand_features.lose_odds_vs_better, win_odds_vs_tied=hand_features.win_odds_vs_tied, tie_odds_vs_tied=hand_features.tie_odds_vs_tied, lose_odds_vs_tied=hand_features.lose_odds_vs_tied, win_odds_vs_worse=hand_features.win_odds_vs_worse, tie_odds_vs_worse=hand_features.tie_odds_vs_worse, lose_odds_vs_worse=hand_features.lose_odds_vs_worse, ) street_cache[street] = player_state player_states.append(player_state) return player_states
def test_royal() -> None: hole_cards = mkhand("AcKc") board = Board(flop=mkflop("TcJcQc")) eval_result = evaluate_hand(hole_cards, board) assert eval_result == EvaluationResult(hand_type=HandType.STRAIGHT_FLUSH, kicker=9)
def test_turn() -> None: hole_cards = mkhand("7d8s") board = Board(flop=mkflop("5h6cJs"), turn=mkcard("5h")) eval_result = evaluate_hand(hole_cards, board) assert eval_result == EvaluationResult(hand_type=HandType.PAIR, kicker=66144)
def test_winner() -> None: hole_cards = mkhand("AdAc") board = Board(flop=mkflop("AdKs3h"), turn=mkcard("5h"), river=mkcard("7s")) eval_result = evaluate_hand(hole_cards, board) assert eval_result == EvaluationResult(hand_type=HandType.TRIPS, kicker=33556512)
def test_wheel() -> None: hole_cards = mkhand("2c7d") board = Board(flop=mkflop("3h4c5s")) eval_result = evaluate_hand(hole_cards, board) assert eval_result == EvaluationResult(hand_type=HandType.HIGH, kicker=47)