コード例 #1
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
    def on_line_received(self, buf):
        LOGGER.debug("%s >> %s", self.process, buf)

        if buf.startswith("feature"):
            return self._feature(buf[8:])
        elif buf.startswith("Illegal"):
            split_buf = buf.split()
            illegal_move = split_buf[-1]
            exception_msg = "Engine received an illegal move: {}".format(illegal_move)
            if len(split_buf) == 4:
                reason = split_buf[2][1:-2]
                exception_msg = " ".join([exception_msg, reason])
            raise EngineStateException(exception_msg)
        elif buf.startswith("Error"):
            err_msg = buf.split()[1][1:-2]
            raise EngineStateException("Engine produced an error: {}".format(err_msg))

        command_and_args = buf.split()
        if not command_and_args:
            return

        if len(command_and_args) == 1:
            if command_and_args[0] == "#":
                pass
            elif command_and_args[0] == "resign":
                return self._resign()
        elif len(command_and_args) == 2:
            if command_and_args[0] == "pong":
                return self._pong(command_and_args[1])
            elif command_and_args[0] == "move":
                return self._move(command_and_args[1])
            elif command_and_args[0] == "offer" and command_and_args[1] == "draw":
                return self._offer_draw()
        elif len(command_and_args) >= 5:
            return self._post(buf)
コード例 #2
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
        def command():
            # Use the join(builder) once we parse usermove=1 feature.
            move_str = " ".join(builder)
            if self.in_force:
                with self.semaphore:
                    self.send_line(move_str)

                if self.terminated.is_set():
                    raise EngineTerminatedException()
            else:
                with self.semaphore:
                    self.send_line(move_str)
                    self.search_started.set()

                self.move_received.wait()

                with self.state_changed:
                    self.idle = True
                    self.state_changed.notify_all()

                if self.terminated.is_set():
                    raise EngineTerminatedException()

                try:
                    self.board.push_uci(str(self.move))
                except ValueError:
                    try:
                        self.board.push_san(str(self.move))
                    except ValueError:
                        LOGGER.exception("exception parsing move")

                return self.move
コード例 #3
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
    def ucinewgame(self, async_callback=None):
        """
        Tell the engine that the next search will be from a different game.

        This can be a new game the engine should play or if the engine should
        analyse a position from a different game. Using this command is
        recommended, but not required.

        :return: Nothing
        """
        # Warn if this is called while the engine is still calculating.
        with self.state_changed:
            if not self.idle:
                LOGGER.warning("ucinewgame while engine is busy")

        def command():
            with self.semaphore:
                with self.readyok_received:
                    self.send_line("ucinewgame")

                    self.send_line("isready")
                    self.readyok_received.wait()

                    if self.terminated.is_set():
                        raise EngineTerminatedException()

        return self._queue_command(command, async_callback)
コード例 #4
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
    def on_line_received(self, buf):
        LOGGER.debug("%s >> %s", self.process, buf)

        command_and_args = buf.split(None, 1)
        if not command_and_args:
            return

        if len(command_and_args) >= 1:
            if command_and_args[0] == "uciok":
                return self._uciok()
            elif command_and_args[0] == "readyok":
                return self._readyok()

        if len(command_and_args) >= 2:
            if command_and_args[0] == "id":
                return self._id(command_and_args[1])
            elif command_and_args[0] == "bestmove":
                return self._bestmove(command_and_args[1])
            elif command_and_args[0] == "copyprotection":
                return self._copyprotection(command_and_args[1])
            elif command_and_args[0] == "registration":
                return self._registration(command_and_args[1])
            elif command_and_args[0] == "info":
                return self._info(command_and_args[1])
            elif command_and_args[0] == "option":
                return self._option(command_and_args[1])
