Example #1
0
    def canCastle(self, row, col):
        # the king cannot castle if it has already moved or if it's in check
        if self.hasMoved or self.isInCheck(self.row, self.col):
            return False

        # short castle
        if row == self.row and col == 6:
            # a lot of conditions have to be met: the king and the rook must not have moved,
            # there has to be no piece between the king and the rook and every square between the king and the rook has to be safe from
            # checks from the enemy pieces
            return (board.isEmpty(self.row, 5) and board.isEmpty(self.row, 6)
                    and not board.isEmpty(self.row, 7)
                    and board.getPiece(self.row, 7).hasMoved == False
                    and not self.isInCheck(self.row, 5)
                    and not self.isInCheck(self.row, 6))

        # long castle
        elif row == self.row and col == 2:
            return (board.isEmpty(self.row, 3) and board.isEmpty(self.row, 2)
                    and board.isEmpty(self.row, 1)
                    and not board.isEmpty(self.row, 0)
                    and board.getPiece(self.row, 0).hasMoved == False
                    and not self.isInCheck(self.row, 3)
                    and not self.isInCheck(self.row, 2))

        return False
Example #2
0
    def castle(self, row, col):
        if col == 6:
            board.getPiece(self.row, 7).updateBoard(self.row, 5)
        else:
            board.getPiece(self.row, 0).updateBoard(self.row, 3)

        self.updateBoard(row, col)
Example #3
0
def promote(pos, row, col, color):
    # calculate the position of the rects
    rectDim = 150
    rectRow = None
    rectCol = None
    if pos[0] + rectDim >= height:
        rectRow = pos[0] - rectDim - 1
    else:
        rectRow = pos[0]

    if pos[1] + rectDim >= width:
        rectCol = pos[1] - rectDim - 1
    else:
        rectCol = pos[1]

    rects = []
    imgs = []
    imgRects = []
    # display the rects
    for x in [rectRow, rectRow + int(rectDim / 2) + 1]:
        for y in [rectCol, rectCol + int(rectDim / 2) + 1]:
            rects.append(
                pygame.draw.rect(screen, (255, 255, 255),
                                 (x, y, int(rectDim / 2), int(rectDim / 2))))
    pygame.draw.line(screen, (50, 50, 50),
                     (rectRow + int(rectDim / 2), rectCol),
                     (rectRow + int(rectDim / 2), rectCol + rectDim))
    pygame.draw.line(screen, (50, 50, 50),
                     (rectRow, rectCol + int(rectDim / 2)),
                     (rectRow + rectDim, rectCol + int(rectDim / 2)))

    # display the imgs
    for piece in ["q", "r", "n", "b"]:
        imgs.append(pygame.image.load("imgs/" + color[0] + piece + ".png"))
        imgRects.append(imgs[len(imgs) - 1].get_rect())
        imgRects[len(imgs) - 1].center = rects[len(imgs) - 1].center
        screen.blit(imgs[len(imgs) - 1], imgRects[len(imgs) - 1])

    pygame.display.update()

    # transform the pawn into another piece
    while True:
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONUP:
                if rects[0].collidepoint(event.pos):
                    pieces.Queen(row, col, color)
                    board.getPiece(row, col).draw(screen, width, height)
                    return
                if rects[1].collidepoint(event.pos):
                    pieces.Rook(row, col, color)
                    board.getPiece(row, col).draw(screen, width, height)
                    return
                if rects[2].collidepoint(event.pos):
                    pieces.Knight(row, col, color)
                    board.getPiece(row, col).draw(screen, width, height)
                    return
                if rects[3].collidepoint(event.pos):
                    pieces.Bishop(row, col, color)
                    board.getPiece(row, col).draw(screen, width, height)
                    return
Example #4
0
    def isLegalMove(self, newRow, newCol):

        # if the move is out of bounds, it is not legal
        if newRow < 0 or newRow > 7 or newCol < 0 or newCol > 7:
            return False

        currentRow = self.row
        currentCol = self.col
        piece = board.getPiece(newRow, newCol)

        board.board[newRow][newCol] = self
        board.board[self.row][self.col] = None
        self.row = newRow
        self.col = newCol

        answer = True
        if (self.notation[0] == "w"
                and whiteKing.isInCheck(whiteKing.row, whiteKing.col)
                or self.notation[0] == "b"
                and blackKing.isInCheck(blackKing.row, blackKing.col)):
            answer = False

        board.board[currentRow][currentCol] = self
        board.board[self.row][self.col] = piece
        self.row = currentRow
        self.col = currentCol

        return answer
