Пример #1
0
 def _reset(self):
     self.board = Board(self.board_shape, max_per_cell=1)
     self.phase = self.game_phases[0]
     self.state = SeegaState(board=self.board,
                             next_player=self.first_player,
                             boring_limit=self.just_stop,
                             game_phase=self.phase)
     self.current_player = self.first_player
Пример #2
0
    def _reset(self):

        self.done = False
        self.rewarding_move = False
        self.board = BoardGUI(self.board_shape)
        self.state = SeegaState(board=self.board.get_board_state(), next_player=self.first_player,
                               boring_limit=self.just_stop)
        self.trace = Trace(self.state, players={-1: self.players[-1].name, 1: self.players[1].name})
        self.current_player = self.first_player
Пример #3
0
 def _reset(self):
     self.done = False
     self.board = Board(self.board_shape)
     self.state = SeegaState(board=self.board,
                             next_player=self.player_color,
                             boring_limit=self.just_stop)
     # self.trace = Trace(
     #     self.state, players={-1: self.players[-1].name, 1: self.players[1].name}
     # )
     self.current_player = self.player_color
     self._fill_board()
Пример #4
0
    def _reset_for_new_game(self):
        self.board.reset_board()
        self.board.score = {-1: 0, 1: 0}
        self.done = False

        self.board.enable_all_squares()
        self.panel.reset_panel_player()
        self.board.current_player = -1
        self.current_player = self.first_player
        self.panel.update_current_player(self.current_player)

        self.state = SeegaState(board=self.board.get_board_state(), next_player=self.first_player,
                               boring_limit=self.just_stop)
        self.board.set_default_colors()

        for key in self.players.keys():
            self.players[key].reset_player_informations()
