[iagno] Calculate move delay after performing search



commit 14a996c91b4bd46ef3af3ae92f0003c27f500ce6
Author: Michael Catanzaro <mcatanzaro gnome org>
Date:   Thu Sep 18 22:58:52 2014 -0500

    Calculate move delay after performing search
    
    Right now, we add a fixed amount of delay before each move, then start
    the search. This means that the game takes longer to move on higher
    difficulty levels and slower computers. Mitigate this by computing
    artifical delay after the completion of the search instead. (This means
    the AI will now move a bit faster than before.)
    
    https://bugzilla.gnome.org/show_bug.cgi?id=736932

 src/Makefile.am          |    5 +++++
 src/computer-player.vala |   34 ++++++++++++++++++++++++++++++++++
 src/iagno.vala           |   44 +++++++++++++-------------------------------
 3 files changed, 52 insertions(+), 31 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 9e8fc39..4491f77 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -23,6 +23,7 @@ iagno_CFLAGS = \
 
 iagno_VALAFLAGS = \
        --pkg posix \
+       --pkg gio-2.0 \
        --pkg gtk+-3.0 \
        --pkg librsvg-2.0 \
        --pkg libcanberra \
@@ -37,6 +38,10 @@ test_iagno_SOURCES = \
        game.vala \
        player.vala
 
+test_iagno_VALAFLAGS = \
+       --pkg gio-2.0 \
+       --target-glib 2.40
+
 test_iagno_CFLAGS = $(IAGNO_CFLAGS)
 
 test_iagno_LDADD = $(IAGNO_LIBS)
diff --git a/src/computer-player.vala b/src/computer-player.vala
index 40aedad..719c2a4 100644
--- a/src/computer-player.vala
+++ b/src/computer-player.vala
@@ -55,6 +55,9 @@ public class ComputerPlayer : Object
         65,  -3, 6, 4, 4, 6,  -3, 65
     };
 
+    /* Source ID of a pending move timeout */
+    private uint pending_move_id = 0;
+
     public ComputerPlayer (Game game, int level = 1)
     {
         this.game = game;
@@ -72,6 +75,37 @@ public class ComputerPlayer : Object
             critical ("Computer chose an invalid move: %d,%d", x, y);
     }
 
+    public async void move_async (double delay_seconds = 0.0)
+    {
+        var timer = new Timer ();
+        int x = 0;
+        int y = 0;
+
+        timer.start ();
+        run_search (ref x, ref y);
+        timer.stop ();
+
+        if (timer.elapsed () < delay_seconds)
+        {
+            pending_move_id = Timeout.add ((uint) ((delay_seconds - timer.elapsed ()) * 1000), 
move_async.callback);
+            yield;
+        }
+
+        pending_move_id = 0;
+
+        if (game.place_tile (x, y) == 0)
+            critical ("Computer chose an invalid move: %d,%d", x, y);
+    }
+
+    public void cancel_move ()
+    {
+        if (pending_move_id != 0)
+        {
+            Source.remove (pending_move_id);
+            pending_move_id = 0;
+        }
+    }
+
     private void run_search (ref int x, ref int y)
         requires (game.can_move (game.current_color))
     {
diff --git a/src/iagno.vala b/src/iagno.vala
index a4e36ac..b7adc94 100644
--- a/src/iagno.vala
+++ b/src/iagno.vala
@@ -18,6 +18,11 @@ public class Iagno : Gtk.Application
     private static bool fast_mode;
     private static int computer_level = 0;
 
+    /* Seconds */
+    private static const double QUICK_MOVE_DELAY = 0.4;
+    private static const double MODERATE_MOVE_DELAY = 1.0;
+    private static const double SLOW_MOVE_DELAY = 2.0;
+
     /* Widgets */
     private Gtk.Window window;
     private int window_width;
@@ -36,9 +41,6 @@ public class Iagno : Gtk.Application
     /* Human player */
     private Player player_one;
 
-    /* Timer to delay computer moves */
-    private uint computer_timer = 0;
-
     /* The game being played */
     private Game? game = null;
 
@@ -209,11 +211,12 @@ public class Iagno : Gtk.Application
 
     private void start_game ()
     {
-        cancel_pending_computer_moves ();
-
         if (game != null)
             SignalHandler.disconnect_by_func (game, null, this);
 
+        if (computer != null)
+            computer.cancel_move ();
+
         game = new Game ();
         game.move.connect (game_move_cb);
         game.complete.connect (game_complete_cb);
@@ -229,12 +232,8 @@ public class Iagno : Gtk.Application
 
         update_ui ();
 
-        /*
-         * Get the computer to move after a delay (so it looks like it's
-         * thinking - but only a short delay for the first move)
-         */
         if (player_one != Player.DARK && computer != null)
-            computer_timer = Timeout.add_seconds (1, computer_move_cb);
+            computer.move_async.begin (MODERATE_MOVE_DELAY);
     }
 
     private void update_ui ()
@@ -268,8 +267,6 @@ public class Iagno : Gtk.Application
 
     private void undo_move_cb ()
     {
-        cancel_pending_computer_moves ();
-
         if (computer == null)
         {
             game.undo (1);
@@ -278,6 +275,8 @@ public class Iagno : Gtk.Application
         }
         else
         {
+            computer.cancel_move ();
+
             /* Undo once if the human player just moved, otherwise undo both moves */
             if (game.current_color != player_one)
                 game.undo (1);
@@ -361,26 +360,9 @@ public class Iagno : Gtk.Application
         if (game.current_color != player_one && computer != null)
         {
             if (game.n_tiles == 63 || fast_mode)
-                computer_timer = Timeout.add (400, computer_move_cb);
+                computer.move_async.begin (QUICK_MOVE_DELAY);
             else
-                computer_timer = Timeout.add_seconds (2, computer_move_cb);
-        }
-    }
-
-    private bool computer_move_cb ()
-    {
-        cancel_pending_computer_moves ();
-        if (game.current_color != player_one)
-            computer.move ();
-        return false;
-    }
-
-    private void cancel_pending_computer_moves ()
-    {
-        if (computer_timer != 0)
-        {
-            Source.remove (computer_timer);
-            computer_timer = 0;
+                computer.move_async.begin (SLOW_MOVE_DELAY);
         }
     }
 


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