Ejemplo n.º 1
0
class MainWindow(QWidget):
    def __init__(self):
        super().__init__()

        self.movehistory = []
        self.game = chess.pgn.Game()

        self.setGeometry(1050, 200, 500, 500)

        self.widgetSvg = QSvgWidget(parent=self)
        self.widgetSvg.setGeometry(0, 0, 500, 500)

        self.boardSize = min(self.widgetSvg.width(), self.widgetSvg.height())
        self.squareSize = self.boardSize / 8.0
        self.pieceToMove = [None, None]

        self.board = chess.Board()

        self.drawBoard()

    @pyqtSlot(QWidget)
    def mousePressEvent(self, event):
        if self.board.is_game_over(claim_draw=True) is False:
            if not self.board.turn:
                move = select_move(self.board, DEPTH)
                self.board.push(move)
                self.movehistory.append(move)
            elif event.x() <= self.boardSize and event.y() <= self.boardSize:
                if event.buttons() == Qt.LeftButton:
                    file = int((event.x()) / self.squareSize)
                    rank = 7 - int((event.y()) / self.squareSize)
                    square = chess.square(file, rank)
                    piece = self.board.piece_at(square)
                    coordinates = "{}{}".format(chr(file + 97), str(rank + 1))
                    if self.pieceToMove[0] is not None:
                        move = chess.Move.from_uci("{}{}".format(
                            self.pieceToMove[1], coordinates))
                        if move in self.board.legal_moves:
                            self.board.push(move)
                            self.movehistory.append(move)
                        piece = None
                        coordinates = None
                    self.pieceToMove = [piece, coordinates]
            self.drawBoard()
        else:
            self.game.add_line(self.movehistory)
            print(self.game, file=open("gameresult.pgn", "w"), end="\n\n")
            print("Game over")
            exit()

    def drawBoard(self):
        lastmove = self.board.peek() if self.board.move_stack else None
        self.boardSvg = chess.svg.board(board=self.board,
                                        lastmove=lastmove).encode("UTF-8")
        self.drawBoardSvg = self.widgetSvg.load(self.boardSvg)

        return self.boardSvg