Пример #5
0
class SeegaGUI(QMainWindow):
    depth_to_cover = 9
    automatic_save_game = False

    def __init__(self,
                 app,
                 shape,
                 players,
                 allowed_time=120.0,
                 sleep_time=.500,
                 first_player=-1,
                 boring_limit=200,
                 parent=None):
        super(SeegaGUI, self).__init__(parent)
        self.app = app

        self.saved = True
        self.board_shape = shape
        self.players = players
        self.allowed_time = allowed_time
        self.sleep_time = sleep_time
        self.first_player = first_player
        self.just_stop = boring_limit

        self.setWindowTitle("[*] MAIC 2018 - Seega Game")
        self.statusBar()
        self.setWindowIcon(QtGui.QIcon("assets/icon.png"))
        layout = QHBoxLayout()
        layout.addStretch()
        self.board_gui = BoardGUI(self.board_shape)
        layout.addWidget(self.board_gui)
        layout.addSpacing(15)
        self.panel = Panel([players[-1].name, players[1].name])
        layout.addWidget(self.panel)
        layout.addStretch()
        content = QWidget()
        content.setLayout(layout)
        self.setCentralWidget(content)
        self.create_menu()

        self._reset()

        # self.trace = Trace(self.board.get_board_array())

        # self.random_player = AI(self.board.currentPlayer, self.board_size)

    def _reset(self):

        self.done = False
        self.rewarding_move = False
        self.board = BoardGUI(self.board_shape)
        self.state = SeegaState(board=self.board.get_board_state(),
                                next_player=self.first_player,
                                boring_limit=self.just_stop)
        self.trace = Trace(self.state,
                           players={
                               -1: self.players[-1].name,
                               1: self.players[1].name
                           })
        self.current_player = self.first_player

    def reset(self):
        self._reset()

    def create_menu(self):
        menu = self.menuBar()
        # Game Menu
        game_menu = menu.addMenu("Game")

        # New Game Submenu
        new_game_action = QAction(
            QtGui.QIcon.fromTheme("document-new",
                                  QtGui.QIcon("../assets/New file.png")),
            'New Game', self)
        new_game_action.setShortcut(QtGui.QKeySequence.New)
        new_game_action.setStatusTip("New game Luncher")

        new_game_action.triggered.connect(self.new_game_trigger)

        game_menu.addAction(new_game_action)

        game_menu.addSeparator()

        # Load Game Submenu
        load_game_action = QAction(
            QtGui.QIcon.fromTheme("document-new",
                                  QtGui.QIcon("../assets/Open file.png")),
            'Load Game', self)
        load_game_action.setShortcut(QtGui.QKeySequence.Open)
        load_game_action.setStatusTip("Load a previous game")
        load_game_action.triggered.connect(self.load_game_trigger)
        game_menu.addAction(load_game_action)

        # Save Game
        save_game_action = QAction(
            QtGui.QIcon.fromTheme("document-new",
                                  QtGui.QIcon("pieces/Save.png")), 'Save Game',
            self)
        save_game_action.setShortcut(QtGui.QKeySequence.Save)
        save_game_action.setStatusTip("Save current game")
        save_game_action.triggered.connect(self.save_game_trigger)
        game_menu.addAction(save_game_action)

        game_menu.addSeparator()

        # Exit and close game
        exit_game_action = QAction(
            QtGui.QIcon.fromTheme("document-new",
                                  QtGui.QIcon("pieces/Close.png")),
            'Exit Game', self)
        exit_game_action.setShortcut(QtGui.QKeySequence.Quit)
        exit_game_action.setMenuRole(QAction.QuitRole)
        exit_game_action.setStatusTip("Exit and close window")
        exit_game_action.triggered.connect(self.exit_game_trigger)
        game_menu.addAction(exit_game_action)

        menu.addSeparator()

        # Help Menu
        help_menu = menu.addMenu("Help")

        # Rules
        game_rules_action = QAction(
            QtGui.QIcon.fromTheme("document-new",
                                  QtGui.QIcon("pieces/Help.png")), 'Rules',
            self)
        game_rules_action.setMenuRole(QAction.AboutRole)
        game_rules_action.triggered.connect(self.game_rules_trigger)
        help_menu.addAction(game_rules_action)

        help_menu.addSeparator()

        # About
        about_action = QAction('About', self)
        about_action.setMenuRole(QAction.AboutRole)
        about_action.triggered.connect(self.about_trigger)
        help_menu.addAction(about_action)

    def new_game_trigger(self):
        new_game = QMessageBox.question(self, 'New Game',
                                        "You're about to start a new Game.",
                                        QMessageBox.Yes | QMessageBox.No,
                                        QMessageBox.Yes)
        if new_game == QMessageBox.Yes:
            self._reset_for_new_game()
            self.app.processEvents()
            self.play_game()
        else:
            pass

    def _reset_for_new_game(self):
        self.board.reset_board()
        self.board.score = {-1: 0, 1: 0}
        self.done = False

        self.board.enable_all_squares()
        self.panel.reset_panel_player()
        self.board.current_player = -1
        self.current_player = self.first_player
        self.panel.update_current_player(self.current_player)

        self.state = SeegaState(board=self.board.get_board_state(),
                                next_player=self.first_player,
                                boring_limit=self.just_stop)
        self.board.set_default_colors()

        for key in self.players.keys():
            self.players[key].reset_player_informations()

    def step(self, action):
        """Plays one step of the game. Takes an action and perform in the environment.

        Args:
            action (Action): An action containing the move from a player.

        Returns:
            bool: Dependent on the validity of the action will return True if the was was performed False if not.
        """
        assert isinstance(
            action, SeegaAction), "action has to be an Action class object"
        result = SeegaRules.act(self.state, action, self.current_player)
        if isinstance(result, bool):
            return False
        else:
            self.state, self.done = result
            self.current_player = self.state.get_next_player()
            return True

    def play_game(self):
        hit = 0

        timer_first_player = Timer("first_player",
                                   total_time=self.allowed_time,
                                   logger=None)
        timer_second_player = Timer("second_player",
                                    total_time=self.allowed_time,
                                    logger=None)
        turn = self.first_player
        while not self.done:
            hit += 1
            time.sleep(self.sleep_time)
            state = deepcopy(self.state)
            remain_time = timer_first_player.remain_time(
            ) if turn == -1 else timer_second_player.remain_time()
            remain_time_copy = deepcopy(remain_time)
            if SeegaRules.is_player_stuck(state, turn):
                state.set_next_player(turn * -1)
                self.state.set_next_player(turn * -1)
                turn = turn * -1
                self.current_player = state.get_next_player()
                self._update_gui()
            if remain_time > 0:
                timer_first_player.start(
                ) if turn == -1 else timer_second_player.start()
                action = self.players[turn].play(state, remain_time_copy)
                elapsed_time = timer_first_player.stop(
                ) if turn == -1 else timer_second_player.stop()
                remain_time = timer_first_player.remain_time(
                ) if turn == -1 else timer_second_player.remain_time()
                if self.step(action):
                    print('Action performed successfully by', turn, ' in',
                          str(elapsed_time), ' rest ', remain_time)
                else:
                    print(
                        "An illegal move were given. Performing a random move")
                    print(f"Lunching a random move for {turn}")
                    action = SeegaRules.random_play(
                        state, turn)  # TODO: Should we use the original state?

            else:
                print("Not remain time for ", turn,
                      " Performing a random move")
                print(f"Lunching a random move for {turn}")
                action = SeegaRules.random_play(
                    state, turn)  # TODO: Should we use the original state?
            self._update_gui()
            self.trace.add(self.state)
            self.players[turn].update_player_infos(self.get_player_info(turn))
            turn = self.state.get_next_player()
        self._update_gui()
        self._results()
        self.save_game_trigger()
        self.board_gui.set_default_colors()
        print("\nIt's over.")

    def _update_gui(self):
        action = self.state.get_latest_move()
        self.app.processEvents()
        if action['action_type'] == 'ADD':
            # app.processEvents()
            to = action['action']['to']
            self.board_gui.squares[to[0]][to[1]].set_background_color("blue")
            self.board_gui.add_piece(to, self.state.get_latest_player())
            self.app.processEvents()
        elif action['action_type'] == 'MOVE':
            to = action['action']['to']
            at = action['action']['at']
            self.app.processEvents()
            self.board_gui.squares[at[0]][at[1]].set_background_color("blue")
            self.app.processEvents()
            time.sleep(self.sleep_time / 2)
            self.board_gui.set_default_colors()
            self.board_gui.squares[to[0]][to[1]].set_background_color("green")
            self.app.processEvents()
            time.sleep(self.sleep_time / 2)
            self.board_gui.move_piece(at, to, self.state.get_latest_player())
            self.board_gui.set_default_colors()
            time.sleep(self.sleep_time / 2)
            if self.state.captured is not None:
                for p in self.state.captured:
                    i, j = p
                    self.board_gui.squares[i][j].set_background_color("red")
                    self.app.processEvents()
                    self.board_gui.remove_piece(p)
            time.sleep(self.sleep_time / 2)
            self.app.processEvents()
        self.panel.update_score(self.state.score, self.state.in_hand)
        self.board_gui.set_default_colors()
        self.panel.update_current_player(self.state.get_next_player())

    def get_player_info(self, player):
        return self.state.get_player_info(player)

    def is_end_game(self):
        return self.done

    def _results(self):
        if self.done:
            self.trace.done = self.done
            results = SeegaRules.get_results(self.state)
            if not results['tie']:
                end = QMessageBox.information(
                    self, "End",
                    f"{self.players[results['winner']].name} wins.")
            else:
                end = QMessageBox.information(self, "End", "No winners.")

    def load_battle(self, states, delay=0.5, done=True):
        hit = 0
        self.board.set_default_colors()
        self.state = states[0]
        for state in states[1:]:
            action = state.get_latest_move()
            self.state = state
            self._update_gui()
            time.sleep(delay)
        self.done = done
        self._results()
        print("It's over.")

    def load_game_trigger(self):
        self.board.set_default_colors()
        name = QtWidgets.QFileDialog.getOpenFileName(
            self, 'Load Game', options=QFileDialog.DontUseNativeDialog)
        print(name[0])
        trace = self.trace.load(name[0])
        print(trace.players)
        self._reset_for_new_game()
        actions = trace.get_actions()
        delay, ok = QInputDialog.getDouble(self, 'Enter the delay', '')
        players_name = trace.players
        self.panel.update_players_name(players_name)
        self.load_battle(actions, delay, trace.done)

    def save_game_trigger(self):
        if self.done:
            if self.automatic_save_game:
                self.trace.write(self.players[-1].name + "-" +
                                 self.players[1].name)
            else:
                name = QtWidgets.QFileDialog.getSaveFileName(
                    self, 'Save Game', options=QFileDialog.DontUseNativeDialog)
                if name[0] == "":
                    pass
                else:
                    self.trace.write(name[0])
        else:
            warning = QMessageBox.warning(self, "Warning", "No game ongoing")

    def exit_game_trigger(self):
        sys.exit(self.app.exec_())

    def game_rules_trigger(self):
        rules = "Yoté Rules \n " \
                "The game is played on a 5×6 board, which is empty at the beginning of the game. Each player has twelve pieces in hand. Players alternate turns, with White(or green) moving first. In a move, a player may either: \n" \
                "-Place a piece in hand on any empty cell of the board. \n" \
                "-Move one of their pieces already on the board orthogonally to an empty adjacent cell. \n" \
                "-Capture an opponent's piece if it is orthogonally adjacent to a player's piece, by jumping to the empty cell immediately beyond it. The captured piece is removed from the board, and the capturing player removes another of the opponent's pieces of his choosing from the board. \n" \
                "The player who captures all the opponent's pieces is the winner. The game can end in a draw if both players are left with three or fewer pieces. \n" \
                "For more informations : https://en.wikipedia.org/wiki/Yot%C3%A9"
        box = QMessageBox()
        box.about(self, "Rules", rules)

    def about_trigger(self):
        about = "MAIC 2018 Seega Game by MIFY and AAAI Benin"
        box = QMessageBox()
        box.about(self, "About", about)

    def closeEvent(self, a0: QtGui.QCloseEvent):
        if self.exit_game_trigger() == True:
            a0.accept()
        else:
            a0.ignore()
