def step(self,
             dog: List[Card]) -> Tuple[DogPhaseObservation, float, bool, None]:
        if type(dog) != list:
            raise FrenchTarotException("Wrong type for 'action'")
        if len(set(dog)) != len(dog):
            raise FrenchTarotException("Duplicated cards in dog")
        if np.any(["king" in card.value for card in dog]):
            raise FrenchTarotException("There should be no king in dog")
        if np.any([is_oudler(card) for card in dog]):
            raise FrenchTarotException("There should be no oudler in dog")
        if np.any([card not in self.hand for card in dog]):
            raise FrenchTarotException(
                "Card in dog not in taking player's hand")
        if len(dog) != self._n_cards_in_dog:
            raise FrenchTarotException("Wrong number of cards in dog")

        n_trumps_in_dog = np.sum(["trump" in card.value for card in dog])
        if n_trumps_in_dog > 0:
            n_trumps_in_taking_player_hand = count_trumps_and_excuse(self.hand)
            n_kings_in_taking_player_hand = np.sum(
                ["king" in card.value for card in self.hand])
            allowed_trumps_in_dog = self._n_cards_in_dog - (
                len(self.hand) - n_trumps_in_taking_player_hand -
                n_kings_in_taking_player_hand)
            if n_trumps_in_dog != allowed_trumps_in_dog:
                raise FrenchTarotException(
                    "There should be no more trumps in dog than needed")

        index_to_keep_in_hand = [card not in dog for card in self.hand]
        self.hand = list(np.array(self.hand)[index_to_keep_in_hand])
        reward = compute_card_set_points(dog)
        self.new_dog = dog
        done = True
        info = None
        return self.observation, reward, done, info
def test_play_excuse_first():
    environment = setup_environment_for_card_phase()[0]
    environment.step(Card.EXCUSE)
    environment.step(Card.HEART_KING)
    environment.step(Card.HEART_4)
    observation, reward, done, _ = environment.step(Card.HEART_2)

    expected_values = [
        Card.EXCUSE, Card.HEART_KING, Card.HEART_4, Card.HEART_2
    ]
    assert reward[-1] == compute_card_set_points(
        expected_values)  # last player's team won this round
    assert not done
def test_play_complete_round_valid_last_player_team_wins():
    environment = setup_environment_for_card_phase()[0]
    environment.step(Card.HEART_1)
    environment.step(Card.HEART_KING)
    environment.step(Card.HEART_4)
    observation, reward, done, _ = environment.step(Card.HEART_2)

    expected_reward = compute_card_set_points(
        [Card.HEART_1, Card.HEART_KING, Card.HEART_4, Card.HEART_2])
    assert reward[0] == 0
    assert reward[1] == expected_reward
    assert reward[2] == expected_reward
    assert reward[3] == expected_reward
    assert not done
def test_play_complete_round_valid_last_player_team_loses():
    environment = setup_environment_for_card_phase(taker=1)[0]
    environment.step(Card.HEART_1)
    environment.step(Card.HEART_KING)
    environment.step(Card.HEART_4)
    observation, reward, done, _ = environment.step(Card.HEART_2)

    expected_values = [
        Card.HEART_KING, Card.HEART_4, Card.HEART_2, Card.HEART_1
    ]
    assert reward[0] == compute_card_set_points(expected_values)
    assert reward[1] == 0
    assert reward[2] == 0
    assert reward[3] == 0
    assert not done
Ejemplo n.º 5
0
    def _solve_round(self) -> List[float]:
        starting_player = self.next_player
        winning_card_index = self._get_winning_card_index(
            self._played_cards_in_round)
        play_order = np.arange(
            starting_player, starting_player + self.n_players) % self.n_players
        winner = play_order[winning_card_index]
        reward_for_winner = compute_card_set_points(
            self._played_cards_in_round)
        rewards = []
        if winner == 0:  # if winner is taking player
            rewards.append(reward_for_winner)
            rewards.extend([0] * (self.n_players - 1))
            self._winners_per_round.append("taker")
        else:
            rewards.append(0)
            rewards.extend([reward_for_winner] * (self.n_players - 1))
            self._winners_per_round.append("opponents")

        won_cards = self._played_cards_in_round.copy()
        if Card.EXCUSE in self._played_cards_in_round:
            excuse_owner = play_order[self._played_cards_in_round.index(
                Card.EXCUSE)]
            won_cards.remove(Card.EXCUSE)
            if excuse_owner == 0:
                self._won_cards_per_teams["taker"].append(Card.EXCUSE)
                self._bonus_points_per_teams["opponents"] += 0.5
                self._bonus_points_per_teams["taker"] -= 0.5
            else:
                self._won_cards_per_teams["opponents"].append(Card.EXCUSE)
                if winner == 0:
                    self._bonus_points_per_teams["opponents"] -= 0.5
                    self._bonus_points_per_teams["taker"] += 0.5
        if winner == 0:
            self._won_cards_per_teams["taker"] += won_cards
        else:
            self._won_cards_per_teams["opponents"] += won_cards
        self.current_player_id = winner
        self._played_cards_in_round = []
        return rewards
