RosettaCodeData/Task/Find-Chess960-starting-position-identifier/Python/find-chess960-starting-position-identifier.py
2023-07-01 13:44:08 -04:00

71 lines
2.1 KiB
Python

# optional, but task function depends on it as written
def validate_position(candidate: str):
assert (
len(candidate) == 8
), f"candidate position has invalide len = {len(candidate)}"
valid_pieces = {"R": 2, "N": 2, "B": 2, "Q": 1, "K": 1}
assert {
piece for piece in candidate
} == valid_pieces.keys(), f"candidate position contains invalid pieces"
for piece_type in valid_pieces.keys():
assert (
candidate.count(piece_type) == valid_pieces[piece_type]
), f"piece type '{piece_type}' has invalid count"
bishops_pos = [index for index,
value in enumerate(candidate) if value == "B"]
assert (
bishops_pos[0] % 2 != bishops_pos[1] % 2
), f"candidate position has both bishops in the same color"
assert [piece for piece in candidate if piece in "RK"] == [
"R",
"K",
"R",
], "candidate position has K outside of RR"
def calc_position(start_pos: str):
try:
validate_position(start_pos)
except AssertionError:
raise AssertionError
# step 1
subset_step1 = [piece for piece in start_pos if piece not in "QB"]
nights_positions = [
index for index, value in enumerate(subset_step1) if value == "N"
]
nights_table = {
(0, 1): 0,
(0, 2): 1,
(0, 3): 2,
(0, 4): 3,
(1, 2): 4,
(1, 3): 5,
(1, 4): 6,
(2, 3): 7,
(2, 4): 8,
(3, 4): 9,
}
N = nights_table.get(tuple(nights_positions))
# step 2
subset_step2 = [piece for piece in start_pos if piece != "B"]
Q = subset_step2.index("Q")
# step 3
dark_squares = [
piece for index, piece in enumerate(start_pos) if index in range(0, 9, 2)
]
light_squares = [
piece for index, piece in enumerate(start_pos) if index in range(1, 9, 2)
]
D = dark_squares.index("B")
L = light_squares.index("B")
return 4 * (4 * (6*N + Q) + D) + L
if __name__ == '__main__':
for example in ["QNRBBNKR", "RNBQKBNR", "RQNBBKRN", "RNQBBKRN"]:
print(f'Position: {example}; Chess960 PID= {calc_position(example)}')