コード例 #5
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
    def _bestmove(self, arg):
        tokens = arg.split(None, 2)

        self.bestmove = None
        if tokens[0] != "(none)":
            try:
                self.bestmove = self.board.parse_uci(tokens[0])
            except ValueError:
                LOGGER.exception("exception parsing bestmove")

        self.ponder = None
        if self.bestmove is not None and len(tokens) >= 3 and tokens[1] == "ponder" and tokens[2] != "(none)":
            # The ponder move must be legal after the bestmove. Generally, we
            # trust the engine on this. But we still have to convert
            # non-UCI_Chess960 castling moves.
            try:
                self.ponder = chess.Move.from_uci(tokens[2])
                if self.ponder.from_square in [chess.E1, chess.E8] and self.ponder.to_square in [chess.C1, chess.C8, chess.G1, chess.G8]:
                    # Make a copy of the board to avoid race conditions.
                    board = self.board.copy(stack=False)
                    board.push(self.bestmove)
                    self.ponder = board.parse_uci(tokens[2])
            except ValueError:
                LOGGER.exception("exception parsing bestmove ponder")
                self.ponder = None

        self.bestmove_received.set()

        for info_handler in self.info_handlers:
            info_handler.on_bestmove(self.bestmove, self.ponder)
コード例 #6
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
        def command():
            with self.semaphore:
                self.send_line("go")
                self.search_started.set()

            self.move_received.wait()

            with self.state_changed:
                self.idle = True
                self.state_changed.notify_all()

            if self.terminated.is_set():
                raise EngineTerminatedException()

            if self.auto_force:
                self.force()

            if self.move in DUMMY_RESPONSES:
                return self.move

            try:
                self.board.push_uci(str(self.move))
            except ValueError:
                try:
                    self.board.push_san(str(self.move))
                except ValueError:
                    LOGGER.exception("exception parsing move")

            return self.move
コード例 #7
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
        def handle_move_token(token, fn):
            try:
                move = chess.Move.from_uci(token)
            except ValueError:
                LOGGER.exception("exception parsing move token")
                return

            for info_handler in self.info_handlers:
                fn(info_handler, move)
コード例 #8
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
        def handle_integer_token(token, fn):
            try:
                intval = int(token)
            except ValueError:
                LOGGER.exception("exception parsing integer token")
                return

            for info_handler in self.info_handlers:
                fn(info_handler, intval)
コード例 #9
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
    def _pong(self, pong_arg):
        try:
            pong_num = int(pong_arg)
        except ValueError:
            LOGGER.exception("exception parsing pong")

        if self.ping_num == pong_num:
            self.pong.set()
            with self.pong_received:
                self.pong_received.notify_all()
コード例 #10
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
    def set_feature(self, key, value):
        if key == "egt":
            for egt_type in value.split(","):
                self._features["egt"].append(egt_type)
        else:
            try:
                value = int(value)
            except ValueError:
                pass

            try:
                self._features[key] = value
            except KeyError:
                LOGGER.exception("exception looking up feature")
コード例 #11
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
    def _move(self, arg):
        self.move = None
        try:
            self.move = self.board.parse_uci(arg)
        except ValueError:
            try:
                self.move = self.board.parse_san(arg)
            except ValueError:
                LOGGER.exception("exception parsing move")

        self.move_received.set()
        if self.draw_handler:
            self.draw_handler.clear_offer()
            self.engine_offered_draw = False
        for post_handler in self.post_handlers:
            post_handler.on_move(self.move)
コード例 #12
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
    def _post(self, arg):
        if not self.post_handlers:
            return

        # Notify post handlers of start.
        for post_handler in self.post_handlers:
            post_handler.pre_info()

        def handle_integer_token(token, fn):
            try:
                intval = int(token)
            except ValueError:
                LOGGER.exception("exception parsing integer token")
                return

            for post_handler in self.post_handlers:
                fn(post_handler, intval)

        pv = []
        board = self.board.copy(stack=False)
        tokens = arg.split()
        # Order: <score> <depth> <time> <nodes> <pv>.
        handle_integer_token(tokens[0], lambda handler, val: handler.depth(val))
        handle_integer_token(tokens[1], lambda handler, val: handler.score(val))
        handle_integer_token(tokens[2], lambda handler, val: handler.time(val))
        handle_integer_token(tokens[3], lambda handler, val: handler.nodes(val))
        for token in tokens[4:]:
            # Ignore move number. For example, 1. Nf3 Nf6 -> Nf3 Nf6.
            if '.' in token or '<' in token:
                continue
            try:
                pv.append(board.push_uci(token))
            except ValueError:
                try:
                    pv.append(board.push_san(token))
                except ValueError:
                    LOGGER.exception("exception parsing pv")

        if pv is not None:
            for post_handler in self.post_handlers:
                post_handler.pv(pv)

        # Notify post handlers of end.
        for post_handler in self.post_handlers:
            post_handler.post_info()
