Георги обнови решението на 29.11.2022 01:17 (преди почти 3 години)
+white_piece_points = {
+    'R': 5,
+    'N': 3,
+    'B': 3,
+    'Q': 9,
+    'K': 4,
+    'P': 1
+}
+
+black_piece_points = {
+    'r': 5,
+    'n': 3,
+    'b': 3,
+    'q': 9,
+    'k': 4,
+    'p': 1
+}
+
+
+class ChessException(Exception):
Можеш да минеш и само с един pass в тялото на класа, защото този инициализатор реално не прави нищо.
+
+    def __init__(self, message: str = "Raised a chess excpetion"):
+        super().__init__(message)
+
+
+class ChessPosition():
Скобите тук са излишни.
+
+    def __init__(self, FEN):
Прието е главните букви да значат константа, така че аргументът ти трябва да е с малки букви.
+        board = self._init_board(FEN)
+
+        if not self._is_king_init_valid(FEN, board):
+            raise ChessException('kings')
+
+        if not self._is_pawn_init_valid(board):
+            raise ChessException('pawns')
+
+        self._board = board
+        self._FEN = FEN
+        
+    def _init_board(self, FEN):
+
+        board = []
+        rows = FEN.split('/')
+
+        for row in reversed(rows):
+            row_to_append = []
+            for symbol in row:
+                if symbol >= '1' and symbol <= '8':
+                    row_to_append += ['0'] * int(symbol)
+                else:
+                    row_to_append.append(symbol)
+            board.append(row_to_append)
+                
+        return board
+
+    def _is_king_init_valid(self, FEN, board):
+
+        if FEN.count('k') != 1 or FEN.count('K') != 1:
+            return False
+        
+        black_king_row, black_king_col = (0, 0)
+        for row_number, row in enumerate(board):
+            if 'K' in row:
+                column_number = row.index('K')
+                black_king_row, black_king_col = row_number, column_number
+                break
+
+        for i in [-1, 0, 1]:
+            for j in [-1, 0, 1]:
+                if (black_king_row + i > 7) or (
Отварящите скоби трябва да са на новия ред при подобни пренасяния.
+                    black_king_row + i < 0) or (
+                    black_king_col + j > 7) or (
+                    black_king_col + j < 0) or (
+                    i == 0 and j == 0):
+                    continue
+                if board[black_king_row + i][black_king_col + j] == 'k':
+                    return False
+
+        return True
+
+    def _is_pawn_init_valid(self, board):
+        
+        for pawn in ['p', 'P']:
+            if pawn in board[0] or pawn in board[7]:
+                return False
+
+        return True
+
+    def get_white_score(self):
+
+        score = 0
+        
+        for row in range(8):
+            for col in range(8):
+                piece = self._board[row][col]
+                if piece in white_piece_points:
+                    score += white_piece_points[piece]
+        
+        return score
+
+    def get_black_score(self):
+
+        score = 0
+        
+        for row in range(8):
+            for col in range(8):
+                piece = self._board[row][col]
+                if piece in black_piece_points:
+                    score += black_piece_points[piece]
+        
+        return score
+
+    def white_is_winning(self):
+        
+        return self.get_white_score() > self.get_black_score()
+
+    def black_is_winning(self):
+        
+        return self.get_black_score() > self.get_white_score()
+
+    def is_equal(self):
+        
+        return self.get_black_score() == self.get_white_score()
+
+    def __repr__(self):
+        return self._FEN
+
+    def __len__(self):
+        count_pieces = 0
+        for row in range(8):
+            for col in range(8):
+                piece = self._board[row][col]
+                if piece != '0':
+                    count_pieces += 1
+        return count_pieces
+
+    def __getitem__(self, position):
+        col = ord(position[0]) - ord('A')
+        row = int(position[1]) - 1
+        piece = self._board[row][col]
+        return None if piece == '0' else piece
+
+
+class ChessScore():
+
+    def __init__(self, pieces):
+        self._pieces = pieces
+
+    def _is_white_piece(self, piece):
+        return piece in white_piece_points
+
+    def _is_black_piece(self, piece):
+        return piece in black_piece_points
+
+    def _calculate_score(self):
Няма причина да изчисляваш черните и белите отделно. Този клас получава списък от фигури с малки букви.
+        white_pieces_scores = [white_piece_points[piece] for piece in filter(self._is_white_piece, self._pieces)]
+        black_pieces_scores = [black_piece_points[piece] for piece in filter(self._is_black_piece, self._pieces)]
+        return sum(white_pieces_scores) + sum(black_pieces_scores)
+
+    def __eq__(self, other):
+        return self._calculate_score() == other._calculate_score()
Вместо всяки път да изчисляваш наново, по-добре изчисли при инициализация и запази в атрибут на инстанцията.
+
+    def __lt__(self, other):
+        return self._calculate_score() < other._calculate_score()
+
+    def __le__(self, other):
+        return self._calculate_score() <= other._calculate_score()
+
+    def __gt__(self, other):
+        return self._calculate_score() > other._calculate_score()
+
+    def __ge__(self, other):
+        return self._calculate_score() >= other._calculate_score()
+
+    def __add__(self, other):
+        return self._calculate_score() + other._calculate_score()
+
+    def __sub__(self, other):
+        return self._calculate_score() - other._calculate_score()
Не знам дали и друг път не съм го коментирал, но имаш доста излишни празни редове, които нарушават логическата обособеност на отделните методи и кодът се следи трудно.

Можеш да минеш и само с един
passв тялото на класа, защото този инициализатор реално не прави нищо.