Йоан обнови решението на 28.11.2022 22:46 (преди почти 2 години)
+from itertools import chain
+
+cols = "ABCDEFGH"
+rows = ["1", "2", "3", "4", "5", "6", "7", "8"]
+fig_to_score = {"r": 5, "n": 3, "b": 3, "q": 9, "k": 4, "p": 1}
+
+
+class ChessException(Exception):
+ def __init__(self, message):
Можеш да минеш и само с един pass
в тялото на класа, защото този инициализатор реално не прави нищо.
+ self._message = message
+ super().__init__(self._message)
+
+
+def are_adjacent(f_figure, s_figure):
Би било по-добре това да е в тялото на класа, който го използва.
+ f_col, f_row = [i for i in f_figure]
+ s_col, s_row = [i for i in s_figure]
+
+ if cols.index(f_col) == cols.index(s_col):
+ return rows.index(f_row) in [rows.index(s_row) - 1, rows.index(s_row) + 1]
+
+ if rows.index(f_row) == rows.index(s_row):
+ return cols.index(f_col) in [rows.index(s_col) - 1, rows.index(s_col) + 1]
+
+ return rows.index(f_row) in [rows.index(s_row) - 1, rows.index(s_row) + 1] \
+ and cols.index(f_col) in [cols.index(s_col) - 1, cols.index(s_col) + 1]
+
+
+class ChessPosition:
+ def __init__(self, fen_str):
+ self.fen = fen_str
+ fen_str = fen_str.split("/")
+ self.figures = list(chain(*list(figure for figure in
Доста сложен ред. По-добре да го поразделиш на парчета. Харесва ми, че поне си го разцепил на редове, но все пак едва в повече.
+ list(
+ map(
+ lambda row: list(
+ chain(*list(
+ ["None" for _ in range(int(figure))]
Не знам дали това няма да накара нещо друго да гръмне, но бих използвал None
като сингълтън, а не като стринг. Предполагам после правиш операции върху списъка, оачквайки всичко да е стринг, но в такъв случай бих използвал друг символ - например _
.
+ if figure.isnumeric()
+ else figure for figure in row))),
+ fen_str
+ )))))
+
+ self.positions = {(col + str(row + 1)): self.figures[56 - 8 * row + ind]
Избягвай магически числа като 56. Нямам никаква идея откъде идва това число.
+ for row in range(0, 8)
+ for ind, col in enumerate(cols)
+ }
+
+ kings = [k for k, v in self.positions.items() if v in "Kk"]
+ if len(kings) != 2 or kings[0] == kings[1] or are_adjacent(kings[0], kings[1]):
+ raise ChessException("kings")
+
+ pawns = [k for k, v in self.positions.items() if v in "Pp"]
+ if [pawn for pawn in pawns if pawn[1] in [1, 8]]:
+ raise ChessException("pawns")
+
+ def __len__(self):
+ return len([figure for figure in self.figures if figure != "None"])
+
+ def __getitem__(self, item):
+ return self.positions[item]
+
+ def __repr__(self):
+ return self.fen
+
+ def get_white_score(self):
+ return ChessScore([figure for figure in self.figures if figure.isupper()])
+
+ def get_black_score(self):
+ return ChessScore([figure for figure in self.figures if figure.islower()])
+
+ 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()
+
+
+class ChessScore:
+ def __init__(self, figs):
+ self.score = sum([fig_to_score[fig.lower()] for fig in figs])
+
+ def __add__(self, other):
+ return self.score + other.score
+
+ def __sub__(self, other):
+ return self.score - other.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 __gt__(self, other):
+ return self.score > other.score
+
+ def __ne__(self, other):
+ return self.score != other.score
+
+ def __int__(self):
+ return self.score