Commit 5a5d567c authored by Christian Persch's avatar Christian Persch

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.
parent a2fd20bc
......@@ -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
......
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)
......
......@@ -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)
......
......@@ -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)
......
......@@ -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))
......
......@@ -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)
......
......@@ -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))
......
......@@ -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)
......
......@@ -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))
......
......@@ -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))
......
......@@ -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))
......
......@@ -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);
......
......@@ -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);
}
......@@ -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 */
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment