shithub: puzzles

Download patch

ref: 3aa4516a680f52e2e6c8a16234a7ecca0ec77233
parent: 74aff6741b50c58c71527a0524e3f6b081a2da7e
author: Simon Tatham <anakin@pobox.com>
date: Fri Sep 29 15:20:49 EDT 2017

Net: reference-count the barriers array.

Net is one of the very oldest puzzles in the collection, and has
apparently been physically copying the complete collection of totally
immutable barrier data in every game state since 2004. About time it
stopped, I think!

--- a/net.c
+++ b/net.c
@@ -102,12 +102,17 @@
     float barrier_probability;
 };
 
+typedef struct game_immutable_state {
+    int refcount;
+    unsigned char *barriers;
+} game_immutable_state;
+
 struct game_state {
     int width, height, wrapping, completed;
     int last_rotate_x, last_rotate_y, last_rotate_dir;
     int used_solve;
     unsigned char *tiles;
-    unsigned char *barriers;
+    struct game_immutable_state *imm;
 };
 
 #define OFFSETWH(x2,y2,x1,y1,dir,width,height) \
@@ -119,7 +124,7 @@
 
 #define index(state, a, x, y) ( a[(y) * (state)->width + (x)] )
 #define tile(state, x, y)     index(state, (state)->tiles, x, y)
-#define barrier(state, x, y)  index(state, (state)->barriers, x, y)
+#define barrier(state, x, y)  index(state, (state)->imm->barriers, x, y)
 
 struct xyd {
     int x, y, direction;
@@ -1653,12 +1658,14 @@
     w = state->width = params->width;
     h = state->height = params->height;
     state->wrapping = params->wrapping;
+    state->imm = snew(game_immutable_state);
+    state->imm->refcount = 1;
     state->last_rotate_dir = state->last_rotate_x = state->last_rotate_y = 0;
     state->completed = state->used_solve = FALSE;
     state->tiles = snewn(state->width * state->height, unsigned char);
     memset(state->tiles, 0, state->width * state->height);
-    state->barriers = snewn(state->width * state->height, unsigned char);
-    memset(state->barriers, 0, state->width * state->height);
+    state->imm->barriers = snewn(state->width * state->height, unsigned char);
+    memset(state->imm->barriers, 0, state->width * state->height);
 
     /*
      * Parse the game description into the grid.
@@ -1729,6 +1736,8 @@
     game_state *ret;
 
     ret = snew(game_state);
+    ret->imm = state->imm;
+    ret->imm->refcount++;
     ret->width = state->width;
     ret->height = state->height;
     ret->wrapping = state->wrapping;
@@ -1739,8 +1748,6 @@
     ret->last_rotate_y = state->last_rotate_y;
     ret->tiles = snewn(state->width * state->height, unsigned char);
     memcpy(ret->tiles, state->tiles, state->width * state->height);
-    ret->barriers = snewn(state->width * state->height, unsigned char);
-    memcpy(ret->barriers, state->barriers, state->width * state->height);
 
     return ret;
 }
@@ -1747,8 +1754,11 @@
 
 static void free_game(game_state *state)
 {
+    if (--state->imm->refcount == 0) {
+        sfree(state->imm->barriers);
+        sfree(state->imm);
+    }
     sfree(state->tiles);
-    sfree(state->barriers);
     sfree(state);
 }
 
@@ -1771,7 +1781,7 @@
 
 	memcpy(tiles, state->tiles, state->width * state->height);
 	solver_result = net_solver(state->width, state->height, tiles,
-                                   state->barriers, state->wrapping);
+                                   state->imm->barriers, state->wrapping);
 
         if (solver_result < 0) {
             *error = "No solution exists for this puzzle";
@@ -2004,7 +2014,7 @@
 static int *compute_loops(const game_state *state)
 {
     return compute_loops_inner(state->width, state->height, state->wrapping,
-                               state->tiles, state->barriers);
+                               state->tiles, state->imm->barriers);
 }
 
 struct game_ui {