Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chess game #374

Merged
merged 3 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added GAMES/chess/assets/images/imgs-80px/black_pawn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added GAMES/chess/assets/images/imgs-80px/black_rook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added GAMES/chess/assets/sounds/capture.wav
Binary file not shown.
Binary file added GAMES/chess/assets/sounds/move.wav
Binary file not shown.
455 changes: 455 additions & 0 deletions GAMES/chess/src/board.py

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions GAMES/chess/src/color.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
class Color:
def __init__(self, light, dark):
self.light = light
self.dark = dark
60 changes: 60 additions & 0 deletions GAMES/chess/src/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import pygame
import os

from sound import Sound
from theme import Theme


class Config:
def __init__(self):
# themes code
self.themes = []
self._add_themes()
self.idx = 0
self.theme = self.themes[self.idx]
# font
self.font = pygame.font.SysFont("monospace", 18, bold=True)
# sound file path
self.move_sound = Sound(os.path.join("assets/sounds/move.wav"))
self.capture_sound = Sound(os.path.join("assets/sounds/capture.wav"))

def change_theme(self):
self.idx += 1
self.idx %= len(self.themes)
self.theme = self.themes[self.idx]

def _add_themes(self):
green = Theme(
(234, 235, 200),
(119, 154, 88),
(244, 247, 116),
(172, 195, 51),
"#C86464",
"#C84646",
)
brown = Theme(
(235, 209, 166),
(165, 117, 80),
(245, 234, 100),
(209, 185, 59),
"#C86464",
"#C84646",
)
blue = Theme(
(229, 228, 200),
(60, 95, 135),
(124, 187, 227),
(43, 119, 191),
"#C86464",
"#C84646",
)
gray = Theme(
(128, 119, 118),
(86, 85, 84),
(99, 126, 143),
(82, 102, 128),
"#C86464",
"#C84646",
)

self.themes = [green, brown, blue, gray]
8 changes: 8 additions & 0 deletions GAMES/chess/src/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Screen dimensions
WIDTH = 700
HEIGHT = 700

# Board dimensions
ROWS = 8
COLS = 8
SQSIZE = WIDTH // COLS
46 changes: 46 additions & 0 deletions GAMES/chess/src/dragger.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import pygame

from const import *


class Dragger:
def __init__(self):
self.piece = None
self.dragging = False
self.mouseX = 0
self.mouseY = 0
self.initial_row = 0
self.initial_col = 0

# blit method

def update_blit(self, surface):
# texture
self.piece.set_texture(size=80)
texture = self.piece.texture
# image
img = pygame.image.load(texture)

# drag coordinates
img_center = (self.mouseX, self.mouseY)
self.piece.texture_rect = img.get_rect(center=img_center)

# update blit
surface.blit(img, self.piece.texture_rect)

# other dragging methods

def update_mouse(self, pos):
self.mouseX, self.mouseY = pos

def save_initial(self, pos):
self.initial_row = pos[1] // SQSIZE
self.initial_col = pos[0] // SQSIZE

def drag_piece(self, piece):
self.piece = piece
self.dragging = True

def undrag_piece(self):
self.piece = None
self.dragging = False
150 changes: 150 additions & 0 deletions GAMES/chess/src/game.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import pygame

from const import *
from board import Board
from dragger import Dragger
from config import Config
from square import Square


class Game:
def __init__(self):
self.next_player = "white"
self.hovered_sqr = None
self.board = Board()
self.dragger = Dragger()
self.config = Config()

# background display
def show_bg(self, surface):
theme = self.config.theme

for row in range(ROWS):
for col in range(COLS):
# color
color = theme.bg.light if (row + col) % 2 == 0 else theme.bg.dark
# rect
rect = (col * SQSIZE, row * SQSIZE, SQSIZE, SQSIZE)
# blit
pygame.draw.rect(surface, color, rect)

# row coordinates
if col == 0:
# color
color = theme.bg.dark if row % 2 == 0 else theme.bg.light
# label
lbl = self.config.font.render(str(ROWS - row), 1, color)
lbl_pos = (5, 5 + row * SQSIZE)
# blit
surface.blit(lbl, lbl_pos)

# col coordinates
if row == 7:
# color
color = theme.bg.dark if (row + col) % 2 == 0 else theme.bg.light
# label
lbl = self.config.font.render(Square.get_alphacol(col), 1, color)
lbl_pos = (col * SQSIZE + SQSIZE - 20, HEIGHT - 20)
# blit
surface.blit(lbl, lbl_pos)

def show_pieces(self, surface):
for row in range(ROWS):
for col in range(COLS):
if self.board.squares[row][col].has_piece():
piece = self.board.squares[row][col].piece
if piece is not self.dragger.piece:
piece.set_texture(size=80)
img = pygame.image.load(piece.texture)
img_center = (
col * SQSIZE + SQSIZE // 2,
row * SQSIZE + SQSIZE // 2,
)
piece.texture_rect = img.get_rect(center=img_center)
surface.blit(img, piece.texture_rect)

