Example #1
0
def test_loss():
    deal = FullDeal(
        hole_cards=[mkhand("AcAd"), mkhand("AsKh")],
        board=Board(flop=mkflop("KsJs3d"),
                    turn=mkcard("7s"),
                    river=mkcard("6s")),
    )

    game = GameRunner(starting_stacks=[300, 400])
    game.start_game()

    # Preflop
    game.bet_raise(to=10)
    game.call()

    # Flop
    game.bet_raise(to=25)
    game.call()

    # Turn
    game.check()
    game.bet_raise(to=40)
    game.call()

    # River
    game.check()
    game.check()

    results = result.get_result(deal, game.game_view())

    model = heads_up.HeadsUpModel("HeadsUp")

    player_index = 1

    example = make_forward_backward_example(
        player_index,
        game.game_view(),
        deal.hole_cards[player_index],
        deal.board,
        results,
    )

    (
        feature_tensors,
        target_tensors,
    ) = model.feature_config.make_features_and_target_tensors(
        [example.SerializeToString()])

    print(tf.cast(target_tensors["reward__cumulative_reward"], tf.float32))

    loss = model.loss(feature_tensors, target_tensors)

    batch_size = 1
    num_steps = 9
    assert loss.shape == [batch_size, num_steps]
Example #2
0
def test_action_probs():
    deal = FullDeal(
        hole_cards=[mkhand("AcAd"), mkhand("AsKh")],
        board=Board(flop=mkflop("KsJs3d"),
                    turn=mkcard("7s"),
                    river=mkcard("6s")),
    )

    game = GameRunner(starting_stacks=[300, 400])
    game.start_game()

    # Preflop
    game.bet_raise(to=10)
    game.call()

    # Flop
    game.bet_raise(to=25)
    game.call()

    # Turn
    game.check()
    game.bet_raise(to=40)
    game.call()

    # River
    game.check()
    game.check()

    model = heads_up.HeadsUpModel("HeadsUp")

    player_index = 1

    example = make_forward_example(
        player_index,
        game.game_view(),
        deal.hole_cards[player_index],
        deal.board,
    )

    logits = model.action_logits(
        model.feature_config.make_feature_tensors(
            [example.SerializeToString()]))

    batch_size = 1
    num_steps = 9
    num_possible_actions = 22
    assert logits.shape == [batch_size, num_steps, num_possible_actions]

    probs = model.action_probs(
        model.feature_config.make_feature_tensors(
            [example.SerializeToString()]))

    assert_array_almost_equal(
        tf.reduce_sum(probs, -1).numpy(),
        np.array([[1, 1, 1, 1, 1, 1, 1, 1, 1]]))
Example #3
0
def test_game_result():
    deal = FullDeal(
        hole_cards=[mkhand("AcAh"),
                    mkhand("KdKs"),
                    mkhand("JhJd")],
        board=Board(flop=mkflop("6dQc2s"),
                    turn=mkcard("6s"),
                    river=mkcard("3c")),
    )

    game = GameRunner(starting_stacks=[100, 200, 300])
    game.start_game()

    # Preflop
    game.bet_raise(to=10)
    game.call()
    game.call()

    # Flop
    game.bet_raise(to=20)
    game.call()
    game.call()

    # Turn
    game.bet_raise(to=30)
    game.call()
    game.call()

    # River
    game.check()
    game.check()
    game.check()

    result = get_result(deal, game.game_view())

    assert result == Result(
        won_hand=[True, False, False],
        hand_results=[
            EvaluationResult(
                hand_type=HandType.TWO_PAIR,
                kicker=33686528,
            ),
            EvaluationResult(hand_type=HandType.TWO_PAIR, kicker=16909312),
            EvaluationResult(hand_type=HandType.TWO_PAIR, kicker=4326400),
        ],
        went_to_showdown=[True, True, True],
        remained_in_hand=[True, True, True],
        earned_from_pot=[180, 0, 0],
        profits=[120, -60, -60],
    )
