Exemplo n.º 1
0
    def init_game(self):
        ''' Initialize players and state.

        Returns:
            dict: first state in one game
            int: current player's id
        '''
        # initialize public variables
        self.winner_id = None
        self.history = []

        # initialize players
        self.players = [Player(num) for num in range(self.num_players)]

        # initialize round to deal cards and determine landlord
        self.round = Round()
        self.round.initiate(self.players)

        # initialize judger
        self.judger = Judger(self.players)

        # get state of first player
        player_id = self.round.current_player
        player = self.players[player_id]
        others_hands = self._get_others_current_hand(player)
        actions = list(self.judger.playable_cards[player_id])
        state = player.get_state(self.round.public, others_hands, actions)
        state['all_actions'] = state['actions']

        self.state = state

        return state, player_id
Exemplo n.º 2
0
Arquivo: game.py Projeto: yli96/rlcard
    def init_game(self):
        ''' Initialize players and state.

        Returns:
            dict: first state in one game
            int: current player's id
        '''

        # initialize public variables
        self.current_game += 1
        self.game_result = {0: 0, 1: 0, 2: 0}
        self.histories = []
        self.trace = []
        self.played_cards = []
        self.state = {'deck': None, 'seen_cards': None, 'landlord': None,
                      'self': None, 'initial_hand': None, 'trace': self.trace,
                      'played_cards': None, 'others_hand': None,
                      'current_hand': None, 'actions': []}

        # initialize players
        self.players = [Player(num)
                        for num in range(DoudizhuGame.players_num)]

        # initialize round to deal cards and determine landlord
        self.rounder = Round()
        self.rounder.initiate(self.players)
        self.current_player = self.rounder.landlord_num

        # initialize Judger
        self.judger = Judger(self.players)

        # initialize state of landlord to be ready for proceeding round
        player = self.players[self.current_player]
        self.rounder.round_last = get_upstream_player_id(player, self.players)
        deck = init_54_deck()
        deck.sort(key=functools.cmp_to_key(doudizhu_sort_card))
        self.state['deck'] = cards2str(deck)
        self.state['landlord'] = self.rounder.landlord_num
        self.state['self'] = self.current_player
        self.state['hand'] = cards2str(player.hand)
        self.state['seen_cards'] = self.rounder.seen_cards
        self.state['current_hand'] = cards2str(player.current_hand)
        self.state['others_hand'] = self._get_others_current_hand(player)
        self.state['actions'] = list(
            self.judger.playable_cards[self.current_player])
        return copy.deepcopy(self.state), self.current_player
