chiark / gitweb /
Rather than each game backend file exporting a whole load of
authorSimon Tatham <anakin@pobox.com>
Mon, 17 Jan 2005 13:48:57 +0000 (13:48 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 17 Jan 2005 13:48:57 +0000 (13:48 +0000)
functions and a couple of variables, now each one exports a single
structure containing a load of function pointers and said variables.
This should make it easy to support platforms on which it's sensible
to compile all the puzzles into a single monolithic application. The
two existing platforms are still one-binary-per-game.

[originally from svn r5126]

12 files changed:
cube.c
fifteen.c
gtk.c
midend.c
net.c
netslide.c
nullgame.c
pattern.c
puzzles.h
rect.c
sixteen.c
windows.c

diff --git a/cube.c b/cube.c
index d5221e645e00f901411cecb4aba50add7a358235..71c56d8a01d81c02b9546ded68b374731fae4b18 100644 (file)
--- a/cube.c
+++ b/cube.c
 
 #include "puzzles.h"
 
-const char *const game_name = "Cube";
-const char *const game_winhelp_topic = "games.cube";
-const int game_can_configure = TRUE;
-
 #define MAXVERTICES 20
 #define MAXFACES 20
 #define MAXORDER 4
@@ -215,7 +211,7 @@ struct game_state {
     int movecount;
 };
 
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -226,7 +222,7 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret = snew(game_params);
     char *str;
@@ -266,19 +262,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
     return TRUE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = default_params();
 
@@ -299,7 +295,7 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     char data[256];
 
@@ -477,7 +473,7 @@ static int grid_area(int d1, int d2, int order)
         return d1*d1 + d2*d2 + 4*d1*d2;
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     config_item *ret = snewn(4, config_item);
     char buf[80];
@@ -507,7 +503,7 @@ config_item *game_configure(game_params *params)
     return ret;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -533,7 +529,7 @@ static void count_grid_square_callback(void *ctx, struct grid_square *sq)
     classes[thisclass]++;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     int classes[5];
     int i;
@@ -593,7 +589,7 @@ static void classify_grid_square_callback(void *ctx, struct grid_square *sq)
        data->squareindex++;
 }
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     struct grid_data data;
     int i, j, k, m, area, facesperclass;
@@ -842,7 +838,7 @@ static struct solid *transform_poly(const struct solid *solid, int flip,
     return ret;
 }
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     int area = grid_area(params->d1, params->d2, solids[params->solid]->order);
     int i, j;
@@ -870,7 +866,7 @@ char *validate_seed(game_params *params, char *seed)
     return NULL;
 }
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     game_state *state = snew(game_state);
     int area;
@@ -949,7 +945,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -978,21 +974,22 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state);
 }
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     return NULL;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
 }
 
-game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *from, game_ui *ui,
+                            int x, int y, int button)
 {
     int direction;
     int pkey[2], skey[2], dkey[2];
@@ -1309,14 +1306,14 @@ static struct bbox find_bbox(game_params *params)
     return bb;
 }
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     struct bbox bb = find_bbox(params);
     *x = (int)((bb.r - bb.l + 2*solids[params->solid]->border) * GRID_SCALE);
     *y = (int)((bb.d - bb.u + 2*solids[params->solid]->border) * GRID_SCALE);
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
 
@@ -1334,7 +1331,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
     return ret;
 }
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     struct bbox bb = find_bbox(&state->params);
@@ -1345,12 +1342,12 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                  game_state *state, int dir, game_ui *ui,
                  float animtime, float flashtime)
 {
@@ -1512,17 +1509,52 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     }
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate,
+                             game_state *newstate, int dir)
 {
     return ROLLTIME;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate,
+                              game_state *newstate, int dir)
 {
     return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return TRUE;
 }
+
+#ifdef COMBINED
+#define thegame cube
+#endif
+
+const struct game thegame = {
+    "Cube", "games.cube", TRUE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
index f6ff24ac2f81fcbf305332dfc20dd5e9c101fc73..2263bc1a1998b744d9283a66a12ba8df93c61156 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
 
 #include "puzzles.h"
 
-const char *const game_name = "Fifteen";
-const char *const game_winhelp_topic = "games.fifteen";
-const int game_can_configure = TRUE;
-
 #define TILE_SIZE 48
 #define BORDER    (TILE_SIZE / 2)
 #define HIGHLIGHT_WIDTH (TILE_SIZE / 20)
@@ -48,7 +44,7 @@ struct game_state {
     int movecount;
 };
 
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -57,24 +53,24 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     return FALSE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = default_params();
 
@@ -88,7 +84,7 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     char data[256];
 
@@ -97,7 +93,7 @@ char *encode_params(game_params *params)
     return dupstr(data);
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -124,7 +120,7 @@ config_item *game_configure(game_params *params)
     return ret;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -134,7 +130,7 @@ game_params *custom_params(config_item *cfg)
     return ret;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     if (params->w < 2 && params->h < 2)
        return "Width and height must both be at least two";
@@ -142,7 +138,7 @@ char *validate_params(game_params *params)
     return NULL;
 }
 
-int perm_parity(int *perm, int n)
+static int perm_parity(int *perm, int n)
 {
     int i, j, ret;
 
@@ -156,7 +152,7 @@ int perm_parity(int *perm, int n)
     return ret;
 }
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     int gap, n, i, x;
     int x1, x2, p1, p2, parity;
@@ -271,7 +267,7 @@ char *new_game_seed(game_params *params, random_state *rs)
     return ret;
 }
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     char *p, *err;
     int i, area;
@@ -322,7 +318,7 @@ char *validate_seed(game_params *params, char *seed)
     return err;
 }
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     game_state *state = snew(game_state);
     int i;
@@ -353,7 +349,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -369,21 +365,22 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state);
 }
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     return NULL;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
 }
 
-game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *from, game_ui *ui,
+                            int x, int y, int button)
 {
     int gx, gy, dx, dy, ux, uy, up, p;
     game_state *ret;
@@ -457,13 +454,13 @@ struct game_drawstate {
     int *tiles;
 };
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     *x = TILE_SIZE * params->w + 2 * BORDER;
     *y = TILE_SIZE * params->h + 2 * BORDER;
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
     int i;
@@ -494,7 +491,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
     return ret;
 }
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -510,7 +507,7 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds->tiles);
     sfree(ds);
@@ -552,7 +549,7 @@ static void draw_tile(frontend *fe, game_state *state, int x, int y,
     draw_update(fe, x, y, TILE_SIZE, TILE_SIZE);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                  game_state *state, int dir, game_ui *ui,
                  float animtime, float flashtime)
 {
@@ -702,12 +699,14 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     }
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate,
+                             game_state *newstate, int dir)
 {
     return ANIM_TIME;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate,
+                              game_state *newstate, int dir)
 {
     if (!oldstate->completed && newstate->completed)
         return 2 * FLASH_FRAME;
@@ -715,7 +714,40 @@ float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
         return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return TRUE;
 }
