def test_step(self): game = Game() state, _ = game.init_game() action = np.random.choice(game.get_legal_actions(state)) state, next_player_id = game.step(action) current = game.round.current_player self.assertLessEqual(len(state['current_hand']), 14) self.assertEqual(next_player_id, current)
def test_step_back(self): game = Game(allow_step_back=True) state, player_id = game.init_game() action = np.random.choice(game.get_legal_actions(state)) game.step(action) game.step_back() self.assertEqual(game.round.current_player, player_id) self.assertEqual(len(game.history), 0) success = game.step_back() self.assertEqual(success, False)
def __init__(self, config): self.game = Game() super().__init__(config) self.action_id = card_encoding_dict self.de_action_id = { self.action_id[key]: key for key in self.action_id.keys() } self.state_shape = [6, 34, 4]
def test_get_payoffs(self): game = Game() state, _ = game.init_game() while not game.is_over(): actions = game.get_legal_actions(state) action = np.random.choice(actions) state, _ = game.step(action) total_cards = len(state['current_hand']) self.assertLessEqual(total_cards, 14) win = game.is_over() self.assertEqual(win, True)
def test_get_player_num(self): game = Game() num_player = game.get_player_num() self.assertEqual(num_player, 4)
def test_get_legal_actions(self): game = Game() state, _ = game.init_game() actions = game.get_legal_actions(state) for action in actions: self.assertIn(action, state['current_hand'])
def test_get_player_id(self): game = Game() _, player_id = game.init_game() current = game.get_player_id() self.assertEqual(player_id, current)
def test_init_game(self): game = Game() state, _ = game.init_game() total_cards = list(state['current_hand']) self.assertGreaterEqual(len(total_cards), 14)
def test_get_action_num(self): game = Game() action_num = game.get_action_num() self.assertEqual(action_num, 38)
def test_get_num_players(self): game = Game() num_players = game.get_num_players() self.assertEqual(num_players, 4)
def test_get_num_actions(self): game = Game() num_actions = game.get_num_actions() self.assertEqual(num_actions, 38)
class MahjongEnv(Env): ''' Mahjong Environment ''' def __init__(self, config): self.game = Game() super().__init__(config) self.action_id = card_encoding_dict self.de_action_id = { self.action_id[key]: key for key in self.action_id.keys() } self.state_shape = [6, 34, 4] def _extract_state(self, state): ''' Encode state Args: state (dict): dict of original state Returns: numpy array: 6*5*15 array 6 : current hand the union of the other two players' hand the recent three actions the union of all played cards ''' players_pile = state['players_pile'] hand_rep = encode_cards(state['current_hand']) piles_rep = [] for p in players_pile.keys(): piles_rep.append(encode_cards(pile2list(players_pile[p]))) piles_rep = np.array(piles_rep) table_rep = encode_cards(state['table']) rep = [hand_rep, table_rep] rep.extend(piles_rep) obs = np.array(rep) extracted_state = { 'obs': obs, 'legal_actions': self._get_legal_actions() } if self.allow_raw_data: extracted_state['raw_obs'] = state extracted_state['raw_legal_actions'] = [ a for a in state['action_cards'] ] if self.record_action: extracted_state['action_record'] = self.action_recorder return extracted_state # def get_payoffs(self): # ''' Get the payoffs of players. Must be implemented in the child class. # # Returns: # payoffs (list): a list of payoffs for each player # ''' # _, player, _ = self.game.judger.judge_game(self.game) # if player == -1: # payoffs = [0, 0, 0, 0] # else: # payoffs = [-1, -1, -1, -1] # payoffs[player] = 1 # return payoffs def get_payoffs(self): ''' Get the payoffs of players. Must be implemented in the child class. Returns: payoffs (list): a list of payoffs for each player ''' _, player, _ = self.game.judger.judge_game(self.game) if player == -1: # payoffs = [0, 0, 0, 0] payoffs = np.zeros(self.game.num_players) else: payoffs = -1 * np.ones(self.game.num_players) payoffs[player] = 1 return payoffs def _decode_action(self, action_id): ''' Action id -> the action in the game. Must be implemented in the child class. Args: action_id (int): the id of the action Returns: action (string): the action that will be passed to the game engine. ''' action = self.de_action_id[action_id] if action_id < 16: candidates = self.game.get_legal_actions( self.game.get_state(self.game.round.current_player)) for card in candidates: if card.get_str() == action: action = card break return action def _get_legal_actions(self): ''' Get all legal actions for current state Returns: if type(legal_actions[0]) == Card: print("GET:", [c.get_str() for c in legal_actions]) else: print(legal_actions) legal_actions (list): a list of legal actions' id ''' legal_action_id = [] legal_actions = self.game.get_legal_actions( self.game.get_state(self.game.round.current_player)) if legal_actions: for action in legal_actions: if isinstance(action, Card): action = action.get_str() action_id = self.action_id[action] legal_action_id.append(action_id) else: print("##########################") print("No Legal Actions") print(self.game.judger.judge_game(self.game)) print(self.game.is_over()) print([len(p.pile) for p in self.game.players]) #print(self.game.get_state(self.game.round.current_player)) #exit() return legal_action_id