Ejemplo n.º 2
0
class ScalableDial(QDial):
    # enum CustomPaintMode
    CUSTOM_PAINT_MODE_NULL = 0  # default (NOTE: only this mode has label gradient)
    CUSTOM_PAINT_MODE_CARLA_WET = 1  # color blue-green gradient (reserved #3)
    CUSTOM_PAINT_MODE_CARLA_VOL = 2  # color blue (reserved #3)
    CUSTOM_PAINT_MODE_CARLA_L = 3  # color yellow (reserved #4)
    CUSTOM_PAINT_MODE_CARLA_R = 4  # color yellow (reserved #4)
    CUSTOM_PAINT_MODE_CARLA_PAN = 5  # color yellow (reserved #3)
    CUSTOM_PAINT_MODE_COLOR = 6  # color, selectable (reserved #3)
    CUSTOM_PAINT_MODE_ZITA = 7  # custom zita knob (reserved #6)
    CUSTOM_PAINT_MODE_NO_GRADIENT = 8  # skip label gradient

    # enum Orientation
    HORIZONTAL = 0
    VERTICAL = 1

    HOVER_MIN = 0
    HOVER_MAX = 9

    MODE_DEFAULT = 0
    MODE_LINEAR = 1

    # signals
    dragStateChanged = pyqtSignal(bool)
    realValueChanged = pyqtSignal(float)

    def __init__(self, parent, index=0):
        QDial.__init__(self, parent)

        self.fDialMode = self.MODE_LINEAR

        self.fMinimum = 0.0
        self.fMaximum = 1.0
        self.fRealValue = 0.0
        self.fPrecision = 10000
        self.fIsInteger = False

        self.fIsHovered = False
        self.fIsPressed = False
        self.fHoverStep = self.HOVER_MIN

        self.fLastDragPos = None
        self.fLastDragValue = 0.0

        self.fIndex = index
        self.fImage = QSvgWidget(":/scalable/dial_03.svg")
        self.fImageNum = "01"

        if self.fImage.sizeHint().width() > self.fImage.sizeHint().height():
            self.fImageOrientation = self.HORIZONTAL
        else:
            self.fImageOrientation = self.VERTICAL

        self.fLabel = ""
        self.fLabelPos = QPointF(0.0, 0.0)
        self.fLabelFont = QFont(self.font())
        self.fLabelFont.setPixelSize(8)
        self.fLabelWidth = 0
        self.fLabelHeight = 0

        if self.palette().window().color().lightness() > 100:
            # Light background
            c = self.palette().dark().color()
            self.fLabelGradientColor1 = c
            self.fLabelGradientColor2 = QColor(c.red(), c.green(), c.blue(), 0)
            self.fLabelGradientColorT = [
                self.palette().buttonText().color(),
                self.palette().mid().color()
            ]
        else:
            # Dark background
            self.fLabelGradientColor1 = QColor(0, 0, 0, 255)
            self.fLabelGradientColor2 = QColor(0, 0, 0, 0)
            self.fLabelGradientColorT = [Qt.white, Qt.darkGray]

        self.fLabelGradient = QLinearGradient(0, 0, 0, 1)
        self.fLabelGradient.setColorAt(0.0, self.fLabelGradientColor1)
        self.fLabelGradient.setColorAt(0.6, self.fLabelGradientColor1)
        self.fLabelGradient.setColorAt(1.0, self.fLabelGradientColor2)

        self.fLabelGradientRect = QRectF(0.0, 0.0, 0.0, 0.0)

        self.fCustomPaintMode = self.CUSTOM_PAINT_MODE_NULL
        self.fCustomPaintColor = QColor(0xff, 0xff, 0xff)

        self.updateSizes()

        # Fake internal value, custom precision
        QDial.setMinimum(self, 0)
        QDial.setMaximum(self, self.fPrecision)
        QDial.setValue(self, 0)

        self.valueChanged.connect(self.slot_valueChanged)

    def getIndex(self):
        return self.fIndex

    def getBaseSize(self):
        return self.fImageBaseSize

    def forceWhiteLabelGradientText(self):
        self.fLabelGradientColor1 = QColor(0, 0, 0, 255)
        self.fLabelGradientColor2 = QColor(0, 0, 0, 0)
        self.fLabelGradientColorT = [Qt.white, Qt.darkGray]

    def setLabelColor(self, enabled, disabled):
        self.fLabelGradientColor1 = QColor(0, 0, 0, 255)
        self.fLabelGradientColor2 = QColor(0, 0, 0, 0)
        self.fLabelGradientColorT = [enabled, disabled]

    def updateSizes(self):
        if isinstance(self.fImage, QPixmap):
            self.fImageWidth = self.fImage.width()
            self.fImageHeight = self.fImage.height()
        else:
            self.fImageWidth = self.fImage.sizeHint().width()
            self.fImageHeight = self.fImage.sizeHint().height()

        if self.fImageWidth < 1:
            self.fImageWidth = 1

        if self.fImageHeight < 1:
            self.fImageHeight = 1

        if self.fImageOrientation == self.HORIZONTAL:
            self.fImageBaseSize = self.fImageHeight
            self.fImageLayersCount = self.fImageWidth / self.fImageHeight
        else:
            self.fImageBaseSize = self.fImageWidth
            self.fImageLayersCount = self.fImageHeight / self.fImageWidth

        self.setMinimumSize(self.fImageBaseSize,
                            self.fImageBaseSize + self.fLabelHeight + 5)
        self.setMaximumSize(self.fImageBaseSize,
                            self.fImageBaseSize + self.fLabelHeight + 5)

        if not self.fLabel:
            self.fLabelHeight = 0
            self.fLabelWidth = 0
            return

        self.fLabelWidth = QFontMetrics(self.fLabelFont).width(self.fLabel)
        self.fLabelHeight = QFontMetrics(self.fLabelFont).height()

        self.fLabelPos.setX(
            float(self.fImageBaseSize) / 2.0 - float(self.fLabelWidth) / 2.0)

        if self.fImageNum in ("01", "02", "07", "08", "09", "10"):
            self.fLabelPos.setY(self.fImageBaseSize + self.fLabelHeight)
        elif self.fImageNum in ("11", ):
            self.fLabelPos.setY(self.fImageBaseSize +
                                self.fLabelHeight * 2 / 3)
        else:
            self.fLabelPos.setY(self.fImageBaseSize + self.fLabelHeight / 2)

        self.fLabelGradient.setStart(0, float(self.fImageBaseSize) / 2.0)
        self.fLabelGradient.setFinalStop(
            0, self.fImageBaseSize + self.fLabelHeight + 5)

        self.fLabelGradientRect = QRectF(
            float(self.fImageBaseSize) / 8.0,
            float(self.fImageBaseSize) / 2.0,
            float(self.fImageBaseSize * 3) / 4.0,
            self.fImageBaseSize + self.fLabelHeight + 5)

    def setCustomPaintMode(self, paintMode):
        if self.fCustomPaintMode == paintMode:
            return

        self.fCustomPaintMode = paintMode
        self.update()

    def setCustomPaintColor(self, color):
        if self.fCustomPaintColor == color:
            return

        self.fCustomPaintColor = color
        self.update()

    def setLabel(self, label):
        if self.fLabel == label:
            return

        self.fLabel = label
        self.updateSizes()
        self.update()

    def setIndex(self, index):
        self.fIndex = index

    def setImage(self, imageId):
        self.fImageNum = "%02i" % imageId
        if imageId in (2, 6, 7, 8, 9, 10, 11, 12, 13):
            img = ":/bitmaps/dial_%s%s.png" % (self.fImageNum,
                                               "" if self.isEnabled() else "d")
        else:
            img = ":/scalable/dial_%s%s.svg" % (self.fImageNum, ""
                                                if self.isEnabled() else "d")

        if img.endswith(".png"):
            if not isinstance(self.fImage, QPixmap):
                self.fImage = QPixmap()
        else:
            if not isinstance(self.fImage, QSvgWidget):
                self.fImage = QSvgWidget()

        self.fImage.load(img)

        if self.fImage.width() > self.fImage.height():
            self.fImageOrientation = self.HORIZONTAL
        else:
            self.fImageOrientation = self.VERTICAL

        # special svgs
        if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_NULL:
            # reserved for carla-wet, carla-vol, carla-pan and color
            if self.fImageNum == "03":
                self.fCustomPaintMode = self.CUSTOM_PAINT_MODE_COLOR

            # reserved for carla-L and carla-R
            elif self.fImageNum == "04":
                self.fCustomPaintMode = self.CUSTOM_PAINT_MODE_CARLA_L

            # reserved for zita
            elif self.fImageNum == "06":
                self.fCustomPaintMode = self.CUSTOM_PAINT_MODE_ZITA

        self.updateSizes()
        self.update()

    def setPrecision(self, value, isInteger):
        self.fPrecision = value
        self.fIsInteger = isInteger
        QDial.setMaximum(self, value)

    def setMinimum(self, value):
        self.fMinimum = value

    def setMaximum(self, value):
        self.fMaximum = value

    def rvalue(self):
        return self.fRealValue

    def setValue(self, value, emitSignal=False):
        if self.fRealValue == value or isnan(value):
            return

        if value <= self.fMinimum:
            qtValue = 0
            self.fRealValue = self.fMinimum

        elif value >= self.fMaximum:
            qtValue = self.fPrecision
            self.fRealValue = self.fMaximum

        else:
            qtValue = round(
                float(value - self.fMinimum) /
                float(self.fMaximum - self.fMinimum) * self.fPrecision)
            self.fRealValue = value

        # Block change signal, we'll handle it ourselves
        self.blockSignals(True)
        QDial.setValue(self, qtValue)
        self.blockSignals(False)

        if emitSignal:
            self.realValueChanged.emit(self.fRealValue)

    @pyqtSlot(int)
    def slot_valueChanged(self, value):
        self.fRealValue = float(value) / self.fPrecision * (
            self.fMaximum - self.fMinimum) + self.fMinimum
        self.realValueChanged.emit(self.fRealValue)

    @pyqtSlot()
    def slot_updateImage(self):
        self.setImage(int(self.fImageNum))

    def minimumSizeHint(self):
        return QSize(self.fImageBaseSize, self.fImageBaseSize)

    def sizeHint(self):
        return QSize(self.fImageBaseSize, self.fImageBaseSize)

    def changeEvent(self, event):
        QDial.changeEvent(self, event)

        # Force svg update if enabled state changes
        if event.type() == QEvent.EnabledChange:
            self.slot_updateImage()

    def enterEvent(self, event):
        self.fIsHovered = True
        if self.fHoverStep == self.HOVER_MIN:
            self.fHoverStep = self.HOVER_MIN + 1
        QDial.enterEvent(self, event)

    def leaveEvent(self, event):
        self.fIsHovered = False
        if self.fHoverStep == self.HOVER_MAX:
            self.fHoverStep = self.HOVER_MAX - 1
        QDial.leaveEvent(self, event)

    def mousePressEvent(self, event):
        if self.fDialMode == self.MODE_DEFAULT:
            return QDial.mousePressEvent(self, event)

        if event.button() == Qt.LeftButton:
            self.fIsPressed = True
            self.fLastDragPos = event.pos()
            self.fLastDragValue = self.fRealValue
            self.dragStateChanged.emit(True)

    def mouseMoveEvent(self, event):
        if self.fDialMode == self.MODE_DEFAULT:
            return QDial.mouseMoveEvent(self, event)

        if not self.fIsPressed:
            return

        range = (self.fMaximum - self.fMinimum) / 4.0
        pos = event.pos()
        dx = range * float(pos.x() - self.fLastDragPos.x()) / self.width()
        dy = range * float(pos.y() - self.fLastDragPos.y()) / self.height()
        value = self.fLastDragValue + dx - dy

        if value < self.fMinimum:
            value = self.fMinimum
        elif value > self.fMaximum:
            value = self.fMaximum
        elif self.fIsInteger:
            value = float(round(value))

        self.setValue(value, True)

    def mouseReleaseEvent(self, event):
        if self.fDialMode == self.MODE_DEFAULT:
            return QDial.mouseReleaseEvent(self, event)

        if self.fIsPressed:
            self.fIsPressed = False
            self.dragStateChanged.emit(False)

    def paintEvent(self, event):
        painter = QPainter(self)
        event.accept()

        painter.save()
        painter.setRenderHint(QPainter.Antialiasing, True)

        if self.fLabel:
            if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_NULL:
                painter.setPen(self.fLabelGradientColor2)
                painter.setBrush(self.fLabelGradient)
                painter.drawRect(self.fLabelGradientRect)

            painter.setFont(self.fLabelFont)
            painter.setPen(
                self.fLabelGradientColorT[0 if self.isEnabled() else 1])
            painter.drawText(self.fLabelPos, self.fLabel)

        if self.isEnabled():
            normValue = float(self.fRealValue -
                              self.fMinimum) / float(self.fMaximum -
                                                     self.fMinimum)
            curLayer = int((self.fImageLayersCount - 1) * normValue)

            if self.fImageOrientation == self.HORIZONTAL:
                xpos = self.fImageBaseSize * curLayer
                ypos = 0.0
            else:
                xpos = 0.0
                ypos = self.fImageBaseSize * curLayer

            source = QRectF(xpos, ypos, self.fImageBaseSize,
                            self.fImageBaseSize)

            if isinstance(self.fImage, QPixmap):
                target = QRectF(0.0, 0.0, self.fImageBaseSize,
                                self.fImageBaseSize)
                painter.drawPixmap(target, self.fImage, source)
            else:
                self.fImage.renderer().render(painter, source)

            # Custom knobs (Dry/Wet and Volume)
            if self.fCustomPaintMode in (self.CUSTOM_PAINT_MODE_CARLA_WET,
                                         self.CUSTOM_PAINT_MODE_CARLA_VOL):
                # knob color
                colorGreen = QColor(0x5D, 0xE7,
                                    0x3D).lighter(100 + self.fHoverStep * 6)
                colorBlue = QColor(0x3E, 0xB8,
                                   0xBE).lighter(100 + self.fHoverStep * 6)

                # draw small circle
                ballRect = QRectF(8.0, 8.0, 15.0, 15.0)
                ballPath = QPainterPath()
                ballPath.addEllipse(ballRect)
                #painter.drawRect(ballRect)
                tmpValue = (0.375 + 0.75 * normValue)
                ballValue = tmpValue - floor(tmpValue)
                ballPoint = ballPath.pointAtPercent(ballValue)

                # draw arc
                startAngle = 218 * 16
                spanAngle = -255 * 16 * normValue

                if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_CARLA_WET:
                    painter.setBrush(colorBlue)
                    painter.setPen(QPen(colorBlue, 0))
                    painter.drawEllipse(
                        QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2))

                    gradient = QConicalGradient(15.5, 15.5, -45)
                    gradient.setColorAt(0.0, colorBlue)
                    gradient.setColorAt(0.125, colorBlue)
                    gradient.setColorAt(0.625, colorGreen)
                    gradient.setColorAt(0.75, colorGreen)
                    gradient.setColorAt(0.76, colorGreen)
                    gradient.setColorAt(1.0, colorGreen)
                    painter.setBrush(gradient)
                    painter.setPen(QPen(gradient, 3))

                else:
                    painter.setBrush(colorBlue)
                    painter.setPen(QPen(colorBlue, 0))
                    painter.drawEllipse(
                        QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2))

                    painter.setBrush(colorBlue)
                    painter.setPen(QPen(colorBlue, 3))

                painter.drawArc(4.0, 4.0, 26.0, 26.0, startAngle, spanAngle)

            # Custom knobs (L and R)
            elif self.fCustomPaintMode in (self.CUSTOM_PAINT_MODE_CARLA_L,
                                           self.CUSTOM_PAINT_MODE_CARLA_R):
                # knob color
                color = QColor(0xAD, 0xD5,
                               0x48).lighter(100 + self.fHoverStep * 6)

                # draw small circle
                ballRect = QRectF(7.0, 8.0, 11.0, 12.0)
                ballPath = QPainterPath()
                ballPath.addEllipse(ballRect)
                #painter.drawRect(ballRect)
                tmpValue = (0.375 + 0.75 * normValue)
                ballValue = tmpValue - floor(tmpValue)
                ballPoint = ballPath.pointAtPercent(ballValue)

                painter.setBrush(color)
                painter.setPen(QPen(color, 0))
                painter.drawEllipse(
                    QRectF(ballPoint.x(), ballPoint.y(), 2.0, 2.0))

                # draw arc
                if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_CARLA_L:
                    startAngle = 218 * 16
                    spanAngle = -255 * 16 * normValue
                else:
                    startAngle = 322.0 * 16
                    spanAngle = 255.0 * 16 * (1.0 - normValue)

                painter.setPen(QPen(color, 2.5))
                painter.drawArc(3.5, 3.5, 22.0, 22.0, startAngle, spanAngle)

            # Custom knobs (Color)
            elif self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_COLOR:
                # knob color
                color = self.fCustomPaintColor.lighter(100 +
                                                       self.fHoverStep * 6)

                # draw small circle
                ballRect = QRectF(8.0, 8.0, 15.0, 15.0)
                ballPath = QPainterPath()
                ballPath.addEllipse(ballRect)
                tmpValue = (0.375 + 0.75 * normValue)
                ballValue = tmpValue - floor(tmpValue)
                ballPoint = ballPath.pointAtPercent(ballValue)

                # draw arc
                startAngle = 218 * 16
                spanAngle = -255 * 16 * normValue

                painter.setBrush(color)
                painter.setPen(QPen(color, 0))
                painter.drawEllipse(
                    QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2))

                painter.setBrush(color)
                painter.setPen(QPen(color, 3))
                painter.drawArc(4.0, 4.8, 26.0, 26.0, startAngle, spanAngle)

            # Custom knobs (Zita)
            elif self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_ZITA:
                a = normValue * pi * 1.5 - 2.35
                r = 10.0
                x = 10.5
                y = 10.5
                x += r * sin(a)
                y -= r * cos(a)
                painter.setBrush(Qt.black)
                painter.setPen(QPen(Qt.black, 2))
                painter.drawLine(QPointF(11.0, 11.0), QPointF(x, y))

            # Custom knobs
            else:
                painter.restore()
                return

            if self.HOVER_MIN < self.fHoverStep < self.HOVER_MAX:
                self.fHoverStep += 1 if self.fIsHovered else -1
                QTimer.singleShot(20, self.update)

        else:  # isEnabled()
            target = QRectF(0.0, 0.0, self.fImageBaseSize, self.fImageBaseSize)
            if isinstance(self.fImage, QPixmap):
                painter.drawPixmap(target, self.fImage, target)
            else:
                self.fImage.renderer().render(painter, target)

        painter.restore()

    def resizeEvent(self, event):
        QDial.resizeEvent(self, event)
        self.updateSizes()
