From 6ce7e540b86954ffee4f757ab72d9eace2634f58 Mon Sep 17 00:00:00 2001 From: VincentAuriau Date: Sat, 21 Oct 2023 09:12:18 +0000 Subject: [PATCH] :art: Format Python code with psf/black --- python/engine/color.py | 2 +- python/engine/engine.py | 237 ++++++++++++++++++++------------ python/engine/material.py | 138 +++++++++++++------ python/engine/move.py | 76 ++++++---- python/interface/interface.py | 157 +++++++++++++-------- python/player/ai_player.py | 94 +++++++++---- python/player/my_player.py | 54 ++++---- python/player/player.py | 29 ++-- python/utils/images_creation.py | 12 +- python/utils/profile_game.py | 8 +- python/utils/training_ai.py | 1 - run_app.py | 3 +- tests/engine_test.py | 50 ++++--- 13 files changed, 545 insertions(+), 316 deletions(-) diff --git a/python/engine/color.py b/python/engine/color.py index b9941f4..4b2c455 100644 --- a/python/engine/color.py +++ b/python/engine/color.py @@ -1,4 +1,4 @@ class Color: GREEN = "\x1b[32m" - WHITE = '\033[0m' + WHITE = "\033[0m" RED = "\x1b[31m" diff --git a/python/engine/engine.py b/python/engine/engine.py index 7d91d1a..e9b0fea 100644 --- a/python/engine/engine.py +++ b/python/engine/engine.py @@ -16,7 +16,7 @@ class Color: GREEN = "\x1b[32m" - WHITE = '\033[0m' + WHITE = "\033[0m" RED = "\x1b[31m" @@ -39,7 +39,6 @@ def set_piece(self, piece): self.piece.x = self.x self.piece.y = self.y - def get_piece(self): return self.piece @@ -49,9 +48,20 @@ def get_x(self): def get_y(self): return self.y - def is_threatened(self, board, threaten_color): # change threaten_color par #white_threatened + def is_threatened( + self, board, threaten_color + ): # change threaten_color par #white_threatened # Check Knights threatening - for i, j in [(2, 1), (-2, 1), (2, -1), (-2, -1), (1, 2), (1, -2), (-1, 2), (-1, -2)]: + for i, j in [ + (2, 1), + (-2, 1), + (2, -1), + (-2, -1), + (1, 2), + (1, -2), + (-1, 2), + (-1, -2), + ]: x_to_check = self.x + i y_to_check = self.y + j @@ -72,8 +82,11 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.King) or isinstance(piece_to_check, material.Rook) or isinstance(piece_to_check, - material.Queen): + if ( + isinstance(piece_to_check, material.King) + or isinstance(piece_to_check, material.Rook) + or isinstance(piece_to_check, material.Queen) + ): if piece_to_check.is_white() != threaten_color: return True @@ -85,7 +98,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Rook) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Rook) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -100,7 +115,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Rook) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Rook) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -115,7 +132,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Rook) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Rook) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -130,7 +149,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Rook) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Rook) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -147,14 +168,25 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.King) or isinstance(piece_to_check, material.Bishop) or isinstance(piece_to_check, - material.Queen): + if ( + isinstance(piece_to_check, material.King) + or isinstance(piece_to_check, material.Bishop) + or isinstance(piece_to_check, material.Queen) + ): if piece_to_check.is_white() != threaten_color: return True - elif i > 0 and threaten_color and isinstance(piece_to_check, material.Pawn): + elif ( + i > 0 + and threaten_color + and isinstance(piece_to_check, material.Pawn) + ): if piece_to_check.is_white() != threaten_color: return True - elif i < 0 and not threaten_color and isinstance(piece_to_check, material.Pawn): + elif ( + i < 0 + and not threaten_color + and isinstance(piece_to_check, material.Pawn) + ): if piece_to_check.is_white() != threaten_color: return True @@ -166,7 +198,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Bishop) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Bishop) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -182,7 +216,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Bishop) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Bishop) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -198,7 +234,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Bishop) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Bishop) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -214,7 +252,9 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh cell_to_check = board.get_cell(x_to_check, y_to_check) piece_to_check = cell_to_check.get_piece() - if isinstance(piece_to_check, material.Bishop) or isinstance(piece_to_check, material.Queen): + if isinstance(piece_to_check, material.Bishop) or isinstance( + piece_to_check, material.Queen + ): keep_going = False if piece_to_check.is_white() != threaten_color: return True @@ -227,7 +267,6 @@ def is_threatened(self, board, threaten_color): # change threaten_color par #wh class Board: - def __init__(self, empty_init=False): if not empty_init: self.board = None @@ -238,15 +277,15 @@ def deepcopy(self, memodict={}): board = [[Cell(i, j, None) for j in range(8)] for i in range(8)] copied_object.board = board copied_material = self.deep_copy_material() - white_king = copied_material['white']['alive']['king'][0] - black_king = copied_material['black']['alive']['king'][0] + white_king = copied_material["white"]["alive"]["king"][0] + black_king = copied_material["black"]["alive"]["king"][0] copied_object.all_material = copied_material copied_object.white_king = white_king copied_object.black_king = black_king - for piece_list in copied_material['white']['alive'].values(): + for piece_list in copied_material["white"]["alive"].values(): for piece in piece_list: copied_object.get_cell(piece.x, piece.y).set_piece(piece) - for piece_list in copied_material['black']['alive'].values(): + for piece_list in copied_material["black"]["alive"].values(): for piece in piece_list: copied_object.get_cell(piece.x, piece.y).set_piece(piece) @@ -261,7 +300,7 @@ def deep_copy_material(self): "bishop": [], "rook": [], "queen": [], - "king": [] + "king": [], }, "killed": { "pawn": [], @@ -269,8 +308,8 @@ def deep_copy_material(self): "bishop": [], "rook": [], "queen": [], - "king": [] - } + "king": [], + }, }, "black": { "alive": { @@ -279,7 +318,7 @@ def deep_copy_material(self): "bishop": [], "rook": [], "queen": [], - "king": [] + "king": [], }, "killed": { "pawn": [], @@ -287,16 +326,18 @@ def deep_copy_material(self): "bishop": [], "rook": [], "queen": [], - "king": [] - } - } + "king": [], + }, + }, } - for color in ['white', 'black']: - for status in ['alive', 'killed']: - for piece_type in ['pawn', 'knight', 'bishop', 'rook', 'queen', 'king']: + for color in ["white", "black"]: + for status in ["alive", "killed"]: + for piece_type in ["pawn", "knight", "bishop", "rook", "queen", "king"]: for piece in self.all_material[color][status][piece_type]: - material[color][status][piece_type].append(piece.piece_deepcopy()) + material[color][status][piece_type].append( + piece.piece_deepcopy() + ) return material def __deepcopy__(self, memodict={}): @@ -305,15 +346,15 @@ def __deepcopy__(self, memodict={}): copied_object.board = board copied_material = self.deep_copy_material() - white_king = copied_material['white']['alive']['king'][0] - black_king = copied_material['black']['alive']['king'][0] + white_king = copied_material["white"]["alive"]["king"][0] + black_king = copied_material["black"]["alive"]["king"][0] copied_object.all_material = copied_material copied_object.white_king = white_king copied_object.black_king = black_king - for piece_list in copied_material['white']['alive'].values(): + for piece_list in copied_material["white"]["alive"].values(): for piece in piece_list: copied_object.get_cell(piece.x, piece.y).set_piece(piece) - for piece_list in copied_material['black']['alive'].values(): + for piece_list in copied_material["black"]["alive"].values(): for piece in piece_list: copied_object.get_cell(piece.x, piece.y).set_piece(piece) @@ -331,7 +372,7 @@ def to_fen(self): if no_piece_count > 0: fen += str(no_piece_count) no_piece_count = 0 - letter = piece.get_str().replace(' ', '') + letter = piece.get_str().replace(" ", "") if piece.is_white(): letter = letter.lower() fen += letter @@ -347,7 +388,7 @@ def one_hot_encode(self, white_side=True): "knight": [0, 0, 1, 0, 0, 0], "rook": [0, 0, 0, 1, 0, 0], "queen": [0, 0, 0, 0, 1, 0], - "king": [0, 0, 0, 0, 0, 1] + "king": [0, 0, 0, 0, 0, 1], } one_hot_board = [] for line in self.board: @@ -355,11 +396,11 @@ def one_hot_encode(self, white_side=True): for cell in line: piece = cell.get_piece() if piece is None: - one_hot_line.append([0]*6) + one_hot_line.append([0] * 6) else: one_hot_piece = material_to_one_hot[piece.type] if piece.is_white() != white_side: - one_hot_piece = [-1*val for val in one_hot_piece] + one_hot_piece = [-1 * val for val in one_hot_piece] one_hot_line.append(one_hot_piece) one_hot_board.append(one_hot_line) return one_hot_board @@ -387,7 +428,7 @@ def _reset_board(self): "bishop": [], "rook": [], "queen": [], - "king": [] + "king": [], }, "killed": { "pawn": [], @@ -395,8 +436,8 @@ def _reset_board(self): "bishop": [], "rook": [], "queen": [], - "king": [] - } + "king": [], + }, }, "black": { "alive": { @@ -405,7 +446,7 @@ def _reset_board(self): "bishop": [], "rook": [], "queen": [], - "king": [] + "king": [], }, "killed": { "pawn": [], @@ -413,9 +454,9 @@ def _reset_board(self): "bishop": [], "rook": [], "queen": [], - "king": [] - } - } + "king": [], + }, + }, } white_king = material.King(True, 0, 4) @@ -441,9 +482,16 @@ def _reset_board(self): w_queen = material.Queen(True, 0, 3) pieces["white"]["alive"]["queen"].append(w_queen) - line = [Cell(0, 0, w_rook_1), Cell(0, 1, w_knight_1), Cell(0, 2, w_bishop_1), - Cell(0, 3, w_queen), Cell(0, 4, white_king), Cell(0, 5, w_bishop_2), - Cell(0, 6, w_knight_2), Cell(0, 7, w_rook_2)] + line = [ + Cell(0, 0, w_rook_1), + Cell(0, 1, w_knight_1), + Cell(0, 2, w_bishop_1), + Cell(0, 3, w_queen), + Cell(0, 4, white_king), + Cell(0, 5, w_bishop_2), + Cell(0, 6, w_knight_2), + Cell(0, 7, w_rook_2), + ] board.append(line) line = [] @@ -456,7 +504,7 @@ def _reset_board(self): for i in range(4): line = [] for j in range(8): - line.append(Cell(i+2, j, None)) + line.append(Cell(i + 2, j, None)) board.append(line) line = [] @@ -484,9 +532,16 @@ def _reset_board(self): b_queen = material.Queen(False, 7, 3) pieces["black"]["alive"]["queen"].append(b_queen) - line = [Cell(7, 0, b_rook_1), Cell(7, 1, b_knight_1), Cell(7, 2, b_bishop_1), - Cell(7, 3, b_queen), Cell(7, 4, black_king), Cell(7, 5, b_bishop_2), - Cell(7, 6, b_knight_2), Cell(7, 7, b_rook_2)] + line = [ + Cell(7, 0, b_rook_1), + Cell(7, 1, b_knight_1), + Cell(7, 2, b_bishop_1), + Cell(7, 3, b_queen), + Cell(7, 4, black_king), + Cell(7, 5, b_bishop_2), + Cell(7, 6, b_knight_2), + Cell(7, 7, b_rook_2), + ] board.append(line) self.board = board @@ -531,33 +586,32 @@ def transform_pawn(self, coordinates): self.all_material[color]["alive"]["queen"].append(new_queen) def draw(self, printing=True): - whole_text = ' | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |' + whole_text = " | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |" # ###print(' | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |') - boarder_line = '+---+-----+-----+-----+-----+-----+-----+-----+-----+' + boarder_line = "+---+-----+-----+-----+-----+-----+-----+-----+-----+" # ###print(boarder_line) - whole_text += '\n' + whole_text += "\n" whole_text += boarder_line for i in range(8): - current_line = ' ' + str(i) + ' |' + current_line = " " + str(i) + " |" for j in range(8): cell = self.get_cell(i, j) if cell.get_piece() is None: - current_line += ' ' + current_line += " " else: current_line += cell.get_piece().draw() - current_line += '|' - whole_text += '\n' + current_line += "|" + whole_text += "\n" # ###print(current_line) whole_text += current_line # ###print(boarder_line) - whole_text += '\n' + whole_text += "\n" whole_text += boarder_line print(whole_text) return whole_text class Game: - game_status = [] def __init__(self, automatic_draw=True, ai=False): @@ -572,7 +626,7 @@ def __init__(self, automatic_draw=True, ai=False): self.to_play_player = self.player1 self.board = Board() - self.status = 'ACTIVE' + self.status = "ACTIVE" self.played_moves = [] self.automatic_draw = automatic_draw @@ -584,11 +638,11 @@ def reset_game(self): def to_fen(self): pieces, castling = self.board.to_fen() - color_playing = 'w' if self.to_play_player.is_white_side() else "b" + color_playing = "w" if self.to_play_player.is_white_side() else "b" return pieces + " " + color_playing + " " + castling + " - 0 1" def is_finished(self): - return self.status != 'ACTIVE' + return self.status != "ACTIVE" def move_from_coordinates(self, player, start_x, start_y, end_x, end_y): start_cell = self.board.get_cell(start_x, start_y) @@ -608,12 +662,15 @@ def can_player_move(self, player): selected_piece = self.board.get_cell(i, j).get_piece() if selected_piece is not None: if selected_piece.is_white() == player.is_white_side(): - possible_moves = selected_piece.get_potential_moves(i, j) for k in range(len(possible_moves)): selected_move = possible_moves[k] - selected_move = Move(player, self.board, self.board.get_cell(i, j), - self.board.get_cell(selected_move[0], selected_move[1])) + selected_move = Move( + player, + self.board, + self.board.get_cell(i, j), + self.board.get_cell(selected_move[0], selected_move[1]), + ) verified_move = selected_move.is_possible_move() if verified_move: @@ -632,14 +689,15 @@ def check_pat_mat(self, player): king = self.board.white_king else: king = self.board.black_king - is_mat = self.board.get_cell(king.x, king.y).is_threatened(self.board, not player.is_white_side) + is_mat = self.board.get_cell(king.x, king.y).is_threatened( + self.board, not player.is_white_side + ) if is_mat: return 2 else: return 1 def move(self, move, player): - moved_piece = move.moved_piece # List of checks @@ -679,11 +737,11 @@ def move(self, move, player): self.board.draw() # self.save() if self.board.white_king.is_killed(): - print('END OF THE GAME, BLACK HAS WON') - return False, 'black' + print("END OF THE GAME, BLACK HAS WON") + return False, "black" elif self.board.black_king.is_killed(): - print('END OF THE GAME, WHITE HAS WON') - return False, 'white' + print("END OF THE GAME, WHITE HAS WON") + return False, "white" ###print('PLAYER TO PLAY:', self.to_play_player) @@ -696,31 +754,34 @@ def update_status(self): game_status = self.check_pat_mat(self.player1) if game_status == 1: ###print('PAT, white & black do not differentiate each other') - return False, 'black&white' + return False, "black&white" elif game_status == 2: ###print('END OF THE GAME, MAT DETECTED, BLACK HAS WON') - return False, 'black' + return False, "black" else: game_status = self.check_pat_mat(self.player2) if game_status == 1: ###print('PAT, white & black do not differentiate each other') - return False, 'black&white' + return False, "black&white" elif game_status == 2: ###print('END OF THE GAME, MAT DETECTED WHITE HAS WON') - return False, 'white' + return False, "white" else: ###print('Game keeps going') - return True, '' + return True, "" - def save(self, directory='debug_files'): + def save(self, directory="debug_files"): draw_text = self.draw_board() draw_text = draw_text.replace("\x1b[32m", "") - draw_text = draw_text.replace('\033[0m', "") + draw_text = draw_text.replace("\033[0m", "") draw_text = draw_text.replace("\x1b[31m", "") import os import matplotlib.pyplot as plt - plt.rc('figure', figsize=(12, 7)) - plt.text(0.01, 0.05, str(draw_text), {"fontsize": 10}, fontproperties='monospace') - plt.axis('off') + + plt.rc("figure", figsize=(12, 7)) + plt.text( + 0.01, 0.05, str(draw_text), {"fontsize": 10}, fontproperties="monospace" + ) + plt.axis("off") plt.tight_layout() - plt.savefig(os.path.join(directory, str(len(self.played_moves))+'.png')) + plt.savefig(os.path.join(directory, str(len(self.played_moves)) + ".png")) diff --git a/python/engine/material.py b/python/engine/material.py index b078689..5f3b8f4 100644 --- a/python/engine/material.py +++ b/python/engine/material.py @@ -77,8 +77,7 @@ def is_killed(self): return self.killed def set_killed(self): - """Sets the piece status to killed. - """ + """Sets the piece status to killed.""" self.killed = True @abstractmethod @@ -149,7 +148,7 @@ def get_str(self): str String representation of the piece """ - return ' ' + return " " def draw(self): """Method to represent the piece as a colored string in order to draw a board. @@ -204,7 +203,9 @@ def __init__(self, *args, **kwargs): """ super().__init__(*args, **kwargs) self.has_moved = False # if the pawn has yet been moved or not to keep ? - self.last_move_is_double = False # check for en passant, if last move was a double tap + self.last_move_is_double = ( + False # check for en passant, if last move was a double tap + ) def piece_deepcopy(self): """Method to create an uncorrelated clone of the piece. @@ -237,7 +238,6 @@ def piece_move_authorized(self, start, end): """ # Check if there is a piece on the landing cell if end.get_piece() is not None: - # check if there is not another piece of same color if end.get_piece().is_white() == self.is_white(): return False @@ -266,7 +266,9 @@ def piece_move_authorized(self, start, end): # Initial move authorized to be two cells at once. Should check self.has_moved here ? if start.get_x() == 1 and dx == 2 and dy == 0 and self.is_white(): return True - elif start.get_x() == 6 and dx == -2 and dy == 0 and not self.is_white(): + elif ( + start.get_x() == 6 and dx == -2 and dy == 0 and not self.is_white() + ): return True else: return False @@ -293,7 +295,10 @@ def can_move(self, board, move): crossed_cell = board.get_cell(move.start.get_x(), move.end.get_y()) crossed_piece = crossed_cell.get_piece() if isinstance(crossed_piece, Pawn): - if crossed_piece.last_move_is_double and crossed_piece.is_white() != self.is_white(): + if ( + crossed_piece.last_move_is_double + and crossed_piece.is_white() != self.is_white() + ): # Revoir comment on update cet attribut last_move_is_double authorized_move = True move.complementary_passant = crossed_cell @@ -302,10 +307,20 @@ def can_move(self, board, move): dx = move.end.get_x() - move.start.get_x() if dx > 1: - if board.get_cell(move.start.get_x()+1, move.start.get_y()).get_piece() is not None: + if ( + board.get_cell( + move.start.get_x() + 1, move.start.get_y() + ).get_piece() + is not None + ): return False elif dx < -1: - if board.get_cell(move.start.get_x()-1, move.start.get_y()).get_piece() is not None: + if ( + board.get_cell( + move.start.get_x() - 1, move.start.get_y() + ).get_piece() + is not None + ): return False """ if move.end.get_x() == 7 and self.is_white(): @@ -371,7 +386,7 @@ def get_str(self): str String representation of the piece """ - return ' P ' + return " P " class Bishop(Piece): @@ -541,7 +556,7 @@ def get_str(self): str String representation of the piece """ - return ' B ' + return " B " class Rook(Piece): @@ -715,7 +730,7 @@ def get_str(self): str String representation of the piece """ - return ' R ' + return " R " class Knight(Piece): @@ -813,7 +828,7 @@ def get_str(self): str String representation of the piece """ - return ' N ' + return " N " def get_potential_moves(self, x, y): """Method to list all the possible moves from coordinates. Only uses authorized movements, no other pieces on a @@ -834,10 +849,19 @@ def get_potential_moves(self, x, y): possible_moves = [] # All difference position that a knight can move to - combos = [(2, 1), (1, 2), (-2, 1), (2, -1), (-2, -1), (-1, 2), (1, -2), (-1, -2)] + combos = [ + (2, 1), + (1, 2), + (-2, 1), + (2, -1), + (-2, -1), + (-1, 2), + (1, -2), + (-1, -2), + ] for nx, ny in combos: - if 0 <= nx+x <= 7 and 0 <= ny+y <= 7: - possible_moves.append((x+nx, y+ny)) + if 0 <= nx + x <= 7 and 0 <= ny + y <= 7: + possible_moves.append((x + nx, y + ny)) return possible_moves @@ -943,13 +967,19 @@ def can_move(self, board, move): for i in range(1, abs(dx)): x_trajectory = i * int(dx / abs(dx)) + move.start.get_x() y_trajectory = move.start.get_y() - if board.get_cell(x_trajectory, y_trajectory).get_piece() is not None: + if ( + board.get_cell(x_trajectory, y_trajectory).get_piece() + is not None + ): return False # Along Y-axis for i in range(1, abs(dy)): x_trajectory = move.start.get_x() y_trajectory = i * int(dy / abs(dy)) + move.start.get_y() - if board.get_cell(x_trajectory, y_trajectory).get_piece() is not None: + if ( + board.get_cell(x_trajectory, y_trajectory).get_piece() + is not None + ): return False return True @@ -958,7 +988,10 @@ def can_move(self, board, move): for i in range(1, abs(dx)): x_trajectory = i * int(dx / abs(dx)) + move.start.get_x() y_trajectory = i * int(dy / abs(dy)) + move.start.get_y() - if board.get_cell(x_trajectory, y_trajectory).get_piece() is not None: + if ( + board.get_cell(x_trajectory, y_trajectory).get_piece() + is not None + ): return False return True else: @@ -1048,7 +1081,7 @@ def get_str(self): str String representation of the piece """ - return ' Q ' + return " Q " class King(Piece): @@ -1161,11 +1194,13 @@ def can_move(self, board, move): return True # If move is not authorized it could mean that player is trying to do a special move, i.e. castling else: - # Checking castling conditions on the right then on the left - if not self.castling_done and not self.has_moved and (move.end.y == 6 or move.end.y == 2): + if ( + not self.castling_done + and not self.has_moved + and (move.end.y == 6 or move.end.y == 2) + ): if move.end.y == 6: # Roque vers la droite - # Getting the rook for castling rook_to_move = board.get_cell(move.start.x, 7).get_piece() rook_starting_coordinates = (move.start.x, 7) @@ -1173,10 +1208,15 @@ def can_move(self, board, move): # Listing cells that must not have material on if isinstance(rook_to_move, Rook): - must_be_empty_cells = [board.get_cell(move.start.x, 5), board.get_cell(move.start.x, 6)] - must_not_be_threatened_cells = [board.get_cell(move.start.x, 4), - board.get_cell(move.start.x, 5), - board.get_cell(move.start.x, 6)] + must_be_empty_cells = [ + board.get_cell(move.start.x, 5), + board.get_cell(move.start.x, 6), + ] + must_not_be_threatened_cells = [ + board.get_cell(move.start.x, 4), + board.get_cell(move.start.x, 5), + board.get_cell(move.start.x, 6), + ] else: return False @@ -1187,13 +1227,17 @@ def can_move(self, board, move): # Getting the rook if isinstance(rook_to_move, Rook): - - # Listing cells that must not have material on - must_be_empty_cells = [board.get_cell(move.start.x, 1), board.get_cell(move.start.x, 2), - board.get_cell(move.start.x, 3)] - must_not_be_threatened_cells = [board.get_cell(move.start.x, 2), - board.get_cell(move.start.x, 3), - board.get_cell(move.start.x, 4)] + # Listing cells that must not have material on + must_be_empty_cells = [ + board.get_cell(move.start.x, 1), + board.get_cell(move.start.x, 2), + board.get_cell(move.start.x, 3), + ] + must_not_be_threatened_cells = [ + board.get_cell(move.start.x, 2), + board.get_cell(move.start.x, 3), + board.get_cell(move.start.x, 4), + ] else: return False @@ -1212,17 +1256,26 @@ def can_move(self, board, move): # Verify that all conditions are met and completes the move so that it has the full castling information # to operate all the movements - conditions_to_castling = [not rook_to_move.has_moved, empty_cells_check, not_threatened_cells] + conditions_to_castling = [ + not rook_to_move.has_moved, + empty_cells_check, + not_threatened_cells, + ] if all(conditions_to_castling): - move.complementary_castling = rook_to_move, board.get_cell(rook_starting_coordinates[0], - rook_starting_coordinates[1]), \ - board.get_cell(rook_ending_coordinates[0], rook_ending_coordinates[1]) + move.complementary_castling = ( + rook_to_move, + board.get_cell( + rook_starting_coordinates[0], rook_starting_coordinates[1] + ), + board.get_cell( + rook_ending_coordinates[0], rook_ending_coordinates[1] + ), + ) return True else: return False return False - def get_potential_moves(self, x, y): """Method to list all the possible moves from coordinates. Only uses authorized movements, no other pieces on a board. @@ -1244,8 +1297,8 @@ def get_potential_moves(self, x, y): # All possible moves combos = [(1, 0), (1, 1), (-1, 1), (1, -1), (-1, -1), (0, 1), (0, -1), (-1, 0)] for nx, ny in combos: - if 0 <= x+nx <= 7 and 0 <= y+ny <= 7: - possible_moves.append((nx+x, ny+y)) + if 0 <= x + nx <= 7 and 0 <= y + ny <= 7: + possible_moves.append((nx + x, ny + y)) # Add castling as potential moves if not done yet if not self.has_moved: @@ -1262,7 +1315,7 @@ def get_str(self): str String representation of the piece """ - return ' K ' + return " K " def is_checked(self, board): """Method to verify that the king at its current position is not threatened / checked by opponent material. @@ -1296,4 +1349,3 @@ def is_checked(self, board): # # if verified_move: # copied_board = board.copy() - diff --git a/python/engine/move.py b/python/engine/move.py index 99e05ce..2613ffb 100644 --- a/python/engine/move.py +++ b/python/engine/move.py @@ -22,8 +22,12 @@ def __init__(self, player, board, start, end): def deepcopy(self): copied_board = self.board.deepcopy() - copied_move = Move(self.player, copied_board, copied_board.get_cell(self.start.x, self.start.y), - copied_board.get_cell(self.end.x, self.end.y)) + copied_move = Move( + self.player, + copied_board, + copied_board.get_cell(self.start.x, self.start.y), + copied_board.get_cell(self.end.x, self.end.y), + ) copied_move.is_castling = self.is_castling copied_move.complementary_castling = self.complementary_castling copied_move.en_passant = self.en_passant @@ -31,11 +35,11 @@ def deepcopy(self): return copied_move def _set_moved_attribute(self): - if hasattr(self.moved_piece, 'has_moved'): + if hasattr(self.moved_piece, "has_moved"): self.moved_piece.has_moved = True ###print('PIECE', self.moved_piece.is_white(), self.moved_piece, "set to moved") ###print(self.start.x, self.start.y, self.end.x, self.end.y) - if hasattr(self.moved_piece, 'last_move_is_double'): + if hasattr(self.moved_piece, "last_move_is_double"): if abs(self.start.get_x() - self.end.get_x()) > 1: self.moved_piece.last_move_is_double = True else: @@ -67,11 +71,15 @@ def _is_castling(self): else: rook_starting_coordinates = (self.start.x, 7) rook_ending_coordinates = (self.start.x, 5) - must_be_empty_cells = [self.board.get_cell(self.start.x, 5), - self.board.get_cell(self.start.x, 6)] - must_not_be_threatened_cells = [self.board.get_cell(self.start.x, 4), - self.board.get_cell(self.start.x, 5), - self.board.get_cell(self.start.x, 6)] + must_be_empty_cells = [ + self.board.get_cell(self.start.x, 5), + self.board.get_cell(self.start.x, 6), + ] + must_not_be_threatened_cells = [ + self.board.get_cell(self.start.x, 4), + self.board.get_cell(self.start.x, 5), + self.board.get_cell(self.start.x, 6), + ] elif self.end.y == 2: # Castling on the left rook_to_move = self.board.get_cell(self.start.x, 0).get_piece() @@ -84,12 +92,16 @@ def _is_castling(self): else: rook_starting_coordinates = (self.start.x, 0) rook_ending_coordinates = (self.start.x, 3) - must_be_empty_cells = [self.board.get_cell(self.start.x, 1), - self.board.get_cell(self.start.x, 2), - self.board.get_cell(self.start.x, 3)] - must_not_be_threatened_cells = [self.board.get_cell(self.start.x, 2), - self.board.get_cell(self.start.x, 3), - self.board.get_cell(self.start.x, 4)] + must_be_empty_cells = [ + self.board.get_cell(self.start.x, 1), + self.board.get_cell(self.start.x, 2), + self.board.get_cell(self.start.x, 3), + ] + must_not_be_threatened_cells = [ + self.board.get_cell(self.start.x, 2), + self.board.get_cell(self.start.x, 3), + self.board.get_cell(self.start.x, 4), + ] else: ###print('king did not move to a castling position') return False @@ -106,11 +118,15 @@ def _is_castling(self): conditions_to_castling = [empty_cells_check, not_threatened_cells] if all(conditions_to_castling): - self.complementary_castling = rook_to_move, \ - self.board.get_cell(rook_starting_coordinates[0], - rook_starting_coordinates[1]), \ - self.board.get_cell(rook_ending_coordinates[0], - rook_ending_coordinates[1]) + self.complementary_castling = ( + rook_to_move, + self.board.get_cell( + rook_starting_coordinates[0], rook_starting_coordinates[1] + ), + self.board.get_cell( + rook_ending_coordinates[0], rook_ending_coordinates[1] + ), + ) return True else: @@ -122,7 +138,6 @@ def _is_castling(self): def _is_en_passant(self): if isinstance(self.moved_piece, material.Pawn): - dx = self.start.get_x() - self.end.get_x() dy = self.start.get_y() - self.end.get_y() if dy == 0 or self.killed_piece is not None: @@ -132,7 +147,10 @@ def _is_en_passant(self): crossed_cell = self.board.get_cell(self.start.get_x(), self.end.get_y()) crossed_piece = crossed_cell.get_piece() if isinstance(crossed_piece, material.Pawn): - if crossed_piece.last_move_is_double and crossed_piece.is_white() != self.moved_piece.is_white(): + if ( + crossed_piece.last_move_is_double + and crossed_piece.is_white() != self.moved_piece.is_white() + ): # Revoir comment on update cet attribut last_move_is_double self.killed_piece = crossed_piece self.en_passant = True @@ -167,12 +185,16 @@ def move_pieces(self): if self.killed_piece is not None: self.board.kill_piece_from_coordinates((self.end.x, self.end.y)) - self.board.move_piece_from_coordinates((self.start.x, self.start.y), (self.end.x, self.end.y)) + self.board.move_piece_from_coordinates( + (self.start.x, self.start.y), (self.end.x, self.end.y) + ) # ADD CASTLING if self.complementary_castling is not None and self.is_castling: castling_rook, rook_start, rook_end = self.complementary_castling - self.board.move_piece_from_coordinates((rook_start.x, rook_start.y), (rook_end.x, rook_end.y)) + self.board.move_piece_from_coordinates( + (rook_start.x, rook_start.y), (rook_end.x, rook_end.y) + ) ###print("CASTLING DETECTED PPPPPPPPP") self._set_castling_done() @@ -180,7 +202,7 @@ def move_pieces(self): self._transform_pawn() self._set_moved_attribute() - def is_possible_move(self): # REFONDRE + def is_possible_move(self): # REFONDRE # To be implemented # Should be kept ? @@ -289,4 +311,6 @@ def _work_future_to_check_chess(self): king = move.board.white_king else: king = move.board.black_king - return move.board.get_cell(king.x, king.y).is_threatened(move.board, king.is_white()) \ No newline at end of file + return move.board.get_cell(king.x, king.y).is_threatened( + move.board, king.is_white() + ) diff --git a/python/interface/interface.py b/python/interface/interface.py index 0a71766..cf99006 100644 --- a/python/interface/interface.py +++ b/python/interface/interface.py @@ -15,20 +15,18 @@ from engine.engine import Game - class LoginScreen(GridLayout): - def __init__(self, **kwargs): super(LoginScreen, self).__init__(**kwargs) self.cols = 8 - self.add_widget(Label(text='')) + self.add_widget(Label(text="")) self.username = TextInput(multiline=False) self.add_widget(self.username) - self.add_widget(Label(text='password')) + self.add_widget(Label(text="password")) self.password = TextInput(password=True, multiline=False) self.add_widget(self.password) - self.add_widget(Label(text='password2')) + self.add_widget(Label(text="password2")) self.password2 = TextInput(password=True, multiline=False) self.add_widget(self.password2) @@ -36,7 +34,6 @@ def __init__(self, **kwargs): class DisplayableCell(Button): - def __init__(self, row, column, **kwargs): super(DisplayableCell, self).__init__(**kwargs) self.row = row @@ -44,10 +41,9 @@ def __init__(self, row, column, **kwargs): class TableScreen(GridLayout): - def __init__(self, game, **kwargs): super(TableScreen, self).__init__(**kwargs) - self.path_to_illustrations = 'illustrations' + self.path_to_illustrations = "illustrations" self.game = game if game.ai: @@ -69,53 +65,70 @@ def __init__(self, game, **kwargs): for j in range(8): if (i % 2 == 0 and j % 2 == 0) or (i % 2 == 1 and j % 2 == 1): color = (0.4, 0.4, 0.8, 1) - c_img = 'b' + c_img = "b" else: color = (0.4, 0.8, 0.4, 1) - c_img = 'w' + c_img = "w" # self.add_widget(Button(text='Button %i %i' % (i, j), background_color=color, # background_down='illustrations/white_pawn.png', # background_normal='illustrations/white_queen.png')) piece = game.board.get_cell(i, j).get_piece() if piece is not None: - path_to_img = c_img if piece.is_white(): piece_color = (1, 1, 1, 1) - path_to_img += 'w' + path_to_img += "w" else: piece_color = (0, 0, 0, 1) - path_to_img += 'b' - path_to_img += ('_' + piece.get_str().replace(' ', '') + '.png') - path_to_down_img = 'down_' + path_to_img + path_to_img += "b" + path_to_img += "_" + piece.get_str().replace(" ", "") + ".png" + path_to_down_img = "down_" + path_to_img path_to_img = os.path.join(self.path_to_illustrations, path_to_img) - path_to_down_img = os.path.join(self.path_to_illustrations, path_to_down_img) + path_to_down_img = os.path.join( + self.path_to_illustrations, path_to_down_img + ) piece = piece.get_str() - button = DisplayableCell(text=piece, on_press=self.click_cell, row=i, column=j, - color=piece_color, background_normal=path_to_img, border=(0, 0, 0, 0), - background_down=path_to_down_img) + button = DisplayableCell( + text=piece, + on_press=self.click_cell, + row=i, + column=j, + color=piece_color, + background_normal=path_to_img, + border=(0, 0, 0, 0), + background_down=path_to_down_img, + ) else: - piece = '' + piece = "" piece_color = (1, 1, 1, 1) - path_to_img = c_img + '.png' - path_to_down_img = 'down_' + path_to_img + path_to_img = c_img + ".png" + path_to_down_img = "down_" + path_to_img path_to_img = os.path.join(self.path_to_illustrations, path_to_img) - path_to_down_img = os.path.join(self.path_to_illustrations, path_to_down_img) - - button = DisplayableCell(text=piece, background_normal=path_to_img, on_press=self.click_cell, row=i, - column=j, color=piece_color, border=(0, 0, 0, 0), - background_down=path_to_down_img) + path_to_down_img = os.path.join( + self.path_to_illustrations, path_to_down_img + ) + + button = DisplayableCell( + text=piece, + background_normal=path_to_img, + on_press=self.click_cell, + row=i, + column=j, + color=piece_color, + border=(0, 0, 0, 0), + background_down=path_to_down_img, + ) self.add_widget(button) line.append(button) self.cells.append(line) def reset_game(self, button): - print('On click, Reset', button) + print("On click, Reset", button) self.game.reset_game() self.update() @@ -124,41 +137,43 @@ def update(self): for i in range(8): for j in range(8): if (i % 2 == 0 and j % 2 == 0) or (i % 2 == 1 and j % 2 == 1): - c_img = 'b' + c_img = "b" else: - c_img = 'w' + c_img = "w" piece = board.get_cell(i, j).get_piece() if piece is not None: path_to_img = c_img if piece.is_white(): piece_color = (1, 1, 1, 1) - path_to_img += 'w' + path_to_img += "w" else: piece_color = (0, 0, 0, 1) - path_to_img += 'b' + path_to_img += "b" piece = piece.get_str() - path_to_img += ('_' + piece.replace(' ', '') + '.png') + path_to_img += "_" + piece.replace(" ", "") + ".png" else: - piece = '' + piece = "" piece_color = (1, 1, 1, 1) - path_to_img = c_img + '.png' + path_to_img = c_img + ".png" - path_to_down_img = 'down_' + path_to_img + path_to_down_img = "down_" + path_to_img path_to_img = os.path.join(self.path_to_illustrations, path_to_img) - path_to_down_img = os.path.join(self.path_to_illustrations, path_to_down_img) + path_to_down_img = os.path.join( + self.path_to_illustrations, path_to_down_img + ) self.cells[i][j].text = piece self.cells[i][j].color = piece_color self.cells[i][j].background_normal = path_to_img self.cells[i][j].background_down = path_to_down_img def finish_game(self, winner): - popup = Popup(title='Game finished', auto_dismiss=False) + popup = Popup(title="Game finished", auto_dismiss=False) popup.bind(on_dismiss=self.reset_game) box = BoxLayout() - box.add_widget(Label(text='Congratulations %s has won' % winner)) - restart_button = Button(text='Restart a game!') + box.add_widget(Label(text="Congratulations %s has won" % winner)) + restart_button = Button(text="Restart a game!") restart_button.bind(on_press=popup.dismiss) box.add_widget(restart_button) @@ -167,12 +182,20 @@ def finish_game(self, winner): popup.open() def click_cell(self, event): - self.cells[event.row][event.column].background_normal, self.cells[event.row][event.column].background_down = \ - self.cells[event.row][event.column].background_down, self.cells[event.row][event.column].background_normal + ( + self.cells[event.row][event.column].background_normal, + self.cells[event.row][event.column].background_down, + ) = ( + self.cells[event.row][event.column].background_down, + self.cells[event.row][event.column].background_normal, + ) if self.first_cell_clicked is None: self.first_cell_clicked = (event.row, event.column) - elif self.first_cell_clicked[0] == event.row and self.first_cell_clicked[1] == event.column: - print('Selection Aborted') + elif ( + self.first_cell_clicked[0] == event.row + and self.first_cell_clicked[1] == event.column + ): + print("Selection Aborted") self.first_cell_clicked = None else: start_x = self.first_cell_clicked[0] @@ -181,15 +204,25 @@ def click_cell(self, event): end_y = event.column print(self.game.player1, self.game.to_play_player) - validated_move, winner = self.game.move_from_coordinates(self.game.to_play_player, start_x, start_y, end_x, end_y) - print('Validated move ?', validated_move, self.game.to_play_player, start_x, start_y, end_x, end_y, winner) + validated_move, winner = self.game.move_from_coordinates( + self.game.to_play_player, start_x, start_y, end_x, end_y + ) + print( + "Validated move ?", + validated_move, + self.game.to_play_player, + start_x, + start_y, + end_x, + end_y, + winner, + ) if validated_move: self.update() if self.ai_playing: - - print('Time for AI') + print("Time for AI") ai_move = self.game.player2.time_to_play(self.game.board) self.game.board.draw() game_is_on = self.game.move(ai_move, self.game.player2) @@ -203,28 +236,34 @@ def click_cell(self, event): pass elif isinstance(winner, str): - print('WINNER', winner) + print("WINNER", winner) self.finish_game(winner) return None row, col = self.first_cell_clicked - self.cells[row][col].background_normal, self.cells[row][col].background_down = \ - self.cells[row][event.column].background_down, self.cells[event.row][col].background_normal + ( + self.cells[row][col].background_normal, + self.cells[row][col].background_down, + ) = ( + self.cells[row][event.column].background_down, + self.cells[event.row][col].background_normal, + ) self.first_cell_clicked = None - self.cells[event.row][event.column].background_normal, self.cells[event.row][event.column].background_down = \ - self.cells[event.row][event.column].background_down, self.cells[event.row][event.column].background_normal - + ( + self.cells[event.row][event.column].background_normal, + self.cells[event.row][event.column].background_down, + ) = ( + self.cells[event.row][event.column].background_down, + self.cells[event.row][event.column].background_normal, + ) class MyApp(App): - def __init__(self, play_with_ai=False, **kwargs): super().__init__(**kwargs) self.play_with_ai = play_with_ai - + def build(self): game = Game(automatic_draw=False, ai=self.play_with_ai) - print('game created') + print("game created") return TableScreen(game) - - diff --git a/python/player/ai_player.py b/python/player/ai_player.py index 6d2031e..076819e 100644 --- a/python/player/ai_player.py +++ b/python/player/ai_player.py @@ -8,25 +8,24 @@ class EasyAIPlayer(Player): - piece_weights = { "pawn": 10, "knight": 30, "bishop": 30, "rook": 50, "queen": 90, - "king": 900 + "king": 900, } piece_positions_weights = { "pawn": [ - [0.]*8, - [5.0]*8, + [0.0] * 8, + [5.0] * 8, [1.0, 1.0, 2.0, 3.0, 3.0, 2.0, 1.0, 1.0], [0.5, 0.5, 1.0, 2.5, 2.5, 1.0, 0.5, 0.5], [0.0, 0.0, 0.0, 2.0, 2.0, 0.0, 0.0, 0.0], [0.5, -0.5, -1.0, 0.0, 0.0, -1.0, -0.5, 0.5], [0.5, 1.0, 1.0, -2.0, -2.0, 1.0, 1.0, 0.5], - [0.]*8 + [0.0] * 8, ], "bishop": [ [-2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0], @@ -36,7 +35,7 @@ class EasyAIPlayer(Player): [-1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0], [-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0], [-1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, -1.0], - [-2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0] + [-2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0], ], "knight": [ [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0], @@ -46,7 +45,7 @@ class EasyAIPlayer(Player): [-3.0, 0.0, 1.5, 2.0, 2.0, 1.5, 0.0, -3.0], [-3.0, 0.5, 1.0, 1.5, 1.5, 1.0, 0.5, -3.0], [-4.0, -2.0, 0.0, 0.5, 0.5, 0.0, -2.0, -4.0], - [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0] + [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0], ], "rook": [ [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], @@ -56,7 +55,7 @@ class EasyAIPlayer(Player): [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], - [0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0] + [0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0], ], "queen": [ [-2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0], @@ -66,7 +65,7 @@ class EasyAIPlayer(Player): [0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, 0.0], [-1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -1.0], [-1.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0], - [-2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0] + [-2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0], ], "king": [ [-3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0], @@ -76,8 +75,8 @@ class EasyAIPlayer(Player): [-2.0, -3.0, -3.0, -4.0, -4.0, -3.0, -3.0, -2.0], [-1.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -1.0], [2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0], - [2.0, 3.0, 1.0, 0.0, 0.0, 1.0, 3.0, 2.0] - ] + [2.0, 3.0, 1.0, 0.0, 0.0, 1.0, 3.0, 2.0], + ], } def __init__(self, *args, **kwargs): @@ -91,13 +90,14 @@ def __init__(self, *args, **kwargs): self.piece_positions_weights[key] = new_values def __str__(self): - return 'EasyAIPlayer' + return "EasyAIPlayer" def _get_possible_moves(self, board, is_white=None): if is_white is None: is_white = self.white_side() if self.white_side != is_white: + class TempPlayer: def __init__(self): self.white_side = is_white @@ -119,8 +119,12 @@ def is_white_side(self): if isinstance(piece, material.Pawn): ###print("POSSIBLE MOVES FOR PAWN", piece_available_moves) pass - selected_move = move.Move(player, board, board.get_cell(piece.x, piece.y), - board.get_cell(mv[0], mv[1])) + selected_move = move.Move( + player, + board, + board.get_cell(piece.x, piece.y), + board.get_cell(mv[0], mv[1]), + ) if selected_move.is_possible_move(): possible_moves.append(selected_move) ###print("possible move +1") @@ -166,7 +170,9 @@ def _select_move_from_score(self, moves, method="max"): def _search_tree(self, init_board, depth=2, method="max"): possible_moves = self._get_possible_moves(init_board) if depth == 1: - best_move, best_score = self._select_move_from_score(possible_moves, method=method) + best_move, best_score = self._select_move_from_score( + possible_moves, method=method + ) return best_move, best_score else: new_method = {"max": "min", "min": "max"} @@ -176,7 +182,9 @@ def _search_tree(self, init_board, depth=2, method="max"): # p_mv = pickle.loads(pickle.dumps(p_mv, -1)) # p_mv = copy.deepcopy(p_mv) p_mv.move_pieces() - _, score = self._search_tree(p_mv.board, depth=depth-1, method=new_method[method]) + _, score = self._search_tree( + p_mv.board, depth=depth - 1, method=new_method[method] + ) scores.append(score) if method == "max": @@ -184,12 +192,11 @@ def _search_tree(self, init_board, depth=2, method="max"): else: best_score = np.min(score) - best_indexes = np.where(np.array(scores)==best_score)[0] + best_indexes = np.where(np.array(scores) == best_score)[0] final_index = best_indexes[np.random.permutation(len(best_indexes))[0]] ###print(final_index) return possible_moves[int(final_index)], best_score - def _score_move(self, move): all_scores = {} mv_ = move.deepcopy() @@ -200,7 +207,15 @@ def _score_move(self, move): return move, score - def _alpha_beta(self, init_board, init_move=None, depth=2, alpha=-10000, beta=10000, is_white=None): + def _alpha_beta( + self, + init_board, + init_move=None, + depth=2, + alpha=-10000, + beta=10000, + is_white=None, + ): if is_white is None: is_white = self.white_side ###print('ALPHA BETA FOR BOARD:', "with depth", depth) @@ -224,8 +239,14 @@ def _alpha_beta(self, init_board, init_move=None, depth=2, alpha=-10000, beta=10 # p_mv_ = copy.deepcopy(p_mv) p_mv_ = p_mv.deepcopy() p_mv_.move_pieces() - score, _ = self._alpha_beta(p_mv_.board, init_move=p_mv_, depth=depth-1, alpha=alpha, beta=beta, - is_white=not is_white) + score, _ = self._alpha_beta( + p_mv_.board, + init_move=p_mv_, + depth=depth - 1, + alpha=alpha, + beta=beta, + is_white=not is_white, + ) ###print(score, p_mv.start.x, p_mv.start.y, p_mv.end.x, p_mv.end.y) best_move = [best_move, p_mv][np.argmax([best_score, score])] best_score = np.max([best_score, score]) @@ -246,8 +267,14 @@ def _alpha_beta(self, init_board, init_move=None, depth=2, alpha=-10000, beta=10 # p_mv_ = pickle.loads(pickle.dumps(p_mv, -1)) p_mv_ = p_mv.deepcopy() p_mv_.move_pieces() - score, _ = self._alpha_beta(p_mv_.board, init_move=p_mv_, depth=depth-1, alpha=alpha, beta=beta, - is_white=is_white) + score, _ = self._alpha_beta( + p_mv_.board, + init_move=p_mv_, + depth=depth - 1, + alpha=alpha, + beta=beta, + is_white=is_white, + ) ###print(score, p_mv.start.x, p_mv.start.y, p_mv.end.x, p_mv.end.y) best_move = [best_move, p_mv][np.argmin([best_score, score])] best_score = np.min([best_score, score]) @@ -264,7 +291,10 @@ def random_move(self, board): for i in np.random.permutation(8): for j in np.random.permutation(8): if board.get_cell(i, j).get_piece() is not None: - if board.get_cell(i, j).get_piece().is_white() == self.is_white_side(): + if ( + board.get_cell(i, j).get_piece().is_white() + == self.is_white_side() + ): selected_piece = board.get_cell(i, j).get_piece() ###print('AI Selected Piece', selected_piece) possible_moves = selected_piece.get_potential_moves(i, j) @@ -275,8 +305,12 @@ def random_move(self, board): ###print('Verifying Moves,', len(possible_moves), 'Moves Possibles') while not verified_move and index < len(random_move): selected_move = possible_moves[random_move[index]] - selected_move = move.Move(self, board, board.get_cell(i, j), - board.get_cell(selected_move[0], selected_move[1])) + selected_move = move.Move( + self, + board, + board.get_cell(i, j), + board.get_cell(selected_move[0], selected_move[1]), + ) verified_move = selected_move.is_possible_move() index += 1 @@ -303,16 +337,16 @@ def time_to_play(self, board, depth=3): def _score_board(self, board): score = 0 - for piece_type in board.all_material[self.color]['alive'].keys(): - for piece in board.all_material[self.color]['alive'][piece_type]: + for piece_type in board.all_material[self.color]["alive"].keys(): + for piece in board.all_material[self.color]["alive"][piece_type]: score += self.piece_weights[piece_type] ###print(piece_type, piece.x, piece.y) score += self.piece_positions_weights[piece_type][piece.x][piece.y] adv_color = "white" if self.color == "black" else "black" - for piece_type in board.all_material[adv_color]['alive'].keys(): - for piece in board.all_material[adv_color]['alive'][piece_type]: + for piece_type in board.all_material[adv_color]["alive"].keys(): + for piece in board.all_material[adv_color]["alive"][piece_type]: score -= self.piece_weights[piece_type] score -= self.piece_positions_weights[piece_type][piece.x][piece.y] return score diff --git a/python/player/my_player.py b/python/player/my_player.py index 675d9d1..6eb582c 100644 --- a/python/player/my_player.py +++ b/python/player/my_player.py @@ -15,7 +15,7 @@ def __init__(self, max_memory=200): def remember(self, m): self.memory.append(m) - self.memory = self.memory[max(len(self.memory)- self.max_memory, 0):] + self.memory = self.memory[max(len(self.memory) - self.max_memory, 0) :] def random_access(self): rn = np.random.randint(0, max(len(self.memory), 1)) @@ -23,7 +23,6 @@ def random_access(self): class MyPlayer(Player): - def __init__(self, path_to_model="", epsilon_explorer=0.15, *args, **kwargs): super().__init__(*args, **kwargs) self.color = "white" if self.white_side else "black" @@ -45,11 +44,11 @@ def __init__(self, path_to_model="", epsilon_explorer=0.15, *args, **kwargs): if not os.path.exists(path_to_model): self.model = tf.keras.Model(inputs=in_, outputs=out) - self.model.compile(loss='mse', optimizer="Adam") + self.model.compile(loss="mse", optimizer="Adam") else: print("Loading Model") self.model = tf.keras.models.load_model(path_to_model) - self.model.compile(loss='mse', optimizer="Adam") + self.model.compile(loss="mse", optimizer="Adam") print("Model Loaded") print(self.model.summary()) self.memory = Memory() @@ -63,10 +62,11 @@ def _score_board(self, board, white_side=None): if self.white_side != white_side: one_hot_encode_board = np.flip(one_hot_encode_board) - score = self.model.predict(np.expand_dims(one_hot_encode_board, 0).astype('float32')) + score = self.model.predict( + np.expand_dims(one_hot_encode_board, 0).astype("float32") + ) return score[0][0] - def _get_possible_moves(self, board, is_white=None): if is_white is None: is_white = self.white_side() @@ -77,16 +77,19 @@ def _get_possible_moves(self, board, is_white=None): for piece in board.all_material[color]["alive"][type_piece]: piece_available_moves = piece.get_potential_moves(piece.x, piece.y) for mv in piece_available_moves: - selected_move = move.Move(self, board, board.get_cell(piece.x, piece.y), - board.get_cell(mv[0], mv[1])) + selected_move = move.Move( + self, + board, + board.get_cell(piece.x, piece.y), + board.get_cell(mv[0], mv[1]), + ) if selected_move.is_possible_move(): possible_moves.append(selected_move) return possible_moves def _select_move_from_score(self, moves, train=True): - if train: - do_random_move = (np.random.randint(100) <= self.epsilon_explorer * 100) + do_random_move = np.random.randint(100) <= self.epsilon_explorer * 100 if do_random_move: print("RANDOM MOVE SELECTED") index_random_move = np.random.randint(len(moves)) @@ -119,18 +122,18 @@ def _base_scoring(self, board, game_is_won="", white_side=None): "bishop": 30, "rook": 50, "queen": 90, - "king": 900 + "king": 900, } piece_positions_weights = { "pawn": [ - [0.]*8, - [5.0]*8, + [0.0] * 8, + [5.0] * 8, [1.0, 1.0, 2.0, 3.0, 3.0, 2.0, 1.0, 1.0], [0.5, 0.5, 1.0, 2.5, 2.5, 1.0, 0.5, 0.5], [0.0, 0.0, 0.0, 2.0, 2.0, 0.0, 0.0, 0.0], [0.5, -0.5, -1.0, 0.0, 0.0, -1.0, -0.5, 0.5], [0.5, 1.0, 1.0, -2.0, -2.0, 1.0, 1.0, 0.5], - [0.]*8 + [0.0] * 8, ], "bishop": [ [-2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0], @@ -140,7 +143,7 @@ def _base_scoring(self, board, game_is_won="", white_side=None): [-1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0], [-1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0], [-1.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.5, -1.0], - [-2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0] + [-2.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -2.0], ], "knight": [ [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0], @@ -150,7 +153,7 @@ def _base_scoring(self, board, game_is_won="", white_side=None): [-3.0, 0.0, 1.5, 2.0, 2.0, 1.5, 0.0, -3.0], [-3.0, 0.5, 1.0, 1.5, 1.5, 1.0, 0.5, -3.0], [-4.0, -2.0, 0.0, 0.5, 0.5, 0.0, -2.0, -4.0], - [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0] + [-5.0, -4.0, -3.0, -3.0, -3.0, -3.0, -4.0, -5.0], ], "rook": [ [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], @@ -160,7 +163,7 @@ def _base_scoring(self, board, game_is_won="", white_side=None): [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], [-0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, -0.5], - [0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0] + [0.0, 0.0, 0.0, 0.5, 0.5, 0.0, 0.0, 0.0], ], "queen": [ [-2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0], @@ -170,7 +173,7 @@ def _base_scoring(self, board, game_is_won="", white_side=None): [0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.0, 0.0], [-1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, -1.0], [-1.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0], - [-2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0] + [-2.0, -1.0, -1.0, -0.5, -0.5, -1.0, -1.0, -2.0], ], "king": [ [-3.0, -4.0, -4.0, -5.0, -5.0, -4.0, -4.0, -3.0], @@ -180,18 +183,18 @@ def _base_scoring(self, board, game_is_won="", white_side=None): [-2.0, -3.0, -3.0, -4.0, -4.0, -3.0, -3.0, -2.0], [-1.0, -2.0, -2.0, -2.0, -2.0, -2.0, -2.0, -1.0], [2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 2.0, 2.0], - [2.0, 3.0, 1.0, 0.0, 0.0, 1.0, 3.0, 2.0] - ] + [2.0, 3.0, 1.0, 0.0, 0.0, 1.0, 3.0, 2.0], + ], } score = 0 - for piece_type in board.all_material["white"]['alive'].keys(): - for piece in board.all_material["white"]['alive'][piece_type]: + for piece_type in board.all_material["white"]["alive"].keys(): + for piece in board.all_material["white"]["alive"][piece_type]: score += piece_weights[piece_type] score += np.flip(piece_positions_weights[piece_type])[piece.x][piece.y] - for piece_type in board.all_material["black"]['alive'].keys(): - for piece in board.all_material["black"]['alive'][piece_type]: + for piece_type in board.all_material["black"]["alive"].keys(): + for piece in board.all_material["black"]["alive"][piece_type]: score -= piece_weights[piece_type] score -= piece_positions_weights[piece_type][piece.x][piece.y] if not white_side: @@ -220,9 +223,8 @@ def _reinforce(self, board, best_next_score, batch_size=12, white_side=None): self.model.train_on_batch(input_states, target_q) self.model.save(self.path_to_model) - def __str__(self): - return 'MyAIPlayer' + return "MyAIPlayer" def time_to_play(self, board, white_side=None): if white_side is None: diff --git a/python/player/player.py b/python/player/player.py index c037588..c5f7542 100644 --- a/python/player/player.py +++ b/python/player/player.py @@ -9,7 +9,7 @@ def __init__(self, white_side): self.random_number = np.random.randint(0, 1000, 1) def __str__(self): - return 'NormalPlayer%i' % self.random_number + return "NormalPlayer%i" % self.random_number def is_white_side(self): return self.white_side @@ -19,32 +19,39 @@ def time_to_play(self, board): class AIRandomPlayer(Player): - def __str__(self): - return 'AIRandomPlayer' + return "AIRandomPlayer" def time_to_play(self, board): - for i in np.random.permutation(8): for j in np.random.permutation(8): if board.get_cell(i, j).get_piece() is not None: - if board.get_cell(i, j).get_piece().is_white() == self.is_white_side(): + if ( + board.get_cell(i, j).get_piece().is_white() + == self.is_white_side() + ): selected_piece = board.get_cell(i, j).get_piece() - print('AI Selected Piece', selected_piece) + print("AI Selected Piece", selected_piece) possible_moves = selected_piece.get_potential_moves(i, j) verified_move = False random_move = np.random.permutation(len(possible_moves)) index = 0 - print('Verifying Moves,', len(possible_moves), 'Moves Possibles') + print( + "Verifying Moves,", len(possible_moves), "Moves Possibles" + ) while not verified_move and index < len(random_move): selected_move = possible_moves[random_move[index]] - selected_move = Move(self, board, board.get_cell(i, j), - board.get_cell(selected_move[0], selected_move[1])) + selected_move = Move( + self, + board, + board.get_cell(i, j), + board.get_cell(selected_move[0], selected_move[1]), + ) verified_move = selected_move.is_possible_move() index += 1 if verified_move: - print('Move is verified, ') + print("Move is verified, ") return selected_move - print('No moved found, aborting...') + print("No moved found, aborting...") diff --git a/python/utils/images_creation.py b/python/utils/images_creation.py index 2850bda..8d33854 100644 --- a/python/utils/images_creation.py +++ b/python/utils/images_creation.py @@ -5,17 +5,17 @@ from PIL import Image -black_pawn = np.array(Image.open('own_illustrations/queen_grey.png')) +black_pawn = np.array(Image.open("own_illustrations/queen_grey.png")) -black_back = (np.array([0.4, 0.4, 0.8]) * 255).astype('uint8') -white_back = (np.array([0.4, 0.8, 0.4]) * 255).astype('uint8') +black_back = (np.array([0.4, 0.4, 0.8]) * 255).astype("uint8") +white_back = (np.array([0.4, 0.8, 0.4]) * 255).astype("uint8") changed = [] for i in range(3): channel = np.copy(black_pawn[:, :, i]) - channel[black_pawn[:, :, i]<137] = 100 * i - channel[black_pawn[:, :, i]==0] = 200 / (i+1) - channel[black_pawn[:, :, i]>137] = 100 * i - 50 + channel[black_pawn[:, :, i] < 137] = 100 * i + channel[black_pawn[:, :, i] == 0] = 200 / (i + 1) + channel[black_pawn[:, :, i] > 137] = 100 * i - 50 changed.append(channel) plt.figure() diff --git a/python/utils/profile_game.py b/python/utils/profile_game.py index 41121f7..26223aa 100644 --- a/python/utils/profile_game.py +++ b/python/utils/profile_game.py @@ -4,9 +4,10 @@ sys.path.append("../") import engine.engine as engine -#import move -#import time -#import ai_player + +# import move +# import time +# import ai_player game = engine.Game(automatic_draw=False, ai=True) print(game.board.one_hot_encode()) @@ -25,4 +26,3 @@ game_is_on = game.move(ai_move, game.player2) score = my_player._score_board(game.board) print(my_player.model.summary()) - diff --git a/python/utils/training_ai.py b/python/utils/training_ai.py index 1feacd9..e492ac5 100644 --- a/python/utils/training_ai.py +++ b/python/utils/training_ai.py @@ -23,4 +23,3 @@ if not game_is_on[0]: print(game_is_on) break - diff --git a/run_app.py b/run_app.py index 9bd80fb..5557084 100644 --- a/run_app.py +++ b/run_app.py @@ -4,6 +4,5 @@ from interface.interface import MyApp -if __name__ == '__main__': +if __name__ == "__main__": MyApp(play_with_ai=True).run() - diff --git a/tests/engine_test.py b/tests/engine_test.py index c74d790..d2acf79 100644 --- a/tests/engine_test.py +++ b/tests/engine_test.py @@ -1,44 +1,47 @@ import sys + sys.path.append("../python") import engine.engine as engine import importlib import engine.move as move import time + importlib.reload(engine) import player.ai_player as ai_player + def test_working_castling(): game = engine.Game() game.move_from_coordinates(game.player1, 1, 4, 3, 4) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player2, 6, 4, 4, 4) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player1, 0, 5, 3, 2) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player2, 7, 3, 4, 6) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player1, 0, 6, 2, 5) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player2, 7, 1, 5, 2) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) # small castling move game.move_from_coordinates(game.player1, 0, 4, 0, 6) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player2, 6, 3, 5, 3) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player1, 0, 1, 2, 2) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player2, 7, 2, 6, 3) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player1, 0, 3, 1, 4) - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) # big castling move - print('big castling') - print("///", game.board.all_material['black']['alive']['king'][0].has_moved) + print("big castling") + print("///", game.board.all_material["black"]["alive"]["king"][0].has_moved) game.move_from_coordinates(game.player2, 7, 4, 7, 2) game.draw_board() @@ -99,6 +102,7 @@ def test_pawn_transformation(): game.move_from_coordinates(game.player1, 1, 5, 2, 5) game.move_from_coordinates(game.player2, 1, 4, 0, 4) + def check_unchecking(): game = engine.Game() game.move_from_coordinates(game.player1, 1, 4, 3, 4) @@ -106,6 +110,7 @@ def check_unchecking(): game.move_from_coordinates(game.player1, 0, 3, 4, 7) game.move_from_coordinates(game.player2, 6, 6, 5, 6) + def test_blocked_double_pawn(): game = engine.Game() game.move_from_coordinates(game.player1, 1, 4, 3, 4) @@ -115,6 +120,7 @@ def test_blocked_double_pawn(): game.move_from_coordinates(game.player1, 4, 4, 5, 4) game.move_from_coordinates(game.player2, 6, 4, 4, 4) + def test_king_taking_queen(): game = engine.Game() game.move_from_coordinates(game.player1, 1, 4, 3, 4) @@ -130,6 +136,7 @@ def test_king_taking_queen(): game.move_from_coordinates(game.player1, 7, 6, 7, 5) game.move_from_coordinates(game.player2, 7, 4, 7, 5) + def specific_test(): game = engine.Game() game.move_from_coordinates(game.player1, 1, 4, 3, 4) @@ -169,12 +176,18 @@ def possible_moves(): print(piece_available_moves) for mv in piece_available_moves: print(mv) - selected_move = move.Move(game.player1, game.board, game.board.get_cell(piece.x, piece.y), - game.board.get_cell(mv[0], mv[1])) + selected_move = move.Move( + game.player1, + game.board, + game.board.get_cell(piece.x, piece.y), + game.board.get_cell(mv[0], mv[1]), + ) if selected_move.is_possible_move(): print("move ok") else: print("move not ok") + + def test_player(): player = ai_player.EasyAIPlayer(False) game = engine.Game() @@ -189,9 +202,7 @@ def test_player(): print(score) - - -if __name__ == '__main__': +if __name__ == "__main__": check_unchecking() test_working_castling() test_failing_castling() @@ -204,7 +215,8 @@ def test_player(): specific_test() possible_moves() test_player() - print('Tests finished') + print("Tests finished") import sys + print(sys.executable)