Beispiel #1
0
def test_when_deck_order_cards_and_non_card_passed_then_raise_error():
    deck = Deck()
    cards = [Card("C5"), "Six of Spades", Card("S9")]
    with raises(
            ValueError,
            match=
            "All objects within cards value must be an instance of the Cards Class"
    ):
        deck.order_cards(cards)
Beispiel #2
0
def test_when_card_init_and_suit_value_bad_then_raise_error(suit_val):
    with raises(
            ValueError,
            match=
            f"Card ID first character '{suit_val}' is not within valid list of suit identifiers"
    ):
        Card(f"{suit_val}6")
Beispiel #3
0
def test_when_card_init_then_correct_values_set(card_val, card_rank, card_suit,
                                                card_name, card_id):
    card = Card(card_id)
    assert card.name == card_name
    assert card.identity == card_id
    assert card.suit == card_suit
    assert card.rank == card_rank
    assert card.value == card_val
Beispiel #4
0
def cards_five():
    return [Card("D3"), Card("DA"), Card("CQ"), Card("H7"), Card("S9")]
Beispiel #5
0
def test_when_card_init_and_card_rank_bad_then_raise_error(card_val):
    with raises(ValueError,
                match=f"Card ID second character '{card_val}' "
                f"is not within valid list of rank identifiers"):
        Card(f"H{card_val}")
Beispiel #6
0
def test_when_card_init_and_card_id_not_2_chars_then_raise_error(card_id):
    with raises(ValueError,
                match="Card ID provided must be exactly 2 characters long"):
        Card(card_id)
Beispiel #7
0
                f"is not within valid list of rank identifiers"):
        Card(f"H{card_val}")


@mark.parametrize("suit_val", [3, "s", "c", "h", "d"])
def test_when_card_init_and_suit_value_bad_then_raise_error(suit_val):
    with raises(
            ValueError,
            match=
            f"Card ID first character '{suit_val}' is not within valid list of suit identifiers"
    ):
        Card(f"{suit_val}6")


@mark.parametrize("card_a, card_b, expected",
                  [(Card("D7"), Card("DT"), False),
                   (Card("HQ"), Card("H3"), True),
                   (Card("S3"), Card("CK"), False),
                   (Card("CT"), Card("H4"), True),
                   (Card("H7"), Card("S7"), False)])
def test_when_card_greater_than_then_correct_result_returned(
        card_a, card_b, expected):
    actual = card_a > card_b
    assert actual == expected


