Skip to content

Commit 0ff7dd3

Browse files
Initial commit
0 parents  commit 0ff7dd3

18 files changed

+374
-0
lines changed

Diff for: assets/WB.png

1.9 KB
Loading

Diff for: assets/WK.png

2.23 KB
Loading

Diff for: assets/WN.png

1.83 KB
Loading

Diff for: assets/WP.png

1.26 KB
Loading

Diff for: assets/WQ.png

2.58 KB
Loading

Diff for: assets/WR.png

933 Bytes
Loading

Diff for: assets/b.png

1.23 KB
Loading

Diff for: assets/check.wav

50.1 KB
Binary file not shown.

Diff for: assets/checkmate.wav

264 KB
Binary file not shown.

Diff for: assets/image.jpeg

27.2 KB
Loading

Diff for: assets/k.png

2.43 KB
Loading

Diff for: assets/move.wav

248 KB
Binary file not shown.

Diff for: assets/n.png

1.48 KB
Loading

Diff for: assets/p.png

797 Bytes
Loading

Diff for: assets/pops.png

72.8 KB
Loading

Diff for: assets/q.png

2.21 KB
Loading

Diff for: assets/r.png

725 Bytes
Loading

Diff for: chess-game.py

+374
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
import socket
2+
import chess
3+
import pygame
4+
import random
5+
6+
class ChessGame:
7+
def __init__(self):
8+
self.board = chess.Board()
9+
self.selected_square = None
10+
self.valid_moves = []
11+
self.window_size = 640
12+
self.square_size = self.window_size // 8
13+
self.colors = [(240, 217, 181), (181, 136, 99)] # Light and dark squares
14+
self.piece_images = self.load_piece_images()
15+
# self.sounds = self.load_sounds()
16+
self.play_with_bot = False
17+
self.multiplayer = False
18+
self.elo = 1200
19+
self.state = "home" # Game state: "home" or "game"
20+
21+
22+
pygame.init()
23+
pygame.mixer.init() # Initialize sound mixer
24+
self.screen = pygame.display.set_mode((self.window_size, self.window_size))
25+
pygame.display.set_caption("Chess Game")
26+
self.font = pygame.font.Font(None, 36)
27+
self.sounds = self.load_sounds()
28+
29+
def load_sounds(self):
30+
sounds = {}
31+
try:
32+
sounds['move'] = pygame.mixer.Sound("assets/move.wav")
33+
sounds['check'] = pygame.mixer.Sound("assets/check.wav")
34+
sounds['checkmate'] = pygame.mixer.Sound("assets/checkmate.wav")
35+
except FileNotFoundError:
36+
print("Sound files not found. Please ensure they are in the assets folder.")
37+
return sounds
38+
39+
40+
41+
def load_piece_images(self):
42+
pieces = ["p", "r", "n", "b", "q", "k", "WP", "WR", "WN", "WB", "WQ", "WK"]
43+
images = {}
44+
for piece in pieces:
45+
file_path = f"assets/{piece}.png"
46+
try:
47+
images[piece] = pygame.image.load(file_path)
48+
images[piece] = pygame.transform.scale(images[piece], (self.square_size, self.square_size))
49+
except FileNotFoundError:
50+
print(f"Error: File {file_path} not found. Please add the image to the assets folder.")
51+
placeholder = pygame.Surface((self.square_size, self.square_size))
52+
placeholder.fill((255, 0, 0)) # Red square as a placeholder
53+
images[piece] = placeholder
54+
return images
55+
56+
57+
58+
def draw_board(self):
59+
for row in range(8):
60+
for col in range(8):
61+
color = self.colors[(row + col) % 2]
62+
pygame.draw.rect(
63+
self.screen, color, pygame.Rect(col * self.square_size, row * self.square_size, self.square_size, self.square_size)
64+
)
65+
66+
def draw_pieces(self):
67+
for row in range(8):
68+
for col in range(8):
69+
piece = self.board.piece_at(chess.square(col, 7 - row))
70+
if piece:
71+
symbol = piece.symbol()
72+
if symbol.isupper(): # White pieces
73+
symbol = "W" + symbol
74+
self.screen.blit(self.piece_images[symbol], (col * self.square_size, row * self.square_size))
75+
76+
def bot_move(self):
77+
legal_moves = list(self.board.legal_moves)
78+
if not legal_moves:
79+
return
80+
81+
# Basic piece values for evaluation
82+
piece_values = {
83+
chess.PAWN: 100,
84+
chess.KNIGHT: 320,
85+
chess.BISHOP: 330,
86+
chess.ROOK: 500,
87+
chess.QUEEN: 900,
88+
chess.KING: 20000
89+
}
90+
91+
def evaluate_position():
92+
if self.board.is_checkmate():
93+
return -20000 if self.board.turn else 20000
94+
95+
score = 0
96+
for square in chess.SQUARES:
97+
piece = self.board.piece_at(square)
98+
if piece is None:
99+
continue
100+
101+
value = piece_values[piece.piece_type]
102+
if piece.color:
103+
score += value
104+
else:
105+
score -= value
106+
107+
return score
108+
109+
def evaluate_move(move):
110+
self.board.push(move)
111+
score = -evaluate_position()
112+
self.board.pop()
113+
return score
114+
115+
# Different play styles based on ELO
116+
if self.elo < 800: # Beginner: Mostly random moves
117+
if random.random() < 0.8: # 80% random moves
118+
move = random.choice(legal_moves)
119+
else:
120+
move = max(legal_moves, key=evaluate_move)
121+
122+
elif self.elo < 1200: # Intermediate: Mix of random and calculated moves
123+
if random.random() < 0.1: # 40% random moves
124+
move = random.choice(legal_moves)
125+
else:
126+
move = max(legal_moves, key=evaluate_move)
127+
128+
elif self.elo < 1600: # Advanced: Better evaluation with some mistakes
129+
if random.random() < 0.0: # 20% random moves
130+
move = random.choice(legal_moves)
131+
else:
132+
move = max(legal_moves, key=evaluate_move)
133+
134+
else: # Expert: Best calculated moves
135+
move = max(legal_moves, key=evaluate_move)
136+
137+
self.board.push(move)
138+
139+
def play_bot_turn(self):
140+
if self.play_with_bot and not self.board.turn: # If it's black's turn and bot is enabled
141+
self.bot_move()
142+
143+
def handle_click(self, pos):
144+
if self.check_game_state(): # Check if game is over before handling clicks
145+
return
146+
147+
col = pos[0] // self.square_size
148+
row = pos[1] // self.square_size
149+
square = chess.square(col, 7 - row)
150+
151+
if self.selected_square is None:
152+
piece = self.board.piece_at(square)
153+
if piece is not None and ((piece.color and self.board.turn) or (not piece.color and not self.board.turn)):
154+
self.selected_square = square
155+
self.valid_moves = [move.to_square for move in self.board.legal_moves if move.from_square == square]
156+
else:
157+
move = chess.Move(self.selected_square, square)
158+
159+
# Check if it's a pawn promotion move
160+
piece = self.board.piece_at(self.selected_square)
161+
if (piece and piece.piece_type == chess.PAWN and
162+
((chess.square_rank(square) == 7 and self.board.turn) or
163+
(chess.square_rank(square) == 0 and not self.board.turn))
164+
):
165+
promotion_piece = self.show_promotion_dialog()
166+
if promotion_piece:
167+
move = chess.Move(self.selected_square, square, promotion=promotion_piece)
168+
if move in self.board.legal_moves:
169+
self.board.push(move)
170+
if not self.check_game_state() and self.play_with_bot: # Check game state before bot move
171+
self.play_bot_turn()
172+
if 'move' in self.sounds:
173+
self.sounds['move'].play()
174+
else:
175+
if move in self.board.legal_moves:
176+
self.board.push(move)
177+
if not self.check_game_state() and self.play_with_bot: # Check game state before bot move
178+
self.play_bot_turn()
179+
180+
self.selected_square = None
181+
self.valid_moves = []
182+
183+
184+
185+
def show_promotion_dialog(self):
186+
dialog_width = 200
187+
dialog_height = 250
188+
dialog_x = (self.window_size - dialog_width) // 2
189+
dialog_y = (self.window_size - dialog_height) // 2
190+
191+
dialog_surface = pygame.Surface((dialog_width, dialog_height))
192+
dialog_surface.fill((255, 255, 255))
193+
pygame.draw.rect(dialog_surface, (0, 0, 0), pygame.Rect(0, 0, dialog_width, dialog_height), 2)
194+
195+
pieces = [(chess.QUEEN, "Q"), (chess.ROOK, "R"), (chess.BISHOP, "B"), (chess.KNIGHT, "N")]
196+
button_height = 50
197+
198+
while True:
199+
for event in pygame.event.get():
200+
if event.type == pygame.MOUSEBUTTONDOWN:
201+
mouse_pos = pygame.mouse.get_pos()
202+
relative_y = mouse_pos[1] - dialog_y
203+
204+
if dialog_y <= mouse_pos[1] <= dialog_y + dialog_height:
205+
index = relative_y // button_height
206+
if 0 <= index < len(pieces):
207+
return pieces[index][0]
208+
209+
# Draw promotion options
210+
for i, (piece, symbol) in enumerate(pieces):
211+
y_pos = i * button_height
212+
pygame.draw.rect(dialog_surface, (200, 200, 200), (0, y_pos, dialog_width, button_height))
213+
text = self.font.render(f"Promote to {symbol}", True, (0, 0, 0))
214+
text_rect = text.get_rect(center=(dialog_width // 2, y_pos + button_height // 2))
215+
dialog_surface.blit(text, text_rect)
216+
217+
self.screen.blit(dialog_surface, (dialog_x, dialog_y))
218+
pygame.display.flip()
219+
220+
def bot_move(self):
221+
legal_moves = list(self.board.legal_moves)
222+
if 'move' in self.sounds:
223+
self.sounds['move'].play()
224+
225+
if self.elo < 1000:
226+
move = random.choice(legal_moves)
227+
else:
228+
move = max(legal_moves, key=lambda m: self.evaluate_move(m))
229+
self.board.push(move)
230+
231+
232+
def evaluate_move(self, move):
233+
return random.random()
234+
235+
def draw_highlights(self):
236+
if self.selected_square is not None:
237+
row, col = 7 - chess.square_rank(self.selected_square), chess.square_file(self.selected_square)
238+
pygame.draw.rect(
239+
self.screen, (0, 255, 0, 128), pygame.Rect(col * self.square_size, row * self.square_size, self.square_size, self.square_size), 3
240+
)
241+
242+
for square in self.valid_moves:
243+
row, col = 7 - chess.square_rank(square), chess.square_file(square)
244+
pygame.draw.circle(
245+
self.screen, (0, 255, 0),
246+
(col * self.square_size + self.square_size // 2, row * self.square_size + self.square_size // 2),
247+
self.square_size // 6
248+
)
249+
250+
if self.board.is_check():
251+
king_square = self.board.king(self.board.turn)
252+
row, col = 7 - chess.square_rank(king_square), chess.square_file(king_square)
253+
pygame.draw.rect(
254+
self.screen, (255, 0, 0), pygame.Rect(col * self.square_size, row * self.square_size, self.square_size, self.square_size), 3
255+
)
256+
def check_game_state(self):
257+
if self.board.is_checkmate():
258+
winner = "Black" if self.board.turn else "White"
259+
if 'checkmate' in self.sounds:
260+
self.sounds['checkmate'].play()
261+
self.display_message(f"Checkmate! {winner} wins!", show_buttons=True)
262+
return True
263+
elif self.board.is_stalemate():
264+
self.display_message("Stalemate! It's a draw!", show_buttons=True)
265+
return True
266+
elif self.board.is_insufficient_material():
267+
self.display_message("Draw! Insufficient material!", show_buttons=True)
268+
return True
269+
return False
270+
271+
def display_message(self, message, show_buttons=False):
272+
self.screen.fill((0, 0, 0))
273+
message_surface = self.font.render(message, True, (255, 255, 255))
274+
message_rect = message_surface.get_rect(center=(self.window_size // 2, self.window_size // 2 - 50))
275+
self.screen.blit(message_surface, message_rect)
276+
277+
if show_buttons:
278+
new_game_button = pygame.Rect(180, 300, 120, 50)
279+
home_button = pygame.Rect(340, 300, 120, 50)
280+
281+
pygame.draw.rect(self.screen, (0, 128, 0), new_game_button)
282+
pygame.draw.rect(self.screen, (0, 128, 0), home_button)
283+
284+
new_game_text = self.font.render("New Game", True, (255, 255, 255))
285+
home_text = self.font.render("Home", True, (255, 255, 255))
286+
287+
self.screen.blit(new_game_text, (new_game_button.x + 10, new_game_button.y + 10))
288+
self.screen.blit(home_text, (home_button.x + 30, home_button.y + 10))
289+
290+
pygame.display.flip()
291+
292+
while True:
293+
for event in pygame.event.get():
294+
if event.type == pygame.QUIT:
295+
pygame.quit()
296+
exit()
297+
elif event.type == pygame.MOUSEBUTTONDOWN:
298+
if new_game_button.collidepoint(event.pos):
299+
self.__init__()
300+
return
301+
elif home_button.collidepoint(event.pos):
302+
self.__init__()
303+
self.state = "home"
304+
return
305+
306+
def display_home(self):
307+
self.screen.fill((30, 30, 30))
308+
309+
play_bot_button = pygame.Rect(200, 150, 240, 50)
310+
multiplayer_button = pygame.Rect(200, 250, 240, 50)
311+
local_button = pygame.Rect(200, 350, 240, 50)
312+
elo_slider_rect = pygame.Rect(200, 450, 240, 50)
313+
314+
pygame.draw.rect(self.screen, (0, 128, 128), play_bot_button)
315+
pygame.draw.rect(self.screen, (0, 128, 128), multiplayer_button)
316+
pygame.draw.rect(self.screen, (0, 128, 128), local_button)
317+
pygame.draw.rect(self.screen, (128, 0, 128), elo_slider_rect)
318+
319+
play_bot_text = self.font.render("Play with Bot", True, (255, 255, 255))
320+
multiplayer_text = self.font.render("Multiplayer", True, (255, 255, 255))
321+
local_text = self.font.render("Play Locally", True, (255, 255, 255))
322+
elo_text = self.font.render(f"ELO: {self.elo}", True, (255, 255, 255))
323+
324+
self.screen.blit(play_bot_text, (play_bot_button.x + 30, play_bot_button.y + 10))
325+
self.screen.blit(multiplayer_text, (multiplayer_button.x + 30, multiplayer_button.y + 10))
326+
self.screen.blit(local_text, (local_button.x + 30, local_button.y + 10))
327+
self.screen.blit(elo_text, (elo_slider_rect.x + 60, elo_slider_rect.y + 10))
328+
329+
pygame.display.flip()
330+
331+
return play_bot_button, multiplayer_button, local_button, elo_slider_rect
332+
333+
def run(self):
334+
clock = pygame.time.Clock()
335+
336+
while True:
337+
for event in pygame.event.get():
338+
if event.type == pygame.QUIT:
339+
pygame.quit()
340+
exit()
341+
elif self.state == "home" and event.type == pygame.MOUSEBUTTONDOWN:
342+
play_bot_button, multiplayer_button, local_button, elo_slider_rect = self.display_home()
343+
344+
if play_bot_button.collidepoint(event.pos):
345+
self.play_with_bot = True
346+
self.state = "game"
347+
elif multiplayer_button.collidepoint(event.pos):
348+
self.multiplayer = True
349+
self.state = "game"
350+
elif local_button.collidepoint(event.pos):
351+
self.play_with_bot = False
352+
self.multiplayer = False
353+
self.state = "game"
354+
elif elo_slider_rect.collidepoint(event.pos):
355+
self.elo = min(3200, max(400, self.elo + 200))
356+
357+
elif self.state == "game" and event.type == pygame.MOUSEBUTTONDOWN:
358+
self.handle_click(event.pos)
359+
360+
if self.state == "home":
361+
self.display_home()
362+
elif self.state == "game":
363+
self.screen.fill((0, 0, 0))
364+
self.draw_board()
365+
self.draw_pieces()
366+
self.draw_highlights()
367+
self.check_game_state()
368+
pygame.display.flip()
369+
370+
clock.tick(60)
371+
372+
if __name__ == "__main__":
373+
app = ChessGame()
374+
app.run()

0 commit comments

Comments
 (0)