Георги обнови решението на 28.11.2022 23:26 (преди почти 2 години)
+from re import findall
+
+ROW_TO_IDX_MAPPING = {
+ '1': 7,
+ '2': 6,
+ '3': 5,
+ '4': 4,
+ '5': 3,
+ '6': 2,
+ '7': 1,
+ '8': 0
+}
+
+COLUMN_TO_IDX_MAPPING = {
+ 'A': 0,
+ 'B': 1,
+ 'C': 2,
+ 'D': 3,
+ 'E': 4,
+ 'F': 5,
+ 'G': 6,
+ 'H': 7
+}
+
+PIECE_TO_SCORE_MAPPING = {
+ 'r': 5,
+ 'n': 3,
+ 'b': 3,
+ 'q': 9,
+ 'k': 4,
+ 'p': 1
+}
+
+
+def locate_symbol(strings, symbol):
Добре е тази и останалите функции по-долу да са в класа, който ги използва.
+ r = -1
За всички променливи бих използвал малко по-описателни имена. В момента имаш r
, c
, res
, idx
.
+ c = -1
+
+ for idx, str in enumerate(strings):
+ res = str.find(symbol)
+
+ if res != -1:
+ r = idx
+ c = res
+ break
+
+ return r, c
+
+
+def translated_fen(fen):
+ rows = fen.split('/')
+
+ translated_rows = [''.join(
+ [c.replace(c, '-'*int(c)) if c.isdigit() else c for c in row]) for row in rows]
+
+ return '/'.join(translated_rows)
+
+
+def kings_are_unique(fen):
+ white_kings_count = fen.count('K')
+ black_kings_count = fen.count('k')
+
+ if white_kings_count != 1 or black_kings_count != 1:
return white_kings_count == 1 and black_kings_count == 1
+ return False
+
+ return True
+
+
+def kings_are_neighbors(fen):
+ rows = translated_fen(fen).split('/')
+
+ white_r, white_c = locate_symbol(rows, 'K')
+ black_r, black_c = locate_symbol(rows, 'k')
+
+ if white_r == black_r and white_c in (black_c - 1, black_c + 1):
+ return True
+
+ if white_r in (black_r - 1, black_r + 1) and white_c in (black_c - 1, black_c, black_c + 1):
+ return True
+
+ return False
+
+
+def pawns_are_on_allowed_rows(fen):
+ rows = translated_fen(fen).split('/')
+
+ if ('P' in rows[0] or 'p' in rows[0] or 'P' in rows[7] or 'p' in rows[7]):
+ return False
+
+ return True
+
+
+class ChessException(Exception):
+ def __init__(self, message):
Можеш да минеш и само с един pass
в тялото на класа, защото този инициализатор реално не прави нищо.
+ self._message = message
+ super().__init__(self._message)
+
+
+class ChessScore:
+ def __init__(self, pieces):
+ self._score = 0
+
+ for piece in pieces:
+ self._score += PIECE_TO_SCORE_MAPPING[piece]
+
+ def __int__(self):
+ return self._score
+
+ def __lt__(self, other):
+ if self._score < other._score:
return self._score < other._score
. Подобно на това, всички методи надолу могат да се направят доста по-компактни.
Благодаря за коментарите! Мисля, че адресирах всички от тях. :)
+ return True
+
+ return False
+
+ def __le__(self, other):
+ if self._score <= other._score:
+ return True
+
+ return False
+
+ def __eq__(self, other):
+ if self._score == other._score:
+ return True
+
+ return False
+
+ def __ge__(self, other):
+ if self._score >= other._score:
+ return True
+
+ return False
+
+ def __gt__(self, other):
+ if self._score > other._score:
+ return True
+
+ return False
+
+ def __ne__(self, other):
+ if self._score != other._score:
+ return True
+
+ return False
+
+ def __add__(self, other):
+ return self._score + other._score
+
+ def __sub__(self, other):
+ return self._score - other._score
+
+
+class ChessPosition:
+ def __init__(self, fen):
+ if not kings_are_unique(fen):
+ raise ChessException('kings')
+
+ if kings_are_neighbors(fen):
+ raise ChessException('kings')
+
+ if not pawns_are_on_allowed_rows(fen):
+ raise ChessException('pawns')
+
+ self._fen = fen
+
+ def __str__(self):
+ return self._fen
+
+ def __len__(self):
+ count = 0
+
+ for symbol in self._fen:
+ if symbol.isalpha():
+ count += 1
+
+ return count
+
+ def __getitem__(self, position):
+ column_idx = COLUMN_TO_IDX_MAPPING[position[0]]
+ row_idx = ROW_TO_IDX_MAPPING[position[1]]
+
+ translated = translated_fen(self._fen).split('/')
+ piece = translated[row_idx][column_idx]
+
+ return piece if piece != '-' else None
+
+ def get_white_score(self):
+ white_pieces = findall(r'[RNBQKP]', self._fen)
+ return ChessScore([symbol.lower() for symbol in white_pieces])
+
+ def get_black_score(self):
+ black_pieces = findall(r'[rnbqkp]', self._fen)
+ return ChessScore(black_pieces)
+
+ def white_is_winning(self):
+ if self.get_white_score() > self.get_black_score():
+ return True
+
+ return False
+
+ def black_is_winning(self):
+ if self.get_black_score() > self.get_white_score():
+ return True
+
+ return False
+
+ def is_equal(self):
+ if self.get_white_score() == self.get_black_score():
+ return True
+
+ return False