[gnome-chess] Fix Undo before engine moves



commit cc5704a57c0cfbbf80d3be64462c3aa3daa528d8
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Wed Jun 25 10:20:03 2014 -0500

    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

 src/chess-engine-cecp.vala |    2 +-
 src/chess-engine-uci.vala  |   19 +++++++++++++++----
 src/chess-engine.vala      |   17 +++++++++++++++--
 3 files changed, 31 insertions(+), 7 deletions(-)
---
diff --git a/src/chess-engine-cecp.vala b/src/chess-engine-cecp.vala
index 3070c2d..b636e6a 100644
--- a/src/chess-engine-cecp.vala
+++ b/src/chess-engine-cecp.vala
@@ -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
diff --git a/src/chess-engine-uci.vala b/src/chess-engine-uci.vala
index 9a67663..e76f1df 100644
--- a/src/chess-engine-uci.vala
+++ b/src/chess-engine-uci.vala
@@ -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;
                 }
             }
diff --git a/src/chess-engine.vala b/src/chess-engine.vala
index 44bca7a..3e9be02 100644
--- a/src/chess-engine.vala
+++ b/src/chess-engine.vala
@@ -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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]