"Spec" is being far too kind to it. If you want to know what UCI means, you have to look at engines and GUIs. No rigorous definition of the protocol exists. It's even worse than the old winboard specs, and that's saying something.Sven Schüle wrote:I quoted the relevant part of the UCI spec above, read again. If the engine sends a valid command (here "bestmove") but an unknown parameter token (here "(none)" for instance), it should not ignore the whole command but only the unknown token. Ignoring the whole command would contradict to the sentence of the spec I quoted. So "bestmove (none)" can only mean that the engine has fulfilled its duty to reply to "go" but has not made a move (for which the reason is obvious).hgm wrote:It should not ignore it, but it should keep waiting for a valid move token.Sven Schüle wrote:Since the GUI shall ignore all tokens that it does not understand it is supposed to also ignore a token like "(none)". But this does not mean that it shall ignore the whole "bestmove (none)" command.
Sven
UCI nullmove
Moderator: Ras
-
wgarvin
- Posts: 838
- Joined: Thu Jul 05, 2007 5:03 pm
- Location: British Columbia, Canada
Re: UCI nullmove
-
Sven
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: UCI nullmove
Hi Marco,mcostalba wrote:Ok, let's do the last attempt to discuss on topic.hgm wrote:What is amazing is that you let your engine do something completly unique, where other engines do something completely different, and then insist that this is preferable over every engine doing the same thing rooted in the protocol specs.Discussing about that is indeed a waste of time. Like discussing why the sky is green is a waste of time...
Please state clearly, without comments / opinions, what SF does differently from other engines and what should do.
As a hint for yourself please remember that a null move (coded as "0000") is _not_ MOVE_NONE, in particularity, if there are no legal moves it is not correct to send
"bestmove 0000"
it is incorrect as would be to send "bestmove a2a4" or anything else. A null move it means to give the possibility to the other color to move instead of you, it means to pass the move so it has _nothing_ to do with the following facts:
- Communicate to the GUI that there are no legal moves available
- Communicate to the GUI that we have crossed the 50 rule threshold
- Communicate to the GUI that we have done a 3-fold repetition
- Add here your special meaning motivated by the infamous (and deadly broken) "because I don't see what else could be" way of reasoning.
let me state at this point that I do neither fully agree to your viewpoint, nor to that of HGM. I believe that both "bestmove 0000" and "bestmove (none)" are acceptable reactions of the engine, for the following reasons:
1) I agree that the null move cannot be played in a game by an engine. I also understand the difference between "null move" and MOVE_NONE.
2) As I wrote in another post in this thread a few minutes ago, I believe that sending "bestmove (none)" is correct in the sense that it must cause the GUI to recognize that the engine has finished its search but does not make a move.
3) The UCI spec remains very silent about the expected scenario in end-of-game positions. For me this is simply caused by the minimalistic approach of the whole spec. The bottom line is like "everything is forbidden that is not explicitly allowed, and all that is forbidden shall be ignored". That means, if you say "bestmove 0000" is illegal then the (well-defined!) reaction of an UCI-compliant GUI is to ignore the "0000" token, as in the "(none)" case, and recognize that the engine has not sent a best move to be played. If I say "bestmove 0000" is ok to send then the reaction of the GUI is basically the same: the engine does not send a best move.
Now you will say: the GUI must not accept "bestmove 0000" as a synonym for MOVE_NONE. But why shouldn't it? The UCI spec does not define the end-of-game scenario at all, not with any single word, so why should "bestmove 0000" have "more faulty" semantics compared to "bestmove (none)"? A spec which does not specify a scenario at all can't reject a specific message that occurs within that scenario as "illegal". It can only do what it already does: say that everything that is "unknown" shall be ignored.
I agree, though, that you regard "bestmove 0000" as "not acceptable" on an aesthetical level, since you don't want your engine to send something that anybody could interpret as an illegal move. That is enough justification to prefer sending an "unknown" token as parameter for "bestmove". But on the level of deciding what has to happen according to the UCI spec, for me it does not justify to formally reject the "bestmove 0000" simply since the outcome is the same.
Sven
-
Sven
- Posts: 4052
- Joined: Thu May 15, 2008 9:57 pm
- Location: Berlin, Germany
- Full name: Sven Schüle
Re: UCI nullmove
Well, you would surely be right when stating that some special parts are left ambiguous. But I would not agree upon a statement that "no rigorous definition of the protocol exists". Personally I like the WB protocol a lot more (that's why I always used WB in my engines) but nevertheless I can cope with the existing UCI protocol spec as a technical document that does not show a lack of "rigorous definition". UCI specifies what is allowed, and that everything else is not allowed, and that all that is not allowed shall be ignored, resp. handled consistently. That is one way of specifying, and it is not the worst, since the opposite, specifying all and everything in every detail, can be a lot worse, and can trigger writing a never ending story.wgarvin wrote:"Spec" is being far too kind to it. If you want to know what UCI means, you have to look at engines and GUIs. No rigorous definition of the protocol exists. It's even worse than the old winboard specs, and that's saying something.Sven Schüle wrote:I quoted the relevant part of the UCI spec above, read again. If the engine sends a valid command (here "bestmove") but an unknown parameter token (here "(none)" for instance), it should not ignore the whole command but only the unknown token. Ignoring the whole command would contradict to the sentence of the spec I quoted. So "bestmove (none)" can only mean that the engine has fulfilled its duty to reply to "go" but has not made a move (for which the reason is obvious).hgm wrote:It should not ignore it, but it should keep waiting for a valid move token.Sven Schüle wrote:Since the GUI shall ignore all tokens that it does not understand it is supposed to also ignore a token like "(none)". But this does not mean that it shall ignore the whole "bestmove (none)" command.
Sven
I do not share your view that "If you want to know what UCI means, you have to look at engines and GUIs.".
Sven
-
mcostalba
- Posts: 2684
- Joined: Sat Jun 14, 2008 9:17 pm
Re: UCI nullmove
Hi Sven,Sven Schüle wrote: Now you will say: the GUI must not accept "bestmove 0000" as a synonym for MOVE_NONE. But why shouldn't it? The UCI spec does not define the end-of-game scenario at all, not with any single word, so why should "bestmove 0000" have "more faulty" semantics compared to "bestmove (none)"? A spec which does not specify a scenario at all can't reject a specific message that occurs within that scenario as "illegal". It can only do what it already does: say that everything that is "unknown" shall be ignored.
I understand your point and I think you are right saying that the effect of sending "bestmove 0000" to the GUI in case of a mate position is the same of sending "bestmove (none)". Because the GUI discards and ignores the move anyhow. Extending your reasoning we could also say that in mate position the engine can send also "bestmove a2a4" or "bestmove d2d8" and the effect is the same.
But nevertheless although the final effect is the same I think is more appropriate to _not_ send a random move (also 0000 is a move) that, given the current position, turns out to be illegal and so discarded. I think is more appropriate to send something that could not be interpreted as a move and so is discarded early on, on a pure semantic level, without requiring a validation against the current position's state.
The reason why I prefer to explicitly state that no move is possible through the use of a string like, for instance, "bestmove (none)" is because it is more clear and less ambiguous especially in the eye of the casual reader. If you read the posts of this thread you can easily spot how "bestmove 0000" could lead to misunderstandings on _why_ the GUI reacts in the correct way (but for the wrong reason) and for many people it is difficult to grasp the difference between a pseudolegal move that turns out to be illegal and a string that is not a pseudolegal move like "(none)", and they incorrectly conclude that "bestmove 0000" is the _correct_ way for the engine to answerer the GUI in case of stalemate.
-
hgm
- Posts: 28440
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: UCI nullmove
This "can only mean" is entirely your conclusion, but in fact not what the specs you quoted say. If the (non) is an invalid token that should beignored, it means the engine should treatSven Schüle wrote:So "bestmove (none)" can only mean that the engine has fulfilled its duty to reply to "go" but has not made a move (for which the reason is obvious).
bestmove (none)
e2e4
as if it received
bestmove
e2e4
After that the linefeed is an invalid token, and thus be ignored. That reduces the input to
bestmove e2e4
which is valid. So a parser should wait for the next line of input to see if there is a valid move on it, because that will be the move it should process. In practice, this next line will of course never come...
-
mcostalba
- Posts: 2684
- Joined: Sat Jun 14, 2008 9:17 pm
Re: UCI nullmove
NO !hgm wrote: which is valid. So a parser should wait for the next line of input to see if there is a valid move on it, because that will be the move it should process. In practice, this next line will of course never come...
Please read better the specs:
Code: Select all
* all command strings the engine receives will end with '\n',
also all commands the GUI receives should end with '\n'
Code: Select all
bestmove (none)
e2e4
Code: Select all
bestmove (none) '\n' --> bestmove --> command received with missing argument, do nothing.
e2e4 '\n' --> unknown command, do nothing.
-
hgm
- Posts: 28440
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: UCI nullmove
OK, Fact: MOVE_NONE is not mentioned in the UCI specs, it is an internal Stockfish macromcostalba wrote:Ok, let's do the last attempt to discuss on topic.
Please state clearly, without comments / opinions, what SF does differently from other engines and what should do.
As a hint for yourself please remember that a null move (coded as "0000") is _not_ MOVE_NONE,
Fact: in general two solutions are not automatically equally bad just because they are both incorrect.in particularity, if there are no legal moves it is not correct to send
"bestmove 0000"
it is incorrect as would be to send "bestmove a2a4" or anything else.
Fact: The UCI specs say an engine can send 0000 for a move, or long algebraic, and "(none)" is neither of those.
That does seem like like a lot of opinions to me. For one, where in the UCI specs does it exactly say what a null move means?A null move it means to give the possibility to the other color to move instead of you, it means to pass the move so it has _nothing_ to do with the following facts:
- Communicate to the GUI that there are no legal moves available
- Communicate to the GUI that we have crossed the 50 rule threshold
- Communicate to the GUI that we have done a 3-fold repetition
- Add here your special meaning motivated by the infamous (and deadly broken) "because I don't see what else could be" way of reasoning.
This seems a hard fact, though:
If I play an illegal move, one does not have to draw on any specs to conclude that I did not play a legal move, right?
It seems to me your line of reasoning only serves to argue that UCI is broken, and in addition to 0000 would have needed pseudo-moves for resign, (did youk now there are engines that actually print "bestmove resign"?), draw claim, draw offer etc. But unfortunately there aren't in theofficial specs, and we either have to extend the protocol, or live with it.
Extending the protocol in an "everyone for himself" way, like using "(none)" for a move, seems the worst possible way to do it. Especially since extension would be possible by merely extending the interpretation of existing symbols, which were not really well-definedin the first place. Sending illegal movesis not against UCI specs, right?
-
mcostalba
- Posts: 2684
- Joined: Sat Jun 14, 2008 9:17 pm
Re: UCI nullmove
"extending the interpretation of existing symbols" is a dangerous practice and I am against it. For me one symbol should mean one thing. Period.hgm wrote: Especially since extension would be possible by merely extending the interpretation of existing symbols, which were not really well-definedin the first place.
If you extend "0000" meaning to include more than just null move (and we have a clear idea of what a null move is), and you pretend "0000" is sent by the engine to inform the GUI about other facts you open the door to possible ambiguities in which, for instance, the GUI, upon receiving "bestmove 0000" could wonder how that symbol should be interpreted and we cannot a priori demonstrate that do not exists a position / game state in which a "bestmove 0000" string could be legally interpreted in more than one way. And this would mean that the protocol is broken.
-
hgm
- Posts: 28440
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: UCI nullmove
Well, I don't think it is a great revelation that UCI protocol is badly broken, and in fact it is mystery to me why any one would want to use it.
So we are reduced to choosing the lesser evil of available options.
I fully agree that life would be better if UCI were extended to define new keywords through which engines could resign, claim draws, complain about illegal moves. (What does Stockfish do when you feed it a string of moves containing illegal ones, and you send it a go command, btw? Glaurung 2.2 simply hung in that position, which does not seem an optimal response. When I fed Stockfish the position 1q1qk1q1/pppppppp/8/8/8/8/PPPPPPPP/NNNNKNNN w - - 0 1 it plays without complaint, but seemed to ignore the presence of some of the pieces. This also seems quite bad behavior. I understand of course that the internal workings of an engine can make it impossible to handle every position expressible as FEN, but refusing to play any moves from positions itcannot handle would seem much more useful to the user than pretending it is an arbitrary other position that it can handle.)
But unfortunately UCI does not supply such keywords.
Overloading existing keywords could in theory have all the disadvantages you mention. But in an actual case one can take proper care to avoid that. In particular, "0000" in chess is always an illegal move, so used in the context "bestmove 0000" has little danger to be confused with a situation where the engine actually wants to play that move, and continue the game like nothing special happened. (In games like Go and Reversi this would not work, but long-algebraic would also not be suitable for move encoding, so it is clear that UCI cannot be used for these games without alteration.) So it must mean something else. And it can be unambiguously defined what it would mean, depending on other available info. For instane, in combination with a checkmated score it could be unambiguously defined to mean the engine recognizes it is checkmated, and in combination with a null score it can be defined to be a draw claim.
But in any case a solution overloading existing symbols is of much more practical value as the chaos that will result when everyone starts making up his own keywords, shared by no one. IIRC Fruit prints "bestmove (null)", other engines print "bestmove resign", and there are zillions of other possibilities.
I think there is a basic misunderstanding here of what a protocol is. A protocol is like a language, and the specs are its dictionary and grammar. But a dictionary doesn't specify what you can say. That is semantics,and up to the creativity of the writer. The dictionary ustspecifies what you can use. With a little creativity (although that might overrate it; "common sense" would be a better term) the dictionary of UCI can be used to exactly express what you need. So why not do it, but resort to gobbledeekook in stead?
I fully agree that life would be better if UCI were extended to define new keywords through which engines could resign, claim draws, complain about illegal moves. (What does Stockfish do when you feed it a string of moves containing illegal ones, and you send it a go command, btw? Glaurung 2.2 simply hung in that position, which does not seem an optimal response. When I fed Stockfish the position 1q1qk1q1/pppppppp/8/8/8/8/PPPPPPPP/NNNNKNNN w - - 0 1 it plays without complaint, but seemed to ignore the presence of some of the pieces. This also seems quite bad behavior. I understand of course that the internal workings of an engine can make it impossible to handle every position expressible as FEN, but refusing to play any moves from positions itcannot handle would seem much more useful to the user than pretending it is an arbitrary other position that it can handle.)
But unfortunately UCI does not supply such keywords.
Overloading existing keywords could in theory have all the disadvantages you mention. But in an actual case one can take proper care to avoid that. In particular, "0000" in chess is always an illegal move, so used in the context "bestmove 0000" has little danger to be confused with a situation where the engine actually wants to play that move, and continue the game like nothing special happened. (In games like Go and Reversi this would not work, but long-algebraic would also not be suitable for move encoding, so it is clear that UCI cannot be used for these games without alteration.) So it must mean something else. And it can be unambiguously defined what it would mean, depending on other available info. For instane, in combination with a checkmated score it could be unambiguously defined to mean the engine recognizes it is checkmated, and in combination with a null score it can be defined to be a draw claim.
But in any case a solution overloading existing symbols is of much more practical value as the chaos that will result when everyone starts making up his own keywords, shared by no one. IIRC Fruit prints "bestmove (null)", other engines print "bestmove resign", and there are zillions of other possibilities.
I think there is a basic misunderstanding here of what a protocol is. A protocol is like a language, and the specs are its dictionary and grammar. But a dictionary doesn't specify what you can say. That is semantics,and up to the creativity of the writer. The dictionary ustspecifies what you can use. With a little creativity (although that might overrate it; "common sense" would be a better term) the dictionary of UCI can be used to exactly express what you need. So why not do it, but resort to gobbledeekook in stead?
-
hgm
- Posts: 28440
- Joined: Fri Mar 10, 2006 10:06 am
- Location: Amsterdam
- Full name: H G Muller
Re: UCI nullmove
And this is exactly the point I don't agree on. The rule that tokens that are not expected does not apply here, since 0000 is defined as a valid move token. That it happens to be an illegal move, and that this must have consequences for the engine, is another matter that is entirely without the jurisdiction of the protocol. In general illegal moves should not be ignored. What would you want the GUI to do if it receives "e4e5" in the opening position? Just ignoreit, and wait until the engine sends a legal one, or forfeit it for an illegal move? (Or perhaps reload it with the position and set itthinking again?)Sven Schüle wrote:That means, if you say "bestmove 0000" is illegal then the (well-defined!) reaction of an UCI-compliant GUI is to ignore the "0000" token, as in the "(none)" case, and recognize that the engine has not sent a best move to be played.
I agree that any other illegal move in a position with no legal moves couldserve the purpose, and be interpreted in the same way. But it would be really stupid to base a standard message on that, because which moves are legaland which not is dependent on the current position, and requires alot of intelligence on the part of the GUI to figure out. While 0000 is by definition always illegal (semantically, not syntactically!).