[swell-foop/arnaudb/save-on-exit] Save game on exit.



commit 16b326df2b74d6b984bda22a1f05494cb5384220
Author: Arnaud Bonatti <arnaud bonatti gmail com>
Date:   Sun May 10 22:22:45 2020 +0200

    Save game on exit.

 data/org.gnome.swell-foop.gschema.xml | 17 +++++++
 src/game.vala                         | 88 ++++++++++++++++++++++++++++++++++-
 src/window.vala                       | 32 ++++++++-----
 3 files changed, 124 insertions(+), 13 deletions(-)
---
diff --git a/data/org.gnome.swell-foop.gschema.xml b/data/org.gnome.swell-foop.gschema.xml
index 3c1d735..e63b093 100644
--- a/data/org.gnome.swell-foop.gschema.xml
+++ b/data/org.gnome.swell-foop.gschema.xml
@@ -7,29 +7,46 @@
   <schema id="org.gnome.swell-foop" path="/org/gnome/swell-foop/" gettext-domain="swell-foop">
     <key name="theme" type="s">
       <default>'shapesandcolors'</default>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/swell-foop/theme' -->
       <summary>The theme to use</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/swell-foop/theme' -->
       <description>The title of the tile theme to use.</description>
     </key>
     <key name="size" enum="org.gnome.swell-foop.Sizes">
       <default>'small'</default>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/swell-foop/size' -->
       <summary>Board size</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/swell-foop/size' -->
       <description>The size of the game board.</description>
     </key>
     <key name="colors" type="i">
       <default>3</default>
       <range min="2" max="4"/>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/swell-foop/colors' -->
       <summary>Board color count</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/swell-foop/colors' -->
       <description>The number of colors of tiles to use in the game.</description>
     </key>
     <key name="first-run" type="b">
       <default>true</default>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/swell-foop/first-run' -->
       <summary>Is this the first run</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/swell-foop/first-run' -->
       <description>Setting to decide whether to show first-run hint dialog or not.</description>
     </key>
     <key name="zealous" type="b">
       <default>true</default>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/swell-foop/zealous' -->
       <summary>Zealous animation</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/swell-foop/zealous' -->
       <description>Use more flashy, but slower, animations.</description>
     </key>
+    <key name="saved-game" type="m(yqaay)">
+      <default>nothing</default>
+      <!-- Translators: summary of a settings key, see 'dconf-editor /org/gnome/swell-foop/saved-game' -->
+      <summary>Saved game</summary>
+      <!-- Translators: description of a settings key, see 'dconf-editor /org/gnome/swell-foop/saved-game'; 
"nothing" is a keyword: you might want to translate « “nothing” (your translation) » for example -->
+      <description>Has value “nothing” if there is no saved game. Else, the values are: the number of 
colors, the score, and a copy of the board, where “0” means “empty”.</description>
+    </key>
   </schema>
 </schemalist>
