[gnome-games] chess: Start to get undo to work again



commit cdcc65b7c49148777a498fdcd81261ec4b94a125
Author: Robert Ancell <robert ancell canonical com>
Date:   Tue Jan 25 21:44:15 2011 +1000

    chess: Start to get undo to work again

 glchess/src/chess-engine-cecp.vala |    7 +++-
 glchess/src/chess-engine-uci.vala  |   19 ++++++---
 glchess/src/chess-engine.vala      |    4 ++
 glchess/src/chess-game.vala        |   31 +++++++++++++++
 glchess/src/glchess.vala           |   76 +++++++++++++++++++++++++++---------
 glchess/src/history.vala           |   10 +++++
 6 files changed, 121 insertions(+), 26 deletions(-)
---
diff --git a/glchess/src/chess-engine-cecp.vala b/glchess/src/chess-engine-cecp.vala
index a5008c7..cb40419 100644
--- a/glchess/src/chess-engine-cecp.vala
+++ b/glchess/src/chess-engine-cecp.vala
@@ -69,7 +69,7 @@ public class ChessEngineCECP : ChessEngine
     public override void start_game ()
     {
     }
-
+    
     public override void request_move ()
     {
         write_line ("go");
@@ -86,4 +86,9 @@ public class ChessEngineCECP : ChessEngine
         }
         moving = false;
     }
+
+    public override void undo ()
+    {
+        write_line ("undo");
+    }
 }
diff --git a/glchess/src/chess-engine-uci.vala b/glchess/src/chess-engine-uci.vala
index 842cd5f..a7a9c02 100644
--- a/glchess/src/chess-engine-uci.vala
+++ b/glchess/src/chess-engine-uci.vala
@@ -1,14 +1,14 @@
 public class ChessEngineUCI : ChessEngine
 {
     private char[] buffer;
-    private string position_command;
+    private string moves;
     private string[] options;
     
     public ChessEngineUCI (string[] options)
     {
         this.options = options;
         buffer = new char[0];
-        position_command = "position startpos";
+        moves = "";
         starting.connect (start_cb);
     }
 
@@ -24,15 +24,22 @@ public class ChessEngineUCI : ChessEngine
 
     public override void request_move ()
     {
+        if (moves != "")
+            write_line ("position startpos moves" + moves);
+        else
+            write_line ("position startpos");
         write_line ("go wtime 30000 btime 30000");
     }
 
     public override void report_move (ChessMove move)
     {
-        if (position_command == "position startpos")
-            position_command += " moves";
-        position_command += " " + move.get_engine ();
-        write_line (position_command);
+        moves += " " + move.get_engine ();
+    }
+
+    public override void undo ()
+    {
+        write_line ("stop");
+        moves = moves.slice (0, moves.last_index_of (" "));
     }
 
     public override void process_input (char[] data)
diff --git a/glchess/src/chess-engine.vala b/glchess/src/chess-engine.vala
index ece5e4a..fe12607 100644
--- a/glchess/src/chess-engine.vala
+++ b/glchess/src/chess-engine.vala
@@ -73,6 +73,10 @@ public class ChessEngine : Object
     {
     }
 
+    public virtual void undo ()
+    {
+    }
+
     public void stop ()
     {
         // FIXME
diff --git a/glchess/src/chess-game.vala b/glchess/src/chess-game.vala
index d5ef9c0..44ab141 100644
--- a/glchess/src/chess-game.vala
+++ b/glchess/src/chess-game.vala
@@ -9,6 +9,7 @@ public class ChessPlayer : Object
     public Color color;
     public signal void start_turn ();
     public signal bool do_move (string move, bool apply);
+    public signal void do_undo ();
     public signal bool do_resign ();
     public signal bool do_claim_draw ();
 
@@ -28,6 +29,11 @@ public class ChessPlayer : Object
         return do_move (move, apply);
     }
 
+    public void undo ()
+    {
+        do_undo ();
+    }
+
     public bool resign ()
     {
         return do_resign ();
@@ -1134,6 +1140,7 @@ public class ChessGame
     public signal void started ();
     public signal void turn_started (ChessPlayer player);
     public signal void moved (ChessMove move);
+    public signal void undo ();
     public signal void ended ();
 
     public ChessPlayer white
@@ -1148,6 +1155,10 @@ public class ChessGame
     {
         get { return move_stack.data.current_player; }
     }
+    public ChessPlayer opponent
+    {
+        get { return move_stack.data.opponent; }
+    }
     private ChessClock? _clock;
     public ChessClock? clock
     {
@@ -1176,9 +1187,11 @@ public class ChessGame
         }
 
         white.do_move.connect (move_cb);
+        white.do_undo.connect (undo_cb);
         white.do_resign.connect (resign_cb);
         white.do_claim_draw.connect (claim_draw_cb);
         black.do_move.connect (move_cb);
+        black.do_undo.connect (undo_cb);
         black.do_resign.connect (resign_cb);
         black.do_claim_draw.connect (claim_draw_cb);
     }
@@ -1229,6 +1242,24 @@ public class ChessGame
         return true;
     }
 