コード例 #13
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
 def _registration(self, arg):
     LOGGER.error("engine registration not supported")
コード例 #14
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
 def _copyprotection(self, arg):
     LOGGER.error("engine copyprotection not supported")
コード例 #15
0
ファイル: uci.py プロジェクト: mrtseb/lazarus_forge
    def _info(self, arg):
        if not self.info_handlers:
            return

        # Notify info handlers of start.
        for info_handler in self.info_handlers:
            info_handler.pre_info(arg)

        # Initialize parser state.
        board = None
        pv = None
        score_kind = None
        score_cp = None
        score_mate = None
        score_lowerbound = False
        score_upperbound = False
        refutation_move = None
        refuted_by = []
        currline_cpunr = None
        currline_moves = []
        string = []

        def end_of_parameter():
            # Parameters with variable length can only be handled when the
            # next parameter starts or at the end of the line.

            if pv is not None:
                for info_handler in self.info_handlers:
                    info_handler.pv(pv)

            if score_cp is not None or score_mate is not None:
                for info_handler in self.info_handlers:
                    info_handler.score(score_cp, score_mate, score_lowerbound, score_upperbound)

            if refutation_move is not None:
                if refuted_by:
                    for info_handler in self.info_handlers:
                        info_handler.refutation(refutation_move, refuted_by)
                else:
                    for info_handler in self.info_handlers:
                        info_handler.refutation(refutation_move, None)

            if currline_cpunr is not None:
                for info_handler in self.info_handlers:
                    info_handler.currline(currline_cpunr, currline_moves)

        def handle_integer_token(token, fn):
            try:
                intval = int(token)
            except ValueError:
                LOGGER.exception("exception parsing integer token")
                return

            for info_handler in self.info_handlers:
                fn(info_handler, intval)

        def handle_move_token(token, fn):
            try:
                move = chess.Move.from_uci(token)
            except ValueError:
                LOGGER.exception("exception parsing move token")
                return

            for info_handler in self.info_handlers:
                fn(info_handler, move)

        # Find multipv parameter first.
        if "multipv" in arg:
            current_parameter = None
            for token in arg.split(" "):
                if token == "string":
                    break

                if current_parameter == "multipv":
                    handle_integer_token(token, lambda handler, val: handler.multipv(val))

                current_parameter = token

        # Parse all other parameters.
        current_parameter = None
        for token in arg.split(" "):
            if current_parameter == "string":
                string.append(token)
            elif not token:
                # Ignore extra spaces. Those can not be directly discarded,
                # because they may occur in the string parameter.
                pass
            elif token in ["depth", "seldepth", "time", "nodes", "pv", "multipv", "score", "currmove", "currmovenumber", "hashfull", "nps", "tbhits", "cpuload", "refutation", "currline", "string"]:
                end_of_parameter()
                current_parameter = token

                pv = None
                score_kind = None
                score_mate = None
                score_cp = None
                score_lowerbound = False
                score_upperbound = False
                refutation_move = None
                refuted_by = []
                currline_cpunr = None
                currline_moves = []

                if current_parameter == "pv":
                    pv = []

                if current_parameter in ["refutation", "pv", "currline"]:
                    board = self.board.copy(stack=False)
            elif current_parameter == "depth":
                handle_integer_token(token, lambda handler, val: handler.depth(val))
            elif current_parameter == "seldepth":
                handle_integer_token(token, lambda handler, val: handler.seldepth(val))
            elif current_parameter == "time":
                handle_integer_token(token, lambda handler, val: handler.time(val))
            elif current_parameter == "nodes":
                handle_integer_token(token, lambda handler, val: handler.nodes(val))
            elif current_parameter == "pv":
                try:
                    pv.append(board.push_uci(token))
                except ValueError:
                    LOGGER.exception("exception parsing pv")
            elif current_parameter == "multipv":
                # Ignore multipv. It was already parsed before anything else.
                pass
            elif current_parameter == "score":
                if token in ["cp", "mate"]:
                    score_kind = token
                elif token == "lowerbound":
                    score_lowerbound = True
                elif token == "upperbound":
                    score_upperbound = True
                elif score_kind == "cp":
                    try:
                        score_cp = int(token)
                    except ValueError:
                        LOGGER.exception("exception parsing score cp value")
                elif score_kind == "mate":
                    try:
                        score_mate = int(token)
                    except ValueError:
                        LOGGER.exception("exception parsing score mate value")
            elif current_parameter == "currmove":
                handle_move_token(token, lambda handler, val: handler.currmove(val))
            elif current_parameter == "currmovenumber":
                handle_integer_token(token, lambda handler, val: handler.currmovenumber(val))
            elif current_parameter == "hashfull":
                handle_integer_token(token, lambda handler, val: handler.hashfull(val))
            elif current_parameter == "nps":
                handle_integer_token(token, lambda handler, val: handler.nps(val))
            elif current_parameter == "tbhits":
                handle_integer_token(token, lambda handler, val: handler.tbhits(val))
            elif current_parameter == "cpuload":
                handle_integer_token(token, lambda handler, val: handler.cpuload(val))
            elif current_parameter == "refutation":
                try:
                    if refutation_move is None:
                        refutation_move = board.push_uci(token)
                    else:
                        refuted_by.append(board.push_uci(token))
                except ValueError:
                    LOGGER.exception("exception parsing refutation")
            elif current_parameter == "currline":
                try:
                    if currline_cpunr is None:
                        currline_cpunr = int(token)
                    else:
                        currline_moves.append(board.push_uci(token))
                except ValueError:
                    LOGGER.exception("exception parsing currline")

        end_of_parameter()

        if string:
            for info_handler in self.info_handlers:
                info_handler.string(" ".join(string))

        # Notify info handlers of end.
        for info_handler in self.info_handlers:
            info_handler.post_info()
