1

我正在尝试使用 stockfish 来评估使用 FEN 符号的国际象棋位置,所有这些都在 Python 中。我主要使用两个库(我在 github 上找到的 pgnToFen:https ://github.com/SindreSvendby/pgnToFen和 Stockfish,MIT 在这里获得了许可:https ://github.com/zhelyabuzhsky/stockfish )。在许多错误之后,我遇到了一个又一个问题。Stockfish不仅无法分析这个FEN位置(3b2k1/1p3pp1/8/3pP1P1/pP3P2/P2pB3/6K1/8 b f3 -),而且它无限循环!“不用担心!” 并认为更改源代码是可以完成的。更改为 _put(),但基本上我无法放入虚拟值,因为一旦我给它这些值,stdin.flush() 就不会执行!这意味着我什至不认为我可以跳到数据框中的下一行。:( 我更改的代码如下。

def _put(self, command: str, tmp_time) -> None:
        if not self.stockfish.stdin:
            raise BrokenPipeError()
        self.stockfish.stdin.write(f"{command}\n")

        try:
            self.stockfish.stdin.flush()

        except:
            if command != "quit":
                self.stockfish.stdin.write('isready\n')  
                try:   
                    time.sleep(tmp_time)
                    self.stockfish.stdin.flush()
                except:
                    #print ('Imma head out', file=sys.stderr)
                    raise ValueError('Imma head out...')
                    #sys.stderr.close()

def get_evaluation(self) -> dict:
        """Evaluates current position

        Returns:
            A dictionary of the current advantage with "type" as "cp" (centipawns) or "mate" (checkmate in)
        """

        evaluation = dict()
        fen_position = self.get_fen_position()
        if "w" in fen_position:  # w can only be in FEN if it is whites move
            compare = 1
        else:  # stockfish shows advantage relative to current player, convention is to do white positive
            compare = -1
        self._put(f"position {fen_position}", 5)
        self._go()
        x=0
        while True:
            x=x+1
            text = self._read_line()
            #print(text)
            splitted_text = text.split(" ")
            if splitted_text[0] == "info":
                for n in range(len(splitted_text)):
                    if splitted_text[n] == "score":
                        evaluation = {
                            "type": splitted_text[n + 1],
                            "value": int(splitted_text[n + 2]) * compare,
                        }
            elif splitted_text[0] == "bestmove":
                return evaluation

            elif x == 500:
                evaluation = {
                    "type": 'cp',
                    "value": 10000,
                }
                return evaluation

最后但并非最不重要的更改为下面的init _ 构造函数:

self._stockfish_major_version: float = float(self._read_line().split(" ")[1])

下面是我要导入此代码的代码,这是弹出错误的地方。

import pandas as pd
import re
import nltk
import numpy as np
from stockfish import Stockfish
import os
import sys

sys.path.insert(0, r'C:\Users\path\to\pgntofen')

import pgntofen

#nltk.download('punkt')

#Changed models.py for major version line 39 in stockfish from int to float

stockfish = Stockfish(r"C:\Users\path\to\Stockfish.exe")

file = r'C:\Users\path\to\selenium-pandas output.csv'

chunksize = 10 ** 6
for chunk in pd.read_csv(file, chunksize=chunksize):
    for index, row in chunk.iterrows():
        FullMovesStr = str(row['FullMoves']) 
        FullMovesStr = FullMovesStr.replace('+', '')
        if "e.p" in FullMovesStr:
            row.to_csv(r'C:\Users\MyName\Logger.csv', header=None, index=False, mode='a')
            
            print('Enpassant')
            continue

        tokens = nltk.word_tokenize(FullMovesStr)
        
        movelist = []
        for tokenit in range(len(tokens)):
            
            if "." in str(tokens[tokenit]):
                try:
                    tokenstripped = re.sub(r"[0-9]+\.", "", tokens[tokenit])
                    token = [tokenstripped, tokens[tokenit+1]]
                    movelist.append(token)
                except:
                    continue
            else:
                continue
        DFMoves = pd.DataFrame(movelist, columns=[['WhiteMove', 'BlackMove']])
        DFMoves['index'] = row['index']
        DFMoves['Date'] = row['Date']
        DFMoves['White'] = row['White']
        DFMoves['Black'] = row['Black']
        DFMoves['W ELO'] = row['W ELO']
        DFMoves['B ELO'] = row['B ELO']
        DFMoves['Av ELO'] = row['Av ELO']
        DFMoves['Event'] = row['Event']
        DFMoves['Site'] = row['Site']
        DFMoves['ECO'] = row['ECO']
        DFMoves['Opening'] = row['Opening']
        pd.set_option('display.max_rows', DFMoves.shape[0]+1)
        print(DFMoves[['WhiteMove', 'BlackMove']])
        seqmoves = []
        #seqmovesBlack = []
        evalmove = []

        pgnConverter = pgntofen.PgnToFen()
        #stockfish.set_fen_position("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
        #rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
        for index, row in DFMoves.iterrows():
            try:
                stockfish.set_fen_position("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
            except:
                evalmove.append("?")
                continue
            #stockfish.set_fen_position("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
            pgnConverter.resetBoard()
            WhiteMove = str(row['WhiteMove'])
            BlackMove = str(row['BlackMove'])

            if index == 0:
                PGNMoves1 = [WhiteMove]
                seqmoves.append(WhiteMove)
                #seqmoves.append(BlackMove)
            else:
                seqmoves.append(WhiteMove)
                #seqmoves.append(BlackMove)
                PGNMoves1 = seqmoves.copy()

            #print(seqmoves)
            try:
                pgnConverter.pgnToFen(PGNMoves1)
                fen = pgnConverter.getFullFen()
            except:
                break

            try:
          
                stockfish.set_fen_position(fen)
                print(stockfish.get_board_visual())
                evalpos = stockfish.get_evaluation()
                evalmove.append(evalpos)
              
            except:
                pass
          
            try:
                stockfish.set_fen_position("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1")
            except:
                evalmove.append("?")
                continue

            pgnConverter.resetBoard()

            if index == 0:
                PGNMoves2 = [WhiteMove, BlackMove]
                seqmoves.append(BlackMove)
            else:
                seqmoves.append(BlackMove)
                PGNMoves2 = seqmoves.copy()

            try:
                pgnConverter.pgnToFen(PGNMoves2)
                fen = pgnConverter.getFullFen()
            except:
                break

            try:
                stockfish.set_fen_position(fen)
                print(stockfish.get_board_visual())
                evalpos = stockfish.get_evaluation()
                print(evalpos)
                evalmove.append(evalpos)
            except:
                pass

        #DFMoves['EvalWhite'] = evalwhite
        #DFMoves['EvalBlack'] = evalblack
        print(evalmove)

因此,详细的问题是让 stockfish.get_evalution() 跳过,或者更好地解决问题,为此( 3b2k1/1p3pp1/8/3pP1P1/pP3P2/P2pB3/6K1/8 b f3 - )FEN 位置。我一直在研究这个问题很长一段时间,所以任何对此的见解都将非常感激。

我的规格是 Windows 10、Python 3.9、处理器:Intel(R) Core(TM) i9-10980XE CPU @ 3.00GHz 3.00 GHz,RAM 为 64.0 GB。

谢谢 :)

4

1 回答 1

2

好的。看来您的 fen 无效(3b2k1/1p3pp1/8/3pP1P1/pP3P2/P2pB3/6K1/8 b f3 -)。所以检查一下。并且 python-chess ( https://python-chess.readthedocs.io/en/latest/index.html ) 库允许您使用 FEN AND chess 引擎。所以,很酷,不是吗?这是这两个神奇工具的示例:

import chess
import chess.engine
import chess.pgn

pgn = open("your_pgn_file.pgn")
game = chess.pgn.read_game(pgn)

engine = chess.engine.SimpleEngine.popen_uci("your_stockfish_path.exe")

 # Iterate through all moves, play them on a board and analyse them.
board = game.board()
for move in game.mainline_moves():
    board.push(move)
    print(engine.analyse(board, chess.engine.Limit(time=0.1))["score"])
于 2021-11-03T19:13:45.937 回答