Add a completion flash when you get down to a single peg.

[originally from svn r6061]
This commit is contained in:
Jacob Nevins
2005-07-05 18:57:34 +00:00
parent b74dac6de2
commit b75ce34179

48
pegs.c
View File

@ -42,6 +42,8 @@ static char const *const pegs_titletypes[] = { TYPELIST(TITLE) };
static char const *const pegs_lowertypes[] = { TYPELIST(LOWER) }; static char const *const pegs_lowertypes[] = { TYPELIST(LOWER) };
#define TYPECONFIG TYPELIST(CONFIG) #define TYPECONFIG TYPELIST(CONFIG)
#define FLASH_FRAME 0.13F
struct game_params { struct game_params {
int w, h; int w, h;
int type; int type;
@ -49,6 +51,7 @@ struct game_params {
struct game_state { struct game_state {
int w, h; int w, h;
int completed;
unsigned char *grid; unsigned char *grid;
}; };
@ -574,6 +577,7 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc)
state->w = w; state->w = w;
state->h = h; state->h = h;
state->completed = 0;
state->grid = snewn(w*h, unsigned char); state->grid = snewn(w*h, unsigned char);
for (i = 0; i < w*h; i++) for (i = 0; i < w*h; i++)
state->grid[i] = (desc[i] == 'P' ? GRID_PEG : state->grid[i] = (desc[i] == 'P' ? GRID_PEG :
@ -589,6 +593,7 @@ static game_state *dup_game(game_state *state)
ret->w = state->w; ret->w = state->w;
ret->h = state->h; ret->h = state->h;
ret->completed = state->completed;
ret->grid = snewn(w*h, unsigned char); ret->grid = snewn(w*h, unsigned char);
memcpy(ret->grid, state->grid, w*h); memcpy(ret->grid, state->grid, w*h);
@ -682,6 +687,7 @@ struct game_drawstate {
int w, h; int w, h;
unsigned char *grid; unsigned char *grid;
int started; int started;
int bgcolour;
}; };
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
@ -789,6 +795,21 @@ static game_state *execute_move(game_state *state, char *move)
ret->grid[my*w+mx] = GRID_HOLE; ret->grid[my*w+mx] = GRID_HOLE;
ret->grid[ty*w+tx] = GRID_PEG; ret->grid[ty*w+tx] = GRID_PEG;
/*
* Opinion varies on whether getting to a single peg counts as
* completing the game, or whether that peg has to be at a
* specific location (central in the classic cross game, for
* instance). For now we take the former, rather lax position.
*/
if (!ret->completed) {
int count = 0, i;
for (i = 0; i < w*h; i++)
if (ret->grid[i] == GRID_PEG)
count++;
if (count == 1)
ret->completed = 1;
}
return ret; return ret;
} }
return NULL; return NULL;
@ -873,6 +894,7 @@ static game_drawstate *game_new_drawstate(game_state *state)
memset(ds->grid, 255, w*h); memset(ds->grid, 255, w*h);
ds->started = FALSE; ds->started = FALSE;
ds->bgcolour = -1;
return ds; return ds;
} }
@ -886,10 +908,10 @@ static void game_free_drawstate(game_drawstate *ds)
} }
static void draw_tile(frontend *fe, game_drawstate *ds, static void draw_tile(frontend *fe, game_drawstate *ds,
int x, int y, int v, int erasebg) int x, int y, int v, int bgcolour)
{ {
if (erasebg) { if (bgcolour >= 0) {
draw_rect(fe, x, y, TILESIZE, TILESIZE, COL_BACKGROUND); draw_rect(fe, x, y, TILESIZE, TILESIZE, bgcolour);
} }
if (v == GRID_HOLE) { if (v == GRID_HOLE) {
@ -909,6 +931,13 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
{ {
int w = state->w, h = state->h; int w = state->w, h = state->h;
int x, y; int x, y;
int bgcolour;
if (flashtime > 0) {
int frame = (int)(flashtime / FLASH_FRAME);
bgcolour = (frame % 2 ? COL_LOWLIGHT : COL_HIGHLIGHT);
} else
bgcolour = COL_BACKGROUND;
/* /*
* Erase the sprite currently being dragged, if any. * Erase the sprite currently being dragged, if any.
@ -1025,8 +1054,10 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
*/ */
if (ui->dragging && ui->sx == x && ui->sy == y && v == GRID_PEG) if (ui->dragging && ui->sx == x && ui->sy == y && v == GRID_PEG)
v = GRID_HOLE; v = GRID_HOLE;
if (v != ds->grid[y*w+x] && v != GRID_OBST) { if (v != GRID_OBST &&
draw_tile(fe, ds, COORD(x), COORD(y), v, TRUE); (bgcolour != ds->bgcolour || /* always redraw when flashing */
v != ds->grid[y*w+x])) {
draw_tile(fe, ds, COORD(x), COORD(y), v, bgcolour);
} }
} }
@ -1038,8 +1069,10 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
ds->dragx = ui->dx - TILESIZE/2; ds->dragx = ui->dx - TILESIZE/2;
ds->dragy = ui->dy - TILESIZE/2; ds->dragy = ui->dy - TILESIZE/2;
blitter_save(fe, ds->drag_background, ds->dragx, ds->dragy); blitter_save(fe, ds->drag_background, ds->dragx, ds->dragy);
draw_tile(fe, ds, ds->dragx, ds->dragy, GRID_PEG, FALSE); draw_tile(fe, ds, ds->dragx, ds->dragy, GRID_PEG, -1);
} }
ds->bgcolour = bgcolour;
} }
static float game_anim_length(game_state *oldstate, game_state *newstate, static float game_anim_length(game_state *oldstate, game_state *newstate,
@ -1051,6 +1084,9 @@ static float game_anim_length(game_state *oldstate, game_state *newstate,
static float game_flash_length(game_state *oldstate, game_state *newstate, static float game_flash_length(game_state *oldstate, game_state *newstate,
int dir, game_ui *ui) int dir, game_ui *ui)
{ {
if (!oldstate->completed && newstate->completed)
return 2 * FLASH_FRAME;
else
return 0.0F; return 0.0F;
} }