shithub: puzzles

Download patch

ref: b32b4f87632e97dbdaeb5813183879507e494626
parent: cf7988afb39eacb608eeacc73eb08a42db91b3d4
author: Simon Tatham <anakin@pobox.com>
date: Mon May 2 12:59:50 EDT 2005

I've changed my mind. For the benefit of users with slower
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]

--- a/pattern.c
+++ b/pattern.c
@@ -472,6 +472,11 @@
     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)
 {
@@ -485,6 +490,20 @@
     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
      * contents are listed in the order (columns left to right,
@@ -539,7 +558,8 @@
 
 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 @@
     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;
--- a/solo.c
+++ b/solo.c
@@ -1351,6 +1351,11 @@
     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 @@
         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 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 @@
     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;
 
+    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 solution in the aux_info, save
+     * ourselves some time.
      */
+    if (ai) {
 
-    ret = dup_game(state);
-    ret->completed = ret->cheated = TRUE;
+	assert(c == ai->c);
+	assert(r == ai->r);
+	memcpy(ret->grid, ai->grid, cr * cr * sizeof(digit));
 
-    rsolve_ret = rsolve(c, r, ret->grid, NULL, 2);
+    } 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;
+	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;