Exemplo n.º 3
0
class DoudizhuGame(object):
    ''' Provide game APIs for env to run doudizhu and get corresponding state
    information.

    An example of state during runtime:
            {
             'deck': '3333444455556666777788889999TTTTJJJJQQQQKKKKAAAA2222BR',
             'seen_cards': 'TQA',
             'landlord': 0,
             'self': 2,
             'initial_hand': '3456677799TJQKAAB',
             'trace': [(0, '8222'), (1, 'pass'), (2, 'pass'), (0, '6KKK'),
                       (1, 'pass'), (2, 'pass'), (0, '8'), (1, 'Q')],
             'played_cards': ['6', '8', '8', 'Q', 'K', 'K', 'K', '2', '2', '2'],
             'others_hand': '333444555678899TTTJJJQQAA2R',
             'current_hand': '3456677799TJQKAAB',
             'actions': ['pass', 'K', 'A', 'B']
            }
    '''
    def __init__(self, allow_step_back=False):
        self.allow_step_back = allow_step_back
        self.num_players = 3

    def init_game(self):
        ''' Initialize players and state.

        Returns:
            dict: first state in one game
            int: current player's id
        '''
        # initialize public variables
        self.winner_id = None
        self.history = []

        # initialize players
        self.players = [Player(num) for num in range(self.num_players)]

        # initialize round to deal cards and determine landlord
        self.round = Round()
        self.round.initiate(self.players)

        # initialize judger
        self.judger = Judger(self.players)

        # get state of first player
        player_id = self.round.current_player
        player = self.players[player_id]
        others_hands = self._get_others_current_hand(player)
        actions = list(self.judger.playable_cards[player_id])
        state = player.get_state(self.round.public, others_hands, actions)
        state['all_actions'] = state['actions']

        self.state = state

        return state, player_id

    def step(self, action):
        ''' Perform one draw of the game

        Args:
            action (str): specific action of doudizhu. Eg: '33344'

        Returns:
            dict: next player's state
            int: next player's id
        '''
        if self.allow_step_back:
            # TODO: don't record game.round, game.players, game.judger if allow_step_back not set
            pass

        # perfrom action
        player = self.players[self.round.current_player]
        self.round.proceed_round(player, action)
        if (action != 'pass'):
            self.judger.calc_playable_cards(player)
        if self.judger.judge_game(self.players, self.round.current_player):
            self.winner_id = self.round.current_player
        next_id = get_downstream_player_id(player, self.players)
        self.round.current_player = next_id

        # get next state
        state = self.get_state(next_id)
        self.state = state

        #print("doudizhu状态:",state)

        return state, next_id

    def step_back(self):
        ''' Return to the previous state of the game

        Returns:
            (bool): True if the game steps back successfully
        '''
        if not self.round.trace:
            return False

        #winner_id will be always None no matter step_back from any case
        self.winner_id = None

        #reverse round
        player_id, cards = self.round.trace.pop()
        self.round.current_player = player_id
        if (cards != 'pass'):
            for card in cards:
                self.round.played_cards.remove(card)
        greater_player_id = self.round.find_last_greater_player_id_in_trace()
        if (greater_player_id is not None):
            self.round.greater_player = self.players[greater_player_id]
        else:
            self.round.greater_player = None

        #reverse player
        if (cards != 'pass'):
            self.players[
                player_id].played_cards = self.round.find_last_played_cards_in_trace(
                    player_id)
        self.players[player_id].play_back()

        #reverse judger.played_cards if needed
        if (cards != 'pass'):
            self.judger.restore_playable_cards(player_id)

        self.state = self.get_state(self.round.current_player)
        return True

    def get_state(self, player_id):
        ''' Return player's state

        Args:
            player_id (int): player id

        Returns:
            (dict): The state of the player
        '''
        player = self.players[player_id]
        others_hands = self._get_others_current_hand(player)
        if self.is_over():
            actions = None
            all_actions = None
        else:
            actions, all_actions = player.available_actions(
                self.round.greater_player, self.judger)
            actions = list(actions)
            all_actions = list(all_actions)

        state = player.get_state(self.round.public, others_hands, actions)
        state['all_actions'] = all_actions
        return state

    @staticmethod
    def get_action_num():
        ''' Return the total number of abstract acitons

        Returns:
            int: the total number of abstract actions of doudizhu
        '''
        return 309

    def get_player_id(self):
        ''' Return current player's id

        Returns:
            int: current player's id
        '''
        return self.round.current_player

    def get_player_num(self):
        ''' Return the number of players in doudizhu

        Returns:
            int: the number of players in doudizhu
        '''
        return self.num_players

    def is_over(self):
        ''' Judge whether a game is over

        Returns:
            Bool: True(over) / False(not over)
        '''
        if self.winner_id is None:
            return False
        return True

    def _get_others_current_hand(self, player):
        player_up = self.players[get_upstream_player_id(player, self.players)]
        player_down = self.players[get_downstream_player_id(
            player, self.players)]
        others_hand = merge(player_up.current_hand,
                            player_down.current_hand,
                            key=functools.cmp_to_key(doudizhu_sort_card))
        return cards2str(others_hand)