Example #4
0
def test_game_with_tie():
    deal = FullDeal(
        hole_cards=[mkhand("Ac3h"),
                    mkhand("Ad4s"),
                    mkhand("5s5d")],
        board=Board(flop=mkflop("AsAhKc"),
                    turn=mkcard("Kd"),
                    river=mkcard("7h")),
    )

    game = GameRunner(starting_stacks=[100, 200, 300])
    game.start_game()

    # Preflop
    game.bet_raise(to=30)
    game.call()
    game.call()

    # Flop
    game.bet_raise(to=50)
    game.call()
    game.call()

    # Turn
    game.bet_raise(to=20)
    game.call()
    game.call()

    # River
    game.bet_raise(to=100)
    game.call()

    result = get_result(deal, game.game_view())

    assert result == Result(
        won_hand=[True, True, False],
        hand_results=[
            EvaluationResult(hand_type=HandType.FULL_HOUSE, kicker=33556480),
            EvaluationResult(hand_type=HandType.FULL_HOUSE, kicker=33556480),
            EvaluationResult(hand_type=HandType.TWO_PAIR, kicker=50331680),
        ],
        remained_in_hand=[True, True, True],
        went_to_showdown=[True, True, True],
        earned_from_pot=[150, 350, 0],
        profits=[50, 150, -200],
    )
Example #5
0
def deal_cards(num_players: int) -> FullDeal:

    # First, select the preflop hands
    preflop_hands = random.sample(hands.ALL_HANDS, num_players)

    # Then, select the board
    selected_cards: Set[Card] = set()
    for hand in preflop_hands:
        selected_cards.update(hand.cards)
    remaining_cards = [c for c in cards.ALL_CARDS if c not in selected_cards]
    board_cards = random.sample(remaining_cards, 5)

    return FullDeal(
        hole_cards=preflop_hands,
        board=Board(
            flop=(board_cards[0], board_cards[1], board_cards[2]),
            turn=board_cards[3],
            river=board_cards[4],
        ),
    )
Example #6
0
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")))
Example #7
0
def test_board_at_street() -> None:

    board = Board(flop=mkflop("AdKs3h"), turn=mkcard("5h"), river=mkcard("7s"))

    assert board.at_street(Street.TURN) == Board(
        flop=(
            Card(rank=Rank.ACE, suit=Suit.DIAMONDS),
            Card(rank=Rank.KING, suit=Suit.SPADES),
            Card(rank=Rank.THREE, suit=Suit.HEARTS),
        ),
        turn=Card(rank=Rank.FIVE, suit=Suit.HEARTS),
        river=None,
    )

    assert board.at_street(Street.FLOP) == Board(
        flop=(
            Card(rank=Rank.ACE, suit=Suit.DIAMONDS),
            Card(rank=Rank.KING, suit=Suit.SPADES),
            Card(rank=Rank.THREE, suit=Suit.HEARTS),
        ),
        turn=None,
        river=None,
    )
Example #8
0
def evaluate_hand(hole_cards: HoleCards, board: Board) -> EvaluationResult:
    (hand, kicker) = pyholdthem.evaluate_hand_from_indices(
        hole_cards.index(), [c.index() for c in board.cards()]
    )

    return EvaluationResult(hand_type=HandType(hand), kicker=kicker)