@mark.parametrize("card_a, card_b, expected",
                  [(Card("D7"), Card("DT"), True),
                   (Card("HQ"), Card("H3"), False),
                   (Card("S3"), Card("CK"), True),
                   (Card("CT"), Card("H4"), False),
Beispiel #8
0
    def find_odds(
        self, player_hole_cards: Dict[str, List[Card]], board_cards: List[Card]
    ):
        """
        Abstract method to implement to find the odds of all players winning from the current situation.

        :param player_hole_cards: Dictionary, of player names and their hole cards
        :param board_cards: List of cards representing the current board cards
        :return: Dictionary of player names and their likelyhood of winning from this situation.
        """

        drawable_cards = self._determine_unused_cards(player_hole_cards, board_cards)
        player_current_hand = {
            player: self.find_best_hand(hole_cards, board_cards)
            for player, hole_cards in player_hole_cards.items()
        }
        current_best_hand_rank = max(
            [best_hand[HAND_RANK] for best_hand in player_current_hand.values()]
        )

        ranked_player_outs = {}
        for hand_info in self._hand_rankings:
            for player, current_hand in player_current_hand.items():
                if (
                    current_hand[HAND_RANK]
                    >= hand_info[HAND_RANK]
                    <= current_best_hand_rank
                ):
                    player_outs = find_outs_scenarios(
                        GAME_TYPE_TEXAS_HOLDEM,
                        hand_info[HAND_TITLE],
                        hole_cards=player_hole_cards[player],
                        board_cards=board_cards,
                        available_cards=drawable_cards,
                    )
                    if hand_info[HAND_RANK] not in ranked_player_outs.keys():
                        ranked_player_outs[hand_info[HAND_RANK]] = {player: player_outs}
                    else:
                        ranked_player_outs[hand_info[HAND_RANK]][player] = player_outs

        utilised_outs = []
        wins = {player: 0 for player in player_hole_cards.keys()}

        for rank, player_out_scenarios in ranked_player_outs.items():
            print(f"Assigning wins for rank {rank} outs")
            players_with_outs = [
                player
                for player, out_scenarios in player_out_scenarios.items()
                if out_scenarios
            ]
            if not players_with_outs:
                print("No players with outs for this rank")
                continue
            elif len(players_with_outs) == 1:
                player_name = players_with_outs[0]
                print(
                    f"Only player {player_name} has outs for this rank.  Assigning wins"
                )
                potential_outs = [
                    scenario[OUT_STRING]
                    for scenario in player_out_scenarios[player_name]
                ]
                claimed_outs = [
                    claim_out_string(utilised_outs, out_string, drawable_cards)
                    for out_string in potential_outs
                ]
                claimed_outs = [item for sublist in claimed_outs for item in sublist]

                wins[player_name] += len(claimed_outs)
                utilised_outs.extend(claimed_outs)
            else:
                print(
                    f"Multiple players found to have outs at this rank: {players_with_outs}.  Tiebreaking outs."
                )
                combined_outs = {player: [] for player in players_with_outs}
                for player, out_scenarios in player_out_scenarios.items():
                    if not out_scenarios:
                        continue
                    for scenario in out_scenarios:
                        scenario["OUTS"] = claim_out_string(
                            utilised_outs, scenario[OUT_STRING], drawable_cards
                        )
                        combined_outs[player].extend(scenario["OUTS"])

                for player, out_scenarios in player_out_scenarios.items():
                    if not out_scenarios:
                        continue
                    combined_outs[player].sort()
                    my_outs = list(combo for combo, _ in groupby(combined_outs[player]))
                    my_outs = [out for out in my_outs if out not in utilised_outs]
                    their_outs = [
                        outs
                        for player_name, outs in combined_outs.items()
                        if player_name != player
                    ]
                    their_outs = [item for sublist in their_outs for item in sublist]
                    their_outs.sort()
                    their_outs = list(combo for combo, _ in groupby(their_outs))
                    their_outs = [out for out in their_outs if out not in utilised_outs]

                    unique_outs = [out for out in my_outs if out not in their_outs]
                    conflicted_outs = [out for out in my_outs if out not in unique_outs]

                    wins[player] += len(unique_outs)
                    utilised_outs.extend(unique_outs)

                    for out_ids in conflicted_outs:
                        valid_players = [
                            player_name
                            for player_name, outs in combined_outs.items()
                            if out_ids in outs
                        ]

                        tiebreakers = {}
                        hole_cards = {}
                        for player in valid_players:
                            tiebreakers[player] = [
                                scenario[TIEBREAKER]
                                for scenario in player_out_scenarios[player]
                                if out_ids in scenario["OUTS"]
                            ][0]
                            hole_cards[player] = player_hole_cards[player]

                        drawn_cards = [Card(card_id) for card_id in out_ids]
                        kwarg_set = TB_DRAWS_KWAGRS[self._hand_rankings[HAND_TITLE]]
                        kwargs = {
                            TB_DRAWS_KWARGS_ALL: {
                                "tiebreakers": tiebreakers,
                                "hole_cards": hole_cards,
                                "board_cards": board_cards,
                                "drawn_cards": drawn_cards,
                            },
                            TB_DRAWS_KWARGS_TIEBREAKER: {"tiebreakers": tiebreakers},
                        }[kwarg_set]
                        winner = tiebreak_outs_draw(
                            GAME_TYPE_TEXAS_HOLDEM, hand_info[HAND_TITLE], **kwargs
                        )
                        if winner not in wins.keys():
                            wins[winner] = 1
                        else:
                            wins[winner] += 1
                        utilised_outs.append(out_ids)

        draw_combo_num = 1
        cards_to_draw = 5 - len(board_cards)
        for draw in range(cards_to_draw):
            cards_available = len(drawable_cards) - draw
            draw_combo_num *= cards_available
        draw_combo_num /= cards_to_draw

        odds = {
            player: win_count / draw_combo_num for player, win_count in wins.items()
        }
        return odds