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

ENH pawn promotion #11

Merged
merged 30 commits into from
Oct 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
9161b1f
ADD: Pawn DocString
VincentAuriau Oct 20, 2023
4a4692a
ADD: material main classes descriptions
VincentAuriau Oct 20, 2023
8e28aff
ADD: full docstring for material
VincentAuriau Oct 21, 2023
6ce7e54
:art: Format Python code with psf/black
VincentAuriau Oct 21, 2023
01ef266
Merge pull request #8 from VincentAuriau/actions/black
VincentAuriau Oct 21, 2023
e4f4c8c
ADD: better test CI organization
VincentAuriau Oct 21, 2023
c7b3110
:art: Format Python code with psf/black
VincentAuriau Oct 21, 2023
1158ba4
Merge pull request #9 from VincentAuriau/actions/black
VincentAuriau Oct 21, 2023
c54023f
Update ci.yaml
VincentAuriau Oct 21, 2023
e43e53f
Update ci.yaml
VincentAuriau Oct 21, 2023
b49b4ac
ADD: dev specific env
VincentAuriau Oct 21, 2023
dba0f42
Update ci.yaml
VincentAuriau Oct 21, 2023
69c899f
Create pyproject.toml
VincentAuriau Oct 21, 2023
112b304
Update ci.yaml
VincentAuriau Oct 21, 2023
2da7ef4
Update ci.yaml
VincentAuriau Oct 21, 2023
3bd822b
Update pyproject.toml
VincentAuriau Oct 21, 2023
7175eca
FIX: missing dev packages
VincentAuriau Oct 21, 2023
c54d4bb
Update requirements-dev.txt
VincentAuriau Oct 21, 2023
2460835
Update requirements-dev.txt
VincentAuriau Oct 21, 2023
99e3d11
edit CI
VincentAuriau Oct 21, 2023
578b59e
removed pywin32 version in requirements
VincentAuriau Oct 21, 2023
fae407b
rm pywin32 from requirements
VincentAuriau Oct 21, 2023
426b4d2
rm pypiwin32
VincentAuriau Oct 21, 2023
4e8976a
fix .toml
VincentAuriau Oct 21, 2023
225aac7
add pytest to requirements
VincentAuriau Oct 21, 2023
9c18493
rm tensorflow import
VincentAuriau Oct 21, 2023
acbc65b
:art: Format Python code with psf/black (#10)
github-actions[bot] Oct 21, 2023
464fb6c
ENH: restructure of pawn promotion
VincentAuriau Oct 22, 2023
d222051
ADD: tests for pawn promotion
VincentAuriau Oct 22, 2023
c061ab2
Merge branch 'master' into promotion
VincentAuriau Oct 22, 2023
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
24 changes: 14 additions & 10 deletions python/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 |')
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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:
Expand All @@ -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()

Expand Down
32 changes: 31 additions & 1 deletion python/engine/material.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
21 changes: 12 additions & 9 deletions python/engine/move.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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()
Expand All @@ -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):
Expand Down Expand Up @@ -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):
"""
Expand All @@ -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
Expand Down
38 changes: 36 additions & 2 deletions tests/unit_test/engine_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading