X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/48a10826fef7777bb8b061f4a121f481ced98bc0..f3cc3e50490f3409b85f805dae9872e09f42bd7d:/fifteen.c diff --git a/fifteen.c b/fifteen.c index 0ed5067..226de30 100644 --- a/fifteen.c +++ b/fifteen.c @@ -11,7 +11,8 @@ #include "puzzles.h" -#define TILE_SIZE 48 +#define PREFERRED_TILE_SIZE 48 +#define TILE_SIZE (ds->tilesize) #define BORDER (TILE_SIZE / 2) #define HIGHLIGHT_WIDTH (TILE_SIZE / 20) #define COORD(x) ( (x) * TILE_SIZE + BORDER ) @@ -72,21 +73,17 @@ static game_params *dup_params(game_params *params) return ret; } -static game_params *decode_params(char const *string) +static void decode_params(game_params *ret, char const *string) { - game_params *ret = default_params(); - ret->w = ret->h = atoi(string); while (*string && isdigit(*string)) string++; if (*string == 'x') { string++; ret->h = atoi(string); } - - return ret; } -static char *encode_params(game_params *params) +static char *encode_params(game_params *params, int full) { char data[256]; @@ -134,7 +131,7 @@ static game_params *custom_params(config_item *cfg) 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 NULL; @@ -154,8 +151,8 @@ static int perm_parity(int *perm, int n) return ret; } -static char *new_game_seed(game_params *params, random_state *rs, - game_aux_info **aux) +static char *new_game_desc(game_params *params, random_state *rs, + game_aux_info **aux, int interactive) { int gap, n, i, x; int x1, x2, p1, p2, parity; @@ -247,8 +244,8 @@ static char *new_game_seed(game_params *params, random_state *rs, } /* - * Now construct the game seed, by describing the tile array as - * a simple sequence of comma-separated integers. + * Now construct the game description, by describing the tile + * array as a simple sequence of comma-separated integers. */ ret = NULL; retlen = 0; @@ -275,14 +272,14 @@ static void game_free_aux_info(game_aux_info *aux) assert(!"Shouldn't happen"); } -static char *validate_seed(game_params *params, char *seed) +static char *validate_desc(game_params *params, char *desc) { char *p, *err; int i, area; int *used; area = params->w * params->h; - p = seed; + p = desc; err = NULL; used = snewn(area, int); @@ -326,7 +323,7 @@ static char *validate_seed(game_params *params, char *seed) return err; } -static game_state *new_game(game_params *params, char *seed) +static game_state *new_game(midend_data *me, game_params *params, char *desc) { game_state *state = snew(game_state); int i; @@ -338,7 +335,7 @@ static game_state *new_game(game_params *params, char *seed) state->tiles = snewn(state->n, int); state->gap_pos = 0; - p = seed; + p = desc; i = 0; for (i = 0; i < state->n; i++) { assert(*p); @@ -378,6 +375,7 @@ static game_state *dup_game(game_state *state) static void free_game(game_state *state) { + sfree(state->tiles); sfree(state); } @@ -398,7 +396,7 @@ static game_state *solve_game(game_state *state, game_aux_info *aux, ret->tiles[i] = (i+1) % ret->n; ret->gap_pos = ret->n-1; ret->used_solve = ret->just_used_solve = TRUE; - ret->completed = ret->movecount; + ret->completed = ret->movecount = 1; return ret; } @@ -454,12 +452,25 @@ static void free_ui(game_ui *ui) { } -static game_state *make_move(game_state *from, game_ui *ui, - int x, int y, int button) +static void game_changed_state(game_ui *ui, game_state *oldstate, + game_state *newstate) { +} + +struct game_drawstate { + int started; + int w, h, bgcolour; + int *tiles; + int tilesize; +}; + +static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds, + int x, int y, int button) { int gx, gy, dx, dy, ux, uy, up, p; game_state *ret; + button &= ~MOD_MASK; + gx = X(from, from->gap_pos); gy = Y(from, from->gap_pos); @@ -524,14 +535,23 @@ static game_state *make_move(game_state *from, game_ui *ui, * Drawing routines. */ -struct game_drawstate { - int started; - int w, h, bgcolour; - int *tiles; -}; - -static void game_size(game_params *params, int *x, int *y) +static void game_size(game_params *params, game_drawstate *ds, + int *x, int *y, int expand) { + int tsx, tsy, ts; + /* + * Each window dimension equals the tile size times one more + * than the grid dimension (the border is half the width of the + * tiles). + */ + tsx = *x / (params->w + 1); + tsy = *y / (params->h + 1); + ts = min(tsx, tsy); + if (expand) + ds->tilesize = ts; + else + ds->tilesize = min(ts, PREFERRED_TILE_SIZE); + *x = TILE_SIZE * params->w + 2 * BORDER; *y = TILE_SIZE * params->h + 2 * BORDER; } @@ -577,6 +597,7 @@ static game_drawstate *game_new_drawstate(game_state *state) ds->h = state->h; ds->bgcolour = COL_BACKGROUND; ds->tiles = snewn(ds->w*ds->h, int); + ds->tilesize = 0; /* haven't decided yet */ for (i = 0; i < ds->w*ds->h; i++) ds->tiles[i] = -1; @@ -589,8 +610,8 @@ static void game_free_drawstate(game_drawstate *ds) sfree(ds); } -static void draw_tile(frontend *fe, game_state *state, int x, int y, - int tile, int flash_colour) +static void draw_tile(frontend *fe, game_drawstate *ds, game_state *state, + int x, int y, int tile, int flash_colour) { if (tile == 0) { draw_rect(fe, x, y, TILE_SIZE, TILE_SIZE, @@ -638,7 +659,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, bgcolour = COL_BACKGROUND; if (!ds->started) { - int coords[6]; + int coords[10]; draw_rect(fe, 0, 0, TILE_SIZE * state->w + 2 * BORDER, @@ -654,15 +675,19 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, coords[1] = COORD(state->h) + HIGHLIGHT_WIDTH - 1; coords[2] = COORD(state->w) + HIGHLIGHT_WIDTH - 1; coords[3] = COORD(0) - HIGHLIGHT_WIDTH; - coords[4] = COORD(0) - HIGHLIGHT_WIDTH; - coords[5] = COORD(state->h) + HIGHLIGHT_WIDTH - 1; - draw_polygon(fe, coords, 3, TRUE, COL_HIGHLIGHT); - draw_polygon(fe, coords, 3, FALSE, COL_HIGHLIGHT); + coords[4] = coords[2] - TILE_SIZE; + coords[5] = coords[3] + TILE_SIZE; + coords[8] = COORD(0) - HIGHLIGHT_WIDTH; + coords[9] = COORD(state->h) + HIGHLIGHT_WIDTH - 1; + coords[6] = coords[8] + TILE_SIZE; + coords[7] = coords[9] - TILE_SIZE; + draw_polygon(fe, coords, 5, TRUE, COL_HIGHLIGHT); + draw_polygon(fe, coords, 5, FALSE, COL_HIGHLIGHT); coords[1] = COORD(0) - HIGHLIGHT_WIDTH; coords[0] = COORD(0) - HIGHLIGHT_WIDTH; - draw_polygon(fe, coords, 3, TRUE, COL_LOWLIGHT); - draw_polygon(fe, coords, 3, FALSE, COL_LOWLIGHT); + draw_polygon(fe, coords, 5, TRUE, COL_LOWLIGHT); + draw_polygon(fe, coords, 5, FALSE, COL_LOWLIGHT); ds->started = TRUE; } @@ -747,7 +772,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, y = COORD(Y(state, i)); } - draw_tile(fe, state, x, y, t, bgcolour); + draw_tile(fe, ds, state, x, y, t, bgcolour); } ds->tiles[i] = t0; } @@ -780,7 +805,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, } static float game_anim_length(game_state *oldstate, - game_state *newstate, int dir) + game_state *newstate, int dir, game_ui *ui) { if ((dir > 0 && newstate->just_used_solve) || (dir < 0 && oldstate->just_used_solve)) @@ -790,7 +815,7 @@ static float game_anim_length(game_state *oldstate, } static float game_flash_length(game_state *oldstate, - game_state *newstate, int dir) + game_state *newstate, int dir, game_ui *ui) { if (!oldstate->completed && newstate->completed && !oldstate->used_solve && !newstate->used_solve) @@ -804,6 +829,11 @@ static int game_wants_statusbar(void) return TRUE; } +static int game_timing_state(game_state *state) +{ + return TRUE; +} + #ifdef COMBINED #define thegame fifteen #endif @@ -818,9 +848,9 @@ const struct game thegame = { dup_params, TRUE, game_configure, custom_params, validate_params, - new_game_seed, + new_game_desc, game_free_aux_info, - validate_seed, + validate_desc, new_game, dup_game, free_game, @@ -828,6 +858,7 @@ const struct game thegame = { TRUE, game_text_format, new_ui, free_ui, + game_changed_state, make_move, game_size, game_colours, @@ -837,4 +868,6 @@ const struct game thegame = { game_anim_length, game_flash_length, game_wants_statusbar, + FALSE, game_timing_state, + 0, /* mouse_priorities */ };