chiark / gitweb /
More serialisation changes: the game_aux_info structure has now been
authorSimon Tatham <anakin@pobox.com>
Tue, 28 Jun 2005 11:14:09 +0000 (11:14 +0000)
committerSimon Tatham <anakin@pobox.com>
Tue, 28 Jun 2005 11:14:09 +0000 (11:14 +0000)
retired, and replaced with a simple string. Most of the games which
use it simply encode the string in the same way that the Solve move
will also be encoded, i.e. solve_game() simply returns
dupstr(aux_info). Again, this is a better approach than writing
separate game_aux_info serialise/deserialise functions because doing
it this way is self-testing (the strings are created and parsed
during the course of any Solve operation at all).

[originally from svn r6029]

17 files changed:
cube.c
fifteen.c
flip.c
gtk.c
guess.c
midend.c
mines.c
net.c
netslide.c
nullgame.c
pattern.c
puzzles.h
rect.c
samegame.c
sixteen.c
solo.c
twiddle.c

diff --git a/cube.c b/cube.c
index 57246e4dcbd0a97fbce33b797078c9bd6ac6f5ab..01450624034a8ff4125e7b6d3aaa2e0b5edf0cc1 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -586,7 +586,7 @@ static void classify_grid_square_callback(void *ctx, struct grid_square *sq)
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     struct grid_data data;
     int i, j, k, m, area, facesperclass;
@@ -687,11 +687,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return desc;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static void add_grid_square_callback(void *ctx, struct grid_square *sq)
 {
     game_state *state = (game_state *)ctx;
@@ -985,7 +980,7 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     return NULL;
 }
@@ -1714,7 +1709,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,
index ad7381c3e07c0564c146c8841eb80009b0dbde2e..d7a0c45b5c0456cdf0ae9082e52dba96c23049ef 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
@@ -152,7 +152,7 @@ static int perm_parity(int *perm, int n)
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     int gap, n, i, x;
     int x1, x2, p1, p2, parity;
@@ -267,11 +267,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return ret;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     char *p, *err;
@@ -380,7 +375,7 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     return dupstr("S");
 }
@@ -882,7 +877,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,
diff --git a/flip.c b/flip.c
index 1d7fa172e5623b91e6a0123ed837779a3a6ab46c..ce8202c7ae023a84ba4d92418bd561391ac8356d 100644 (file)
--- a/flip.c
+++ b/flip.c
@@ -347,7 +347,7 @@ static void addneighbours(tree234 *t, int w, int h, int cx, int cy,
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     int w = params->w, h = params->h, wh = w * h;
     int i, j;
@@ -595,11 +595,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return ret;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     int w = params->w, h = params->h, wh = w * h;
@@ -676,7 +671,7 @@ static void rowxor(unsigned char *row1, unsigned char *row2, int len)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     int w = state->w, h = state->h, wh = w * h;
     unsigned char *equations, *solution, *shortest;
@@ -1229,7 +1224,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,
diff --git a/gtk.c b/gtk.c
index 05d7ad44466e02804f2ed27f926f9053ae851115..88f4a0a0431350191e737bef007bb5876e4feaa4 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -1500,12 +1500,11 @@ int main(int argc, char **argv)
        }
 
        while (n-- > 0) {
-           game_aux_info *aux = NULL;
+           char *aux = NULL;
            char *desc = thegame.new_desc(par, rs, &aux, FALSE);
            printf("%s:%s\n", parstr, desc);
            sfree(desc);
-           if (aux)
-               thegame.free_aux_info(aux);
+            sfree(aux);
        }
 
        return 0;
diff --git a/guess.c b/guess.c
index e681d169defe3f1ed7f16e2664b095bfecb47897..613bc590eafa505366a123d28812cccb9781dfcc 100644 (file)
--- a/guess.c
+++ b/guess.c
@@ -264,7 +264,7 @@ static void free_pegrow(pegrow pegs)
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     unsigned char *bmp = snewn(params->npegs, unsigned char);
     char *ret;
@@ -286,11 +286,6 @@ newcol:
     return ret;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     unsigned char *bmp;
@@ -365,7 +360,7 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     return dupstr("S");
 }
@@ -1260,7 +1255,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,
index e5458414e5db73b88209a20cb22d18f446455304..a6d2d40a8861a0fe83f81268a97eb340ad140a12 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -48,7 +48,7 @@ struct midend_data {
      * may also be typed directly into Mines if you like.)
      */
     char *desc, *privdesc, *seedstr;
-    game_aux_info *aux_info;
+    char *aux_info;
     enum { GOT_SEED, GOT_DESC, GOT_NOTHING } genmode;
     int nstates, statesize, statepos;
 