コード例 #16
0
ファイル: uci.py プロジェクト: mrtseb/lazarus_forge
    def _option(self, arg):
        current_parameter = None

        name = []
        type = []
        default = []
        min = None
        max = None
        current_var = None
        var = []

        for token in arg.split(" "):
            if token == "name" and not name:
                current_parameter = "name"
            elif token == "type" and not type:
                current_parameter = "type"
            elif token == "default" and not default:
                current_parameter = "default"
            elif token == "min" and min is None:
                current_parameter = "min"
            elif token == "max" and max is None:
                current_parameter = "max"
            elif token == "var":
                current_parameter = "var"
                if current_var is not None:
                    var.append(" ".join(current_var))
                current_var = []
            elif current_parameter == "name":
                name.append(token)
            elif current_parameter == "type":
                type.append(token)
            elif current_parameter == "default":
                default.append(token)
            elif current_parameter == "var":
                current_var.append(token)
            elif current_parameter == "min":
                try:
                    min = int(token)
                except ValueError:
                    LOGGER.exception("exception parsing option min")
            elif current_parameter == "max":
                try:
                    max = int(token)
                except ValueError:
                    LOGGER.exception("exception parsing option max")

        if current_var is not None:
            var.append(" ".join(current_var))

        type = " ".join(type)

        default = " ".join(default)
        if type == "check":
            if default == "true":
                default = True
            elif default == "false":
                default = False
            else:
                default = None
        elif type == "spin":
            try:
                default = int(default)
            except ValueError:
                LOGGER.exception("exception parsing option spin default")
                default = None

        option = Option(" ".join(name), type, default, min, max, var)
        self.options[option.name] = option
コード例 #17
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
 def send_line(self, line):
     LOGGER.debug("%s << %s", self.process, line)
     return self.process.send_line(line)
