def test_imgage_processor():
    '''Test image processor (multiple tests)'''

    expected_board = BlindBoard.get_starting_board()
    expected_board.remove_piece_at(chess.E2)
    expected_board.set_piece_at(chess.E4, Piece(PAWN, WHITE))

    # retrieve all the images paths and sort
    images = collect_test_images('tests/pictures/game000')
    debug("Calibrating image processor...")
    processor = ImageProcessor(images[0], images[1])

    for img, expected_board in zip(images[2:], expected_boards()):
        debug("Processing `{}`...".format(os.path.basename(img)))
        processor.process(img)
        board = processor.get_blindboard()
        yield compare_blindboards, expected_board, board, img
def test_imgage_processor():
    '''Test image processor (multiple tests)'''

    expected_board = BlindBoard.get_starting_board()
    expected_board.remove_piece_at(chess.E2)
    expected_board.set_piece_at(chess.E4, Piece(PAWN, WHITE))

    # retrieve all the images paths and sort
    images = collect_test_images('tests/pictures/game000')
    debug("Calibrating image processor...")
    processor = ImageProcessor(images[0], images[1])

    for img, expected_board in zip(images[2:], expected_boards()):
        debug("Processing `{}`...".format(os.path.basename(img)))
        processor.process(img)
        board = processor.get_blindboard()
        yield compare_blindboards, expected_board, board, img
Example #3
0
class Core(cmd.Cmd):
    '''TO-F*****G-DO'''

    prompt = ' (chessreader-PLAYING) '

    def __init__(self, capture_engine=None, do_live_analysis=True):
        # parent ctor
        super(Core, self).__init__()
        # core tools
        self.capture_engine        = capture_engine or capture.Fswebcam()
        self.image_processor       = None # will be init. in preloop()
        self.chess_engine          = None  # TODO
        # game status
        self.last_valid_blindboard = BlindBoard.get_starting_board()
        self.current_board         = chess.Board()
        # core options
        self.game_folder           = utils.create_new_game_folder()
        self.do_keep_trace_files   = True # TODO
        self.do_live_analysis      = do_live_analysis
        self.do_show_each_move     = True # TODO

    # cmd-related stuff ########################################################
    #
    def emptyline(self):
        self.do_next(None)

    def preloop(self):
        '''TODO'''
        # whether live analysis is on or off, perform calibration now
        self._calibration()
        print("The game is on!")

    def do_next(self, _):
        '''TODO'''
        # make sure the game is still on
        if self.current_board.is_game_over():
            print('Game is over! Type "help" to see authorized commands')

        # img capture!
        img_path = self._get_img_name()
        self.capture_engine.capture(img_path)
        assert os.path.exists(img_path)

        if self.do_live_analysis:
            try:
                self._process_next_move(img_path)
            except IllegalMove as e:
                log.warn(str(e))
                log.info('no move registered; type "next" again to retry')
        else:
            self.current_board.push(chess.Move.null())

    def do_show(self, _):
        '''Show the current status of the board in a human-readable fashion'''
        print_str = "\nNext move: {0}\n".format(self._get_turn_str())
        utils.log.info(print_str + str(self.current_board) + '\n')

    def do_analyze(self, _):
        '''End the current game and run analysis on captured images'''
        if self.do_live_analysis:
            log.warn('live analysis is on: nothing to do')
            return
        # consider the game is over, and analyze all the pictures available
        # TODO

    def do_takeback(self, _):
        '''TODO'''
        pass

    def do_quit(self, _):
        '''End the current game and leave'''
        if utils.confirm_yes_no('Are you sure you want to end this game?'):
            log.info('leaving current game')
            return True

    ############################################################################

    def _calibration(self):
        # TODO: this is messy - we need to handle calibration failure!
        empty_img = os.path.join(self.game_folder, 'empty.jpg')
        start_img = self._get_img_name()

        print("Prepare the empty chessboard and press Enter")
        input()
        self.capture_engine.capture(empty_img)
        print("Prepare the chessboard in starting position "
                 "and press Enter")
        input()
        self.capture_engine.capture(start_img)

        if self.do_live_analysis:
            log.info("Calibrating image processor...")
            self.image_processor = ImageProcessor(empty_img, start_img,
                    trace=True)
            log.info("Calibration completed")
        else:
            log.info('Delaying image processor calibration')


    def _get_img_name(self):
        '''TODO'''
        fullmove_number = self.current_board.fullmove_number
        turn_number     = '0' if self.current_board.turn else '1'

        filename = "board-{:03}-{}.jpg".format(fullmove_number, turn_number)
        return os.path.join(self.game_folder, filename)

    def _process_next_move(self, image_path):
        '''TODO'''
        log.debug('running img processing on "{}"...'.format(image_path))
        self.image_processor.process(image_path)
        new_blindboard = self.image_processor.get_blindboard()
        diff = new_blindboard.diff(self.last_valid_blindboard)
        move = core.diffreader.read(diff)
        log.info("see {} playing: {}".format(self._get_turn_str(), move))

        if not self.current_board.is_legal(move):
            log.warn("Illegal move: {}".format(move))
            raise IllegalMove(move)

        # the move is legit: change state of board and blindboard
        self.current_board.push(move)
        self.last_valid_blindboard = new_blindboard
        self._print_game_status()

        if self.do_show_each_move:
            self.do_show(None)

        return move

    def _print_game_status(self):
        assert self.do_live_analysis

        turn = self._get_turn_str()
        if self.current_board.is_check():
            log.info("{} is in check!".format(turn))
        elif self.current_board.is_checkmate():
            log.info("{} is checkmated. Game over!".format(turn))
        elif self.current_board.is_stalemate():
            log.info("{} to move is in stalemate. Game over!".format(turn))

    def _get_turn_str(self):
        return "White" if self.current_board.turn else "Black"