Exemplo n.º 4
0
class DoudizhuGame(object):
    ''' Provide game APIs for env to run doudizhu and get corresponding state
    information.

    An example of state during runtime:
            {
             'deck': '3333444455556666777788889999TTTTJJJJQQQQKKKKAAAA2222BR',
             'seen_cards': 'TQA',
             'landlord': 0,
             'self': 2,
             'initial_hand': '3456677799TJQKAAB',
             'trace': [(0, '8222'), (1, 'pass'), (2, 'pass'), (0, '6KKK'),
                       (1, 'pass'), (2, 'pass'), (0, '8'), (1, 'Q')],
             'played_cards': ['6', '8', '8', 'Q', 'K', 'K', 'K', '2', '2', '2'],
             'others_hand': '333444555678899TTTJJJQQAA2R',
             'current_hand': '3456677799TJQKAAB',
             'actions': ['pass', 'K', 'A', 'B']
            }
    '''

    def __init__(self, allow_step_back=False):
        self.allow_step_back = allow_step_back
        self.num_players = 3

    def init_game(self):
        ''' Initialize players and state.

        Returns:
            dict: first state in one game
            int: current player's id
        '''
        # initialize public variables
        self.winner_id = None
        self.history = []

        # initialize players
        self.players = [Player(num)
                        for num in range(self.num_players)]

        # initialize round to deal cards and determine landlord
        self.round = Round()
        self.round.initiate(self.players)

        # initialize judger
        self.judger = Judger(self.players)

        # get state of first player
        player_id = self.round.current_player
        player = self.players[player_id]
        others_hands = self._get_others_current_hand(player)
        actions = list(self.judger.playable_cards[player_id])
        state = player.get_state(self.round.public, others_hands, actions)
        self.state = state

        return state, player_id

    def step(self, action):
        ''' Perform one draw of the game

        Args:
            action (str): specific action of doudizhu. Eg: '33344'

        Returns:
            dict: next player's state
            int: next player's id
        '''
        if self.allow_step_back:
            # record game history
            self._record_history()

        # perfrom action
        player = self.players[self.round.current_player]
        self.round.proceed_round(player, action)
        if self.judger.judge_game(self.players, self.round.current_player):
            self.winner_id = self.round.current_player
        next_id = get_downstream_player_id(player, self.players)
        self.round.current_player = next_id

        # get next state
        state = self.get_state(next_id)
        self.state = state

        return state, next_id

    def step_back(self):
        ''' Return to the previous state of the game

        Returns:
            (bool): True if the game steps back successfully
        '''
        if not self.history:
            return False
        self.winner_id, self.players, self.round, self.judger = self.history.pop()
        return True

    def get_state(self, player_id):
        ''' Return player's state

        Args:
            player_id (int): player id

        Returns:
            (dict): The state of the player
        '''
        player = self.players[player_id]
        others_hands = self._get_others_current_hand(player)
        if self.is_over():
            actions = None
        else:
            actions = player.available_actions(self.round.greater_player, self.judger)
        state = player.get_state(self.round.public, others_hands, actions)

        return state

    @staticmethod
    def get_action_num():
        ''' Return the total number of abstract acitons

        Returns:
            int: the total number of abstract actions of doudizhu
        '''
        return 309

    def get_player_id(self):
        ''' Return current player's id

        Returns:
            int: current player's id
        '''
        return self.round.current_player

    def get_player_num(self):
        ''' Return the number of players in doudizhu

        Returns:
            int: the number of players in doudizhu
        '''
        return self.num_players

    def is_over(self):
        ''' Judge whether a game is over

        Returns:
            Bool: True(over) / False(not over)
        '''
        if self.winner_id is None:
            return False
        return True

    def _record_history(self):
        ''' Record history
        '''
        winner_id_cp = copy.deepcopy(self.winner_id)
        players_cp = copy.deepcopy(self.players)
        round_cp = copy.deepcopy(self.round)
        judger_cp = copy.deepcopy(self.judger)
        self.history.append((winner_id_cp, players_cp, round_cp, judger_cp))

    def _get_others_current_hand(self, player):
        player_up = self.players[get_upstream_player_id(player, self.players)]
        player_down = self.players[get_downstream_player_id(
            player, self.players)]
        others_hand = (player_up.current_hand + player_down.current_hand)
        others_hand.sort(key=functools.cmp_to_key(doudizhu_sort_card))
        return cards2str(others_hand)
