Example #1
0
 def test_window_init_screen(self):
     root = tk.Tk()
     b = ['Easy1', 'Normal1', 'Hard1']
     w = ['Easy2', 'Normal2', 'Hard2']
     window = Window(root=root, black_players=b, white_players=w)
     window.init_screen()
     # board
     self.assertEqual(window.board.size, reversi.window.DEFAULT_BOARD_SIZE)
     self.assertEqual(window.board.cputime, reversi.window.CPU_TIME)
     self.assertEqual(window.board.assist, reversi.window.ASSIST_MENU[1])
     self.assertEqual(window.board._squares,
                      [[None for _ in range(window.board.size)]
                       for _ in range(window.board.size)])
     self.assertEqual(window.board._xlines,
                      [6, 10, 14, 18, 22, 26, 30, 38, 40])
     self.assertEqual(window.board._ylines,
                      [4, 8, 12, 16, 20, 24, 28, 36, 39])
     self.assertEqual(window.board.move, None)
     self.assertEqual(window.board.event.is_set(), False)
     # info
     self.assertEqual(window.info.player, {'black': b[0], 'white': w[0]})
     self.assertEqual(window.info.language, reversi.window.LANGUAGE_MENU[0])
     # start
     self.assertEqual(window.start.language,
                      reversi.window.LANGUAGE_MENU[0])
     self.assertEqual(window.start.event.is_set(), False)
Example #2
0
    def test_window_set_state(self):
        window = Window(root=tk.Tk(), black_players=['b'], white_players=['w'])
        window.init_screen()

        class TestState:
            def __init__(self):
                self.state = None

            def set_state(self, state):
                self.state = state

        window.start = TestState()
        window.menu = TestState()

        window.set_state('Normal')
        self.assertEqual(window.start.state, 'Normal')
        self.assertEqual(window.menu.state, 'Normal')

        window.set_state('Disable')
        self.assertEqual(window.start.state, 'Disable')
        self.assertEqual(window.menu.state, 'Disable')