+
+#ifdef COMBINED
+#define thegame fifteen
+#endif
+
+const struct game thegame = {
+    "Fifteen", "games.fifteen", TRUE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
diff --git a/gtk.c b/gtk.c
index d27f739cde07bec9a13b1c68e84c2c30bdff1f32..3c777af15c8fe067d7dd61f14c578f780803b639 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -783,7 +783,7 @@ static frontend *new_window(char *game_id, char **error)
 
     fe = snew(frontend);
 
-    fe->me = midend_new(fe);
+    fe->me = midend_new(fe, &thegame);
     if (game_id) {
         *error = midend_game_id(fe->me, game_id, FALSE);
         if (*error) {
@@ -795,7 +795,7 @@ static frontend *new_window(char *game_id, char **error)
     midend_new_game(fe->me);
 
     fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
-    gtk_window_set_title(GTK_WINDOW(fe->window), game_name);
+    gtk_window_set_title(GTK_WINDOW(fe->window), thegame.name);
 #if 0
     gtk_window_set_resizable(GTK_WINDOW(fe->window), FALSE);
 #else
@@ -827,7 +827,7 @@ static frontend *new_window(char *game_id, char **error)
                       GTK_SIGNAL_FUNC(menu_config_event), fe);
     gtk_widget_show(menuitem);
 
-    if ((n = midend_num_presets(fe->me)) > 0 || game_can_configure) {
+    if ((n = midend_num_presets(fe->me)) > 0 || thegame.can_configure) {
         GtkWidget *submenu;
         int i;
 
@@ -852,7 +852,7 @@ static frontend *new_window(char *game_id, char **error)
             gtk_widget_show(menuitem);
         }
 
-       if (game_can_configure) {
+       if (thegame.can_configure) {
             menuitem = gtk_menu_item_new_with_label("Custom...");
             gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
                                GPOINTER_TO_INT(CFG_SETTINGS));
index 4636fa00f606efb8f15b44ec117aa8e1566b3dcb..a28f3dbf37d548c0d98387a3f0ee8b194c1babb1 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -14,6 +14,7 @@
 struct midend_data {
     frontend *frontend;
     random_state *random;
+    const game *ourgame;
 
     char *seed;
     int fresh_seed;
@@ -40,7 +41,7 @@ struct midend_data {
     } \
 } while (0)
 
-midend_data *midend_new(frontend *fe)
+midend_data *midend_new(frontend *fe, const game *ourgame)
 {
     midend_data *me = snew(midend_data);
     void *randseed;
@@ -49,10 +50,11 @@ midend_data *midend_new(frontend *fe)
     get_random_seed(&randseed, &randseedsize);
 
     me->frontend = fe;
+    me->ourgame = ourgame;
     me->random = random_init(randseed, randseedsize);
     me->nstates = me->statesize = me->statepos = 0;
     me->states = NULL;
-    me->params = default_params();
+    me->params = ourgame->default_params();
     me->seed = NULL;
     me->fresh_seed = FALSE;
     me->drawstate = NULL;
@@ -74,53 +76,53 @@ void midend_free(midend_data *me)
 {
     sfree(me->states);
     sfree(me->seed);
-    free_params(me->params);
+    me->ourgame->free_params(me->params);
     sfree(me);
 }
 
 void midend_size(midend_data *me, int *x, int *y)
 {
-    game_size(me->params, x, y);
+    me->ourgame->size(me->params, x, y);
 }
 
 void midend_set_params(midend_data *me, game_params *params)
 {
-    free_params(me->params);
-    me->params = dup_params(params);
+    me->ourgame->free_params(me->params);
+    me->params = me->ourgame->dup_params(params);
 }
 
 void midend_new_game(midend_data *me)
 {
     while (me->nstates > 0)
-       free_game(me->states[--me->nstates]);
+       me->ourgame->free_game(me->states[--me->nstates]);
 
     if (me->drawstate)
-        game_free_drawstate(me->drawstate);
+        me->ourgame->free_drawstate(me->drawstate);
 
     assert(me->nstates == 0);
 
     if (!me->fresh_seed) {
        sfree(me->seed);
-       me->seed = new_game_seed(me->params, me->random);
+       me->seed = me->ourgame->new_seed(me->params, me->random);
     } else
        me->fresh_seed = FALSE;
 
     ensure(me);
-    me->states[me->nstates++] = new_game(me->params, me->seed);
+    me->states[me->nstates++] = me->ourgame->new_game(me->params, me->seed);
     me->statepos = 1;
-    me->drawstate = game_new_drawstate(me->states[0]);
+    me->drawstate = me->ourgame->new_drawstate(me->states[0]);
     if (me->ui)
-        free_ui(me->ui);
-    me->ui = new_ui(me->states[0]);
+        me->ourgame->free_ui(me->ui);
+    me->ui = me->ourgame->new_ui(me->states[0]);
 }
 
 void midend_restart_game(midend_data *me)
 {
     while (me->nstates > 1)
-       free_game(me->states[--me->nstates]);
+       me->ourgame->free_game(me->states[--me->nstates]);
     me->statepos = me->nstates;
-    free_ui(me->ui);
-    me->ui = new_ui(me->states[0]);
+    me->ourgame->free_ui(me->ui);
+    me->ui = me->ourgame->new_ui(me->states[0]);
 }
 
 static int midend_undo(midend_data *me)
@@ -148,10 +150,10 @@ static void midend_finish_move(midend_data *me)
     float flashtime;
 
     if (me->oldstate || me->statepos > 1) {
-       flashtime = game_flash_length(me->oldstate ? me->oldstate :
-                                     me->states[me->statepos-2],
-                                     me->states[me->statepos-1],
-                                      me->oldstate ? me->dir : +1);
+       flashtime = me->ourgame->flash_length(me->oldstate ? me->oldstate :
+                                             me->states[me->statepos-2],
+                                             me->states[me->statepos-1],
+                                             me->oldstate ? me->dir : +1);
        if (flashtime > 0) {
            me->flash_pos = 0.0F;
            me->flash_time = flashtime;
@@ -159,7 +161,7 @@ static void midend_finish_move(midend_data *me)
     }
 
     if (me->oldstate)
-       free_game(me->oldstate);
+       me->ourgame->free_game(me->oldstate);
     me->oldstate = NULL;
     me->anim_pos = me->anim_time = 0;
     me->dir = 0;
@@ -180,7 +182,7 @@ static void midend_stop_anim(midend_data *me)
 
 int midend_process_key(midend_data *me, int x, int y, int button)
 {
-    game_state *oldstate = dup_game(me->states[me->statepos - 1]);
+    game_state *oldstate = me->ourgame->dup_game(me->states[me->statepos - 1]);
     float anim_time;
 
     if (button == 'n' || button == 'N' || button == '\x0E') {
@@ -203,11 +205,11 @@ int midend_process_key(midend_data *me, int x, int y, int button)
        if (!midend_redo(me))
             return 1;
     } else if (button == 'q' || button == 'Q' || button == '\x11') {
-       free_game(oldstate);
+       me->ourgame->free_game(oldstate);
         return 0;
     } else {
-        game_state *s = make_move(me->states[me->statepos-1], me->ui,
-                                  x, y, button);
+        game_state *s = me->ourgame->make_move(me->states[me->statepos-1],
+                                              me->ui, x, y, button);
 
         if (s == me->states[me->statepos-1]) {
             /*
@@ -220,13 +222,13 @@ int midend_process_key(midend_data *me, int x, int y, int button)
         } else if (s) {
            midend_stop_anim(me);
             while (me->nstates > me->statepos)
-                free_game(me->states[--me->nstates]);
+                me->ourgame->free_game(me->states[--me->nstates]);
             ensure(me);
             me->states[me->nstates] = s;
             me->statepos = ++me->nstates;
             me->dir = +1;
         } else {
-            free_game(oldstate);
+            me->ourgame->free_game(oldstate);
             return 1;
         }
     }
@@ -234,7 +236,8 @@ int midend_process_key(midend_data *me, int x, int y, int button)
     /*
      * See if this move requires an animation.
      */
-    anim_time = game_anim_length(oldstate, me->states[me->statepos-1], me->dir);
+    anim_time = me->ourgame->anim_length(oldstate, me->states[me->statepos-1],
+                                        me->dir);
 
     me->oldstate = oldstate;
     if (anim_time > 0) {
@@ -259,13 +262,13 @@ void midend_redraw(midend_data *me)
         if (me->oldstate && me->anim_time > 0 &&
             me->anim_pos < me->anim_time) {
             assert(me->dir != 0);
-            game_redraw(me->frontend, me->drawstate, me->oldstate,
-                        me->states[me->statepos-1], me->dir,
-                        me->ui, me->anim_pos, me->flash_pos);
+            me->ourgame->redraw(me->frontend, me->drawstate, me->oldstate,
+                               me->states[me->statepos-1], me->dir,
+                               me->ui, me->anim_pos, me->flash_pos);
         } else {
-            game_redraw(me->frontend, me->drawstate, NULL,
-                        me->states[me->statepos-1], +1 /*shrug*/,
-                        me->ui, 0.0, me->flash_pos);
+            me->ourgame->redraw(me->frontend, me->drawstate, NULL,
+                               me->states[me->statepos-1], +1 /*shrug*/,
+                               me->ui, 0.0, me->flash_pos);
         }
         end_draw(me->frontend);
     }
@@ -294,16 +297,16 @@ float *midend_colours(midend_data *me, int *ncolours)
     float *ret;
 
     if (me->nstates == 0) {
-        char *seed = new_game_seed(me->params, me->random);
-        state = new_game(me->params, seed);
+        char *seed = me->ourgame->new_seed(me->params, me->random);
+        state = me->ourgame->new_game(me->params, seed);
         sfree(seed);
     } else
         state = me->states[0];
 
-    ret = game_colours(me->frontend, state, ncolours);
+    ret = me->ourgame->colours(me->frontend, state, ncolours);
 
     if (me->nstates == 0)
-        free_game(state);
+        me->ourgame->free_game(state);
 
     return ret;
 }
@@ -314,7 +317,7 @@ int midend_num_presets(midend_data *me)
         char *name;
         game_params *preset;
 
-        while (game_fetch_preset(me->npresets, &name, &preset)) {
+        while (me->ourgame->fetch_preset(me->npresets, &name, &preset)) {
             if (me->presetsize <= me->npresets) {
                 me->presetsize = me->npresets + 10;
                 me->presets = sresize(me->presets, me->presetsize,
@@ -342,7 +345,7 @@ void midend_fetch_preset(midend_data *me, int n,
 
 int midend_wants_statusbar(midend_data *me)
 {
-    return game_wants_statusbar();
+    return me->ourgame->wants_statusbar();
 }
 
 config_item *midend_get_config(midend_data *me, int which, char **wintitle)
@@ -350,15 +353,15 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle)
     char *titlebuf, *parstr;
     config_item *ret;
 
-    titlebuf = snewn(40 + strlen(game_name), char);
+    titlebuf = snewn(40 + strlen(me->ourgame->name), char);
 
     switch (which) {
       case CFG_SETTINGS:
-       sprintf(titlebuf, "%s configuration", game_name);
+       sprintf(titlebuf, "%s configuration", me->ourgame->name);
        *wintitle = dupstr(titlebuf);
-       return game_configure(me->params);
+       return me->ourgame->configure(me->params);
       case CFG_SEED:
-       sprintf(titlebuf, "%s game selection", game_name);
+       sprintf(titlebuf, "%s game selection", me->ourgame->name);
        *wintitle = dupstr(titlebuf);
 
        ret = snewn(2, config_item);
@@ -371,7 +374,7 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle)
          * parameters, plus a colon, plus the game seed. This is a
          * full game ID.
          */
-        parstr = encode_params(me->params);
+        parstr = me->ourgame->encode_params(me->params);
         ret[0].sval = snewn(strlen(parstr) + strlen(me->seed) + 2, char);
         sprintf(ret[0].sval, "%s:%s", parstr, me->seed);
         sfree(parstr);
@@ -417,18 +420,18 @@ char *midend_game_id(midend_data *me, char *id, int def_seed)
     }
 
     if (par) {
-        params = decode_params(par);
-        error = validate_params(params);
+        params = me->ourgame->decode_params(par);
+        error = me->ourgame->validate_params(params);
         if (error) {
-            free_params(params);
+            me->ourgame->free_params(params);
             return error;
         }
-        free_params(me->params);
+        me->ourgame->free_params(me->params);
         me->params = params;
     }
 
     if (seed) {
-        error = validate_seed(me->params, seed);
+        error = me->ourgame->validate_seed(me->params, seed);
         if (error)
             return error;
 
@@ -447,15 +450,15 @@ char *midend_set_config(midend_data *me, int which, config_item *cfg)
 
     switch (which) {
       case CFG_SETTINGS:
-       params = custom_params(cfg);
-       error = validate_params(params);
+       params = me->ourgame->custom_params(cfg);
+       error = me->ourgame->validate_params(params);
 
        if (error) {
-           free_params(params);
+           me->ourgame->free_params(params);
            return error;
        }
 
-       free_params(me->params);
+       me->ourgame->free_params(me->params);
        me->params = params;
        break;
 
diff --git a/net.c b/net.c
index 6849dbcdb686edb92d242e1821cef6369bbdbfe9..7b3a501bac49a921437c9d5768877e7b3988aa5a 100644 (file)
--- a/net.c
+++ b/net.c
 #include "puzzles.h"
 #include "tree234.h"
 
-const char *const game_name = "Net";
-const char *const game_winhelp_topic = "games.net";
-const int game_can_configure = TRUE;
-
 #define PI 3.141592653589793238462643383279502884197169399
 
 #define MATMUL(xr,yr,m,x,y) do { \
@@ -127,7 +123,7 @@ static struct xyd *new_xyd(int x, int y, int direction)
 /* ----------------------------------------------------------------------
  * Manage game parameters.
  */
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -139,7 +135,7 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     char str[80];
@@ -173,19 +169,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
     return TRUE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = default_params();
     char const *p = string;
@@ -207,7 +203,7 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     char ret[400];
     int len;
@@ -223,7 +219,7 @@ char *encode_params(game_params *params)
     return dupstr(ret);
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -261,7 +257,7 @@ config_item *game_configure(game_params *params)
     return ret;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -273,7 +269,7 @@ game_params *custom_params(config_item *cfg)
     return ret;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     if (params->width <= 0 && params->height <= 0)
        return "Width and height must both be greater than zero";
@@ -294,7 +290,7 @@ char *validate_params(game_params *params)
  * Randomly select a new game seed.
  */
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     /*
      * The full description of a Net game is far too large to
@@ -312,7 +308,7 @@ char *new_game_seed(game_params *params, random_state *rs)
     return dupstr(buf);
 }
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     /*
      * Since any string at all will suffice to seed the RNG, there
@@ -325,7 +321,7 @@ char *validate_seed(game_params *params, char *seed)
  * Construct an initial game state, given a seed and parameters.
  */
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     random_state *rs;
     game_state *state;
@@ -676,7 +672,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret;
 
@@ -696,7 +692,7 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state->tiles);
     sfree(state->barriers);
@@ -770,7 +766,7 @@ struct game_ui {
     random_state *rs; /* used for jumbling */
 };
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     void *seed;
     int seedsize;
@@ -785,7 +781,7 @@ game_ui *new_ui(game_state *state)
     return ui;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
     random_free(ui->rs);
     sfree(ui);
@@ -794,7 +790,8 @@ void free_ui(game_ui *ui)
 /* ----------------------------------------------------------------------
  * Process a move.
  */
-game_state *make_move(game_state *state, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *state, game_ui *ui,
+                            int x, int y, int button)
 {
     game_state *ret, *nullret;
     int tx, ty, orig;
@@ -951,7 +948,7 @@ struct game_drawstate {
     unsigned char *visible;
 };
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     game_drawstate *ds = snew(game_drawstate);
 
@@ -964,19 +961,19 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds->visible);
     sfree(ds);
 }
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     *x = WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER;
     *y = WINDOW_OFFSET * 2 + TILE_SIZE * params->height + TILE_BORDER;
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret;
 
@@ -1284,7 +1281,7 @@ static void draw_tile(frontend *fe, game_state *state, int x, int y, int tile,
     draw_update(fe, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                  game_state *state, int dir, game_ui *ui, float t, float ft)
 {
     int x, y, tx, ty, frame, last_rotate_dir;
@@ -1436,7 +1433,8 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     sfree(active);
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate,
+                             game_state *newstate, int dir)
 {
     int x, y, last_rotate_dir;
 
@@ -1462,7 +1460,8 @@ float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
     return 0.0F;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate,
+                              game_state *newstate, int dir)
 {
     /*
      * If the game has just been completed, we display a completion
@@ -1485,7 +1484,40 @@ float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
     return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return TRUE;
 }
+
+#ifdef COMBINED
+#define thegame net
+#endif
+
+const struct game thegame = {
+    "Net", "games.net", TRUE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
index ec40852e06ca6051722dab1dd8fbe70138abfb0d..aee6e245390d5af23724ad15c0ff1681677c803a 100644 (file)
 #include "puzzles.h"
 #include "tree234.h"
 
-const char *const game_name = "Netslide";
-const char *const game_winhelp_topic = "games.netslide";
-const int game_can_configure = TRUE;
-
 #define PI 3.141592653589793238462643383279502884197169399
 
 #define MATMUL(xr,yr,m,x,y) do { \
@@ -139,13 +135,13 @@ static struct xyd *new_xyd(int x, int y, int direction)
     return xyd;
 }
 
-void slide_col(game_state *state, int dir, int col);
-void slide_row(game_state *state, int dir, int row);
+static void slide_col(game_state *state, int dir, int col);
+static void slide_row(game_state *state, int dir, int row);
 
 /* ----------------------------------------------------------------------
  * Manage game parameters.
  */
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -157,7 +153,7 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     char str[80];
@@ -190,19 +186,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
     return TRUE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = default_params();
     char const *p = string;
@@ -227,7 +223,7 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     char ret[400];
     int len;
@@ -243,7 +239,7 @@ char *encode_params(game_params *params)
     return dupstr(ret);
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -281,7 +277,7 @@ config_item *game_configure(game_params *params)
     return ret;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -293,7 +289,7 @@ game_params *custom_params(config_item *cfg)
     return ret;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     if (params->width <= 1 && params->height <= 1)
        return "Width and height must both be greater than one";
@@ -312,7 +308,7 @@ char *validate_params(game_params *params)
  * Randomly select a new game seed.
  */
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     /*
      * The full description of a Net game is far too large to
@@ -330,7 +326,7 @@ char *new_game_seed(game_params *params, random_state *rs)
     return dupstr(buf);
 }
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     /*
      * Since any string at all will suffice to seed the RNG, there
@@ -343,7 +339,7 @@ char *validate_seed(game_params *params, char *seed)
  * Construct an initial game state, given a seed and parameters.
  */
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     random_state *rs;
     game_state *state;
@@ -714,7 +710,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret;
 
@@ -737,7 +733,7 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state->tiles);
     sfree(state->barriers);
@@ -815,7 +811,7 @@ struct game_ui {
     int cur_visible;
 };
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cur_x = state->width / 2;
@@ -825,7 +821,7 @@ game_ui *new_ui(game_state *state)
     return ui;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
     sfree(ui);
 }
@@ -834,7 +830,7 @@ void free_ui(game_ui *ui)
  * Process a move.
  */
 
-void slide_row(game_state *state, int dir, int row)
+static void slide_row(game_state *state, int dir, int row)
 {
     int x = dir > 0 ? -1 : state->width;
     int tx = x + dir;
@@ -848,7 +844,7 @@ void slide_row(game_state *state, int dir, int row)
     state->tiles[T(state, tx, row)] = endtile;
 }
 
-void slide_col(game_state *state, int dir, int col)
+static void slide_col(game_state *state, int dir, int col)
 {
     int y = dir > 0 ? -1 : state->height;
     int ty = y + dir;
@@ -862,7 +858,8 @@ void slide_col(game_state *state, int dir, int col)
     state->tiles[T(state, col, ty)] = endtile;
 }
 
-game_state *make_move(game_state *state, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *state, game_ui *ui,
+                            int x, int y, int button)
 {
     int cx, cy;
     int n, dx, dy;
@@ -945,7 +942,7 @@ struct game_drawstate {
     unsigned char *visible;
 };
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     game_drawstate *ds = snew(game_drawstate);
 
@@ -958,19 +955,19 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds->visible);
     sfree(ds);
 }
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     *x = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER;
     *y = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->height + TILE_BORDER;
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret;
 
@@ -1286,7 +1283,7 @@ static void draw_arrow(frontend *fe, int x, int y, int xdx, int xdy)
     draw_polygon(fe, coords, 7, FALSE, COL_TEXT);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                  game_state *state, int dir, game_ui *ui, float t, float ft)
 {
     int x, y, tx, ty, frame;
@@ -1481,12 +1478,14 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     sfree(active);
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate,
+                             game_state *newstate, int dir)
 {
     return ANIM_TIME;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate,
+                              game_state *newstate, int dir)
 {
     /*
      * If the game has just been completed, we display a completion
@@ -1509,7 +1508,40 @@ float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
     return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return TRUE;
 }
+
+#ifdef COMBINED
+#define thegame netslide
+#endif
+
+const struct game thegame = {
+    "Netslide", "games.netslide", TRUE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
index e704de9365b852a7c04f9acfcd372e3a35f6c21d..3d5270d05b1998b8f975113942c040d2c808ef6c 100644 (file)
 
 #include "puzzles.h"
 
-const char *const game_name = "Null Game";
-const char *const game_winhelp_topic = NULL;
-const int game_can_configure = FALSE;
-
 enum {
     COL_BACKGROUND,
     NCOLOURS
@@ -37,7 +33,7 @@ struct game_state {
     int FIXME;
 };
 
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -46,24 +42,24 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     return FALSE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = snew(game_params);
 
@@ -72,37 +68,37 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     return dupstr("FIXME");
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     return NULL;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     return NULL;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     return NULL;
 }
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     return dupstr("FIXME");
 }
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     return NULL;
 }
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     game_state *state = snew(game_state);
 
@@ -111,7 +107,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -120,21 +116,22 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state);
 }
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     return NULL;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
 }
 
-game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *from, game_ui *ui, int x, int y,
+                            int button)
 {
     return NULL;
 }
@@ -147,12 +144,12 @@ struct game_drawstate {
     int FIXME;
 };
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     *x = *y = 200;                     /* FIXME */
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
 
@@ -162,7 +159,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
     return ret;
 }
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -171,14 +168,14 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
-                 game_state *state, int dir, game_ui *ui,
-                 float animtime, float flashtime)
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+                       game_state *state, int dir, game_ui *ui,
+                       float animtime, float flashtime)
 {
     /*
      * The initial contents of the window are not guaranteed and
@@ -189,17 +186,52 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     draw_rect(fe, 0, 0, 200, 200, COL_BACKGROUND);
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate, game_state *newstate,
+                             int dir)
 {
     return 0.0F;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate, game_state *newstate,
+                              int dir)
 {
     return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return FALSE;
 }
+
+#ifdef COMBINED
+#define thegame nullgame
+#endif
+
+const struct game thegame = {
+    "Null Game", NULL, FALSE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
index e7b99b31f53bf6a20a7409037b25d4f79ba3f975..8f3570580515ba3f6a4247a8b26efbd7f72dc1d9 100644 (file)
--- a/pattern.c
+++ b/pattern.c
 #define max(x,y) ( (x)>(y) ? (x):(y) )
 #define min(x,y) ( (x)<(y) ? (x):(y) )
 
-const char *const game_name = "Pattern";
-const char *const game_winhelp_topic = "games.pattern";
-const int game_can_configure = TRUE;
-
 enum {
     COL_BACKGROUND,
     COL_EMPTY,
@@ -61,7 +57,7 @@ struct game_state {
 
 #define FLASH_TIME 0.13F
 
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -70,7 +66,7 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     char str[80];
@@ -96,19 +92,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
     return TRUE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = default_params();
     char const *p = string;
@@ -126,7 +122,7 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     char ret[400];
     int len;
@@ -138,7 +134,7 @@ char *encode_params(game_params *params)
     return dupstr(ret);
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -165,7 +161,7 @@ config_item *game_configure(game_params *params)
     return ret;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -175,7 +171,7 @@ game_params *custom_params(config_item *cfg)
     return ret;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     if (params->w <= 0 && params->h <= 0)
        return "Width and height must both be greater than zero";
@@ -315,7 +311,7 @@ static void generate(random_state *rs, int w, int h, unsigned char *retgrid)
     sfree(fgrid);
 }
 
-int compute_rowdata(int *ret, unsigned char *start, int len, int step)
+static int compute_rowdata(int *ret, unsigned char *start, int len, int step)
 {
     int i, n;
 
@@ -443,7 +439,7 @@ static unsigned char *generate_soluble(random_state *rs, int w, int h)
     return grid;
 }
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     unsigned char *grid;
     int i, j, max, rowlen, *rowdata;
@@ -507,7 +503,7 @@ char *new_game_seed(game_params *params, random_state *rs)
     return seed;
 }
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     int i, n, rowspace;
     char *p;
@@ -549,7 +545,7 @@ char *validate_seed(game_params *params, char *seed)
     return NULL;
 }
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     int i;
     char *p;
@@ -584,7 +580,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -607,7 +603,7 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state->rowdata);
     sfree(state->rowlen);
@@ -624,7 +620,7 @@ struct game_ui {
     int drag, release, state;
 };
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     game_ui *ret;
 
@@ -634,12 +630,13 @@ game_ui *new_ui(game_state *state)
     return ret;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
     sfree(ui);
 }
 
-game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *from, game_ui *ui,
+                            int x, int y, int button)
 {
     game_state *ret;
 
@@ -775,13 +772,13 @@ struct game_drawstate {
     unsigned char *visible;
 };
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     *x = SIZE(params->w);
     *y = SIZE(params->h);
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
 
@@ -807,7 +804,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
     return ret;
 }
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -820,7 +817,7 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds->visible);
     sfree(ds);
@@ -848,7 +845,7 @@ static void grid_square(frontend *fe, game_drawstate *ds,
                 TILE_SIZE, TILE_SIZE);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                  game_state *state, int dir, game_ui *ui,
                  float animtime, float flashtime)
 {
@@ -957,19 +954,54 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     }
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate,
+                             game_state *newstate, int dir)
 {
     return 0.0F;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate,
+                              game_state *newstate, int dir)
 {
     if (!oldstate->completed && newstate->completed)
         return FLASH_TIME;
     return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return FALSE;
 }
+
+#ifdef COMBINED
+#define thegame pattern
+#endif
+
+const struct game thegame = {
+    "Pattern", "games.pattern", TRUE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
index 027a97356c1a2b0034aebef4a2aa66fd3b2191ce..a9f1a9287d88c2d59f5e35c2949381df348fe552 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -44,6 +44,7 @@ typedef struct game_params game_params;
 typedef struct game_state game_state;
 typedef struct game_ui game_ui;
 typedef struct game_drawstate game_drawstate;
+typedef struct game game;
 
 #define ALIGN_VNORMAL 0x000
 #define ALIGN_VCENTRE 0x100
@@ -111,7 +112,7 @@ void get_random_seed(void **randseed, int *randseedsize);
 /*
  * midend.c
  */
-midend_data *midend_new(frontend *fe);
+midend_data *midend_new(frontend *fe, const game *ourgame);
 void midend_free(midend_data *me);
 void midend_set_params(midend_data *me, game_params *params);
 void midend_size(midend_data *me, int *x, int *y);
@@ -158,37 +159,52 @@ unsigned long random_upto(random_state *state, unsigned long limit);
 void random_free(random_state *state);
 
 /*
- * Game-specific routines
+ * Data structure containing the function calls and data specific
+ * to a particular game. This is enclosed in a data structure so
+ * that a particular platform can choose, if it wishes, to compile
+ * all the games into a single combined executable rather than
+ * having lots of little ones.
  */
-extern const char *const game_name;
-extern const char *const game_winhelp_topic;
-const int game_can_configure;
-game_params *default_params(void);
-int game_fetch_preset(int i, char **name, game_params **params);
-game_params *decode_params(char const *string);
-char *encode_params(game_params *);
-void free_params(game_params *params);
-game_params *dup_params(game_params *params);
-config_item *game_configure(game_params *params);
-game_params *custom_params(config_item *cfg);
-char *validate_params(game_params *params);
-char *new_game_seed(game_params *params, random_state *rs);
-char *validate_seed(game_params *params, char *seed);
-game_state *new_game(game_params *params, char *seed);
-game_state *dup_game(game_state *state);
-void free_game(game_state *state);
-game_ui *new_ui(game_state *state);
-void free_ui(game_ui *ui);
-game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button);
-void game_size(game_params *params, int *x, int *y);
-float *game_colours(frontend *fe, game_state *state, int *ncolours);
-game_drawstate *game_new_drawstate(game_state *state);
-void game_free_drawstate(game_drawstate *ds);
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
-                 game_state *newstate, int dir, game_ui *ui, float anim_time,
-                 float flash_time);
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir);
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir);
-int game_wants_statusbar(void);
+struct game {
+    const char *name;
+    const char *winhelp_topic;
+    int can_configure;
+    game_params *(*default_params)(void);
+    int (*fetch_preset)(int i, char **name, game_params **params);
+    game_params *(*decode_params)(char const *string);
+    char *(*encode_params)(game_params *);
+    void (*free_params)(game_params *params);
+    game_params *(*dup_params)(game_params *params);
+    config_item *(*configure)(game_params *params);
+    game_params *(*custom_params)(config_item *cfg);
+    char *(*validate_params)(game_params *params);
+    char *(*new_seed)(game_params *params, random_state *rs);
+    char *(*validate_seed)(game_params *params, char *seed);
+    game_state *(*new_game)(game_params *params, char *seed);
+    game_state *(*dup_game)(game_state *state);
+    void (*free_game)(game_state *state);
+    game_ui *(*new_ui)(game_state *state);
+    void (*free_ui)(game_ui *ui);
+    game_state *(*make_move)(game_state *from, game_ui *ui, int x, int y,
+                            int button);
+    void (*size)(game_params *params, int *x, int *y);
+    float *(*colours)(frontend *fe, game_state *state, int *ncolours);
+    game_drawstate *(*new_drawstate)(game_state *state);
+    void (*free_drawstate)(game_drawstate *ds);
+    void (*redraw)(frontend *fe, game_drawstate *ds, game_state *oldstate,
+                  game_state *newstate, int dir, game_ui *ui, float anim_time,
+                  float flash_time);
+    float (*anim_length)(game_state *oldstate, game_state *newstate, int dir);
+    float (*flash_length)(game_state *oldstate, game_state *newstate, int dir);
+    int (*wants_statusbar)(void);
+};
+
+/*
+ * For one-game-at-a-time platforms, there's a single structure
+ * like the above, under a fixed name.
+ */
+#ifndef COMBINED
+extern const game thegame;
+#endif
 
 #endif /* PUZZLES_PUZZLES_H */
diff --git a/rect.c b/rect.c
index 06ccff6d2ffc90c58ea590e24b26301b6e3325a9..e3914b054ad5517cfe564049350cc4707e0a9d0e 100644 (file)
--- a/rect.c
+++ b/rect.c
 
 #include "puzzles.h"
 
-const char *const game_name = "Rectangles";
-const char *const game_winhelp_topic = "games.rectangles";
-const int game_can_configure = TRUE;
-
 enum {
     COL_BACKGROUND,
     COL_CORRECT,
@@ -89,7 +85,7 @@ struct game_state {
     int completed;
 };
 
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -99,7 +95,7 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     int w, h;
@@ -122,19 +118,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
     return TRUE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = default_params();
 
@@ -154,7 +150,7 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     char data[256];
 
@@ -163,7 +159,7 @@ char *encode_params(game_params *params)
     return dupstr(data);
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -196,7 +192,7 @@ config_item *game_configure(game_params *params)
     return ret;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -207,7 +203,7 @@ game_params *custom_params(config_item *cfg)
     return ret;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     if (params->w <= 0 && params->h <= 0)
        return "Width and height must both be greater than zero";
@@ -390,7 +386,7 @@ static void display_grid(game_params *params, int *grid, int *numbers, int all)
 }
 #endif
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     int *grid, *numbers;
     struct rectlist *list;
@@ -902,7 +898,7 @@ char *new_game_seed(game_params *params, random_state *rs)
     return seed;
 }
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     int area = params->w * params->h;
     int squares = 0;
@@ -930,7 +926,7 @@ char *validate_seed(game_params *params, char *seed)
     return NULL;
 }
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     game_state *state = snew(game_state);
     int x, y, i, area;
@@ -973,7 +969,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -993,7 +989,7 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state->grid);
     sfree(state->vedge);
@@ -1118,7 +1114,7 @@ struct game_ui {
     int dragged;
 };
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->drag_start_x = -1;
@@ -1129,12 +1125,12 @@ game_ui *new_ui(game_state *state)
     return ui;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
     sfree(ui);
 }
 
