import pygame from config.constants import COLS, ROWS, LIGHT_BROWN, DARK_BROWN, SQUARE_SIZE, PIECES class ChessBoard: def __init__(self): self.board = self.create_board() def create_board(self): board = [['' for _ in range(COLS)] for _ in range(ROWS)] # Assign unique IDs to each piece # Pawns for i in range(COLS): board[1][i] = f'black_pawn{i+1}' board[6][i] = f'white_pawn{i+1}' # Rooks board[0][0] = board[0][7] = 'black_rook' board[7][0] = board[7][7] = 'white_rook' # Knights board[0][1] = board[0][6] = 'black_knight' board[7][1] = board[7][6] = 'white_knight' # Bishops board[0][2] = board[0][5] = 'black_bishop' board[7][2] = board[7][5] = 'white_bishop' # Queens board[0][3] = 'black_queen' board[7][3] = 'white_queen' # Kings board[0][4] = 'black_king' board[7][4] = 'white_king' return board def draw(self, win): self.draw_squares(win) self.draw_pieces(win) def draw_squares(self, win): for row in range(ROWS): for col in range(COLS): color = LIGHT_BROWN if (row + col) % 2 == 0 else DARK_BROWN pygame.draw.rect(win, color, (col * SQUARE_SIZE, row * SQUARE_SIZE, SQUARE_SIZE, SQUARE_SIZE)) def draw_pieces(self, win): for row in range(ROWS): for col in range(COLS): piece = self.board[row][col] if piece != '': base_piece_name = ''.join([i for i in piece if not i.isdigit()]) piece_image = PIECES[base_piece_name] piece_image = pygame.transform.scale(piece_image, (SQUARE_SIZE, SQUARE_SIZE)) win.blit(piece_image, (col * SQUARE_SIZE, row * SQUARE_SIZE)) def is_legal(self, piece, start_row, start_col, dest_row, dest_col): piece_type = ''.join([i for i in piece if not i.isdigit()]).split('_')[1] # e.g., 'pawn' delta_row = dest_row - start_row delta_col = dest_col - start_col # Determine the piece color piece_color = 'white' if 'white' in piece else 'black' # Check if destination square is occupied by own piece dest_piece = self.board[dest_row][dest_col] if dest_piece != '' and piece_color in dest_piece: return False # Cannot capture own piece if piece_type == 'pawn': # Pawn move logic direction = -1 if piece_color == 'white' else 1 # white moves up (-1), black moves down (+1) # Single square move if delta_col == 0 and delta_row == direction: if self.board[dest_row][dest_col] == '': return True # Double square move from initial position if delta_col == 0 and delta_row == 2 * direction and (start_row == 6 if piece_color == 'white' else start_row == 1): if self.board[start_row + direction][dest_col] == '' and self.board[dest_row][dest_col] == '': return True # Capturing move if abs(delta_col) == 1 and delta_row == direction: if self.board[dest_row][dest_col] != '' and piece_color not in self.board[dest_row][dest_col]: return True # En passant can be added here (not implemented) return False elif piece_type == 'rook': # Rook move logic if delta_row == 0 or delta_col == 0: if self.is_path_clear(start_row, start_col, dest_row, dest_col): return True return False elif piece_type == 'knight': # Knight move logic if (abs(delta_row), abs(delta_col)) in [(2, 1), (1, 2)]: return True return False elif piece_type == 'bishop': # Bishop move logic if abs(delta_row) == abs(delta_col): if self.is_path_clear(start_row, start_col, dest_row, dest_col): return True return False elif piece_type == 'queen': # Queen move logic (combination of rook and bishop) if delta_row == 0 or delta_col == 0 or abs(delta_row) == abs(delta_col): if self.is_path_clear(start_row, start_col, dest_row, dest_col): return True return False elif piece_type == 'king': # King move logic if max(abs(delta_row), abs(delta_col)) == 1: return True # Castling can be added here (not implemented) return False return False def is_path_clear(self, start_row, start_col, dest_row, dest_col): step_row = (dest_row - start_row) // max(1, abs(dest_row - start_row)) if dest_row != start_row else 0 step_col = (dest_col - start_col) // max(1, abs(dest_col - start_col)) if dest_col != start_col else 0 current_row = start_row + step_row current_col = start_col + step_col while (current_row != dest_row or current_col != dest_col): if self.board[current_row][current_col] != '': return False # Path is blocked current_row += step_row current_col += step_col return True def move_piece(self, piece_type, start_square, dest_square): col_map = {'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4, 'f':5, 'g':6, 'h':7} row_map = {'1':7, '2':6, '3':5, '4':4, '5':3, '6':2, '7':1, '8':0} dest_col = col_map[dest_square[0]] dest_row = row_map[dest_square[1]] start_col = col_map[start_square[0]] start_row = row_map[start_square[1]] # Get the piece at start_square piece_at_start = self.board[start_row][start_col] if not piece_at_start: # print(f"No piece at {start_square}") return False # Check if the piece is of the correct type if piece_type not in piece_at_start: # print(f"The piece at {start_square} is not a {piece_type}") return False # Check if the piece belongs to the player (assuming player is white) if 'white' not in piece_at_start: # print(f"The piece at {start_square} is not yours") return False # Check if the move is legal if not self.is_legal(piece_at_start, start_row, start_col, dest_row, dest_col): # print("Illegal move!") return False # Check if destination square is occupied by own piece piece_at_dest = self.board[dest_row][dest_col] if piece_at_dest != '': if 'white' in piece_at_dest: # print(f"Cannot move to {dest_square}, it's occupied by your own piece") return False # else: # print(f"Capturing opponent's piece at {dest_square}") # Move the piece to the destination self.board[dest_row][dest_col] = piece_at_start self.board[start_row][start_col] = '' return True