Rather than each game backend file exporting a whole load of

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]
This commit is contained in:
Simon Tatham
2005-01-17 13:48:57 +00:00
parent 46fa25240e
commit cc54553226
12 changed files with 626 additions and 346 deletions

90
cube.c
View File

@ -11,10 +11,6 @@
#include "puzzles.h" #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 MAXVERTICES 20
#define MAXFACES 20 #define MAXFACES 20
#define MAXORDER 4 #define MAXORDER 4
@ -215,7 +211,7 @@ struct game_state {
int movecount; int movecount;
}; };
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -226,7 +222,7 @@ game_params *default_params(void)
return ret; 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); game_params *ret = snew(game_params);
char *str; char *str;
@ -266,19 +262,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
return TRUE; return TRUE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = default_params(); game_params *ret = default_params();
@ -299,7 +295,7 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
char data[256]; 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; 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); config_item *ret = snewn(4, config_item);
char buf[80]; char buf[80];
@ -507,7 +503,7 @@ config_item *game_configure(game_params *params)
return ret; return ret;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -533,7 +529,7 @@ static void count_grid_square_callback(void *ctx, struct grid_square *sq)
classes[thisclass]++; classes[thisclass]++;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
int classes[5]; int classes[5];
int i; int i;
@ -593,7 +589,7 @@ static void classify_grid_square_callback(void *ctx, struct grid_square *sq)
data->squareindex++; 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; struct grid_data data;
int i, j, k, m, area, facesperclass; int i, j, k, m, area, facesperclass;
@ -842,7 +838,7 @@ static struct solid *transform_poly(const struct solid *solid, int flip,
return ret; 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 area = grid_area(params->d1, params->d2, solids[params->solid]->order);
int i, j; int i, j;
@ -870,7 +866,7 @@ char *validate_seed(game_params *params, char *seed)
return NULL; 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); game_state *state = snew(game_state);
int area; int area;
@ -949,7 +945,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret = snew(game_state); game_state *ret = snew(game_state);
@ -978,21 +974,22 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state); sfree(state);
} }
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
return NULL; 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 direction;
int pkey[2], skey[2], dkey[2]; int pkey[2], skey[2], dkey[2];
@ -1309,14 +1306,14 @@ static struct bbox find_bbox(game_params *params)
return bb; 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); struct bbox bb = find_bbox(params);
*x = (int)((bb.r - bb.l + 2*solids[params->solid]->border) * GRID_SCALE); *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); *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); float *ret = snewn(3 * NCOLOURS, float);
@ -1334,7 +1331,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
return ret; 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 game_drawstate *ds = snew(struct game_drawstate);
struct bbox bb = find_bbox(&state->params); struct bbox bb = find_bbox(&state->params);
@ -1345,12 +1342,12 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(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, game_state *state, int dir, game_ui *ui,
float animtime, float flashtime) 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; 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; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return TRUE; 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,
};

View File

@ -11,10 +11,6 @@
#include "puzzles.h" #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 TILE_SIZE 48
#define BORDER (TILE_SIZE / 2) #define BORDER (TILE_SIZE / 2)
#define HIGHLIGHT_WIDTH (TILE_SIZE / 20) #define HIGHLIGHT_WIDTH (TILE_SIZE / 20)
@ -48,7 +44,7 @@ struct game_state {
int movecount; int movecount;
}; };
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -57,24 +53,24 @@ game_params *default_params(void)
return ret; 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; return FALSE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = default_params(); game_params *ret = default_params();
@ -88,7 +84,7 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
char data[256]; char data[256];
@ -97,7 +93,7 @@ char *encode_params(game_params *params)
return dupstr(data); return dupstr(data);
} }
config_item *game_configure(game_params *params) static config_item *game_configure(game_params *params)
{ {
config_item *ret; config_item *ret;
char buf[80]; char buf[80];
@ -124,7 +120,7 @@ config_item *game_configure(game_params *params)
return ret; return ret;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -134,7 +130,7 @@ game_params *custom_params(config_item *cfg)
return ret; return ret;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
if (params->w < 2 && params->h < 2) if (params->w < 2 && params->h < 2)
return "Width and height must both be at least two"; return "Width and height must both be at least two";
@ -142,7 +138,7 @@ char *validate_params(game_params *params)
return NULL; return NULL;
} }
int perm_parity(int *perm, int n) static int perm_parity(int *perm, int n)
{ {
int i, j, ret; int i, j, ret;
@ -156,7 +152,7 @@ int perm_parity(int *perm, int n)
return ret; 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 gap, n, i, x;
int x1, x2, p1, p2, parity; int x1, x2, p1, p2, parity;
@ -271,7 +267,7 @@ char *new_game_seed(game_params *params, random_state *rs)
return ret; return ret;
} }
char *validate_seed(game_params *params, char *seed) static char *validate_seed(game_params *params, char *seed)
{ {
char *p, *err; char *p, *err;
int i, area; int i, area;
@ -322,7 +318,7 @@ char *validate_seed(game_params *params, char *seed)
return err; 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); game_state *state = snew(game_state);
int i; int i;
@ -353,7 +349,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret = snew(game_state); game_state *ret = snew(game_state);
@ -369,21 +365,22 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state); sfree(state);
} }
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
return NULL; 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; int gx, gy, dx, dy, ux, uy, up, p;
game_state *ret; game_state *ret;
@ -457,13 +454,13 @@ struct game_drawstate {
int *tiles; 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; *x = TILE_SIZE * params->w + 2 * BORDER;
*y = TILE_SIZE * params->h + 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); float *ret = snewn(3 * NCOLOURS, float);
int i; int i;
@ -494,7 +491,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
return ret; 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 game_drawstate *ds = snew(struct game_drawstate);
int i; int i;
@ -510,7 +507,7 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(ds->tiles); sfree(ds->tiles);
sfree(ds); 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); 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, game_state *state, int dir, game_ui *ui,
float animtime, float flashtime) 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; 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) if (!oldstate->completed && newstate->completed)
return 2 * FLASH_FRAME; return 2 * FLASH_FRAME;
@ -715,7 +714,40 @@ float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
return 0.0F; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return TRUE; 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,
};

