Exemple #1
0
    def makeMove(self, board1, move, board2):
        log.debug("ICPlayer.makemove: id(self)=%d self=%s move=%s board1=%s board2=%s" % \
                (id(self), self, move, board1, board2))
        if board2 and not self.gamemodel.isObservationGame():
            # TODO: Will this work if we just always use CASTLE_SAN?
            castle_notation = CASTLE_KK
            if board2.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            self.connection.bm.sendMove(toAN(board2, move, castleNotation=castle_notation))

        item = self.queue.get(block=True)
        try:
            if item == "del":
                raise PlayerIsDead
            if item == "int":
                raise TurnInterrupt

            ply, sanmove = item
            if ply < board1.ply:
                # This should only happen in an observed game
                board1 = self.gamemodel.getBoardAtPly(max(ply - 1, 0))
            log.debug("ICPlayer.makemove: id(self)=%d self=%s from queue got: ply=%d sanmove=%s" % \
                (id(self), self, ply, sanmove))

            try:
                move = parseSAN(board1, sanmove)
                log.debug("ICPlayer.makemove: id(self)=%d self=%s parsed move=%s" % \
                    (id(self), self, move))
            except ParsingError as err:
                raise
            return move
        finally:
            log.debug("ICPlayer.makemove: id(self)=%d self=%s returning move=%s" % \
                (id(self), self, move))
            self.okqueue.put("ok")
Exemple #2
0
    def __sendAnalyze (self, inverse=False):

        if inverse and self.board.board.opIsChecked():
            # Many engines don't like positions able to take down enemy
            # king. Therefore we just return the "kill king" move
            # automaticaly
            self.emit("analyze", [([toAN(self.board, getMoveKillingKing(self.board))], MATE_VALUE-1, "")])
            return

        def stop_analyze ():
            if self.engineIsAnalyzing:
                print("exit", file=self.engine)
                # Some engines (crafty, gnuchess) doesn't respond to exit command
                # we try to force them to stop with an empty board fen
                print("setboard 8/8/8/8/8/8/8/8 w - - 0 1", file=self.engine)
                self.engineIsAnalyzing = False
        
        print("post", file=self.engine)
        print("analyze", file=self.engine)
        self.engineIsAnalyzing = True

        if self.analysis_timer is not None:
            self.analysis_timer.cancel()
            self.analysis_timer.join()

        self.analysis_timer = Timer(conf.get("max_analysis_spin", 3), stop_analyze)
        self.analysis_timer.start()
Exemple #3
0
    def _searchNow(self, ponderhit=False):
        log.debug("_searchNow: self.needBestmove=%s ponderhit=%s self.board=%s" % (
            self.needBestmove, ponderhit, self.board), extra={"task": self.defname})

        commands = []

        if ponderhit:
            commands.append("ponderhit")

        elif self.mode == NORMAL:
            commands.append("position %s" % self.uciPosition)
            if self.strength <= 3:
                commands.append("go depth %d" % self.strength)
            else:
                if self.moves > 0:
                    commands.append("go wtime %d winc %d btime %d binc %d movestogo %s" % (
                                    self.wtime, self.incr, self.btime, self.incr, self.moves))
                else:
                    commands.append("go wtime %d winc %d btime %d binc %d" % (
                                    self.wtime, self.incr, self.btime, self.incr))

        else:
            print("stop", file=self.engine)

            if self.mode == INVERSE_ANALYZING:
                if self.board.board.opIsChecked():
                    # Many engines don't like positions able to take down enemy
                    # king. Therefore we just return the "kill king" move
                    # automaticaly
                    self.emit("analyze", [([toAN(
                        self.board, getMoveKillingKing(self.board))], MATE_VALUE - 1, "")])
                    return
                commands.append("position fen %s" % self.board.asFen())
            else:
                commands.append("position %s" % self.uciPosition)

            # commands.append("go infinite")
            move_time = int(conf.get("max_analysis_spin", 3)) * 1000
            commands.append("go movetime %s" % move_time)

        if self.hasOption("MultiPV") and self.multipvSetting > 1:
            self.multipvExpected = min(self.multipvSetting,
                                       legalMoveCount(self.board))
        else:
            self.multipvExpected = 1
        self.analysis = [None] * self.multipvExpected

        if self.needBestmove:
            self.commands.append(commands)
            log.debug("_searchNow: self.needBestmove==True, appended to self.commands=%s" %
                      self.commands, extra={"task": self.defname})
        else:
            for command in commands:
                print(command, file=self.engine)
            if getStatus(self.board)[
                    1] != WON_MATE:  # XXX This looks fishy.
                self.needBestmove = True
                self.readyForStop = True