@@ -140,8 +140,7 @@ void midend_free(midend_data *me)
     sfree(me->states);
     sfree(me->desc);
     sfree(me->seedstr);
-    if (me->aux_info)
-       me->ourgame->free_aux_info(me->aux_info);
+    sfree(me->aux_info);
     me->ourgame->free_params(me->params);
     if (me->npresets) {
        for (i = 0; i < me->npresets; i++) {
@@ -235,8 +234,7 @@ void midend_new_game(midend_data *me)
 
        sfree(me->desc);
        sfree(me->privdesc);
-       if (me->aux_info)
-           me->ourgame->free_aux_info(me->aux_info);
+        sfree(me->aux_info);
        me->aux_info = NULL;
 
         rs = random_init(me->seedstr, strlen(me->seedstr));
@@ -634,13 +632,12 @@ float *midend_colours(midend_data *me, int *ncolours)
     float *ret;
 
     if (me->nstates == 0) {
-       game_aux_info *aux = NULL;
+       char *aux = NULL;
         char *desc = me->ourgame->new_desc(me->params, me->random,
                                           &aux, TRUE);
         state = me->ourgame->new_game(me, me->params, desc);
         sfree(desc);
-       if (aux)
-           me->ourgame->free_aux_info(aux);
+        sfree(aux);
     } else
         state = me->states[0].state;
 
@@ -925,8 +922,7 @@ static char *midend_game_id_int(midend_data *me, char *id, int defmode)
 
         me->desc = dupstr(desc);
         me->genmode = GOT_DESC;
-       if (me->aux_info)
-           me->ourgame->free_aux_info(me->aux_info);
+        sfree(me->aux_info);
        me->aux_info = NULL;
     }
 
diff --git a/mines.c b/mines.c
index f9f714bf589a4c340cf638988519b1b56838a239..157c0ea44591d1454c60f7e536d91ed41fc36c5a 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -1946,7 +1946,7 @@ static char *new_mine_layout(int w, int h, int n, int x, int y, int unique,
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     /*
      * We generate the coordinates of an initial click even if they
@@ -1984,11 +1984,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     }
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     int wh = params->w * params->h;
@@ -2298,7 +2293,7 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     if (!state->layout->mines) {
        *error = "Game has not been started yet";
@@ -3045,7 +3040,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,
diff --git a/net.c b/net.c
index 3b1339a70fd6f4a19b7d43d14f657a8fb1031e7d..7c14f6f68ef396c4cb469ce773cf83c2ea617a48 100644 (file)
--- a/net.c
+++ b/net.c
@@ -77,11 +77,6 @@ struct game_params {
     float barrier_probability;
 };
 
-struct game_aux_info {
-    int width, height;
-    unsigned char *tiles;
-};
-
 struct game_state {
     int width, height, wrapping, completed;
     int last_rotate_x, last_rotate_y, last_rotate_dir;
@@ -1139,7 +1134,7 @@ static void perturb(int w, int h, unsigned char *tiles, int wrapping,
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     tree234 *possibilities, *barriertree;
     int w, h, x, y, cx, cy, nbarriers;
@@ -1401,16 +1396,16 @@ static char *new_game_desc(game_params *params, random_state *rs,
     }
 
     /*
-     * Save the unshuffled grid in an aux_info.
+     * Save the unshuffled grid in aux.
      */
     {
-       game_aux_info *solution;
+       char *solution;
+        int i;
 
-       solution = snew(game_aux_info);
-       solution->width = w;
-       solution->height = h;
-       solution->tiles = snewn(w * h, unsigned char);
-       memcpy(solution->tiles, tiles, w * h);
+       solution = snewn(w * h + 1, char);
+        for (i = 0; i < w * h; i++)
+            solution[i] = "0123456789abcdef"[tiles[i] & 0xF];
+        solution[w*h] = '\0';
 
        *aux = solution;
     }
@@ -1515,12 +1510,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->tiles);
-    sfree(aux);
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     int w = params->width, h = params->height;
@@ -1667,27 +1656,34 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     unsigned char *tiles;
     char *ret;
     int retlen, retsize;
     int i;
-    int tiles_need_freeing;
+
+    tiles = snewn(state->width * state->height, unsigned char);
 
     if (!aux) {
        /*
         * Run the internal solver on the provided grid. This might
         * not yield a complete solution.
         */
-       tiles = snewn(state->width * state->height, unsigned char);
        memcpy(tiles, state->tiles, state->width * state->height);
        net_solver(state->width, state->height, tiles,
                   state->barriers, state->wrapping);
-       tiles_need_freeing = TRUE;
     } else {
-       tiles = aux->tiles;
-       tiles_need_freeing = FALSE;
+        for (i = 0; i < state->width * state->height; i++) {
+            int c = aux[i];
+
+            if (c >= '0' && c <= '9')
+                tiles[i] = c - '0';
+            else if (c >= 'a' && c <= 'f')
+                tiles[i] = c - 'a' + 10;
+            else if (c >= 'A' && c <= 'F')
+                tiles[i] = c - 'A' + 10;
+        }
     }
 
     /*
@@ -1747,6 +1743,8 @@ static char *solve_game(game_state *state, game_state *currstate,
     ret[retlen] = '\0';
     ret = sresize(ret, retlen+1, char);
 
+    sfree(tiles);
+
     return ret;
 }
 
@@ -2747,7 +2745,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,
index b2b50e84c2029ff19a6bd219a90984d5b3ae77aa..397508e47cc57f89a62105a5261f3a4ea822ecdd 100644 (file)
@@ -82,11 +82,6 @@ struct game_params {
     int movetarget;
 };
 
-struct game_aux_info {
-    int width, height;
-    unsigned char *tiles;
-};
-
 struct game_state {
     int width, height, cx, cy, wrapping, completed;
     int used_solve, just_used_solve;
@@ -330,7 +325,7 @@ static char *validate_params(game_params *params)
  */
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     tree234 *possibilities, *barriertree;
     int w, h, x, y, cx, cy, nbarriers;
@@ -535,19 +530,22 @@ static char *new_game_desc(game_params *params, random_state *rs,
     }
 
     /*
-     * Save the unshuffled grid. We do this using a separate
-     * reference-counted structure since it's a large chunk of
-     * memory which we don't want to have to replicate in every
-     * game state while playing.
+     * Save the unshuffled grid in aux.
      */
     {
-        game_aux_info *solution;
+       char *solution;
+        int i;
+
+        /*
+         * String format is exactly the same as a solve move, so we
+         * can just dupstr this in solve_game().
+         */
 
-       solution = snew(game_aux_info);
-       solution->width = w;
-       solution->height = h;
-       solution->tiles = snewn(w * h, unsigned char);
-       memcpy(solution->tiles, tiles, w * h);
+       solution = snewn(w * h + 2, char);
+        solution[0] = 'S';
+        for (i = 0; i < w * h; i++)
+            solution[i+1] = "0123456789abcdef"[tiles[i] & 0xF];
+        solution[w*h+1] = '\0';
 
        *aux = solution;
     }
@@ -698,12 +696,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->tiles);
-    sfree(aux);
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     int w = params->width, h = params->height;
@@ -894,24 +886,14 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
-    char *ret;
-    int i;
-
     if (!aux) {
        *error = "Solution not known for this puzzle";
        return NULL;
     }
 
