X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/957099664a88cb1c3d83949355ca87043ae63d9b..11c44cf574b43cec747d490cb264829a535ed42a:/fifteen.c diff --git a/fifteen.c b/fifteen.c index 7f6769a..2788604 100644 --- a/fifteen.c +++ b/fifteen.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "puzzles.h" @@ -19,8 +20,8 @@ const int game_can_configure = TRUE; #define COORD(x) ( (x) * TILE_SIZE + BORDER ) #define FROMCOORD(x) ( ((x) - BORDER + TILE_SIZE) / TILE_SIZE - 1 ) -#define ANIM_TIME 0.1F -#define FLASH_FRAME 0.1F +#define ANIM_TIME 0.13F +#define FLASH_FRAME 0.13F #define X(state, i) ( (i) % (state)->w ) #define Y(state, i) ( (i) / (state)->w ) @@ -72,6 +73,29 @@ game_params *dup_params(game_params *params) return ret; } +game_params *decode_params(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; +} + +char *encode_params(game_params *params) +{ + char data[256]; + + sprintf(data, "%dx%d", params->w, params->h); + + return dupstr(data); +} + config_item *game_configure(game_params *params) { config_item *ret; @@ -131,7 +155,7 @@ int perm_parity(int *perm, int n) return ret; } -char *new_game_seed(game_params *params) +char *new_game_seed(game_params *params, random_state *rs) { int gap, n, i, x; int x1, x2, p1, p2, parity; @@ -149,7 +173,7 @@ char *new_game_seed(game_params *params) used[i] = FALSE; } - gap = rand_upto(n); + gap = random_upto(rs, n); tiles[gap] = 0; used[0] = TRUE; @@ -157,7 +181,7 @@ char *new_game_seed(game_params *params) * Place everything else except the last two tiles. */ for (x = 0, i = n-1; i > 2; i--) { - int k = rand_upto(i); + int k = random_upto(rs, i); int j; for (j = 0; j < n; j++) @@ -199,15 +223,16 @@ char *new_game_seed(game_params *params) * Determine the required parity of the overall permutation. * This is the XOR of: * - * - The chessboard parity ((x^y)&1) of the gap square. The - * bottom right, and therefore also the top left, count as - * even. + * - The chessboard parity ((x^y)&1) of the gap square. The + * bottom right counts as even. * * - The parity of n. (The target permutation is 1,...,n-1,0 * rather than 0,...,n-1; this is a cyclic permutation of * the starting point and hence is odd iff n is even.) */ - parity = (X(params, gap) ^ Y(params, gap) ^ (n+1)) & 1; + parity = ((X(params, gap) - (params->w-1)) ^ + (Y(params, gap) - (params->h-1)) ^ + (n+1)) & 1; /* * Try the last two tiles one way round. If that fails, swap @@ -245,6 +270,57 @@ char *new_game_seed(game_params *params) return ret; } +char *validate_seed(game_params *params, char *seed) +{ + char *p, *err; + int i, area; + int *used; + + area = params->w * params->h; + p = seed; + err = NULL; + + used = snewn(area, int); + for (i = 0; i < area; i++) + used[i] = FALSE; + + for (i = 0; i < area; i++) { + char *q = p; + int n; + + if (*p < '0' || *p > '9') { + err = "Not enough numbers in string"; + goto leave; + } + while (*p >= '0' && *p <= '9') + p++; + if (i < area-1 && *p != ',') { + err = "Expected comma after number"; + goto leave; + } + else if (i == area-1 && *p) { + err = "Excess junk at end of string"; + goto leave; + } + n = atoi(q); + if (n < 0 || n >= area) { + err = "Number out of range"; + goto leave; + } + if (used[n]) { + err = "Number used twice"; + goto leave; + } + used[n] = TRUE; + + if (*p) p++; /* eat comma */ + } + + leave: + sfree(used); + return err; +} + game_state *new_game(game_params *params, char *seed) { game_state *state = snew(game_state); @@ -297,7 +373,16 @@ void free_game(game_state *state) sfree(state); } -game_state *make_move(game_state *from, int x, int y, int button) +game_ui *new_ui(game_state *state) +{ + return NULL; +} + +void free_ui(game_ui *ui) +{ +} + +game_state *make_move(game_state *from, game_ui *ui, int x, int y, int button) { int gx, gy, dx, dy, ux, uy, up, p; game_state *ret; @@ -467,7 +552,8 @@ static void draw_tile(frontend *fe, game_state *state, int x, int y, } void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, - game_state *state, float animtime, float flashtime) + game_state *state, game_ui *ui, + float animtime, float flashtime) { int i, pass, bgcolour;