def test_play_excuse_in_round():
    shuffled_deck = list(np.random.RandomState(seed=1988).permutation(CARDS))
    shuffled_deck[15] = Card.DIAMOND_KING
    shuffled_deck[40] = Card.EXCUSE
    environment, observation_0 = setup_environment_for_card_phase(
        shuffled_deck=shuffled_deck)
    observation_1 = environment.step(Card.HEART_1)[0]
    observation_2 = environment.step(Card.HEART_5)[0]
    observation_3 = environment.step(Card.EXCUSE)[0]
    observation_4, reward, done, _ = environment.step(Card.HEART_2)

    assert observation_0.played_cards_in_round == []
    assert observation_1.played_cards_in_round == [Card.HEART_1]
    assert observation_2.played_cards_in_round == [Card.HEART_1, Card.HEART_5]
    assert observation_3.played_cards_in_round == [
        Card.HEART_1, Card.HEART_5, Card.EXCUSE
    ]

    expected_values = [Card.HEART_1, Card.HEART_5, Card.EXCUSE, Card.HEART_2]
    assert reward[-1] == compute_card_set_points(
        expected_values)  # last player's team won this round
    assert not done
Ejemplo n.º 7
0
def test_point_count_card_set():
    assert compute_card_set_points(CARDS) == 91
Ejemplo n.º 8
0
    def _compute_win_loss(self, is_petit_played_in_round: bool,
                          is_excuse_played_in_round: bool,
                          is_taker_win_round: bool) -> List[float]:
        dog = self._made_dog if len(self._made_dog) > 0 else self._original_dog
        taker_points = compute_card_set_points(
            self._won_cards_per_teams["taker"] + list(dog))
        taker_points += self._bonus_points_per_teams["taker"]
        opponents_points = compute_card_set_points(
            self._won_cards_per_teams["opponents"])
        opponents_points += self._bonus_points_per_teams["opponents"]
        if taker_points + opponents_points != 91:
            raise FrenchTarotException("Invalid score")
        if taker_points != round(taker_points):
            raise FrenchTarotException("Score should be integer")
        n_oudlers_taker = np.sum([
            is_oudler(card)
            for card in list(self._won_cards_per_teams["taker"]) + list(dog)
        ])
        victory_threshold = None
        if n_oudlers_taker == 3:
            victory_threshold = 36
        elif n_oudlers_taker == 2:
            victory_threshold = 41
        elif n_oudlers_taker == 1:
            victory_threshold = 51
        elif n_oudlers_taker == 0:
            victory_threshold = 56
        else:
            FrenchTarotException("Invalid number of oudlers")
        # noinspection PyTypeChecker
        diff = abs(victory_threshold - taker_points)
        contract_value = 25 + diff
        bid_to_multiplier_map = {
            Bid.PASS: 0,
            Bid.PETITE: 1,
            Bid.GARDE: 2,
            Bid.GARDE_SANS: 4,
            Bid.GARDE_CONTRE: 6
        }
        multiplier = bid_to_multiplier_map[np.max(self._bid_per_player)]
        contract_value = int(contract_value * multiplier)
        if taker_points < victory_threshold:
            contract_value *= -1

        winners_per_round = self._winners_per_round
        taker_achieved_chelem = self.has_team_achieved_chelem(
            winners_per_round, is_excuse_played_in_round, "taker")
        if taker_achieved_chelem:
            contract_value += 400 if self.chelem_announced else 200
        elif self.has_team_achieved_chelem(winners_per_round,
                                           is_excuse_played_in_round,
                                           "opponents"):
            contract_value -= 200
        elif not taker_achieved_chelem and self.chelem_announced:
            contract_value -= 200

        if is_petit_played_in_round:
            to_add = (10 if not is_taker_win_round else -10) * multiplier
            if taker_points > victory_threshold:
                to_add *= -1
            contract_value += to_add

        rewards = [
            3 * contract_value, -contract_value, -contract_value,
            -contract_value
        ]
        rewards = self._update_rewards_with_poignee(rewards)

        assert np.sum(rewards) == 0
        return rewards