class MainWindow(QWidget):
    """
    Create a surface for the chessboard.
    """
    def __init__(self):
        """
        Initialize the chessboard.
        """
        super().__init__()

        self.setWindowTitle("Chess GUI")
        self.setGeometry(300, 300, 610, 610)

        self.widgetSvg = QSvgWidget(parent=self)
        self.widgetSvg.setGeometry(10, 10, 600, 600)

        self.boardSize = min(self.widgetSvg.width(), self.widgetSvg.height())
        self.coordinates = True
        self.margin = 0.05 * self.boardSize if self.coordinates else 0
        self.squareSize = (self.boardSize - 2 * self.margin) / 8.0
        self.pieceToMove = [None, None]

        self.board = chess.Board()

        self.game = chess.pgn.Game()
        self.game.headers["Event"] = "test"
        self.game.headers["White"] = "user"
        self.game.headers["Black"] = "homemade engine"
        self.game.setup(self.board)
        self.node = self.game

        self.drawBoard()

    @pyqtSlot(QWidget)
    def mousePressEvent(self, event):
        """
        Handle left mouse clicks and enable moving chess pieces by
        clicking on a chess piece and then the target square.

        Moves must be made according to the rules of chess because
        illegal moves are suppressed.
        """
        if (event.x() <= self.boardSize) and (event.y() <= self.boardSize):
            if (event.buttons() == Qt.LeftButton):
                if (self.margin < event.x() < self.boardSize -
                        self.margin) and (self.margin < event.y() <
                                          self.boardSize - self.margin):
                    file = int((event.x() - self.margin) / self.squareSize)
                    rank = 7 - int((event.y() - self.margin) / self.squareSize)
                    square = chess.square(file, rank)
                    piece = self.board.piece_at(square)
                    coordinates = "{}{}".format(chr(file + 97), str(rank + 1))
                    if self.pieceToMove[0] is not None:
                        move = chess.Move.from_uci("{}{}".format(
                            self.pieceToMove[1], coordinates))
                        if move in self.board.legal_moves:
                            self.board.push(move)
                            self.node = self.node.add_variation(move)
                        piece = None
                        coordinates = None
                    self.pieceToMove = [piece, coordinates]
                    self.drawBoard()
                    if self.board.is_game_over() == True:
                        self.game.headers["Result"] = self.board.result()
                        pgn = open('test_game.pgn', 'w', encoding='utf-8')
                        exporter = chess.pgn.FileExporter(pgn)
                        self.game.accept(exporter)

    def drawBoard(self):
        """
        Draw a chessboard with the starting position and then redraw
        it for every new move.
        """
        self.boardSvg = self.board._repr_svg_().encode("UTF-8")
        self.drawBoardSvg = self.widgetSvg.load(self.boardSvg)

        return self.drawBoardSvg
