Handling xboard new game race condition in protover 1 engine

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Handling xboard new game race condition in protover 1 engine

Post by matthewlai »

Hello!

Just wondering if anyone knows how xboard handles the new game race condition in "protover 1" engines?

Specifically, when an engine's opponent resigns for example, the GUI would send "result" to both engines, and then set up engines for a new game... and then the engine that didn't resign would output a move from the previous game, before processing the new command.

If the move is illegal on new board that can be ignored, but there's a chance that the move will happen to be legal on the new board, and the engine may happen to be playing white the next game. That would be very bad.

On "protover 2" engines this can be solved using ping, but what about "protover 1" engines, and "protover 2" engines that don't support ping?

Thanks
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
User avatar
hgm
Posts: 27790
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Handling xboard new game race condition in protover 1 en

Post by hgm »

It doesn't. This is why protover 2 / ping was invented.

The move from the previous game will be taken as a move for the new game, which usually leads to an immediate forfeit. If it happens to be legal in the opening position, the true move will be ignored by XBoard as an out-of-turn move, and as it usually will be a different on this will cause a discrepancy between XBoard's idea of the position and the engine's, leading to an illegal move later.

The only remedy is to specify a pause between games long enough that the engine would typically have moved before the new game starts.
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: Handling xboard new game race condition in protover 1 en

Post by matthewlai »

hgm wrote:It doesn't. This is why protover 2 / ping was invented.

The move from the previous game will be taken as a move for the new game, which usually leads to an immediate forfeit. If it happens to be legal in the opening position, the true move will be ignored by XBoard as an out-of-turn move, and as it usually will be a different on this will cause a discrepancy between XBoard's idea of the position and the engine's, leading to an illegal move later.