Exemple #4
0
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return
        color = self.view.model.boards[-1].color
        board = self.view.model.getBoardAtPly(self.view.shown,
                                              self.view.shown_variation_idx)
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used
        if promotion is None and board[
                cord0].sign == PAWN and cord1.cord in board.PROMOTION_ZONE[
                    color]:
            if self.variant.variant == SITTUYINCHESS:
                # no promotion allowed if we have queen
                if board.board.boards[color][QUEEN]:
                    promotion = None
                else:
                    # promotion is always optional
                    promotion = self.getPromotion()
                    if promotion is None and cord0 == cord1:
                        # if don't want in place promotion
                        return
            elif len(self.variant.PROMOTIONS) == 1:
                promotion = lmove.PROMOTE_PIECE(self.variant.PROMOTIONS[0])
            else:
                if conf.get("autoPromote", False):
                    promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
                else:
                    promotion = self.getPromotion()
                    if promotion is None:
                        # Put back pawn moved be d'n'd
                        self.view.runAnimation(redraw_misc=False)
                        return
        if cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
                self.view.shownIsMainLine() and \
                self.view.model.boards[-1] == board and \
                self.view.model.status == RUNNING:
            if self.setup_position:
                self.emit("piece_moved", (cord0, cord1), board[cord0].color)
            else:
                self.emit("piece_moved", move, color)
                if self.view.model.examined:
                    self.view.model.connection.bm.sendMove(toAN(board, move))
        else:
            if board.board.next is None and not self.view.shownIsMainLine():
                self.view.model.add_move2variation(
                    board, move, self.view.shown_variation_idx)
                self.view.shown += 1
            else:
                new_vari = self.view.model.add_variation(board, (move, ))
                self.view.setShownBoard(new_vari[-1])
Exemple #5
0
 def __usermove (self, board, move):
     if self.features["usermove"]:
         self.engine.write("usermove ")
     
     if self.features["san"]:
         print(toSAN(board, move), file=self.engine)
     else:
         cn = CASTLE_KK
         if board.variant == FISCHERRANDOMCHESS:
             cn = CASTLE_SAN
         print(toAN(board, move, short=True, castleNotation=cn), file=self.engine)
    def __usermove(self, board, move):
        if self.features["usermove"]:
            self.engine.write("usermove ")

        if self.features["san"]:
            print(toSAN(board, move), file=self.engine)
        else:
            castle_notation = CASTLE_KK
            if board.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            print(
                toAN(board, move, short=True, castleNotation=castle_notation),
                file=self.engine,
            )
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return
        color = self.view.model.boards[-1].color
        board = self.view.model.getBoardAtPly(self.view.shown,
                                              self.view.shown_variation_idx)
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used
        if promotion is None and board[cord0].sign == PAWN and \
                cord1.cord in board.PROMOTION_ZONE[color]:
            if self.variant.variant == SITTUYINCHESS:
                # no promotion allowed if we have queen
                if board.board.boards[color][QUEEN]:
                    promotion = None
                else:
                    # promotion is always optional
                    promotion = self.getPromotion()
                    if promotion is None and cord0 == cord1:
                        # if don't want in place promotion
                        return
            elif len(self.variant.PROMOTIONS) == 1:
                promotion = lmove.PROMOTE_PIECE(self.variant.PROMOTIONS[0])
            else:
                if conf.get("autoPromote", False):
                    promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
                else:
                    promotion = self.getPromotion()
                    if promotion is None:
                        # Put back pawn moved be d'n'd
                        self.view.runAnimation(redraw_misc=False)
                        return
        if cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
                self.view.shownIsMainLine() and \
                self.view.model.boards[-1] == board and \
                self.view.model.status == RUNNING:
            # emit move
            if self.setup_position:
                self.emit("piece_moved", (cord0, cord1), board[cord0].color)
            else:
                self.emit("piece_moved", move, color)
                if self.view.model.examined:
                    self.view.model.connection.bm.sendMove(toAN(board, move))
        else:
            play_or_add_move(self.view, board, move)