Example #9
0
def test_full_hand() -> None:
    # Player 3 wins with a flopped set of jacks.
    deal = FullDeal(
        hole_cards=[mkhand("AhKs"), mkhand("Kc10d"), mkhand("5h5c"), mkhand("7s3d")],
        board=Board(flop=mkflop("KdJs3d"), turn=mkcard("7s"), river=mkcard("6s")),
    )

    game = GameRunner(starting_stacks=[300, 300, 300, 300])
    game.start_game()

    # Preflop
    game.bet_raise(to=10)
    game.fold()
    game.bet_raise(to=25)
    game.call()
    game.call()

    # Flop
    game.bet_raise(to=40)
    game.call()
    game.fold()

    # Turn
    game.check()
    game.bet_raise(to=60)
    game.call()

    # River
    game.check()
    game.bet_raise(to=100)
    game.call()

    results = result.get_result(deal, game.game_view())

    player_index = 1

    example = make_example(
        public_context=make_public_context(game.game_view()),
        private_context=make_private_context(deal.hole_cards[1]),
        target=make_target(deal, results),
        public_states=make_public_states(game.game_view(), deal.board),
        player_states=make_player_states(
            player_index, game.game_view(), deal.hole_cards[player_index], deal.board
        ),
        last_actions=make_last_actions(game.game_view()),
        next_actions=make_next_actions(game.game_view()),
        rewards=make_rewards(game.game_view(), results),
    )
    example_dict = seq_example_to_dict(example)

    assert example_dict == {
        "context": {
            "num_steps": [14],
            "private_context__hand_encoded": [140],
            "private_context__hole_card_0_rank": [13],
            "private_context__hole_card_0_suit": [2],
            "private_context__hole_card_1_rank": [10],
            "private_context__hole_card_1_suit": [3],
            "public_context__num_players": [4],
            "public_context__starting_stack_sizes": [300, 300, 300, 300],
            "target__hole_cards": [168, 140, 3, 36],
            "target__total_rewards": [250, -225, -25, 0],
        },
        "features": {
            "last_action__action_encoded": [
                [-1],
                [3],
                [0],
                [3],
                [1],
                [1],
                [5],
                [1],
                [0],
                [1],
                [7],
                [1],
                [1],
                [14],
            ],
            "last_action__amount_added": [
                [-1],
                [10],
                [0],
                [24],
                [23],
                [15],
                [40],
                [40],
                [0],
                [0],
                [60],
                [60],
                [0],
                [100],
            ],
            "last_action__amount_added_percent_of_remaining": [
                [-1.0],
                [0.03333333507180214],
                [0.0],
                [0.08026755601167679],
                [0.07718120515346527],
                [0.0517241396009922],
                [0.145454540848732],
                [0.145454540848732],
                [0.0],
                [0.0],
                [0.25531914830207825],
                [0.25531914830207825],
                [0.0],
                [0.5714285969734192],
            ],
            "last_action__amount_raised": [
                [-1],
                [8],
                [0],
                [15],
                [0],
                [0],
                [40],
                [0],
                [0],
                [0],
                [60],
                [0],
                [0],
                [100],
            ],
            "last_action__amount_raised_percent_of_pot": [
                [-1.0],
                [2.6666667461395264],
                [0.0],
                [1.1538461446762085],
                [0.0],
                [0.0],
                [0.5333333611488342],
                [0.0],
                [0.0],
                [0.0],
                [0.3870967626571655],
                [0.0],
                [0.0],
                [0.3636363744735718],
            ],
            "last_action__move": [
                [-1],
                [5],
                [3],
                [5],
                [4],
                [4],
                [5],
                [4],
                [3],
                [4],
                [5],
                [4],
                [4],
                [5],
            ],
            "next_action__action_encoded": [
                [3],
                [0],
                [3],
                [1],
                [1],
                [5],
                [1],
                [0],
                [1],
                [7],
                [1],
                [1],
                [14],
                [1],
            ],
            "next_action__amount_added": [
                [10],
                [0],
                [24],
                [23],
                [15],
                [40],
                [40],
                [0],
                [0],
                [60],
                [60],
                [0],
                [100],
                [100],
            ],
            "next_action__amount_raised": [
                [8],
                [0],
                [15],
                [0],
                [0],
                [40],
                [0],
                [0],
                [0],
                [60],
                [0],
                [0],
                [100],
                [0],
            ],
            "next_action__move": [
                [5],
                [3],
                [5],
                [4],
                [4],
                [5],
                [4],
                [3],
                [4],
                [5],
                [4],
                [4],
                [5],
                [4],
            ],
            "next_action__new_total_bet": [
                [10],
                [10],
                [25],
                [25],
                [25],
                [40],
                [40],
                [40],
                [0],
                [60],
                [60],
                [0],
                [100],
                [100],
            ],
            "player_state__current_hand_rank": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [3652],
                [-1],
                [-1],
                [3648],
                [-1],
                [-1],
                [3648],
                [-1],
            ],
            "player_state__current_hand_strength": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.5105869770050049],
                [-1.0],
                [-1.0],
                [0.51112300157547],
                [-1.0],
                [-1.0],
                [0.51112300157547],
                [-1.0],
            ],
            "player_state__current_hand_type": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [2],
                [-1],
                [-1],
                [2],
                [-1],
                [-1],
                [2],
                [-1],
            ],
            "player_state__current_player_offset": [
                [1],
                [2],
                [-1],
                [0],
                [1],
                [-1],
                [0],
                [1],
                [-1],
                [0],
                [-1],
                [-1],
                [0],
                [-1],
            ],
            "player_state__frac_hands_better": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.046253468841314316],
                [-1.0],
                [-1.0],
                [0.07439613342285156],
                [-1.0],
                [-1.0],
                [0.17171716690063477],
                [-1.0],
            ],
            "player_state__frac_hands_tied": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.005550416186451912],
                [-1.0],
                [-1.0],
                [0.005797101650387049],
                [-1.0],
                [-1.0],
                [0.005050505045801401],
                [-1.0],
            ],
            "player_state__frac_hands_worse": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.9481961131095886],
                [-1.0],
                [-1.0],
                [0.9198067784309387],
                [-1.0],
                [-1.0],
                [0.8232323527336121],
                [-1.0],
            ],
            "player_state__is_current_player": [
                [0],
                [0],
                [0],
                [1],
                [0],
                [0],
                [1],
                [0],
                [0],
                [1],
                [0],
                [0],
                [1],
                [0],
            ],
            "player_state__win_prob_vs_any": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.8297058343887329],
                [-1.0],
                [-1.0],
                [0.8359622955322266],
                [-1.0],
                [-1.0],
                [0.8232323527336121],
                [-1.0],
            ],
            "player_state__win_prob_vs_better": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.17900000512599945],
                [-1.0],
                [-1.0],
                [0.09700000286102295],
                [-1.0],
                [-1.0],
                [0.0],
                [-1.0],
            ],
            "player_state__win_prob_vs_tied": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.052000001072883606],
                [-1.0],
                [-1.0],
                [0.0],
                [-1.0],
                [-1.0],
                [0.0],
                [-1.0],
            ],
            "player_state__win_prob_vs_worse": [
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [-1.0],
                [0.8659999966621399],
                [-1.0],
                [-1.0],
                [0.9010000228881836],
                [-1.0],
                [-1.0],
                [1.0],
                [-1.0],
            ],
            "public_state__all_in_player_mask": [
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
            ],
            "public_state__amount_to_call": [
                [1, 0, 2, 2],
                [9, 8, 0, 10],
                [9, 8, 0, 10],
                [0, 23, 15, 25],
                [0, 0, 15, 25],
                [0, 0, 0, 0],
                [0, 40, 40, 40],
                [0, 0, 40, 40],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [60, 0, 60, 60],
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [100, 0, 100, 100],
            ],
            "public_state__current_player_mask": [
                [0, 0, 1, 0],
                [0, 0, 0, 1],
                [1, 0, 0, 0],
                [0, 1, 0, 0],
                [0, 0, 1, 0],
                [1, 0, 0, 0],
                [0, 1, 0, 0],
                [0, 0, 1, 0],
                [1, 0, 0, 0],
                [0, 1, 0, 0],
                [1, 0, 0, 0],
                [1, 0, 0, 0],
                [0, 1, 0, 0],
                [1, 0, 0, 0],
            ],
            "public_state__flop_0_rank": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [13],
                [13],
                [13],
                [13],
                [13],
                [13],
                [13],
                [13],
                [13],
            ],
            "public_state__flop_0_suit": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
            ],
            "public_state__flop_1_rank": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [11],
                [11],
                [11],
                [11],
                [11],
                [11],
                [11],
                [11],
                [11],
            ],
            "public_state__flop_1_suit": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [1],
                [1],
                [1],
                [1],
                [1],
                [1],
                [1],
                [1],
                [1],
            ],
            "public_state__flop_2_rank": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
            ],
            "public_state__flop_2_suit": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
                [3],
            ],
            "public_state__folded_player_mask": [
                [0, 0, 0, 0],
                [0, 0, 0, 0],
                [0, 0, 0, 1],
                [0, 0, 0, 1],
                [0, 0, 0, 1],
                [0, 0, 0, 1],
                [0, 0, 0, 1],
                [0, 0, 0, 1],
                [0, 0, 1, 1],
                [0, 0, 1, 1],
                [0, 0, 1, 1],
                [0, 0, 1, 1],
                [0, 0, 1, 1],
                [0, 0, 1, 1],
            ],
            "public_state__min_raise_amount": [
                [2],
                [8],
                [8],
                [15],
                [15],
                [2],
                [40],
                [40],
                [2],
                [2],
                [60],
                [2],
                [2],
                [100],
            ],
            "public_state__pot_size": [
                [3],
                [13],
                [13],
                [37],
                [60],
                [75],
                [115],
                [155],
                [155],
                [155],
                [215],
                [275],
                [275],
                [375],
            ],
            "public_state__river_rank": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [6],
                [6],
                [6],
            ],
            "public_state__river_suit": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [1],
                [1],
                [1],
            ],
            "public_state__stack_sizes": [
                [299, 298, 300, 300],
                [299, 298, 290, 300],
                [299, 298, 290, 300],
                [275, 298, 290, 300],
                [275, 275, 290, 300],
                [275, 275, 275, 300],
                [235, 275, 275, 300],
                [235, 235, 275, 300],
                [235, 235, 275, 300],
                [235, 235, 275, 300],
                [235, 175, 275, 300],
                [175, 175, 275, 300],
                [175, 175, 275, 300],
                [175, 75, 275, 300],
            ],
            "public_state__street": [
                [1],
                [1],
                [1],
                [1],
                [1],
                [2],
                [2],
                [2],
                [3],
                [3],
                [3],
                [4],
                [4],
                [4],
            ],
            "public_state__turn_rank": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [7],
                [7],
                [7],
                [7],
                [7],
                [7],
            ],
            "public_state__turn_suit": [
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [-1],
                [1],
                [1],
                [1],
                [1],
                [1],
                [1],
            ],
            "reward__cumulative_reward": [
                [-25],
                [0],
                [251],
                [-223],
                [-15],
                [275],
                [-200],
                [0],
                [315],
                [-160],
                [315],
                [375],
                [-100],
                [375],
            ],
            "reward__instant_reward": [
                [-10],
                [0],
                [-24],
                [-23],
                [-15],
                [-40],
                [-40],
                [0],
                [0],
                [-60],
                [-60],
                [0],
                [-100],
                [375],
            ],
            "reward__is_players_last_action": [
                [0],
                [1],
                [0],
                [0],
                [0],
                [0],
                [0],
                [1],
                [0],
                [0],
                [0],
                [0],
                [1],
                [1],
            ],
            "reward__won_hand": [
                [0],
                [0],
                [1],
                [0],
                [0],
                [1],
                [0],
                [0],
                [1],
                [0],
                [1],
                [1],
                [0],
                [1],
            ],
        },
    }