-void coord_round(float x, float y, int *xr, int *yr)
+static void coord_round(float x, float y, int *xr, int *yr)
 {
     float xs, ys, xv, yv, dx, dy, dist;
 
@@ -1265,7 +1261,8 @@ static void ui_draw_rect(game_state *state, game_ui *ui,
             }
 }
 
-game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *from, game_ui *ui,
+                            int x, int y, int button)
 {
     int xc, yc;
     int startdrag = FALSE, enddrag = FALSE, active = FALSE;
@@ -1374,13 +1371,13 @@ struct game_drawstate {
     unsigned int *visible;
 };
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     *x = params->w * TILE_SIZE + 2*BORDER + 1;
     *y = params->h * TILE_SIZE + 2*BORDER + 1;
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
 
@@ -1410,7 +1407,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
     return ret;
 }
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1425,13 +1422,13 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds->visible);
     sfree(ds);
 }
 
-void draw_tile(frontend *fe, game_state *state, int x, int y,
+static void draw_tile(frontend *fe, game_state *state, int x, int y,
                unsigned char *hedge, unsigned char *vedge,
               unsigned char *corners, int correct)
 {
@@ -1487,7 +1484,7 @@ void draw_tile(frontend *fe, game_state *state, int x, int y,
     draw_update(fe, cx, cy, TILE_SIZE+1, TILE_SIZE+1);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                  game_state *state, int dir, game_ui *ui,
                  float animtime, float flashtime)
 {
@@ -1579,19 +1576,54 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     sfree(correct);
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate,
+                             game_state *newstate, int dir)
 {
     return 0.0F;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate,
+                              game_state *newstate, int dir)
 {
     if (!oldstate->completed && newstate->completed)
         return FLASH_TIME;
     return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return FALSE;
 }
+
+#ifdef COMBINED
+#define thegame rect
+#endif
+
+const struct game thegame = {
+    "Rectangles", "games.rectangles", TRUE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
index f6215bdb587bac9cbef177aacf8cb396809c9b74..ddafdd6816415d1a1eaf89921f6032128be0db2d 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
 
 #include "puzzles.h"
 
-const char *const game_name = "Sixteen";
-const char *const game_winhelp_topic = "games.sixteen";
-const int game_can_configure = TRUE;
-
 #define TILE_SIZE 48
 #define BORDER    TILE_SIZE            /* big border to fill with arrows */
 #define HIGHLIGHT_WIDTH (TILE_SIZE / 20)
@@ -50,7 +46,7 @@ struct game_state {
     int last_movement_sense;
 };
 
-game_params *default_params(void)
+static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
@@ -59,7 +55,7 @@ game_params *default_params(void)
     return ret;
 }
 
-int game_fetch_preset(int i, char **name, game_params **params)
+static int game_fetch_preset(int i, char **name, game_params **params)
 {
     game_params *ret;
     int w, h;
@@ -82,19 +78,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
     return TRUE;
 }
 
-void free_params(game_params *params)
+static void free_params(game_params *params)
 {
     sfree(params);
 }
 
-game_params *dup_params(game_params *params)
+static game_params *dup_params(game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
     return ret;
 }
 
-game_params *decode_params(char const *string)
+static game_params *decode_params(char const *string)
 {
     game_params *ret = default_params();
 
@@ -108,7 +104,7 @@ game_params *decode_params(char const *string)
     return ret;
 }
 
-char *encode_params(game_params *params)
+static char *encode_params(game_params *params)
 {
     char data[256];
 
@@ -117,7 +113,7 @@ char *encode_params(game_params *params)
     return dupstr(data);
 }
 
-config_item *game_configure(game_params *params)
+static config_item *game_configure(game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -144,7 +140,7 @@ config_item *game_configure(game_params *params)
     return ret;
 }
 
-game_params *custom_params(config_item *cfg)
+static game_params *custom_params(config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -154,7 +150,7 @@ game_params *custom_params(config_item *cfg)
     return ret;
 }
 
-char *validate_params(game_params *params)
+static char *validate_params(game_params *params)
 {
     if (params->w < 2 && params->h < 2)
        return "Width and height must both be at least two";
@@ -162,7 +158,7 @@ char *validate_params(game_params *params)
     return NULL;
 }
 
-int perm_parity(int *perm, int n)
+static int perm_parity(int *perm, int n)
 {
     int i, j, ret;
 
@@ -176,7 +172,7 @@ int perm_parity(int *perm, int n)
     return ret;
 }
 
-char *new_game_seed(game_params *params, random_state *rs)
+static char *new_game_seed(game_params *params, random_state *rs)
 {
     int stop, n, i, x;
     int x1, x2, p1, p2;
@@ -283,7 +279,7 @@ char *new_game_seed(game_params *params, random_state *rs)
 }
 
 
-char *validate_seed(game_params *params, char *seed)
+static char *validate_seed(game_params *params, char *seed)
 {
     char *p, *err;
     int i, area;
@@ -334,7 +330,7 @@ char *validate_seed(game_params *params, char *seed)
     return err;
 }
 
-game_state *new_game(game_params *params, char *seed)
+static game_state *new_game(game_params *params, char *seed)
 {
     game_state *state = snew(game_state);
     int i;
@@ -362,7 +358,7 @@ game_state *new_game(game_params *params, char *seed)
     return state;
 }
 
-game_state *dup_game(game_state *state)
+static game_state *dup_game(game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -378,21 +374,22 @@ game_state *dup_game(game_state *state)
     return ret;
 }
 
-void free_game(game_state *state)
+static void free_game(game_state *state)
 {
     sfree(state);
 }
 
-game_ui *new_ui(game_state *state)
+static game_ui *new_ui(game_state *state)
 {
     return NULL;
 }
 
-void free_ui(game_ui *ui)
+static void free_ui(game_ui *ui)
 {
 }
 
-game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button)
+static game_state *make_move(game_state *from, game_ui *ui,
+                            int x, int y, int button)
 {
     int cx, cy;
     int dx, dy, tx, ty, n;
@@ -458,13 +455,13 @@ struct game_drawstate {
     int *tiles;
 };
 
-void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, int *x, int *y)
 {
     *x = TILE_SIZE * params->w + 2 * BORDER;
     *y = TILE_SIZE * params->h + 2 * BORDER;
 }
 
-float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
     int i;
@@ -495,7 +492,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
     return ret;
 }
 
-game_drawstate *game_new_drawstate(game_state *state)
+static game_drawstate *game_new_drawstate(game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -511,7 +508,7 @@ game_drawstate *game_new_drawstate(game_state *state)
     return ds;
 }
 
-void game_free_drawstate(game_drawstate *ds)
+static void game_free_drawstate(game_drawstate *ds)
 {
     sfree(ds->tiles);
     sfree(ds);
@@ -574,7 +571,7 @@ static void draw_arrow(frontend *fe, int x, int y, int xdx, int xdy)
     draw_polygon(fe, coords, 7, FALSE, COL_TEXT);
 }
 
-void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
+static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
                  game_state *state, int dir, game_ui *ui,
                  float animtime, float flashtime)
 {
@@ -752,12 +749,14 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     }
 }
 
-float game_anim_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_anim_length(game_state *oldstate,
+                             game_state *newstate, int dir)
 {
     return ANIM_TIME;
 }
 
-float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
+static float game_flash_length(game_state *oldstate,
+                              game_state *newstate, int dir)
 {
     if (!oldstate->completed && newstate->completed)
         return 2 * FLASH_FRAME;
@@ -765,7 +764,36 @@ float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
         return 0.0F;
 }
 
-int game_wants_statusbar(void)
+static int game_wants_statusbar(void)
 {
     return TRUE;
 }
