The ChessAIThon project (2025-1-ES01-KA220-VET-000354329) is co-funded by the European Union. The views and opinions expressed in this publication are those of the author(s) only and do not necessarily reflect those of the European Union or the Spanish Service for the Internationalisation of Education (SEPIE). Neither the European Union nor the National Agency SEPIE can be held responsible for them.
Table of Contents
Challenge students with the following task:
Write a function generate_bishop_moves(board, r, c) that returns all squares reachable by a Bishop, considering obstacles.
SOLUTION
def generate_bishop_moves(board, r, c):
moves = []
piece = board[r][c]
# The 4 diagonal directions
directions = [(-1, -1), (-1, 1), (1, -1), (1, 1)]
for dr, dc in directions:
new_r, new_c = r + dr, c + dc
while 0 <= new_r <= 7 and 0 <= new_c <= 7:
destination = board[new_r][new_c]
if destination == ".":
moves.append((new_r, new_c))
elif destination.isupper() != piece.isupper():
moves.append((new_r, new_c))
break
else:
break
new_r += dr
new_c += dc
return moves
Challenge students with the following task:
Given a chessboard, write a function count_total_moves(board, white_turn) that returns the total number of legal moves available for a color.
SOLUTION
def count_total_moves(board, white_turn):
moves = generate_all_moves(board, white_turn)
return len(moves)
# Test
initial_board = create_board() # From Chapter 1 function
print(f"Available moves for White: {count_total_moves(initial_board, True)}")
# Output: about 20 moves in the initial position
Challenge students with the following task:
Write a function execute_move(board, r1, c1, r2, c2) that returns a NEW board with the move executed, without modifying the original.
SOLUTION
import copy
def execute_move(board, r1, c1, r2, c2):
"""
Execute a move and return a NEW board.
The original is not modified.
"""
new_board = copy.deepcopy(board)
piece = new_board[r1][c1]
new_board[r2][c2] = piece
new_board[r1][c1] = '.'
return new_board
# Test
board = create_board()
new_board = execute_move(board, 6, 4, 4, 4) # e2-e4
print(board[6][4]) # Output: 'P' (original intact)
print(new_board[6][4]) # Output: '.' (move executed)
print(new_board[4][4]) # Output: 'P'
Challenge students with the following task:
Write a function pieces_giving_check(board, white_king) that returns a list of coordinates of all pieces that are giving check to the specified King.
SOLUTION
def pieces_giving_check(board, white_king):
"""
Returns coordinates of all pieces giving check.
"""
king_pos = find_king(board, white_king)
if king_pos is None:
return []
king_r, king_c = king_pos
attackers = []
for r in range(8):
for c in range(8):
piece = board[r][c]
if piece == '.':
continue
# Is it an enemy piece?
if piece.isupper() == white_king:
continue
# Can this piece reach the King?
moves = generate_piece_moves(board, r, c, piece)
if (king_r, king_c) in moves:
attackers.append((r, c, piece))
return attackers
Challenge students with the following task:
Improve the evaluate_position function by adding a bonus for pieces in the center of the board (central squares are more strategic).
SOLUTION
def advanced_evaluate_position(board):
material_values = {
'P': 100, 'N': 320, 'B': 330, 'R': 500, 'Q': 900, 'K': 0,
'p': -100, 'n': -320, 'b': -330, 'r': -500, 'q': -900, 'k': 0
}
# Bonus for center control
center_bonus = [
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 5, 10, 10, 5, 0, 0],
[0, 0, 10, 20, 20, 10, 0, 0],
[0, 0, 10, 20, 20, 10, 0, 0],
[0, 0, 5, 10, 10, 5, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]
]
score = 0
for r in range(8):
for c in range(8):
piece = board[r][c]
if piece in material_values:
score += material_values[piece]
# Add center bonus (positive for white, negative for black)
if piece.isupper():
score += center_bonus[r][c]
else:
score -= center_bonus[r][c]
return score