Code complexity, yes, but not needless. Since race conditions are nasty to debug, and their absence cannot be proven through testing, I prefer a design that will never lose messages simply because it doesn't discard any to begin with. Even if it's not strictly in line with the protocol definition, as long as it doesn't introduce new problems at functional level.
Formalizing the Universal Chess Interface
Moderator: Ras
-
- Posts: 2696
- Joined: Tue Aug 30, 2016 8:19 pm
- Full name: Rasmus Althoff
Re: Formalizing the Universal Chess Interface
Rasmus Althoff
https://www.ct800.net
https://www.ct800.net
-
- Posts: 60
- Joined: Sat Dec 11, 2021 5:03 am
- Full name: expositor
Re: Formalizing the Universal Chess Interface
Chess programming is a hobby – everything we do here is completely pointless.Well, then it is a completely pointless exercise.
That said, I'm not sure what your purpose is in belittling a project that I find interesting.
We'll find out!People are not going to abandon UCI for any new protocol you invent. Not in a million years.
I'll take that as a yes for the question Should this formalization of UCI be given [its own] name? listed under the Outstanding Issues question. I have no intention or desire to mislead anyone.If you try to present this as UCI, and thereby mislead engine authors into thinking they can follow your specs to make their engine interoperable with true UCI software, you should not be surprised if others (and I in particular) will warn them against such practice.
I'm a little surprised at the negativity of the reception and the readiness to promise to be my opponent.
———
That's fair! Any refinement of UCI is not particularly useful for those who already have their engine working with the clients they care about.1. One of the strong points of UCI is that it isn't amended all the time, resulting in a stable ecosystem instead of fragmentation. UCI engines simply tend to work. I don't see the need for a mostly identical but slightly incompatible UCI version.
If it's not helpful, feel free to ignore the state diagram! I was very, very careful to restrict the specification to governing only the messages that the client and engine send to each other. Anything have to do with meaning or semantics or the internal operation of clients and engines is given as a recommendation within a comment (light grey text) and is not part of the specification proper.2. I don't like the state diagrams. That's a possible the implementation of a protocol - the protocol definition should not be concerned with implementation. It's only relevant what goes back and forth "on the line".
If you can put on a finger on why, that would help me know how I can improve the draft.3. I find the original spec easier to understand.
Yes! agreed. Both of these are included in the draft.4. What would be good would be the old spec, just with some more clarifying comments on frequently asked questions and hints for how the ecosystem has developed in reality. For example, most UCI engines including Shredder cannot deal with parameters after searchmoves in go if searchmoves isn't the last parameter. Similarly, the PV should probably be the last part of the info message during search. Everyone does it that way already, but that should be documented.
-
- Posts: 2696
- Joined: Tue Aug 30, 2016 8:19 pm
- Full name: Rasmus Althoff
Re: Formalizing the Universal Chess Interface
It's not useful for client authors, either, because what engines would they target with a slightly incompatible protocol? And for new engine authors, which clients would they target? In both cases: there are none, and I don't see any disruptive feature with any hope to beat that network effect. On top of that, the success of a protocol is rarely determined by what exactly goes over the line, and much more by the ecosystem.
The CECP ecosystem serves as cautionary tale here. The protocol got amended with tons of new features in theory, but the actual support was spotty at best in the wild. The result is that you can rely only on the basic features that have always been there, and even then.
With UCI, it's not perfect, but the strongest point is that it doesn't get amended - which is a point you'd destroy with a slightly incompatible version. That is, if that got any traction, which it will not.
Then it is bloat that shouldn't even be there.If it's not helpful, feel free to ignore the state diagram!
Too much bloat. The original spec just goes to the meat. You could ofc have formalisation stuff that nobody cares about, but then just tuck it away in some appendix that is not meant to even being read. Or even better, cut it out.If you can put on a finger on why, that would help me know how I can improve the draft.
My suggestion: stay in line with what UCI already is, avoid the https://xkcd.com/927/ trap, just concentrate on clarifying ambigous parts and document common interpretations such as searchmoves / pv order. That would have value. "Improving" the protocol while still calling it "UCI" has no value. Whatever you think would be "nicer" to have over the line has no value compared to the value of the existing ecosystem. That's the harsh reality.
Rasmus Althoff
https://www.ct800.net
https://www.ct800.net
-
- Posts: 60
- Joined: Sat Dec 11, 2021 5:03 am
- Full name: expositor
Re: Formalizing the Universal Chess Interface
I am fairly certain that, given the current draft, a conforming client would work with most (if not all) legacy engines.It's not useful for client authors, either, because what engines would they target with a slightly incompatible protocol?
The goal of the endeavour is to provide a guarantee: if your engine conforms to the formal UCI specification (or whatever it'd be called), then it is guaranteed that your engine will work with any conforming client.I don't see any disruptive feature with any hope to beat that network effect.
No such guarantee exists currently. Every time I've used a different client, a new edge case has caused problems, and I'm not the only one this has happened to. And there's no way to know whether your engine implements UCI correctly, but my hope is to provide a set of conformance tests that will diagnose any issues. To write tests, you first need a specification.
I meant if it's not helpful to you, feel free to ignore the state diagram. I happen to find it quite helpful ^_^Then it is bloat that shouldn't even be there.
But I can omit it from future drafts.
I don't understand how it would qualify as a specification, then, rather than an informal tutorial or "getting started" guide.Too much bloat. The original spec just goes to the meat. You could ofc have formalisation stuff that nobody cares about, but then just tuck it away in some appendix that is not meant to even being read. Or even better, cut it out.
An analogy: many people believe that C is a simple language, but it isn't at all – this is what's needed to define C, and this is what compilers implement. It's been my experience that people who don't consult documentation* write programs riddled with undefined behavior, and this has caused some nasty bugs. Anyway, although C is usually straightforward, there are tricky edge cases, and having an exhaustive resource is handy. I thought UCI could use something similar, because it doesn't answer questions like these:
- If an engine sends a bestmove message with a bad value, does it have to send another bestmove message to indicate that it's done searching? Is it allowed to send another bestmove message? Or should the client simply kill the engine for sending a bad message?
- How large can numeric arguments be? When can they be positive, negative, or zero?
- When more than one of "movetime", "depth", and "nodes" are given in a single go command, do all quantities need to be met for the engine to halt, or should the engine halt as soon as any of the quantities are met? Is the client even allowed to send more than one?
*My favorite resource is https://en.cppreference.com, which is excellent! and which I'd highly recommend.
You've just described my goal! The list of differences is on page 15, under Revision Notes. There are only three notable differences:My suggestion: stay in line with what UCI already is, avoid the https://xkcd.com/927/ trap, just concentrate on clarifying ambigous parts and document common interpretations such as searchmoves / pv order. That would have value.
- the engine may send a bestmove message during an infinite search (so that it can communicate, when it has reached its depth limit, that it will make no further progress)
- the client is not required to send a position before sending go – the engine assumes the last given position, or the starting position if no position has been given (this matches the behavior of Stockfish and countless other engines)
- when the client sends a stop message it must wait for a bestmove message before preceding (given feedback I've received, I think this will be changed in the next draft)
-
- Posts: 253
- Joined: Mon Aug 26, 2019 4:34 pm
- Location: Clearwater, Florida USA
- Full name: JoAnn Peeler
Re: Formalizing the Universal Chess Interface
As it exists there is no way to look at the specification and know whether an engine/client is conforming. I think the idea to tighten up the spec so there is no ambiguity is a worthy goal.expositor wrote: ↑Sat Dec 31, 2022 1:45 amThe goal of the endeavour is to provide a guarantee: if your engine conforms to the formal UCI specification (or whatever it'd be called), then it is guaranteed that your engine will work with any conforming client.I don't see any disruptive feature with any hope to beat that network effect.
Please leave it in. If you need a TLDR section, then provide that as an opening section.
Maybe less words and more charts and diagrams. Perhaps a fully exploded grammar for the commands/responses would be nice as well. BNF would work well there.
-
- Posts: 127
- Joined: Sat Jul 30, 2022 12:12 pm
- Full name: Jamie Whiting
Re: Formalizing the Universal Chess Interface
Any chance you could detail some specific examples? I think aside from the ongoing debate about this project it would be quite nice to compile a list of common problems/edge cases for beginners. One I remember distinctly was being unsure whether to use an ‘n’ or ‘k’ for knight promotions (which you have explicitly stated in your spec, thanks).
-
- Posts: 29
- Joined: Thu Jun 09, 2022 5:09 am
- Full name: Clayton Ramsey
Re: Formalizing the Universal Chess Interface
Hey, I just wanted to chime in and say thank you for making this!
Writing the UCI part of a chess engine was by far the most inconvenient step of the process, since it revolved around trying to divine the "true" meaning of the original UCI write-up. This would have been a big help for me about a year ago.
Writing the UCI part of a chess engine was by far the most inconvenient step of the process, since it revolved around trying to divine the "true" meaning of the original UCI write-up. This would have been a big help for me about a year ago.
-
- Posts: 396
- Joined: Fri Aug 12, 2016 8:43 pm
Re: Formalizing the Universal Chess Interface
Honestly, I didn't find it very formal.
Compared for example with the definition of something more complex, like HTTP:
https://datatracker.ietf.org/doc/html/rfc1945
If the engine sends an illegal move maybe it will lose the game. Or maybe the current position will be sent again with the updated time. Or maybe something else. It depends on the circumstances and there is no right behavior that needs to be specified.
The engine should just stop thinking when it reaches the first limit.
Let's recap it simply.
The engine enters "search mode" after receiving "go" and return to "wait mode" just before sending "bestmove".
In "search mode" the direction of communication is reversed. The engine repeatedly sends "info messages" and the client is only allowed to send "stop" to ask the engine to return to "wait mode".
The "go" message have diffent options with default values:
enter "search mode", search at most to depth 30 or for 20 seconds, stay in "search mode" and send "best move" only after receiving "stop".
Compared for example with the definition of something more complex, like HTTP:
https://datatracker.ietf.org/doc/html/rfc1945
This is like asking why the HTTP protocol does not define what to do if threre are grammatical errors in a web page. Should the browser fix it? Should the server send another response?expositor wrote: ↑Sat Dec 31, 2022 1:45 am I thought UCI could use something similar, because it doesn't answer questions like these:
- If an engine sends a bestmove message with a bad value, does it have to send another bestmove message to indicate that it's done searching? Is it allowed to send another bestmove message? Or should the client simply kill the engine for sending a bad message?
- How large can numeric arguments be? When can they be positive, negative, or zero?
- When more than one of "movetime", "depth", and "nodes" are given in a single go command, do all quantities need to be met for the engine to halt, or should the engine halt as soon as any of the quantities are met? Is the client even allowed to send more than one?
If the engine sends an illegal move maybe it will lose the game. Or maybe the current position will be sent again with the updated time. Or maybe something else. It depends on the circumstances and there is no right behavior that needs to be specified.
It is impossible to guarantee that all limits are met, a fast computer may reach the desired depth in less than movetime. A slower one maybe not.expositor wrote: ↑Sat Dec 31, 2022 1:45 am
- When more than one of "movetime", "depth", and "nodes" are given in a single go command, do all quantities need to be met for the engine to halt, or should the engine halt as soon as any of the quantities are met? Is the client even allowed to send more than one?
The engine should just stop thinking when it reaches the first limit.
Let's recap it simply.
The engine enters "search mode" after receiving "go" and return to "wait mode" just before sending "bestmove".
In "search mode" the direction of communication is reversed. The engine repeatedly sends "info messages" and the client is only allowed to send "stop" to ask the engine to return to "wait mode".
Code: Select all
--> go
<-- info
<-- info
....
[--> stop]
[<-- info]
<-- bestmove
- searchmoves: default is all the moves
- ponder: false
- wtime/btime: infinite
- winc/binc: 0
- movestogo: 0
- depth: infinite
- nodes: infinite
- movetime: infinite
- infinite: false [this should have been called auto_exit_search_mode]
enter "search mode", search at most to depth 30 or for 20 seconds, stay in "search mode" and send "best move" only after receiving "stop".
-
- Posts: 28353
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Formalizing the Universal Chess Interface
This is not a matter of protocol, but of client design. Full covarage of error handling is a logical impossibility for any protocol: by prescribing what to do in case of 'error' you in fact extended the protocol with new rules, and these rules could be violated too in new ways.expositor wrote: ↑Sat Dec 31, 2022 1:45 amIf an engine sends a bestmove message with a bad value, does it have to send another bestmove message to indicate that it's done searching? Is it allowed to send another bestmove message? Or should the client simply kill the engine for sending a bad message?
Engines should not send invalid commands, period. If they do, they are not complient, and they are completely at the mercy of the client. If they receive invalid commands, they can also do whatever they feel would be appropriate. Non-complient clients do not qualify for any mercy either.
You missed the point. The recommendation was that there should not be any difference. Just clarification and recommendations.You've just described my goal! The list of differences is on page 15, under Revision Notes. There are only three notable differences:
- the engine may send a bestmove message during an infinite search (so that it can communicate, when it has reached its depth limit, that it will make no further progress)
- the client is not required to send a position before sending go – the engine assumes the last given position, or the starting position if no position has been given (this matches the behavior of Stockfish and countless other engines)
- when the client sends a stop message it must wait for a bestmove message before preceding (given feedback I've received, I think this will be changed in the next draft)
That doesn't exclude that what you propose would make a better protocol. As far as I am concerned almost anything would be better than UCI. But designing new protocols is something completely different from improving the specification of an existing one. Just call it NCI for New Chess Interface, and you would not hear any objections from me.
-
- Posts: 28353
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: Formalizing the Universal Chess Interface
There is a problem with that definition, because it delimits the "search mode" (which the specs call "calculating") by communication events in opposit directions. This can lead to race conditions. A specification that would cover existing practice would say:Fulvio wrote: ↑Sat Dec 31, 2022 8:00 amLet's recap it simply.
The engine enters "search mode" after receiving "go" and return to "wait mode" just before sending "bestmove".
In "search mode" the direction of communication is reversed. The engine repeatedly sends "info messages" and the client is only allowed to send "stop" to ask the engine to return to "wait mode".Code: Select all
--> go <-- info <-- info .... [--> stop] [<-- info] <-- bestmove
And as for stating the obvious:A 'go' command will bring the engine in the "calculating" state, during which it is not allowed to send it any other commands than 'stop', 'ponderhit', 'debug' and 'isready' (and 'quit'?). This limitation lasts until the 'stop' command or the 'bestmove' command (whichever comes earlier).
An engine should execute allowed commands in the order it receives those. It should not start executing a command before execution of all previous commands has been completed, but should never delay execution any further than that. Commands that are not allowed when their turn for execution comes up should be ignored. Each of the other commands should be executed as per their specification. It is not allowed to ignore commands just because the engine feels their purpose has already been accomplished.
A 'go' command is considered executed as soon as the engine has started up calculation of the new move. Processing of subsequent commands must start immediately after that, and not wait for this calculation to finish. A 'stop' command is considered executed when the engine would be ready to initiate calculation of a new move.