Response from my chess engine using Universal Chess Interface (UCI) isn't received by the chess GUI apps

509 Views Asked by At

I've coded some toy chess engines in the past using different languages, all of them providing their own simple text-based UI. Now I want to write an engine that can be used with chess GUIs like ChessX or Cute Chess. I've read and understood (at least I thought so) the Universal Chess Interface (UCI) protocol.

To get a first working version, I'm using Python (3.9 on macOS) for my engine, here's the part that's looking for input via STDIN a full (non-)working example as requested:

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)

When I put my engine in one of the GUIs (or a simple python-chess app, see below), my engine gets the initial "uci" command and answers accordingly as I can verify using some test and logging code not shown in the minimal example above.

But then, nothing happens ... until the GUIs are telling me they timed-out. Obviously, they didn't get any answer from my engine. Using the python-chess library, I can verify that the response from my engine isn't coming through to the GUI process.

This is the code in my python-chess app to connect to my engine:

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

If I put there the path to the stockfish engine, I can see the response from that engine and how the python-chess app answers with "ucinewgame" and a lot of other communication.

So, why is the response from my engine not read by the GUI client?

Update: I suspect it has something to do with the select code in my example. It's there to simulate non-blocking access to STDIN. In a simpler approach, I'm just using a blocking call to input and it works (here's the gist of it):

while True:
    line = input()
    if line.strip().lower() == "uci":
        print("id name mychess")
        print("uciok")
2

There are 2 best solutions below

0
z80crew On BEST ANSWER

The problem seems to be in using select.select() and/or fileinput.input(). If I omit those fancy techniques and simply read from STDIN, everything works and cutechess accepts my engine. This is the basic code for a UCI chess engine to get recognized:

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")

Of course, the blocking call to input() now doesn't allow for concurrent calculations in my engine while accepting input from the GUI immediately, but that's stuff for perhaps another question.

1
user3210861 On

My reputation level does not allow commenting, so I am forced to enter an answer: In other similar situations, I often found that a "flush" command to the console's StdOut stream allows the redirected console output to show in the recipient GUI application.