def test_get_legal_actions(self): self.env.game.get_legal_actions = MagicMock(return_value=[ Card(Spades, Queen), Card(Clubs, Ten), Card(Diamonds, Ace), Card(Hearts, Jack) ]) expected = [2, 10, 17, 19] self.assertEqual(expected, self.env._get_legal_actions())
def test_judge_round_when_no_active_marriage(self): np_random = np.random.RandomState() judger = Judger(np_random) active_marriage = None stock = [(0, Card(Clubs, Ten)), (1, Card(Hearts, Nine)), (2, Card(Clubs, Ace))] expected = (2, 21) result = judger.judge_round(stock, active_marriage) self.assertEqual(expected, result)
def test_encode_cards_set(self): cards = [ Card(Spades, Queen), Card(Clubs, Ten), Card(Diamonds, Ace), Card(Hearts, Jack) ] expected = [2, 10, 17, 19] result = self.env._encode_cards_set(cards) self.assertSetEqual(set(expected), set(result))
def _check_marriage(player: ThousandSchnapsenPlayer, card: Card) -> bool: """ Check if new marriage is activated Args: player (ThousandSchnapsenPlayer): Current player card (Card): Card to put on the stock Return: (bool): True if new marriage activated, otherwise False """ if card.rank == King and (Card(card.suit, Queen) in player.hand): return True if card.rank == Queen and (Card(card.suit, King) in player.hand): return True return False
def test_get_legal_actions_when_cannot_put_same_suit_nor_beat(self): num_players = 3 np_random = np.random.RandomState() cur_round = Round(num_players, np_random) player = Player(0, np_random) cards = { Card(Spades, Ten), Card(Diamonds, Nine), Card(Spades, Queen), } player.hand = cards stock = [(2, Card(Clubs, Ace))] active_marriage = Hearts expected = cards result = cur_round.get_legal_actions(stock, active_marriage, player) self.assertSetEqual(expected, result)
def _reason_about_cards(self, action: Card, trump: bool): current_player = self.get_player_id() for i in range(self.player_num): self.possible_cards[i] -= {action} self.certain_cards[i] -= {action} self.possible_cards[current_player] -= self._get_impossible_cards( action) if trump: second_marriage_part = Card(action.suit, King if action.rank == Queen else King) self.certain_cards[current_player] |= {second_marriage_part} if len(self.state['stock']) == 0 and not trump and action.rank in { Queen, King }: second_marriage_part = Card(action.suit, King if action.rank == Queen else King) self.possible_cards[current_player] -= {second_marriage_part}
def test_proceed_round(self): num_players = 3 np_random = np.random.RandomState() cur_round = Round(num_players, np_random) game_pointer = 0 players = [ Player(player_id, np_random) for player_id in range(num_players) ] stock = [(2, Card(Diamonds, Ten))] used_marriages = set() card = Card(Diamonds, Queen) players[game_pointer].hand = [card] expected = (1, None) result = cur_round.proceed_round(game_pointer, players, stock, used_marriages, card) self.assertEqual(expected, result) self.assertEqual((game_pointer, card), stock[1]) self.assertEqual(0, len(players[game_pointer].hand))
def test_get_legal_actions_when_stock_empty(self): num_players = 3 np_random = np.random.RandomState() cur_round = Round(num_players, np_random) player = Player(0, np_random) cards = { Card(Spades, Ten), Card(Diamonds, Nine), Card(Hearts, Queen), Card(Spades, King), Card(Clubs, Ace), } player.hand = cards stock = [] active_marriage = None expected = cards result = cur_round.get_legal_actions(stock, active_marriage, player) self.assertSetEqual(expected, result)
def test_extract_state_when_round_in_progress(self): state = { 'stock': [(1, Card(Diamonds, Jack))], 'active_marriage': Hearts, 'used_marriages': {Hearts, Diamonds}, 'hand': frozenset([Card(Diamonds, Queen), Card(Spades, Nine)]), 'players_used': [[], [Card(Diamonds, Jack)], []], 'current_player': 2 } expected = np.zeros(152, dtype=int) expected[[0, 14]] = 1 # hand expected[24:48] = 1 # common possible expected[[24 + 0, 24 + 14]] = 0 # remove hand from possible expected[109] = 1 # stock expected[147] = 1 # active marriage expected[[150, 151]] = 1 # used marriages result = self.env._extract_state(state)['obs'] self.assertTrue(np.allclose(expected, result))
def _decode_action(self, action_id): """ Decode Action id to the action in the game. Arg: action_id (int): The id of the action Return: (Card): The action that will be passed to the game engine. """ suit = Card.valid_suit[action_id // CARDS_PER_SUIT_COUNT] rank = Card.valid_rank[action_id % CARDS_PER_SUIT_COUNT] return Card(suit, rank)
def test_proceed_round_when_marriage_activated(self): num_players = 3 np_random = np.random.RandomState() cur_round = Round(num_players, np_random) game_pointer = 0 players = [ Player(player_id, np_random) for player_id in range(num_players) ] stock = [] used_marriages = set() card = Card(Diamonds, Queen) players[game_pointer].hand = [card, Card(Diamonds, King)] players[game_pointer].points = 0 expected = (1, Diamonds) result = cur_round.proceed_round(game_pointer, players, stock, used_marriages, card) self.assertEqual(expected, result) self.assertEqual((game_pointer, card), stock[0]) self.assertEqual(80, players[game_pointer].points) self.assertEqual(1, len(players[game_pointer].hand))
def test_encode_card_when_card_is_defined(self): expected = 10 result = self.env._encode_card(Card(Clubs, Ten)) self.assertEqual(expected, result)
class TestThousandSchnapsenEnv(unittest.TestCase): def __init__(self, *args): super().__init__(*args) self.env = make('thousand-schnapsen', config={'seed': 0}) self.env.reset() @data((2, Card(Spades, Queen)), (19, Card(Hearts, Jack)), (10, Card(Clubs, Ten)), (17, Card(Diamonds, Ace))) @unpack def test_decode_action(self, action_id: int, card: Card): decoded_action = self.env._decode_action(action_id) self.assertEqual(card, decoded_action) def test_get_legal_actions(self): self.env.game.get_legal_actions = MagicMock(return_value=[ Card(Spades, Queen), Card(Clubs, Ten), Card(Diamonds, Ace), Card(Hearts, Jack) ]) expected = [2, 10, 17, 19] self.assertEqual(expected, self.env._get_legal_actions()) def test_encode_cards_set(self): cards = [ Card(Spades, Queen), Card(Clubs, Ten), Card(Diamonds, Ace), Card(Hearts, Jack) ] expected = [2, 10, 17, 19] result = self.env._encode_cards_set(cards) self.assertSetEqual(set(expected), set(result)) def test_encode_card_when_card_is_none(self): expected = [] result = self.env._encode_card(None) self.assertSetEqual(set(expected), set(result)) def test_encode_card_when_card_is_defined(self): expected = 10 result = self.env._encode_card(Card(Clubs, Ten)) self.assertEqual(expected, result) def test_encode_marriage_when_suit_is_none(self): expected = [] result = self.env._encode_marriage(None) self.assertSetEqual(set(expected), set(result)) def test_encode_marriage_when_suit_is_defined(self): expected = 2 result = self.env._encode_marriage(Diamonds) self.assertEqual(expected, result) def test_encode_marriages(self): expected = [1, 3] result = self.env._encode_marriages({Clubs, Hearts}) self.assertSetEqual(set(expected), set(result)) def test_encode(self): code = np.zeros(10, dtype=int) chunk = [1, 2] start_index = 2 length = 4 expected = np.zeros(10, dtype=int) expected[[3, 4]] = 1 end_index = self.env._encode(code, chunk, start_index, length) self.assertTrue(np.allclose(expected, code)) self.assertEqual(6, end_index) def test_extract_state_when_round_in_progress(self): state = { 'stock': [(1, Card(Diamonds, Jack))], 'active_marriage': Hearts, 'used_marriages': {Hearts, Diamonds}, 'hand': frozenset([Card(Diamonds, Queen), Card(Spades, Nine)]), 'players_used': [[], [Card(Diamonds, Jack)], []], 'current_player': 2 } expected = np.zeros(152, dtype=int) expected[[0, 14]] = 1 # hand expected[24:48] = 1 # common possible expected[[24 + 0, 24 + 14]] = 0 # remove hand from possible expected[109] = 1 # stock expected[147] = 1 # active marriage expected[[150, 151]] = 1 # used marriages result = self.env._extract_state(state)['obs'] self.assertTrue(np.allclose(expected, result)) def test_extract_state_when_new_round(self): state = { 'stock': [(1, Card(Diamonds, Jack)), (1, Card(Diamonds, King)), (1, Card(Diamonds, Ace))], 'active_marriage': Hearts, 'used_marriages': {Hearts, Diamonds}, 'hand': frozenset([Card(Diamonds, Queen), Card(Spades, Nine)]), 'players_used': [[], [Card(Diamonds, Jack)], []], 'current_player': 2 } expected = np.zeros(152, dtype=int) expected[[0, 14]] = 1 # hand expected[24:48] = 1 # common possible expected[[24 + 0, 24 + 14]] = 0 # remove hand from possible expected[147] = 1 # active marriage expected[[150, 151]] = 1 # used marriages result = self.env._extract_state(state)['obs'] self.assertTrue(np.allclose(expected, result))
def get_color(suit: str) -> Set[Card]: ranks = ['9', 'J', 'Q', 'K', 'T', 'A'] return {Card(suit, rank) for rank in ranks}
def action_dto_to_env_action(action: Action) -> int: card = Card(rank=action.card.rank, suit=action.card.suit) return card.__hash__()