Ejemplo n.º 4
0
class MainWindow(QWidget):
    """
    Create a surface for the chessboard.
    """
    def __init__(self):
        """
        Initialize the chessboard.
        """
        super().__init__()

        self.setWindowTitle("Chess GUI")
        self.setGeometry(300, 300, 800, 800)

        self.widgetSvg = QSvgWidget(parent=self)
        self.widgetSvg.setGeometry(10, 10, 600, 600)

        self.boardSize = min(self.widgetSvg.width(),
                             self.widgetSvg.height())
        self.coordinates = True
        self.margin = 0.05 * self.boardSize if self.coordinates else 0
        self.squareSize = (self.boardSize - 2 * self.margin) / 8.0
        self.pieceToMove = [None, None]

        self.board = chess.Board()
        self.drawBoard()

    @pyqtSlot(QWidget)
    def mousePressEvent(self, event):
        """
        Handle left mouse clicks and enable moving chess pieces by
        clicking on a chess piece and then the target square.

        Moves must be made according to the rules of chess because
        illegal moves are suppressed.
        """
        if event.x() <= self.boardSize and event.y() <= self.boardSize:
            if event.buttons() == Qt.LeftButton:
                if self.margin < event.x() < self.boardSize - self.margin and self.margin < event.y() < self.boardSize - self.margin:
                    file = int((event.x() - self.margin) / self.squareSize)
                    rank = 7 - int((event.y() - self.margin) / self.squareSize)
                    square = chess.square(file, rank) 
                    piece = self.board.piece_at(square)
                    coordinates = "{}{}".format(chr(file + 97), str(rank + 1))
                    if self.pieceToMove[0] is not None:
                        move = chess.Move.from_uci("{}{}".format(self.pieceToMove[1], coordinates))
                        if move in self.board.legal_moves:
                            self.board.push(move)
                            self.setWindowTitle("Ai making move")
                            time1=time.time()
                            from aiPlayer import AiPlayer
                            a = AiPlayer()
                            a.minimax(self.board)
                            time2=time.time()
                            print('Ai move took {:.3f} seconds'.format(time2-time1))
                            self.setWindowTitle("Chess GUI")
                        piece = None
                        coordinates = None
                    self.pieceToMove = [piece, coordinates]
                    self.drawBoard()

    def drawBoard(self):
        """
        Draw a chessboard with the starting position and then redraw
        it for every new move.
        """
        self.boardSvg = self.board._repr_svg_().encode("UTF-8")
        self.drawBoardSvg = self.widgetSvg.load(self.boardSvg)

        return self.drawBoardSvg
