[aisleriot] guile: Load games from %load-path



commit 5a5d567cca4ad1d984b4fed83d74e7efac1f5e62
Author: Christian Persch <chpe gnome org>
Date:   Sat Dec 3 00:20:25 2011 +0100

    guile: Load games from %load-path
    
    Instead of constructing the path directly, load the game with
    scm_primitive_load_path().
    
    Install the game files in a directory versioned with the effective
    guile version.
    
    Add a function to get the list of installed games, and use it in
    the game chooser.

 configure.ac                 |    2 +
 games/Makefile.am            |   13 ++---
 games/athena.scm             |    2 +-
 games/aunt-mary.scm          |    2 +-
 games/bakers-game.scm        |    2 +-
 games/gold-mine.scm          |    2 +-
 games/peek.scm               |    2 +-
 games/saratoga.scm           |    2 +-
 games/spider-three-decks.scm |    2 +-
 games/spiderette.scm         |    2 +-
 games/will-o-the-wisp.scm    |    2 +-
 src/ar-game-chooser.c        |   29 ++++-------
 src/game.c                   |   62 +++++++++++++++++++---
 src/game.h                   |    2 +
 src/window.c                 |  119 +++++++++++++++++++-----------------------
 15 files changed, 135 insertions(+), 110 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 0b6da51..4586b5a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -570,6 +570,8 @@ PKG_CHECK_MODULES([GUILE],[$GUILE_PKGS])
 
 AM_CONDITIONAL([HAVE_GUILE_2_X],[test "$with_guile" != "1.8"])
 
+AC_SUBST([GUILE_EFFECTIVE_VERSION],[$with_guile])
+
 AC_ARG_VAR([GUILE_TOOLS])
 AC_PATH_PROG([GUILE_TOOLS],[guile-tools],[false])
 if test "$GUILE_TOOLS" = "false"; then
diff --git a/games/Makefile.am b/games/Makefile.am
index a536d35..4c424f5 100644
--- a/games/Makefile.am
+++ b/games/Makefile.am
@@ -1,14 +1,13 @@
 NULL = 
 
-guiledir = $(pkgdatadir)/aisleriot
+pkgguiledir = $(pkgdatadir)/guile/$(GUILE_EFFECTIVE_VERSION)
 
-guile_DATA = \
+moduledir = $(pkgguiledir)/aisleriot
+module_DATA = \
 	api.scm \
 	$(NULL)
 
-rulesdir  = $(pkgdatadir)/games
-
-rules_DATA  = \
+pkgguile_DATA  = \
 	accordion.scm \
 	agnes.scm \
 	athena.scm \
@@ -100,8 +99,8 @@ rules_DATA  = \
 	$(NULL)
 
 EXTRA_DIST = \
-	$(rules_DATA) \
-	$(guile_DATA) \
+	$(pkgguile_DATA) \
+	$(module_DATA) \
 	template.scm \
 	Rules.HOWTO \
 	$(NULL)
diff --git a/games/athena.scm b/games/athena.scm
index f9ee71d..b988564 100644
--- a/games/athena.scm
+++ b/games/athena.scm
@@ -24,7 +24,7 @@
 ;; TODO rewrite in a way less redundant way and share code with Klondike
 ;; As seen in Pretty Good Solitaire 10  http://goodsol.com  2005.  
 