8
gtk.c
View File

@ -783,7 +783,7 @@ static frontend *new_window(char *game_id, char **error)
fe = snew(frontend); fe = snew(frontend);
fe->me = midend_new(fe); fe->me = midend_new(fe, &thegame);
if (game_id) { if (game_id) {
*error = midend_game_id(fe->me, game_id, FALSE); *error = midend_game_id(fe->me, game_id, FALSE);
if (*error) { if (*error) {
@ -795,7 +795,7 @@ static frontend *new_window(char *game_id, char **error)
midend_new_game(fe->me); midend_new_game(fe->me);
fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 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 #if 0
gtk_window_set_resizable(GTK_WINDOW(fe->window), FALSE); gtk_window_set_resizable(GTK_WINDOW(fe->window), FALSE);
#else #else
@ -827,7 +827,7 @@ static frontend *new_window(char *game_id, char **error)
GTK_SIGNAL_FUNC(menu_config_event), fe); GTK_SIGNAL_FUNC(menu_config_event), fe);
gtk_widget_show(menuitem); 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; GtkWidget *submenu;
int i; int i;
@ -852,7 +852,7 @@ static frontend *new_window(char *game_id, char **error)
gtk_widget_show(menuitem); gtk_widget_show(menuitem);
} }
if (game_can_configure) { if (thegame.can_configure) {
menuitem = gtk_menu_item_new_with_label("Custom..."); menuitem = gtk_menu_item_new_with_label("Custom...");
gtk_object_set_data(GTK_OBJECT(menuitem), "user-data", gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
GPOINTER_TO_INT(CFG_SETTINGS)); GPOINTER_TO_INT(CFG_SETTINGS));

View File

@ -14,6 +14,7 @@
struct midend_data { struct midend_data {
frontend *frontend; frontend *frontend;
random_state *random; random_state *random;
const game *ourgame;
char *seed; char *seed;
int fresh_seed; int fresh_seed;
@ -40,7 +41,7 @@ struct midend_data {
} \ } \
} while (0) } while (0)
midend_data *midend_new(frontend *fe) midend_data *midend_new(frontend *fe, const game *ourgame)
{ {
midend_data *me = snew(midend_data); midend_data *me = snew(midend_data);
void *randseed; void *randseed;
@ -49,10 +50,11 @@ midend_data *midend_new(frontend *fe)
get_random_seed(&randseed, &randseedsize); get_random_seed(&randseed, &randseedsize);
me->frontend = fe; me->frontend = fe;
me->ourgame = ourgame;
me->random = random_init(randseed, randseedsize); me->random = random_init(randseed, randseedsize);
me->nstates = me->statesize = me->statepos = 0; me->nstates = me->statesize = me->statepos = 0;
me->states = NULL; me->states = NULL;
me->params = default_params(); me->params = ourgame->default_params();
me->seed = NULL; me->seed = NULL;
me->fresh_seed = FALSE; me->fresh_seed = FALSE;
me->drawstate = NULL; me->drawstate = NULL;
@ -74,53 +76,53 @@ void midend_free(midend_data *me)
{ {
sfree(me->states); sfree(me->states);
sfree(me->seed); sfree(me->seed);
free_params(me->params); me->ourgame->free_params(me->params);
sfree(me); sfree(me);
} }
void midend_size(midend_data *me, int *x, int *y) 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) void midend_set_params(midend_data *me, game_params *params)
{ {
free_params(me->params); me->ourgame->free_params(me->params);
me->params = dup_params(params); me->params = me->ourgame->dup_params(params);
} }
void midend_new_game(midend_data *me) void midend_new_game(midend_data *me)
{ {
while (me->nstates > 0) while (me->nstates > 0)
free_game(me->states[--me->nstates]); me->ourgame->free_game(me->states[--me->nstates]);
if (me->drawstate) if (me->drawstate)
game_free_drawstate(me->drawstate); me->ourgame->free_drawstate(me->drawstate);
assert(me->nstates == 0); assert(me->nstates == 0);
if (!me->fresh_seed) { if (!me->fresh_seed) {
sfree(me->seed); sfree(me->seed);
me->seed = new_game_seed(me->params, me->random); me->seed = me->ourgame->new_seed(me->params, me->random);
} else } else
me->fresh_seed = FALSE; me->fresh_seed = FALSE;
ensure(me); 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->statepos = 1;
me->drawstate = game_new_drawstate(me->states[0]); me->drawstate = me->ourgame->new_drawstate(me->states[0]);
if (me->ui) if (me->ui)
free_ui(me->ui); me->ourgame->free_ui(me->ui);
me->ui = new_ui(me->states[0]); me->ui = me->ourgame->new_ui(me->states[0]);
} }
void midend_restart_game(midend_data *me) void midend_restart_game(midend_data *me)
{ {
while (me->nstates > 1) while (me->nstates > 1)
free_game(me->states[--me->nstates]); me->ourgame->free_game(me->states[--me->nstates]);
me->statepos = me->nstates; me->statepos = me->nstates;
free_ui(me->ui); me->ourgame->free_ui(me->ui);
me->ui = new_ui(me->states[0]); me->ui = me->ourgame->new_ui(me->states[0]);
} }
static int midend_undo(midend_data *me) static int midend_undo(midend_data *me)
@ -148,7 +150,7 @@ static void midend_finish_move(midend_data *me)
float flashtime; float flashtime;
if (me->oldstate || me->statepos > 1) { if (me->oldstate || me->statepos > 1) {
flashtime = game_flash_length(me->oldstate ? me->oldstate : flashtime = me->ourgame->flash_length(me->oldstate ? me->oldstate :
me->states[me->statepos-2], me->states[me->statepos-2],
me->states[me->statepos-1], me->states[me->statepos-1],
me->oldstate ? me->dir : +1); me->oldstate ? me->dir : +1);
@ -159,7 +161,7 @@ static void midend_finish_move(midend_data *me)
} }
if (me->oldstate) if (me->oldstate)
free_game(me->oldstate); me->ourgame->free_game(me->oldstate);
me->oldstate = NULL; me->oldstate = NULL;
me->anim_pos = me->anim_time = 0; me->anim_pos = me->anim_time = 0;
me->dir = 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) 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; float anim_time;
if (button == 'n' || button == 'N' || button == '\x0E') { 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)) if (!midend_redo(me))
return 1; return 1;
} else if (button == 'q' || button == 'Q' || button == '\x11') { } else if (button == 'q' || button == 'Q' || button == '\x11') {
free_game(oldstate); me->ourgame->free_game(oldstate);
return 0; return 0;
} else { } else {
game_state *s = make_move(me->states[me->statepos-1], me->ui, game_state *s = me->ourgame->make_move(me->states[me->statepos-1],
x, y, button); me->ui, x, y, button);
if (s == me->states[me->statepos-1]) { 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) { } else if (s) {
midend_stop_anim(me); midend_stop_anim(me);
while (me->nstates > me->statepos) while (me->nstates > me->statepos)
free_game(me->states[--me->nstates]); me->ourgame->free_game(me->states[--me->nstates]);
ensure(me); ensure(me);
me->states[me->nstates] = s; me->states[me->nstates] = s;
me->statepos = ++me->nstates; me->statepos = ++me->nstates;
me->dir = +1; me->dir = +1;
} else { } else {
free_game(oldstate); me->ourgame->free_game(oldstate);
return 1; 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. * 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; me->oldstate = oldstate;
if (anim_time > 0) { if (anim_time > 0) {
@ -259,11 +262,11 @@ void midend_redraw(midend_data *me)
if (me->oldstate && me->anim_time > 0 && if (me->oldstate && me->anim_time > 0 &&
me->anim_pos < me->anim_time) { me->anim_pos < me->anim_time) {
assert(me->dir != 0); assert(me->dir != 0);
game_redraw(me->frontend, me->drawstate, me->oldstate, me->ourgame->redraw(me->frontend, me->drawstate, me->oldstate,
me->states[me->statepos-1], me->dir, me->states[me->statepos-1], me->dir,
me->ui, me->anim_pos, me->flash_pos); me->ui, me->anim_pos, me->flash_pos);
} else { } else {
game_redraw(me->frontend, me->drawstate, NULL, me->ourgame->redraw(me->frontend, me->drawstate, NULL,
me->states[me->statepos-1], +1 /*shrug*/, me->states[me->statepos-1], +1 /*shrug*/,
me->ui, 0.0, me->flash_pos); me->ui, 0.0, me->flash_pos);
} }
@ -294,16 +297,16 @@ float *midend_colours(midend_data *me, int *ncolours)
float *ret; float *ret;
if (me->nstates == 0) { if (me->nstates == 0) {
char *seed = new_game_seed(me->params, me->random); char *seed = me->ourgame->new_seed(me->params, me->random);
state = new_game(me->params, seed); state = me->ourgame->new_game(me->params, seed);
sfree(seed); sfree(seed);
} else } else
state = me->states[0]; state = me->states[0];
ret = game_colours(me->frontend, state, ncolours); ret = me->ourgame->colours(me->frontend, state, ncolours);
if (me->nstates == 0) if (me->nstates == 0)
free_game(state); me->ourgame->free_game(state);
return ret; return ret;
} }
@ -314,7 +317,7 @@ int midend_num_presets(midend_data *me)
char *name; char *name;
game_params *preset; 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) { if (me->presetsize <= me->npresets) {
me->presetsize = me->npresets + 10; me->presetsize = me->npresets + 10;
me->presets = sresize(me->presets, me->presetsize, 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) 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) 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; char *titlebuf, *parstr;
config_item *ret; config_item *ret;
titlebuf = snewn(40 + strlen(game_name), char); titlebuf = snewn(40 + strlen(me->ourgame->name), char);
switch (which) { switch (which) {
case CFG_SETTINGS: case CFG_SETTINGS:
sprintf(titlebuf, "%s configuration", game_name); sprintf(titlebuf, "%s configuration", me->ourgame->name);
*wintitle = dupstr(titlebuf); *wintitle = dupstr(titlebuf);
return game_configure(me->params); return me->ourgame->configure(me->params);
case CFG_SEED: case CFG_SEED:
sprintf(titlebuf, "%s game selection", game_name); sprintf(titlebuf, "%s game selection", me->ourgame->name);
*wintitle = dupstr(titlebuf); *wintitle = dupstr(titlebuf);
ret = snewn(2, config_item); 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 * parameters, plus a colon, plus the game seed. This is a
* full game ID. * 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); ret[0].sval = snewn(strlen(parstr) + strlen(me->seed) + 2, char);
sprintf(ret[0].sval, "%s:%s", parstr, me->seed); sprintf(ret[0].sval, "%s:%s", parstr, me->seed);
sfree(parstr); sfree(parstr);
@ -417,18 +420,18 @@ char *midend_game_id(midend_data *me, char *id, int def_seed)
} }
if (par) { if (par) {
params = decode_params(par); params = me->ourgame->decode_params(par);
error = validate_params(params); error = me->ourgame->validate_params(params);
if (error) { if (error) {
free_params(params); me->ourgame->free_params(params);
return error; return error;
} }
free_params(me->params); me->ourgame->free_params(me->params);
me->params = params; me->params = params;
} }
if (seed) { if (seed) {
error = validate_seed(me->params, seed); error = me->ourgame->validate_seed(me->params, seed);
if (error) if (error)
return error; return error;
@ -447,15 +450,15 @@ char *midend_set_config(midend_data *me, int which, config_item *cfg)
switch (which) { switch (which) {
case CFG_SETTINGS: case CFG_SETTINGS:
params = custom_params(cfg); params = me->ourgame->custom_params(cfg);
error = validate_params(params); error = me->ourgame->validate_params(params);
if (error) { if (error) {
free_params(params); me->ourgame->free_params(params);
return error; return error;
} }
free_params(me->params); me->ourgame->free_params(me->params);
me->params = params; me->params = params;
break; break;

90
net.c
View File

@ -12,10 +12,6 @@
#include "puzzles.h" #include "puzzles.h"
#include "tree234.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 PI 3.141592653589793238462643383279502884197169399
#define MATMUL(xr,yr,m,x,y) do { \ #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. * Manage game parameters.
*/ */
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -139,7 +135,7 @@ game_params *default_params(void)
return ret; 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; game_params *ret;
char str[80]; char str[80];
@ -173,19 +169,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
return TRUE; return TRUE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = default_params(); game_params *ret = default_params();
char const *p = string; char const *p = string;
@ -207,7 +203,7 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
char ret[400]; char ret[400];
int len; int len;
@ -223,7 +219,7 @@ char *encode_params(game_params *params)
return dupstr(ret); return dupstr(ret);
} }
config_item *game_configure(game_params *params) static config_item *game_configure(game_params *params)
{ {
config_item *ret; config_item *ret;
char buf[80]; char buf[80];
@ -261,7 +257,7 @@ config_item *game_configure(game_params *params)
return ret; return ret;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -273,7 +269,7 @@ game_params *custom_params(config_item *cfg)
return ret; return ret;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
if (params->width <= 0 && params->height <= 0) if (params->width <= 0 && params->height <= 0)
return "Width and height must both be greater than zero"; 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. * 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 * 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); 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 * 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. * 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; random_state *rs;
game_state *state; game_state *state;
@ -676,7 +672,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret; game_state *ret;
@ -696,7 +692,7 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state->tiles); sfree(state->tiles);
sfree(state->barriers); sfree(state->barriers);
@ -770,7 +766,7 @@ struct game_ui {
random_state *rs; /* used for jumbling */ random_state *rs; /* used for jumbling */
}; };
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
void *seed; void *seed;
int seedsize; int seedsize;
@ -785,7 +781,7 @@ game_ui *new_ui(game_state *state)
return ui; return ui;
} }
void free_ui(game_ui *ui) static void free_ui(game_ui *ui)
{ {
random_free(ui->rs); random_free(ui->rs);
sfree(ui); sfree(ui);
@ -794,7 +790,8 @@ void free_ui(game_ui *ui)
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Process a move. * 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; game_state *ret, *nullret;
int tx, ty, orig; int tx, ty, orig;
@ -951,7 +948,7 @@ struct game_drawstate {
unsigned char *visible; 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); game_drawstate *ds = snew(game_drawstate);
@ -964,19 +961,19 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(ds->visible); sfree(ds->visible);
sfree(ds); 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; *x = WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER;
*y = WINDOW_OFFSET * 2 + TILE_SIZE * params->height + 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; 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); 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) game_state *state, int dir, game_ui *ui, float t, float ft)
{ {
int x, y, tx, ty, frame, last_rotate_dir; 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); 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; 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; 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 * 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; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return TRUE; 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,
};