Exemple #8
0
    def __sendAnalyze(self, inverse=False):
        if inverse and self.board.board.opIsChecked():
            # Many engines don't like positions able to take down enemy
            # king. Therefore we just return the "kill king" move
            # automaticaly
            self.emit("analyze", [(self.board.ply, [toAN(
                self.board, getMoveKillingKing(self.board))], MATE_VALUE - 1, "1", "")])
            return

        print("post", file=self.engine)
        print("analyze", file=self.engine)
        self.engineIsAnalyzing = True

        if not conf.get("infinite_analysis"):
            loop = asyncio.get_event_loop()
            loop.call_later(conf.get("max_analysis_spin"), self.__stop_analyze)
Exemple #9
0
    def __sendAnalyze(self, inverse=False):
        if inverse and self.board.board.opIsChecked():
            # Many engines don't like positions able to take down enemy
            # king. Therefore we just return the "kill king" move
            # automaticaly
            self.emit("analyze", [(self.board.ply, [toAN(
                self.board, getMoveKillingKing(self.board))], MATE_VALUE - 1, "", "")])
            return

        print("post", file=self.engine)
        print("analyze", file=self.engine)
        self.engineIsAnalyzing = True

        if not conf.get("infinite_analysis", False):
            loop = asyncio.get_event_loop()
            loop.call_later(conf.get("max_analysis_spin", 3), self.__stop_analyze)
Exemple #10
0
    def makeMove(self, board1, move, board2):
        log.debug("ICPlayer.makemove: id(self)=%d self=%s move=%s board1=%s board2=%s" % (
            id(self), self, move, board1, board2))
        if board2 and not self.gamemodel.isObservationGame():
            # TODO: Will this work if we just always use CASTLE_SAN?
            castle_notation = CASTLE_KK
            if board2.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            self.connection.bm.sendMove(toAN(board2, move, castleNotation=castle_notation))
        item = yield from self.gamemodel.ficsgame.queue.get()
        try:
            if item == "del":
                raise PlayerIsDead

            gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms = item
            self.gamemodel.onBoardUpdate(gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms)

            if curcol == self.color and ply == self.gamemodel.ply:
                item = yield from self.gamemodel.ficsgame.queue.get()

                if item == "del":
                    raise PlayerIsDead

                gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms = item
                self.gamemodel.onBoardUpdate(gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms)

            if self.turn_interrupt:
                self.turn_interrupt = False
                raise TurnInterrupt

            if ply < board1.ply:
                # This should only happen in an observed game
                board1 = self.gamemodel.getBoardAtPly(max(ply - 1, 0))
            log.debug("ICPlayer.makemove: id(self)=%d self=%s from queue got: ply=%d sanmove=%s" % (
                id(self), self, ply, lastmove))

            try:
                move = parseSAN(board1, lastmove)
                log.debug("ICPlayer.makemove: id(self)=%d self=%s parsed move=%s" % (
                    id(self), self, move))
            except ParsingError:
                raise
            return move
        finally:
            log.debug("ICPlayer.makemove: id(self)=%d self=%s returning move=%s" % (id(self), self, move))
Exemple #11
0
    def makeMove(self, board1, move, board2):
        log.debug("ICPlayer.makemove: id(self)=%d self=%s move=%s board1=%s board2=%s" % (
            id(self), self, move, board1, board2))
        if board2 and not self.gamemodel.isObservationGame():
            # TODO: Will this work if we just always use CASTLE_SAN?
            castle_notation = CASTLE_KK
            if board2.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            self.connection.bm.sendMove(toAN(board2, move, castleNotation=castle_notation))
            # wait for fics to send back our move we made
            item = yield from self.move_queue.get()

        item = yield from self.move_queue.get()
        try:
            if item == "end":
                raise GameEnded
            elif item == "del":
                raise PlayerIsDead

            gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms = item
            self.gamemodel.onBoardUpdate(gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms)

            if self.turn_interrupt:
                self.turn_interrupt = False
                raise TurnInterrupt

            if ply < board1.ply:
                # This should only happen in an observed game
                board1 = self.gamemodel.getBoardAtPly(max(ply - 1, 0))
            log.debug("ICPlayer.makemove: id(self)=%d self=%s from queue got: ply=%d sanmove=%s" % (
                id(self), self, ply, lastmove))

            try:
                move = parseSAN(board1, lastmove)
                log.debug("ICPlayer.makemove: id(self)=%d self=%s parsed move=%s" % (
                    id(self), self, move))
            except ParsingError:
                raise
            return move
        finally:
            log.debug("ICPlayer.makemove: id(self)=%d self=%s returning move=%s" % (id(self), self, move))
