def in_board(self, coordinate: Coordinate) -> bool: """ returns whether a coordinate is within the bounds of the board arguments: coordinate -- coordinate to check """ return (coordinate.get_rank() >= 0 and coordinate.get_file() >= 0 and coordinate.get_rank() < self.HEIGHT and coordinate.get_file() < self.WIDTH)
def get_diagonal_moves(self, piece: Piece, board: List[List[Piece]]) -> List[Move]: """ returns a list of all diagonal moves arguments: piece -- piece to generate moves board -- board to validate moves """ if piece.piece_type != Type.BISHOP and piece.piece_type != Type.QUEEN: return [] directions: List[Tuple[int, int]] = [(1, 1), (-1, 1), (-1, -1), (1, -1)] moves: List[Move] = [] for direction in directions: destination: Coordinate = Coordinate( piece.coordinate.get_rank() + direction[0], piece.coordinate.get_file() + direction[1], ) while self.in_board(destination): moves.append( Move(piece.coordinate, destination, self.piece_at(destination, board))) if self.piece_at(destination, board): break destination = Coordinate( destination.get_rank() + direction[0], destination.get_file() + direction[1], ) return moves
def piece_at(self, coordinate: Coordinate, board: List[List[Piece]]) -> Union[Piece, None]: """ returns a reference to the piece at a specified coordinate, if no piece is present returns None arguments: coordinate -- coordinate to check board -- board to check for piece in """ if not self.in_board(coordinate): return None else: return board[coordinate.get_rank()][coordinate.get_file()]
def get_pawn_moves(self, piece: Piece, board: List[List[Piece]]) -> List[Move]: """ returns a list of all pawn moves arguments: piece -- piece to generate moves board -- board to validate moves """ if piece.piece_type != Type.PAWN: return [] direction: int = 1 if piece.color == Color.WHITE else -1 moves: List[Move] = [] # Add one square move destination: Coordinate = Coordinate( piece.coordinate.get_rank() + 1 * direction, piece.coordinate.get_file()) if self.in_board(destination) and not self.piece_at( destination, board): if (piece.color == Color.WHITE and destination.get_rank() == self.HEIGHT - 1) or (piece.color == Color.BLACK and destination.get_rank() == 0): moves.append( Move(piece.coordinate, destination, False, MoveType.N_PROMO)) moves.append( Move(piece.coordinate, destination, False, MoveType.B_PROMO)) moves.append( Move(piece.coordinate, destination, False, MoveType.R_PROMO)) moves.append( Move(piece.coordinate, destination, False, MoveType.Q_PROMO)) else: moves.append(Move(piece.coordinate, destination)) # Add two square move destination = Coordinate( piece.coordinate.get_rank() + 2 * direction, piece.coordinate.get_file()) if (not piece.moved and self.in_board(destination) and not self.piece_at(destination, board) and ((piece.coordinate.get_rank() == 1 and piece.color == Color.WHITE) or (piece.coordinate.get_rank() == self.HEIGHT - 2 and piece.color == Color.BLACK))): moves.append( Move(piece.coordinate, destination, False, MoveType.DOUBLE)) # Add capturing moves (default and en passant) for offset in [-1, 1]: destination = Coordinate( piece.coordinate.get_rank() + 1 * direction, piece.coordinate.get_file() + offset, ) # Add en passant moves if (self.in_board(destination) and self.en_passant_target and destination == self.en_passant_target): moves.append( Move(piece.coordinate, destination, False, MoveType.EN_PASSANT)) # Add default capturing moves elif self.in_board(destination) and self.piece_at( destination, board): if (piece.color == Color.WHITE and destination.get_rank() == self.HEIGHT - 1) or (piece.color == Color.BLACK and destination.get_rank() == 0): moves.append( Move(piece.coordinate, destination, True, MoveType.N_PROMO)) moves.append( Move(piece.coordinate, destination, True, MoveType.B_PROMO)) moves.append( Move(piece.coordinate, destination, True, MoveType.R_PROMO)) moves.append( Move(piece.coordinate, destination, True, MoveType.Q_PROMO)) else: moves.append(Move(piece.coordinate, destination, True)) return moves