Ejemplo n.º 5
0
class MainWindow(QWidget):
    """
    Create a surface for the chessboard.
    """
    def __init__(self):
        """
        Initialize the chessboard.
        """
        super().__init__()

        self.setWindowTitle("DeepChess")
        self.setGeometry(300, 300, 800, 800)

        self.widgetSvg = QSvgWidget(parent=self)
        self.widgetSvg.setGeometry(10, 10, 600, 600)

        self.label = QLabel('---', parent=self)
        self.label.setGeometry(10, 600, 600, 100)

        self.boardSize = min(self.widgetSvg.width(), self.widgetSvg.height())
        self.coordinates = True
        self.margin = 0.05 * self.boardSize if self.coordinates else 0
        self.squareSize = (self.boardSize - 2 * self.margin) / 8.0
        self.playerMove = True

        self.engine = DeepChess('b')
        #self.board = chess.Board()
        self.pieceToMove = [None, None]
        self.updateBoard()

    @pyqtSlot(QWidget)
    def mousePressEvent(self, event):
        """
        Handle left mouse clicks and enable moving chess pieces by
        clicking on a chess piece and then the target square.

        Moves must be made according to the rules of chess because
        illegal moves are suppressed.
        """
        if self.playerMove and event.x() <= self.boardSize and event.y(
        ) <= self.boardSize:
            if event.buttons() == Qt.LeftButton:
                if self.margin < event.x(
                ) < self.boardSize - self.margin and self.margin < event.y(
                ) < self.boardSize - self.margin:
                    file = int((event.x() - self.margin) / self.squareSize)
                    rank = 7 - int((event.y() - self.margin) / self.squareSize)
                    square = chess.square(file, rank)
                    piece = self.engine.board.piece_at(square)
                    coordinates = "{}{}".format(chr(file + 97), str(rank + 1))
                    if self.pieceToMove[0] is not None and self.pieceToMove[
                            1] != coordinates:
                        move = chess.Move.from_uci("{}{}".format(
                            self.pieceToMove[1], coordinates))
                        if move in self.engine.board.legal_moves:
                            self.engine.board.push(move)
                            if self.engine.board.is_check():
                                self.label.setText("Check!")
                            self.playerMove = False
                            # start timer
                            self.label.setText('DeepChess evaluating move...')
                            QTimer.singleShot(200, self.deepchess_evaluate)
                        piece = None
                        coordinates = None
                    self.pieceToMove = [piece, coordinates]
                    self.updateBoard()
                else:
                    # Envoke the paint event.
                    #self.update()
                    self.updateBoard()
        else:
            QWidget.mousePressEvent(self, event)

    #@pyqtSlot(QWidget)
    #def paintEvent(self, event):
    def updateBoard(self):
        """
        Draw a chessboard with the starting position and then redraw
        it for every new move.
        """
        self.boardSvg = chess.svg.board(board=self.engine.board,
                                        size=self.boardSize).encode("UTF-8")
        self.widgetSvg.load(self.boardSvg)
        if self.playerMove:
            self.label.setText('player move: {}-{}'.format(
                self.pieceToMove[0], self.pieceToMove[1]))

    def deepchess_evaluate(self):
        self.engine.evaluate()
        self.playerMove = True
        self.updateBoard()
