I have this simple code using Python that will allow me to play chess against Stockfish. I also implemented a simple GUI that helps visualize the pieces easier. I have name the black pieces images "p", "r", "n", "b", "q", "k", and for the white pieces: "P", "R", "N", "B", "Q", "K". However, at first the script was loading the black pieces for both sides, so I figured the problem was with the naming of the white pieces, as Windows inserted (2) after the file names. I changed the code a little bit, but now it's only loading the images of white pieces for both sides.
import chess
import chess.engine
import tkinter as tk
from tkinter import simpledialog, messagebox
from PIL import Image, ImageTk
import os
import fnmatch
class ChessGUI(tk.Tk):
def __init__(self):
super().__init__()
self.title("Chess Game")
self.geometry("600x600")
self.canvas = tk.Canvas(self, width=600, height=600, bg="white")
self.canvas.pack(fill=tk.BOTH, expand=True)
self.board = chess.Board()
self.load_piece_images()
self.draw_board()
def load_piece_images(self):
self.piece_images = {}
piece_symbols = ["p", "r", "n", "b", "q", "k", "P", "R", "N", "B", "Q", "K"]
for piece_symbol in piece_symbols:
try:
# Use fnmatch to perform case-insensitive matching
files = [f for f in os.listdir("pieces") if fnmatch.fnmatch(f, f"{piece_symbol}*") and f.lower().endswith(".png")]
if files:
img_path = f"pieces/{files[0]}"
img = Image.open(img_path)
img = img.resize((75, 75), Image.BILINEAR)
key = piece_symbol.lower()
self.piece_images[key] = ImageTk.PhotoImage(img)
print(f"Loaded image for {piece_symbol} from {img_path}")
else:
print(f"No matching image found for {piece_symbol}. Skipping.")
except FileNotFoundError:
print(f"Error loading image for {piece_symbol}. Skipping.")
def draw_board(self):
self.canvas.delete("all")
for square in chess.SQUARES:
rank, file = chess.square_rank(square), chess.square_file(square)
color = "white" if (rank + file) % 2 == 0 else "black"
x, y = file * 75, (7 - rank) * 75
self.canvas.create_rectangle(x, y, x + 75, y + 75, fill=color)
piece = self.board.piece_at(square)
if piece:
# Print the piece symbol for troubleshooting
print(piece.symbol())
# Convert the piece symbol to lowercase for dictionary access
piece_image = self.piece_images[piece.symbol().lower()]
self.canvas.create_image(x + 37.5, y + 37.5, image=piece_image)
def get_user_move(self):
user_move = simpledialog.askstring("Your Move", "Enter your move (in UCI format, e.g., e2e4):")
try:
self.board.push_uci(user_move)
self.draw_board()
except ValueError:
messagebox.showerror("Invalid Move", "Invalid move. Try again.")
self.get_user_move()
def get_stockfish_move(self):
stockfish_path = "D:/Test/stockfish/stockfish.exe" # Replace with the actual path to Stockfish
with chess.engine.SimpleEngine.popen_uci(stockfish_path) as engine:
result = engine.play(self.board, chess.engine.Limit(time=2.0))
return result.move
def play_game(self):
while not self.board.is_game_over():
self.draw_board()
if self.board.turn == chess.WHITE:
self.get_user_move()
else:
stockfish_move = self.get_stockfish_move()
self.board.push(stockfish_move)
self.draw_board()
messagebox.showinfo("Game Over", f"Game Over!\nResult: {self.board.result()}")
if __name__ == "__main__":
chess_gui = ChessGUI()
chess_gui.play_game()
chess_gui.mainloop()
I tried changing the load_piece_images part, but the only thing that changed was that instead of using black pieces for both sides, the white pieces images loaded instead. I also tried changing the draw_board part, but things didn't change. I expected that both sides would be loaded with their respective color, but it only loads either of them. I changed the file names too, but then the GUI wouldn't even start.