Exemple #12
0
    def makeMove(self, board1, move, board2):
        log.debug(
            "ICPlayer.makemove: id(self)=%d self=%s move=%s board1=%s board2=%s"
            % (id(self), self, move, board1, board2))
        if board2 and not self.gamemodel.isObservationGame():
            # TODO: Will this work if we just always use CASTLE_SAN?
            castle_notation = CASTLE_KK
            if board2.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            self.connection.bm.sendMove(
                toAN(board2, move, castleNotation=castle_notation))

        item = self.queue.get(block=True)
        try:
            if item == "del":
                raise PlayerIsDead
            if item == "int":
                raise TurnInterrupt

            ply, sanmove = item
            if ply < board1.ply:
                # This should only happen in an observed game
                board1 = self.gamemodel.getBoardAtPly(max(ply - 1, 0))
            log.debug(
                "ICPlayer.makemove: id(self)=%d self=%s from queue got: ply=%d sanmove=%s"
                % (id(self), self, ply, sanmove))

            try:
                move = parseSAN(board1, sanmove)
                log.debug(
                    "ICPlayer.makemove: id(self)=%d self=%s parsed move=%s" %
                    (id(self), self, move))
            except ParsingError:
                raise
            return move
        finally:
            log.debug(
                "ICPlayer.makemove: id(self)=%d self=%s returning move=%s" %
                (id(self), self, move))
            self.okqueue.put("ok")
Exemple #13
0
    def key_pressed(self, keyname):
        if keyname in "PNBRQKMFSOox12345678abcdefgh":
            self.keybuffer += keyname

        elif keyname == "minus":
            self.keybuffer += "-"

        elif keyname == "at":
            self.keybuffer += "@"

        elif keyname == "equal":
            self.keybuffer += "="

        elif keyname == "Return":
            color = self.view.model.boards[-1].color
            board = self.view.model.getBoardAtPly(
                self.view.shown, self.view.shown_variation_idx)
            try:
                move = parseAny(board, self.keybuffer)
            except ParsingError:
                self.keybuffer = ""
                return

            if validate(board, move):
                if ((self.view.model.curplayer.__type__ == LOCAL
                     or self.view.model.examined)
                        and self.view.shownIsMainLine()
                        and self.view.model.boards[-1] == board
                        and self.view.model.status == RUNNING):
                    # emit move
                    self.emit("piece_moved", move, color)
                    if self.view.model.examined:
                        self.view.model.connection.bm.sendMove(
                            toAN(board, move))
                else:
                    self.play_or_add_move(board, move)
            self.keybuffer = ""

        elif keyname == "BackSpace":
            self.keybuffer = self.keybuffer[:-1] if self.keybuffer else ""
Exemple #14
0
    def key_pressed(self, keyname):
        if keyname in "PNBRQKMFSOox12345678abcdefgh":
            self.keybuffer += keyname

        elif keyname == "minus":
            self.keybuffer += "-"

        elif keyname == "at":
            self.keybuffer += "@"

        elif keyname == "equal":
            self.keybuffer += "="

        elif keyname == "Return":
            color = self.view.model.boards[-1].color
            board = self.view.model.getBoardAtPly(
                self.view.shown, self.view.shown_variation_idx)
            try:
                move = parseAny(board, self.keybuffer)
            except:
                self.keybuffer = ""
                return

            if validate(board, move):
                if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
                        self.view.shownIsMainLine() and \
                        self.view.model.boards[-1] == board and \
                        self.view.model.status == RUNNING:
                    # emit move
                    self.emit("piece_moved", move, color)
                    if self.view.model.examined:
                        self.view.model.connection.bm.sendMove(toAN(board, move))
                else:
                    play_or_add_move(self.view, board, move)
            self.keybuffer = ""

        elif keyname == "BackSpace":
            self.keybuffer = self.keybuffer[:-1] if self.keybuffer else ""
Exemple #15
0
    def __sendAnalyze(self, inverse=False):

        if inverse and self.board.board.opIsChecked():
            # Many engines don't like positions able to take down enemy
            # king. Therefore we just return the "kill king" move
            # automaticaly
            self.emit("analyze", [([toAN(
                self.board, getMoveKillingKing(self.board))], MATE_VALUE - 1, "")])
            return

        def stop_analyze():
            if self.engineIsAnalyzing:
                print("exit", file=self.engine)
                # Some engines (crafty, gnuchess) doesn't respond to exit command
                # we try to force them to stop with an empty board fen
                print("setboard 8/8/8/8/8/8/8/8 w - - 0 1", file=self.engine)
                self.engineIsAnalyzing = False

        print("post", file=self.engine)
        print("analyze", file=self.engine)
        self.engineIsAnalyzing = True

        loop = asyncio.get_event_loop()
        loop.call_later(conf.get("max_analysis_spin", 3), stop_analyze)
