예제 #1
0
    def place_piece(self, piece, square):
        """ Places piece on board at square specified
            Input piece can be str(K) or Piece
            Input square can be one of:
                - str('E4'),
                - tuple of array coordinates((0,2))
                - Piece with file and rank properties """
        if type(square) is str:
            file = FILE[square[0]]
            rank = RANK[square[1]]
        elif type(square) is Piece:
            file = square.file
            rank = square.rank
        else:
            rank = square[0]
            file = square[1]

        if type(piece) is str:
            piece = Piece(piece, rank=rank, file=file)
        else:
            piece.rank = rank
            piece.file = file

        self.BOARD[rank][file] = piece
예제 #2
0
파일: game.py 프로젝트: mrdavidoneill/chess
    def get_possible_squares(self, piece=None, square=None):
        """ Returns a list of possible squares availale to move to.
            Input needed: One of: piece or square, or both
            piece can be one of: string - 'K'
                                 Piece - Piece('K')
            square can be one of: string - 'E4'
                                  array coordinates - [3,5]
            Usage:  get_possible_squares(piece='K', square='E4')
                    get_possible_squares(square='E4')
                    get_possible_squares(piece=<Piece>)  // Piece with .file and .rank
                    get_possible_squares(square=<Piece>) // Piece with .file and .rank
            """
        #print(f"piece:{piece}, square:{square}")

        # if both piece and square are None
        if not piece and not square:
            return None

        # piece can be string or Piece object or empty
        if type(piece) is str:
            piece_obj = Piece(piece)
        elif type(piece) is Piece:
            piece_obj = piece
        else:
            piece_obj = self.board.BOARD[RANK[square[1]]][FILE[square[0]]]

        # square can be empty, string or array coordinates
        if not square:
            file = piece_obj.file
            rank = piece_obj.rank
        elif type(square) is str:
            file = FILE[square[0]]
            rank = RANK[square[1]]
        else:
            file = square[1]
            rank = square[0]

        # If no piece enterred and square is EMPTY:
        if not piece and self.board.BOARD[rank][file] is EMPTY:
            return None

        # If piece is newly created without file and rank
        if not piece_obj.file:
            piece_obj.file = file
            piece_obj.rank = rank

        # If not active colour
        if piece_obj.colour is not self.whose_move():
            return None

        #print(f"get_possible_squares({piece_obj._id} on {Board.square_name((piece_obj.rank, piece_obj.file))})")

        # Loop through directions of piece movements
        possible_squares = []
        for movement in piece_obj.movements:
            distance = 0
            possible_file = file
            possible_rank = rank
            max_distance = piece_obj.max_distance

            # Loop until range of piece is exceeded
            while distance != max_distance:

                # If pawn on starting position
                if piece_obj.name is PAWN:
                    if piece_obj.colour == WHITE and rank == 1 or \
                       piece_obj.colour == BLACK and rank == 6:
                        max_distance = 2

                # copy board for testing in_check conditions
                possible_board = Board(self.board.BOARD)
                possible_file += movement[1]
                possible_rank += movement[0]

                # If passed edge of board
                if possible_file < 0 or possible_file > 7 or \
                   possible_rank < 0 or possible_rank > 7:
                    #print("Can't move: off edge of board")
                    break

                possible_square = possible_board.BOARD[possible_rank][
                    possible_file]

                # If square is occupied
                if possible_square is not EMPTY:
                    # If own piece in the way
                    if possible_square.colour == piece_obj.colour:
                        break
                    # If opposition piece in the way
                    else:
                        # If moving piece is a pawn
                        if piece_obj.name == PAWN:
                            # If forward pawn move
                            if movement in piece_obj.normal_movements:
                                break

                        # Test for putting self in check
                        possible_board.remove_piece((rank, file))
                        possible_board.place_piece(square=possible_square,
                                                   piece=piece_obj._id)

                        if self.in_check(board=possible_board,
                                         colour=piece_obj.colour):
                            break
                        # Can capture piece
                        else:
                            possible_squares.append(
                                [possible_rank, possible_file])
                            break

                # Square not occupied
                else:
                    # If pawn
                    if piece_obj.name == PAWN:
                        # Can't move diagonal if not capturing unless en-passant
                        if movement in piece_obj.capture_movements:
                            if not self.en_passant_sq:
                                break
                            elif self.en_passant_sq and \
                                    Board.square_name((possible_rank, possible_file)) != self.en_passant_sq.upper():
                                break

                        # If not on 2nd rank(WHITE) or 7th rank(BLACK): Can't move two squares
                        if piece_obj.colour == WHITE and rank != 1 and distance == 1 or \
                           piece_obj.colour == BLACK and rank != 6 and distance == 1:
                            break

                    # If Castling King
                    if piece_obj.name is KING and piece_obj.colour is WHITE:
                        if movement is E and self.castling_rights[0]:
                            if max_distance == 1:
                                max_distance = 2
                        if movement is W and self.castling_rights[1]:
                            if max_distance == 1:
                                max_distance = 2
                    elif piece_obj.name is KING and piece_obj.colour is BLACK:
                        if movement is E and self.castling_rights[2]:
                            if max_distance == 1:
                                max_distance = 2
                        if movement is W and self.castling_rights[3]:
                            if max_distance == 1:
                                max_distance = 2

                    # Test for putting self in check
                    possible_board.remove_piece((rank, file))
                    possible_board.place_piece(square=(possible_rank,
                                                       possible_file),
                                               piece=piece_obj._id)
                    if not self.in_check(board=possible_board,
                                         colour=piece_obj.colour):
                        possible_squares.append([possible_rank, possible_file])
                    else:
                        # Can't castle through a check
                        if piece_obj.name is KING:
                            max_distance = 1

                distance += 1
        if not possible_squares:
            return None
        else:
            return possible_squares