国际象棋 GUI 应用程序未收到使用通用国际象棋接口 (UCI) 的国际象棋引擎的响应

问题描述 投票:0回答:2

我过去使用不同的语言编写了一些玩具国际象棋引擎,它们都提供了自己的简单的基于文本的 UI。现在我想编写一个可以与 ChessX 或 Cute Chess 等国际象棋 GUI 一起使用的引擎。我已经阅读并理解了(至少我是这么认为的)通用国际象棋接口(UCI)协议。

为了获得第一个工作版本,我使用 Python(macOS 上的 3.9)作为我的引擎,这里是 通过 STDIN 寻找输入的部分根据要求提供了完整(非)工作示例:

import sys
import os
import time
import re
import select
import fileinput


if __name__ == '__main__':
    while True:
        if select.select([sys.stdin, ], [], [], 0.0)[0]:
            for line in fileinput.input():
                tokens = [ x.strip().lower() for x in re.split("\s+", line.strip()) ]
                if tokens[0] == "uci":
                    sys.stdout.write("id name mychess\n")
                    sys.stdout.write("id author myname\n")
                    sys.stdout.write("uciok\n")
                elif tokens[0] == "isready":
                    sys.stdout.write("readyok\n")
        time.sleep(2)

当我将我的引擎放入其中一个 GUI(或一个简单的 python-chess 应用程序,见下文)时,我的引擎会获取初始的“uci”命令并相应地回答,因为我可以使用一些测试和日志记录代码进行验证,这些代码未在上面的最小示例。

但是,什么也没有发生……直到 GUI 告诉我它们超时了。显然,他们没有从我的引擎那里得到任何答案。使用 python-chess 库,我可以验证引擎的响应没有到达 GUI 进程。

这是我的 python-chess 应用程序中用于连接到我的引擎的代码:

engine = chess.engine.SimpleEngine.popen_uci(r"./engine.py")

如果我将

stockfish
引擎的路径放在那里,我可以看到该引擎的响应以及 python-chess 应用程序如何用“ucinewgame”和许多其他通信进行应答。

那么,为什么 GUI 客户端无法读取我的引擎的响应?

更新: 我怀疑这与我的示例中的

select
代码有关。它的作用是模拟对 STDIN 的非阻塞访问。在一种更简单的方法中,我只是使用阻塞调用来输入并且它有效(这是它的要点):

while True:
    line = input()
    if line.strip().lower() == "uci":
        print("id name mychess")
        print("uciok")
python chess uci
2个回答
0
投票

问题似乎在于使用

select.select()
和/或
fileinput.input()
。如果我省略这些花哨的技术并简单地从 STDIN 读取,则一切正常并且
cutechess
接受我的引擎。这是 UCI 国际象棋引擎获得认可的基本代码:

import sys
import os
import re


if __name__ == '__main__':
    while True:
        line = input()
        tokens = [ x.strip().lower() for x in re.split("\s+", line.strip()) ]
        if tokens[0] == "uci":
            sys.stdout.write("id name mychess\n")
            sys.stdout.write("id author myname\n")
            sys.stdout.write("uciok\n")
        elif tokens[0] == "isready":
            print("readyok")

当然,对

input()
的阻塞调用现在不允许在我的引擎中进行并发计算,同时立即接受来自 GUI 的输入,但这可能是另一个问题。


0
投票

我的声誉级别不允许发表评论,因此我被迫输入答案:在其他类似情况下,我经常发现对控制台的 StdOut 流的“刷新”命令允许重定向的控制台输出显示在接收者 GUI 应用程序中。

© www.soinside.com 2019 - 2024. All rights reserved.