+
+const struct game thegame = {
+    "Sixteen", "games.sixteen", TRUE,
+    default_params,
+    game_fetch_preset,
+    decode_params,
+    encode_params,
+    free_params,
+    dup_params,
+    game_configure,
+    custom_params,
+    validate_params,
+    new_game_seed,
+    validate_seed,
+    new_game,
+    dup_game,
+    free_game,
+    new_ui,
+    free_ui,
+    make_move,
+    game_size,
+    game_colours,
+    game_new_drawstate,
+    game_free_drawstate,
+    game_redraw,
+    game_anim_length,
+    game_flash_length,
+    game_wants_statusbar,
+};
index ac5e20c88cc3dc321bdd177d7ba47d5277ef543f..2833969b0ba88e9c36bb903638093296cdf54fca 100644 (file)
--- a/windows.c
+++ b/windows.c
@@ -1,5 +1,14 @@
 /*
  * windows.c: Windows front end for my puzzle collection.
+ * 
+ * TODO:
+ * 
+ *  - Figure out what to do if a puzzle requests a size bigger than
+ *    the screen will take. In principle we could put scrollbars in
+ *    the window, although that would be pretty horrid. Another
+ *    option is to detect in advance that this will be a problem -
+ *    we can probably tell this using midend_size() before actually
+ *    generating the puzzle - and simply refuse to do it.
  */
 
 #include <windows.h>
