Skip to content

Commit

Permalink
Merge pull request #36 from VincentAuriau/readme
Browse files Browse the repository at this point in the history
Readme enhancement
  • Loading branch information
VincentAuriau authored Nov 1, 2023
2 parents ea8d168 + 7c109a1 commit 000357b
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 22 deletions.
26 changes: 21 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,39 @@ Special thanks and dedication to LeMerluche, crushing its opponents on chess.com

## How to play with interface
```python
from interface.interface import MyApp
from pyalapin.interface.interface import MyApp

if __name__ == '__main__':
MyApp().run()
MyApp(
play_with_ai=False # Set to True if you want to play agains AI
).run()

```

![](interface_example.PNG)
![](docs/scholars_mate_interface.gif)

## How to play with Python commands

<img align="right" src="docs/scholars_mate_command.gif">

```python
import sys
sys.path.append("python/")
import python.engine as engine

game = engine.engine.Game()
game = engine.engine.Game(
automatic_draw=True, # Set to True if you want
# to have each turn drawn in terminal
ai=False, # set to True if you want to play agains AI
save_pgn=False # set to True if you want to
# save moves as PGN
)
game.move_from_coordinates(game.player1, 1, 4, 3, 4)
game.move_from_coordinates(game.player2, 6, 0, 5, 0)
game.move_from_coordinates(game.player2, 6, 4, 4, 4)
game.move_from_coordinates(game.player1, 0, 5, 3, 2)
game.move_from_coordinates(game.player2, 6, 3, 5, 4)
game.move_from_coordinates(game.player1, 0, 3, 2, 5)
game.move_from_coordinates(game.player2, 6, 2, 4, 2)
game.move_from_coordinates(game.player2, 2, 5, 6, 5)
```
There are colors in the command line not showing here in the GIF, though...
Binary file added docs/scholars_mate_command.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/scholars_mate_interface.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
33 changes: 29 additions & 4 deletions pyalapin/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,9 @@ def is_threatened(

# King + Rook + Queen
# Checking direct surroundings
for i, j in [(1, 0), (0, -1), (-1, 0), (0, -1)]:
for i, j in [(1, 0), (0, -1), (-1, 0), (0, 1)]:
x_to_check = self.x + i
y_to_check = self.y + j

if 0 <= x_to_check < 8 and 0 <= y_to_check < 8:
cell_to_check = board.get_cell(x_to_check, y_to_check)
piece_to_check = cell_to_check.get_piece()
Expand Down Expand Up @@ -964,11 +963,17 @@ class Game:
List storing all the played move during the game.
automatic draw: bool
Whether to draw the board in the terminal at each round.
save_pgn: bool
Whether to keep track of the moves with PGN.
history: list of str
PGN representation of the past move of the game.
"""

game_status = []

def __init__(self, player1=None, player2=None, automatic_draw=True, ai=False):
def __init__(
self, player1=None, player2=None, automatic_draw=True, ai=False, save_pgn=False
):
"""Initialization of the cell.
Parameters
Expand Down Expand Up @@ -1007,13 +1012,17 @@ def __init__(self, player1=None, player2=None, automatic_draw=True, ai=False):
self.board = Board()
self.status = "ACTIVE"
self.played_moves = []
self.save_pgn = save_pgn
if self.save_pgn:
self.history = []

self.automatic_draw = automatic_draw

def reset_game(self):
"""Method to reset the game. Recreates the borad, the pieces and restarts the game."""
self.board.reset()
self.played_moves = []
self.history = []
self.to_play_player = self.player1

def to_fen(self):
Expand Down Expand Up @@ -1200,6 +1209,8 @@ def move(self, move, player):

# Store move
self.played_moves.append(move)
if self.save_pgn:
self.history.append(move.to_pgn())

# Change player
if self.to_play_player == self.player1:
Expand Down Expand Up @@ -1271,11 +1282,25 @@ def save(self, directory="debug_files"):
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.tight_layout()
plt.savefig(os.path.join(directory, str(len(self.played_moves)) + ".png"))
"""
with open(os.path.join(directory, str(len(self.played_moves)) + ".txt"), "w") as f:
f.writelines(draw_text)

def to_pgn(self):
assert self.save_pgn
pgn = ""
for i in range(len(self.history)):
if i % 2 == 0:
pgn += f"{int(i/2)+1}. "
pgn += self.history[i]
pgn += " "

return pgn[:-1]
38 changes: 37 additions & 1 deletion pyalapin/engine/move.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,42 @@ def _set_moved_attribute(self):
else:
self.moved_piece.last_move_is_double = False

def to_pgn(self):
"""
Method to return the PGN representation of the move.
Returns
-------
str:
pgn representation of the move
"""
rows = ["a", "b", "c", "d", "e", "f", "g", "h"]
start = f"{rows[self.start.y]}{self.start.x + 1}"
end = f"{rows[self.end.y]}{self.end.x + 1}"
piece = self.moved_piece.get_str().replace(" ", "")
if isinstance(self.moved_piece, material.Pawn):
piece = ""
if self.killed_piece is not None:
start += "x"
elif self.is_castling:
if (self.moved_piece.is_white() and self.end.y == 1) or (
not self.moved_piece.is_white() and self.end.y == 6
):
piece = "O-O-O"
start = ""
end = ""
king = (
self.board.white_king
if not self.player.white_side
else self.board.black_king
)
if self.board.get_cell(king.x, king.y).is_threatened(
board=self.board, threaten_color=not self.player.white_side
):
end += "+"
print(f"{piece}{start}{end}")
return f"{piece}{start}{end}"

def _set_castling_done(self):
"""
If self is a castling move, then when it is done this function sets the castling_done attribute
Expand Down Expand Up @@ -140,7 +176,7 @@ def _is_castling(self):
return False

else:
if self.end.y == 6: # Castling in the right
if self.end.y == 6: # Castling on the right
rook_to_move = self.board.get_cell(self.start.x, 7).get_piece()
if not isinstance(rook_to_move, material.Rook):
return False
Expand Down
9 changes: 5 additions & 4 deletions pyalapin/player/ai_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,11 @@ def _alpha_beta(
beta=beta,
is_white=not is_white,
)
random_noise = np.random.randint(0, self.random_coeff)
best_move = [best_move, p_mv][
np.argmax([best_score, score + random_noise])
]
if self.random_coeff > 0:
random_noise = np.random.randint(0, self.random_coeff)
else:
random_noise = 0
best_move = [best_move, p_mv][np.argmax([best_score, score + random_noise])]
best_score = np.max([best_score, score + random_noise])

if best_score >= beta:
Expand Down
6 changes: 1 addition & 5 deletions run_app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import sys

sys.path.append("python/")

from pyalapin.interface.interface import MyApp

if __name__ == "__main__":
MyApp(play_with_ai=True).run()
MyApp(play_with_ai=False).run()
12 changes: 9 additions & 3 deletions tests/unit_test/engine_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ def test_end_game():
print(keep_going, status)


if __name__ == "__main__":
test_en_passant()
test_end_game()
def test_pgn():
"""Tests the pgn history of the game."""
game = engine.Game(automatic_draw=False, save_pgn=True)
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, 0, 3, 4, 7)
game.move_from_coordinates(game.player2, 6, 6, 5, 6)
print(game.to_pgn())
assert game.to_pgn() == "1. e2e4 f7f5 2. Qd1h5+ g7g6"

0 comments on commit 000357b

Please sign in to comment.