如何与Python中的象棋引擎通信?

2024-05-09 23:56:23 发布

您现在位置:Python中文网/ 问答频道 /正文

在win 7上,我可以通过命令行与象棋引擎通信。Win 7上与Stockfish的小示例会话:

C:\run\Stockfish>stockfish-x64.exe
Stockfish 2.2.2 JA SSE42 by Tord Romstad, Marco Costalba and Joona Kiiski
quit

C:\run\Stockfish>

第一行是引擎输出的,“quit”是我键入的退出引擎的内容(这里有other things i can do,但我很清楚)。

现在我想和python中的引擎通信:

import subprocess
engine = subprocess.Popen(
    'stockfish-x64.exe',
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
)
for line in engine.stdout:
    print(line.strip())
engine.stdin.write('quit\n')

我得到了

C:\run\Stockfish>communicate.py
b'Stockfish 2.2.2 JA SSE42 by Tord Romstad, Marco Costalba and Joona Kiiski'

但它没有退出引擎(没有C:\ run\Stockfish>;提示),它一直在等待输入。我得用手关上窗户。似乎没有将我的退出消息(python脚本的最后一行)写入stdin。

换言之,我可以从stdout中阅读,但当我给stdin写信时,什么也不会发生。

我做错了什么,怎么做才对?


编辑:好吧,多亏拉尔曼的帮助,我解决了这个问题:

示例Python脚本:

import subprocess, time

engine = subprocess.Popen(
    'stockfish-x64.exe',
    universal_newlines=True,
    stdin=subprocess.PIPE,
    stdout=subprocess.PIPE,
)

def put(command):
    print('\nyou:\n\t'+command)
    engine.stdin.write(command+'\n')

def get():
    # using the 'isready' command (engine has to answer 'readyok')
    # to indicate current last line of stdout
    engine.stdin.write('isready\n')
    print('\nengine:')
    while True:
        text = engine.stdout.readline().strip()
        if text == 'readyok':
            break
        if text !='':
            print('\t'+text)

get()
put('uci')
get()
put('setoption name Hash value 128')
get()
put('ucinewgame')
get()
put('position startpos moves e2e4 e7e5 f2f4')
get()
put('go infinite')
time.sleep(3)
get()
put('stop')
get()
put('quit')

输出:

C:\run\Stockfish>1-communicate.py

engine:
        Stockfish 2.2.2 JA SSE42 by Tord Romstad, Marco Costalba and Joona Kiiski

you:
        uci

engine:
        id name Stockfish 2.2.2 JA SSE42
        id author Tord Romstad, Marco Costalba and Joona Kiiski
        option name Use Search Log type check default false
        option name Search Log Filename type string default SearchLog.txt
        ... etc ...
        uciok

you:
        setoption name Hash value 128

engine:

you:
        ucinewgame

engine:

you:
        position startpos moves e2e4 e7e5 f2f4

engine:

you:
        go infinite

engine:
        info depth 1 seldepth 1 score cp 56 nodes 62 nps 1675 time 37 multipv 1 pv e5f4
        info depth 2 seldepth 2 score cp 48 nodes 804 nps 21157 time 38 multipv 1 pv b8c6 g1h3
        info depth 3 seldepth 3 score cp 64 nodes 1409 nps 37078 time 38 multipv 1 pv b8c6 b1c3 e5f4
        ... etc ...

you:
        stop

engine:
        bestmove e5f4 ponder g1f3

you:
        quit

C:\run\Stockfish>

Tags: runname引擎yougettimeputstdin
2条回答

您遇到了死锁:子进程正在等待输入,而您的程序正在等待它输出更多的行

for line in engine.stdout:
    print(line.strip())

此循环仅在子进程关闭其stdout时停止。

您可能希望像python chess那样使用asyncio。 见

engine.py

以及来自documentation的示例

import asyncio
import chess
import chess.engine

    async def main():
        transport, engine = await chess.engine.popen_uci("/usr/bin/stockfish")

        board = chess.Board()
        while not board.is_game_over():
            result = await engine.play(board, chess.engine.Limit(time=0.1))
            board.push(result.move)

        await engine.quit()

    asyncio.set_event_loop_policy(chess.engine.EventLoopPolicy())
    asyncio.run(main())

相关问题 更多 >