@@ -363,7 +372,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
 
     fe = snew(frontend);
 
-    fe->me = midend_new(fe);
+    fe->me = midend_new(fe, &thegame);
 
     if (game_id) {
         *error = midend_game_id(fe->me, game_id, FALSE);
@@ -412,7 +421,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
                       (WS_THICKFRAME | WS_MAXIMIZEBOX | WS_OVERLAPPED),
                       TRUE, 0);
 
-    fe->hwnd = CreateWindowEx(0, game_name, game_name,
+    fe->hwnd = CreateWindowEx(0, thegame.name, thegame.name,
                              WS_OVERLAPPEDWINDOW &~
                              (WS_THICKFRAME | WS_MAXIMIZEBOX),
                              CW_USEDEFAULT, CW_USEDEFAULT,
@@ -429,7 +438,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
        AppendMenu(menu, MF_ENABLED, IDM_SEED, "Specific...");
 
        if ((fe->npresets = midend_num_presets(fe->me)) > 0 ||
-           game_can_configure) {
+           thegame.can_configure) {
            HMENU sub = CreateMenu();
            int i;
 
@@ -450,7 +459,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
                AppendMenu(sub, MF_ENABLED, IDM_PRESETS + 0x10 * i, name);
            }
 
-           if (game_can_configure) {
+           if (thegame.can_configure) {
                AppendMenu(sub, MF_ENABLED, IDM_CONFIG, "Custom...");
            }
        }
@@ -464,11 +473,11 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
             HMENU hmenu = CreateMenu();
             AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)hmenu, "Help");
             AppendMenu(hmenu, MF_ENABLED, IDM_HELPC, "Contents");
