Skip to content

Commit 5456f25

Browse files
authored
Merge pull request #374 from sahilrw/chess-game
Chess game
2 parents 01eea30 + 6785fb7 commit 5456f25

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1181
-0
lines changed
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
Loading
933 Bytes
Loading
Loading
1016 Bytes
Loading
Loading
Loading
Loading
Loading
Loading
Loading

GAMES/chess/assets/sounds/capture.wav

8.84 KB
Binary file not shown.

GAMES/chess/assets/sounds/move.wav

1.38 KB
Binary file not shown.

GAMES/chess/src/board.py

+455
Large diffs are not rendered by default.

GAMES/chess/src/color.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class Color:
2+
def __init__(self, light, dark):
3+
self.light = light
4+
self.dark = dark

GAMES/chess/src/config.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import pygame
2+
import os
3+
4+
from sound import Sound
5+
from theme import Theme
6+
7+
8+
class Config:
9+
def __init__(self):
10+
# themes code
11+
self.themes = []
12+
self._add_themes()
13+
self.idx = 0
14+
self.theme = self.themes[self.idx]
15+
# font
16+
self.font = pygame.font.SysFont("monospace", 18, bold=True)
17+
# sound file path
18+
self.move_sound = Sound(os.path.join("assets/sounds/move.wav"))
19+
self.capture_sound = Sound(os.path.join("assets/sounds/capture.wav"))
20+
21+
def change_theme(self):
22+
self.idx += 1
23+
self.idx %= len(self.themes)
24+
self.theme = self.themes[self.idx]
25+
26+
def _add_themes(self):
27+
green = Theme(
28+
(234, 235, 200),
29+
(119, 154, 88),
30+
(244, 247, 116),
31+
(172, 195, 51),
32+
"#C86464",
33+
"#C84646",
34+
)
35+
brown = Theme(
36+
(235, 209, 166),
37+
(165, 117, 80),
38+
(245, 234, 100),
39+
(209, 185, 59),
40+
"#C86464",
41+
"#C84646",
42+
)
43+
blue = Theme(
44+
(229, 228, 200),
45+
(60, 95, 135),
46+
(124, 187, 227),
47+
(43, 119, 191),
48+
"#C86464",
49+
"#C84646",
50+
)
51+
gray = Theme(
52+
(128, 119, 118),
53+
(86, 85, 84),
54+
(99, 126, 143),
55+
(82, 102, 128),
56+
"#C86464",
57+
"#C84646",
58+
)
59+
60+
self.themes = [green, brown, blue, gray]

GAMES/chess/src/const.py

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Screen dimensions
2+
WIDTH = 700
3+
HEIGHT = 700
4+
5+
# Board dimensions
6+
ROWS = 8
7+
COLS = 8
8+
SQSIZE = WIDTH // COLS

GAMES/chess/src/dragger.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import pygame
2+
3+
from const import *
4+
5+
6+
class Dragger:
7+
def __init__(self):
8+
self.piece = None
9+
self.dragging = False
10+
self.mouseX = 0
11+
self.mouseY = 0
12+
self.initial_row = 0
13+
self.initial_col = 0
14+
15+
# blit method
16+
17+
def update_blit(self, surface):
18+
# texture
19+
self.piece.set_texture(size=80)
20+
texture = self.piece.texture
21+
# image
22+
img = pygame.image.load(texture)
23+
24+
# drag coordinates
25+
img_center = (self.mouseX, self.mouseY)
26+
self.piece.texture_rect = img.get_rect(center=img_center)
27+
28+
# update blit
29+
surface.blit(img, self.piece.texture_rect)
30+
31+
# other dragging methods
32+
33+
def update_mouse(self, pos):
34+
self.mouseX, self.mouseY = pos
35+
36+
def save_initial(self, pos):
37+
self.initial_row = pos[1] // SQSIZE
38+
self.initial_col = pos[0] // SQSIZE
39+
40+
def drag_piece(self, piece):
41+
self.piece = piece
42+
self.dragging = True
43+
44+
def undrag_piece(self):
45+
self.piece = None
46+
self.dragging = False