def show_moves(self, surface):
theme = self.config.theme
if self.dragger.dragging:
piece = self.dragger.piece

# loop all valid moves
for move in piece.moves:
# color
color = (
theme.moves.light
if (move.final.row + move.final.col) % 2 == 0
else theme.moves.dark
)
# rect
rect = (
move.final.col * SQSIZE,
move.final.row * SQSIZE,
SQSIZE,
SQSIZE,
)
# blit
pygame.draw.rect(surface, color, rect)

# circle
# center_x = move.final.col * SQSIZE + SQSIZE // 2
# center_y = move.final.row * SQSIZE + SQSIZE // 2
# radius = SQSIZE // 6
# blit
# pygame.draw.circle(surface, color, (center_x, center_y), radius)

def show_last_move(self, surface):
theme = self.config.theme

if self.board.last_move:
initial = self.board.last_move.initial
final = self.board.last_move.final

for pos in [initial, final]:
# color
color = (
theme.trace.light
if (pos.row + pos.col) % 2 == 0
else theme.trace.dark
)
# rect
rect = (pos.col * SQSIZE, pos.row * SQSIZE, SQSIZE, SQSIZE)
# blit
pygame.draw.rect(surface, color, rect)

def show_hover(self, surface):
if self.hovered_sqr:
# color
color = (180, 180, 180)
# rect
rect = (
self.hovered_sqr.col * SQSIZE,
self.hovered_sqr.row * SQSIZE,
SQSIZE,
SQSIZE,
)
# blit
pygame.draw.rect(surface, color, rect, width=3)

def next_turn(self):
self.next_player = "white" if self.next_player == "black" else "black"

def set_hover(self, row, col):
if 0 <= row < ROWS and 0 <= col < COLS:
self.hovered_sqr = self.board.squares[row][col]
else:
# Handle the case where the indices are out of range
# print(f"Invalid indices: row={row}, col={col}")
self.hovered_sqr = None

def change_theme(self):
self.config.change_theme()

def play_sound(self, captured=False):
if captured:
self.config.capture_sound.play()
else:
self.config.move_sound.play()

def reset(self):
self.__init__()
126 changes: 126 additions & 0 deletions GAMES/chess/src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import pygame
import sys

from const import *
from game import Game
from square import Square
from move import Move


class Main:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Chess")
self.game = Game()

def mainloop(self):
screen = self.screen
game = self.game
board = self.game.board
dragger = self.game.dragger

while True:
# display methods
game.show_bg(screen)
game.show_last_move(screen)
game.show_moves(screen)
game.show_pieces(screen)

game.show_hover(screen)

if dragger.dragging:
dragger.update_blit(screen)

for event in pygame.event.get():
# click
if event.type == pygame.MOUSEBUTTONDOWN:
dragger.update_mouse(event.pos)
# print(event.pos)

clicked_row = dragger.mouseY // SQSIZE
clicked_col = dragger.mouseX // SQSIZE

# print(dragger.mouseY, clicked_row)
# print(dragger.mouseX, clicked_col)

# if clicked square has a piece
if board.squares[clicked_row][clicked_col].has_piece():
piece = board.squares[clicked_row][clicked_col].piece
if piece.color == game.next_player:
board.calc_moves(piece, clicked_row, clicked_col, bool=True)
dragger.save_initial(event.pos)
dragger.drag_piece(piece)
# display methods
game.show_bg(screen)
game.show_last_move(screen)
game.show_moves(screen)
game.show_pieces(screen)

# dragging the pieces
elif event.type == pygame.MOUSEMOTION:
motion_row = event.pos[1] // SQSIZE
motion_col = event.pos[0] // SQSIZE
game.set_hover(motion_row, motion_col)
if dragger.dragging:
dragger.update_mouse(event.pos)
# display methods
game.show_bg(screen)
game.show_last_move(screen)
game.show_moves(screen)
game.show_pieces(screen)
game.show_hover(screen)
dragger.update_blit(screen)

# mouse release
elif event.type == pygame.MOUSEBUTTONUP:
if dragger.dragging:
dragger.update_mouse(event.pos)
released_row = dragger.mouseY // SQSIZE
released_col = dragger.mouseX // SQSIZE

initial = Square(dragger.initial_row, dragger.initial_col)
final = Square(released_row, released_col)
move = Move(initial, final)

if board.valid_move(dragger.piece, move):
captured = board.squares[released_row][
released_col
].has_piece()

board.move(dragger.piece, move)
board.set_true_en_passant(dragger.piece)
game.play_sound(captured)
# display move methods
game.show_bg(screen)
game.show_last_move(screen)
game.show_pieces(screen)

# next turn
game.next_turn()

dragger.undrag_piece()

# key press
elif event.type == pygame.KEYDOWN:
# change themes
if event.key == pygame.K_t:
game.change_theme()

# restart event
if event.key == pygame.K_r:
game.reset()
game = self.game
board = self.game.board
dragger = self.game.dragger

# quit application
elif event.type == pygame.QUIT:
pygame.quit()
sys.exit()

pygame.display.update()


main = Main()
main.mainloop()
Loading
Loading