Example #10
0
def test_fold_preflop() -> None:
    # Player 3 wins with a flopped set of jacks.
    deal = FullDeal(
        hole_cards=[mkhand("AcAd"), mkhand("AsKh"), mkhand("JcJh")],
        board=Board(flop=mkflop("KsJs3d"), turn=mkcard("7s"), river=mkcard("6s")),
    )

    game = GameRunner(starting_stacks=[200, 250, 100])
    game.start_game()
    game.bet_raise(to=10)
    game.fold()
    game.fold()

    results = result.get_result(deal, game.game_view())

    player_index = 1

    example = make_example(
        public_context=make_public_context(game.game_view()),
        private_context=make_private_context(deal.hole_cards[1]),
        target=make_target(deal, results),
        public_states=make_public_states(game.game_view(), deal.board),
        player_states=make_player_states(
            player_index, game.game_view(), deal.hole_cards[player_index], deal.board
        ),
        last_actions=make_last_actions(game.game_view()),
        next_actions=make_next_actions(game.game_view()),
        rewards=make_rewards(game.game_view(), results),
    )
    example_dict = seq_example_to_dict(example)

    assert example_dict == {
        "context": {
            "num_steps": [3],
            "private_context__hand_encoded": [168],
            "private_context__hole_card_0_rank": [14],
            "private_context__hole_card_0_suit": [1],
            "private_context__hole_card_1_rank": [13],
            "private_context__hole_card_1_suit": [4],
            "public_context__num_players": [3],
            "public_context__starting_stack_sizes": [200, 250, 100],
            "target__hole_cards": [12, 168, 9],
            "target__total_rewards": [-1, -2, 3],
        },
        "features": {
            "last_action__action_encoded": [[-1], [4], [0]],
            "last_action__amount_added": [[-1], [10], [0]],
            "last_action__amount_added_percent_of_remaining": [
                [-1.0],
                [0.10000000149011612],
                [0.0],
            ],
            "last_action__amount_raised": [[-1], [8], [0]],
            "last_action__amount_raised_percent_of_pot": [
                [-1.0],
                [2.6666667461395264],
                [0.0],
            ],
            "last_action__move": [[-1], [5], [3]],
            "next_action__action_encoded": [[4], [0], [0]],
            "next_action__amount_added": [[10], [0], [0]],
            "next_action__amount_raised": [[8], [0], [0]],
            "next_action__move": [[5], [3], [3]],
            "next_action__new_total_bet": [[10], [10], [10]],
            "player_state__current_hand_rank": [[-1], [-1], [-1]],
            "player_state__current_hand_strength": [[-1.0], [-1.0], [-1.0]],
            "player_state__current_hand_type": [[-1], [-1], [-1]],
            "player_state__current_player_offset": [[1], [-1], [0]],
            "player_state__frac_hands_better": [[-1.0], [-1.0], [-1.0]],
            "player_state__frac_hands_tied": [[-1.0], [-1.0], [-1.0]],
            "player_state__frac_hands_worse": [[-1.0], [-1.0], [-1.0]],
            "player_state__is_current_player": [[0], [0], [1]],
            "player_state__win_prob_vs_any": [[-1.0], [-1.0], [-1.0]],
            "player_state__win_prob_vs_better": [[-1.0], [-1.0], [-1.0]],
            "player_state__win_prob_vs_tied": [[-1.0], [-1.0], [-1.0]],
            "player_state__win_prob_vs_worse": [[-1.0], [-1.0], [-1.0]],
            "public_state__all_in_player_mask": [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
            "public_state__amount_to_call": [[1, 0, 2], [9, 8, 0], [9, 8, 0]],
            "public_state__current_player_mask": [[0, 0, 1], [1, 0, 0], [0, 1, 0]],
            "public_state__flop_0_rank": [[-1], [-1], [-1]],
            "public_state__flop_0_suit": [[-1], [-1], [-1]],
            "public_state__flop_1_rank": [[-1], [-1], [-1]],
            "public_state__flop_1_suit": [[-1], [-1], [-1]],
            "public_state__flop_2_rank": [[-1], [-1], [-1]],
            "public_state__flop_2_suit": [[-1], [-1], [-1]],
            "public_state__folded_player_mask": [[0, 0, 0], [0, 0, 0], [1, 0, 0]],
            "public_state__min_raise_amount": [[2], [8], [8]],
            "public_state__pot_size": [[3], [13], [13]],
            "public_state__river_rank": [[-1], [-1], [-1]],
            "public_state__river_suit": [[-1], [-1], [-1]],
            "public_state__stack_sizes": [
                [199, 248, 100],
                [199, 248, 90],
                [199, 248, 90],
            ],
            "public_state__street": [[1], [1], [1]],
            "public_state__turn_rank": [[-1], [-1], [-1]],
            "public_state__turn_suit": [[-1], [-1], [-1]],
            "reward__cumulative_reward": [[3], [0], [0]],
            "reward__instant_reward": [[3], [0], [0]],
            "reward__is_players_last_action": [[1], [1], [1]],
            "reward__won_hand": [[1], [0], [0]],
        },
    }
Example #11
0
def test_monster() -> None:
    deal = FullDeal(
        hole_cards=[mkhand("JcJd"), mkhand("Kc10d")],
        board=Board(flop=mkflop("JsTs3h"),
                    turn=mkcard("Jh"),
                    river=mkcard("As")),
    )

    game = GameRunner(starting_stacks=[300, 400])
    game.start_game()

    # Preflop
    game.bet_raise(to=10)
    game.call()

    # Flop
    game.check()
    game.check()

    # Turn
    game.check()
    game.check()

    # River
    game.check()
    game.check()

    player_index = 0
    private_states = make_player_states(player_index, game.game_view(),
                                        deal.hole_cards[player_index],
                                        deal.board)

    assert private_states == [
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=4,
            frac_better_hands=0.0,
            frac_tied_hands=0.0,
            frac_worse_hands=1.0,
            win_odds=approx(0.9300000071525574, abs=0.1),
            tie_odds=0.0,
            lose_odds=approx(0.07000000029802322, abs=0.1),
            win_odds_vs_better=0.0,
            tie_odds_vs_better=0.0,
            lose_odds_vs_better=0.0,
            win_odds_vs_tied=0.0,
            tie_odds_vs_tied=0.0,
            lose_odds_vs_tied=0.0,
            win_odds_vs_worse=approx(0.9300000071525574, abs=0.1),
            tie_odds_vs_worse=0.0,
            lose_odds_vs_worse=approx(0.07000000029802322, abs=0.1),
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=8,
            frac_better_hands=0.0,
            frac_tied_hands=0.0,
            frac_worse_hands=1.0,
            win_odds=approx(0.9990000128746033, abs=0.1),
            tie_odds=0.0,
            lose_odds=approx(0.0010000000474974513, abs=0.1),
            win_odds_vs_better=0.0,
            tie_odds_vs_better=0.0,
            lose_odds_vs_better=0.0,
            win_odds_vs_tied=0.0,
            tie_odds_vs_tied=0.0,
            lose_odds_vs_tied=0.0,
            win_odds_vs_worse=approx(0.9990000128746033, abs=0.1),
            tie_odds_vs_worse=0.0,
            lose_odds_vs_worse=approx(0.0010000000474974513, abs=0.1),
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=8,
            frac_better_hands=approx(0.001010101055726409, abs=0.1),
            frac_tied_hands=0.0,
            frac_worse_hands=approx(0.9989898800849915, abs=0.1),
            win_odds=approx(0.9989898800849915, abs=0.1),
            tie_odds=0.0,
            lose_odds=approx(0.001010101055726409, abs=0.1),
            win_odds_vs_better=0.0,
            tie_odds_vs_better=0.0,
            lose_odds_vs_better=1.0,
            win_odds_vs_tied=0.0,
            tie_odds_vs_tied=0.0,
            lose_odds_vs_tied=0.0,
            win_odds_vs_worse=1.0,
            tie_odds_vs_worse=0.0,
            lose_odds_vs_worse=0.0,
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
    ]
Example #12
0
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)
Example #13
0
def make_public_states(game: GameView, board: Optional[Board]):
    public_states = []

    for i in iter_game_states(game):
        game_view = game.view(i)

        if board is None:
            current_board = Board(flop=None, turn=None, river=None)
        else:
            current_board = board.at_street(game_view.street())

        current_player_mask = [0 for _ in range(game_view.num_players())]
        current_player_mask[game_view.current_player()] = 1

        if game_view.street(
        ) >= Street.FLOP and current_board.flop is not None:
            flop_0, flop_1, flop_2 = sorted(current_board.flop, key=card_order)
            flop_0_rank = flop_0.rank.value
            flop_0_suit = flop_0.suit.value
            flop_1_rank = flop_1.rank.value
            flop_1_suit = flop_1.suit.value
            flop_2_rank = flop_2.rank.value
            flop_2_suit = flop_2.suit.value
        else:
            flop_0_rank = None
            flop_0_suit = None
            flop_1_rank = None
            flop_1_suit = None
            flop_2_rank = None
            flop_2_suit = None

        if game_view.street(
        ) >= Street.TURN and current_board.turn is not None:
            turn = current_board.turn
            turn_rank = turn.rank.value
            turn_suit = turn.suit.value
        else:
            turn_rank = None
            turn_suit = None

        if game_view.street(
        ) >= Street.RIVER and current_board.river is not None:
            river = current_board.river
            river_rank = river.rank.value
            river_suit = river.suit.value
        else:
            river_rank = None
            river_suit = None

        public_states.append(
            PublicState(
                num_players_remaining=sum(game_view.is_in_hand()),
                pot_size=game_view.pot_size(),
                street=game_view.street().value,
                current_player_mask=current_player_mask,
                folded_player_mask=game_view.is_folded(),
                all_in_player_mask=game_view.is_all_in(),
                stack_sizes=game_view.current_stack_sizes(),
                amount_to_call=game_view.amount_to_call(),
                min_raise_amount=game_view.min_bet_amount(),
                flop_0_rank=flop_0_rank,
                flop_0_suit=flop_0_suit,
                flop_1_rank=flop_1_rank,
                flop_1_suit=flop_1_suit,
                flop_2_rank=flop_2_rank,
                flop_2_suit=flop_2_suit,
                turn_rank=turn_rank,
                turn_suit=turn_suit,
                river_rank=river_rank,
                river_suit=river_suit,
            ))

    return public_states
