lyceum-env/clubs/chess/board.py

192 lines
7 KiB
Python
Raw Normal View History

2024-10-03 14:19:13 +00:00
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
2024-10-03 14:19:13 +00:00
for i in range(COLS):
board[1][i] = f'black_pawn{i+1}'
board[6][i] = f'white_pawn{i+1}'
2024-10-03 14:19:13 +00:00
# Rooks
2024-10-03 14:19:13 +00:00
board[0][0] = board[0][7] = 'black_rook'
board[7][0] = board[7][7] = 'white_rook'
# Knights
2024-10-03 14:19:13 +00:00
board[0][1] = board[0][6] = 'black_knight'
board[7][1] = board[7][6] = 'white_knight'
# Bishops
2024-10-03 14:19:13 +00:00
board[0][2] = board[0][5] = 'black_bishop'
board[7][2] = board[7][5] = 'white_bishop'
# Queens
2024-10-03 14:19:13 +00:00
board[0][3] = 'black_queen'
board[7][3] = 'white_queen'
# Kings
2024-10-03 14:19:13 +00:00
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]
2024-10-03 14:19:13 +00:00
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
2024-10-03 14:19:13 +00:00
# Determine the piece color
piece_color = 'white' if 'white' in piece else 'black'
2024-10-03 14:19:13 +00:00
# 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] == '':
2024-10-03 14:19:13 +00:00
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
2024-10-03 14:19:13 +00:00
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