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!
This commit is contained in:
Simon Tatham
2017-09-29 19:20:49 +01:00
parent 74aff6741b
commit 3aa4516a68

28
net.c
View File

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