chessbot: Upgrade python-chess to chess.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
1e6513136a
commit
189cf48573
|
@ -1,9 +1,9 @@
|
||||||
import copy
|
import copy
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
import chess
|
import chess
|
||||||
import chess.uci
|
import chess.engine
|
||||||
|
|
||||||
from zulip_bots.lib import BotHandler
|
from zulip_bots.lib import BotHandler
|
||||||
|
|
||||||
|
@ -28,8 +28,9 @@ class ChessHandler:
|
||||||
self.config_info = bot_handler.get_config_info("chess")
|
self.config_info = bot_handler.get_config_info("chess")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.engine = chess.uci.popen_engine(self.config_info["stockfish_location"])
|
self.engine = chess.engine.SimpleEngine.popen_uci(
|
||||||
self.engine.uci()
|
self.config_info["stockfish_location"]
|
||||||
|
)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
# It is helpful to allow for fake Stockfish locations if the bot
|
# It is helpful to allow for fake Stockfish locations if the bot
|
||||||
# runner is testing or knows they won't be using an engine.
|
# runner is testing or knows they won't be using an engine.
|
||||||
|
@ -203,7 +204,7 @@ class ChessHandler:
|
||||||
# be over if it's *5*-fold or *75* moves, but if either player
|
# be over if it's *5*-fold or *75* moves, but if either player
|
||||||
# wants the game to be a draw, after 3 or 75 it a draw. For now,
|
# wants the game to be a draw, after 3 or 75 it a draw. For now,
|
||||||
# just assume that the players would want the draw.
|
# just assume that the players would want the draw.
|
||||||
if new_board.is_game_over(True):
|
if new_board.is_game_over(claim_draw=True):
|
||||||
game_over_output = ""
|
game_over_output = ""
|
||||||
|
|
||||||
if new_board.is_checkmate():
|
if new_board.is_checkmate():
|
||||||
|
@ -289,6 +290,10 @@ class ChessHandler:
|
||||||
|
|
||||||
computer_move = calculate_computer_move(new_board, self.engine)
|
computer_move = calculate_computer_move(new_board, self.engine)
|
||||||
|
|
||||||
|
if not computer_move:
|
||||||
|
bot_handler.send_reply(message, make_engine_failed_response())
|
||||||
|
return
|
||||||
|
|
||||||
new_board_after_computer_move = copy.copy(new_board)
|
new_board_after_computer_move = copy.copy(new_board)
|
||||||
new_board_after_computer_move.push(computer_move)
|
new_board_after_computer_move.push(computer_move)
|
||||||
|
|
||||||
|
@ -317,9 +322,16 @@ class ChessHandler:
|
||||||
"""
|
"""
|
||||||
last_board = self.validate_board(message, bot_handler, last_fen)
|
last_board = self.validate_board(message, bot_handler, last_fen)
|
||||||
|
|
||||||
|
if not last_board:
|
||||||
|
return
|
||||||
|
|
||||||
computer_move = calculate_computer_move(last_board, self.engine)
|
computer_move = calculate_computer_move(last_board, self.engine)
|
||||||
|
|
||||||
new_board_after_computer_move = copy.copy(last_board) # type: chess.Board
|
if not computer_move:
|
||||||
|
bot_handler.send_reply(message, make_engine_failed_response())
|
||||||
|
return
|
||||||
|
|
||||||
|
new_board_after_computer_move = copy.copy(last_board)
|
||||||
new_board_after_computer_move.push(computer_move)
|
new_board_after_computer_move.push(computer_move)
|
||||||
|
|
||||||
if self.check_game_over(message, bot_handler, new_board_after_computer_move):
|
if self.check_game_over(message, bot_handler, new_board_after_computer_move):
|
||||||
|
@ -353,7 +365,9 @@ class ChessHandler:
|
||||||
handler_class = ChessHandler
|
handler_class = ChessHandler
|
||||||
|
|
||||||
|
|
||||||
def calculate_computer_move(board: chess.Board, engine: Any) -> chess.Move:
|
def calculate_computer_move(
|
||||||
|
board: chess.Board, engine: chess.engine.SimpleEngine
|
||||||
|
) -> Optional[chess.Move]:
|
||||||
"""Calculates the computer's move.
|
"""Calculates the computer's move.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
|
@ -362,9 +376,8 @@ def calculate_computer_move(board: chess.Board, engine: Any) -> chess.Move:
|
||||||
|
|
||||||
Returns: The computer's move object.
|
Returns: The computer's move object.
|
||||||
"""
|
"""
|
||||||
engine.position(board)
|
result = engine.play(board, chess.engine.Limit(time=3.0))
|
||||||
best_move_and_ponder_move = engine.go(movetime=(3000))
|
return result.move
|
||||||
return best_move_and_ponder_move[0]
|
|
||||||
|
|
||||||
|
|
||||||
def make_draw_response(reason: str) -> str:
|
def make_draw_response(reason: str) -> str:
|
||||||
|
@ -493,6 +506,14 @@ def make_move_reponse(last_board: chess.Board, new_board: chess.Board, move: che
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def make_engine_failed_response() -> str:
|
||||||
|
"""Makes a response string for engine failure.
|
||||||
|
|
||||||
|
Returns: The engine failure response string.
|
||||||
|
"""
|
||||||
|
return "The computer failed to make a move."
|
||||||
|
|
||||||
|
|
||||||
def make_footer() -> str:
|
def make_footer() -> str:
|
||||||
"""Makes a footer to be appended to the bottom of other, actionable
|
"""Makes a footer to be appended to the bottom of other, actionable
|
||||||
responses.
|
responses.
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
python-chess[engine,gaviota] == 0.22.0
|
python-chess==0.31.* ; python_version < '3.7'
|
||||||
|
chess==1.* ; python_version >= '3.7'
|
||||||
|
|
Loading…
Reference in a new issue