introduced 'ray' based move checking
This commit is contained in:
+108
-4
@@ -77,21 +77,125 @@ class ChessBoard:
|
|||||||
|
|
||||||
return brd
|
return brd
|
||||||
|
|
||||||
|
def moves_unchecked(self, piece: Piece, pos: BoardPos) -> list[list[tuple[int, int]]]:
|
||||||
|
row, column = pos.p
|
||||||
|
rays: list[list[tuple[int, int]]] = []
|
||||||
|
|
||||||
def possible_moves(self) -> list[BoardMove]:
|
if piece.type == PieceType.KING:
|
||||||
|
king_offsets = [(1, 1), (1, 0), (0, 1), (-1, -1), (-1, 0), (0, -1), (1, -1), (-1, 1)]
|
||||||
|
rays.append([(row + dr, column + dc) for dr, dc in king_offsets])
|
||||||
|
elif piece.type == PieceType.KNIGHT:
|
||||||
|
knight_offsets = [
|
||||||
|
(2, 1), (2, -1), (-2, 1), (-2, -1),
|
||||||
|
(1, 2), (1, -2), (-1, 2), (-1, -2)
|
||||||
|
]
|
||||||
|
rays.append([(row + dr, column + dc) for dr, dc in knight_offsets])
|
||||||
|
elif piece.type == PieceType.PAWN:
|
||||||
|
# correct forward direction and start row depending on color
|
||||||
|
if piece.color == Color.WHITE:
|
||||||
|
forward = -1
|
||||||
|
start_row = 6
|
||||||
|
else:
|
||||||
|
forward = 1
|
||||||
|
start_row = 1
|
||||||
|
|
||||||
|
forward_ray: list[tuple[int, int]] = []
|
||||||
|
forward_ray.append((row + forward, column))
|
||||||
|
# if the pawn is at the start row, include the double-step
|
||||||
|
if row == start_row:
|
||||||
|
forward_ray.append((row + 2 * forward, column))
|
||||||
|
rays.append(forward_ray)
|
||||||
|
|
||||||
|
# capture moves
|
||||||
|
captures = [(row + forward, column - 1), (row + forward, column + 1)]
|
||||||
|
rays.extend([[(rr, cc)] for rr, cc in captures])
|
||||||
|
elif piece.type == PieceType.BISHOP:
|
||||||
|
directions = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
|
||||||
|
for dr, dc in directions:
|
||||||
|
ray = []
|
||||||
|
for k in range(1, 8):
|
||||||
|
ray.append((row + k * dr, column + k * dc))
|
||||||
|
rays.append(ray)
|
||||||
|
elif piece.type == PieceType.ROOK:
|
||||||
|
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
|
||||||
|
for dr, dc in directions:
|
||||||
|
ray = []
|
||||||
|
for k in range(1, 8):
|
||||||
|
ray.append((row + k * dr, column + k * dc))
|
||||||
|
rays.append(ray)
|
||||||
|
elif piece.type == PieceType.QUEEN:
|
||||||
|
directions = [
|
||||||
|
(1, 0), (-1, 0), (0, 1), (0, -1),
|
||||||
|
(1, 1), (1, -1), (-1, 1), (-1, -1)
|
||||||
|
]
|
||||||
|
for dr, dc in directions:
|
||||||
|
ray = []
|
||||||
|
for k in range(1, 8):
|
||||||
|
ray.append((row + k * dr, column + k * dc))
|
||||||
|
rays.append(ray)
|
||||||
|
|
||||||
|
return rays
|
||||||
|
|
||||||
|
def on_board(self, rr: int, cc: int) -> bool:
|
||||||
|
return 0 <= rr < 8 and 0 <= cc < 8
|
||||||
|
|
||||||
|
def moves_basic_checked(self) -> list[BoardMove]:
|
||||||
moves: list[BoardMove] = []
|
moves: list[BoardMove] = []
|
||||||
|
|
||||||
for i, row in enumerate(self.fields):
|
for i, row in enumerate(self.fields):
|
||||||
for j, field in enumerate(row):
|
for j, field in enumerate(row):
|
||||||
print(f"Row: {i}, Column: {j}, field: {field}")
|
if field.piece is None:
|
||||||
|
continue
|
||||||
|
src_pos = BoardPos((i, j))
|
||||||
|
piece = field.piece
|
||||||
|
rays = self.moves_unchecked(piece, src_pos)
|
||||||
|
|
||||||
|
for ray in rays:
|
||||||
|
# detect pawn capture ray and dont allow movement in that ray without capturing
|
||||||
|
is_pawn_capture_ray = (
|
||||||
|
piece.type == PieceType.PAWN
|
||||||
|
and len(ray) == 1
|
||||||
|
and ray[0][1] != j
|
||||||
|
and abs(ray[0][0] - i) == 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# non sliding rays get treated individually
|
||||||
|
non_sliding = piece.type in (PieceType.KNIGHT, PieceType.KING) or is_pawn_capture_ray
|
||||||
|
|
||||||
|
for (tr, tc) in ray:
|
||||||
|
if not self.on_board(tr, tc):
|
||||||
|
if non_sliding:
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
target_field = self.fields[tr][tc]
|
||||||
|
if target_field.piece is None:
|
||||||
|
# empty target
|
||||||
|
if is_pawn_capture_ray:
|
||||||
|
# pawn cant move diagonally into empty square
|
||||||
|
break
|
||||||
|
moves.append(BoardMove(src_pos, BoardPos((tr, tc))))
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# occupied
|
||||||
|
if target_field.piece.color == piece.color:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# opponent piece
|
||||||
|
moves.append(BoardMove(src_pos, BoardPos((tr, tc))))
|
||||||
|
break
|
||||||
|
|
||||||
return moves
|
return moves
|
||||||
|
|
||||||
|
|
||||||
|
def possible_moves(self) -> list[BoardMove]:
|
||||||
|
|
||||||
|
return self.moves_basic_checked()
|
||||||
|
|
||||||
# used only for testing purposes
|
# used only for testing purposes
|
||||||
def main():
|
def main():
|
||||||
default_brd = ChessBoard.init_default()
|
default_brd = ChessBoard.init_default()
|
||||||
default_brd.possible_moves()
|
mvs = default_brd.possible_moves()
|
||||||
|
for mv in mvs:
|
||||||
|
print(mv)
|
||||||
|
print(f"len of moves: { len(mvs)}")
|
||||||
|
|
||||||
main()
|
main()
|
||||||
Reference in New Issue
Block a user