GAMES/chess/src/game.py

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import pygame
2+
3+
from const import *
4+
from board import Board
5+
from dragger import Dragger
6+
from config import Config
7+
from square import Square
8+
9+
10+
class Game:
11+
def __init__(self):
12+
self.next_player = "white"
13+
self.hovered_sqr = None
14+
self.board = Board()
15+
self.dragger = Dragger()
16+
self.config = Config()
17+
18+
# background display
19+
def show_bg(self, surface):
20+
theme = self.config.theme
21+
22+
for row in range(ROWS):
23+
for col in range(COLS):
24+
# color
25+
color = theme.bg.light if (row + col) % 2 == 0 else theme.bg.dark
26+
# rect
27+
rect = (col * SQSIZE, row * SQSIZE, SQSIZE, SQSIZE)
28+
# blit
29+
pygame.draw.rect(surface, color, rect)
30+
31+
# row coordinates
32+
if col == 0:
33+
# color
34+
color = theme.bg.dark if row % 2 == 0 else theme.bg.light
35+
# label
36+
lbl = self.config.font.render(str(ROWS - row), 1, color)
37+
lbl_pos = (5, 5 + row * SQSIZE)
38+
# blit
39+
surface.blit(lbl, lbl_pos)
40+
41+
# col coordinates
42+
if row == 7:
43+
# color
44+
color = theme.bg.dark if (row + col) % 2 == 0 else theme.bg.light
45+
# label
46+
lbl = self.config.font.render(Square.get_alphacol(col), 1, color)
47+
lbl_pos = (col * SQSIZE + SQSIZE - 20, HEIGHT - 20)
48+
# blit
49+
surface.blit(lbl, lbl_pos)
50+
51+
def show_pieces(self, surface):
52+
for row in range(ROWS):
53+
for col in range(COLS):
54+
if self.board.squares[row][col].has_piece():
55+
piece = self.board.squares[row][col].piece
56+
if piece is not self.dragger.piece:
57+
piece.set_texture(size=80)
58+
img = pygame.image.load(piece.texture)
59+
img_center = (
60+
col * SQSIZE + SQSIZE // 2,
61+
row * SQSIZE + SQSIZE // 2,
62+
)
63+
piece.texture_rect = img.get_rect(center=img_center)
64+
surface.blit(img, piece.texture_rect)
65+
66+
def show_moves(self, surface):
67+
theme = self.config.theme
68+
if self.dragger.dragging:
69+
piece = self.dragger.piece
70+
71+
# loop all valid moves
72+
for move in piece.moves:
73+
# color
74+
color = (
75+
theme.moves.light
76+
if (move.final.row + move.final.col) % 2 == 0
77+
else theme.moves.dark
78+
)
79+
# rect
80+
rect = (
81+
move.final.col * SQSIZE,
82+
move.final.row * SQSIZE,
83+
SQSIZE,
84+
SQSIZE,
85+
)
86+
# blit
87+
pygame.draw.rect(surface, color, rect)
88+
89+
# circle
90+
# center_x = move.final.col * SQSIZE + SQSIZE // 2
91+
# center_y = move.final.row * SQSIZE + SQSIZE // 2
92+
# radius = SQSIZE // 6
93+
# blit
94+
# pygame.draw.circle(surface, color, (center_x, center_y), radius)
95+
96+
def show_last_move(self, surface):
97+
theme = self.config.theme
98+
99+
if self.board.last_move:
100+
initial = self.board.last_move.initial
101+
final = self.board.last_move.final
102+
103+
for pos in [initial, final]:
104+
# color
105+
color = (
106+
theme.trace.light
107+
if (pos.row + pos.col) % 2 == 0
108+
else theme.trace.dark
109+
)
110+
# rect
111+
rect = (pos.col * SQSIZE, pos.row * SQSIZE, SQSIZE, SQSIZE)
112+
# blit
113+
pygame.draw.rect(surface, color, rect)
114+
115+
def show_hover(self, surface):
116+
if self.hovered_sqr:
117+
# color
118+
color = (180, 180, 180)
119+
# rect
120+
rect = (
121+
self.hovered_sqr.col * SQSIZE,
122+
self.hovered_sqr.row * SQSIZE,
123+
SQSIZE,
124+
SQSIZE,
125+
)
126+
# blit
127+
pygame.draw.rect(surface, color, rect, width=3)
128+
129+
def next_turn(self):
130+
self.next_player = "white" if self.next_player == "black" else "black"
131+
132+
def set_hover(self, row, col):
133+
if 0 <= row < ROWS and 0 <= col < COLS:
134+
self.hovered_sqr = self.board.squares[row][col]
135+
else:
136+
# Handle the case where the indices are out of range
137+
# print(f"Invalid indices: row={row}, col={col}")
138+
self.hovered_sqr = None
139+
140+
def change_theme(self):
141+
self.config.change_theme()
142+
143+
def play_sound(self, captured=False):
144+
if captured:
145+
self.config.capture_sound.play()
146+
else:
147+
self.config.move_sound.play()
148+
149+
def reset(self):
150+
self.__init__()

