Fix Undo before engine moves

Since I added a delay before telling the engine to move, this opened a
window where the engine could become desynced if you use Undo before it
receives a move request, since during this time, the ChessEngine class
thinks it's still the human player's turn
This commit is contained in:
Michael Catanzaro 2014-06-25 10:20:03 -05:00
parent 9f9afa4044
commit cc5704a57c
3 changed files with 31 additions and 7 deletions

View file

@ -119,7 +119,7 @@ public class ChessEngineCECP : ChessEngine
moving = false;
}
public override void undo ()
public override void do_undo ()
{
/*
* We're undoing only the most recent move here, so there's no need to

View file

@ -53,7 +53,7 @@ public class ChessEngineUCI : ChessEngine
moves += " " + move.get_engine ();
}
public override void undo ()
public override void do_undo ()
{
if (waiting_for_move)
write_line ("stop");
@ -105,9 +105,20 @@ public class ChessEngineUCI : ChessEngine
case "bestmove":
if (tokens.length < 2)
warning ("No move with bestmove: %s", line);
debug ("Engine moves %s", tokens[1]);
waiting_for_move = false;
moved (tokens[1]);
/* GNU Chess likes to report a move after receiving a stop command,
* and the UCI spec does not seem to prohibit this, so just discard
* the move if we were not expecting it. */
if (waiting_for_move)
{
debug ("Engine moves %s", tokens[1]);
waiting_for_move = false;
moved (tokens[1]);
}
else
{
debug ("Discarding engine move during human's turn (OK after recent Undo)");
}
break;
}
}

View file

@ -16,6 +16,7 @@ public abstract class ChessEngine : Object
private string[] args;
private uint delay_seconds;
private uint pending_move_source_id;
private Pid pid;
private int stdin_fd;
@ -108,19 +109,31 @@ public abstract class ChessEngine : Object
public abstract void report_move (ChessMove move);
public abstract void undo ();
protected abstract void do_undo ();
protected abstract void request_move ();
public void move ()
{
Timeout.add_seconds (delay_seconds, () => {
pending_move_source_id = Timeout.add_seconds (delay_seconds, () => {
pending_move_source_id = 0;
request_move ();
/* Disconnect from main loop */
return false;
});
}
public void undo ()
{
if (pending_move_source_id != 0)
{
Source.remove (pending_move_source_id);
pending_move_source_id = 0;
}
do_undo ();
}
public void stop ()
{
if (!started)