Айше обнови решението на 29.11.2022 13:25 (преди почти 3 години)
+import string
+
+PIECES = [
+    'R',
+    'N',
+    'B',
+    'Q',
+    'K',
+    'P'
+]
+
+ROW_TO_INDEX = {
+    '1': 7,
+    '2': 6,
+    '3': 5,
+    '4': 4,
+    '5': 3,
+    '6': 2,
+    '7': 1,
+    '8': 0
+}
+
+COLUMN_TO_INDEX = {
+    'A': 0,
+    'B': 1,
+    'C': 2,
+    'D': 3,
+    'E': 4,
+    'F': 5,
+    'G': 6,
+    'H': 7
+}
+
+PIECES_TO_SCORE = {
+    'r': 5,
+    'n': 3,
+    'b': 3,
+    'q': 9,
+    'k': 4,
+    'p': 1
+}
+
+class ChessException(Exception):
Можеш да минеш и само с един pass в тялото на класа, защото този инициализатор реално не прави нищо.
+    def __init__(self, message):
+        self.message = message
+        super().__init__(self.message)
+
+
+class ChessPosition:
+    def __init__(self, fen):
+        board = self._generate_board(fen)
+        self._fen = fen
+        self._board = board
+        self._validate()
+
+    def __str__(self):
+        return self._fen
+  
+    def __len__(self):
+        return len(list(filter(lambda symbol: symbol != '-' , ''.join(self._board))))
Не мисля, че е нужно да join-ваш. self._board е итерабъл така или иначе. Дано не греша, но ми се струва, че е едномерен масив и ще е все едно.
Aко не го джойнна, тъй като е масив от стрингове няма ли да итерирам по самите стрингове (което в моя случай отговаря на ред от дъската)? В случая аз искам да итерирам по символите, т.е. отделните квадратчета на дъската
+
+    def __getitem__(self, position):
+        column = COLUMN_TO_INDEX[position[0]]
+        row = ROW_TO_INDEX[position[1]]
+    
+        if self._board[row][column] != '-':
+            return self._board[row][column]
+        else:
+            return None
+
+    def _neighbouring_in_column(self, row, column):
Има и по-лесни начини да се справиш с кошийството. Когато отключим решенията, може да погледнеш останалите имплементации.
+        return (
+            column < 7 and
+            self._board[row][column].lower() == self._board[row][column + 1].lower() and
+            self._board[row][column].lower() == 'k'
+        )
+
+    def _neighbouring_in_row(self, row, column):
+        return (
+            row < 7 and
+            self._board[row][column].lower() == self._board[row + 1][column].lower() and
+            self._board[row][column].lower() == 'k'
+        )
+
+    def _neighbouring_in_first_diagonal(self, row, column):
+        return (
+            row < 7 and
+            column < 7 and
+            self._board[row][column].lower() == self._board[row + 1][column + 1].lower() and
+            self._board[row][column].lower() == 'k'
+        )
+
+    def _neighbouring_in_second_diagonal(self, row, column):
+        return (
+            row > 0 and
+            column > 0 and
+            self._board[row][column].lower() == self._board[row - 1][column - 1].lower()
+            and self._board[row][column].lower() == 'k'
+        )
+
+    def _kings_neighbours(self, row, column):
+        return (
+            self._neighbouring_in_column(row, column) or
+            self._neighbouring_in_row(row, column) or
+            self._neighbouring_in_first_diagonal(row, column) or
+            self._neighbouring_in_second_diagonal(row, column)
+        )
+
+    def _invalid_kings_number(self):
+        return self._fen.count('k') != 1 or self._fen.count('K') != 1
+
+    def _invalid_pawns(self):
+        return 'p' in self._board[0] or 'P' in self._board[7]
+  
+    def _validate(self):
+        for row in range(len(self._board)):
+            for column in range(len(self._board[row])):
+                if self._kings_neighbours(row, column):
+                    raise ChessException('kings')
+        
+                elif self._invalid_kings_number():
+                    raise ChessException('kings')
+        
+                elif self._invalid_pawns():
+                    raise ChessException('pawns')
+
+    def _generate_board(self, fen):
+        rows = fen.split('/')
+        return [self._get_row(row) for row in rows]
+    
+    def _get_row(self, row):
+        if len(row) == 8:
+            return row
+    
+        result = ''
+        for symbol in row:
+            if symbol.upper() in PIECES:
+                result += symbol
+            else:
+                result += int(symbol)*'-'
Прието е около * да се слагат интервали.
+    
+        return result
+
+    def get_white_score(self):
+        whites = [symbol.lower() for symbol in list(filter(lambda row: row in string.ascii_uppercase,''.join(self._board)))]
string.ascii_uppercase можеш да замениш с something.isupper()
+        return ChessScore(whites)
+
+    def get_black_score(self):
+        blacks = list(filter(lambda row: row in string.ascii_lowercase, ''.join(self._board)))
+        return ChessScore(blacks)
+
+    def black_is_winning(self):
+        return self.get_black_score() > self.get_white_score()
+
+    def white_is_winning(self):
+        return self.get_white_score() > self.get_black_score()
+
+    def is_equal(self):
+        return self.get_black_score() == self.get_white_score()
+
+
+class ChessScore:
+    def __init__(self, figures):
+        self.score = sum([PIECES_TO_SCORE[figure] for figure in figures])
+
+    def __int__(self):
+        return self.score
+
+    def __lt__(self, other):
+        return self.score < other.score
+    
+    def __le__(self, other):
+        return self.score <= other.score
+
+    def __eq__(self, other):
+        return self.score == other.score
+
+    def __ne__(self, other):
+        return self.score != other.score
+
+    def __gt__(self, other):
+        return self.score > other.score
+
+    def __ge__(self, other):
+        return self.score >= other.score
+    
+    def __add__(self, other):
+        return self.score + other.score
+
+    def __sub__(self, other):
+        return self.score - other.score
+

Можеш да минеш и само с един
passв тялото на класа, защото този инициализатор реално не прави нищо.Не мисля, че е нужно да
join-ваш.self._boardе итерабъл така или иначе. Дано не греша, но ми се струва, че е едномерен масив и ще е все едно.Aко не го джойнна, тъй като е масив от стрингове няма ли да итерирам по самите стрингове (което в моя случай отговаря на ред от дъската)? В случая аз искам да итерирам по символите, т.е. отделните квадратчета на дъската
Има и по-лесни начини да се справиш с кошийството. Когато отключим решенията, може да погледнеш останалите имплементации.