Exemplo n.º 5
0
Arquivo: game.py Projeto: yli96/rlcard
class DoudizhuGame(object):
    ''' Provide game APIs for env to run doudizhu and get corresponding state
    information.

    An example of state during runtime:
            {
             'deck': '3333444455556666777788889999TTTTJJJJQQQQKKKKAAAA2222BR',
             'seen_cards': 'TQA',
             'landlord': 0,
             'self': 2,
             'initial_hand': '3456677799TJQKAAB',
             'trace': [(0, '8222'), (1, 'pass'), (2, 'pass'), (0, '6KKK'),
                       (1, 'pass'), (2, 'pass'), (0, '8'), (1, 'Q')],
             'played_cards': ['6', '8', '8', 'Q', 'K', 'K', 'K', '2', '2', '2'],
             'others_hand': '333444555678899TTTJJJQQAA2R',
             'current_hand': '3456677799TJQKAAB',
             'actions': ['pass', 'K', 'A', 'B']
            }
    '''

    players_num = 3

    def __init__(self):
        self.current_game = -1
        self.seeds = None
        self.histories = []

    def init_game(self):
        ''' Initialize players and state.

        Returns:
            dict: first state in one game
            int: current player's id
        '''

        # initialize public variables
        self.current_game += 1
        self.game_result = {0: 0, 1: 0, 2: 0}
        self.histories = []
        self.trace = []
        self.played_cards = []
        self.state = {'deck': None, 'seen_cards': None, 'landlord': None,
                      'self': None, 'initial_hand': None, 'trace': self.trace,
                      'played_cards': None, 'others_hand': None,
                      'current_hand': None, 'actions': []}

        # initialize players
        self.players = [Player(num)
                        for num in range(DoudizhuGame.players_num)]

        # initialize round to deal cards and determine landlord
        self.rounder = Round()
        self.rounder.initiate(self.players)
        self.current_player = self.rounder.landlord_num

        # initialize Judger
        self.judger = Judger(self.players)

        # initialize state of landlord to be ready for proceeding round
        player = self.players[self.current_player]
        self.rounder.round_last = get_upstream_player_id(player, self.players)
        deck = init_54_deck()
        deck.sort(key=functools.cmp_to_key(doudizhu_sort_card))
        self.state['deck'] = cards2str(deck)
        self.state['landlord'] = self.rounder.landlord_num
        self.state['self'] = self.current_player
        self.state['hand'] = cards2str(player.hand)
        self.state['seen_cards'] = self.rounder.seen_cards
        self.state['current_hand'] = cards2str(player.current_hand)
        self.state['others_hand'] = self._get_others_current_hand(player)
        self.state['actions'] = list(
            self.judger.playable_cards[self.current_player])
        return copy.deepcopy(self.state), self.current_player

    def step(self, action):
        ''' Perform one draw of the game

        Args:
            action (str): specific action of doudizhu. Eg: '33344'

        Returns:
            dict: next player's state
            int: next player's id
        '''

        # record game history
        player = self.players[self.current_player]
        self._record_history()
        self.trace.append((self.current_player, action))

        # update cards played
        if action != 'pass':
            self._add_played_cards(action)
            self.state['played_cards'] = self.played_cards
        # perform action
        greater_player = self.rounder.proceed_round(player, action)
        next_player_id = get_downstream_player_id(player, self.players)

        # update next_state
        self.state['self'] = next_player_id
        next_player = self.players[next_player_id]
        self.state['hand'] = cards2str(next_player.hand)
        self.state['current_hand'] = cards2str(next_player.current_hand)
        actions = next_player.available_actions(greater_player, self.judger)
        self.state['actions'] = actions
        self.state['others_hand'] = self._get_others_current_hand(next_player)
        self.current_player = next_player_id
        return copy.deepcopy(self.state), next_player_id

    def step_back(self):
        ''' Return to the previous state of the game.
        '''

        if not self.histories:
            return False
        records = self.histories.pop()
        action = self.trace.pop()
        self.current_player = action[0]
        self.rounder.round_last = records['round_last']
        self.played_cards = records['played_cards']
        self.players[self.current_player] = records['player']
        if records['greater_id'] is None:
            self.rounder.greater_player = None
        else:
            self.rounder.greater_player = self.players[records['greater_id']]
        self.judger.playable_cards[self.current_player] = records['plable_cards']
        return True

    def get_state(self, player_id):
        ''' Return player's state

        Args:
            player_id (int): the player_id of a player

        Returns:
            dict: corresponding player's state
        '''

        player = self.players[player_id]
        if self.current_player is not None:  # when get first state
            return copy.deepcopy(self.state)
        else:  # when get final states of all players
            self.state['self'] = player_id
            self.state['hand'] = cards2str(player.hand)
            self.state['current_hand'] = cards2str(player.current_hand)
            self.state['actions'] = None
            self.state['others_hand'] = self._get_others_current_hand(player)
            return copy.deepcopy(self.state)

    @staticmethod
    def get_action_num():
        ''' Return the total number of abstract acitons

        Returns:
            int: the total number of abstract actions of doudizhu
        '''

        return 309

    def get_player_id(self):
        ''' Return current player's id

        Returns:
            int: current player's id
        '''

        return self.current_player

    @staticmethod
    def get_player_num():
        ''' Return the number of players in doudizhu

        Returns:
            int: the number of players in doudizhu
        '''

        return DoudizhuGame.players_num

    def is_winner(self, player_id):
        ''' Judge whether a player is winner in one game

        Args:
            player_id (int): the player_id of a player

        Returns:
            int: 1(winner) / 0(not winner)

        Note:
            1. This function only can be called after game over
        '''

        return self.game_result[player_id]

    def is_over(self):
        ''' Judge whether a game is over

        Returns:
            Bool: True(over) / False(not over)
        '''

        if self.current_player is None:
            return True
        last_player = get_upstream_player_id(
            self.players[self.current_player], self.players)
        if len(self.players[last_player].current_hand) == 0:
            if self.players[last_player].role == 'peasant':
                for _, player in enumerate(self.players):
                    if player.role == 'peasant':
                        self.game_result[_] = 1
            else:
                self.game_result[last_player] = 1
            self.current_player = None
            return True
        return False

    def _record_history(self):
        ''' Record game histories
        '''

        player = self.players[self.current_player]
        records = {'round_last': self.rounder.round_last,
                   'played_cards': self.played_cards.copy(),
                   'plable_cards': self.judger.playable_cards[self.current_player].copy(),
                   'player': copy.deepcopy(player)}
        if self.rounder.greater_player is None:
            records['greater_id'] = None
        else:
            records['greater_id'] = self.rounder.greater_player.player_id
        self.histories.append(records)

    def _get_others_current_hand(self, player):
        player_up = self.players[get_upstream_player_id(player, self.players)]
        player_down = self.players[get_downstream_player_id(
            player, self.players)]
        others_hand = (player_up.current_hand +
                        player_down.current_hand)
        others_hand.sort(key=functools.cmp_to_key(doudizhu_sort_card))
        return cards2str(others_hand)

    def _add_played_cards(self, action):
        self.played_cards.extend(list(action))
        self.played_cards.sort(key=functools.cmp_to_key(doudizhu_sort_str))