X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/ae8290c655dec864db8ef0dc6b59891d6434c71f..871bf2946c5cbfdc7621c4b3d6850af0699297a0:/pattern.c diff --git a/pattern.c b/pattern.c index 115e813..b7c5334 100644 --- a/pattern.c +++ b/pattern.c @@ -30,7 +30,7 @@ enum { ( ((x) - (BORDER + GUTTER + TILE_SIZE * TLBORDER(d))) / TILE_SIZE ) #define SIZE(d) (2*BORDER + GUTTER + TILE_SIZE * (TLBORDER(d) + (d))) -#define GETTILESIZE(d, w) (w / (2 + TLBORDER(d) + (d))) +#define GETTILESIZE(d, w) ((double)w / (2.0 + (double)TLBORDER(d) + (double)(d))) #define TOCOORD(d, x) (BORDER + GUTTER + TILE_SIZE * (TLBORDER(d) + (x))) @@ -466,13 +466,8 @@ static unsigned char *generate_soluble(random_state *rs, int w, int h) return grid; } -struct game_aux_info { - int w, h; - unsigned char *grid; -}; - static char *new_game_desc(game_params *params, random_state *rs, - game_aux_info **aux, int interactive) + char **aux, int interactive) { unsigned char *grid; int i, j, max, rowlen, *rowdata; @@ -484,14 +479,22 @@ static char *new_game_desc(game_params *params, random_state *rs, rowdata = snewn(max, int); /* - * Save the solved game in an aux_info. + * Save the solved game in aux. */ { - game_aux_info *ai = snew(game_aux_info); + char *ai = snewn(params->w * params->h + 2, char); + + /* + * String format is exactly the same as a solve move, so we + * can just dupstr this in solve_game(). + */ - ai->w = params->w; - ai->h = params->h; - ai->grid = grid; + ai[0] = 'S'; + + for (i = 0; i < params->w * params->h; i++) + ai[i+1] = grid[i] ? '1' : '0'; + + ai[params->w * params->h + 1] = '\0'; *aux = ai; } @@ -546,15 +549,10 @@ static char *new_game_desc(game_params *params, random_state *rs, assert(desc[desclen-1] == '/'); desc[desclen-1] = '\0'; sfree(rowdata); + sfree(grid); return desc; } -static void game_free_aux_info(game_aux_info *aux) -{ - sfree(aux->grid); - sfree(aux); -} - static char *validate_desc(game_params *params, char *desc) { int i, n, rowspace; @@ -665,81 +663,66 @@ static void free_game(game_state *state) } static char *solve_game(game_state *state, game_state *currstate, - game_aux_info *ai, char **error) + char *ai, char **error) { unsigned char *matrix; - int matrix_needs_freeing; - int full, empty; int w = state->w, h = state->h; int i; char *ret; + int done_any, max; + unsigned char *workspace; + int *rowdata; /* - * If we already have the solved state in an aux_info, copy it - * out. + * If we already have the solved state in ai, copy it out. */ - if (ai) { - assert(ai->w == w && ai->h == h); - - matrix = ai->grid; - matrix_needs_freeing = FALSE; - full = GRID_FULL; - empty = GRID_EMPTY; - } else { - int done_any, max; - unsigned char *workspace; - int *rowdata; - - matrix = snewn(w*h, unsigned char); - max = max(w, h); - workspace = snewn(max*3, unsigned char); - rowdata = snewn(max+1, int); + if (ai) + return dupstr(ai); - memset(matrix, 0, w*h); + matrix = snewn(w*h, unsigned char); + max = max(w, h); + workspace = snewn(max*3, unsigned char); + rowdata = snewn(max+1, int); - do { - done_any = 0; - for (i=0; irowdata + state->rowsize*(w+i), - max*sizeof(int)); - rowdata[state->rowlen[w+i]] = 0; - done_any |= do_row(workspace, workspace+max, workspace+2*max, - matrix+i*w, w, 1, rowdata); - } - for (i=0; irowdata + state->rowsize*i, max*sizeof(int)); - rowdata[state->rowlen[i]] = 0; - done_any |= do_row(workspace, workspace+max, workspace+2*max, - matrix+i, h, w, rowdata); - } - } while (done_any); + memset(matrix, 0, w*h); - sfree(workspace); - sfree(rowdata); + do { + done_any = 0; + for (i=0; irowdata + state->rowsize*(w+i), + max*sizeof(int)); + rowdata[state->rowlen[w+i]] = 0; + done_any |= do_row(workspace, workspace+max, workspace+2*max, + matrix+i*w, w, 1, rowdata); + } + for (i=0; irowdata + state->rowsize*i, max*sizeof(int)); + rowdata[state->rowlen[i]] = 0; + done_any |= do_row(workspace, workspace+max, workspace+2*max, + matrix+i, h, w, rowdata); + } + } while (done_any); - for (i = 0; i < w*h; i++) { - if (matrix[i] != BLOCK && matrix[i] != DOT) { - sfree(matrix); - *error = "Solving algorithm cannot complete this puzzle"; - return NULL; - } - } + sfree(workspace); + sfree(rowdata); - matrix_needs_freeing = TRUE; - full = BLOCK; - empty = DOT; + for (i = 0; i < w*h; i++) { + if (matrix[i] != BLOCK && matrix[i] != DOT) { + sfree(matrix); + *error = "Solving algorithm cannot complete this puzzle"; + return NULL; + } } ret = snewn(w*h+2, char); ret[0] = 'S'; for (i = 0; i < w*h; i++) { - assert(matrix[i] == full || matrix[i] == empty); - ret[i+1] = (matrix[i] == full ? '1' : '0'); + assert(matrix[i] == BLOCK || matrix[i] == DOT); + ret[i+1] = (matrix[i] == BLOCK ? '1' : '0'); } ret[w*h+1] = '\0'; - if (matrix_needs_freeing) - sfree(matrix); + sfree(matrix); return ret; } @@ -773,12 +756,12 @@ static void free_ui(game_ui *ui) sfree(ui); } -char *encode_ui(game_ui *ui) +static char *encode_ui(game_ui *ui) { return NULL; } -void decode_ui(game_ui *ui, char *encoding) +static void decode_ui(game_ui *ui, char *encoding) { } @@ -876,8 +859,8 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, if (move_needed) { char buf[80]; sprintf(buf, "%c%d,%d,%d,%d", - (ui->state == GRID_FULL ? 'F' : - ui->state == GRID_EMPTY ? 'E' : 'U'), + (char)(ui->state == GRID_FULL ? 'F' : + ui->state == GRID_EMPTY ? 'E' : 'U'), x1, y1, x2-x1+1, y2-y1+1); return dupstr(buf); } else @@ -965,13 +948,13 @@ static game_state *execute_move(game_state *from, char *move) static void game_size(game_params *params, game_drawstate *ds, int *x, int *y, int expand) { - int ts; + double ts; ts = min(GETTILESIZE(params->w, *x), GETTILESIZE(params->h, *y)); if (expand) - ds->tilesize = ts; + ds->tilesize = (int)(ts + 0.5); else - ds->tilesize = min(ts, PREFERRED_TILE_SIZE); + ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE); *x = SIZE(params->w); *y = SIZE(params->h); @@ -1194,7 +1177,6 @@ const struct game thegame = { TRUE, game_configure, custom_params, validate_params, new_game_desc, - game_free_aux_info, validate_desc, new_game, dup_game,