Page 1 of 2

Handling xboard new game race condition in protover 1 engine

Posted: Tue Aug 12, 2014 10:35 pm
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

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

Posted: Wed Aug 13, 2014 7:27 am
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.

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

Posted: Wed Aug 13, 2014 7:31 am
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.

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

Posted: Wed Aug 13, 2014 8:21 am
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.

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

Posted: Wed Aug 13, 2014 10:09 am
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.

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

Posted: Wed Aug 13, 2014 10:14 am
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.

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

Posted: Wed Aug 13, 2014 1:42 pm
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.)

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

Posted: Wed Aug 13, 2014 5:55 pm
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).

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

Posted: Fri Aug 15, 2014 12:22 am
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.

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

Posted: Fri Aug 15, 2014 12:44 am
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.