Пример #6
0
class SeegaEnv(Env):
    player_color = Color.black.value  # player using the env
    oponent_color = Color.green.value

    metadata = {"render.modes": ["log"]}

    _color_to_int = np.vectorize(lambda color: color.value)

    def __init__(
        self,
        shape,
        oponent,
        n_turn=300,
        allowed_time=120.0,
        boring_limit=200,
        render_mode="log",
    ):
        super(SeegaEnv, self).__init__()
        assert isinstance(
            oponent, Player), "The oponent needs to be an instance of Player"

        self.nrow, self.ncol = self.board_shape = np.array(shape)
        self.oponent = oponent
        self.turn = 0
        self.n_turn = n_turn
        self.allowed_time = allowed_time
        self.just_stop = boring_limit
        self.done = False

        self.oponent_timer = Timer("oponent_time",
                                   total_time=self.allowed_time,
                                   logger=None)

        self.observation_space = gym.spaces.Box(
            -1, 1, shape=self.board_shape
        )  # -1 = black (player), 0 = empty, 1 = green (oponent)
        # self.action_space = gym.spaces.Dict(
        #     {
        #         str(SeegaActionType.ADD.value): gym.spaces.Box(
        #             0,
        #             np.array([self.ncol, self.nrow]),
        #             shape=np.array([2]),
        #             dtype=np.uint8,
        #         ),
        #         str(SeegaActionType.MOVE.value): gym.spaces.Box(
        #             0,
        #             np.array([self.ncol, self.nrow, 3]),
        #             shape=np.array([3]),
        #             dtype=np.uint8,
        #         ),  # 0 = left, 1 = up, 2 = right, 3 = down
        #     }
        # )
        # self.action_space = gym.spaces.Box(
        #     0, np.array([self.ncol, self.nrow, 3]), shape=np.array([3]), dtype=np.uint8
        # )  # 0 = left, 1 = up, 2 = right, 3 = down
        self.action_space = gym.spaces.Discrete(self.ncol * self.nrow * 4)

        self._reset()

    # def _log_timer(fun):
    #     def inner(self, *args, **kwargs):
    #         self.timer.start()
    #         results = fun(self, *args, **kwargs)
    #         self.timer.stop()
    #         return results

    #     return inner

    def _state_to_ndarray(self, state):
        return self._color_to_int(state.board.get_board_state())

    def _action_from_3D_to_1D(self, x: int, y: int, z: int):
        return (z * self.nrow * self.ncol) + (y * self.nrow) + x

    def _action_from_1D_to_3D(self, index: int):
        z = index // (self.nrow * self.ncol)
        index -= z * self.nrow * self.ncol
        y = index // self.nrow
        x = index % self.nrow
        return x, y, z

    def _reset(self):
        self.done = False
        self.board = Board(self.board_shape)
        self.state = SeegaState(board=self.board,
                                next_player=self.player_color,
                                boring_limit=self.just_stop)
        # self.trace = Trace(
        #     self.state, players={-1: self.players[-1].name, 1: self.players[1].name}
        # )
        self.current_player = self.player_color
        self._fill_board()

    def _fill_board(self):
        turn = self.player_color
        while self.state.phase == 1:
            self.state.set_next_player(turn)
            action = SeegaRules.random_play(self.state, turn)
            result = SeegaRules.act(self.state, action, turn)

            if not isinstance(result, bool):
                self.state, _ = result

            turn *= -1

    def reset(self):
        self._reset()
        state = self._state_to_ndarray(self.state)
        return state

    def step(self, action):
        self.turn += 1
        init_state = deepcopy(self.state)

        reward = 0.0

        # Our turn
        self.state.set_next_player(self.player_color)
        if not isinstance(action, Iterable):
            action = self._action_from_1D_to_3D(action)

        *at, move = action
        dx = Action.get_dx(move)
        at = tuple(at)
        to = tuple(map(operator.add, at, dx))
        action = SeegaAction(SeegaActionType.MOVE, at=at, to=to)

        result = SeegaRules.act(self.state, action, self.player_color)
        # Not legal move
        if isinstance(result, bool):
            reward += Reward.ILLEGAL_MOVE.value
        else:
            self.state, self.done = result

        # Oponent turn
        self.state.set_next_player(self.oponent_color)
        if not SeegaRules.is_player_stuck(self.state, self.oponent_color):
            oponent_remaining_time = self.oponent_timer.remain_time()
            self.oponent_timer.start()
            try:
                oponent_action = self.oponent.play(self.state,
                                                   oponent_remaining_time)
            except Exception as e:
                print(e)
                oponent_action = None
            self.oponent_timer.stop()
            if isinstance(oponent_action, SeegaAction):
                oponent_result = SeegaRules.act(self.state, oponent_action,
                                                self.oponent_color)
                if not isinstance(oponent_result, bool):
                    self.state, self.done = oponent_result

        reward += Reward.PLAYER_PART.value * (
            init_state.score[self.player_color] -
            self.state.score[self.player_color])
        reward += Reward.OPONENT_PART.value * (
            init_state.score[self.oponent_color] -
            self.state.score[self.oponent_color])
        next_state = self._state_to_ndarray(self.state)

        done = self.done and self.turn < self.n_turn
        info = dict(**SeegaRules.get_results(self.state))

        return next_state, reward, self.done, info

    @classmethod
    def as_TF(cls, *args, **kwargs):
        from tf_agents.environments import tf_py_environment
        from tf_agents.environments.gym_wrapper import GymWrapper

        env = SeegaEnv(*args, **kwargs)
        suite_gym = GymWrapper(env)
        return tf_py_environment.TFPyEnvironment(suite_gym)
