An engine should still be responsive while searching, and therefore things like "echo go depth 5 | ./myengine" usually don't work, because the first time that the engine interrupts the search for checking input it will get an eof and terminate.
This is good, when you want the engine to be responsive even while thinking but bad if you want to script your engine. I currently have two ideas to mitigate that problem. I could write a little filter that knows which uci commands expect an engine reply and which one's don't or I can implement a custom command "batch on/off" into my engine controlling whether input should interrupt a search or not.
Has that been discussed before? Is there something like a standard solution to it? Using cutechess-cli for such a simple task looks a little bit like of overkill to me.
Piping input into an engine
Moderator: Ras
-
gflohr
- Posts: 57
- Joined: Fri Jul 23, 2021 5:24 pm
- Location: Elin Pelin
- Full name: Guido Flohr
-
BrokenKeyboard
- Posts: 24
- Joined: Tue Mar 16, 2021 11:11 pm
- Full name: Het Satasiya
Re: Piping input into an engine
You could just use the < operator in bash (which i assume your using).
./myengine < commands.txt
This doesnt allow you to do timings, but it does simulate stdin and you can pipe stdout to a file if you wish.
./myengine < commands.txt
This doesnt allow you to do timings, but it does simulate stdin and you can pipe stdout to a file if you wish.
-
gflohr
- Posts: 57
- Joined: Fri Jul 23, 2021 5:24 pm
- Location: Elin Pelin
- Full name: Guido Flohr
Re: Piping input into an engine
I know how to redirect input and output. But a properly written engine will terminate the search and the program itself as soon as it sees EOF. Try "echo go | stockfish" and it will just print its greeting and then "bestmove a2a3" because this is the first move that the move generator produces.
-
mvanthoor
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: Piping input into an engine
Why? That's a choice. My engine only stops the search if it receives the "stop" and "quit" commands (and in my case, "exit", because I type that half of the time). When I perform your test, the engine keeps searching and searching; you can never quit by typing a command however, because input doesn't come from stdin anymore.gflohr wrote: ↑Tue Sep 28, 2021 9:11 am I know how to redirect input and output. But a properly written engine will terminate the search and the program itself as soon as it sees EOF. Try "echo go | stockfish" and it will just print its greeting and then "bestmove a2a3" because this is the first move that the move generator produces.
Maybe the proper way _is_ to quit on EOF; if so, I'll have to add that some day.
-
gflohr
- Posts: 57
- Joined: Fri Jul 23, 2021 5:24 pm
- Location: Elin Pelin
- Full name: Guido Flohr
Re: Piping input into an engine
My engine treats almost every valid input as an implicit stop. IMHO that is more user-friendly. You can just type "go ..." start a new search.
I think you are well advised to terminate on EOF. Imagine you are currently in an "go infinite" search and the user closes the window.
I think you are well advised to terminate on EOF. Imagine you are currently in an "go infinite" search and the user closes the window.
-
gflohr
- Posts: 57
- Joined: Fri Jul 23, 2021 5:24 pm
- Location: Elin Pelin
- Full name: Guido Flohr
Re: Piping input into an engine
Back to the original question: I have now implemented an option "Batch" with default false. When set to true, the engine does not check input during the search, so that all commands are processed sequentially. I think that this is a reasonable extension.
-
Ras
- Posts: 2703
- Joined: Tue Aug 30, 2016 8:19 pm
- Full name: Rasmus Althoff
Re: Piping input into an engine
It is. If the GUI exits unexpectedly, you don't want your engine process to linger around.
Rasmus Althoff
https://www.ct800.net
https://www.ct800.net
-
mvanthoor
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: Piping input into an engine
OK. When I did "echo go | ./rustic", the engine would start a "go infinite", and be unable to terminate because input is not coming from stdin. I added terminating on reading 0 bytes (EOF), and if I now try the same thing, the engine starts but immediately exits. The termination command follows "go" so quickly that all threads terminate even before the move generator has a chance to output anything. As using a chess engine in this way is a super-niche case, I'm going to leave it at that.
To OP and Ras: thanks for pointing out that terminating on EOF should be standard behavior.
-
gflohr
- Posts: 57
- Joined: Fri Jul 23, 2021 5:24 pm
- Location: Elin Pelin
- Full name: Guido Flohr
Re: Piping input into an engine
Well, I'm a unix-guy and for me it is not a super-niche case but rather second nature. If I want to find out what Stockfish's favorite opening move is, I would test that with "echo go depth 80 | stockfish" but that gives me "bestmove a2a3" as a desperate attempt by stockfish to recover from the unexpected EOF with at least any move.mvanthoor wrote: ↑Tue Sep 28, 2021 6:57 pm OK. When I did "echo go | ./rustic", the engine would start a "go infinite", and be unable to terminate because input is not coming from stdin. I added terminating on reading 0 bytes (EOF), and if I now try the same thing, the engine starts but immediately exits. The termination command follows "go" so quickly that all threads terminate even before the move generator has a chance to output anything. As using a chess engine in this way is a super-niche case, I'm going to leave it at that.
If Stockfish followed my suggestion, I could create this text file:
Code: Select all
uci
setoption name Batch value true
go depth 80
-
mvanthoor
- Posts: 1784
- Joined: Wed Jul 03, 2019 4:42 pm
- Location: Netherlands
- Full name: Marcel Vanthoor
Re: Piping input into an engine
I could make it so that the engine sees the EOF and not react to it until the last command has been completely executed, discarding all other commands that may come in. Even though I'm a long-time Linux user myself (and recently fully switched to it on the desktop, finally) who uses the command line extensively, I can't see myself using a chess engine like that.gflohr wrote: ↑Thu Sep 30, 2021 9:57 pmWell, I'm a unix-guy and for me it is not a super-niche case but rather second nature. If I want to find out what Stockfish's favorite opening move is, I would test that with "echo go depth 80 | stockfish" but that gives me "bestmove a2a3" as a desperate attempt by stockfish to recover from the unexpected EOF with at least any move.mvanthoor wrote: ↑Tue Sep 28, 2021 6:57 pm OK. When I did "echo go | ./rustic", the engine would start a "go infinite", and be unable to terminate because input is not coming from stdin. I added terminating on reading 0 bytes (EOF), and if I now try the same thing, the engine starts but immediately exits. The termination command follows "go" so quickly that all threads terminate even before the move generator has a chance to output anything. As using a chess engine in this way is a super-niche case, I'm going to leave it at that.
If Stockfish followed my suggestion, I could create this text file:
and then pipe it into Stockfish with "stockfish <commands.txt" and it would do what I want. With Stockfish it doesn't work, with Plisco it now does.Code: Select all
uci setoption name Batch value true go depth 80![]()
If I ever need to, I'll change it at that time. For now, Rustic sees the EOF, and the communication thread sends a Quit to the main engine thread, which makes the engine terminate all of its running threads. This happens so fast that the engine doesn't even come up with a move, but it doesn't hang anymore either.