Example #5
0
    def canMove(self, newRow, newCol):
        # it can't move there if it's not in the moves set
        if not (newRow - self.row, newCol - self.col) in self.moves:
            return False

        # finding out the direction the piece will go, on the x and y axes
        signRow = 0
        signCol = 0
        if self.row != newRow:
            signRow = int(abs(newRow - self.row) / (newRow - self.row))
        if self.col != newCol:
            signCol = int(abs(newCol - self.col) / (newCol - self.col))

        # it can't move if there is a piece between its current and new position
        # we check every single suare between the current and next position, in the direction that we found out earlier
        diff = 0
        while self.row + signRow * diff != newRow or self.col + signCol * diff != newCol:
            diff += 1

            # if there is a piece between the current and next position
            if not board.isEmpty(self.row + signRow * diff,
                                 self.col + signCol * diff):

                # if the piece is exactly on the next position and its color is opposite to this piece's, then the piece can capture it
                if (self.row + signRow * diff == newRow
                        and self.col + signCol * diff == newCol
                        and board.getPiece(
                            newRow, newCol).notation[0] != self.notation[0]):
                    return True

                # otherwise, it can't move there
                return False

        return True
Example #6
0
    def canTakeEnPassant(self, row, col):
        if not board.isEmpty(row, col):
            return False

        # check the position of the pawn and the next position
        if self.notation[0] == "w":
            if row != self.row - 1 or abs(col - self.col) != 1:
                return False
            if board.isEmpty(self.row, col) or board.getPiece(
                    self.row, col).notation != "bp" or not board.getPiece(
                        self.row, col).hasJustMovedTwo:
                return False
        else:
            if row != self.row + 1 or abs(col - self.col) != 1:
                return False
            if board.isEmpty(self.row, col) or board.getPiece(
                    self.row, col).notation != "wp" or not board.getPiece(
                        self.row, col).hasJustMovedTwo:
                return False

        otherPawn = board.getPiece(self.row, col)
        currentRow = self.row
        currentCol = self.col

        board.board[self.row][col] = None
        board.board[row][col] = self
        self.row = row
        self.col = col
        valid = True

        # if the move puts the pawn's king in check, it's not valid
        if (self.notation[0] == "w"
                and whiteKing.isInCheck(whiteKing.row, whiteKing.col)
                or self.notation[0] == "b"
                and blackKing.isInCheck(blackKing.row, blackKing.col)):
            valid = False

        self.row = currentRow
        self.col = currentCol
        board.board[self.row][self.col] = self
        board.board[row][col] = None
        board.board[self.row][col] = otherPawn

        return valid
Example #7
0
    def canMove(self, newRow, newCol):
        if (newRow - self.row, newCol - self.col) not in self.moves:
            return False

        if (not board.isEmpty(newRow, newCol)) and board.getPiece(
                newRow, newCol).notation[0] != self.notation[0]:
            return True

        if board.isEmpty(newRow, newCol):
            return True

        return False
Example #8
0
    def canMove(self, newRow, newCol):

        # if it doesn't move in an L shape, the move isn't valid
        if (newRow - self.row, newCol - self.col) not in self.moves:
            return False

        #if there is a piece on that square, it can capture it if it's of a different color, or otherwise it can't move there
        if not board.isEmpty(newRow, newCol):
            if board.getPiece(newRow, newCol).notation[0] != self.notation[0]:
                return True
            else:
                return False

        return True
Example #9
0
    def updateBoard(self, newRow, newCol):
        global fiftyMove
        self.hasMoved = True

        # increment the fifty-move rule counter or reset it if a pawn moves or a piece is captured
        if board.getPiece(newRow,
                          newCol) is not None or self.notation[1] == "p":
            fiftyMove = 0
            board.positionsDict.clear()
        else:
            fiftyMove += 1

        board.board[newRow][newCol] = self
        board.board[self.row][self.col] = None
        self.row = newRow
        self.col = newCol

        return True