View File

@ -13,10 +13,6 @@
#include "puzzles.h" #include "puzzles.h"
#include "tree234.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 PI 3.141592653589793238462643383279502884197169399
#define MATMUL(xr,yr,m,x,y) do { \ #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; return xyd;
} }
void slide_col(game_state *state, int dir, int col); static void slide_col(game_state *state, int dir, int col);
void slide_row(game_state *state, int dir, int row); static void slide_row(game_state *state, int dir, int row);
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------
* Manage game parameters. * Manage game parameters.
*/ */
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -157,7 +153,7 @@ game_params *default_params(void)
return ret; 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; game_params *ret;
char str[80]; char str[80];
@ -190,19 +186,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
return TRUE; return TRUE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = default_params(); game_params *ret = default_params();
char const *p = string; char const *p = string;
@ -227,7 +223,7 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
char ret[400]; char ret[400];
int len; int len;
@ -243,7 +239,7 @@ char *encode_params(game_params *params)
return dupstr(ret); return dupstr(ret);
} }
config_item *game_configure(game_params *params) static config_item *game_configure(game_params *params)
{ {
config_item *ret; config_item *ret;
char buf[80]; char buf[80];
@ -281,7 +277,7 @@ config_item *game_configure(game_params *params)
return ret; return ret;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -293,7 +289,7 @@ game_params *custom_params(config_item *cfg)
return ret; return ret;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
if (params->width <= 1 && params->height <= 1) if (params->width <= 1 && params->height <= 1)
return "Width and height must both be greater than one"; 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. * 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 * 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); 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 * 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. * 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; random_state *rs;
game_state *state; game_state *state;
@ -714,7 +710,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret; game_state *ret;
@ -737,7 +733,7 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state->tiles); sfree(state->tiles);
sfree(state->barriers); sfree(state->barriers);
@ -815,7 +811,7 @@ struct game_ui {
int cur_visible; int cur_visible;
}; };
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
game_ui *ui = snew(game_ui); game_ui *ui = snew(game_ui);
ui->cur_x = state->width / 2; ui->cur_x = state->width / 2;
@ -825,7 +821,7 @@ game_ui *new_ui(game_state *state)
return ui; return ui;
} }
void free_ui(game_ui *ui) static void free_ui(game_ui *ui)
{ {
sfree(ui); sfree(ui);
} }
@ -834,7 +830,7 @@ void free_ui(game_ui *ui)
* Process a move. * 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 x = dir > 0 ? -1 : state->width;
int tx = x + dir; 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; 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 y = dir > 0 ? -1 : state->height;
int ty = y + dir; 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; 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 cx, cy;
int n, dx, dy; int n, dx, dy;
@ -945,7 +942,7 @@ struct game_drawstate {
unsigned char *visible; 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); game_drawstate *ds = snew(game_drawstate);
@ -958,19 +955,19 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(ds->visible); sfree(ds->visible);
sfree(ds); 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; *x = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER;
*y = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->height + 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; 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); 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) game_state *state, int dir, game_ui *ui, float t, float ft)
{ {
int x, y, tx, ty, frame; int x, y, tx, ty, frame;
@ -1481,12 +1478,14 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
sfree(active); 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; 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 * 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; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return TRUE; 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,
};

View File

@ -20,10 +20,6 @@
#include "puzzles.h" #include "puzzles.h"
const char *const game_name = "Null Game";
const char *const game_winhelp_topic = NULL;
const int game_can_configure = FALSE;
enum { enum {
COL_BACKGROUND, COL_BACKGROUND,
NCOLOURS NCOLOURS
@ -37,7 +33,7 @@ struct game_state {
int FIXME; int FIXME;
}; };
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -46,24 +42,24 @@ game_params *default_params(void)
return ret; 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; return FALSE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -72,37 +68,37 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
return dupstr("FIXME"); return dupstr("FIXME");
} }
config_item *game_configure(game_params *params) static config_item *game_configure(game_params *params)
{ {
return NULL; return NULL;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
return NULL; return NULL;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
return NULL; 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"); return dupstr("FIXME");
} }
char *validate_seed(game_params *params, char *seed) static char *validate_seed(game_params *params, char *seed)
{ {
return NULL; 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); game_state *state = snew(game_state);
@ -111,7 +107,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret = snew(game_state); game_state *ret = snew(game_state);
@ -120,21 +116,22 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state); sfree(state);
} }
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
return NULL; 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; return NULL;
} }
@ -147,12 +144,12 @@ struct game_drawstate {
int FIXME; 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 */ *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); float *ret = snewn(3 * NCOLOURS, float);
@ -162,7 +159,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
return ret; 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 game_drawstate *ds = snew(struct game_drawstate);
@ -171,12 +168,12 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(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, game_state *state, int dir, game_ui *ui,
float animtime, float flashtime) float animtime, float flashtime)
{ {
@ -189,17 +186,52 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
draw_rect(fe, 0, 0, 200, 200, COL_BACKGROUND); 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; 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; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return FALSE; 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,
};

View File

@ -18,10 +18,6 @@
#define max(x,y) ( (x)>(y) ? (x):(y) ) #define max(x,y) ( (x)>(y) ? (x):(y) )
#define min(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 { enum {
COL_BACKGROUND, COL_BACKGROUND,
COL_EMPTY, COL_EMPTY,
@ -61,7 +57,7 @@ struct game_state {
#define FLASH_TIME 0.13F #define FLASH_TIME 0.13F
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -70,7 +66,7 @@ game_params *default_params(void)
return ret; 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; game_params *ret;
char str[80]; char str[80];
@ -96,19 +92,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
return TRUE; return TRUE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = default_params(); game_params *ret = default_params();
char const *p = string; char const *p = string;
@ -126,7 +122,7 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
char ret[400]; char ret[400];
int len; int len;
@ -138,7 +134,7 @@ char *encode_params(game_params *params)
return dupstr(ret); return dupstr(ret);
} }
config_item *game_configure(game_params *params) static config_item *game_configure(game_params *params)
{ {
config_item *ret; config_item *ret;
char buf[80]; char buf[80];
@ -165,7 +161,7 @@ config_item *game_configure(game_params *params)
return ret; return ret;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -175,7 +171,7 @@ game_params *custom_params(config_item *cfg)
return ret; return ret;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
if (params->w <= 0 && params->h <= 0) if (params->w <= 0 && params->h <= 0)
return "Width and height must both be greater than zero"; 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); 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; int i, n;
@ -443,7 +439,7 @@ static unsigned char *generate_soluble(random_state *rs, int w, int h)
return grid; 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; unsigned char *grid;
int i, j, max, rowlen, *rowdata; int i, j, max, rowlen, *rowdata;
@ -507,7 +503,7 @@ char *new_game_seed(game_params *params, random_state *rs)
return seed; return seed;
} }
char *validate_seed(game_params *params, char *seed) static char *validate_seed(game_params *params, char *seed)
{ {
int i, n, rowspace; int i, n, rowspace;
char *p; char *p;
@ -549,7 +545,7 @@ char *validate_seed(game_params *params, char *seed)
return NULL; return NULL;
} }
game_state *new_game(game_params *params, char *seed) static game_state *new_game(game_params *params, char *seed)
{ {
int i; int i;
char *p; char *p;
@ -584,7 +580,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret = snew(game_state); game_state *ret = snew(game_state);
@ -607,7 +603,7 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state->rowdata); sfree(state->rowdata);
sfree(state->rowlen); sfree(state->rowlen);
@ -624,7 +620,7 @@ struct game_ui {
int drag, release, state; int drag, release, state;
}; };
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
game_ui *ret; game_ui *ret;
@ -634,12 +630,13 @@ game_ui *new_ui(game_state *state)
return ret; return ret;
} }
void free_ui(game_ui *ui) static void free_ui(game_ui *ui)
{ {
sfree(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; game_state *ret;
@ -775,13 +772,13 @@ struct game_drawstate {
unsigned char *visible; 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); *x = SIZE(params->w);
*y = SIZE(params->h); *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); float *ret = snewn(3 * NCOLOURS, float);
@ -807,7 +804,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
return ret; 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 game_drawstate *ds = snew(struct game_drawstate);
@ -820,7 +817,7 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(ds->visible); sfree(ds->visible);
sfree(ds); sfree(ds);
@ -848,7 +845,7 @@ static void grid_square(frontend *fe, game_drawstate *ds,
TILE_SIZE, TILE_SIZE); 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, game_state *state, int dir, game_ui *ui,
float animtime, float flashtime) 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; 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) if (!oldstate->completed && newstate->completed)
return FLASH_TIME; return FLASH_TIME;
return 0.0F; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return FALSE; 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,
};