GAMES/chess/src/main.py

+126
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import pygame
2+
import sys
3+
4+
from const import *
5+
from game import Game
6+
from square import Square
7+
from move import Move
8+
9+
10+
class Main:
11+
def __init__(self):
12+
pygame.init()
13+
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
14+
pygame.display.set_caption("Chess")
15+
self.game = Game()
16+
17+
def mainloop(self):
18+
screen = self.screen
19+
game = self.game
20+
board = self.game.board
21+
dragger = self.game.dragger
22+
23+
while True:
24+
# display methods
25+
game.show_bg(screen)
26+
game.show_last_move(screen)
27+
game.show_moves(screen)
28+
game.show_pieces(screen)
29+
30+
game.show_hover(screen)
31+
32+
if dragger.dragging:
33+
dragger.update_blit(screen)
34+
35+
for event in pygame.event.get():
36+
# click
37+
if event.type == pygame.MOUSEBUTTONDOWN:
38+
dragger.update_mouse(event.pos)
39+
# print(event.pos)
40+
41+
clicked_row = dragger.mouseY // SQSIZE
42+
clicked_col = dragger.mouseX // SQSIZE
43+
44+
# print(dragger.mouseY, clicked_row)
45+
# print(dragger.mouseX, clicked_col)
46+
47+
# if clicked square has a piece
48+
if board.squares[clicked_row][clicked_col].has_piece():
49+
piece = board.squares[clicked_row][clicked_col].piece
50+
if piece.color == game.next_player:
51+
board.calc_moves(piece, clicked_row, clicked_col, bool=True)
52+
dragger.save_initial(event.pos)
53+
dragger.drag_piece(piece)
54+
# display methods
55+
game.show_bg(screen)
56+
game.show_last_move(screen)
57+
game.show_moves(screen)
58+
game.show_pieces(screen)
59+
60+
# dragging the pieces
61+
elif event.type == pygame.MOUSEMOTION:
62+
motion_row = event.pos[1] // SQSIZE
63+
motion_col = event.pos[0] // SQSIZE
64+
game.set_hover(motion_row, motion_col)
65+
if dragger.dragging:
66+
dragger.update_mouse(event.pos)
67+
# display methods
68+
game.show_bg(screen)
69+
game.show_last_move(screen)
70+
game.show_moves(screen)
71+
game.show_pieces(screen)
72+
game.show_hover(screen)
73+
dragger.update_blit(screen)
74+
75+
# mouse release
76+
elif event.type == pygame.MOUSEBUTTONUP:
77+
if dragger.dragging:
78+
dragger.update_mouse(event.pos)
79+
released_row = dragger.mouseY // SQSIZE
80+
released_col = dragger.mouseX // SQSIZE
81+
82+
initial = Square(dragger.initial_row, dragger.initial_col)
83+
final = Square(released_row, released_col)
84+
move = Move(initial, final)
85+
86+
if board.valid_move(dragger.piece, move):
87+
captured = board.squares[released_row][
88+
released_col
89+
].has_piece()
90+
91+
board.move(dragger.piece, move)
92+
board.set_true_en_passant(dragger.piece)
93+
game.play_sound(captured)
94+
# display move methods
95+
game.show_bg(screen)
96+
game.show_last_move(screen)
97+
game.show_pieces(screen)
98+
99+
# next turn
100+
game.next_turn()
101+
102+
dragger.undrag_piece()
103+
104+
# key press
105+
elif event.type == pygame.KEYDOWN:
106+
# change themes
107+
if event.key == pygame.K_t:
108+
game.change_theme()
109+
110+
# restart event
111+
if event.key == pygame.K_r:
112+
game.reset()
113+
game = self.game
114+
board = self.game.board
115+
dragger = self.game.dragger
116+
117+
# quit application
118+
elif event.type == pygame.QUIT:
119+
pygame.quit()
120+
sys.exit()
121+
122+
pygame.display.update()
123+
124+
125+
main = Main()
126+
main.mainloop()

0 commit comments

Comments
 (0)