Ejemplo n.º 6
0
class ScalableButton(QPushButton):
    def __init__(self, parent):
        QPushButton.__init__(self, parent)

        self.fImageNormal = None
        self.fImageDown = None
        self.fImageHover = None
        self.fImageRect = QRectF()
        self.fIsHovered = False
        self.fTopText = ""
        self.fTopTextColor = QColor()
        self.fTopTextFont = QFont()
        self.setText("")

    def setPixmaps(self, normal, down, hover):
        self.fImageNormal = QPixmap()
        self.fImageDown = QPixmap()
        self.fImageHover = QPixmap()
        self._loadImages(normal, down, hover)

    def setSvgs(self, normal, down, hover):
        self.fImageNormal = QSvgWidget()
        self.fImageDown = QSvgWidget()
        self.fImageHover = QSvgWidget()
        self._loadImages(normal, down, hover)

    def _loadImages(self, normal, down, hover):
        self.fImageNormal.load(normal)
        self.fImageDown.load(down)
        self.fImageHover.load(hover)

        if isinstance(self.fImageNormal, QPixmap):
            width = self.fImageNormal.width()
            height = self.fImageNormal.height()
        else:
            width = self.fImageNormal.sizeHint().width()
            height = self.fImageNormal.sizeHint().height()

        self.fImageRect = QRectF(0, 0, width, height)

        self.setMinimumSize(width, height)
        self.setMaximumSize(width, height)

    def setTopText(self, text, color, font):
        self.fTopText = text
        self.fTopTextColor = color
        self.fTopTextFont = font

    def enterEvent(self, event):
        self.fIsHovered = True
        QPushButton.enterEvent(self, event)

    def leaveEvent(self, event):
        self.fIsHovered = False
        QPushButton.leaveEvent(self, event)

    def paintEvent(self, event):
        painter = QPainter(self)
        event.accept()

        if self.fImageNormal is None:
            return

        if isinstance(self.fImageNormal, QPixmap):
            self.paintEventPixmap(painter)
        else:
            self.paintEventSvg(painter)

        if not self.fTopText:
            return

        painter.save()
        painter.setPen(self.fTopTextColor)
        painter.setBrush(self.fTopTextColor)
        painter.setFont(self.fTopTextFont)
        painter.drawText(QPointF(10, 16), self.fTopText)
        painter.restore()

    def paintEventPixmap(self, painter):
        if not self.isEnabled():
            painter.save()
            painter.setOpacity(0.2)
            painter.drawPixmap(self.fImageRect, self.fImageNormal,
                               self.fImageRect)
            painter.restore()

        elif self.isChecked() or self.isDown():
            painter.drawPixmap(self.fImageRect, self.fImageDown,
                               self.fImageRect)

        elif self.fIsHovered:
            painter.drawPixmap(self.fImageRect, self.fImageHover,
                               self.fImageRect)

        else:
            painter.drawPixmap(self.fImageRect, self.fImageNormal,
                               self.fImageRect)

    def paintEventSvg(self, painter):
        if not self.isEnabled():
            painter.save()
            painter.setOpacity(0.2)
            self.fImageNormal.renderer().render(painter, self.fImageRect)
            painter.restore()

        elif self.isChecked() or self.isDown():
            self.fImageDown.renderer().render(painter, self.fImageRect)

        elif self.fIsHovered:
            self.fImageHover.renderer().render(painter, self.fImageRect)

        else:
            self.fImageNormal.renderer().render(painter, self.fImageRect)