Пример #7
0
class SeegaEnv(BoardEnv):
    def __init__(self,
                 board_shape,
                 players,
                 allowed_time,
                 first_player=-1,
                 boring_limit=200):  # TODO: Remove player object
        self.players = players
        self.board_shape = board_shape
        self.allowed_time = allowed_time
        self.game_phases = [1, 2]
        self.rewarding_move = False
        self.done = False
        self.first_player = first_player
        self.just_stop = boring_limit
        self._reset()

    def reset(self):
        self._reset()

    def _reset(self):
        self.board = Board(self.board_shape, max_per_cell=1)
        self.phase = self.game_phases[0]
        self.state = SeegaState(board=self.board,
                                next_player=self.first_player,
                                boring_limit=self.just_stop,
                                game_phase=self.phase)
        self.current_player = self.first_player

    def step(self, action):
        """Plays one step of the game. Takes an action and perform in the environment.

        Args:
            action (Action): An action containing the move from a player.

        Returns:
            bool: Dependent on the validity of the action will return True if the was was performed False if not.
        """
        assert isinstance(
            action, SeegaAction), "action has to be an Action class object"
        result = SeegaRules.act(self.state, action, self.current_player)
        if isinstance(result, bool):
            return False
        else:
            self.state, self.done = result
            self.current_player = self.state.get_next_player()
            return True

    def render(self):
        """Gives the current state of the environnement

        Returns:
            (state, done): The state and the game status
        """
        return self.state, self.done

    def get_player_info(self, player):
        return self.state.get_player_info(player)

    def get_state(self):
        return self.state

    def is_end_game(self):
        return self.done