int w, h, n;
int *tiles;
int completed;
- int just_used_solve; /* used to suppress undo animation */
int used_solve; /* used to suppress completion flash */
int movecount, movetarget;
int last_movement_sense;
state->completed = state->movecount = 0;
state->movetarget = params->movetarget;
- state->used_solve = state->just_used_solve = FALSE;
+ state->used_solve = FALSE;
state->last_movement_sense = 0;
return state;
ret->movecount = state->movecount;
ret->movetarget = state->movetarget;
ret->used_solve = state->used_solve;
- ret->just_used_solve = state->just_used_solve;
ret->last_movement_sense = state->last_movement_sense;
return ret;
return dupstr("S");
}
+static int game_can_format_as_text_now(game_params *params)
+{
+ return TRUE;
+}
+
static char *game_text_format(game_state *state)
{
char *ret, *p, buf[80];
return ret;
}
+struct game_ui {
+ int cur_x, cur_y;
+ int cur_visible;
+};
+
static game_ui *new_ui(game_state *state)
{
- return NULL;
+ game_ui *ui = snew(game_ui);
+ ui->cur_x = 0;
+ ui->cur_y = -1;
+ ui->cur_visible = FALSE;
+
+ return ui;
}
static void free_ui(game_ui *ui)
{
+ sfree(ui);
}
static char *encode_ui(game_ui *ui)
int w, h, bgcolour;
int *tiles;
int tilesize;
+ int cur_x, cur_y;
};
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
int x, int y, int button)
{
- int cx, cy, dx, dy;
+ int cx = -1, cy = -1, dx, dy;
char buf[80];
button &= ~MOD_MASK;
- if (button != LEFT_BUTTON && button != RIGHT_BUTTON)
- return NULL;
- cx = FROMCOORD(x);
- cy = FROMCOORD(y);
+ if (IS_CURSOR_MOVE(button)) {
+ /* right/down rotates cursor clockwise,
+ * left/up rotates anticlockwise. */
+ int cpos, diff;
+ cpos = c2pos(state->w, state->h, ui->cur_x, ui->cur_y);
+ diff = c2diff(state->w, state->h, ui->cur_x, ui->cur_y, button);
+
+ cpos += diff;
+ pos2c(state->w, state->h, cpos, &ui->cur_x, &ui->cur_y);
+
+ ui->cur_visible = 1;
+ return "";
+ }
+
+ if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
+ cx = FROMCOORD(x);
+ cy = FROMCOORD(y);
+ ui->cur_visible = 0;
+ } else if (IS_CURSOR_SELECT(button)) {
+ if (ui->cur_visible) {
+ cx = ui->cur_x;
+ cy = ui->cur_y;
+ } else {
+ ui->cur_visible = 1;
+ return "";
+ }
+ } else {
+ return NULL;
+ }
+
if (cx == -1 && cy >= 0 && cy < state->h)
dx = -1, dy = 0;
else if (cx == state->w && cy >= 0 && cy < state->h)
else if (cy == state->h && cx >= 0 && cx < state->w)
dy = +1, dx = 0;
else
- return NULL; /* invalid click location */
+ return ""; /* invalid click location */
/* reverse direction if right hand button is pressed */
- if (button == RIGHT_BUTTON) {
+ if (button == RIGHT_BUTTON || button == CURSOR_SELECT2) {
dx = -dx;
dy = -dy;
}
*/
for (i = 0; i < ret->n; i++)
ret->tiles[i] = i+1;
- ret->used_solve = ret->just_used_solve = TRUE;
+ ret->used_solve = TRUE;
ret->completed = ret->movecount = 1;
return ret;
return NULL;
ret = dup_game(from);
- ret->just_used_solve = FALSE; /* zero this in a hurry */
do {
tx = (cx - dx + from->w) % from->w;
ds->tilesize = tilesize;
}
-static float *game_colours(frontend *fe, game_state *state, int *ncolours)
+static float *game_colours(frontend *fe, int *ncolours)
{
float *ret = snewn(3 * NCOLOURS, float);
int i;
ds->tilesize = 0; /* haven't decided yet */
for (i = 0; i < ds->w*ds->h; i++)
ds->tiles[i] = -1;
+ ds->cur_x = ds->cur_y = -1;
return ds;
}
}
static void draw_arrow(drawing *dr, game_drawstate *ds,
- int x, int y, int xdx, int xdy)
+ int x, int y, int xdx, int xdy, int cur)
{
int coords[14];
int ydy = -xdx, ydx = xdy;
POINT(5, 3 * TILE_SIZE / 8, TILE_SIZE / 2); /* left concave */
POINT(6, TILE_SIZE / 4, TILE_SIZE / 2); /* left corner */
- draw_polygon(dr, coords, 7, COL_LOWLIGHT, COL_TEXT);
+ draw_polygon(dr, coords, 7, cur ? COL_HIGHLIGHT : COL_LOWLIGHT, COL_TEXT);
+}
+
+static void draw_arrow_for_cursor(drawing *dr, game_drawstate *ds,
+ int cur_x, int cur_y, int cur)
+{
+ if (cur_x == -1 && cur_y == -1)
+ return; /* 'no cursur here */
+ else if (cur_x == -1) /* LH column. */
+ draw_arrow(dr, ds, COORD(0), COORD(cur_y+1), 0, -1, cur);
+ else if (cur_x == ds->w) /* RH column */
+ draw_arrow(dr, ds, COORD(ds->w), COORD(cur_y), 0, +1, cur);
+ else if (cur_y == -1) /* Top row */
+ draw_arrow(dr, ds, COORD(cur_x), COORD(0), +1, 0, cur);
+ else if (cur_y == ds->h) /* Bottom row */
+ draw_arrow(dr, ds, COORD(cur_x+1), COORD(ds->h), -1, 0, cur);
+ else
+ assert(!"Invalid cursor position");
+
+ draw_update(dr, COORD(cur_x), COORD(cur_y),
+ TILE_SIZE, TILE_SIZE);
}
static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
float animtime, float flashtime)
{
int i, bgcolour;
+ int cur_x = -1, cur_y = -1;
if (flashtime > 0) {
int frame = (int)(flashtime / FLASH_FRAME);
* Arrows for making moves.
*/
for (i = 0; i < state->w; i++) {
- draw_arrow(dr, ds, COORD(i), COORD(0), +1, 0);
- draw_arrow(dr, ds, COORD(i+1), COORD(state->h), -1, 0);
+ draw_arrow(dr, ds, COORD(i), COORD(0), +1, 0, 0);
+ draw_arrow(dr, ds, COORD(i+1), COORD(state->h), -1, 0, 0);
}
for (i = 0; i < state->h; i++) {
- draw_arrow(dr, ds, COORD(state->w), COORD(i), 0, +1);
- draw_arrow(dr, ds, COORD(0), COORD(i+1), 0, -1);
+ draw_arrow(dr, ds, COORD(state->w), COORD(i), 0, +1, 0);
+ draw_arrow(dr, ds, COORD(0), COORD(i+1), 0, -1, 0);
}
ds->started = TRUE;
}
+ /*
+ * Cursor (highlighted arrow around edge)
+ */
+ if (ui->cur_visible) {
+ cur_x = ui->cur_x; cur_y = ui->cur_y;
+ }
+ if (cur_x != ds->cur_x || cur_y != ds->cur_y) {
+ /* Cursor has changed; redraw two (prev and curr) arrows. */
+ draw_arrow_for_cursor(dr, ds, cur_x, cur_y, 1);
+ draw_arrow_for_cursor(dr, ds, ds->cur_x, ds->cur_y, 0);
+ ds->cur_x = cur_x; ds->cur_y = cur_y;
+ }
/*
* Now draw each tile.
static float game_anim_length(game_state *oldstate,
game_state *newstate, int dir, game_ui *ui)
{
- if ((dir > 0 && newstate->just_used_solve) ||
- (dir < 0 && oldstate->just_used_solve))
- return 0.0F;
- else
- return ANIM_TIME;
+ return ANIM_TIME;
}
static float game_flash_length(game_state *oldstate,
return 0.0F;
}
-static int game_wants_statusbar(void)
-{
- return TRUE;
-}
-
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
#endif
const struct game thegame = {
- "Sixteen", "games.sixteen",
+ "Sixteen", "games.sixteen", "sixteen",
default_params,
game_fetch_preset,
decode_params,
dup_game,
free_game,
TRUE, solve_game,
- TRUE, game_text_format,
+ TRUE, game_can_format_as_text_now, game_text_format,
new_ui,
free_ui,
encode_ui,
game_anim_length,
game_flash_length,
FALSE, FALSE, game_print_size, game_print,
- game_wants_statusbar,
+ TRUE, /* wants_statusbar */
FALSE, game_timing_state,
- 0, /* mouse_priorities */
+ 0, /* flags */
};
+
+/* vim: set shiftwidth=4 tabstop=8: */