-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathchess_gui.py
165 lines (136 loc) · 6.65 KB
/
chess_gui.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
import tkinter as tk
import threading
from PIL import ImageTk, Image # pip install pillow
from typing import Optional
from chess_board import ChessBoard, Position
from pieces.chess_piece import PlayerColor
from engine import minimax, get_best_move
class ChessGUI(tk.Tk):
def __init__(self, board: ChessBoard):
self.board = board
self.selected_piece: Optional[Position] = None
self.current_player = PlayerColor.WHITE
# self.window = tk.Tk()
# self.window.title("Chess")
# self.canvas = tk.Canvas(self.window, width=640, height=640)
# self.canvas.pack()
self.window = tk.Tk()
self.window.title("Chess")
self.frame = tk.Frame(self.window)
self.frame.pack()
self.canvas = tk.Canvas(self.frame, width=640, height=640)
self.canvas.pack(side=tk.LEFT)
self.move_history = tk.Text(self.frame, width=30, height=40)
self.move_history.pack(side=tk.RIGHT, fill=tk.BOTH)
self.canvas.bind("<Button-1>", self.on_tile_click)
# load piece images
self.white_pieces = {
"Pawn": ImageTk.PhotoImage(Image.open("images/white_pieces/pawn.png")),
"Rook": ImageTk.PhotoImage(Image.open("images/white_pieces/rook.png")),
"Knight": ImageTk.PhotoImage(Image.open("images/white_pieces/knight.png")),
"Bishop": ImageTk.PhotoImage(Image.open("images/white_pieces/bishop.png")),
"Queen": ImageTk.PhotoImage(Image.open("images/white_pieces/queen.png")),
"King": ImageTk.PhotoImage(Image.open("images/white_pieces/king.png")),
}
self.black_pieces = {
"Pawn": ImageTk.PhotoImage(Image.open("images/black_pieces/pawn.png")),
"Rook": ImageTk.PhotoImage(Image.open("images/black_pieces/rook.png")),
"Knight": ImageTk.PhotoImage(Image.open("images/black_pieces/knight.png")),
"Bishop": ImageTk.PhotoImage(Image.open("images/black_pieces/bishop.png")),
"Queen": ImageTk.PhotoImage(Image.open("images/black_pieces/queen.png")),
"King": ImageTk.PhotoImage(Image.open("images/black_pieces/king.png")),
}
self.draw_board()
self.place_pieces()
def refresh_board(self):
self.draw_board()
self.place_pieces()
def switch_player(self):
if self.current_player == PlayerColor.WHITE:
self.current_player = PlayerColor.BLACK
else:
self.current_player = PlayerColor.WHITE
def highlight_square(self, row, col, color: str):
x1, y1 = col * 80, row * 80
x2, y2 = x1 + 80, y1 + 80
self.canvas.create_rectangle(x1, y1, x2, y2, fill=color, tags="highlight", stipple="gray12")
def remove_square_highlight(self, row, col):
x1, y1 = col * 80, row * 80
x2, y2 = x1 + 80, y1 + 80
color = "white" if (row + col) % 2 == 0 else "gray"
self.canvas.create_rectangle(x1, y1, x2, y2, fill=color)
def draw_board(self):
self.canvas.delete("highlight")
self.canvas.delete("piece")
for row in range(8):
for col in range(8):
x1, y1 = col * 80, row * 80
x2, y2 = x1 + 80, y1 + 80
color = "lemon chiffon" if (row + col) % 2 == 0 else "sienna4"
self.canvas.create_rectangle(x1, y1, x2, y2, fill=color)
def on_tile_click(self, event):
if self.current_player == PlayerColor.WHITE:
col, row = event.x // 80, event.y // 80
clicked_position = (row, col)
clicked_piece = self.board.get_piece(clicked_position)
if not self.selected_piece:
if clicked_piece and clicked_piece.color == self.current_player:
self.selected_piece = clicked_piece
self.highlight_square(row, col, "blue")
else:
if clicked_piece and clicked_piece.color == self.selected_piece.color:
# Deselect the previously selected piece and select the new piece
self.remove_square_highlight(self.selected_piece.position[0], self.selected_piece.position[1])
self.selected_piece = clicked_piece
self.highlight_square(row, col, "blue")
else:
valid_move = self.board.move_piece(self.selected_piece, clicked_position)
if valid_move:
self.remove_square_highlight(self.selected_piece.position[0], self.selected_piece.position[1])
self.selected_piece = None
self.refresh_board()
self.switch_player()
# Update move history
move_text = f"White: {self.board.moves[-1]}\n"
self.move_history.insert(tk.END, move_text)
# self.move_history.see(tk.END)
if self.current_player == PlayerColor.BLACK:
threading.Thread(target=self.play_black_move).start()
else:
# Invalid move
self.highlight_square(row, col, "red")
def play_black_move(self):
print("getting black move...")
best_piece, best_move = get_best_move(self.board, PlayerColor.BLACK, max_depth=5, max_time=15)
print(f"best move: {best_piece}, {best_move}")
if best_move:
self.board.move_piece(best_piece, best_move)
self.window.after(0, self.refresh_board_and_switch_player)
# Update move history
move_text = f"{self.current_player.name.capitalize()}: {self.board.moves[-1]}\n"
self.move_history.insert(tk.END, move_text)
print(f"board score: {self.board.evaluation_function()}")
def refresh_board_and_switch_player(self):
self.refresh_board()
self.switch_player()
def place_pieces(self):
for row in range(8):
for col in range(8):
piece = self.board.get_piece((row, col))
if piece:
if piece.color == PlayerColor.WHITE:
piece_image = self.white_pieces[piece.__class__.__name__]
else:
piece_image = self.black_pieces[piece.__class__.__name__]
self.canvas.create_image(
col * 80 + 40,
row * 80 + 40,
image=piece_image,
tags=("piece", f"{row},{col}"),
)
def run(self):
self.window.mainloop()
if __name__ == "__main__":
chess_board = ChessBoard()
gui = ChessGUI(chess_board)
gui.run()