-    assert(aux->width == state->width);
-    assert(aux->height == state->height);
-    ret = snewn(aux->width * aux->height + 2, char);
-    ret[0] = 'S';
-    for (i = 0; i < aux->width * aux->height; i++)
-       ret[i+1] = "0123456789abcdef"[aux->tiles[i] & 0xF];
-    ret[i+1] = '\0';
-    return ret;
+    return dupstr(aux);
 }
 
 static char *game_text_format(game_state *state)
@@ -1822,7 +1804,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,
index 46f903f461adf9739f959d9295eb3868d888a1c1..26307e11452e2225e551a00c2cf01c8e85c634b9 100644 (file)
@@ -84,16 +84,11 @@ static char *validate_params(game_params *params)
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     return dupstr("FIXME");
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     return NULL;
@@ -123,7 +118,7 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     return NULL;
 }
@@ -255,7 +250,6 @@ const struct game thegame = {
     FALSE, game_configure, custom_params,
     validate_params,
     new_game_desc,
-    game_free_aux_info,
     validate_desc,
     new_game,
     dup_game,
index 115e8137b6858d3057b769235ed350f41f74ee44..671b56f5cf014e6069e62808415ca2d47d264d01 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -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;
     }
@@ -549,12 +552,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 i, n, rowspace;
@@ -665,81 +662,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; i<h; i++) {
-               memcpy(rowdata, state->rowdata + 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; i<w; i++) {
-               memcpy(rowdata, state->rowdata + 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; i<h; i++) {
+            memcpy(rowdata, state->rowdata + 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; i<w; i++) {
+            memcpy(rowdata, state->rowdata + 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;
 }
@@ -1194,7 +1176,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,
index 17b0b007a0d40b24826e17c6d4421e8b1b140389..5ee391b0bb97fc36c1b2e39e5581c1122238e451 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -70,7 +70,6 @@ typedef struct midend_data midend_data;
 typedef struct random_state random_state;
 typedef struct game_params game_params;
 typedef struct game_state game_state;
-typedef struct game_aux_info game_aux_info;
 typedef struct game_ui game_ui;
 typedef struct game_drawstate game_drawstate;
 typedef struct game game;
@@ -262,15 +261,14 @@ struct game {
     game_params *(*custom_params)(config_item *cfg);
     char *(*validate_params)(game_params *params);
     char *(*new_desc)(game_params *params, random_state *rs,
-                     game_aux_info **aux, int interactive);
-    void (*free_aux_info)(game_aux_info *aux);
+                     char **aux, int interactive);
     char *(*validate_desc)(game_params *params, char *desc);
     game_state *(*new_game)(midend_data *me, game_params *params, char *desc);
     game_state *(*dup_game)(game_state *state);
     void (*free_game)(game_state *state);
     int can_solve;
     char *(*solve)(game_state *orig, game_state *curr,
-                  game_aux_info *aux, char **error);
+                   char *aux, char **error);
     int can_format_as_text;
     char *(*text_format)(game_state *state);
     game_ui *(*new_ui)(game_state *state);
diff --git a/rect.c b/rect.c
index ca8c04bad916478fb779791de0eb5261737c5567..f4ce74b8a9bda23c630d6a9fa85e95ff2d5e77b8 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -1117,14 +1117,8 @@ static void display_grid(game_params *params, int *grid, int *numbers, int all)
 }
 #endif
 
-struct game_aux_info {
-    int w, h;
-    unsigned char *vedge;             /* (w+1) x h */
-    unsigned char *hedge;             /* w x (h+1) */
-};
-
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     int *grid, *numbers = NULL;
     int x, y, y2, y2last, yx, run, i, nsquares;
@@ -1679,26 +1673,31 @@ static char *new_game_desc(game_params *params, random_state *rs,
     }
 
     /*
-     * Store the rectangle data in the game_aux_info.
+     * Store the solution in aux.
      */
     {
-        game_aux_info *ai = snew(game_aux_info);
+        char *ai;
+        int len;
+
+        len = 2 + (params->w-1)*params->h + (params->h-1)*params->w;
+        ai = snewn(len, char);
+
+        ai[0] = 'S';
 
-        ai->w = params->w;
-        ai->h = params->h;
-        ai->vedge = snewn(ai->w * ai->h, unsigned char);
-        ai->hedge = snewn(ai->w * ai->h, unsigned char);
+        p = ai+1;
 
         for (y = 0; y < params->h; y++)
-            for (x = 1; x < params->w; x++) {
-                vedge(ai, x, y) =
-                    index(params, grid, x, y) != index(params, grid, x-1, y);
-            }
+            for (x = 1; x < params->w; x++)
+                *p++ = (index(params, grid, x, y) !=
+                        index(params, grid, x-1, y) ? '1' : '0');
+
         for (y = 1; y < params->h; y++)
-            for (x = 0; x < params->w; x++) {
-                hedge(ai, x, y) =
-                    index(params, grid, x, y) != index(params, grid, x, y-1);
-            }
+            for (x = 0; x < params->w; x++)
+                *p++ = (index(params, grid, x, y) !=
+                        index(params, grid, x, y-1) ? '1' : '0');
+
+        assert(p - ai == len-1);
+        *p = '\0';
 
         *aux = ai;
     }
@@ -1746,13 +1745,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return desc;
 }
 
-static void game_free_aux_info(game_aux_info *ai)
-{
-    sfree(ai->vedge);
-    sfree(ai->hedge);
-    sfree(ai);
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     int area = params->w * params->h;
@@ -1854,61 +1846,53 @@ 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 *vedge, *hedge;
-    int edges_need_freeing;
     int x, y, len;
     char *ret, *p;
+    int i, j, n;
+    struct numberdata *nd;
 
-    if (!ai) {
-       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++;
-           }
+    if (ai)
+        return dupstr(ai);
 
-       assert(j == n);
+    /*
+     * Attempt the in-built solver.
+     */
 
-       vedge = snewn(state->w * state->h, unsigned char);
-       hedge = snewn(state->w * state->h, unsigned char);
-       memset(vedge, 0, state->w * state->h);
-       memset(hedge, 0, state->w * state->h);
-       edges_need_freeing = TRUE;
+    /* 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++;
+        }
 
-       rect_solver(state->w, state->h, n, nd, hedge, vedge, NULL);
+    assert(j == n);
 
-       /*
-        * Clean up.
-        */
-       for (i = 0; i < n; i++)
-           sfree(nd[i].points);
-       sfree(nd);
-    } else {
-       assert(state->w == ai->w);
-       assert(state->h == ai->h);
-       vedge = ai->vedge;
-       hedge = ai->hedge;
-       edges_need_freeing = FALSE;
-    }
+    vedge = snewn(state->w * state->h, unsigned char);
+    hedge = snewn(state->w * state->h, unsigned char);
+    memset(vedge, 0, state->w * state->h);
+    memset(hedge, 0, state->w * state->h);
+
+    rect_solver(state->w, state->h, n, nd, hedge, vedge, NULL);
+
+    /*
+     * Clean up.
+     */
+    for (i = 0; i < n; i++)
+        sfree(nd[i].points);
+    sfree(nd);
 
     len = 2 + (state->w-1)*state->h + (state->h-1)*state->w;
     ret = snewn(len, char);
@@ -1916,18 +1900,16 @@ static char *solve_game(game_state *state, game_state *currstate,
     p = ret;
     *p++ = 'S';
     for (y = 0; y < state->h; y++)
-       for (x = 1; x < state->w; x++)
-           *p++ = vedge[y*state->w+x] ? '1' : '0';
+        for (x = 1; x < state->w; x++)
+            *p++ = vedge[y*state->w+x] ? '1' : '0';
     for (y = 1; y < state->h; y++)
        for (x = 0; x < state->w; x++)
            *p++ = hedge[y*state->w+x] ? '1' : '0';
     *p++ = '\0';
     assert(p - ret == len);
 
-    if (edges_need_freeing) {
-       sfree(vedge);
-       sfree(hedge);
-    }
+    sfree(vedge);
+    sfree(hedge);
 
     return ret;
 }
@@ -2799,7 +2781,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,
index 18e461eebb6139e4d7016ed35083e7ae5394d227..163a959af2a3bcf66920e135bf5c58f86e722f5f 100644 (file)
@@ -240,7 +240,7 @@ static char *validate_params(game_params *params)
  */
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     char *ret;
     int n, i, j, c, retlen, *tiles;
@@ -282,11 +282,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return ret;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     int area = params->w * params->h, i;
@@ -356,7 +351,7 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     return NULL;
 }
@@ -999,7 +994,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,
index a7e6efbce480b88cecc4652eb4c15f81b8c0c3fc..ea544c929f9ae7b791576c5e0052c648ca4aae40 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
@@ -195,7 +195,7 @@ static int perm_parity(int *perm, int n)
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     int stop, n, i, x;
     int x1, x2, p1, p2;
@@ -398,11 +398,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return ret;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 
 static char *validate_desc(game_params *params, char *desc)
 {
@@ -511,7 +506,7 @@ static void free_game(game_state *state)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     return dupstr("S");
 }
@@ -1060,7 +1055,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,
diff --git a/solo.c b/solo.c
index 20e6c079a696297db7b9dee5f8dc61a01ebe586c..0abed8cac610ef8bcc23aad6041a7d2799978383 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -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) {
-
-       assert(c == ai->c);
-       assert(r == ai->r);
-       grid = ai->grid;
-       grid_needs_freeing = FALSE;
+    if (ai)
+        return dupstr(ai);
 
-    } 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 = snewn(cr*cr, digit);
+    memcpy(grid, state->grid, cr*cr);
+    rsolve_ret = rsolve(c, r, grid, NULL, 2);
 
-       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;
 }
@@ -2420,7 +2401,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,
index 02b1d7907ac5344c81795dfb630a87b0e4b885c5..06dbaed73aa5298694af6c3308268c3e87b7c3b3 100644 (file)
--- a/twiddle.c
+++ b/twiddle.c
@@ -307,7 +307,7 @@ static int grid_complete(int *grid, int wh, int orientable)
 }
 
 static char *new_game_desc(game_params *params, random_state *rs,
-                          game_aux_info **aux, int interactive)
+                          char **aux, int interactive)
 {
     int *grid;
     int w = params->w, h = params->h, n = params->n, wh = w*h;
@@ -430,11 +430,6 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return ret;
 }
 
-static void game_free_aux_info(game_aux_info *aux)
-{
-    assert(!"Shouldn't happen");
-}
-
 static char *validate_desc(game_params *params, char *desc)
 {
     char *p, *err;
@@ -547,7 +542,7 @@ static int compare_int(const void *av, const void *bv)
 }
 
 static char *solve_game(game_state *state, game_state *currstate,
-                       game_aux_info *aux, char **error)
+                       char *aux, char **error)
 {
     return dupstr("S");
 }
@@ -1224,7 +1219,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,