View File

@ -44,6 +44,7 @@ typedef struct game_params game_params;
typedef struct game_state game_state; typedef struct game_state game_state;
typedef struct game_ui game_ui; typedef struct game_ui game_ui;
typedef struct game_drawstate game_drawstate; typedef struct game_drawstate game_drawstate;
typedef struct game game;
#define ALIGN_VNORMAL 0x000 #define ALIGN_VNORMAL 0x000
#define ALIGN_VCENTRE 0x100 #define ALIGN_VCENTRE 0x100
@ -111,7 +112,7 @@ void get_random_seed(void **randseed, int *randseedsize);
/* /*
* midend.c * 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_free(midend_data *me);
void midend_set_params(midend_data *me, game_params *params); void midend_set_params(midend_data *me, game_params *params);
void midend_size(midend_data *me, int *x, int *y); 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); 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; struct game {
extern const char *const game_winhelp_topic; const char *name;
const int game_can_configure; const char *winhelp_topic;
game_params *default_params(void); int can_configure;
int game_fetch_preset(int i, char **name, game_params **params); game_params *(*default_params)(void);
game_params *decode_params(char const *string); int (*fetch_preset)(int i, char **name, game_params **params);
char *encode_params(game_params *); game_params *(*decode_params)(char const *string);
void free_params(game_params *params); char *(*encode_params)(game_params *);
game_params *dup_params(game_params *params); void (*free_params)(game_params *params);
config_item *game_configure(game_params *params); game_params *(*dup_params)(game_params *params);
game_params *custom_params(config_item *cfg); config_item *(*configure)(game_params *params);
char *validate_params(game_params *params); game_params *(*custom_params)(config_item *cfg);
char *new_game_seed(game_params *params, random_state *rs); char *(*validate_params)(game_params *params);
char *validate_seed(game_params *params, char *seed); char *(*new_seed)(game_params *params, random_state *rs);
game_state *new_game(game_params *params, char *seed); char *(*validate_seed)(game_params *params, char *seed);
game_state *dup_game(game_state *state); game_state *(*new_game)(game_params *params, char *seed);
void free_game(game_state *state); game_state *(*dup_game)(game_state *state);
game_ui *new_ui(game_state *state); void (*free_game)(game_state *state);
void free_ui(game_ui *ui); game_ui *(*new_ui)(game_state *state);
game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button); void (*free_ui)(game_ui *ui);
void game_size(game_params *params, int *x, int *y); game_state *(*make_move)(game_state *from, game_ui *ui, int x, int y,
float *game_colours(frontend *fe, game_state *state, int *ncolours); int button);
game_drawstate *game_new_drawstate(game_state *state); void (*size)(game_params *params, int *x, int *y);
void game_free_drawstate(game_drawstate *ds); float *(*colours)(frontend *fe, game_state *state, int *ncolours);
void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, 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, game_state *newstate, int dir, game_ui *ui, float anim_time,
float flash_time); float flash_time);
float game_anim_length(game_state *oldstate, game_state *newstate, int dir); float (*anim_length)(game_state *oldstate, game_state *newstate, int dir);
float game_flash_length(game_state *oldstate, game_state *newstate, int dir); float (*flash_length)(game_state *oldstate, game_state *newstate, int dir);
int game_wants_statusbar(void); 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 */ #endif /* PUZZLES_PUZZLES_H */

