diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..bd3a460 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1728328548744 + + + 1728329364900 + + + + + + + + + \ No newline at end of file diff --git a/gui/__pycache__/game.cpython-310.pyc b/gui/__pycache__/game.cpython-310.pyc new file mode 100644 index 0000000..8d6abfd Binary files /dev/null and b/gui/__pycache__/game.cpython-310.pyc differ diff --git a/gui/__pycache__/game.cpython-39.pyc b/gui/__pycache__/game.cpython-39.pyc new file mode 100644 index 0000000..ee2e831 Binary files /dev/null and b/gui/__pycache__/game.cpython-39.pyc differ diff --git a/gui/__pycache__/tchess.cpython-310.pyc b/gui/__pycache__/tchess.cpython-310.pyc new file mode 100644 index 0000000..e7026e8 Binary files /dev/null and b/gui/__pycache__/tchess.cpython-310.pyc differ diff --git a/gui/__pycache__/tchess.cpython-39.pyc b/gui/__pycache__/tchess.cpython-39.pyc new file mode 100644 index 0000000..331fa98 Binary files /dev/null and b/gui/__pycache__/tchess.cpython-39.pyc differ diff --git a/gui/events/__pycache__/event.cpython-310.pyc b/gui/events/__pycache__/event.cpython-310.pyc new file mode 100644 index 0000000..e5983d9 Binary files /dev/null and b/gui/events/__pycache__/event.cpython-310.pyc differ diff --git a/gui/events/__pycache__/mouse_events.cpython-310.pyc b/gui/events/__pycache__/mouse_events.cpython-310.pyc new file mode 100644 index 0000000..b834de7 Binary files /dev/null and b/gui/events/__pycache__/mouse_events.cpython-310.pyc differ diff --git a/gui/events/event.py b/gui/events/event.py new file mode 100644 index 0000000..a43b82d --- /dev/null +++ b/gui/events/event.py @@ -0,0 +1,13 @@ +class Event: + listeners: list = [] + + def call(self): + for listener in Event.listeners: + if type(listener) == list: + listener[0](listener[1]) + else: + listener() + + def addListener(func, mself = None): + Event.listeners.append(func) if mself == None else Event.listeners.append([func, mself]) + diff --git a/gui/events/mouse_events.py b/gui/events/mouse_events.py new file mode 100644 index 0000000..a3098a6 --- /dev/null +++ b/gui/events/mouse_events.py @@ -0,0 +1,36 @@ +from gui.events.event import * + +class MouseEvent(Event): + def __init__(self, mouseX: int, mouseY: int, mouseButton: int) -> None: + super().__init__() + self.mouseX = mouseX + self.mouseY = mouseY + self.mouseButton = mouseButton + + def call(self): + for listener in MouseEvent.listeners: + if type(listener) == list: + listener[0](listener[1], self.mouseX, self.mouseY, self.mouseButton) + else: + listener(self.mouseX, self.mouseY, self.mouseButton) + + +class ClickEvent(MouseEvent): + def __init__(self, mouseX: int, mouseY: int, mouseButton: int) -> None: + super().__init__(mouseX, mouseY, mouseButton) + +class ReleaseEvent(MouseEvent): + def __init__(self, mouseX: int, mouseY: int, mouseButton: int) -> None: + super().__init__(mouseX, mouseY, mouseButton) + +class DragEvent(MouseEvent): + def __init__(self, piece: int, mouseX: int, mouseY: int, mouseButton: int) -> None: + super().__init__(mouseX, mouseY, mouseButton) + self.piece = piece + + def call(self): + for listener in DragEvent.listeners: + if type(listener) == list: + listener[0](listener[1], self.mouseX, self.mouseY, self.mouseButton, self.piece) + else: + listener(self.mouseX, self.mouseY, self.mouseButton, self.piece) \ No newline at end of file diff --git a/gui/game.py b/gui/game.py index 19f3a81..8316b85 100644 --- a/gui/game.py +++ b/gui/game.py @@ -1,8 +1,26 @@ import pygame as pg -import os +import platform -WHITE = 0 -BLACK = 1 + +''' +The system used is a 5-bit encoding, with the first 2 bits representing the team of the piece. + WHITE = 0b10000 + BLACK = 0b01000 + +The last 3 bits represent the type of piece. + KING = 0b00001 + QUEEN = 0b00010 + BISHOP = 0b00011 + KNIGHT = 0b00100 + ROOK = 0b00101 + PAWN = 0b00111 + +If we want a white rook for example, we do a bitwise OR operation. +Example: WHITE | ROOK = 16 | 5 + = 0b10101 +''' +WHITE = 16 +BLACK = 8 KING = 1 QUEEN = 2 @@ -13,37 +31,31 @@ class Game(): def __init__(self): - self.board = [[[5,1], [4,1], [3,1], [2,1], [1,1], [3,1], [4,1], [5,1]], - [[6,1], [6,1], [6,1], [6,1], [6,1], [6,1], [6,1], [6,1]], - [[0], [0], [0], [0], [0], [0], [0], [0]], - [[0], [0], [0], [0], [0], [0], [0], [0]], - [[0], [0], [0], [0], [0], [0], [0], [0]], - [[0], [0], [0], [0], [0], [0], [0], [0]], - [[6,0], [6,0], [6,0], [6,0], [6,0], [6,0], [6,0], [6,0]], - [[5, 0], [4, 0], [3, 0], [1, 0], [2, 0], [3, 0], [4, 0], [5, 0]]] - self.turn = 'Player' - self.moves = {'1' : ([(0, 1), (0, -1), (1, 1), (-1, -1), (1, -1), (-1, 1), (1, 0), (-1, 0)], 1, 1), - '2' : ([(0, 8), (0, -8), (8, 8), (-8, -8), (8, -8), (-8, 8), (8, 0), (-8, 0)], 1, 8), - '3' : ([(3, 1), (3, -1), (-3, 1), (-3, -1), (1, -3), (-1, -3), (1, 3), (-1, 3)], 2, 0) - } - def next_turn(self): - - - self.turn = 'Bot' - - -class Pieces(): - def __init__(self): - self.board = Game() - self.pieces_index = ['white_1', 'black_1', 'white_2', 'black_2', 'white_3', 'black_3', 'white_4', 'black_4', 'white_5', 'black_5', 'white_6', 'black_6' ] - self.pieces = [] - for i in range(8): - for j in range(8): - if not self.board.board[i][j] == [0]: - name_of = self.pieces_index[self.board.board[i][j][0]*2-self.board.board[i][j][1]-1] - item = [j, i,pg.image.load(('ressources\\' + name_of + '.png')), self.board.board[i][j][0]] - self.pieces.append(item) - self.board.next_turn() - - - + self.boardSize = 512 + self.board = [0 for i in range(64)] + self.board[0] = WHITE | PAWN + self.board[5] = BLACK | KING + + prefix = "resources\\" if platform.system() == "Windows" else "resources/" + + self.pieces_tex = { + 0: None, + + WHITE | KING: pg.image.load(f"{prefix}white_1.png"), + WHITE | QUEEN: pg.image.load(f"{prefix}white_2.png"), + WHITE | BISHOP: pg.image.load(f"{prefix}white_3.png"), + WHITE | KNIGHT: pg.image.load(f"{prefix}white_4.png"), + WHITE | ROOK: pg.image.load(f"{prefix}white_5.png"), + WHITE | PAWN: pg.image.load(f"{prefix}white_6.png"), + + BLACK | KING: pg.image.load(f"{prefix}black_1.png"), + BLACK | QUEEN: pg.image.load(f"{prefix}black_2.png"), + BLACK | BISHOP: pg.image.load(f"{prefix}black_3.png"), + BLACK | KNIGHT: pg.image.load(f"{prefix}black_4.png"), + BLACK | ROOK: pg.image.load(f"{prefix}black_5.png"), + BLACK | PAWN: pg.image.load(f"{prefix}black_6.png"), + } + + for key in self.pieces_tex.keys(): + if key != 0: + self.pieces_tex[key] = pg.transform.scale(self.pieces_tex[key], (self.boardSize/8, self.boardSize/8)) \ No newline at end of file diff --git a/gui/tchess.py b/gui/tchess.py index b2727af..12ab4ee 100644 --- a/gui/tchess.py +++ b/gui/tchess.py @@ -1,5 +1,7 @@ import pygame as pg import gui.game as game +import gui.events.event as event +from gui.events.mouse_events import * class Aplication(): def __init__(self): @@ -11,9 +13,22 @@ def __init__(self): self.FPS = 120 self.running = True self.clicking = False - self.mouse_pos = (0, 0) - self.game = game.Pieces() - self.select = (0, 0) + self.game = game.Game() + self.mouseState = [False, False, False, (0, 0)] + self.dragState = {"x": 0, "y": 0, "piece": 0, "offsetX": 0, "offsetY": 0} + ClickEvent.addListener(self.onStartDrag, self) + + def get_piece_at(self, pos: tuple[int, int]): + x = int(pos[0]/64) + y = int(pos[1]/64) + i = 8*y+x + return self.game.board[i] if i >= 0 and i <= 63 else None + + def onStartDrag(self, mouseX: int, mouseY: int, mouseButton: int, piece: int): + self.dragState["x"] = mouseX + self.dragState["y"] = mouseY + self.dragState["piece"] = piece + print("cacadrag") def update(self): self.mouse_pos = pg.mouse.get_pos() @@ -22,44 +37,34 @@ def update(self): if event.type == pg.QUIT: self.running = False exit() - pg.quit() - if pg.mouse.get_pressed()[0]: - self.clicking = True - else: - self.clicking = False - if self.clicking: - for i in self.game.pieces: - idle = pg.Rect(i[0]*self.size, i[1]*self.size, self.size, self.size) - if idle.collidepoint(self.mouse_pos): - self.select = (i[0]*self.size, i[1]*self.size) - moves = self.game.board.moves[str(i[3])] - for j in moves[0]: - if moves[1] == 1: - for k in range(moves[2], 0, -1): - pg.draw.circle(self.screen, (255, 255, 255), (self.select[0]+k*self.size, self.select[1]+k*self.size), 20) - pg.display.update(pg.draw.circle(self.screen, (255, 255, 255), (self.select), 20)) - print(self.select[0]+k, self.select[1]+k) - while True: - self.mouse_pos = pg.mouse.get_pos() - for event in pg.event.get(): - if event.type == pg.QUIT: - pg.quit() - - + + c = pg.mouse.get_pressed() + piece = self.get_piece_at(pg.mouse.get_pos()) + for i in range(3): + if self.mouseState[i] != c[i]: # If the button state is not the same as the one registered last frame, call an event. + self.mouseState[i] = c[i] + if c[i]: + ClickEvent(self.mouseState[3][0], self.mouseState[3][1], i).call() + else: + ReleaseEvent(self.mouseState[3][0], self.mouseState[3][1], i).call() + elif c[i]: + DragEvent(piece, self.mouseState[3][0], self.mouseState[3][1], i).call() # do stuff - self.drawing(50) + self.render() pg.display.flip() pg.display.set_caption('Chess Bot vs Player Game | ' + str(round(self.clock.get_fps(), 1))) self.clock.tick(self.FPS) - def drawing(self, a): - colors = ((237, 212, 175), (170, 125, 92)) - for i in range(8): - for j in range(8): - pg.draw.rect(self.screen, colors[(i+j)%2], pg.Rect(self.size*i, self.size*j, self.size, self.size)) - - for i in self.game.pieces: - idle = i[2].get_rect(center=(i[0]*self.size+self.size/2, i[1]*self.size+self.size/2)) - self.screen.blit(i[2], idle) + def render(self): + col = ((237, 212, 175), (170, 125, 92)) + sqrSize = self.game.boardSize/8 + for y in range(8): + for x in range(8): + current_piece = self.game.board[8*y+x] + pg.draw.rect(self.screen, col[(x+y)%2], pg.Rect(x*sqrSize, y*sqrSize, sqrSize, sqrSize)) + if current_piece != 0: + self.screen.blit(self.game.pieces_tex[current_piece], pg.Rect(x*sqrSize, y*sqrSize, sqrSize, sqrSize)) + + diff --git a/main.py b/main.py index 678c4f0..0214e29 100644 --- a/main.py +++ b/main.py @@ -1,7 +1,5 @@ - - ''' -Change the variable MODE to test either the GUI mode or the Terminal mode +Change the variable MODE to test either the GUI mode or the Terminal mode. Note that Terminal mode is currently not working well. ''' MODE = "GUI" diff --git a/ressources/black_1.png b/resources/black_1.png similarity index 100% rename from ressources/black_1.png rename to resources/black_1.png diff --git a/ressources/black_2.png b/resources/black_2.png similarity index 100% rename from ressources/black_2.png rename to resources/black_2.png diff --git a/ressources/black_3.png b/resources/black_3.png similarity index 100% rename from ressources/black_3.png rename to resources/black_3.png diff --git a/ressources/black_4.png b/resources/black_4.png similarity index 100% rename from ressources/black_4.png rename to resources/black_4.png diff --git a/ressources/black_5.png b/resources/black_5.png similarity index 100% rename from ressources/black_5.png rename to resources/black_5.png diff --git a/ressources/black_6.png b/resources/black_6.png similarity index 100% rename from ressources/black_6.png rename to resources/black_6.png diff --git a/ressources/idle b/resources/idle similarity index 100% rename from ressources/idle rename to resources/idle diff --git a/ressources/white_1.png b/resources/white_1.png similarity index 100% rename from ressources/white_1.png rename to resources/white_1.png diff --git a/ressources/white_2.png b/resources/white_2.png similarity index 100% rename from ressources/white_2.png rename to resources/white_2.png diff --git a/ressources/white_3.png b/resources/white_3.png similarity index 100% rename from ressources/white_3.png rename to resources/white_3.png diff --git a/ressources/white_4.png b/resources/white_4.png similarity index 100% rename from ressources/white_4.png rename to resources/white_4.png diff --git a/ressources/white_5.png b/resources/white_5.png similarity index 100% rename from ressources/white_5.png rename to resources/white_5.png diff --git a/ressources/white_6.png b/resources/white_6.png similarity index 100% rename from ressources/white_6.png rename to resources/white_6.png