コード例 #18
0
    def usermove(self, move, async_callback=None):
        """
        Tells the XBoard engine to make a move on its internal
        board.

        If *auto_force* is set to ``True``, the engine will not start
        thinking about its next move immediately after.

        :param move: The move to play in XBoard notation.

        :return: Nothing.
        """
        builder = []
        if self.features.supports("usermove"):
            builder.append("usermove")

        if self.draw_handler:
            self.draw_handler.clear_offer()
            self.engine_offered_draw = False

        if self.auto_force:
            self.force()
        elif not self.in_force:
            with self.state_changed:
                if not self.idle:
                    raise EngineStateException("usermove command while engine is already busy")

                self.idle = False
                self.search_started.clear()
                self.move_received.clear()
                self.state_changed.notify_all()

            for post_handler in self.post_handlers:
                post_handler.on_go()

        try:
            self.board.push_uci(str(move))
        except ValueError:
            try:
                self.board.push_san(str(move))
            except ValueError:
                LOGGER.exception("exception parsing move")

        builder.append(str(move))

        def command():
            # Use the join(builder) once we parse usermove=1 feature.
            move_str = " ".join(builder)
            if self.in_force:
                with self.semaphore:
                    self.send_line(move_str)

                if self.terminated.is_set():
                    raise EngineTerminatedException()
            else:
                with self.semaphore:
                    self.send_line(move_str)
                    self.search_started.set()

                self.move_received.wait()

                with self.state_changed:
                    self.idle = True
                    self.state_changed.notify_all()

                if self.terminated.is_set():
                    raise EngineTerminatedException()

                try:
                    self.board.push_uci(str(self.move))
                except ValueError:
                    try:
                        self.board.push_san(str(self.move))
                    except ValueError:
                        LOGGER.exception("exception parsing move")

                return self.move

        return self._queue_command(command, async_callback)
コード例 #19
0
ファイル: uci.py プロジェクト: mrtseb/lazarus_forge
    def position(self, board, async_callback=None):
        """
        Set up a given position.

        Instead of just the final FEN, the initial FEN and all moves leading
        up to the position will be sent, so that the engine can detect
        repetitions.

        If the position is from a new game it is recommended to use the
        *ucinewgame* command before the *position* command.

        :param board: A *chess.Board*.

        :return: Nothing

        :raises: :exc:`~chess.uci.EngineStateException` if the engine is still
            calculating.
        """
        # Check UCI_Variant
        uci_variant = type(board).uci_variant
        if uci_variant == "chess" and self.uci_variant is None:
            pass
        elif uci_variant != self.uci_variant:
            LOGGER.error("current UCI_Variant (%s) does not match position (%s)", self.uci_variant, uci_variant)

        # Raise if this is called while the engine is still calculating.
        with self.state_changed:
            if not self.idle:
                raise EngineStateException("position command while engine is busy")

        builder = []
        builder.append("position")

        # Take back moves to obtain the FEN at the latest pawn move or
        # capture. Later giving the moves explicitly allows for transposition
        # detection.
        switchyard = collections.deque()
        while board.move_stack:
            move = board.pop()
            switchyard.append(move)

            if board.is_irreversible(move):
                break

        # Validate castling rights.
        if not self.uci_chess960 and board.chess960:
            if board.has_chess960_castling_rights():
                LOGGER.error("not in UCI_Chess960 mode but position has non-standard castling rights")

                # Just send the final FEN without transpositions in hopes
                # that this will work.
                while switchyard:
                    board.push(switchyard.pop())

        # Send startposition.
        if uci_variant == "chess" and board.fen() == chess.STARTING_FEN:
            builder.append("startpos")
        else:
            builder.append("fen")
            builder.append(board.shredder_fen() if self.uci_chess960 else board.fen())

        # Send moves.
        if switchyard:
            builder.append("moves")

            while switchyard:
                move = switchyard.pop()
                builder.append(board.uci(move, chess960=self.uci_chess960))
                board.push(move)

        self.board = board.copy(stack=False)

        def command():
            with self.semaphore:
                self.send_line(" ".join(builder))

                if self.terminated.is_set():
                    raise EngineTerminatedException()

        return self._queue_command(command, async_callback)
コード例 #20
0
 def get_option(self, key):
     try:
         return self._features["option"][key]
     except KeyError:
         LOGGER.exception("exception looking up option")
コード例 #21
0
ファイル: uci.py プロジェクト: mrtseb/lazarus_forge
 def _registration(self, arg):
     LOGGER.error("engine registration not supported")