Exemple #16
0
    def _searchNow(self, ponderhit=False):
        log.debug(
            "_searchNow: self.needBestmove=%s ponderhit=%s self.board=%s" %
            (self.needBestmove, ponderhit, self.board),
            extra={"task": self.defname})

        commands = []

        if ponderhit:
            commands.append("ponderhit")

        elif self.mode == NORMAL:
            commands.append("position %s" % self.uciPosition)
            if self.strength <= 3:
                commands.append("go depth %d" % self.strength)
            else:
                if self.moves > 0:
                    commands.append(
                        "go wtime %d winc %d btime %d binc %d movestogo %s" %
                        (self.wtime, self.incr, self.btime, self.incr,
                         self.moves))
                else:
                    commands.append(
                        "go wtime %d winc %d btime %d binc %d" %
                        (self.wtime, self.incr, self.btime, self.incr))

        else:
            print("stop", file=self.engine)

            if self.mode == INVERSE_ANALYZING:
                if self.board.board.opIsChecked():
                    # Many engines don't like positions able to take down enemy
                    # king. Therefore we just return the "kill king" move
                    # automaticaly
                    self.emit("analyze", [(self.board.ply, [
                        toAN(self.board, getMoveKillingKing(self.board))
                    ], MATE_VALUE - 1, "1", "")])
                    return
                commands.append("position fen %s" % self.board.asFen())
            else:
                commands.append("position %s" % self.uciPosition)

            if self.analysis_depth is not None:
                commands.append("go depth %s" % self.analysis_depth)
            elif conf.get("infinite_analysis"):
                commands.append("go infinite")
            else:
                move_time = int(conf.get("max_analysis_spin")) * 1000
                commands.append("go movetime %s" % move_time)

        if self.hasOption("MultiPV") and self.multipvSetting > 1:
            self.multipvExpected = min(self.multipvSetting,
                                       legalMoveCount(self.board))
        else:
            self.multipvExpected = 1
        self.analysis = [None] * self.multipvExpected

        if self.needBestmove:
            self.commands.append(commands)
            log.debug(
                "_searchNow: self.needBestmove==True, appended to self.commands=%s"
                % self.commands,
                extra={"task": self.defname})
        else:
            for command in commands:
                print(command, file=self.engine)
            if getStatus(self.board)[1] != WON_MATE:  # XXX This looks fishy.
                self.needBestmove = True
                self.readyForStop = True
Exemple #17
0
 def _moveToUCI(self, board, move):
     castle_notation = CASTLE_KK
     if board.variant == FISCHERRANDOMCHESS:
         castle_notation = CASTLE_KR
     return toAN(board, move, short=True, castleNotation=castle_notation)
Exemple #18
0
    def makeMove(self, board1, move, board2):
        log.debug("ICPlayer.makemove: id(self)=%d self=%s move=%s board1=%s board2=%s" % (
            id(self), self, move, board1, board2))
        if board2 and not self.gamemodel.isObservationGame():
            # TODO: Will this work if we just always use CASTLE_SAN?
            castle_notation = CASTLE_KK
            if board2.variant == FISCHERRANDOMCHESS:
                castle_notation = CASTLE_SAN
            self.connection.bm.sendMove(toAN(board2, move, castleNotation=castle_notation))
            # wait for fics to send back our move we made
            item = yield from self.move_queue.get()
            log.debug("ICPlayer.makeMove: fics sent back the move we made")

        item = yield from self.move_queue.get()
        try:
            if item == "end":
                log.debug("ICPlayer.makeMove got: end")
                raise GameEnded
            elif item == "del":
                log.debug("ICPlayer.makeMove got: del")
                raise PlayerIsDead
            elif item == "stm":
                log.debug("ICPlayer.makeMove got: stm")
                self.turn_interrupt = False
                raise TurnInterrupt
            elif item == "fen":
                log.debug("ICPlayer.makeMove got: fen")
                self.turn_interrupt = False
                raise TurnInterrupt
            elif item == "pass":
                log.debug("ICPlayer.makeMove got: pass")
                self.pass_interrupt = False
                raise PassInterrupt

            gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms = item
            log.debug("ICPlayer.makeMove got: %s %s %s %s" % (gameno, ply, curcol, lastmove))
            self.gamemodel.onBoardUpdate(gameno, ply, curcol, lastmove, fen, wname, bname, wms, bms)

            if self.turn_interrupt:
                self.turn_interrupt = False
                raise TurnInterrupt

            if self.pass_interrupt:
                self.pass_interrupt = False
                raise PassInterrupt

            if ply < board1.ply:
                # This should only happen in an observed game
                board1 = self.gamemodel.getBoardAtPly(max(ply - 1, 0))
            log.debug("ICPlayer.makemove: id(self)=%d self=%s from queue got: ply=%d sanmove=%s" % (
                id(self), self, ply, lastmove))

            try:
                move = parseSAN(board1, lastmove)
                log.debug("ICPlayer.makemove: id(self)=%d self=%s parsed move=%s" % (
                    id(self), self, move))
            except ParsingError:
                raise
            return move
        finally:
            log.debug("ICPlayer.makemove: id(self)=%d self=%s returning move=%s" % (id(self), self, move))