94
rect.c
View File

@ -39,10 +39,6 @@
#include "puzzles.h" #include "puzzles.h"
const char *const game_name = "Rectangles";
const char *const game_winhelp_topic = "games.rectangles";
const int game_can_configure = TRUE;
enum { enum {
COL_BACKGROUND, COL_BACKGROUND,
COL_CORRECT, COL_CORRECT,
@ -89,7 +85,7 @@ struct game_state {
int completed; int completed;
}; };
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -99,7 +95,7 @@ game_params *default_params(void)
return ret; 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; game_params *ret;
int w, h; int w, h;
@ -122,19 +118,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
return TRUE; return TRUE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = default_params(); game_params *ret = default_params();
@ -154,7 +150,7 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
char data[256]; char data[256];
@ -163,7 +159,7 @@ char *encode_params(game_params *params)
return dupstr(data); return dupstr(data);
} }
config_item *game_configure(game_params *params) static config_item *game_configure(game_params *params)
{ {
config_item *ret; config_item *ret;
char buf[80]; char buf[80];
@ -196,7 +192,7 @@ config_item *game_configure(game_params *params)
return ret; return ret;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -207,7 +203,7 @@ game_params *custom_params(config_item *cfg)
return ret; return ret;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
if (params->w <= 0 && params->h <= 0) if (params->w <= 0 && params->h <= 0)
return "Width and height must both be greater than zero"; 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 #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; int *grid, *numbers;
struct rectlist *list; struct rectlist *list;
@ -902,7 +898,7 @@ char *new_game_seed(game_params *params, random_state *rs)
return seed; 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 area = params->w * params->h;
int squares = 0; int squares = 0;
@ -930,7 +926,7 @@ char *validate_seed(game_params *params, char *seed)
return NULL; 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); game_state *state = snew(game_state);
int x, y, i, area; int x, y, i, area;
@ -973,7 +969,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret = snew(game_state); game_state *ret = snew(game_state);
@ -993,7 +989,7 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state->grid); sfree(state->grid);
sfree(state->vedge); sfree(state->vedge);
@ -1118,7 +1114,7 @@ struct game_ui {
int dragged; int dragged;
}; };
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
game_ui *ui = snew(game_ui); game_ui *ui = snew(game_ui);
ui->drag_start_x = -1; ui->drag_start_x = -1;
@ -1129,12 +1125,12 @@ game_ui *new_ui(game_state *state)
return ui; return ui;
} }
void free_ui(game_ui *ui) static void free_ui(game_ui *ui)
{ {
sfree(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; 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 xc, yc;
int startdrag = FALSE, enddrag = FALSE, active = FALSE; int startdrag = FALSE, enddrag = FALSE, active = FALSE;
@ -1374,13 +1371,13 @@ struct game_drawstate {
unsigned int *visible; 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; *x = params->w * TILE_SIZE + 2*BORDER + 1;
*y = params->h * 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); float *ret = snewn(3 * NCOLOURS, float);
@ -1410,7 +1407,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
return ret; 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 game_drawstate *ds = snew(struct game_drawstate);
int i; int i;
@ -1425,13 +1422,13 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(ds->visible); sfree(ds->visible);
sfree(ds); 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 *hedge, unsigned char *vedge,
unsigned char *corners, int correct) 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); 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, game_state *state, int dir, game_ui *ui,
float animtime, float flashtime) float animtime, float flashtime)
{ {
@ -1579,19 +1576,54 @@ void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
sfree(correct); 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; 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) if (!oldstate->completed && newstate->completed)
return FLASH_TIME; return FLASH_TIME;
return 0.0F; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return FALSE; 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,
};