Example #10
0
    def canMove(self, newRow, newCol):

        # if the piece can't attack nor move there, it is not valid
        if ((newRow - self.row, newCol - self.col) not in self.moves) and (
            (newRow - self.row, newCol - self.col) not in self.attackMoves):
            return False

        # if that square is not empty
        if not board.isEmpty(newRow, newCol):

            # the pawn can capture the piece on that square if the square is in the attackMoves set
            # and the piece is not of the same color
            if board.getPiece(newRow, newCol).notation[0] != self.notation[0]:
                if (newRow - self.row, newCol - self.col) in self.attackMoves:
                    return True

            # otherwise, the piece is of the same color as this pawn or the pawn is just not allowed to go there
            return False

        # if it is in the moves set
        if (newRow - self.row, newCol - self.col) in self.moves:

            # after the first move, the 2-square move is not valid anymore
            if self.notation[0] == "w" and self.col == 6:
                self.moves = {(-1, 0)}
            elif self.notation[0] == "b" and self.col == 1:
                self.moves = {(1, 0)}

            # if the pawn wants to move 2 squares, there have to be no pieces between those squares
            if abs(self.row - newRow) == 2:
                if (self.notation[0] == "w"
                        and not board.isEmpty(self.row - 1, self.col)
                        or self.notation[0] == "b"
                        and not board.isEmpty(self.row + 1, self.col)):
                    return False
                else:
                    self.hasJustMovedTwo = True

            return True

        return False
Example #11
0
def gameLoop():
    global done
    global turn

    done = False
    turn = "w"
    pieces.fiftyMove = 0

    pieces.initGame()
    currentBoard = board.getString(turn)
    board.positionsDict[currentBoard] = 1

    while not done:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

            # if the user presses the mouse
            if event.type == pygame.MOUSEBUTTONDOWN:

                # get the row and column the mouse is located in
                currentRow = math.floor(event.pos[1] / int(height / 8))
                currentCol = math.floor(event.pos[0] / int(width / 8))

                # if there is a piece that the user clicks on and it is its turn, make it the current piece
                piece = board.getPiece(currentRow, currentCol)
                if piece is not None and turn == piece.notation[0]:
                    pieces.currentPiece = piece

            # if the user releases the mouse, try to move the piece and switch the turn if the move is successful
            if event.type == pygame.MOUSEBUTTONUP and pieces.currentPiece is not None:
                nextRow = math.floor(event.pos[1] / int(height / 8))
                nextCol = math.floor(event.pos[0] / int(width / 8))

                if pieces.currentPiece.move(nextRow, nextCol):
                    # promotion of a pawn
                    if pieces.currentPiece.notation[
                            1] == "p" and pieces.currentPiece.row in [0, 7]:
                        promote(event.pos, pieces.currentPiece.row,
                                pieces.currentPiece.col, turn)

                    if turn == "w":
                        turn = "b"
                    else:
                        turn = "w"

                    # remove the hasJustMovedTwo attribute if the enemy turn passed and they can't capture the pawn en passant anymore
                    for r in board.board:
                        for piece in r:
                            if piece is None or piece.notation != (turn + "p"):
                                continue
                            piece.hasJustMovedTwo = False

                    # update the positions dictionary
                    currentBoard = board.getString(turn)
                    if currentBoard in board.positionsDict:
                        board.positionsDict[currentBoard] += 1
                    else:
                        board.positionsDict[currentBoard] = 1

                # the current piece should be none if the mouse is released
                pieces.currentPiece = None

            # draw the squares of the board
            colors = [(232, 235, 239), (125, 135, 150)]
            for i in range(0, 8):
                for j in range(0, 8):
                    # change the color based on the col+row mod 2
                    pygame.draw.rect(screen, colors[(i + j) % 2],
                                     (i * int(width / 8), j * int(height / 8),
                                      int(width / 8), int(height / 8)))

            # highlight the square of the king with red if it is in check
            for king in [pieces.whiteKing, pieces.blackKing]:
                if king.isInCheck(king.row, king.col):
                    pygame.draw.rect(
                        screen, (255, 0, 0),
                        (king.col * int(width / 8), king.row * int(height / 8),
                         int(width / 8), int(height / 8)))

            # display the pieces in their respective squares
            for row in board.board:
                for piece in row:
                    if piece is None:
                        continue
                    if pieces.currentPiece != piece:
                        piece.draw(screen, width, height)

            # display the current piece at the mouse location
            if pieces.currentPiece is not None:
                screen.blit(pieces.currentPiece.img,
                            pieces.currentPiece.imgRect)
                pieces.currentPiece.imgRect.center = pygame.mouse.get_pos()

            checkEndOfGame(currentBoard)

            pygame.display.flip()
            pygame.display.update()