Example #3
0
class Reversi:
    """
    リバーシゲーム
    """
    INIT, DEMO, PLAY, END, REINIT = 'INIT', 'DEMO', 'PLAY', 'END', 'REINIT'

    def __init__(self, players_info={}, turn_disc_wait=0.1, sleep_time_play=1.5, sleep_time_end=0.01, sleep_time_turn=0.3, sleep_time_move=0.3):
        root = tk.Tk()
        root.withdraw()  # 表示が整うまで隠す

        self.state = Reversi.INIT

        b = ['User1'] + list(players_info.keys())
        w = ['User2'] + list(players_info.keys())
        self.window = Window(root=root, black_players=b, white_players=w)

        players_info['User1'] = strategies.WindowUserInput(self.window)
        players_info['User2'] = strategies.WindowUserInput(self.window)
        self.players_info = players_info

        self.err_msg = ErrorMessage()

        # wait or sleep time (sec)
        self.turn_disc_wait = turn_disc_wait
        self.sleep_time_play = sleep_time_play
        self.sleep_time_end = sleep_time_end
        self.sleep_time_turn = sleep_time_turn
        self.sleep_time_move = sleep_time_move

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self, state):
        self._state = state

        if state == Reversi.INIT:
            self.game = self.__init
        elif state == Reversi.DEMO:
            self.game = self.__demo
        elif state == Reversi.PLAY:
            self.game = self.__play
        elif state == Reversi.END:
            self.game = self.__end
        else:
            self.game = self.__reinit

    def gameloop(self):
        """
        ゲーム処理
        """
        while True:
            if self.game():
                break

    def start(self):
        """
        アプリ開始
        """
        self.game_start()    # ゲーム開始
        self.window_start()  # ウィンドウ開始

    def game_start(self):
        """
        ゲーム開始
        """
        game_thread = threading.Thread(target=self.gameloop)
        game_thread.daemon = True
        self._thread_start(game_thread)

    def _thread_start(self, thread):
        """
        スレッド開始
        """
        thread.start()

    def window_start(self):
        """
        ウィンドウ開始
        """
        self.window.root.deiconify()  # 表示する
        self.window.root.mainloop()

    def __init(self):
        """
        画面初期化(初回、設定変更時)
        """
        self.window.init_screen()
        self.window.set_state('normal')

        # メニューで登録ファイルが読み込まれた場合
        if self.window.extra_file:
            extra_file = self.window.extra_file
            self.window.extra_file = ""
            self._load_extra_file(extra_file)

        self.state = Reversi.DEMO

    def _load_extra_file(self, extra_file):
        """
        登録ファイルを読み込む
        """
        if os.path.isfile(extra_file):
            with open(extra_file, 'r') as f:
                name, cmd, timeouttime = None, None, None
                try:
                    # 設定の読み出し
                    json_dict = json.load(f)
                    name = json_dict['name']
                    cmd = json_dict['cmd']
                    timeouttime = json_dict['timeouttime']

                except Exception:
                    self.err_msg.show('フォーマットエラーのため登録ファイルが読み込めませんでした')

                else:
                    # メニューにAIの名前を追加
                    for color in ('black', 'white'):
                        if name not in self.window.menu.menu_items[color]:
                            self.window.menu.menu_items[color].append(name)
                            self.window.menu.menus[color].add_command(label=str(name), command=self.window.menu._command(color, name))

                    # 戦略を追加
                    self.players_info[name] = strategies.External(cmd, timeouttime)

        else:
            self.err_msg.show('指定された登録ファイルが見つかりませんでした')

    def __demo(self):
        """
        デモ画面
        """
        while True:
            if self.window.start.event.is_set():
                self.window.start.event.clear()
                self.state = Reversi.PLAY
                break

            if not self._demo_animation():
                self.state = Reversi.INIT
                break

    def _demo_animation(self):
        """
        デモアニメーション継続中
        """
        center = self.window.board.size // 2

        target = [
            ('black', center, center-1),
            ('black', center-1, center),
            ('white', center-1, center-1),
            ('white', center, center),
        ]

        ptn = {
            'black': [
                ('black', 'turnblack'),
                ('turnblack', 'white'),
                ('white', 'turnwhite'),
                ('turnwhite', 'black'),
            ],
            'white': [
                ('white', 'turnwhite'),
                ('turnwhite', 'black'),
                ('black', 'turnblack'),
                ('turnblack', 'white'),
            ],
        }

        for color, x, y in target:
            for remove_color, put_color in ptn[color]:
                # メニュー設定変更時
                if self._setting_changed():
                    return False

                # アニメーション処理
                time.sleep(self.turn_disc_wait)
                self.window.board.remove_disc(remove_color, x, y)
                self.window.board.put_disc(put_color, x, y)

        return True

    def __play(self):
        """
        ゲーム画面
        """
        self.window.set_state('disable')

        board = BitBoard(self.window.board.size)
        players = {}

        for color in ('black', 'white'):
            name = self.window.player[color]
            players[color] = Player(color, name, self.players_info[name])

        # ウィンドウの設定をゲームに反映
        strategies.common.Timer.time_limit = self.window.cputime

        Game(
            players['black'],
            players['white'],
            board,
            WindowDisplay(self.window, sleep_time_turn=self.sleep_time_turn, sleep_time_move=self.sleep_time_move),
            cancel=self.window.menu,
        ).play()

        time.sleep(self.sleep_time_play)  # 少し待って終了状態へ
        self.state = Reversi.END

    def __end(self):
        """
        終了画面
        """
        self.window.set_state('normal')

        while True:
            time.sleep(self.sleep_time_end)

            if self.window.start.event.is_set():
                self.window.start.event.clear()
                self.state = Reversi.REINIT
                break

            if self._setting_changed():
                self.state = Reversi.INIT
                break

    def __reinit(self):
        """
        再初期化(ゲーム終了後再スタート時)
        """
        self.window.init_screen()
        self.state = Reversi.PLAY

    def _setting_changed(self):
        """
        ウィンドウの設定が変更されたとき
        """
        if self.window.menu.event.is_set():
            self.window.size = self.window.menu.size
            self.window.player['black'] = self.window.menu.black_player
            self.window.player['white'] = self.window.menu.white_player
            self.window.assist = self.window.menu.assist
            self.window.language = self.window.menu.language
            self.window.menu.event.clear()

            return True

        return False