From 47cec547e59ac8c5012f6091394dcb4304d64fc3 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 13 Nov 2018 21:58:14 +0000 Subject: [PATCH] Unruly, Group: reference-count the 'immutable' array. I noticed this during the bool trawl: both of these games have an array of flags indicating which grid squares are immutable starting clues, and copy it in every call to dup_game, which is completely unnecessary because it doesn't change during play. So now each one lives in a reference-counted structure, as per my usual practice in similar cases elsewhere. --- unfinished/group.c | 33 ++++++++++++++++++++++----------- unruly.c | 31 +++++++++++++++++++++---------- 2 files changed, 43 insertions(+), 21 deletions(-) diff --git a/unfinished/group.c b/unfinished/group.c index e5aa81f..ef7ffba 100644 --- a/unfinished/group.c +++ b/unfinished/group.c @@ -82,11 +82,16 @@ struct game_params { bool id; }; +typedef struct group_common { + int refcount; + bool *immutable; +} group_common; + struct game_state { game_params par; digit *grid; - bool *immutable; int *pencil; /* bitmaps using bits 1<<1..1<par = *params; /* structure copy */ state->grid = snewn(a, digit); - state->immutable = snewn(a, bool); + state->common = snew(group_common); + state->common->refcount = 1; + state->common->immutable = snewn(a, bool); state->pencil = snewn(a, int); for (i = 0; i < a; i++) { state->grid[i] = 0; - state->immutable[i] = false; + state->common->immutable[i] = false; state->pencil[i] = 0; } state->sequence = snewn(w, digit); @@ -867,7 +874,7 @@ static game_state *new_game(midend *me, const game_params *params, desc = spec_to_grid(desc, state->grid, a); for (i = 0; i < a; i++) if (state->grid[i] != 0) - state->immutable[i] = true; + state->common->immutable[i] = true; state->completed = false; state->cheated = false; @@ -883,12 +890,12 @@ static game_state *dup_game(const game_state *state) ret->par = state->par; /* structure copy */ ret->grid = snewn(a, digit); - ret->immutable = snewn(a, bool); + ret->common = state->common; + ret->common->refcount++; ret->pencil = snewn(a, int); ret->sequence = snewn(w, digit); ret->dividers = snewn(w, int); memcpy(ret->grid, state->grid, a*sizeof(digit)); - memcpy(ret->immutable, state->immutable, a*sizeof(bool)); memcpy(ret->pencil, state->pencil, a*sizeof(int)); memcpy(ret->sequence, state->sequence, w*sizeof(digit)); memcpy(ret->dividers, state->dividers, w*sizeof(int)); @@ -902,7 +909,10 @@ static game_state *dup_game(const game_state *state) static void free_game(game_state *state) { sfree(state->grid); - sfree(state->immutable); + if (--state->common->refcount == 0) { + sfree(state->common->immutable); + sfree(state->common); + } sfree(state->pencil); sfree(state->sequence); sfree(state); @@ -1318,7 +1328,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, ui->ohy = oty; ui->odx = ui->ody = 0; ui->odn = 1; - ui->hshow = !state->immutable[ty*w+tx]; + ui->hshow = !state->common->immutable[ty*w+tx]; ui->hpencil = false; } ui->hcursor = false; @@ -1423,7 +1433,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, */ if (!ui->hpencil && state->grid[index] == n) /* OK even if it is immutable */; - else if (state->immutable[index]) + else if (state->common->immutable[index]) return NULL; } @@ -1487,7 +1497,8 @@ static game_state *execute_move(const game_state *from, const char *move) free_game(ret); return NULL; } - if (from->immutable[y*w+x] && !(!pencil && from->grid[y*w+x] == n)) + if (from->common->immutable[y*w+x] && + !(!pencil && from->grid[y*w+x] == n)) return NULL; if (move[0] == 'P' && n > 0) { @@ -1900,7 +1911,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, else pencil = (long)state->pencil[sy*w+sx]; - if (state->immutable[sy*w+sx]) + if (state->common->immutable[sy*w+sx]) tile |= DF_IMMUTABLE; if ((ui->drag == 5 && ui->dragnum == sy) || diff --git a/unruly.c b/unruly.c index bccddb3..e69c31b 100644 --- a/unruly.c +++ b/unruly.c @@ -133,11 +133,16 @@ enum { #define FF_FLASH2 0x0800 #define FF_IMMUTABLE 0x1000 +typedef struct unruly_common { + int refcount; + bool *immutable; +} unruly_common; + struct game_state { int w2, h2; bool unique; char *grid; - bool *immutable; + unruly_common *common; bool completed, cheated; }; @@ -353,10 +358,12 @@ static game_state *blank_state(int w2, int h2, bool unique) state->h2 = h2; state->unique = unique; state->grid = snewn(s, char); - state->immutable = snewn(s, bool); + state->common = snew(unruly_common); + state->common->refcount = 1; + state->common->immutable = snewn(s, bool); memset(state->grid, EMPTY, s); - memset(state->immutable, 0, s*sizeof(bool)); + memset(state->common->immutable, 0, s*sizeof(bool)); state->completed = state->cheated = false; @@ -379,14 +386,14 @@ static game_state *new_game(midend *me, const game_params *params, pos += (*p - 'a'); if (pos < s) { state->grid[pos] = N_ZERO; - state->immutable[pos] = true; + state->common->immutable[pos] = true; } pos++; } else if (*p >= 'A' && *p < 'Z') { pos += (*p - 'A'); if (pos < s) { state->grid[pos] = N_ONE; - state->immutable[pos] = true; + state->common->immutable[pos] = true; } pos++; } else if (*p == 'Z' || *p == 'z') { @@ -409,7 +416,8 @@ static game_state *dup_game(const game_state *state) game_state *ret = blank_state(w2, h2, state->unique); memcpy(ret->grid, state->grid, s); - memcpy(ret->immutable, state->immutable, s*sizeof(bool)); + ret->common = state->common; + ret->common->refcount++; ret->completed = state->completed; ret->cheated = state->cheated; @@ -420,7 +428,10 @@ static game_state *dup_game(const game_state *state) static void free_game(game_state *state) { sfree(state->grid); - sfree(state->immutable); + if (--state->common->refcount == 0) { + sfree(state->common->immutable); + sfree(state->common); + } sfree(state); } @@ -1539,7 +1550,7 @@ static char *interpret_move(const game_state *state, game_ui *ui, char buf[80]; char c, i; - if (state->immutable[hy * w2 + hx]) + if (state->common->immutable[hy * w2 + hx]) return NULL; c = '-'; @@ -1604,7 +1615,7 @@ static game_state *execute_move(const game_state *state, const char *move) ret = dup_game(state); i = y * w2 + x; - if (state->immutable[i]) { + if (state->common->immutable[i]) { free_game(ret); return NULL; } @@ -1820,7 +1831,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, tile |= flash; - if (state->immutable[i]) + if (state->common->immutable[i]) tile |= FF_IMMUTABLE; if (ui->cursor && ui->cx == x && ui->cy == y)