diff --git a/python/engine/engine.py b/python/engine/engine.py index e9b0fea..2115abd 100644 --- a/python/engine/engine.py +++ b/python/engine/engine.py @@ -575,7 +575,6 @@ def kill_piece_from_coordinates(self, coordinates): def transform_pawn(self, coordinates): pawn = self.get_cell(coordinates[0], coordinates[1]).get_piece() if not isinstance(pawn, material.Pawn): - ###print(pawn) raise ValueError("Transforming piece that is not a Pawn") else: color = "white" if pawn.is_white() else "black" @@ -585,6 +584,18 @@ def transform_pawn(self, coordinates): self.get_cell(pawn.x, pawn.y).set_piece(new_queen) self.all_material[color]["alive"]["queen"].append(new_queen) + def promote_pawn(self, coordinates, promote_into="Queen"): + pawn = self.get_cell(coordinates[0], coordinates[1]).get_piece() + if not isinstance(pawn, material.Pawn): + raise ValueError("Transforming piece that is not a Pawn") + else: + color = "white" if pawn.is_white() else "black" + self.all_material[color]["alive"][pawn.type].remove(pawn) + + new_piece = pawn.promote(promote_into=promote_into) + self.get_cell(pawn.x, pawn.y).set_piece(new_piece) + self.all_material[color]["alive"]["queen"].append(new_piece) + def draw(self, printing=True): whole_text = " | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |" # ###print(' | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |') @@ -644,11 +655,11 @@ def to_fen(self): def is_finished(self): return self.status != "ACTIVE" - def move_from_coordinates(self, player, start_x, start_y, end_x, end_y): + def move_from_coordinates(self, player, start_x, start_y, end_x, end_y, extras={}): start_cell = self.board.get_cell(start_x, start_y) end_cell = self.board.get_cell(end_x, end_y) - move = Move(player, self.board, start_cell, end_cell) + move = Move(player, self.board, start_cell, end_cell, extras=extras) return self.move(move, player) @@ -703,22 +714,17 @@ def move(self, move, player): # List of checks # To change if castling or en passant move if moved_piece is None: - ###print('There is no moved piece, move is aborted') return False, 0 assert moved_piece is not None if player != self.to_play_player: - ###print('The wrong player has played, move is aborted') - ###print(self.to_play_player, 'supposed to play and', player, 'has played') return False, 0 assert player == self.to_play_player allowed_move = move.is_possible_move() if not allowed_move: - ###print('Move method checking legality of move rejected it') return False, 0 elif moved_piece.is_white() != player.is_white_side(): - ###print("Engine detected player to move other side piece") return False, 0 else: @@ -743,8 +749,6 @@ def move(self, move, player): print("END OF THE GAME, WHITE HAS WON") return False, "white" - ###print('PLAYER TO PLAY:', self.to_play_player) - # Checking for PAT & MAT check_status, winner = self.update_status() diff --git a/python/engine/material.py b/python/engine/material.py index 5f3b8f4..807a9eb 100644 --- a/python/engine/material.py +++ b/python/engine/material.py @@ -376,7 +376,37 @@ def get_potential_moves(self, x, y): return possible_moves def promote(self, promote_into="Queen"): - raise NotImplementedError + """Method to promote a pawn to other material type. Only happens if the pawn reaches the other side of the board. + The player can choose which type of material he wants its pawn to be promoted into. + + Parameters + ---------- + promote_into: str + Type of material to promote the pawn into. + + Returns + ------- + Piece + New piece with right promotion and same coordinates of current pawn. + """ + # Should we verify color and coordinates of Pawn ? + if self.is_white(): + assert self.x == 7, "Pawn has not reached other side of the board" + else: + assert self.x == 0, "Pawn has not reached the other side of the board" + + if promote_into.lower() == "queen": + return Queen(white=self.is_white(), x=self.x, y=self.y) + elif promote_into.lower() == "rook": + rook = Rook(white=self.is_white(), x=self.x, y=self.y) + rook.has_moved = True + return rook + elif promote_into == "knight": + return Knight(white=self.is_white(), x=self.x, y=self.y) + elif promote_into == "bishop": + return Bishop(white=self.is_white(), x=self.x, y=self.y) + else: + raise ValueError(f"Cannot promote piece into, {promote_into}, piece unknown") def get_str(self): """Method to represent the piece as a string. diff --git a/python/engine/move.py b/python/engine/move.py index 2613ffb..1bcf377 100644 --- a/python/engine/move.py +++ b/python/engine/move.py @@ -5,11 +5,13 @@ class Move: - def __init__(self, player, board, start, end): + def __init__(self, player, board, start, end, extras={}): self.player = player self.board = board self.start = start self.end = end + self.extras = extras + self.moved_piece = start.get_piece() if self.moved_piece is None: ###print("Empty cell selected as start of a move") @@ -18,7 +20,6 @@ def __init__(self, player, board, start, end): self.is_castling = False self.complementary_castling = None self.en_passant = False - self.transform_pawn = False def deepcopy(self): copied_board = self.board.deepcopy() @@ -31,7 +32,6 @@ def deepcopy(self): copied_move.is_castling = self.is_castling copied_move.complementary_castling = self.complementary_castling copied_move.en_passant = self.en_passant - copied_move.transform_pawn = self.transform_pawn return copied_move def _set_moved_attribute(self): @@ -162,21 +162,24 @@ def _is_en_passant(self): else: return False - def _is_pawn_transformation(self): + def _is_pawn_promotion(self): if not isinstance(self.moved_piece, material.Pawn): return False else: if self.end.get_x() == 7 and self.moved_piece.is_white(): + self.promote_into = self.extras.get("promote_into", "queen") + print(self.extras) return True elif self.end.get_x() == 0 and not self.moved_piece.is_white(): + self.promote_into = self.extras.get("promote_into", "queen") return True else: return False - def _transform_pawn(self): - ###print("TRANSFORM PAWN 2", self.moved_piece, self.moved_piece.is_white()) + def _promote_pawn(self): coordinates = (self.end.get_x(), self.end.get_y()) - self.board.transform_pawn(coordinates) + print("promote into", self.promote_into) + self.board.promote_pawn(coordinates=coordinates, promote_into=self.promote_into) def move_pieces(self): """ @@ -198,8 +201,8 @@ def move_pieces(self): ###print("CASTLING DETECTED PPPPPPPPP") self._set_castling_done() - if self._is_pawn_transformation(): - self._transform_pawn() + if self._is_pawn_promotion(): + self._promote_pawn() self._set_moved_attribute() def is_possible_move(self): # REFONDRE diff --git a/tests/unit_test/engine_test.py b/tests/unit_test/engine_test.py index 87986c2..b97f415 100644 --- a/tests/unit_test/engine_test.py +++ b/tests/unit_test/engine_test.py @@ -10,9 +10,43 @@ def test_blocked_moves(): """ Test that a blocked move does not happen. """ - print("ok") game = engine.Game(automatic_draw=False) game.move_from_coordinates(game.player1, 1, 4, 3, 4) _, winner = game.move_from_coordinates(game.player2, 7, 0, 5, 0) - print("win", winner) assert winner == 0 + +def test_promotion_to_rook(): + """ + Test that the promotion works well + """ + game = engine.Game(automatic_draw=False) + game.move_from_coordinates(game.player1, 1, 4, 3, 4) + game.move_from_coordinates(game.player2, 6, 5, 4, 5) + game.move_from_coordinates(game.player1, 3, 4, 4, 5) + game.move_from_coordinates(game.player2, 7, 6, 5, 7) + game.move_from_coordinates(game.player1, 4, 5, 5, 5) + game.move_from_coordinates(game.player2, 6, 0, 5, 0) + game.move_from_coordinates(game.player1, 5, 5, 6, 6) + game.move_from_coordinates(game.player2, 5, 0, 4, 0) + game.move_from_coordinates(game.player1, 6, 6, 7, 6, extras={"promote_into": "rook"}) + assert game.board.to_fen()[0] == "rnbqkbnr/pppp1ppp/8/8/P7/7N/1PPPP2P/RNBQKBrR" + + +def test_default_promotion(): + """ + Test that the promotion works well + """ + game = engine.Game(automatic_draw=False) + game.move_from_coordinates(game.player1, 1, 4, 3, 4) + game.move_from_coordinates(game.player2, 6, 5, 4, 5) + game.move_from_coordinates(game.player1, 3, 4, 4, 5) + game.move_from_coordinates(game.player2, 7, 6, 5, 7) + game.move_from_coordinates(game.player1, 4, 5, 5, 5) + game.move_from_coordinates(game.player2, 6, 0, 5, 0) + game.move_from_coordinates(game.player1, 5, 5, 6, 6) + game.move_from_coordinates(game.player2, 5, 0, 4, 0) + game.move_from_coordinates(game.player1, 6, 6, 7, 6) + assert game.board.to_fen()[0] == "rnbqkbnr/pppp1ppp/8/8/P7/7N/1PPPP2P/RNBQKBqR" + +if __name__ == "__main__": + pass