[gnome-robots] Rewrite GameConfig in Vala



commit eebf5e111fa9cb48621f80d8d04949b9394ae714
Author: Andrey Kutejko <andy128k gmail com>
Date:   Mon Aug 24 20:37:09 2020 +0200

    Rewrite GameConfig in Vala

 meson.build          |   6 +
 src/config.vapi      |   7 +
 src/game-config.vala | 209 +++++++++++++++++++++++
 src/game.c           |  95 ++++++-----
 src/gameconfig.c     | 466 ---------------------------------------------------
 src/gameconfig.h     |  58 -------
 src/gnome-robots.c   |   5 +-
 src/meson.build      |  22 ++-
 src/properties.c     |  32 ++--
 src/properties.h     |   4 +
 10 files changed, 315 insertions(+), 589 deletions(-)
---
diff --git a/meson.build b/meson.build
index db53890..54b0f92 100644
--- a/meson.build
+++ b/meson.build
@@ -7,6 +7,12 @@ i18n = import('i18n')
 
 application_id = 'org.gnome.Robots'
 
+add_project_arguments([
+    '-include', 'config.h'
+  ],
+  language: 'c'
+)
+
 gee_dependency = dependency('gee-0.8')
 gio_dependency = dependency('gio-2.0', version: '>= 2.32')
 glib_dependency = dependency('glib-2.0', version: '>= 2.32')
