UCI's readyok: A mistake or a misunderstanding

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: UCI's readyok: A mistake or a misunderstanding

Post by mvanthoor »

CMCanavessi wrote: Sat Jul 31, 2021 4:27 am I agree that the wording is completely contradictory.
How I understand (or how I would use it) is in your #1 way when the engine is initializing (reading TBs, making the Hash, etc), which completely blocks the engine from doing any other thing wether you want it or not, and which by today's standards it's almost instant anyways (or pretty fast).
And then, when all that is already set up and the match has already begun and the search is going on, as #2: reply instantly if receiving isready, as it may be used as some sort of ping (like in Banksia's case).
That is my view as well. If you're not searching, you can be "not ready", because you're loading EGTB's or a massive opening book.

The UCI spec says that the engine should not initialize anything, to make the engine start as quickly as possible. That would mean you should initialize when receiving either "uci" or "ucinewgame", and at that point you can be not ready. When searching, the engine should always be "ready"; either to give a best move, to stop, to quit, etcetera.

So while it is somewhat confusing, I don't think the wording is contradictory.

PS: I ignore the UCI spec with regard to initialization. I initialize everything when the engine starts, and I wrote "go" to assume "go infinite" except if a different search type (node, depth, time, etc....) is encountered. The reason is that I often want to quickly try an analysis by the engine in a position, so I can just do:

Code: Select all

./rustic -f "<fen_string>" -h <tt_size> -q
(-q leaves out intermediate search updates; it only prints the search information at the end of each depth iteration.)

As soon as the engine starts, I can type "go" (enter) and be done with it, without having to go through the "uci", "ucinewgame" and "isready" (let alone "position") stuff. When the engine starts, it is already in the state as if uci, ucinewgame, positon, and isready have been sent, processed, and answered. (When these commands are received though, the engine responds appropriately.) And, the engine is always "ready", except during startup.

The only thing I don't take into account at this point is when you do something that takes a massive amount of time, such as resizing to a 32 GB TT, and then immeidately sending a "search" command. The I/O-thread is separate and independent from the engine thread, and the I/O thread doesn't check if the engine is actually ready. Thus if you make the engine do something that really DOES take a huge amount of time and then make it search, it'll possibly break.

I'll have to test it to make sure, and some day I'll probably address it, but I haven't Rustic ever crash in actual use.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL