192 lines
7 KiB
Python
192 lines
7 KiB
Python
|
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
|
||
|
|