import chess
import chess.pgn
import chess.engine
import tkinter as tk
from tkinter import simpledialog
import os
from tqdm import tqdm
# Function to get FEN position from a popup window
def get_fen_position():
root = tk.Tk()
root.withdraw()
fen_position = simpledialog.askstring("Input", "Paste the FEN position:")
root.destroy()
return fen_position
# Function to evaluate position using Stockfish
def evaluate_position(board, engine, depth_white=17, depth_black=6, multipv=3):
if board.turn == chess.WHITE:
result = engine.analyse(board, chess.engine.Limit(depth=depth_white))
move = result['pv'][0]
board.push(move)
else:
infos = engine.analyse(board, chess.engine.Limit(depth=depth_black), multipv=multipv)
moves = [info['pv'][0] for info in infos if 'pv' in info]
for move in moves:
board.push(move)
response = engine.analyse(board, chess.engine.Limit(depth=depth_white))
board.pop()
return board
# Function to recursively evaluate and write moves to PGN
def recursive_evaluation(board, engine, node, depth=1, max_depth=8, pbar=None):
if depth > max_depth:
return
board = evaluate_position(board, engine)
if board.turn == chess.BLACK:
infos = engine.analyse(board, chess.engine.Limit(depth=6), multipv=3)
for info in infos:
if 'pv' not in info:
continue
new_board = board.copy()
move = info['pv'][0]
new_board.push(move)
new_node = node.add_variation(move)
recursive_evaluation(new_board, engine, new_node, depth + 1, max_depth, pbar)
else:
move = board.peek()
new_node = node.add_variation(move)
recursive_evaluation(board, engine, new_node, depth + 1, max_depth, pbar)
if pbar:
pbar.update(1)
# Main function to run the script
def main():
# Path to Stockfish executable
stockfish_path = 'C:/Users/Admintrator/Downloads/stockfish-windows-x86-64-avx2/stockfish/stockfish-windows-x86-64-avx2.exe'
# Path to the existing PGN file
pgn_path = "C:/Users/Admintrator/OneDrive - Nguyen Sieu School/Documents/EnCroissant/Nhị Cuộc Phi Đao.pgn"
# Initialize engine
engine = chess.engine.SimpleEngine.popen_uci(stockfish_path)
# Set Stockfish options for threads and hash size
engine.configure({"Threads": 16, "Hash": 8192})
# Get FEN position from user
fen = get_fen_position()
# Load the existing PGN file
with open(pgn_path, "r", encoding="utf-8") as pgn:
game = chess.pgn.read_game(pgn)
# Set up the board with the given FEN position
board = chess.Board(fen)
node = game.end()
# Initialize progress bar
max_depth = 8
total_steps = sum(3**i for i in range(max_depth)) # Total steps for progress bar
with tqdm(total=total_steps, desc="Evaluating Position") as pbar:
# Evaluate position and add moves to PGN
recursive_evaluation(board, engine, node, max_depth=max_depth, pbar=pbar)
# Write the updated game to the PGN file
with open("evaluated_game.pgn", "w", encoding="utf-8") as pgn_out:
exporter = chess.pgn.FileExporter(pgn_out)
game.accept(exporter)
# Close engine
engine.quit()
if __name__ == "__main__":
main()
我想制作一个工具,使用 stockfish 自动继续评估 .PGN 文件中的某个位置。不知何故,它跑了 3/4,并说:
Traceback (most recent call last):
File "C:\Users\Admintrator\Downloads\FEN continue.py", line 98, in <module>
main()
File "C:\Users\Admintrator\Downloads\FEN continue.py", line 92, in main
game.accept(exporter)
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\pgn.py", line 883, in accept
self.variations[0]._accept(board, visitor)
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\pgn.py", line 756, in _accept
top.node._accept_node(parent_board, visitor)
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\pgn.py", line 733, in _accept_node
visitor.visit_move(parent_board, self.move)
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\pgn.py", line 1403, in visit_move
self.write_token(board.san(move) + " ")
^^^^^^^^^^^^^^^
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\__init__.py", line 2866, in san
return self._algebraic(move)
^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\__init__.py", line 2879, in _algebraic
san = self._algebraic_and_push(move, long=long)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\__init__.py", line 2884, in _algebraic_and_push
san = self._algebraic_without_suffix(move, long=long)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\Admintrator\AppData\Local\Programs\Python\Python311\Lib\site-packages\chess\__init__.py", line 2920, in _algebraic_without_suffix
assert piece_type, f"san() and lan() expect move to be legal or null, but got {move} in {self.fen()}"
AssertionError: san() and lan() expect move to be legal or null, but got f8b8 in r6K/p1pbqppp/2nP3n/bP6/2B1P3/1Qp2N2/P4PPP/RNB2RK1 b - - 0 11
我不知道要修复什么,尝试使用 ChatGPT 但仍然无法让它工作。经历了 Stackoverflow 上的每一个相同的错误,但仍然无法修复它。
f8 上没有棋子为黑色,因此不能将任何棋子从该方格移动到 b8。请参考Lichess分中的位置。您看到的错误是由于“移动”不合法造成的。