X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/df11cd4e43b66b17df44a1e933f5c71361dc13a4..937a9efffe3be5ecb6c6b9fb6596644d05aed3d9:/solo.c diff --git a/solo.c b/solo.c index 74ca872..881589e 100644 --- a/solo.c +++ b/solo.c @@ -321,7 +321,7 @@ static game_params *custom_params(config_item *cfg) return ret; } -static char *validate_params(game_params *params) +static char *validate_params(game_params *params, int full) { if (params->c < 2 || params->r < 2) return "Both dimensions must be at least 2"; @@ -1419,13 +1419,51 @@ static int symmetries(game_params *params, int x, int y, int *output, int s) return i; } -struct game_aux_info { - int c, r; - digit *grid; -}; +static char *encode_solve_move(int cr, digit *grid) +{ + int i, len; + char *ret, *p, *sep; + + /* + * It's surprisingly easy to work out _exactly_ how long this + * string needs to be. To decimal-encode all the numbers from 1 + * to n: + * + * - every number has a units digit; total is n. + * - all numbers above 9 have a tens digit; total is max(n-9,0). + * - all numbers above 99 have a hundreds digit; total is max(n-99,0). + * - and so on. + */ + len = 0; + for (i = 1; i <= cr; i *= 10) + len += max(cr - i + 1, 0); + len += cr; /* don't forget the commas */ + len *= cr; /* there are cr rows of these */ + + /* + * Now len is one bigger than the total size of the + * comma-separated numbers (because we counted an + * additional leading comma). We need to have a leading S + * and a trailing NUL, so we're off by one in total. + */ + len++; + + ret = snewn(len, char); + p = ret; + *p++ = 'S'; + sep = ""; + for (i = 0; i < cr*cr; i++) { + p += sprintf(p, "%s%d", sep, grid[i]); + sep = ","; + } + *p++ = '\0'; + assert(p - ret == len); + + return ret; +} static char *new_game_desc(game_params *params, random_state *rs, - game_aux_info **aux, int interactive) + char **aux, int interactive) { int c = params->c, r = params->r, cr = c*r; int area = cr*cr; @@ -1493,25 +1531,19 @@ static char *new_game_desc(game_params *params, random_state *rs, assert(check_valid(c, r, grid)); /* - * Save the solved grid in the aux_info. + * Save the solved grid in aux. */ { - game_aux_info *ai = snew(game_aux_info); - ai->c = c; - ai->r = r; - ai->grid = snewn(cr * cr, digit); - memcpy(ai->grid, grid, cr * cr * sizeof(digit)); /* * We might already have written *aux the last time we * went round this loop, in which case we should free - * the old aux_info before overwriting it with the new - * one. + * the old aux before overwriting it with the new one. */ if (*aux) { - sfree((*aux)->grid); sfree(*aux); } - *aux = ai; + + *aux = encode_solve_move(cr, grid); } /* @@ -1652,12 +1684,6 @@ static char *new_game_desc(game_params *params, random_state *rs, 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 area = params->r * params->r * params->c * params->c; @@ -1760,81 +1786,36 @@ 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) { int c = state->c, r = state->r, cr = c*r; - int i, len; - char *ret, *p, *sep; + char *ret; digit *grid; - int grid_needs_freeing; + int rsolve_ret; /* - * If we already have the solution in the aux_info, save - * ourselves some time. + * If we already have the solution in ai, save ourselves some + * time. */ - if (ai) { + if (ai) + return dupstr(ai); - assert(c == ai->c); - assert(r == ai->r); - grid = ai->grid; - grid_needs_freeing = FALSE; + grid = snewn(cr*cr, digit); + memcpy(grid, state->grid, cr*cr); + rsolve_ret = rsolve(c, r, grid, NULL, 2); - } else { - int rsolve_ret; - - grid = snewn(cr*cr, digit); - memcpy(grid, state->grid, cr*cr); - rsolve_ret = rsolve(c, r, grid, NULL, 2); - - if (rsolve_ret != 1) { - sfree(grid); - if (rsolve_ret == 0) - *error = "No solution exists for this puzzle"; - else - *error = "Multiple solutions exist for this puzzle"; - return NULL; - } - - grid_needs_freeing = TRUE; + if (rsolve_ret != 1) { + sfree(grid); + if (rsolve_ret == 0) + *error = "No solution exists for this puzzle"; + else + *error = "Multiple solutions exist for this puzzle"; + return NULL; } - /* - * It's surprisingly easy to work out _exactly_ how long this - * string needs to be. To decimal-encode all the numbers from 1 - * to n: - * - * - every number has a units digit; total is n. - * - all numbers above 9 have a tens digit; total is max(n-9,0). - * - all numbers above 99 have a hundreds digit; total is max(n-99,0). - * - and so on. - */ - len = 0; - for (i = 1; i <= cr; i *= 10) - len += max(cr - i + 1, 0); - len += cr; /* don't forget the commas */ - len *= cr; /* there are cr rows of these */ - - /* - * Now len is one bigger than the total size of the - * comma-separated numbers (because we counted an - * additional leading comma). We need to have a leading S - * and a trailing NUL, so we're off by one in total. - */ - len++; - - ret = snewn(len, char); - p = ret; - *p++ = 'S'; - sep = ""; - for (i = 0; i < cr*cr; i++) { - p += sprintf(p, "%s%d", sep, grid[i]); - sep = ","; - } - *p++ = '\0'; - assert(p - ret == len); + ret = encode_solve_move(cr, grid); - if (grid_needs_freeing) - sfree(grid); + sfree(grid); return ret; } @@ -1931,6 +1912,15 @@ static void free_ui(game_ui *ui) sfree(ui); } +static char *encode_ui(game_ui *ui) +{ + return NULL; +} + +static void decode_ui(game_ui *ui, char *encoding) +{ +} + static void game_changed_state(game_ui *ui, game_state *oldstate, game_state *newstate) { @@ -2034,7 +2024,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, return NULL; sprintf(buf, "%c%d,%d,%d", - ui->hpencil && n > 0 ? 'P' : 'R', ui->hx, ui->hy, n); + (char)(ui->hpencil && n > 0 ? 'P' : 'R'), ui->hx, ui->hy, n); ui->hx = ui->hy = -1; @@ -2100,22 +2090,23 @@ static game_state *execute_move(game_state *from, char *move) */ #define SIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1) -#define GETTILESIZE(cr, w) ( (w-1) / (cr+1) ) +#define GETTILESIZE(cr, w) ( (double)(w-1) / (double)(cr+1) ) -static void game_size(game_params *params, game_drawstate *ds, - int *x, int *y, int expand) +static void game_compute_size(game_params *params, int tilesize, + int *x, int *y) { - int c = params->c, r = params->r, cr = c*r; - int ts; + /* Ick: fake up `ds->tilesize' for macro expansion purposes */ + struct { int tilesize; } ads, *ds = &ads; + ads.tilesize = tilesize; - ts = min(GETTILESIZE(cr, *x), GETTILESIZE(cr, *y)); - if (expand) - ds->tilesize = ts; - else - ds->tilesize = min(ts, PREFERRED_TILE_SIZE); + *x = SIZE(params->c * params->r); + *y = SIZE(params->c * params->r); +} - *x = SIZE(cr); - *y = SIZE(cr); +static void game_set_size(game_drawstate *ds, game_params *params, + int tilesize) +{ + ds->tilesize = tilesize; } static float *game_colours(frontend *fe, game_state *state, int *ncolours) @@ -2225,7 +2216,7 @@ static void draw_number(frontend *fe, game_drawstate *ds, game_state *state, coords[3] = cy; coords[4] = cx; coords[5] = cy+ch/2; - draw_polygon(fe, coords, 3, TRUE, COL_HIGHLIGHT); + draw_polygon(fe, coords, 3, COL_HIGHLIGHT, COL_HIGHLIGHT); } /* new number needs drawing? */ @@ -2411,7 +2402,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, @@ -2420,10 +2410,12 @@ const struct game thegame = { TRUE, game_text_format, new_ui, free_ui, + encode_ui, + decode_ui, game_changed_state, interpret_move, execute_move, - game_size, + PREFERRED_TILE_SIZE, game_compute_size, game_set_size, game_colours, game_new_drawstate, game_free_drawstate, @@ -2447,7 +2439,7 @@ void draw_text(frontend *fe, int x, int y, int fonttype, int fontsize, void draw_rect(frontend *fe, int x, int y, int w, int h, int colour) {} void draw_line(frontend *fe, int x1, int y1, int x2, int y2, int colour) {} void draw_polygon(frontend *fe, int *coords, int npoints, - int fill, int colour) {} + int fillcolour, int outlinecolour) {} void clip(frontend *fe, int x, int y, int w, int h) {} void unclip(frontend *fe) {} void start_draw(frontend *fe) {} @@ -2478,7 +2470,6 @@ int main(int argc, char **argv) game_state *s; int recurse = TRUE; char *id = NULL, *desc, *err; - int y, x; int grade = FALSE; while (--argc > 0) { @@ -2494,7 +2485,7 @@ int main(int argc, char **argv) grade = TRUE; recurse = FALSE; } else if (*p == '-') { - fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0]); + fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p); return 1; } else { id = p;