diff options
| author | Simon Tatham <anakin@pobox.com> | 2005-05-28 08:04:29 +0000 |
|---|---|---|
| committer | Simon Tatham <anakin@pobox.com> | 2005-05-28 08:04:29 +0000 |
| commit | c8362f0a94441e9d1538e69ae6bc667911804f2e (patch) | |
| tree | bb0d6df422800411938dffed6986802cb9b9da51 | |
| parent | c82820e55b5f1afe487ffd027e54e0d1b6c554ca (diff) | |
| download | puzzles-c8362f0a94441e9d1538e69ae6bc667911804f2e.zip puzzles-c8362f0a94441e9d1538e69ae6bc667911804f2e.tar.gz puzzles-c8362f0a94441e9d1538e69ae6bc667911804f2e.tar.bz2 puzzles-c8362f0a94441e9d1538e69ae6bc667911804f2e.tar.xz | |
Add the ability to use the Rectangles solver for actually solving
puzzles, rather than just doing its nondeterministic number
placement thing. This enables the use of the `Solve' menu option on
externally entered game IDs, provided of course that they aren't
_too_ difficult.
[originally from svn r5852]
| -rw-r--r-- | rect.c | 70 |
1 files changed, 64 insertions, 6 deletions
@@ -321,7 +321,7 @@ static void remove_number_placement(int w, int h, struct numberdata *number, } static int rect_solver(int w, int h, int nrects, struct numberdata *numbers, - random_state *rs) + game_state *result, random_state *rs) { struct rectlist *rectpositions; int *overlaps, *rectbyplace, *workspace; @@ -739,7 +739,7 @@ static int rect_solver(int w, int h, int nrects, struct numberdata *numbers, * rectangle) which overlaps a candidate placement of the * number for some other rectangle. */ - { + if (rs) { struct rpn { int rect; int placement; @@ -844,8 +844,28 @@ static int rect_solver(int w, int h, int nrects, struct numberdata *numbers, i, rectpositions[i].n); #endif assert(rectpositions[i].n > 0); - if (rectpositions[i].n > 1) + if (rectpositions[i].n > 1) { ret = FALSE; + } else if (result) { + /* + * Place the rectangle in its only possible position. + */ + int x, y; + struct rect *r = &rectpositions[i].rects[0]; + + for (y = 0; y < r->h; y++) { + if (r->x > 0) + vedge(result, r->x, r->y+y) = 1; + if (r->x+r->w < result->w) + vedge(result, r->x+r->w, r->y+y) = 1; + } + for (x = 0; x < r->w; x++) { + if (r->y > 0) + hedge(result, r->x+x, r->y) = 1; + if (r->y+r->h < result->h) + hedge(result, r->x+x, r->y+r->h) = 1; + } + } } /* @@ -1523,7 +1543,8 @@ static char *new_game_desc(game_params *params, random_state *rs, } if (params->unique) - ret = rect_solver(params->w, params->h, nnumbers, nd, rs); + ret = rect_solver(params->w, params->h, nnumbers, nd, + NULL, rs); else ret = TRUE; /* allow any number placement at all */ @@ -1748,8 +1769,45 @@ static game_state *solve_game(game_state *state, game_aux_info *ai, game_state *ret; if (!ai) { - *error = "Solution not known for this puzzle"; - return NULL; + int i, j, n; + struct numberdata *nd; + + /* + * Attempt the in-built solver. + */ + + /* Set up each number's (very short) candidate position list. */ + for (i = n = 0; i < state->h * state->w; i++) + if (state->grid[i]) + n++; + + nd = snewn(n, struct numberdata); + + for (i = j = 0; i < state->h * state->w; i++) + if (state->grid[i]) { + nd[j].area = state->grid[i]; + nd[j].npoints = 1; + nd[j].points = snewn(1, struct point); + nd[j].points[0].x = i % state->w; + nd[j].points[0].y = i / state->w; + j++; + } + + assert(j == n); + + ret = dup_game(state); + ret->cheated = TRUE; + + rect_solver(state->w, state->h, n, nd, ret, NULL); + + /* + * Clean up. + */ + for (i = 0; i < n; i++) + sfree(nd[i].points); + sfree(nd); + + return ret; } assert(state->w == ai->w); |