コード例 #22
0
 def set_option(self, key, value):
     try:
         self._features["option"][key] = value
     except KeyError:
         LOGGER.exception("exception looking up option")
コード例 #23
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
    def _info(self, arg):
        if not self.info_handlers:
            return

        # Notify info handlers of start.
        for info_handler in self.info_handlers:
            info_handler.pre_info(arg)

        # Initialize parser state.
        board = None
        pv = None
        score_kind = None
        score_cp = None
        score_mate = None
        score_lowerbound = False
        score_upperbound = False
        refutation_move = None
        refuted_by = []
        currline_cpunr = None
        currline_moves = []
        string = []

        def end_of_parameter():
            # Parameters with variable length can only be handled when the
            # next parameter starts or at the end of the line.

            if pv is not None:
                for info_handler in self.info_handlers:
                    info_handler.pv(pv)

            if score_cp is not None or score_mate is not None:
                for info_handler in self.info_handlers:
                    info_handler.score(score_cp, score_mate, score_lowerbound, score_upperbound)

            if refutation_move is not None:
                if refuted_by:
                    for info_handler in self.info_handlers:
                        info_handler.refutation(refutation_move, refuted_by)
                else:
                    for info_handler in self.info_handlers:
                        info_handler.refutation(refutation_move, None)

            if currline_cpunr is not None:
                for info_handler in self.info_handlers:
                    info_handler.currline(currline_cpunr, currline_moves)

        def handle_integer_token(token, fn):
            try:
                intval = int(token)
            except ValueError:
                LOGGER.exception("exception parsing integer token")
                return

            for info_handler in self.info_handlers:
                fn(info_handler, intval)

        def handle_move_token(token, fn):
            try:
                move = chess.Move.from_uci(token)
            except ValueError:
                LOGGER.exception("exception parsing move token")
                return

            for info_handler in self.info_handlers:
                fn(info_handler, move)

        # Find multipv parameter first.
        if "multipv" in arg:
            current_parameter = None
            for token in arg.split(" "):
                if token == "string":
                    break

                if current_parameter == "multipv":
                    handle_integer_token(token, lambda handler, val: handler.multipv(val))

                current_parameter = token

        # Parse all other parameters.
        current_parameter = None
        for token in arg.split(" "):
            if current_parameter == "string":
                string.append(token)
            elif not token:
                # Ignore extra spaces. Those can not be directly discarded,
                # because they may occur in the string parameter.
                pass
            elif token in ["depth", "seldepth", "time", "nodes", "pv", "multipv", "score", "currmove", "currmovenumber", "hashfull", "nps", "tbhits", "cpuload", "refutation", "currline", "string"]:
                end_of_parameter()
                current_parameter = token

                pv = None
                score_kind = None
                score_mate = None
                score_cp = None
                score_lowerbound = False
                score_upperbound = False
                refutation_move = None
                refuted_by = []
                currline_cpunr = None
                currline_moves = []

                if current_parameter == "pv":
                    pv = []

                if current_parameter in ["refutation", "pv", "currline"]:
                    board = self.board.copy(stack=False)
            elif current_parameter == "depth":
                handle_integer_token(token, lambda handler, val: handler.depth(val))
            elif current_parameter == "seldepth":
                handle_integer_token(token, lambda handler, val: handler.seldepth(val))
            elif current_parameter == "time":
                handle_integer_token(token, lambda handler, val: handler.time(val))
            elif current_parameter == "nodes":
                handle_integer_token(token, lambda handler, val: handler.nodes(val))
            elif current_parameter == "pv":
                try:
                    pv.append(board.push_uci(token))
                except ValueError:
                    LOGGER.exception("exception parsing pv")
            elif current_parameter == "multipv":
                # Ignore multipv. It was already parsed before anything else.
                pass
            elif current_parameter == "score":
                if token in ["cp", "mate"]:
                    score_kind = token
                elif token == "lowerbound":
                    score_lowerbound = True
                elif token == "upperbound":
                    score_upperbound = True
                elif score_kind == "cp":
                    try:
                        score_cp = int(token)
                    except ValueError:
                        LOGGER.exception("exception parsing score cp value")
                elif score_kind == "mate":
                    try:
                        score_mate = int(token)
                    except ValueError:
                        LOGGER.exception("exception parsing score mate value")
            elif current_parameter == "currmove":
                handle_move_token(token, lambda handler, val: handler.currmove(val))
            elif current_parameter == "currmovenumber":
                handle_integer_token(token, lambda handler, val: handler.currmovenumber(val))
            elif current_parameter == "hashfull":
                handle_integer_token(token, lambda handler, val: handler.hashfull(val))
            elif current_parameter == "nps":
                handle_integer_token(token, lambda handler, val: handler.nps(val))
            elif current_parameter == "tbhits":
                handle_integer_token(token, lambda handler, val: handler.tbhits(val))
            elif current_parameter == "cpuload":
                handle_integer_token(token, lambda handler, val: handler.cpuload(val))
            elif current_parameter == "refutation":
                try:
                    if refutation_move is None:
                        refutation_move = board.push_uci(token)
                    else:
                        refuted_by.append(board.push_uci(token))
                except ValueError:
                    LOGGER.exception("exception parsing refutation")
            elif current_parameter == "currline":
                try:
                    if currline_cpunr is None:
                        currline_cpunr = int(token)
                    else:
                        currline_moves.append(board.push_uci(token))
                except ValueError:
                    LOGGER.exception("exception parsing currline")

        end_of_parameter()

        if string:
            for info_handler in self.info_handlers:
                info_handler.string(" ".join(string))

        # Notify info handlers of end.
        for info_handler in self.info_handlers:
            info_handler.post_info()
