COL_TEXT,
COL_UNKNOWN,
COL_GRID,
+ COL_CURSOR,
NCOLOURS
};
if (*desc && isdigit((unsigned char)*desc)) {
do {
p = desc;
- while (desc && isdigit((unsigned char)*desc)) desc++;
+ while (*desc && isdigit((unsigned char)*desc)) desc++;
n = atoi(p);
rowspace -= n+1;
if (*desc && isdigit((unsigned char)*desc)) {
do {
p = desc;
- while (desc && isdigit((unsigned char)*desc)) desc++;
+ while (*desc && isdigit((unsigned char)*desc)) desc++;
state->rowdata[state->rowsize * i + state->rowlen[i]++] =
atoi(p);
} while (*desc++ == '.');
return ret;
}
+static int game_can_format_as_text_now(game_params *params)
+{
+ return TRUE;
+}
+
static char *game_text_format(game_state *state)
{
return NULL;
int drag_end_x;
int drag_end_y;
int drag, release, state;
+ int cur_x, cur_y, cur_visible;
};
static game_ui *new_ui(game_state *state)
ret = snew(game_ui);
ret->dragging = FALSE;
+ ret->cur_x = ret->cur_y = ret->cur_visible = 0;
return ret;
}
int w, h;
int tilesize;
unsigned char *visible;
+ int cur_x, cur_y;
};
static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
if (x >= 0 && x < state->w && y >= 0 && y < state->h &&
(button == LEFT_BUTTON || button == RIGHT_BUTTON ||
button == MIDDLE_BUTTON)) {
+#ifdef STYLUS_BASED
+ int currstate = state->grid[y * state->w + x];
+#endif
ui->dragging = TRUE;
if (button == LEFT_BUTTON) {
ui->drag = LEFT_DRAG;
ui->release = LEFT_RELEASE;
+#ifdef STYLUS_BASED
+ ui->state = currstate == GRID_FULL ? GRID_UNKNOWN : GRID_FULL;
+#else
ui->state = GRID_FULL;
+#endif
} else if (button == RIGHT_BUTTON) {
ui->drag = RIGHT_DRAG;
ui->release = RIGHT_RELEASE;
+#ifdef STYLUS_BASED
+ ui->state = currstate == GRID_EMPTY ? GRID_UNKNOWN : GRID_EMPTY;
+#else
ui->state = GRID_EMPTY;
+#endif
} else /* if (button == MIDDLE_BUTTON) */ {
ui->drag = MIDDLE_DRAG;
ui->release = MIDDLE_RELEASE;
ui->drag_start_x = ui->drag_end_x = x;
ui->drag_start_y = ui->drag_end_y = y;
+ ui->cur_visible = 0;
return ""; /* UI activity occurred */
}
return ""; /* UI activity occurred */
}
+ if (IS_CURSOR_MOVE(button)) {
+ move_cursor(button, &ui->cur_x, &ui->cur_y, state->w, state->h, 0);
+ ui->cur_visible = 1;
+ return "";
+ }
+ if (IS_CURSOR_SELECT(button)) {
+ int currstate = state->grid[ui->cur_y * state->w + ui->cur_x];
+ int newstate;
+ char buf[80];
+
+ if (!ui->cur_visible) {
+ ui->cur_visible = 1;
+ return "";
+ }
+
+ if (button == CURSOR_SELECT2)
+ newstate = currstate == GRID_UNKNOWN ? GRID_EMPTY :
+ currstate == GRID_EMPTY ? GRID_FULL : GRID_UNKNOWN;
+ else
+ newstate = currstate == GRID_UNKNOWN ? GRID_FULL :
+ currstate == GRID_FULL ? GRID_EMPTY : GRID_UNKNOWN;
+
+ sprintf(buf, "%c%d,%d,%d,%d",
+ (char)(newstate == GRID_FULL ? 'F' :
+ newstate == GRID_EMPTY ? 'E' : 'U'),
+ ui->cur_x, ui->cur_y, 1, 1);
+ return dupstr(buf);
+ }
+
return NULL;
}
static float *game_colours(frontend *fe, int *ncolours)
{
float *ret = snewn(3 * NCOLOURS, float);
+ int i;
frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
- ret[COL_GRID * 3 + 0] = 0.3F;
- ret[COL_GRID * 3 + 1] = 0.3F;
- ret[COL_GRID * 3 + 2] = 0.3F;
-
- ret[COL_UNKNOWN * 3 + 0] = 0.5F;
- ret[COL_UNKNOWN * 3 + 1] = 0.5F;
- ret[COL_UNKNOWN * 3 + 2] = 0.5F;
-
- ret[COL_TEXT * 3 + 0] = 0.0F;
- ret[COL_TEXT * 3 + 1] = 0.0F;
- ret[COL_TEXT * 3 + 2] = 0.0F;
-
- ret[COL_FULL * 3 + 0] = 0.0F;
- ret[COL_FULL * 3 + 1] = 0.0F;
- ret[COL_FULL * 3 + 2] = 0.0F;
-
- ret[COL_EMPTY * 3 + 0] = 1.0F;
- ret[COL_EMPTY * 3 + 1] = 1.0F;
- ret[COL_EMPTY * 3 + 2] = 1.0F;
+ for (i = 0; i < 3; i++) {
+ ret[COL_GRID * 3 + i] = 0.3F;
+ ret[COL_UNKNOWN * 3 + i] = 0.5F;
+ ret[COL_TEXT * 3 + i] = 0.0F;
+ ret[COL_FULL * 3 + i] = 0.0F;
+ ret[COL_EMPTY * 3 + i] = 1.0F;
+ }
+ ret[COL_CURSOR * 3 + 0] = 1.0F;
+ ret[COL_CURSOR * 3 + 1] = 0.25F;
+ ret[COL_CURSOR * 3 + 2] = 0.25F;
*ncolours = NCOLOURS;
return ret;
ds->visible = snewn(ds->w * ds->h, unsigned char);
ds->tilesize = 0; /* not decided yet */
memset(ds->visible, 255, ds->w * ds->h);
+ ds->cur_x = ds->cur_y = 0;
return ds;
}
}
static void grid_square(drawing *dr, game_drawstate *ds,
- int y, int x, int state)
+ int y, int x, int state, int cur)
{
- int xl, xr, yt, yb;
+ int xl, xr, yt, yb, dx, dy, dw, dh;
draw_rect(dr, TOCOORD(ds->w, x), TOCOORD(ds->h, y),
TILE_SIZE, TILE_SIZE, COL_GRID);
xr = (x % 5 == 4 || x == ds->w-1 ? 1 : 0);
yb = (y % 5 == 4 || y == ds->h-1 ? 1 : 0);
- draw_rect(dr, TOCOORD(ds->w, x) + 1 + xl, TOCOORD(ds->h, y) + 1 + yt,
- TILE_SIZE - xl - xr - 1, TILE_SIZE - yt - yb - 1,
+ dx = TOCOORD(ds->w, x) + 1 + xl;
+ dy = TOCOORD(ds->h, y) + 1 + yt;
+ dw = TILE_SIZE - xl - xr - 1;
+ dh = TILE_SIZE - yt - yb - 1;
+
+ draw_rect(dr, dx, dy, dw, dh,
(state == GRID_FULL ? COL_FULL :
state == GRID_EMPTY ? COL_EMPTY : COL_UNKNOWN));
+ if (cur) {
+ draw_rect_outline(dr, dx, dy, dw, dh, COL_CURSOR);
+ draw_rect_outline(dr, dx+1, dy+1, dw-2, dh-2, COL_CURSOR);
+ }
draw_update(dr, TOCOORD(ds->w, x), TOCOORD(ds->h, y),
TILE_SIZE, TILE_SIZE);
{
int i, j;
int x1, x2, y1, y2;
+ int cx, cy, cmoved;
if (!ds->started) {
/*
x1 = x2 = y1 = y2 = -1; /* placate gcc warnings */
}
+ if (ui->cur_visible) {
+ cx = ui->cur_x; cy = ui->cur_y;
+ } else {
+ cx = cy = -1;
+ }
+ cmoved = (cx != ds->cur_x || cy != ds->cur_y);
+
/*
* Now draw any grid squares which have changed since last
* redraw.
*/
for (i = 0; i < ds->h; i++) {
for (j = 0; j < ds->w; j++) {
- int val;
+ int val, cc = 0;
/*
* Work out what state this square should be drawn in,
else
val = state->grid[i * state->w + j];
+ if (cmoved) {
+ /* the cursor has moved; if we were the old or
+ * the new cursor position we need to redraw. */
+ if (j == cx && i == cy) cc = 1;
+ if (j == ds->cur_x && i == ds->cur_y) cc = 1;
+ }
+
/*
* Briefly invert everything twice during a completion
* flash.
val != GRID_UNKNOWN)
val = (GRID_FULL ^ GRID_EMPTY) ^ val;
- if (ds->visible[i * ds->w + j] != val) {
- grid_square(dr, ds, i, j, val);
+ if (ds->visible[i * ds->w + j] != val || cc) {
+ grid_square(dr, ds, i, j, val,
+ (j == cx && i == cy));
ds->visible[i * ds->w + j] = val;
}
}
}
+ ds->cur_x = cx; ds->cur_y = cy;
}
static float game_anim_length(game_state *oldstate,
return 0.0F;
}
-static int game_wants_statusbar(void)
-{
- return FALSE;
-}
-
static int game_timing_state(game_state *state, game_ui *ui)
{
return TRUE;
* I'll use 5mm squares by default.
*/
game_compute_size(params, 500, &pw, &ph);
- *x = pw / 100.0;
- *y = ph / 100.0;
+ *x = pw / 100.0F;
+ *y = ph / 100.0F;
}
static void game_print(drawing *dr, game_state *state, int tilesize)
#endif
const struct game thegame = {
- "Pattern", "games.pattern",
+ "Pattern", "games.pattern", "pattern",
default_params,
game_fetch_preset,
decode_params,
dup_game,
free_game,
TRUE, solve_game,
- FALSE, game_text_format,
+ FALSE, game_can_format_as_text_now, game_text_format,
new_ui,
free_ui,
encode_ui,
game_anim_length,
game_flash_length,
TRUE, FALSE, game_print_size, game_print,
- game_wants_statusbar,
+ FALSE, /* wants_statusbar */
FALSE, game_timing_state,
- 0, /* flags */
+ REQUIRE_RBUTTON, /* flags */
};
#ifdef STANDALONE_SOLVER
}
#endif
+
+/* vim: set shiftwidth=4 tabstop=8: */