diff --git a/src/config.vapi b/src/config.vapi
new file mode 100644
index 0000000..b9f8304
--- /dev/null
+++ b/src/config.vapi
@@ -0,0 +1,7 @@
+public const string GETTEXT_PACKAGE;
+public const string LOCALEDIR;
+public const string PACKAGE;
+public const string DATA_DIRECTORY;
+public const string SOUND_DIRECTORY;
+public const string VERSION;
+
diff --git a/src/game-config.vala b/src/game-config.vala
new file mode 100644
index 0000000..b85f49b
--- /dev/null
+++ b/src/game-config.vala
@@ -0,0 +1,209 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more details see the file COPYING.
+ */
+
+public struct GameConfig {
+    public string description;
+    public int initial_type1;
+    public int initial_type2;
+    public int increment_type1;
+    public int increment_type2;
+    public int maximum_type1;
+    public int maximum_type2;
+    public int score_type1;
+    public int score_type2;
+    public int score_type1_waiting;
+    public int score_type2_waiting;
+    public int score_type1_splatted;
+    public int score_type2_splatted;
+    public int num_robots_per_safe;
+    public int safe_score_boundary;
+    public int initial_safe_teleports;
+    public int free_safe_teleports;
+    public int max_safe_teleports;
+    public bool moveable_heaps;
+
+    public string name () {
+        return description.replace ("_", " ");
+    }
+
+    public static GameConfig from_file (string filename) throws Error {
+        GameConfig gcfg = GameConfig ();
+
+        gcfg.description = Path.get_basename (filename);
+        if (gcfg.description.has_suffix (".cfg")) {
+            gcfg.description = gcfg.description.substring (0, gcfg.description.length - 4);
+        }
+
+        var line_regex = new Regex ("^(\\w+)\\s*=\\s*(\\d+)");
+
+        var file = File.new_for_path (filename);
+        var dis = new DataInputStream (file.read ());
+
+        string line;
+        uint pflag = 0;
+        while ((line = dis.read_line (null)) != null) {
+            MatchInfo match_info;
+            if (!line_regex.match (line, 0, out match_info)) {
+                continue;
+            }
+            string key = match_info.fetch (1);
+            int val = int.parse (match_info.fetch (2));
+
+            if (key == "initial_type1") {
+                gcfg.initial_type1 = val;
+                pflag |= 0x00000001;
+            }
+            if (key == "initial_type2") {
+                gcfg.initial_type2 = val;
+                pflag |= 0x00000002;
+            }
+            if (key == "increment_type1") {
+                gcfg.increment_type1 = val;
+                pflag |= 0x00000004;
+            }
+            if (key == "increment_type2") {
+                gcfg.increment_type2 = val;
+                pflag |= 0x00000008;
+            }
+            if (key == "maximum_type1") {
+                gcfg.maximum_type1 = val;
+                pflag |= 0x00000010;
+            }
+            if (key == "maximum_type2") {
+                gcfg.maximum_type2 = val;
+                pflag |= 0x00000020;
+            }
+            if (key == "score_type1") {
+                gcfg.score_type1 = val;
+                pflag |= 0x00000040;
+            }
+            if (key == "score_type2") {
+                gcfg.score_type2 = val;
+                pflag |= 0x00000080;
+            }
+            if (key == "score_type1_waiting") {
+                gcfg.score_type1_waiting = val;
+                pflag |= 0x00000100;
+            }
+            if (key == "score_type2_waiting") {
+                gcfg.score_type2_waiting = val;
+                pflag |= 0x00000200;
+            }
+            if (key == "score_type1_splatted") {
+                gcfg.score_type1_splatted = val;
+                pflag |= 0x00000400;
+            }
+            if (key == "score_type2_splatted") {
+                gcfg.score_type2_splatted = val;
+                pflag |= 0x00000800;
+            }
+            if (key == "num_robots_per_safe") {
+                gcfg.num_robots_per_safe = val;
+                pflag |= 0x00001000;
+            }
+            if (key == "safe_score_boundary") {
+                gcfg.safe_score_boundary = val;
+                pflag |= 0x00002000;
+            }
+            if (key == "max_safe_teleports") {
+                gcfg.max_safe_teleports = val;
+                pflag |= 0x00004000;
+            }
+            if (key == "initial_safe_teleports") {
+                gcfg.initial_safe_teleports = val;
+                pflag |= 0x00008000;
+            }
+            if (key == "free_safe_teleports") {
+                gcfg.free_safe_teleports = val;
+                pflag |= 0x00010000;
+            }
+            if (key == "moveable_heaps") {
+                gcfg.moveable_heaps = val != 0;
+                pflag |= 0x00020000;
+            }
+        }
+
+        // Check we have got all types
+        if (pflag != 0x0003ffff) {
+            throw new FileError.INVAL ("Bad game config file.");
+        }
+
+        return gcfg;
+    }
+}
+
+public class GameConfigs {
+    private Gee.ArrayList<GameConfig?> game_configs;
+    private uint current_config;
+
+    public GameConfigs.load () throws Error {
+        var dname = Path.build_filename (DATA_DIRECTORY, "games");
+        var dir = Dir.open (dname);
+        game_configs = new Gee.ArrayList<GameConfig?> ();
+        string? filename;
+        while ((filename = dir.read_name ()) != null) {
+            if (!filename.has_suffix (".cfg")) {
+                continue;
+            }
+            var fullname = Path.build_filename (dname, filename);
+            try {
+                var gcfg = GameConfig.from_file (fullname);
+                game_configs.add (gcfg);
+            } catch (Error e) {
+                warning ("%s", e.message);
+            }
+        }
+
+        if (game_configs.size >= 0) {
+            current_config = 0;
+        } else {
+            throw new FileError.NOENT ("No game config was found.");
+        }
+    }
+
+    public uint count () {
+        return game_configs.size;
+    }
+
+    public GameConfig? @get (uint n) {
+        if (n < game_configs.size)
+            return game_configs[(int)n];
+        else
+            return null;
+    }
+
+    public string? get_name (uint n) {
+        if (n < game_configs.size)
+            return game_configs[(int)n].description.replace ("_", " ");
+        else
+            return null;
+    }
+
+    public GameConfig get_current () {
+        return game_configs[(int)current_config];
+    }
+
+    public uint get_current_index () {
+        return current_config;
+    }
+
+    public void set_current_index (uint n) {
+        if (n < game_configs.size)
+            current_config = n;
+    }
+}
+
diff --git a/src/game.c b/src/game.c
index 417c47b..4c61986 100644
--- a/src/game.c
+++ b/src/game.c
@@ -28,7 +28,7 @@
 #include <libgnome-games-support.h>
 
 #include "gbdefs.h"
-#include "gameconfig.h"
+#include "riiv.h"
 #include "keyboard.h"
 #include "game.h"
 #include "gnome-robots.h"