+    private void undo_cb (ChessPlayer player)
+    {
+        /* If this players turn undo their opponents move then their last move */
+        if (player == current_player)
+        {
+            undo_cb (opponent);
+            return;
+        }
+
+        /* Don't pop off starting move */
+        if (move_stack.next == null)
+            return;
+
+        /* Pop off the move state and notify */
+        move_stack.remove_link (move_stack);
+        undo ();
+    }
+
     private bool resign_cb (ChessPlayer player)
     {
         if (!is_started)
diff --git a/glchess/src/glchess.vala b/glchess/src/glchess.vala
index b89b8b9..76cc26d 100644
--- a/glchess/src/glchess.vala
+++ b/glchess/src/glchess.vala
@@ -110,26 +110,39 @@ public class Application
         if (save_duration_timeout != 0)
             save_duration_cb ();
 
-        /* Autosave */
-        // FIXME: Only once a human has moved
-        if (in_history && pgn_game.moves != null)
+        autosave ();
+        settings.sync ();
+        Gtk.main_quit ();
+    }
+
+    private void autosave ()
+    {
+        /* FIXME: Prompt user to save somewhere */
+        if (!in_history)
+            return;
+
+        /* Don't autosave if no moves (e.g. they have been undone) or only the computer has moved */
+        if (pgn_game.moves == null || (
+            (pgn_game.moves.length () == 1 && opponent != null && opponent.color == Color.WHITE)))
         {
-            try
-            {
-                if (game_file != null)
-                    history.update (game_file, "", pgn_game.result);
-                else
-                    game_file = history.add (pgn_game.date, pgn_game.result);
-                pgn_game.write (game_file);
-            }
-            catch (Error e)
-            {
-                warning ("Failed to autosave: %s", e.message);
-            }
+            if (game_file != null)
+                history.remove (game_file);
+            return;
         }
 
-        settings.sync ();
-        Gtk.main_quit ();
+        try
+        {
+            if (game_file != null)
+                history.update (game_file, "", pgn_game.result);
+            else
+                game_file = history.add (pgn_game.date, pgn_game.result);
+            debug ("Writing current game to %s", game_file.get_path ());
+            pgn_game.write (game_file);
+        }
+        catch (Error e)
+        {
+            warning ("Failed to autosave: %s", e.message);
+        }
     }
 
     private void settings_changed_cb (Settings settings, string key)
@@ -243,6 +256,7 @@ public class Application
         game.started.connect (game_start_cb);
         game.turn_started.connect (game_turn_cb);
         game.moved.connect (game_move_cb);
+        game.undo.connect (game_undo_cb);
         game.ended.connect (game_end_cb);
         if (game.clock != null)
             game.clock.tick.connect (game_clock_tick_cb);
@@ -600,8 +614,8 @@ public class Application
         if (move.number > pgn_game.moves.length ())
             pgn_game.moves.append (move.get_san ());
 
-        Gtk.TreeIter iter;
         var model = (Gtk.ListStore) history_combo.model;
+        Gtk.TreeIter iter;
         model.append (out iter);
         model.set (iter, 1, move.number, -1);        
         set_move_text (iter, move);
@@ -619,6 +633,30 @@ public class Application
         view.queue_draw ();
     }
 
+    private void game_undo_cb (ChessGame game)
+    {
+        /* Notify AI */
+        if (opponent_engine != null)
+            opponent_engine.undo ();
+
+        /* Remove from the PGN game */
+        pgn_game.moves.remove_link (pgn_game.moves.last ());
+
+        /* Remove from the history */
+        var model = (Gtk.ListStore) history_combo.model;
+        Gtk.TreeIter iter;
+        model.iter_nth_child (out iter, null, model.iter_n_children (null) - 1);
+        model.remove (iter);
+
+        /* If watching this move, go back one */
+        if (view_options.move_number > game.n_moves || view_options.move_number == -1)
+        {
+            model.iter_nth_child (out iter, null, model.iter_n_children (null) - 1);
+            history_combo.set_active_iter (iter);
+            view.queue_draw ();
+        }
+    }
+
     private void game_end_cb (ChessGame game)
     {
         string title = "";
@@ -748,7 +786,7 @@ public class Application
     [CCode (cname = "G_MODULE_EXPORT undo_move_cb", instance_pos = -1)]
     public void undo_move_cb (Gtk.Widget widget)
     {
-        warning ("FIXME: Undo last move");
+        game.current_player.undo ();
     }
 
     [CCode (cname = "G_MODULE_EXPORT quit_cb", instance_pos = -1)]
diff --git a/glchess/src/history.vala b/glchess/src/history.vala
index e540847..4e8d78b 100644
--- a/glchess/src/history.vala
+++ b/glchess/src/history.vala
@@ -58,6 +58,16 @@ public class History
         return file;
     }
 
+    public void remove (File file)
+    {
+        var relative_path = history_dir.get_relative_path (file);
+
+        Sqlite.Statement statement;
+        assert (db.prepare_v2 ("DELETE FROM GameTable WHERE path=\"%s\"".printf (relative_path), -1, out statement) == Sqlite.OK);
+        if (statement.step () != Sqlite.DONE)
+            warning ("Failed to remove game from history index: %s", db.errmsg ());
+    }
+
     public void update (File file, string fen, string result)
     {
         var relative_path = history_dir.get_relative_path (file);



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