コード例 #24
0
 def get(self, key):
     try:
         return self._features[key]
     except KeyError:
         LOGGER.exception("exception looking up feature")
コード例 #25
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
    def usermove(self, move, async_callback=None):
        """
        Tells the XBoard engine to make a move on its internal
        board.

        If *auto_force* is set to ``True``, the engine will not start
        thinking about its next move immediately after.

        :param move: The move to play in XBoard notation.

        :return: Nothing.
        """
        builder = []
        if self.features.supports("usermove"):
            builder.append("usermove")

        if self.draw_handler:
            self.draw_handler.clear_offer()
            self.engine_offered_draw = False

        if self.auto_force:
            self.force()
        elif not self.in_force:
            with self.state_changed:
                if not self.idle:
                    raise EngineStateException("usermove command while engine is already busy")

                self.idle = False
                self.search_started.clear()
                self.move_received.clear()
                self.state_changed.notify_all()

            for post_handler in self.post_handlers:
                post_handler.on_go()

        try:
            self.board.push_uci(str(move))
        except ValueError:
            try:
                self.board.push_san(str(move))
            except ValueError:
                LOGGER.exception("exception parsing move")

        builder.append(str(move))

        def command():
            # Use the join(builder) once we parse usermove=1 feature.
            move_str = " ".join(builder)
            if self.in_force:
                with self.semaphore:
                    self.send_line(move_str)

                if self.terminated.is_set():
                    raise EngineTerminatedException()
            else:
                with self.semaphore:
                    self.send_line(move_str)
                    self.search_started.set()

                self.move_received.wait()

                with self.state_changed:
                    self.idle = True
                    self.state_changed.notify_all()

                if self.terminated.is_set():
                    raise EngineTerminatedException()

                try:
                    self.board.push_uci(str(self.move))
                except ValueError:
                    try:
                        self.board.push_san(str(self.move))
                    except ValueError:
                        LOGGER.exception("exception parsing move")

                return self.move

        return self._queue_command(command, async_callback)
コード例 #26
0
 def send_line(self, line):
     LOGGER.debug("%s << %s", self.process, line)
     return self.process.send_line(line)
コード例 #27
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
 def get_option(self, key):
     try:
         return self._features["option"][key]
     except KeyError:
         LOGGER.exception("exception looking up option")
コード例 #28
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
 def set_option(self, key, value):
     try:
         self._features["option"][key] = value
     except KeyError:
         LOGGER.exception("exception looking up option")