@@ -154,19 +154,16 @@ static void
 log_score (gint sc)
 {
   gchar *sbuf = NULL;
+  GameConfig game_config;
+
+  game_configs_get_current (game_configs, &game_config);
 
   if (properties_super_safe_moves ()) {
-    sbuf =
-      g_strdup_printf ("%s-super-safe",
-                       game_config_filename (current_game_config ()));
+    sbuf = g_strdup_printf ("%s-super-safe", game_config.description);
   } else if (properties_safe_moves ()) {
-    sbuf =
-      g_strdup_printf ("%s-safe",
-                       game_config_filename (current_game_config ()));
+    sbuf = g_strdup_printf ("%s-safe", game_config.description);
   } else {
-    sbuf =
-      g_strdup_printf ("%s",
-                       game_config_filename (current_game_config ()));
+    sbuf = g_strdup_printf ("%s", game_config.description);
   }
 
   if (sc != 0) {
@@ -207,42 +204,45 @@ static void
 add_kill (gint type)
 {
   gint si;
+  GameConfig game_config;
+
+  game_configs_get_current (game_configs, &game_config);
 
   if ((game_state == STATE_WAITING) || (game_state == STATE_WTYPE2)) {
     if (type == OBJECT_ROBOT1) {
-      si = game_config ()->score_type1_waiting;
+      si = game_config.score_type1_waiting;
       kills += 1;
     } else {
-      si = game_config ()->score_type2_waiting;
+      si = game_config.score_type2_waiting;
       kills += 2;
     }
   } else {
     if (type == OBJECT_ROBOT1) {
-      si = game_config ()->score_type1;
+      si = game_config.score_type1;
     } else {
-      si = game_config ()->score_type2;
+      si = game_config.score_type2;
     }
   }
 
   score += si;
   score_step += si;
 
-  if (game_config ()->safe_score_boundary > 0) {
-    while (score_step >= game_config ()->safe_score_boundary) {
+  if (game_config.safe_score_boundary > 0) {
+    while (score_step >= game_config.safe_score_boundary) {
       safe_teleports += 1;
-      score_step -= game_config ()->safe_score_boundary;
+      score_step -= game_config.safe_score_boundary;
     }
   }
 
-  if (game_config ()->num_robots_per_safe > 0) {
-    while (kills >= game_config ()->num_robots_per_safe) {
+  if (game_config.num_robots_per_safe > 0) {
+    while (kills >= game_config.num_robots_per_safe) {
       safe_teleports += 1;
-      kills -= game_config ()->num_robots_per_safe;
+      kills -= game_config.num_robots_per_safe;
     }
   }
 
-  if (safe_teleports > game_config ()->max_safe_teleports) {
-    safe_teleports = game_config ()->max_safe_teleports;
+  if (safe_teleports > game_config.max_safe_teleports) {
+    safe_teleports = game_config.max_safe_teleports;
   }
 
   update_game_status (score, current_level + 1, safe_teleports);
@@ -325,6 +325,9 @@ generate_level (void)
 {
   gint i;
   gint xp, yp;
+  GameConfig game_config;
+
+  game_configs_get_current (game_configs, &game_config);
 
   clear_arena ();
 
@@ -332,38 +335,38 @@ generate_level (void)
   player_xpos = PLAYER_DEF_XPOS;
   player_ypos = PLAYER_DEF_YPOS;
 
-  num_robots1 = game_config ()->initial_type1 +
-    game_config ()->increment_type1 * current_level;
+  num_robots1 = game_config.initial_type1 +
+    game_config.increment_type1 * current_level;
 
-  if (num_robots1 > game_config ()->maximum_type1) {
-    num_robots1 = game_config ()->maximum_type1;
+  if (num_robots1 > game_config.maximum_type1) {
+    num_robots1 = game_config.maximum_type1;
   }
   if (num_robots1 > MAX_ROBOTS) {
     current_level = 0;
-    num_robots1 = game_config ()->initial_type1;
+    num_robots1 = game_config.initial_type1;
     message_box (_("Congratulations, You Have Defeated the Robots!! \nBut Can You do it Again?"));
     play_sound (SOUND_VICTORY);
   }
 
-  num_robots2 = game_config ()->initial_type2 +
-    game_config ()->increment_type2 * current_level;
+  num_robots2 = game_config.initial_type2 +
+    game_config.increment_type2 * current_level;
 
-  if (num_robots2 > game_config ()->maximum_type2) {
-    num_robots2 = game_config ()->maximum_type2;
+  if (num_robots2 > game_config.maximum_type2) {
+    num_robots2 = game_config.maximum_type2;
   }
 
   if ((num_robots1 + num_robots2) > MAX_ROBOTS) {
     current_level = 0;
-    num_robots1 = game_config ()->initial_type1;
-    num_robots2 = game_config ()->initial_type2;
+    num_robots1 = game_config.initial_type1;
+    num_robots2 = game_config.initial_type2;
     message_box (_("Congratulations, You Have Defeated the Robots!! \nBut Can You do it Again?"));
     play_sound (SOUND_VICTORY);
   }
 
-  safe_teleports += game_config ()->free_safe_teleports;
+  safe_teleports += game_config.free_safe_teleports;
 
-  if (safe_teleports > game_config ()->max_safe_teleports) {
-    safe_teleports = game_config ()->max_safe_teleports;
+  if (safe_teleports > game_config.max_safe_teleports) {
+    safe_teleports = game_config.max_safe_teleports;
   }
 
   update_game_status (score, current_level, safe_teleports);
@@ -405,6 +408,9 @@ static void
 update_arena (void)
 {
   gint i, j;
+  GameConfig game_config;
+
+  game_configs_get_current (game_configs, &game_config);
 
   num_robots1 = 0;
   num_robots2 = 0;
@@ -419,13 +425,13 @@ update_arena (void)
           add_splat_bubble (i, j);
           play_sound (SOUND_SPLAT);
           push_xpos = push_ypos = -1;
-          score += game_config ()->score_type1_splatted;
+          score += game_config.score_type1_splatted;
         }
         if (arena[i][j] == OBJECT_ROBOT2) {
           add_splat_bubble (i, j);
           play_sound (SOUND_SPLAT);
           push_xpos = push_ypos = -1;
-          score += game_config ()->score_type2_splatted;
+          score += game_config.score_type2_splatted;
         }
       }
 
@@ -587,7 +593,7 @@ init_game (void)
 void
 start_new_game (void)
 {
-  GameConfig *conf;
+  GameConfig game_config;
   current_level = 0;
   score = 0;
   kills = 0;
@@ -596,10 +602,10 @@ start_new_game (void)
   if (game_state == STATE_PLAYING)
     log_score (score);
 
-  conf = game_config ();
-  g_return_if_fail (conf != NULL);
+  game_configs_get_current (game_configs, &game_config);
+  // g_return_if_fail (game_config != NULL);
 
-  safe_teleports = conf->initial_safe_teleports;
+  safe_teleports = game_config.initial_safe_teleports;
 
   remove_bubble ();
   reset_player_animation ();
@@ -901,6 +907,9 @@ static gboolean
 try_player_move (gint dx, gint dy)
 {
   gint nx, ny;
+  GameConfig game_config;
+
+  game_configs_get_current (game_configs, &game_config);
 
   nx = player_xpos + dx;
   ny = player_ypos + dy;
@@ -912,7 +921,7 @@ try_player_move (gint dx, gint dy)
   load_temp_arena ();
 
   if (temp_arena[nx][ny] == OBJECT_HEAP) {
-    if (game_config ()->moveable_heaps) {
+    if (game_config.moveable_heaps) {
       if (!push_heap (nx, ny, dx, dy)) {
         push_xpos = push_ypos = -1;
         return FALSE;
diff --git a/src/gnome-robots.c b/src/gnome-robots.c
index b173736..b42bccc 100644
--- a/src/gnome-robots.c
+++ b/src/gnome-robots.c
@@ -34,7 +34,7 @@
 #include <libgnome-games-support.h>
 
 #include "gbdefs.h"
-#include "gameconfig.h"
+#include "riiv.h"
 #include "graphics.h"
 #include "sound.h"
 #include "properties.h"
@@ -460,7 +460,8 @@ activate (GtkApplication *app, gpointer user_data)
 
   gtk_widget_show_all (window);
 
-  if (!load_game_configs ()) {
+  game_configs = game_configs_new_load (NULL);
+  if (!game_configs) {
     /* Oops, no configs, we probably haven't been installed properly. */
     errordialog = gtk_message_dialog_new_with_markup (NULL, 0, GTK_MESSAGE_ERROR,
                                                       GTK_BUTTONS_OK,
diff --git a/src/meson.build b/src/meson.build
index 085e9a1..3342577 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -1,13 +1,27 @@
+add_project_arguments(['--vapidir', meson.current_source_dir()], language: 'vala')
+
+
+config_header = configure_file(
+    output: 'config.h',
+    configuration: config_h
+)
+
+vapi_sources = files(
+    'config.vapi',
+)
+
 vala_sources = files(
     'image-suffix-list.vala',
     'file-list.vala',
     'find-file.vala',
     'preimage.vala',
     'controls.vala',
+    'game-config.vala',
 )
 
 vala_lib = static_library('riiv',
-    vala_sources,
+    config_header,
+    vapi_sources + vala_sources,
     dependencies: [
         gee_dependency,
         gio_dependency,
@@ -27,7 +41,6 @@ riiv_dependency = declare_dependency(
 sources = files(
     'cursors.c',
     'game.c',
-    'gameconfig.c',
     'gnome-robots.c',
     'graphics.c',
     'keyboard.c',
@@ -40,11 +53,6 @@ resources = gnome.compile_resources(
     source_dir: '../'
 )
 
-config_header = configure_file(
-    output: 'config.h',
-    configuration: config_h
-)
-
 executable(
     meson.project_name(),
     sources + resources,
diff --git a/src/properties.c b/src/properties.c
index d60c4cb..079196c 100644
--- a/src/properties.c
+++ b/src/properties.c
@@ -28,7 +28,6 @@
 #include <libgnome-games-support.h>
 
 #include "properties.h"
-#include "gameconfig.h"
 #include "gnome-robots.h"
 #include "graphics.h"
 #include "gbdefs.h"
@@ -37,6 +36,9 @@
 #include "riiv.h"
 
 
+GameConfigs* game_configs;
+
+
 /**********************************************************************/
 /* Defines                                                            */
 /**********************************************************************/
@@ -203,16 +205,19 @@ pmap_selection (GtkWidget * widget, gpointer data)
 static void
 type_selection (GtkWidget * widget, gpointer data)
 {
-  gchar *config;
+  GameConfig *config;
+  gchar *config_name;
   gint num = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
 
   properties.selected_config = num;
 
-  config = game_config_name (properties.selected_config);
-  conf_set_configuration (config);
-  g_free (config);
+  config = game_configs_get (game_configs, (guint)properties.selected_config);
+
+  config_name = game_config_name (config);
+  conf_set_configuration (config_name);
+  g_free (config_name);
 
-  set_game_config (properties.selected_config);
+  game_configs_set_current_index (game_configs, (guint)properties.selected_config);
 
   start_new_game ();
 }
@@ -310,8 +315,8 @@ fill_typemenu (GtkWidget * menu)
   gint i;
   gchar *config;
 
-  for (i = 0; i < num_game_configs (); ++i) {
-    config = game_config_name (i);
+  for (i = 0; i < game_configs_count (game_configs); ++i) {
+    config = game_configs_get_name (game_configs, (guint)i);
     gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (menu), _(config));
     g_free (config);
   }
@@ -565,8 +570,8 @@ load_properties (void)
   cname = g_settings_get_string (settings, KEY_CONFIGURATION);
 
   properties.selected_config = 0;
-  for (i = 0; i < num_game_configs (); ++i) {
-    config = game_config_name (i);
+  for (i = 0; i < game_configs_count (game_configs); ++i) {
+    config = game_configs_get_name (game_configs, (guint)i);
     if (!strcmp (cname, config)) {
       g_free (config);
       properties.selected_config = i;
@@ -582,7 +587,7 @@ load_properties (void)
   properties.show_toolbar     = g_settings_get_boolean (settings, KEY_SHOW_TOOLBAR);
 
   load_game_graphics ();
-  set_game_config (properties.selected_config);
+  game_configs_set_current_index (game_configs, (guint)properties.selected_config);
   keyboard_set (properties.keys);
   return TRUE;
 }
@@ -677,7 +682,7 @@ save_properties (void)
 
   conf_set_theme (properties.themename);
 
-  config = game_config_name (properties.selected_config);
+  config = game_configs_get_name (game_configs, (guint)properties.selected_config);
   conf_set_configuration (config);
   g_free (config);
 
@@ -766,9 +771,10 @@ properties_show_toolbar (void)
 gboolean
 properties_set_config (gint n)
 {
-  if (!set_game_config (n))
+  if (n >= game_configs_count (game_configs))
     return FALSE;
 
+  game_configs_set_current_index (game_configs, (guint)n);
   properties.selected_config = n;
 
   return TRUE;
diff --git a/src/properties.h b/src/properties.h
index aeceadf..0f9c7d1 100644
--- a/src/properties.h
+++ b/src/properties.h
@@ -1,6 +1,10 @@
 #ifndef PROPERTIES_H
 #define PROPERTIES_H
 
+#include "riiv.h"
+
+extern GameConfigs* game_configs;
+
 /**********************************************************************/
 /* Exported functions                                                 */
 /**********************************************************************/


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