diff --git a/app/chess_sim/test.py b/app/chess_sim/test.py index d10e892..3ac5502 100644 --- a/app/chess_sim/test.py +++ b/app/chess_sim/test.py @@ -75,23 +75,127 @@ class ChessBoard: for col, piece_type in enumerate(back_rank): brd.place(7, col, piece_type, Color.WHITE) - return brd + return brd - - def possible_moves(self) -> list[BoardMove]: + def moves_unchecked(self, piece: Piece, pos: BoardPos) -> list[list[tuple[int, int]]]: + row, column = pos.p + rays: list[list[tuple[int, int]]] = [] + + 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] = [] - for i, row in enumerate(self.fields): 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 + + + def possible_moves(self) -> list[BoardMove]: + + return self.moves_basic_checked() # used only for testing purposes def main(): 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() \ No newline at end of file