mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
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.
This commit is contained in:
@ -82,11 +82,16 @@ struct game_params {
|
|||||||
bool id;
|
bool id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct group_common {
|
||||||
|
int refcount;
|
||||||
|
bool *immutable;
|
||||||
|
} group_common;
|
||||||
|
|
||||||
struct game_state {
|
struct game_state {
|
||||||
game_params par;
|
game_params par;
|
||||||
digit *grid;
|
digit *grid;
|
||||||
bool *immutable;
|
|
||||||
int *pencil; /* bitmaps using bits 1<<1..1<<n */
|
int *pencil; /* bitmaps using bits 1<<1..1<<n */
|
||||||
|
group_common *common;
|
||||||
bool completed, cheated;
|
bool completed, cheated;
|
||||||
digit *sequence; /* sequence of group elements shown */
|
digit *sequence; /* sequence of group elements shown */
|
||||||
|
|
||||||
@ -850,11 +855,13 @@ static game_state *new_game(midend *me, const game_params *params,
|
|||||||
|
|
||||||
state->par = *params; /* structure copy */
|
state->par = *params; /* structure copy */
|
||||||
state->grid = snewn(a, digit);
|
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);
|
state->pencil = snewn(a, int);
|
||||||
for (i = 0; i < a; i++) {
|
for (i = 0; i < a; i++) {
|
||||||
state->grid[i] = 0;
|
state->grid[i] = 0;
|
||||||
state->immutable[i] = false;
|
state->common->immutable[i] = false;
|
||||||
state->pencil[i] = 0;
|
state->pencil[i] = 0;
|
||||||
}
|
}
|
||||||
state->sequence = snewn(w, digit);
|
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);
|
desc = spec_to_grid(desc, state->grid, a);
|
||||||
for (i = 0; i < a; i++)
|
for (i = 0; i < a; i++)
|
||||||
if (state->grid[i] != 0)
|
if (state->grid[i] != 0)
|
||||||
state->immutable[i] = true;
|
state->common->immutable[i] = true;
|
||||||
|
|
||||||
state->completed = false;
|
state->completed = false;
|
||||||
state->cheated = false;
|
state->cheated = false;
|
||||||
@ -883,12 +890,12 @@ static game_state *dup_game(const game_state *state)
|
|||||||
ret->par = state->par; /* structure copy */
|
ret->par = state->par; /* structure copy */
|
||||||
|
|
||||||
ret->grid = snewn(a, digit);
|
ret->grid = snewn(a, digit);
|
||||||
ret->immutable = snewn(a, bool);
|
ret->common = state->common;
|
||||||
|
ret->common->refcount++;
|
||||||
ret->pencil = snewn(a, int);
|
ret->pencil = snewn(a, int);
|
||||||
ret->sequence = snewn(w, digit);
|
ret->sequence = snewn(w, digit);
|
||||||
ret->dividers = snewn(w, int);
|
ret->dividers = snewn(w, int);
|
||||||
memcpy(ret->grid, state->grid, a*sizeof(digit));
|
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->pencil, state->pencil, a*sizeof(int));
|
||||||
memcpy(ret->sequence, state->sequence, w*sizeof(digit));
|
memcpy(ret->sequence, state->sequence, w*sizeof(digit));
|
||||||
memcpy(ret->dividers, state->dividers, w*sizeof(int));
|
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)
|
static void free_game(game_state *state)
|
||||||
{
|
{
|
||||||
sfree(state->grid);
|
sfree(state->grid);
|
||||||
sfree(state->immutable);
|
if (--state->common->refcount == 0) {
|
||||||
|
sfree(state->common->immutable);
|
||||||
|
sfree(state->common);
|
||||||
|
}
|
||||||
sfree(state->pencil);
|
sfree(state->pencil);
|
||||||
sfree(state->sequence);
|
sfree(state->sequence);
|
||||||
sfree(state);
|
sfree(state);
|
||||||
@ -1318,7 +1328,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
|
|||||||
ui->ohy = oty;
|
ui->ohy = oty;
|
||||||
ui->odx = ui->ody = 0;
|
ui->odx = ui->ody = 0;
|
||||||
ui->odn = 1;
|
ui->odn = 1;
|
||||||
ui->hshow = !state->immutable[ty*w+tx];
|
ui->hshow = !state->common->immutable[ty*w+tx];
|
||||||
ui->hpencil = false;
|
ui->hpencil = false;
|
||||||
}
|
}
|
||||||
ui->hcursor = 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)
|
if (!ui->hpencil && state->grid[index] == n)
|
||||||
/* OK even if it is immutable */;
|
/* OK even if it is immutable */;
|
||||||
else if (state->immutable[index])
|
else if (state->common->immutable[index])
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1487,7 +1497,8 @@ static game_state *execute_move(const game_state *from, const char *move)
|
|||||||
free_game(ret);
|
free_game(ret);
|
||||||
return NULL;
|
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;
|
return NULL;
|
||||||
|
|
||||||
if (move[0] == 'P' && n > 0) {
|
if (move[0] == 'P' && n > 0) {
|
||||||
@ -1900,7 +1911,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
|
|||||||
else
|
else
|
||||||
pencil = (long)state->pencil[sy*w+sx];
|
pencil = (long)state->pencil[sy*w+sx];
|
||||||
|
|
||||||
if (state->immutable[sy*w+sx])
|
if (state->common->immutable[sy*w+sx])
|
||||||
tile |= DF_IMMUTABLE;
|
tile |= DF_IMMUTABLE;
|
||||||
|
|
||||||
if ((ui->drag == 5 && ui->dragnum == sy) ||
|
if ((ui->drag == 5 && ui->dragnum == sy) ||
|
||||||
|
31
unruly.c
31
unruly.c
@ -133,11 +133,16 @@ enum {
|
|||||||
#define FF_FLASH2 0x0800
|
#define FF_FLASH2 0x0800
|
||||||
#define FF_IMMUTABLE 0x1000
|
#define FF_IMMUTABLE 0x1000
|
||||||
|
|
||||||
|
typedef struct unruly_common {
|
||||||
|
int refcount;
|
||||||
|
bool *immutable;
|
||||||
|
} unruly_common;
|
||||||
|
|
||||||
struct game_state {
|
struct game_state {
|
||||||
int w2, h2;
|
int w2, h2;
|
||||||
bool unique;
|
bool unique;
|
||||||
char *grid;
|
char *grid;
|
||||||
bool *immutable;
|
unruly_common *common;
|
||||||
|
|
||||||
bool completed, cheated;
|
bool completed, cheated;
|
||||||
};
|
};
|
||||||
@ -353,10 +358,12 @@ static game_state *blank_state(int w2, int h2, bool unique)
|
|||||||
state->h2 = h2;
|
state->h2 = h2;
|
||||||
state->unique = unique;
|
state->unique = unique;
|
||||||
state->grid = snewn(s, char);
|
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->grid, EMPTY, s);
|
||||||
memset(state->immutable, 0, s*sizeof(bool));
|
memset(state->common->immutable, 0, s*sizeof(bool));
|
||||||
|
|
||||||
state->completed = state->cheated = false;
|
state->completed = state->cheated = false;
|
||||||
|
|
||||||
@ -379,14 +386,14 @@ static game_state *new_game(midend *me, const game_params *params,
|
|||||||
pos += (*p - 'a');
|
pos += (*p - 'a');
|
||||||
if (pos < s) {
|
if (pos < s) {
|
||||||
state->grid[pos] = N_ZERO;
|
state->grid[pos] = N_ZERO;
|
||||||
state->immutable[pos] = true;
|
state->common->immutable[pos] = true;
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
} else if (*p >= 'A' && *p < 'Z') {
|
} else if (*p >= 'A' && *p < 'Z') {
|
||||||
pos += (*p - 'A');
|
pos += (*p - 'A');
|
||||||
if (pos < s) {
|
if (pos < s) {
|
||||||
state->grid[pos] = N_ONE;
|
state->grid[pos] = N_ONE;
|
||||||
state->immutable[pos] = true;
|
state->common->immutable[pos] = true;
|
||||||
}
|
}
|
||||||
pos++;
|
pos++;
|
||||||
} else if (*p == 'Z' || *p == 'z') {
|
} 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);
|
game_state *ret = blank_state(w2, h2, state->unique);
|
||||||
|
|
||||||
memcpy(ret->grid, state->grid, s);
|
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->completed = state->completed;
|
||||||
ret->cheated = state->cheated;
|
ret->cheated = state->cheated;
|
||||||
@ -420,7 +428,10 @@ static game_state *dup_game(const game_state *state)
|
|||||||
static void free_game(game_state *state)
|
static void free_game(game_state *state)
|
||||||
{
|
{
|
||||||
sfree(state->grid);
|
sfree(state->grid);
|
||||||
sfree(state->immutable);
|
if (--state->common->refcount == 0) {
|
||||||
|
sfree(state->common->immutable);
|
||||||
|
sfree(state->common);
|
||||||
|
}
|
||||||
|
|
||||||
sfree(state);
|
sfree(state);
|
||||||
}
|
}
|
||||||
@ -1539,7 +1550,7 @@ static char *interpret_move(const game_state *state, game_ui *ui,
|
|||||||
char buf[80];
|
char buf[80];
|
||||||
char c, i;
|
char c, i;
|
||||||
|
|
||||||
if (state->immutable[hy * w2 + hx])
|
if (state->common->immutable[hy * w2 + hx])
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
c = '-';
|
c = '-';
|
||||||
@ -1604,7 +1615,7 @@ static game_state *execute_move(const game_state *state, const char *move)
|
|||||||
ret = dup_game(state);
|
ret = dup_game(state);
|
||||||
i = y * w2 + x;
|
i = y * w2 + x;
|
||||||
|
|
||||||
if (state->immutable[i]) {
|
if (state->common->immutable[i]) {
|
||||||
free_game(ret);
|
free_game(ret);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1820,7 +1831,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds,
|
|||||||
|
|
||||||
tile |= flash;
|
tile |= flash;
|
||||||
|
|
||||||
if (state->immutable[i])
|
if (state->common->immutable[i])
|
||||||
tile |= FF_IMMUTABLE;
|
tile |= FF_IMMUTABLE;
|
||||||
|
|
||||||
if (ui->cursor && ui->cx == x && ui->cy == y)
|
if (ui->cursor && ui->cx == x && ui->cy == y)
|
||||||
|
Reference in New Issue
Block a user