Exemple #19
0
    def emit_move_signal(self, cord0, cord1, promotion=None):
        # Game end can change cord0 to None while dragging a piece
        if cord0 is None:
            return
        gating = None
        board = self.getBoard()
        color = board.color
        # Ask player for which piece to promote into. If this move does not
        # include a promotion, QUEEN will be sent as a dummy value, but not used
        if promotion is None and board[cord0].sign == PAWN and \
                cord1.cord in board.PROMOTION_ZONE[color] and \
                self.variant.variant != SITTUYINCHESS:
            if len(self.variant.PROMOTIONS) == 1:
                promotion = lmove.PROMOTE_PIECE(self.variant.PROMOTIONS[0])
            elif self.variant.variant == LIGHTBRIGADECHESS:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION if color ==
                                                WHITE else KNIGHT_PROMOTION)
            else:
                if conf.get("autoPromote"):
                    promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
                else:
                    promotion = self.getPromotion()
                    if promotion is None:
                        # Put back pawn moved be d'n'd
                        self.view.runAnimation(redraw_misc=False)
                        return
        if promotion is None and board[cord0].sign == PAWN and \
                cord0.cord in board.PROMOTION_ZONE[color] and \
                self.variant.variant == SITTUYINCHESS:
            # no promotion allowed if we have queen
            if board.board.boards[color][QUEEN]:
                promotion = None
            # in place promotion
            elif cord1.cord in board.PROMOTION_ZONE[color]:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)
            # queen move promotion (but not a pawn capture!)
            elif board[cord1] is None and (cord0.cord + cord1.cord) % 2 == 1:
                promotion = lmove.PROMOTE_PIECE(QUEEN_PROMOTION)

        holding = board.board.holding[color]
        if self.variant.variant == SCHESS:
            moved = board[cord0].sign
            hawk = holding[HAWK] > 0
            elephant = holding[ELEPHANT] > 0
            if (hawk or elephant) and cord0.cord in iterBits(
                    board.board.virgin[color]):
                castling = moved == KING and abs(cord0.x - cord1.x) == 2
                gating = self.getGating(castling, hawk, elephant)

        if gating is not None:
            if gating in (HAWK_GATE_AT_ROOK, ELEPHANT_GATE_AT_ROOK):
                side = 0 if cord0.x - cord1.x == 2 else 1
                rcord = board.board.ini_rooks[color][side]
                move = Move(lmovegen.newMove(rcord, cord0.cord, gating))
            else:
                move = Move(lmovegen.newMove(cord0.cord, cord1.cord, gating))
        elif cord0.x < 0 or cord0.x > self.FILES - 1:
            move = Move(lmovegen.newMove(board[cord0].piece, cord1.cord, DROP))
        else:
            move = Move(cord0, cord1, board, promotion)

        if (self.view.model.curplayer.__type__ == LOCAL or self.view.model.examined) and \
                self.view.shownIsMainLine() and \
                self.view.model.boards[-1] == board and \
                self.view.model.status == RUNNING:
            # emit move
            if self.setup_position:
                self.emit("piece_moved", (cord0, cord1), board[cord0].color)
            else:
                self.emit("piece_moved", move, color)
                if self.view.model.examined:
                    self.view.model.connection.bm.sendMove(toAN(board, move))
        else:
            self.play_or_add_move(board, move)
Exemple #20
0
 def _moveToUCI (self, board, move):
     cn = CASTLE_KK
     if board.variant == FISCHERRANDOMCHESS:
         cn = CASTLE_KR
     return toAN(board, move, short=True, castleNotation=cn)