Example #14
0
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)
Example #15
0
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)
Example #16
0
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
Example #17
0
def test_state() -> None:
    deal = FullDeal(
        hole_cards=[mkhand("AhKs"), mkhand("Kc10d")],
        board=Board(flop=mkflop("KdJs3d"),
                    turn=mkcard("7s"),
                    river=mkcard("6s")),
    )

    game = GameRunner(starting_stacks=[300, 400])
    game.start_game()

    # Preflop
    game.bet_raise(to=10)
    game.call()

    # Flop
    game.check()
    game.check()

    # Turn
    game.check()
    game.check()

    # River
    game.check()
    game.check()

    player_index = 0
    private_states = make_player_states(player_index, game.game_view(),
                                        deal.hole_cards[player_index],
                                        deal.board)

    assert private_states == [
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=2,
            frac_better_hands=approx(0.02867715060710907, abs=0.1),
            frac_tied_hands=approx(0.005550416186451912, abs=0.1),
            frac_worse_hands=approx(0.9657724499702454, abs=0.1),
            win_odds=approx(0.8368927240371704, abs=0.1),
            tie_odds=approx(0.010364476591348648, abs=0.1),
            lose_odds=approx(0.15274283289909363, abs=0.1),
            win_odds_vs_better=approx(0.16899999976158142, abs=0.1),
            tie_odds_vs_better=approx(0.0020000000949949026, abs=0.1),
            lose_odds_vs_better=approx(0.8289999961853027, abs=0.1),
            win_odds_vs_tied=0.0,
            tie_odds_vs_tied=approx(0.9869999885559082, abs=0.1),
            lose_odds_vs_tied=approx(0.013000000268220901, abs=0.1),
            win_odds_vs_worse=approx(0.8840000033378601, abs=0.1),
            tie_odds_vs_worse=approx(0.004000000189989805, abs=0.1),
            lose_odds_vs_worse=approx(0.1120000034570694, abs=0.1),
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=2,
            frac_better_hands=approx(0.05603864789009094, abs=0.1),
            frac_tied_hands=approx(0.005797101650387049, abs=0.1),
            frac_worse_hands=approx(0.938164234161377, abs=0.1),
            win_odds=approx(0.8556057810783386, abs=0.1),
            tie_odds=approx(0.005797101650387049, abs=0.1),
            lose_odds=approx(0.13859710097312927, abs=0.1),
            win_odds_vs_better=0.0,
            tie_odds_vs_better=0.0,
            lose_odds_vs_better=1.0,
            win_odds_vs_tied=0.0,
            tie_odds_vs_tied=1.0,
            lose_odds_vs_tied=0.0,
            win_odds_vs_worse=approx(0.9120000004768372, abs=0.1),
            tie_odds_vs_worse=0.0,
            lose_odds_vs_worse=approx(0.08799999952316284, abs=0.1),
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
        PlayerState(
            is_current_player=True,
            current_player_offset=0,
            current_hand_type=2,
            frac_better_hands=approx(0.14646464586257935, abs=0.1),
            frac_tied_hands=approx(0.0060606058686971664, abs=0.1),
            frac_worse_hands=approx(0.8474747538566589, abs=0.1),
            win_odds=approx(0.8474747538566589, abs=0.1),
            tie_odds=approx(0.0060606058686971664, abs=0.1),
            lose_odds=approx(0.14646464586257935, abs=0.1),
            win_odds_vs_better=0.0,
            tie_odds_vs_better=0.0,
            lose_odds_vs_better=1.0,
            win_odds_vs_tied=0.0,
            tie_odds_vs_tied=1.0,
            lose_odds_vs_tied=0.0,
            win_odds_vs_worse=1.0,
            tie_odds_vs_worse=0.0,
            lose_odds_vs_worse=0.0,
        ),
        PlayerState(
            is_current_player=False,
            current_player_offset=1,
            current_hand_type=None,
            frac_better_hands=None,
            frac_tied_hands=None,
            frac_worse_hands=None,
            win_odds=None,
            tie_odds=None,
            lose_odds=None,
            win_odds_vs_better=None,
            tie_odds_vs_better=None,
            lose_odds_vs_better=None,
            win_odds_vs_tied=None,
            tie_odds_vs_tied=None,
            lose_odds_vs_tied=None,
            win_odds_vs_worse=None,
            tie_odds_vs_worse=None,
            lose_odds_vs_worse=None,
        ),
    ]
