CECP "time" and "otim"

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

CECP "time" and "otim"

Post by mvanthoor »

The implementation for these two commands is easy in my engine, but it is confusing to what I should be doing exactly. Even the specs say that it is confusing, and then go and contradict themselves, on the GNU site:
time N
Set a clock that always belongs to the engine. N is a number in centiseconds (units of 1/100 second). Even if the engine changes to playing the opposite color, this clock remains with the engine.
otim N

Set a clock that always belongs to the opponent. N is a number in centiseconds (units of 1/100 second). Even if the opponent changes to playing the opposite color, this clock remains with the opponent.

If needed for purposes of board display in force mode (where the engine is not participating in the game) the time clock should be associated with the last color that the engine was set to play, the otim clock with the opposite color.

This business of "clocks remaining with the engine" is apparently so ambiguous that many engines implement it wrong. The clocks in fact always remain with the color. Which clock reading is relayed with "time", and which by "otim", is determined by which side the engine plays. Note that the way the clocks operate and receive extra time (in accordance with the selected time control) is not affected in any way by which moves are made by the engine, which by the opponent, and which were forced.
"Set a clock that always belongs to the engine" would mean that I assign a clock to the engine, and that the engine keeps using that clock, even if it switches colors. That is what it actually says under "time". But then further down, it says: "This business of "clocks remaining with the engine" is apparently so ambiguous that many engines implement it wrong. The clocks in fact always remain with the color..."

That would mean that I assign a clock to a color, and if the engine switches colors, it will thus change to use the other clock.

So what is it; does the assigned clocks stick with the players (engine/opponent), or with the colors?

Also, this feature specifically states that with "times=0" the sending of time and otim can be disabled, and then immediately afterward, it says to never do that. If disabling this should never be done, then why is it possible? (Similar things are also said for other features, such as "always use..."; in that case, why have other options?)
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
mar
Posts: 2559
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: CECP "time" and "otim"

Post by mar »

The way I implement this is that time is engine's time (doesn't matter which color the engine plays) and otim is opponent's time.
If your engine supports playother (protover 2 feature), then you simply swap time and otim and also swap the color the engine plays.
Martin Sedlak
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: CECP "time" and "otim"

Post by hgm »

This is very confusing wording in the original specs, and I remember that when I first implemented CECP in an engine, I did not understand it at all.

