mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
Patch from Chris Emerson: rather than dynamically calling
get_correct() at (among other things) every redraw, we call it once at the creation of a new game_state to save CPU. [originally from svn r6106]
This commit is contained in:
210
rect.c
210
rect.c
@ -76,6 +76,7 @@ struct game_state {
|
|||||||
unsigned char *vedge; /* (w+1) x h */
|
unsigned char *vedge; /* (w+1) x h */
|
||||||
unsigned char *hedge; /* w x (h+1) */
|
unsigned char *hedge; /* w x (h+1) */
|
||||||
int completed, cheated;
|
int completed, cheated;
|
||||||
|
unsigned char *correct;
|
||||||
};
|
};
|
||||||
|
|
||||||
static game_params *default_params(void)
|
static game_params *default_params(void)
|
||||||
@ -1773,6 +1774,99 @@ static char *validate_desc(game_params *params, char *desc)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned char *get_correct(game_state *state)
|
||||||
|
{
|
||||||
|
unsigned char *ret;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
ret = snewn(state->w * state->h, unsigned char);
|
||||||
|
memset(ret, 0xFF, state->w * state->h);
|
||||||
|
|
||||||
|
for (x = 0; x < state->w; x++)
|
||||||
|
for (y = 0; y < state->h; y++)
|
||||||
|
if (index(state,ret,x,y) == 0xFF) {
|
||||||
|
int rw, rh;
|
||||||
|
int xx, yy;
|
||||||
|
int num, area, valid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find a rectangle starting at this point.
|
||||||
|
*/
|
||||||
|
rw = 1;
|
||||||
|
while (x+rw < state->w && !vedge(state,x+rw,y))
|
||||||
|
rw++;
|
||||||
|
rh = 1;
|
||||||
|
while (y+rh < state->h && !hedge(state,x,y+rh))
|
||||||
|
rh++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We know what the dimensions of the rectangle
|
||||||
|
* should be if it's there at all. Find out if we
|
||||||
|
* really have a valid rectangle.
|
||||||
|
*/
|
||||||
|
valid = TRUE;
|
||||||
|
/* Check the horizontal edges. */
|
||||||
|
for (xx = x; xx < x+rw; xx++) {
|
||||||
|
for (yy = y; yy <= y+rh; yy++) {
|
||||||
|
int e = !HRANGE(state,xx,yy) || hedge(state,xx,yy);
|
||||||
|
int ec = (yy == y || yy == y+rh);
|
||||||
|
if (e != ec)
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Check the vertical edges. */
|
||||||
|
for (yy = y; yy < y+rh; yy++) {
|
||||||
|
for (xx = x; xx <= x+rw; xx++) {
|
||||||
|
int e = !VRANGE(state,xx,yy) || vedge(state,xx,yy);
|
||||||
|
int ec = (xx == x || xx == x+rw);
|
||||||
|
if (e != ec)
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this is not a valid rectangle with no other
|
||||||
|
* edges inside it, we just mark this square as not
|
||||||
|
* complete and proceed to the next square.
|
||||||
|
*/
|
||||||
|
if (!valid) {
|
||||||
|
index(state, ret, x, y) = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have a rectangle. Now see what its area is,
|
||||||
|
* and how many numbers are in it.
|
||||||
|
*/
|
||||||
|
num = 0;
|
||||||
|
area = 0;
|
||||||
|
for (xx = x; xx < x+rw; xx++) {
|
||||||
|
for (yy = y; yy < y+rh; yy++) {
|
||||||
|
area++;
|
||||||
|
if (grid(state,xx,yy)) {
|
||||||
|
if (num > 0)
|
||||||
|
valid = FALSE; /* two numbers */
|
||||||
|
num = grid(state,xx,yy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (num != area)
|
||||||
|
valid = FALSE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now fill in the whole rectangle based on the
|
||||||
|
* value of `valid'.
|
||||||
|
*/
|
||||||
|
for (xx = x; xx < x+rw; xx++) {
|
||||||
|
for (yy = y; yy < y+rh; yy++) {
|
||||||
|
index(state, ret, xx, yy) = valid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static game_state *new_game(midend_data *me, game_params *params, char *desc)
|
static game_state *new_game(midend_data *me, game_params *params, char *desc)
|
||||||
{
|
{
|
||||||
game_state *state = snew(game_state);
|
game_state *state = snew(game_state);
|
||||||
@ -1813,6 +1907,8 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc)
|
|||||||
for (x = 0; x < state->w; x++)
|
for (x = 0; x < state->w; x++)
|
||||||
vedge(state,x,y) = hedge(state,x,y) = 0;
|
vedge(state,x,y) = hedge(state,x,y) = 0;
|
||||||
|
|
||||||
|
state->correct = get_correct(state);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1826,6 +1922,7 @@ static game_state *dup_game(game_state *state)
|
|||||||
ret->vedge = snewn(state->w * state->h, unsigned char);
|
ret->vedge = snewn(state->w * state->h, unsigned char);
|
||||||
ret->hedge = snewn(state->w * state->h, unsigned char);
|
ret->hedge = snewn(state->w * state->h, unsigned char);
|
||||||
ret->grid = snewn(state->w * state->h, int);
|
ret->grid = snewn(state->w * state->h, int);
|
||||||
|
ret->correct = snewn(ret->w * ret->h, unsigned char);
|
||||||
|
|
||||||
ret->completed = state->completed;
|
ret->completed = state->completed;
|
||||||
ret->cheated = state->cheated;
|
ret->cheated = state->cheated;
|
||||||
@ -1834,6 +1931,8 @@ static game_state *dup_game(game_state *state)
|
|||||||
memcpy(ret->vedge, state->vedge, state->w*state->h*sizeof(unsigned char));
|
memcpy(ret->vedge, state->vedge, state->w*state->h*sizeof(unsigned char));
|
||||||
memcpy(ret->hedge, state->hedge, state->w*state->h*sizeof(unsigned char));
|
memcpy(ret->hedge, state->hedge, state->w*state->h*sizeof(unsigned char));
|
||||||
|
|
||||||
|
memcpy(ret->correct, state->correct, state->w*state->h*sizeof(unsigned char));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1842,6 +1941,7 @@ static void free_game(game_state *state)
|
|||||||
sfree(state->grid);
|
sfree(state->grid);
|
||||||
sfree(state->vedge);
|
sfree(state->vedge);
|
||||||
sfree(state->hedge);
|
sfree(state->hedge);
|
||||||
|
sfree(state->correct);
|
||||||
sfree(state);
|
sfree(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2007,99 +2107,6 @@ static char *game_text_format(game_state *state)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char *get_correct(game_state *state)
|
|
||||||
{
|
|
||||||
unsigned char *ret;
|
|
||||||
int x, y;
|
|
||||||
|
|
||||||
ret = snewn(state->w * state->h, unsigned char);
|
|
||||||
memset(ret, 0xFF, state->w * state->h);
|
|
||||||
|
|
||||||
for (x = 0; x < state->w; x++)
|
|
||||||
for (y = 0; y < state->h; y++)
|
|
||||||
if (index(state,ret,x,y) == 0xFF) {
|
|
||||||
int rw, rh;
|
|
||||||
int xx, yy;
|
|
||||||
int num, area, valid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Find a rectangle starting at this point.
|
|
||||||
*/
|
|
||||||
rw = 1;
|
|
||||||
while (x+rw < state->w && !vedge(state,x+rw,y))
|
|
||||||
rw++;
|
|
||||||
rh = 1;
|
|
||||||
while (y+rh < state->h && !hedge(state,x,y+rh))
|
|
||||||
rh++;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We know what the dimensions of the rectangle
|
|
||||||
* should be if it's there at all. Find out if we
|
|
||||||
* really have a valid rectangle.
|
|
||||||
*/
|
|
||||||
valid = TRUE;
|
|
||||||
/* Check the horizontal edges. */
|
|
||||||
for (xx = x; xx < x+rw; xx++) {
|
|
||||||
for (yy = y; yy <= y+rh; yy++) {
|
|
||||||
int e = !HRANGE(state,xx,yy) || hedge(state,xx,yy);
|
|
||||||
int ec = (yy == y || yy == y+rh);
|
|
||||||
if (e != ec)
|
|
||||||
valid = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Check the vertical edges. */
|
|
||||||
for (yy = y; yy < y+rh; yy++) {
|
|
||||||
for (xx = x; xx <= x+rw; xx++) {
|
|
||||||
int e = !VRANGE(state,xx,yy) || vedge(state,xx,yy);
|
|
||||||
int ec = (xx == x || xx == x+rw);
|
|
||||||
if (e != ec)
|
|
||||||
valid = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is not a valid rectangle with no other
|
|
||||||
* edges inside it, we just mark this square as not
|
|
||||||
* complete and proceed to the next square.
|
|
||||||
*/
|
|
||||||
if (!valid) {
|
|
||||||
index(state, ret, x, y) = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We have a rectangle. Now see what its area is,
|
|
||||||
* and how many numbers are in it.
|
|
||||||
*/
|
|
||||||
num = 0;
|
|
||||||
area = 0;
|
|
||||||
for (xx = x; xx < x+rw; xx++) {
|
|
||||||
for (yy = y; yy < y+rh; yy++) {
|
|
||||||
area++;
|
|
||||||
if (grid(state,xx,yy)) {
|
|
||||||
if (num > 0)
|
|
||||||
valid = FALSE; /* two numbers */
|
|
||||||
num = grid(state,xx,yy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num != area)
|
|
||||||
valid = FALSE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now fill in the whole rectangle based on the
|
|
||||||
* value of `valid'.
|
|
||||||
*/
|
|
||||||
for (xx = x; xx < x+rw; xx++) {
|
|
||||||
for (yy = y; yy < y+rh; yy++) {
|
|
||||||
index(state, ret, xx, yy) = valid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct game_ui {
|
struct game_ui {
|
||||||
/*
|
/*
|
||||||
* These coordinates are 2 times the obvious grid coordinates.
|
* These coordinates are 2 times the obvious grid coordinates.
|
||||||
@ -2440,6 +2447,9 @@ static game_state *execute_move(game_state *from, char *move)
|
|||||||
if (*p) p++;
|
if (*p) p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sfree(ret->correct);
|
||||||
|
ret->correct = get_correct(ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
} else if (move[0] == 'R' &&
|
} else if (move[0] == 'R' &&
|
||||||
@ -2473,20 +2483,20 @@ static game_state *execute_move(game_state *from, char *move)
|
|||||||
*/
|
*/
|
||||||
if (!ret->completed) {
|
if (!ret->completed) {
|
||||||
int x, y, ok;
|
int x, y, ok;
|
||||||
unsigned char *correct = get_correct(ret);
|
|
||||||
|
|
||||||
ok = TRUE;
|
ok = TRUE;
|
||||||
for (x = 0; x < ret->w; x++)
|
for (x = 0; x < ret->w; x++)
|
||||||
for (y = 0; y < ret->h; y++)
|
for (y = 0; y < ret->h; y++)
|
||||||
if (!index(ret, correct, x, y))
|
if (!index(ret, ret->correct, x, y))
|
||||||
ok = FALSE;
|
ok = FALSE;
|
||||||
|
|
||||||
sfree(correct);
|
|
||||||
|
|
||||||
if (ok)
|
if (ok)
|
||||||
ret->completed = TRUE;
|
ret->completed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sfree(ret->correct);
|
||||||
|
ret->correct = get_correct(ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2629,11 +2639,8 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
|||||||
float animtime, float flashtime)
|
float animtime, float flashtime)
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
unsigned char *correct;
|
|
||||||
unsigned char *hedge, *vedge, *corners;
|
unsigned char *hedge, *vedge, *corners;
|
||||||
|
|
||||||
correct = get_correct(state);
|
|
||||||
|
|
||||||
if (ui->dragged) {
|
if (ui->dragged) {
|
||||||
hedge = snewn(state->w*state->h, unsigned char);
|
hedge = snewn(state->w*state->h, unsigned char);
|
||||||
vedge = snewn(state->w*state->h, unsigned char);
|
vedge = snewn(state->w*state->h, unsigned char);
|
||||||
@ -2699,7 +2706,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
|||||||
if (x+1 < state->w && y+1 < state->h)
|
if (x+1 < state->w && y+1 < state->h)
|
||||||
/* cast to prevent 2<<14 sign-extending on promotion to long */
|
/* cast to prevent 2<<14 sign-extending on promotion to long */
|
||||||
c |= (unsigned long)index(state,corners,x+1,y+1) << 14;
|
c |= (unsigned long)index(state,corners,x+1,y+1) << 14;
|
||||||
if (index(state, correct, x, y) && !flashtime)
|
if (index(state, state->correct, x, y) && !flashtime)
|
||||||
c |= CORRECT;
|
c |= CORRECT;
|
||||||
|
|
||||||
if (index(ds,ds->visible,x,y) != c) {
|
if (index(ds,ds->visible,x,y) != c) {
|
||||||
@ -2735,7 +2742,6 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sfree(corners);
|
sfree(corners);
|
||||||
sfree(correct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float game_anim_length(game_state *oldstate,
|
static float game_anim_length(game_state *oldstate,
|
||||||
|
Reference in New Issue
Block a user