Example #18
0
def test_fold_preflop() -> None:
    # Player 3 wins with a flopped set of jacks.
    deal = FullDeal(
        hole_cards=[mkhand("AcAd"),
                    mkhand("AsKh"),
                    mkhand("JcJh")],
        board=Board(flop=mkflop("KsJs3d"),
                    turn=mkcard("7s"),
                    river=mkcard("6s")),
    )

    game = GameRunner(starting_stacks=[200, 250, 300])
    game.start_game()
    game.bet_raise(to=10)
    game.fold()
    game.fold()

    results = result.get_result(deal, game.game_view())

    s = Stats()
    s.update_stats(game.game_view(), results, player_id=0)
    assert s == Stats(
        num_hands=1,
        reward=-1,
        num_wins=0,
        num_losses=1,
        num_flops=0,
        num_turns=0,
        num_rivers=0,
        num_showdowns=0,
        num_decisions=1,
        num_check=0,
        num_call=0,
        total_amount_called=0,
        num_bet=0,
        total_amount_bet=0,
        num_fold=1,
    )

    s = Stats()
    s.update_stats(game.game_view(), results, player_id=1)
    assert s == Stats(
        num_hands=1,
        reward=-2,
        num_wins=0,
        num_losses=1,
        num_flops=0,
        num_turns=0,
        num_rivers=0,
        num_showdowns=0,
        num_decisions=1,
        num_check=0,
        num_call=0,
        total_amount_called=0,
        num_bet=0,
        total_amount_bet=0,
        num_fold=1,
    )

    s = Stats()
    s.update_stats(game.game_view(), results, player_id=2)
    assert s == Stats(
        num_hands=1,
        reward=3,
        num_wins=1,
        num_losses=0,
        num_flops=0,
        num_turns=0,
        num_rivers=0,
        num_showdowns=0,
        num_decisions=1,
        num_check=0,
        num_call=0,
        total_amount_called=0,
        num_bet=1,
        total_amount_bet=10,
        num_fold=0,
    )
Example #19
0
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)