diff --git a/src/game.vala b/src/game.vala
index 8dea8a1..50a8be7 100644
--- a/src/game.vala
+++ b/src/game.vala
@@ -78,7 +78,7 @@ private class Game : Object
     public int color_num
     {
         internal get { return _color_num; }
-        protected construct
+        protected construct set     // TODO should be doable to make construct only again
         {
             if (value < 2 || value > 4)
                 _color_num = 3;
@@ -96,10 +96,15 @@ private class Game : Object
     internal signal void started ();
 
     /* Constructor */
-    internal Game (int rows, int columns, int color_num)
+    internal Game (int rows, int columns, int color_num, Variant? variant = null)
     {
         Object (rows: rows, columns: columns, color_num: color_num);
+        if (variant == null || !load_saved_game ((!) variant))
+            create_new_game ();
+    }
 
+    private inline void create_new_game ()
+    {
         /* A 2D array holds all tiles */
         tiles = new Tile [rows, columns];
 
@@ -295,4 +300,83 @@ private class Game : Object
         score += increment;
         update_score (increment);
     }
+
+    /*\
+    * * loading and saving
+    \*/
+
+    private inline bool load_saved_game (Variant variant)
+    {
+        if (variant.get_type_string () != "m(yqaay)")
+            return false;   // assert_not_reached() ?
+
+        Variant? child = variant.get_maybe ();
+        if (child == null)
+            return false;
+
+        VariantIter iter = new VariantIter ((!) child);
+        uint8 color_num;
+        uint16 score;
+        iter.next ("y", out color_num);
+        iter.next ("q", out score);
+        Variant tmp_variant = iter.next_value ();
+
+        if (color_num < 2 || color_num > 4)
+            return false;
+
+        // all the following way to extract values feels horrible, but there is a bug when trying to do it 
properly (05/2020)
+        Variant tmp_variant_2 = tmp_variant.get_child_value (0);
+        uint rows = (uint) tmp_variant.n_children ();
+        uint columns = (uint) tmp_variant_2.n_children ();
+        if (rows    != this.rows
+         || columns != this.columns)
+            return false;
+
+        this.color_num = color_num;
+        this.score = score;
+        update_score (score);
+        tiles = new Tile [rows, columns];
+        for (uint8 i = 0; i < rows; i++)
+        {
+            tmp_variant_2 = tmp_variant.get_child_value (i);
+            for (uint8 j = 0; j < columns; j++)
+            {
+                Variant tmp_variant_3 = tmp_variant_2.get_child_value (j);
+                uint8 color = tmp_variant_3.get_byte ();
+                if (color == 0)
+                {
+                    tiles [rows - i - 1, j] = new Tile (j, (int) (rows - i - 1), 0);
+                    tiles [rows - i - 1, j].closed = true;
+                }
+                else
+                    tiles [rows - i - 1, j] = new Tile (j, (int) (rows - i - 1), color - 1);
+            }
+        }
+        is_started = true;
+        return true;
+    }
+
+    internal Variant get_saved_game ()
+    {
+        if (!is_started || has_completed ())
+            return new Variant ("m(yqaay)", null);
+
+        VariantBuilder builder = new VariantBuilder (new VariantType ("(yqaay)"));
+        builder.add ("y", (uint8) color_num);
+        builder.add ("q", (uint16) score);
+        builder.open (new VariantType ("aay"));
+        VariantType ay_type = new VariantType ("ay");
+        for (uint8 i = (uint8) rows; i > 0; i--)
+        {
+            builder.open (ay_type);
+            for (uint8 j = 0; j < columns; j++)
+                if (tiles [i - 1, j] == null || ((!) tiles [i - 1, j]).closed)
+                    builder.add ("y", 0);
+                else
+                    builder.add ("y", tiles [i - 1, j].color + 1);
+            builder.close ();
+        }
+        builder.close ();
+        return new Variant.maybe (null, builder.end ());
+    }
 }
diff --git a/src/window.vala b/src/window.vala
index 4fa6997..9775412 100644
--- a/src/window.vala
+++ b/src/window.vala
@@ -127,8 +127,12 @@ private class SwellFoopWindow : ApplicationWindow
         stage = (Clutter.Stage) clutter_embed.get_stage ();
         stage.background_color = Clutter.Color.from_string ("#000000");  /* background color is black */
 
-        /* Create an instance of game with initial values for row, column and color */
-        game = new Game (get_board_size ().rows, get_board_size ().columns, settings.get_int ("colors"));
+        /* Create an instance of game, either with a saved game, or with initial values for row, column and 
color */
+        Size size = get_board_size ();
+        game = new Game (size.rows, size.columns, settings.get_int ("colors"), settings.get_value 
("saved-game"));
+        update_score_cb (game.score);
+        if (game.score != 0)
+            game_in_progress = true;
 
         /* Game score change will be sent to the main window and show in the score label */
         game.update_score.connect (update_score_cb);
@@ -222,8 +226,9 @@ private class SwellFoopWindow : ApplicationWindow
 
     internal void new_game ()
     {
-        game = new Game (get_board_size ().rows,
-                         get_board_size ().columns,
+        Size size = get_board_size ();
+        game = new Game (size.rows,
+                         size.columns,
                          settings.get_int ("colors"));
         game.update_score.connect (update_score_cb);
         game.complete.connect (complete_cb);
@@ -240,13 +245,19 @@ private class SwellFoopWindow : ApplicationWindow
         update_score_cb (0);
     }
 
-    private bool being_destroyed = false;
     protected override void destroy ()
     {
-        /* Record the score if the game isn't over. */
-        being_destroyed = true;
-        if (game != null && !game.has_completed () && game.score > 0)
-            add_score ();
+        settings.delay ();
+        settings.set_value ("saved-game", game.get_saved_game ());
+        settings.set_int ("colors", game.color_num);
+        for (uint8 i = 0; i < sizes.length; i++)
+            if (game.rows == sizes [i].rows && game.columns == sizes [i].columns)
+            {
+                settings.set_string ("size", sizes [i].id);
+                break;
+            }
+        settings.apply ();
+
         base.destroy ();
     }
 
@@ -481,8 +492,7 @@ private class SwellFoopWindow : ApplicationWindow
                 {
                     warning ("Failed to add score: %s", e.message);
                 }
-                if (!being_destroyed)
-                    scores_context.run_dialog ();
+                scores_context.run_dialog ();
             });
     }
 


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