-(load "klondike.scm")
+(primitive-load-path "klondike")
 
 (define deal-one #t)
 (define deal-three #f)
diff --git a/games/aunt-mary.scm b/games/aunt-mary.scm
index 5504f0b..a28883e 100644
--- a/games/aunt-mary.scm
+++ b/games/aunt-mary.scm
@@ -17,7 +17,7 @@
 
 (use-modules (aisleriot interface) (aisleriot api))
 
-(load "klondike.scm") 
+(primitive-load-path "klondike") 
 
 (define deal-one #t)
 (define deal-three #f)
diff --git a/games/bakers-game.scm b/games/bakers-game.scm
index 19f0d60..5a9755f 100644
--- a/games/bakers-game.scm
+++ b/games/bakers-game.scm
@@ -16,7 +16,7 @@
 
 (use-modules (aisleriot interface) (aisleriot api))
 
-(load "freecell.scm")
+(primitive-load-path "freecell")
 
 (define (field-join? lower upper)
   (and (eq? (get-suit lower) (get-suit upper))
diff --git a/games/gold-mine.scm b/games/gold-mine.scm
index 717fdc5..08e99fb 100644
--- a/games/gold-mine.scm
+++ b/games/gold-mine.scm
@@ -16,7 +16,7 @@
 
 (use-modules (aisleriot interface) (aisleriot api))
 
-(load "klondike.scm")
+(primitive-load-path "klondike")
 
 (define deal-one #f)
 (define deal-three #t)
diff --git a/games/peek.scm b/games/peek.scm
index 3cd78c6..1482f58 100644
--- a/games/peek.scm
+++ b/games/peek.scm
@@ -16,7 +16,7 @@
 
 (use-modules (aisleriot interface) (aisleriot api))
 
-(load "osmosis.scm")
+(primitive-load-path "osmosis")
 
 (define (initial-deal)
   (deal-cards-face-up 8 '(0 2 4 6 0 2 4 6 0 2 4 6 0 2 4 6 1))
diff --git a/games/saratoga.scm b/games/saratoga.scm
index c8ed305..26a2e50 100644
--- a/games/saratoga.scm
+++ b/games/saratoga.scm
@@ -25,7 +25,7 @@
 
 (use-modules (aisleriot interface) (aisleriot api))
 
-(load "klondike.scm")
+(primitive-load-path "klondike")
 
 (define deal-one #t)
 (define deal-three #f)
diff --git a/games/spider-three-decks.scm b/games/spider-three-decks.scm
index 6039a59..d8fc943 100644
--- a/games/spider-three-decks.scm
+++ b/games/spider-three-decks.scm
@@ -16,7 +16,7 @@
 
 (use-modules (aisleriot interface) (aisleriot api))
 
-(load "spider.scm")
+(primitive-load-path "spider")
 
 (define tableau '(13 14 15 16 17 18 19 20 21 22 23 24))
 (define foundation '(1 2 3 4 5 6 7 8 9 10 11 12))
diff --git a/games/spiderette.scm b/games/spiderette.scm
index e8a110c..52bab0d 100644
--- a/games/spiderette.scm
+++ b/games/spiderette.scm
@@ -16,7 +16,7 @@
 
 (use-modules (aisleriot interface) (aisleriot api))
 
-(load "spider.scm")
+(primitive-load-path "spider")
 
 (define stock 0)
 (define foundation '(1 2 3 4))
diff --git a/games/will-o-the-wisp.scm b/games/will-o-the-wisp.scm
index ed857cd..7aa3f71 100644
--- a/games/will-o-the-wisp.scm
+++ b/games/will-o-the-wisp.scm
@@ -17,7 +17,7 @@
 (use-modules (aisleriot interface) (aisleriot api))
 
 
-(load "spider.scm")
+(primitive-load-path "spider")
 
 (define stock 0)
 (define foundation '(1 2 3 4))
diff --git a/src/ar-game-chooser.c b/src/ar-game-chooser.c
index ded04e8..95c555c 100644
--- a/src/ar-game-chooser.c
+++ b/src/ar-game-chooser.c
@@ -129,8 +129,8 @@ ar_game_chooser_constructor (GType type,
   GtkTreeIter current_iter;
   gboolean current_iter_set = FALSE;
   const char *current_game_module;
-  const char *games_dir;
-  GDir *dir;
+  char **games;
+  int i;
   GtkWidget *content_area;
   GtkDialog *dialog;
 
@@ -147,22 +147,14 @@ ar_game_chooser_constructor (GType type,
 
   current_game_module = aisleriot_window_get_game_module (priv->window);
 
-  games_dir = ar_runtime_get_directory (AR_RUNTIME_GAMES_DIRECTORY);
-
-  dir = g_dir_open (games_dir, 0, NULL);
-  if (dir != NULL) {
-    const char *game_file;
-
-    while ((game_file = g_dir_read_name (dir)) != NULL) {
-      char *game_name, *game_module;
+  games = ar_get_game_modules ();
+  if (games != NULL) {
+    for (i = 0; games[i]; ++i) {
+      const char *game_module = games[i];
+      char *game_name;
       GtkTreeIter iter;
 
-      if (!g_str_has_suffix (game_file, ".scm") ||
-          strcmp (game_file, "api.scm") == 0)
-        continue;
-
-      game_name = ar_filename_to_display_name (game_file);
-      game_module = ar_filename_to_game_module (game_file);
+      game_name = ar_filename_to_display_name (game_module);
 
       gtk_list_store_insert_with_values (GTK_LIST_STORE (list), &iter,
                                          -1,
@@ -177,12 +169,11 @@ ar_game_chooser_constructor (GType type,
       }
 
       g_free (game_name);
-      g_free (game_module);
     }
-
-    g_dir_close (dir);
   }
 
+  g_strfreev (games);
+
   /* Now construct the window contents */
   gtk_window_set_title (window, _("Select Game"));
   gtk_window_set_modal (window, TRUE);
diff --git a/src/game.c b/src/game.c
index e733481..87f2b48 100644
--- a/src/game.c
+++ b/src/game.c
@@ -47,6 +47,9 @@
 #ifndef SCM_MAJOR_VERSION
 #define SCM_MAJOR_VERSION 1
 #endif
+#ifndef SCM_EFFECTIVE_VERSION
+#define SCM_EFFECTIVE_VERSION "1.8"
+#endif
 
 struct _AisleriotGameClass
 {
@@ -1288,7 +1291,7 @@ aisleriot_game_class_init (AisleriotGameClass *klass)
   GType error_types[] = { G_TYPE_ERROR | G_SIGNAL_TYPE_STATIC_SCOPE };
   GType ptr_types[] = { G_TYPE_POINTER };
   SCM variable;
-  const char *path;
+  char *path;
 
   gobject_class->constructor = aisleriot_game_constructor;
   gobject_class->finalize = aisleriot_game_finalize;
@@ -1405,16 +1408,24 @@ aisleriot_game_class_init (AisleriotGameClass *klass)
   scm_c_define_module ("aisleriot interface", cscm_init, NULL);
 
   /* Append load-path */
-  path = ar_runtime_get_directory (AR_RUNTIME_PKG_DATA_DIRECTORY);
+  path = g_build_filename (ar_runtime_get_directory (AR_RUNTIME_PKG_DATA_DIRECTORY),
+                           "guile",
+                           SCM_EFFECTIVE_VERSION,
+                           NULL);
   variable = scm_c_module_lookup (scm_the_root_module (), "%load-path");
   scm_variable_set_x (variable, scm_append_x (scm_list_2 (scm_variable_ref (variable),
                                                           scm_list_1 (scm_from_locale_string (path)))));
+  g_free (path);
 
 #if SCM_MAJOR_VERSION >= 2
-  path = ar_runtime_get_directory (AR_RUNTIME_PKG_LIBRARY_DIRECTORY);
+  path = g_build_filename (ar_runtime_get_directory (AR_RUNTIME_PKG_LIBRARY_DIRECTORY),
+                           "guile",
+                           SCM_EFFECTIVE_VERSION,
+                           NULL);
   variable = scm_c_module_lookup (scm_the_root_module (), "%load-compiled-path");
   scm_variable_set_x (variable, scm_append_x (scm_list_2 (scm_variable_ref (variable),
                                                           scm_list_1 (scm_from_locale_string (path)))));
+  g_free (path);
 #endif
 }
 
@@ -1697,16 +1708,11 @@ game_scm_load_game (void *user_data)
 {
   AisleriotGame *game = app_game;
   const char *game_module = user_data;
-  char *game_file, *path;
   int i;
 
   scm_dynwind_begin (0);
 
-  game_file = g_strconcat (game_module, ".scm", NULL);
-  scm_dynwind_unwind_handler (g_free, game_file, SCM_F_WIND_EXPLICITLY);
-  path = ar_runtime_get_file (AR_RUNTIME_GAMES_DIRECTORY, game_file);
-  scm_dynwind_unwind_handler (g_free, path, SCM_F_WIND_EXPLICITLY);
-  scm_c_primitive_load (path);
+  scm_primitive_load_path (scm_from_locale_string (game_module));
 
   for (i = 0; i <= LAST_MANDATORY_LAMBDA; ++i) {
     if (scm_is_false (scm_procedure_p (game->lambdas[i]))) {
@@ -2622,3 +2628,41 @@ aisleriot_game_reset_old_cards (ArSlot *slot)
 }
 
 #endif /* HAVE_CLUTTER */
+
+/**
+ * ar_get_game_modules:
+ * 
+ * Returns: (tranfer full): the list of available games
+ */
+char **
+ar_get_game_modules (void)
+{
+  char *path;
+  const char *filename;
+  GDir *dir;
+  GPtrArray *array;
+
+  path = g_build_filename (ar_runtime_get_directory (AR_RUNTIME_PKG_DATA_DIRECTORY),
+                           "guile",
+                           SCM_EFFECTIVE_VERSION,
+                           NULL);
+  dir = g_dir_open (path, 0, NULL);
+  g_free (path);
+  if (dir == NULL)
+    return NULL;
+
+  array = g_ptr_array_new ();
+
+  while ((filename = g_dir_read_name (dir)) != NULL) {
+    if (!g_str_has_suffix (filename, ".scm") ||
+        strcmp (filename, "api.scm") == 0)
+      continue;
+
+    g_ptr_array_add (array, ar_filename_to_game_module (filename));
+  }
+
+  g_ptr_array_sort (array, (GCompareFunc) strcmp);
+  g_ptr_array_add (array, NULL);
+
+  return (char **) g_ptr_array_free (array, FALSE);
+}
diff --git a/src/game.h b/src/game.h
index 8143f9f..1d96a4f 100644
--- a/src/game.h
+++ b/src/game.h
@@ -243,6 +243,8 @@ void aisleriot_game_get_card_offset (ArSlot *slot,
 
 void aisleriot_game_reset_old_cards (ArSlot *slot);
 
+char **ar_get_game_modules (void);
+
 G_END_DECLS
 
 #endif /* !AISLERIOT_GAME_H */
diff --git a/src/window.c b/src/window.c
index 0948848..c9bec1e 100644
--- a/src/window.c
+++ b/src/window.c
@@ -573,15 +573,16 @@ debug_exception_cb (GtkAction *action,
 
 typedef struct {
   AisleriotWindow *window;
-  GList *games_list;
-  GList *current_game;
+  char **games;
+  int n_games;
+  int current;
 } DebugWindowData;
 
 static void
 debug_data_free (DebugWindowData *data)
 {
-  g_list_foreach (data->games_list, (GFunc) g_free, NULL);
-  g_list_free (data->games_list);
+  g_strfreev (data->games);
+
   g_slice_free (DebugWindowData, data);
 }
 
@@ -590,37 +591,37 @@ debug_ensure_game_list (AisleriotWindow *window)
 {
   AisleriotWindowPrivate *priv = window->priv;
   DebugWindowData *data;
-  GDir *dir;
-  GList *list = NULL;
-  const char *games_dir;
+  char **games;
+  int n_games;
+  const char *current_game_module;
+  int i;
 
   data = g_object_get_data (G_OBJECT (window), DEBUG_WINDOW_DATA_KEY);
   if (data != NULL)
     return data;
 
-  games_dir = ar_runtime_get_directory (AR_RUNTIME_GAMES_DIRECTORY);
-  dir = g_dir_open (games_dir, 0, NULL);
-  if (dir != NULL) {
-    const char *game_file;
-
-    while ((game_file = g_dir_read_name (dir)) != NULL) {
-      if (!g_str_has_suffix (game_file, ".scm") ||
-          strcmp (game_file, "api.scm") == 0)
-        continue;
-
-      list = g_list_prepend (list, ar_filename_to_game_module (game_file));
-    }
+  games = ar_get_game_modules ();
+  if (games == NULL)
+    return NULL;
 
-    list = g_list_sort (list, (GCompareFunc) strcmp);
-    g_dir_close (dir);
+  n_games = g_strv_length (games);
+  if (n_games == 0) {
+    g_strfreev (games);
+    return NULL;
   }
 
-  data = g_slice_new (DebugWindowData);
   data->window = window;
-  data->games_list = list;
-  data->current_game = g_list_find_custom (data->games_list,
-                                           aisleriot_game_get_game_module (priv->game),
-                                           (GCompareFunc) strcmp);
+  data->games = games;
+  data->n_games = n_games;
+  data->current = -1;
+
+  current_game_module = aisleriot_game_get_game_module (priv->game);
+  for (i = 0; data->games[i]; ++i) {
+    if (strcmp (data->games[i], current_game_module) == 0) {
+      data->current = i;
+      break;
+    }
+  }
 
   g_object_set_data_full (G_OBJECT (window), DEBUG_WINDOW_DATA_KEY,
                           data, (GDestroyNotify) debug_data_free);
@@ -629,35 +630,31 @@ debug_ensure_game_list (AisleriotWindow *window)
 }
 
 static gboolean
-debug_cycle_timeout_cb (AisleriotWindow *window)
+debug_cycle_timeout_cb (DebugWindowData *data)
 {
-  DebugWindowData *data;
-  char *game_module;
+  if (data->current >= -1)
+    data->current++;
 
-  data = debug_ensure_game_list (window);
-  if (data->current_game != NULL) {
-    data->current_game = data->current_game->next;
-    /* We're done */
-    if (!data->current_game)
-      return FALSE;
-  }
-  if (!data->current_game) {
-    data->current_game = data->games_list;
-  }
-  if (!data->current_game)
+  /* We're done */
+  if (data->current >= data->n_games)
     return FALSE;
 
-  game_module = data->current_game->data;  
-  aisleriot_window_set_game_module (data->window, game_module, NULL);
+  aisleriot_window_set_game_module (data->window, data->games[data->current], NULL);
 
-  return TRUE;
+  return TRUE; /* run again */
 }
 
 static void
 debug_cycle_cb (GtkAction *action,
                 AisleriotWindow *window)
 {
-  g_timeout_add (500, (GSourceFunc) debug_cycle_timeout_cb, window);
+  DebugWindowData *data;
+
+  data = debug_ensure_game_list (window);
+  if (data == NULL)
+    return;
+
+  g_timeout_add (500, (GSourceFunc) debug_cycle_timeout_cb, data);
 }
 
 static void
@@ -667,11 +664,11 @@ debug_game_first (GtkAction *action,
   DebugWindowData *data;
 
   data = debug_ensure_game_list (window);
-  data->current_game = data->games_list;
-  if (!data->current_game)
+  if (data == NULL)
     return;
 
-  aisleriot_window_set_game_module (data->window, (const char *) data->current_game->data, NULL);
+  data->current = 0;
+  aisleriot_window_set_game_module (data->window, data->games[data->current], NULL);
 }
 
 static void
@@ -681,11 +678,11 @@ debug_game_last (GtkAction *action,
   DebugWindowData *data;
 
   data = debug_ensure_game_list (window);
-  data->current_game = g_list_last (data->games_list);
-  if (!data->current_game)
+  if (data == NULL)
     return;
 
-  aisleriot_window_set_game_module (data->window, (const char *) data->current_game->data, NULL);
+  data->current = data->n_games - 1;
+  aisleriot_window_set_game_module (data->window, data->games[data->current], NULL);
 }
 
 static void
@@ -695,16 +692,11 @@ debug_game_next (GtkAction *action,
   DebugWindowData *data;
 
   data = debug_ensure_game_list (window);
-  if (data->current_game) {
-    data->current_game = data->current_game->next;
-  }
-  if (!data->current_game) {
-    data->current_game = data->games_list;
-  }
-  if (!data->current_game)
+  if (data == NULL || data->current + 1 == data->n_games)
     return;
 
-  aisleriot_window_set_game_module (data->window, (const char *) data->current_game->data, NULL);
+  data->current++;
+  aisleriot_window_set_game_module (data->window, data->games[data->current], NULL);
 }
 
 static void
@@ -714,16 +706,11 @@ debug_game_prev (GtkAction *action,
   DebugWindowData *data;
 
   data = debug_ensure_game_list (window);
-  if (data->current_game) {
-    data->current_game = data->current_game->prev;
-  }
-  if (!data->current_game) {
-    data->current_game = data->games_list;
-  }
-  if (!data->current_game)
+  if (data == NULL || data->current == 0)
     return;
 
-  aisleriot_window_set_game_module (data->window, (const char *) data->current_game->data, NULL);
+  data->current--;
+  aisleriot_window_set_game_module (data->window, data->games[data->current], NULL);
 }
 
 static void



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