What the text tries to explain (with the "stays with the engine") is that he clocks should not be swapped by the engine when a command is received that makes the engine play the opposite color of what it played before. So if the engine is playing for black, and white is to move, and it receives 'time 1000' (meaning that it has 10 sec on its clock), and then receives 'go' to make it think for white, it should assume that white has 10 sec on its clock. While at the time the 'time' command was received, it was still set to playing black, and if it had received a usermove instead of 'go' (so that it became black's turn, and it would have started thinking up a black move, it would have interpreted the 10 sec as the time on black's clock.

The consequence is that 'time' always relays the time on the clock of the color for which the engine is actually going to think next. So that you can send it both before 'usermove' and 'go'.
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: CECP "time" and "otim"

Post by mvanthoor »

Forgot about "playother". I'll still have to look at that.

The next few days I'll be testing with st, sd, and level to see if everything works; then I'll look at time, otim, and playother. (Maybe colors/white/black too? Don't know yet; can't remember on the top of my head if they are still part of protover 2, or if they're obsolete.)
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
mvanthoor
Posts: 1784
Joined: Wed Jul 03, 2019 4:42 pm
Location: Netherlands
Full name: Marcel Vanthoor

Re: CECP "time" and "otim"

Post by mvanthoor »

hgm wrote: Mon Nov 30, 2020 8:06 pm This is very confusing wording in the original specs, and I remember that when I first implemented CECP in an engine, I did not understand it at all.

What the text tries to explain (with the "stays with the engine") is that he clocks should not be swapped by the engine when a command is received that makes the engine play the opposite color of what it played before. So if the engine is playing for black, and white is to move, and it receives 'time 1000' (meaning that it has 10 sec on its clock), and then receives 'go' to make it think for white, it should assume that white has 10 sec on its clock. While at the time the 'time' command was received, it was still set to playing black, and if it had received a usermove instead of 'go' (so that it became black's turn, and it would have started thinking up a black move, it would have interpreted the 10 sec as the time on black's clock.

The consequence is that 'time' always relays the time on the clock of the color for which the engine is actually going to think next. So that you can send it both before 'usermove' and 'go'.
Thanks.

It seems I was correct with regard the implementation I was thinking of. When assigning time, you should NOT be using a "white" or a "black" clock, because then you'll have problems: you won't know if "time X" is for white or black until the next command comes in. Therefore I intended to implement an "engine" clock, and an "opponent" clock, so "time" will always increase the time of the "engine" clock, and "otim" for the "opponent" clock.

If the engine then keeps playing its own color (say it was black and will stay black), then black will have received "time"; but if the next command sets the engine to play for the side it was NOT playing (in this case, white), then white will have received "time".

Thanks for the clarification.

All in all, I can understand why people writing new engines stick with UCI. It's a simpler protocol. Note that I don't say "better", because there are some things XBoard can do that UCI can't... (especially variants), but it -is- more work to implement, and in some places, harder to understand.
Author of Rustic, an engine written in Rust.
Releases | Code | Docs | Progress | CCRL
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: CECP "time" and "otim"

Post by hgm »

mar wrote: Mon Nov 30, 2020 7:53 pm The way I implement this is that time is engine's time (doesn't matter which color the engine plays) and otim is opponent's time.
If your engine supports playother (protover 2 feature), then you simply swap time and otim and also swap the color the engine plays.
I think that is wrong, but as I don't know any interface that supports 'playother', this is probably moot. But 'playother' doesn't toggle the color the engine plays, but makes it play the side that is currently not on move (which could very well be the side it already plays for, and it could play neither side as well). So by definition it cannot set the engine thinking, and a following command that does would normally be preceded by time and otim, so that it doesn't matter what it does to the clocks, really.

It would only be relevant when you want the engine to be able to keep its own time, and run correctly even on interfaces that do not send time and otim. (By modern standards such interfaces should be considered broken!) Then you have to keep track of a white and black clock yourself, and derive the thinking time from those. To integrate that with the use of time/otim, you cannot use those to directly adjust the white and black clocks, as at the time you receive those, it is not decided yet for which color they are. Only when the engine is set thinking by a later command you would have to adjust the clock it will be using with the 'time' value, and the other one with the 'otim' value.

[Edit]@mvanthoor - Our messages crossed, but I think we are saying exactly the same thing. The understanding is really an issue of the specs, I think. If it would have been explaine as
alt specs wrote:Before every command that makes the engine think the GUI will send a 'time' command to say how many centi-seconds the thinking player has left on his clock, and an 'otim' command to say how much the opponent has.
I don't think there would have been any difficulty in that case.
Ras
Posts: 2488
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: CECP "time" and "otim"

Post by Ras »

Did you also implement the "?" command? Since you have implemented UCI, the engine already must have a way to deal with input during search for isready and stop, so the same infrastructure could be used for CECP's "?".
Rasmus Althoff
https://www.ct800.net
mar
Posts: 2559
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: CECP "time" and "otim"

Post by mar »

I think the details are a bit complicated.
I bet on the fact that the GUI won't send some commands when the engine is thinking.
I think that sending playother while the engine is thinking would be silly. The way I handle this is to stop the search and swap sides, assuming
playother typically comes when it's the opponent's turn.

I keep track of both time and otim, even though I only use "time" for time management (an unimportant detail); time will only take effect when the engine is asked to think so it's sort of cached.
I would also consider it silly for the GUI to send time/otim while the engine is actually thinking (I expect no GUI does this actually) - what should be the expected behavior anyway, reallocate time or buffer for later? (I do the latter)

I don't know, I try to support both protocols, even though I recently fixed another bug in my SAN implementation; SAN is probably fine for PV, but not so great for move commands (it's optional in CECP as far as I remember)

I like CECP because it's less verbose, but comes with some intricacies related to implementation details. Also pondering is entirely up to the engine - it's more flexible but also slightly harder to implement.
Martin Sedlak
mar
Posts: 2559
Joined: Fri Nov 26, 2010 2:00 pm
Location: Czech Republic
Full name: Martin Sedlak

Re: CECP "time" and "otim"

Post by mar »

Ras wrote: Mon Nov 30, 2020 8:33 pm Did you also implement the "?" command? Since you have implemented UCI, the engine already must have a way to deal with input during search for isready and stop, so the same infrastructure could be used for CECP's "?".
I don't know if this question was directed at me or Marcel, but I treat "?" as the UCI stop command, except that I ignore it when the engine is currently analysing or pondering.
Martin Sedlak
Ras
Posts: 2488
Joined: Tue Aug 30, 2016 8:19 pm
Full name: Rasmus Althoff

Re: CECP "time" and "otim"

Post by Ras »

mar wrote: Mon Nov 30, 2020 8:48 pmI don't know if this question was directed at me or Marcel, but I treat "?" as the UCI stop command, except that I ignore it when the engine is currently analysing or pondering.
Actually at Marcel, but yeah, makes sense because exiting analysis mode is using another command.
Rasmus Althoff
https://www.ct800.net