Skip to content

Commit

Permalink
Fixed SAN parsing error
Browse files Browse the repository at this point in the history
  • Loading branch information
hrushikeshrv committed Mar 3, 2023
1 parent e44e702 commit 56677df
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 33 deletions.
80 changes: 52 additions & 28 deletions chessengine/bitboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -675,47 +675,71 @@ def move_san(self, move: str, side: str) -> None:
else:
piece_moved = san_piece_map[groups[0].upper()]

end_pos = 2 ** coords_to_pos[groups[3].upper()]
end_pos = 2 ** coords_to_pos[groups[2].upper()]
moves = self.get_moves(side, piece_moved)

if groups[1] is None:
# No file provided in the SAN
# No rank or file provided in the SAN
candidate_move = None
for m in moves:
if m[1] == end_pos:
if candidate_move:
raise MoveError(
f"{move} is ambiguous for {side}. Specify a file or rank to move from."
)
candidate_move = m
if candidate_move is None:
raise MoveError(f"{move} is not a valid move for {side}.")
self.move(
start=candidate_move[0],
end=candidate_move[1],
score=candidate_move[2],
)
elif groups[1].isalpha():
# File provided in the SAN
candidate_move = None
for m in moves:
file = get_file(m[0])
if groups[1].upper() == "ABCDEFGH"[file - 1] and m[1] == end_pos:
if candidate_move:
raise MoveError(
f"{move} is ambiguous for {side}. Specify a rank to move from."
)
candidate_move = m
if candidate_move is None:
raise MoveError(f"{move} is not valid for {side}.")
self.move(
start=candidate_move[0],
end=candidate_move[1],
score=candidate_move[2],
)
elif groups[1].isnumeric():
# Rank provided in the SAN
candidate_move = None
for m in moves:
rank = get_rank(m[0])
if groups[1] == "12345678"[rank - 1] and m[1] == end_pos:
if candidate_move:
raise MoveError(
f"{move} is ambiguous for {side}. Specify a file to move from."
)
candidate_move = m
if candidate_move is None:
raise MoveError(f"{move} is not a valid move for {side}.")
self.move(
start=candidate_move[0],
end=candidate_move[1],
score=candidate_move[2],
)
elif groups[1].isalnum():
# Both rank and file provided in the SAN
start_pos = 2 ** coords_to_pos[groups[1].upper()]
for m in moves:
if m[0] == start_pos and m[1] == end_pos:
self.move(start=start_pos, end=end_pos, score=m[2])
break
else:
self.move(start=candidate_move[0], end=candidate_move[1])
else:
if groups[2] is None:
# No rank provided in the SAN
candidate_move = None
for m in moves:
file = get_file(m[0])
if (
groups[1].upper() == "ABCDEFGH"[file - 1]
and m[1] == end_pos
):
if candidate_move:
raise MoveError(
f"{move} is ambiguous for {side}. Specify a file as well as rank to move from."
)
candidate_move = m
if candidate_move is None:
raise MoveError(f"{move} is not a valid move for {side}.")
else:
self.move(start=candidate_move[0], end=candidate_move[1])
else:
# File and rank both present in the SAN
start_pos = 2 ** coords_to_pos[groups[1].upper() + groups[2]]
if (start_pos, end_pos) not in moves:
raise MoveError(f"{move} is not a valid move for {side}.")
self.move(start=start_pos, end=end_pos)
raise MoveError(f"{move} is not a valid move for {side}.")

def make_moves(self, *moves: Iterable[tuple[int, int]]) -> None:
"""
Expand Down
12 changes: 12 additions & 0 deletions chessengine/lookup_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,18 @@
"B": "bishops",
"N": "knights",
"R": "rooks",
"\u2654": "kings",
"\u2655": "queens",
"\u2656": "rooks",
"\u2657": "bishops",
"\u2658": "knights",
"\u2659": "pawns",
"\u265A": "kings",
"\u265B": "queens",
"\u265C": "rooks",
"\u265D": "bishops",
"\u265E": "knights",
"\u265F": "pawns",
}

# fmt: off
Expand Down
9 changes: 4 additions & 5 deletions chessengine/pgn/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@
from chessengine.pgn.node import GameNode, Game

# groups()[0] = The piece moved, one of {K, Q, N, R, B}, None if a pawn was moved
# groups()[1] = The file the piece was moved from. Present to resolve ambiguity, if any
# groups()[2] = The rank the piece was moved from. Present to resolve ambiguity, if any
# groups()[3] = The square the piece was moved to. Always non-null
# groups()[4] = The piece a pawn was promoted to, if a pawn reached the last rank
# groups()[1] = The file and/or the rank the piece was moved from. Present to resolve ambiguity, if any
# groups()[2] = The square the piece was moved to. Always non-null
# groups()[3] = The piece a pawn was promoted to, if a pawn reached the last rank
SAN_MOVE_REGEX = re.compile(
"([KQNRB\u2654\u2655\u2656\u2657\u2658\u2659\u265A\u265B\u265C\u265D\u265E\u265F])?([a-h])?([1-8])?x?([a-h][1-8])=?([QNRB])?"
"([KQNRB\u2654\u2655\u2656\u2657\u2658\u2659\u265A\u265B\u265C\u265D\u265E\u265F])?([a-h1-8]{1,2})?x?([a-h][1-8])=?([QNRB])?"
)
MOVE_TEXT_COMMENT_REGEX = re.compile(
r"\s*{.*?}\s*"
Expand Down

0 comments on commit 56677df

Please sign in to comment.