コード例 #29
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
    def _option(self, arg):
        current_parameter = None

        name = []
        type = []
        default = []
        min = None
        max = None
        current_var = None
        var = []

        for token in arg.split(" "):
            if token == "name" and not name:
                current_parameter = "name"
            elif token == "type" and not type:
                current_parameter = "type"
            elif token == "default" and not default:
                current_parameter = "default"
            elif token == "min" and min is None:
                current_parameter = "min"
            elif token == "max" and max is None:
                current_parameter = "max"
            elif token == "var":
                current_parameter = "var"
                if current_var is not None:
                    var.append(" ".join(current_var))
                current_var = []
            elif current_parameter == "name":
                name.append(token)
            elif current_parameter == "type":
                type.append(token)
            elif current_parameter == "default":
                default.append(token)
            elif current_parameter == "var":
                current_var.append(token)
            elif current_parameter == "min":
                try:
                    min = int(token)
                except ValueError:
                    LOGGER.exception("exception parsing option min")
            elif current_parameter == "max":
                try:
                    max = int(token)
                except ValueError:
                    LOGGER.exception("exception parsing option max")

        if current_var is not None:
            var.append(" ".join(current_var))

        type = " ".join(type)

        default = " ".join(default)
        if type == "check":
            if default == "true":
                default = True
            elif default == "false":
                default = False
            else:
                default = None
        elif type == "spin":
            try:
                default = int(default)
            except ValueError:
                LOGGER.exception("exception parsing option spin default")
                default = None

        option = Option(" ".join(name), type, default, min, max, var)
        self.options[option.name] = option
コード例 #30
0
ファイル: xboard.py プロジェクト: ddugovic/python-chess
 def get(self, key):
     try:
         return self._features[key]
     except KeyError:
         LOGGER.exception("exception looking up feature")
コード例 #31
0
ファイル: uci.py プロジェクト: teacoffee2017/python-chess
    def position(self, board, async_callback=None):
        """
        Set up a given position.

        Instead of just the final FEN, the initial FEN and all moves leading
        up to the position will be sent, so that the engine can detect
        repetitions.

        If the position is from a new game, it is recommended to use the
        *ucinewgame* command before the *position* command.

        :param board: A *chess.Board*.

        :return: Nothing

        :raises: :exc:`~chess.uci.EngineStateException` if the engine is still
            calculating.
        """
        # Check UCI_Variant
        uci_variant = type(board).uci_variant
        if uci_variant == "chess" and self.uci_variant is None:
            pass
        elif uci_variant != self.uci_variant:
            LOGGER.error("current UCI_Variant (%s) does not match position (%s)", self.uci_variant, uci_variant)

        # Raise if this is called while the engine is still calculating.
        with self.state_changed:
            if not self.idle:
                raise EngineStateException("position command while engine is busy")

        builder = []
        builder.append("position")

        # Take back moves to obtain the FEN at the latest pawn move or
        # capture. Later giving the moves explicitly allows for transposition
        # detection.
        switchyard = collections.deque()
        while board.move_stack:
            move = board.pop()
            switchyard.append(move)

            if board.is_irreversible(move):
                break

        # Validate castling rights.
        if not self.uci_chess960 and board.chess960:
            if board.has_chess960_castling_rights():
                LOGGER.error("not in UCI_Chess960 mode but position has non-standard castling rights")

                # Just send the final FEN without transpositions in hopes
                # that this will work.
                while switchyard:
                    board.push(switchyard.pop())

        # Send starting position.
        if uci_variant == "chess" and board.fen() == chess.STARTING_FEN:
            builder.append("startpos")
        else:
            builder.append("fen")
            builder.append(board.shredder_fen() if self.uci_chess960 else board.fen())

        # Send moves.
        if switchyard:
            builder.append("moves")

            while switchyard:
                move = switchyard.pop()
                builder.append(board.uci(move, chess960=self.uci_chess960))
                board.push(move)

        self.board = board.copy(stack=False)

        def command():
            with self.semaphore:
                self.send_line(" ".join(builder))

                if self.terminated.is_set():
                    raise EngineTerminatedException()

        return self._queue_command(command, async_callback)
コード例 #32
0
ファイル: uci.py プロジェクト: mrtseb/lazarus_forge
 def _copyprotection(self, arg):
     LOGGER.error("engine copyprotection not supported")