-            if (game_winhelp_topic) {
+            if (thegame.winhelp_topic) {
                 char *item;
-                assert(game_name);
-                item = snewn(9+strlen(game_name), char); /*ick*/
-                sprintf(item, "Help on %s", game_name);
+                assert(thegame.name);
+                item = snewn(9+strlen(thegame.name), char); /*ick*/
+                sprintf(item, "Help on %s", thegame.name);
                 AppendMenu(hmenu, MF_ENABLED, IDM_GAMEHELP, item);
                 sfree(item);
             }
@@ -911,10 +920,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
             break;
           case IDM_GAMEHELP:
             assert(fe->help_path);
-            assert(game_winhelp_topic);
+            assert(thegame.winhelp_topic);
             {
-                char *cmd = snewn(10+strlen(game_winhelp_topic), char); /*ick*/
-                sprintf(cmd, "JI(`',`%s')", game_winhelp_topic);
+                char *cmd = snewn(10+strlen(thegame.winhelp_topic), char);
+                sprintf(cmd, "JI(`',`%s')", thegame.winhelp_topic);
                 WinHelp(hwnd, fe->help_path, HELP_COMMAND, (DWORD)cmd);
                 sfree(cmd);
             }
@@ -1107,7 +1116,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = NULL;
        wndclass.lpszMenuName = NULL;
-       wndclass.lpszClassName = game_name;
+       wndclass.lpszClassName = thegame.name;
 
        RegisterClass(&wndclass);
     }
@@ -1117,7 +1126,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 
     if (!new_window(inst, *cmdline ? cmdline : NULL, &error)) {
        char buf[128];
-       sprintf(buf, "%.100s Error", game_name);
+       sprintf(buf, "%.100s Error", thegame.name);
        MessageBox(NULL, error, buf, MB_OK|MB_ICONERROR);
        return 1;
     }