The only remedy is to specify a pause between games long enough that the engine would typically have moved before the new game starts.
Aah I see. That is unfortunate :(. Was hoping there would be a workaround or something.
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: Handling xboard new game race condition in protover 1 en

Post by matthewlai »

Looks like some old engines will actually respond to "ping" with "Illegal move: ping 3".

I guess that would work as an engine-specific workaround (to just look for "ping x" in any error message sent back).

This is the case with Phalanx.
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
User avatar
hgm
Posts: 27790
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Handling xboard new game race condition in protover 1 en

Post by hgm »

There is a general work-around option in XBoard to make it believe the engine has features that it doesn't:

-firstFeatures "ping=1 setboard=1"

would make XBoard believe the engine supports ping and setboard. (This is processed after the engine has sent feature done=1 or the features timeout, so it would overrule whatever the engine really said, in case these were duplicats.) This way you can force XBoard to send ping even to v1 engines.

Of course this will thouroughly wreck things if the engine does not reply with 'pong'. But perhaps InBetween can be used to substitute pong for the engine's error response to 'ping' (whether it considers it an Illegal move or an Unknown command). But this would only work if the error-response preserves the number. E.g. in the Phalanx case you could have InBetween replace 'Illegal move: ping' by 'pong' in the engine->GUI channel.
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: Handling xboard new game race condition in protover 1 en

Post by matthewlai »

hgm wrote:There is a general work-around option in XBoard to make it believe the engine has features that it doesn't:

-firstFeatures "ping=1 setboard=1"

would make XBoard believe the engine supports ping and setboard. (This is processed after the engine has send feature done=1 or the features timeout, so it would overrule whatever the engine really said, in case these were duplicats.) This way you can force XBoard to send ping even to v1 engines.

Of course this will thouroughly wreck things if the engine does not reply with 'pong'. But perhaps InBetween can be used to substitute pong for the engine's error response to 'ping' (whether it considers it an Illegal move or an Unknown command). But this would only work if the error-response preserves the number. E.g. in the Phalanx case you could have InBetween replace 'Illegal move: ping' by 'pong' in the engine->GUI channel.
Ah I see. That makes sense.

I am actually developing my own thing that matches chess engines since I can't have any UI library dependency (http://talkchess.com/forum/viewtopic.php?t=53254).

Since my "GUI" only ever has 1 ping outstanding at a time, when I send a ping, I basically just keep discarding engine output until I see something coming back with either "ping" or "pong". Haven't tried it with other engines, yet, but works with Phalanx.
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
User avatar
hgm
Posts: 27790
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Handling xboard new game race condition in protover 1 en

Post by hgm »

How do you solve the problem of multiple input sources and timer events? Create a separate input thread for every engine, and let it do blocking input? And use SIGALRM to set up the next timer event?

If you have solved these problems, it might be easier to just hack the GUI-dependence out of XBoard. By making all non-static routines in gtk/xoptions.c into dummies (and deleting the static ones). Basically you would only have to provide a new routines AddInputSource and RemoveInputSource, and rewite the timer handling in gtk/xtimer.c. And delete all the gtk-referring code out of gtk/xboard.c.

The timer handling seems the most tricky, as there can be several timeouts pending simultaneously in XBoard. (A dedicated one for making the clock tick, and a general one for all other events.)
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: Handling xboard new game race condition in protover 1 en

Post by matthewlai »

hgm wrote:How do you solve the problem of multiple input sources and timer events? Create a separate input thread for every engine, and let it do blocking input? And use SIGALRM to set up the next timer event?

If you have solved these problems, it might be easier to just hack the GUI-dependence out of XBoard. By making all non-static routines in gtk/xoptions.c into dummies (and deleting the static ones). Basically you would only have to provide a new routines AddInputSource and RemoveInputSource, and rewite the timer handling in gtk/xtimer.c. And delete all the gtk-referring code out of gtk/xboard.c.

The timer handling seems the most tricky, as there can be several timeouts pending simultaneously in XBoard. (A dedicated one for making the clock tick, and a general one for all other events.)
For multiple input sources I am using select(). It's easier for me because I don't need to support Windows.

I am doing select() with timeouts, and check the clocks at each timeout.

I think the main difference is that I am not making it event driven. So my main loop looks like this (pseudo code) -

Code: Select all

while (game_still_ongoing)
{
	select(both_engine’s_input, timeout = 100ms);

	// these are asynchronous - they will only process what’s available already
	// in the pipes, and not block
	engine1.process_pending_inputs();
	engine2.process_pending_inputs();

	if (either_engine_made_a_move_or_made_draw_offer)
	{
		pass_it_on_to_the_other_engine();
	}

	check_clocks();
}
It's very different from how xboard is organized (since xboard is event driven and need to handle user input).
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Handling xboard new game race condition in protover 1 en

Post by bob »

matthewlai wrote:
hgm wrote:How do you solve the problem of multiple input sources and timer events? Create a separate input thread for every engine, and let it do blocking input? And use SIGALRM to set up the next timer event?

If you have solved these problems, it might be easier to just hack the GUI-dependence out of XBoard. By making all non-static routines in gtk/xoptions.c into dummies (and deleting the static ones). Basically you would only have to provide a new routines AddInputSource and RemoveInputSource, and rewite the timer handling in gtk/xtimer.c. And delete all the gtk-referring code out of gtk/xboard.c.

The timer handling seems the most tricky, as there can be several timeouts pending simultaneously in XBoard. (A dedicated one for making the clock tick, and a general one for all other events.)
For multiple input sources I am using select(). It's easier for me because I don't need to support Windows.

I am doing select() with timeouts, and check the clocks at each timeout.

I think the main difference is that I am not making it event driven. So my main loop looks like this (pseudo code) -

Code: Select all

while (game_still_ongoing)
{
	select(both_engine’s_input, timeout = 100ms);

	// these are asynchronous - they will only process what’s available already
	// in the pipes, and not block
	engine1.process_pending_inputs();
	engine2.process_pending_inputs();

	if (either_engine_made_a_move_or_made_draw_offer)
	{
		pass_it_on_to_the_other_engine();
	}

	check_clocks();
}
It's very different from how xboard is organized (since xboard is event driven and need to handle user input).
One other note. I decided to give up on passing draw offers between programs. Too many do it wrong, so I just gave up. My referee ends a game when a draw state is seen (50 moves, 3-fold rep, stalemate, insufficient material) otherwise "draw" is ignored, which solved a lot of problems. I can disable this, but it only seems to be safe with Crafty vs Crafty matches, to specifically test accepting draw offers which I do a bit differently from some.
matthewlai
Posts: 793
Joined: Sun Aug 03, 2014 4:48 am
Location: London, UK

Re: Handling xboard new game race condition in protover 1 en

Post by matthewlai »

bob wrote:
matthewlai wrote:
hgm wrote:How do you solve the problem of multiple input sources and timer events? Create a separate input thread for every engine, and let it do blocking input? And use SIGALRM to set up the next timer event?

If you have solved these problems, it might be easier to just hack the GUI-dependence out of XBoard. By making all non-static routines in gtk/xoptions.c into dummies (and deleting the static ones). Basically you would only have to provide a new routines AddInputSource and RemoveInputSource, and rewite the timer handling in gtk/xtimer.c. And delete all the gtk-referring code out of gtk/xboard.c.

The timer handling seems the most tricky, as there can be several timeouts pending simultaneously in XBoard. (A dedicated one for making the clock tick, and a general one for all other events.)
For multiple input sources I am using select(). It's easier for me because I don't need to support Windows.

I am doing select() with timeouts, and check the clocks at each timeout.

I think the main difference is that I am not making it event driven. So my main loop looks like this (pseudo code) -

Code: Select all

while (game_still_ongoing)
{
	select(both_engine’s_input, timeout = 100ms);

	// these are asynchronous - they will only process what’s available already
	// in the pipes, and not block
	engine1.process_pending_inputs();
	engine2.process_pending_inputs();

	if (either_engine_made_a_move_or_made_draw_offer)
	{
		pass_it_on_to_the_other_engine();
	}

	check_clocks();
}
It's very different from how xboard is organized (since xboard is event driven and need to handle user input).
One other note. I decided to give up on passing draw offers between programs. Too many do it wrong, so I just gave up. My referee ends a game when a draw state is seen (50 moves, 3-fold rep, stalemate, insufficient material) otherwise "draw" is ignored, which solved a lot of problems. I can disable this, but it only seems to be safe with Crafty vs Crafty matches, to specifically test accepting draw offers which I do a bit differently from some.
How do engines do it wrong? I thought all engines have to do is "offer draw" when they see a draw offer and want to take it.

Do they assume the game is over?

I am hesitant to ignore draw offers, because I am very interested in saving time (to play more games), and if engines agree to draw, it would save a lot of time in some cases.
Disclosure: I work for DeepMind on the AlphaZero project, but everything I say here is personal opinion and does not reflect the views of DeepMind / Alphabet.