chiark / gitweb /
I've changed my mind. For the benefit of users with slower
authorSimon Tatham <anakin@pobox.com>
Mon, 2 May 2005 16:59:50 +0000 (16:59 +0000)
committerSimon Tatham <anakin@pobox.com>
Mon, 2 May 2005 16:59:50 +0000 (16:59 +0000)
computers, let's save the Solo and Pattern grids at generation time
and regurgitate them when asked to solve, rather than doing all the
work over again.

[originally from svn r5737]

pattern.c
solo.c

index 0f0a9c62c8518a90060342482769887bbe109918..a728e15d34dc10b8a760f034d63d5490b2ce605b 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -472,6 +472,11 @@ 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_seed(game_params *params, random_state *rs,
                           game_aux_info **aux)
 {
@@ -484,6 +489,20 @@ static char *new_game_seed(game_params *params, random_state *rs,
     max = max(params->w, params->h);
     rowdata = snewn(max, int);
 
+    /*
+     * Save the solved game in an aux_info.
+     */
+    {
+       game_aux_info *ai = snew(game_aux_info);
+
+       ai->w = params->w;
+       ai->h = params->h;
+       ai->grid = snewn(ai->w * ai->h, unsigned char);
+       memcpy(ai->grid, grid, ai->w * ai->h);
+
+       *aux = ai;
+    }
+
     /*
      * Seed is a slash-separated list of row contents; each row
      * contents section is a dot-separated list of integers. Row
@@ -539,7 +558,8 @@ static char *new_game_seed(game_params *params, random_state *rs,
 
 static void game_free_aux_info(game_aux_info *aux)
 {
-    assert(!"Shouldn't happen");
+    sfree(aux->grid);
+    sfree(aux);
 }
 
 static char *validate_seed(game_params *params, char *seed)
@@ -651,21 +671,25 @@ static void free_game(game_state *state)
     sfree(state);
 }
 
-static game_state *solve_game(game_state *state, game_aux_info *aux,
+static game_state *solve_game(game_state *state, game_aux_info *ai,
                              char **error)
 {
     game_state *ret;
 
+    ret = dup_game(state);
+    ret->completed = ret->cheated = TRUE;
+
     /*
-     * I could have stored the grid I invented in the game_aux_info
-     * and extracted it here where available, but it seems easier
-     * just to run my internal solver in all cases.
+     * If we already have the solved state in an aux_info, copy it
+     * out.
      */
+    if (ai) {
 
-    ret = dup_game(state);
-    ret->completed = ret->cheated = TRUE;
+       assert(ret->w == ai->w);
+       assert(ret->h == ai->h);
+       memcpy(ret->grid, ai->grid, ai->w * ai->h);
 
-    {
+    } else {
        int w = state->w, h = state->h, i, j, done_any, max;
        unsigned char *matrix, *workspace;
        int *rowdata;
diff --git a/solo.c b/solo.c
index dc3bbc49458b1f7c4dbae51a58a2edf05263b47e..eb35e009cfb453b9be21dfdd8c37a7d2fa2d6bdf 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -1351,6 +1351,11 @@ 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 *new_game_seed(game_params *params, random_state *rs,
                           game_aux_info **aux)
 {
@@ -1394,6 +1399,18 @@ static char *new_game_seed(game_params *params, random_state *rs,
         assert(ret == 1);
         assert(check_valid(c, r, grid));
 
+       /*
+        * Save the solved grid in the aux_info.
+        */
+       {
+           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));
+           *aux = ai;
+       }
+
         /*
          * Now we have a solved grid, start removing things from it
          * while preserving solubility.
@@ -1516,7 +1533,8 @@ static char *new_game_seed(game_params *params, random_state *rs,
 
 static void game_free_aux_info(game_aux_info *aux)
 {
-    assert(!"Shouldn't happen");
+    sfree(aux->grid);
+    sfree(aux);
 }
 
 static char *validate_seed(game_params *params, char *seed)
@@ -1614,31 +1632,37 @@ static void free_game(game_state *state)
     sfree(state);
 }
 
-static game_state *solve_game(game_state *state, game_aux_info *aux,
+static game_state *solve_game(game_state *state, game_aux_info *ai,
                              char **error)
 {
     game_state *ret;
-    int c = state->c, r = state->r;
+    int c = state->c, r = state->r, cr = c*r;
     int rsolve_ret;
 
-    /*
-     * I could have stored the grid I invented in the game_aux_info
-     * and extracted it here where available, but it seems easier
-     * just to run my internal solver in all cases.
-     */
-
     ret = dup_game(state);
     ret->completed = ret->cheated = TRUE;
 
-    rsolve_ret = rsolve(c, r, ret->grid, NULL, 2);
+    /*
+     * If we already have the solution in the aux_info, save
+     * ourselves some time.
+     */
+    if (ai) {
+
+       assert(c == ai->c);
+       assert(r == ai->r);
+       memcpy(ret->grid, ai->grid, cr * cr * sizeof(digit));
 
-    if (rsolve_ret != 1) {
-       free_game(ret);
-       if (rsolve_ret == 0)
-           *error = "No solution exists for this puzzle";
-       else
-           *error = "Multiple solutions exist for this puzzle";
-       return NULL;
+    } else {
+       rsolve_ret = rsolve(c, r, ret->grid, NULL, 2);
+
+       if (rsolve_ret != 1) {
+           free_game(ret);
+           if (rsolve_ret == 0)
+               *error = "No solution exists for this puzzle";
+           else
+               *error = "Multiple solutions exist for this puzzle";
+           return NULL;
+       }
     }
 
     return ret;