View File

@ -13,10 +13,6 @@
#include "puzzles.h" #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 TILE_SIZE 48
#define BORDER TILE_SIZE /* big border to fill with arrows */ #define BORDER TILE_SIZE /* big border to fill with arrows */
#define HIGHLIGHT_WIDTH (TILE_SIZE / 20) #define HIGHLIGHT_WIDTH (TILE_SIZE / 20)
@ -50,7 +46,7 @@ struct game_state {
int last_movement_sense; int last_movement_sense;
}; };
game_params *default_params(void) static game_params *default_params(void)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -59,7 +55,7 @@ game_params *default_params(void)
return ret; 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; game_params *ret;
int w, h; int w, h;
@ -82,19 +78,19 @@ int game_fetch_preset(int i, char **name, game_params **params)
return TRUE; return TRUE;
} }
void free_params(game_params *params) static void free_params(game_params *params)
{ {
sfree(params); sfree(params);
} }
game_params *dup_params(game_params *params) static game_params *dup_params(game_params *params)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
*ret = *params; /* structure copy */ *ret = *params; /* structure copy */
return ret; return ret;
} }
game_params *decode_params(char const *string) static game_params *decode_params(char const *string)
{ {
game_params *ret = default_params(); game_params *ret = default_params();
@ -108,7 +104,7 @@ game_params *decode_params(char const *string)
return ret; return ret;
} }
char *encode_params(game_params *params) static char *encode_params(game_params *params)
{ {
char data[256]; char data[256];
@ -117,7 +113,7 @@ char *encode_params(game_params *params)
return dupstr(data); return dupstr(data);
} }
config_item *game_configure(game_params *params) static config_item *game_configure(game_params *params)
{ {
config_item *ret; config_item *ret;
char buf[80]; char buf[80];
@ -144,7 +140,7 @@ config_item *game_configure(game_params *params)
return ret; return ret;
} }
game_params *custom_params(config_item *cfg) static game_params *custom_params(config_item *cfg)
{ {
game_params *ret = snew(game_params); game_params *ret = snew(game_params);
@ -154,7 +150,7 @@ game_params *custom_params(config_item *cfg)
return ret; return ret;
} }
char *validate_params(game_params *params) static char *validate_params(game_params *params)
{ {
if (params->w < 2 && params->h < 2) if (params->w < 2 && params->h < 2)
return "Width and height must both be at least two"; return "Width and height must both be at least two";
@ -162,7 +158,7 @@ char *validate_params(game_params *params)
return NULL; return NULL;
} }
int perm_parity(int *perm, int n) static int perm_parity(int *perm, int n)
{ {
int i, j, ret; int i, j, ret;
@ -176,7 +172,7 @@ int perm_parity(int *perm, int n)
return ret; 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 stop, n, i, x;
int x1, x2, p1, p2; 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; char *p, *err;
int i, area; int i, area;
@ -334,7 +330,7 @@ char *validate_seed(game_params *params, char *seed)
return err; 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); game_state *state = snew(game_state);
int i; int i;
@ -362,7 +358,7 @@ game_state *new_game(game_params *params, char *seed)
return state; return state;
} }
game_state *dup_game(game_state *state) static game_state *dup_game(game_state *state)
{ {
game_state *ret = snew(game_state); game_state *ret = snew(game_state);
@ -378,21 +374,22 @@ game_state *dup_game(game_state *state)
return ret; return ret;
} }
void free_game(game_state *state) static void free_game(game_state *state)
{ {
sfree(state); sfree(state);
} }
game_ui *new_ui(game_state *state) static game_ui *new_ui(game_state *state)
{ {
return NULL; 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 cx, cy;
int dx, dy, tx, ty, n; int dx, dy, tx, ty, n;
@ -458,13 +455,13 @@ struct game_drawstate {
int *tiles; 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; *x = TILE_SIZE * params->w + 2 * BORDER;
*y = TILE_SIZE * params->h + 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); float *ret = snewn(3 * NCOLOURS, float);
int i; int i;
@ -495,7 +492,7 @@ float *game_colours(frontend *fe, game_state *state, int *ncolours)
return ret; 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 game_drawstate *ds = snew(struct game_drawstate);
int i; int i;
@ -511,7 +508,7 @@ game_drawstate *game_new_drawstate(game_state *state)
return ds; return ds;
} }
void game_free_drawstate(game_drawstate *ds) static void game_free_drawstate(game_drawstate *ds)
{ {
sfree(ds->tiles); sfree(ds->tiles);
sfree(ds); 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); 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, game_state *state, int dir, game_ui *ui,
float animtime, float flashtime) 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; 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) if (!oldstate->completed && newstate->completed)
return 2 * FLASH_FRAME; return 2 * FLASH_FRAME;
@ -765,7 +764,36 @@ float game_flash_length(game_state *oldstate, game_state *newstate, int dir)
return 0.0F; return 0.0F;
} }
int game_wants_statusbar(void) static int game_wants_statusbar(void)
{ {
return TRUE; 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,
};

View File

@ -1,5 +1,14 @@
/* /*
* windows.c: Windows front end for my puzzle collection. * 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> #include <windows.h>
@ -363,7 +372,7 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
fe = snew(frontend); fe = snew(frontend);
fe->me = midend_new(fe); fe->me = midend_new(fe, &thegame);
if (game_id) { if (game_id) {
*error = midend_game_id(fe->me, game_id, FALSE); *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), (WS_THICKFRAME | WS_MAXIMIZEBOX | WS_OVERLAPPED),
TRUE, 0); TRUE, 0);
fe->hwnd = CreateWindowEx(0, game_name, game_name, fe->hwnd = CreateWindowEx(0, thegame.name, thegame.name,
WS_OVERLAPPEDWINDOW &~ WS_OVERLAPPEDWINDOW &~
(WS_THICKFRAME | WS_MAXIMIZEBOX), (WS_THICKFRAME | WS_MAXIMIZEBOX),
CW_USEDEFAULT, CW_USEDEFAULT, 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..."); AppendMenu(menu, MF_ENABLED, IDM_SEED, "Specific...");
if ((fe->npresets = midend_num_presets(fe->me)) > 0 || if ((fe->npresets = midend_num_presets(fe->me)) > 0 ||
game_can_configure) { thegame.can_configure) {
HMENU sub = CreateMenu(); HMENU sub = CreateMenu();
int i; 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); AppendMenu(sub, MF_ENABLED, IDM_PRESETS + 0x10 * i, name);
} }
if (game_can_configure) { if (thegame.can_configure) {
AppendMenu(sub, MF_ENABLED, IDM_CONFIG, "Custom..."); 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(); HMENU hmenu = CreateMenu();
AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)hmenu, "Help"); AppendMenu(bar, MF_ENABLED|MF_POPUP, (UINT)hmenu, "Help");
AppendMenu(hmenu, MF_ENABLED, IDM_HELPC, "Contents"); AppendMenu(hmenu, MF_ENABLED, IDM_HELPC, "Contents");
if (game_winhelp_topic) { if (thegame.winhelp_topic) {
char *item; char *item;
assert(game_name); assert(thegame.name);
item = snewn(9+strlen(game_name), char); /*ick*/ item = snewn(9+strlen(thegame.name), char); /*ick*/
sprintf(item, "Help on %s", game_name); sprintf(item, "Help on %s", thegame.name);
AppendMenu(hmenu, MF_ENABLED, IDM_GAMEHELP, item); AppendMenu(hmenu, MF_ENABLED, IDM_GAMEHELP, item);
sfree(item); sfree(item);
} }
@ -911,10 +920,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
break; break;
case IDM_GAMEHELP: case IDM_GAMEHELP:
assert(fe->help_path); assert(fe->help_path);
assert(game_winhelp_topic); assert(thegame.winhelp_topic);
{ {
char *cmd = snewn(10+strlen(game_winhelp_topic), char); /*ick*/ char *cmd = snewn(10+strlen(thegame.winhelp_topic), char);
sprintf(cmd, "JI(`',`%s')", game_winhelp_topic); sprintf(cmd, "JI(`',`%s')", thegame.winhelp_topic);
WinHelp(hwnd, fe->help_path, HELP_COMMAND, (DWORD)cmd); WinHelp(hwnd, fe->help_path, HELP_COMMAND, (DWORD)cmd);
sfree(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.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = NULL; wndclass.hbrBackground = NULL;
wndclass.lpszMenuName = NULL; wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = game_name; wndclass.lpszClassName = thegame.name;
RegisterClass(&wndclass); 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)) { if (!new_window(inst, *cmdline ? cmdline : NULL, &error)) {
char buf[128]; char buf[128];
sprintf(buf, "%.100s Error", game_name); sprintf(buf, "%.100s Error", thegame.name);
MessageBox(NULL, error, buf, MB_OK|MB_ICONERROR); MessageBox(NULL, error, buf, MB_OK|MB_ICONERROR);
return 1; return 1;
} }