Example #4
0
class Core(cmd.Cmd):
    '''TO-F*****G-DO'''

    prompt = ' (chessreader-PLAYING) '

    def __init__(self, capture_engine=None, do_live_analysis=True):
        # parent ctor
        super(Core, self).__init__()
        # core tools
        self.capture_engine = capture_engine or capture.Fswebcam()
        self.image_processor = None  # will be init. in preloop()
        self.chess_engine = None  # TODO
        # game status
        self.last_valid_blindboard = BlindBoard.get_starting_board()
        self.current_board = chess.Board()
        # core options
        self.game_folder = utils.create_new_game_folder()
        self.do_keep_trace_files = True  # TODO
        self.do_live_analysis = do_live_analysis
        self.do_show_each_move = True  # TODO

    # cmd-related stuff ########################################################
    #
    def emptyline(self):
        self.do_next(None)

    def preloop(self):
        '''TODO'''
        # whether live analysis is on or off, perform calibration now
        self._calibration()
        print("The game is on!")

    def do_next(self, _):
        '''TODO'''
        # make sure the game is still on
        if self.current_board.is_game_over():
            print('Game is over! Type "help" to see authorized commands')

        # img capture!
        img_path = self._get_img_name()
        self.capture_engine.capture(img_path)
        assert os.path.exists(img_path)

        if self.do_live_analysis:
            try:
                self._process_next_move(img_path)
            except IllegalMove as e:
                log.warn(str(e))
                log.info('no move registered; type "next" again to retry')
        else:
            self.current_board.push(chess.Move.null())

    def do_show(self, _):
        '''Show the current status of the board in a human-readable fashion'''
        print_str = "\nNext move: {0}\n".format(self._get_turn_str())
        utils.log.info(print_str + str(self.current_board) + '\n')

    def do_analyze(self, _):
        '''End the current game and run analysis on captured images'''
        if self.do_live_analysis:
            log.warn('live analysis is on: nothing to do')
            return
        # consider the game is over, and analyze all the pictures available
        # TODO

    def do_takeback(self, _):
        '''TODO'''
        pass

    def do_quit(self, _):
        '''End the current game and leave'''
        if utils.confirm_yes_no('Are you sure you want to end this game?'):
            log.info('leaving current game')
            return True

    ############################################################################

    def _calibration(self):
        # TODO: this is messy - we need to handle calibration failure!
        empty_img = os.path.join(self.game_folder, 'empty.jpg')
        start_img = self._get_img_name()

        print("Prepare the empty chessboard and press Enter")
        input()
        self.capture_engine.capture(empty_img)
        print("Prepare the chessboard in starting position " "and press Enter")
        input()
        self.capture_engine.capture(start_img)

        if self.do_live_analysis:
            log.info("Calibrating image processor...")
            self.image_processor = ImageProcessor(empty_img,
                                                  start_img,
                                                  trace=True)
            log.info("Calibration completed")
        else:
            log.info('Delaying image processor calibration')

    def _get_img_name(self):
        '''TODO'''
        fullmove_number = self.current_board.fullmove_number
        turn_number = '0' if self.current_board.turn else '1'

        filename = "board-{:03}-{}.jpg".format(fullmove_number, turn_number)
        return os.path.join(self.game_folder, filename)

    def _process_next_move(self, image_path):
        '''TODO'''
        log.debug('running img processing on "{}"...'.format(image_path))
        self.image_processor.process(image_path)
        new_blindboard = self.image_processor.get_blindboard()
        diff = new_blindboard.diff(self.last_valid_blindboard)
        move = core.diffreader.read(diff)
        log.info("see {} playing: {}".format(self._get_turn_str(), move))

        if not self.current_board.is_legal(move):
            log.warn("Illegal move: {}".format(move))
            raise IllegalMove(move)

        # the move is legit: change state of board and blindboard
        self.current_board.push(move)
        self.last_valid_blindboard = new_blindboard
        self._print_game_status()

        if self.do_show_each_move:
            self.do_show(None)

        return move

    def _print_game_status(self):
        assert self.do_live_analysis

        turn = self._get_turn_str()
        if self.current_board.is_check():
            log.info("{} is in check!".format(turn))
        elif self.current_board.is_checkmate():
            log.info("{} is checkmated. Game over!".format(turn))
        elif self.current_board.is_stalemate():
            log.info("{} to move is in stalemate. Game over!".format(turn))

    def _get_turn_str(self):
        return "White" if self.current_board.turn else "Black"