typedef unsigned char digit;
#define ORDER_MAX 255
-#define TILE_SIZE 32
-#define BORDER 18
+#define PREFERRED_TILE_SIZE 32
+#define TILE_SIZE (ds->tilesize)
+#define BORDER (TILE_SIZE / 2)
#define FLASH_TIME 0.4F
sfree(ui);
}
+static void game_changed_state(game_ui *ui, game_state *oldstate,
+ game_state *newstate)
+{
+ int c = newstate->c, r = newstate->r, cr = c*r;
+ /*
+ * We prevent pencil-mode highlighting of a filled square. So
+ * if the user has just filled in a square which we had a
+ * pencil-mode highlight in (by Undo, or by Redo, or by Solve),
+ * then we cancel the highlight.
+ */
+ if (ui->hx >= 0 && ui->hy >= 0 && ui->hpencil &&
+ newstate->grid[ui->hy * cr + ui->hx] != 0) {
+ ui->hx = ui->hy = -1;
+ }
+}
+
+struct game_drawstate {
+ int started;
+ int c, r, cr;
+ int tilesize;
+ digit *grid;
+ unsigned char *pencil;
+ unsigned char *hl;
+ /* This is scratch space used within a single call to game_redraw. */
+ int *entered_items;
+};
+
static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
int x, int y, int button)
{
* Drawing routines.
*/
-struct game_drawstate {
- int started;
- int c, r, cr;
- digit *grid;
- unsigned char *pencil;
- unsigned char *hl;
- /* This is scratch space used within a single call to game_redraw. */
- int *entered_items;
-};
-
-#define XSIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
-#define YSIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
+#define SIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
+#define GETTILESIZE(cr, w) ( (w-1) / (cr+1) )
-static void game_size(game_params *params, int *x, int *y)
+static void game_size(game_params *params, game_drawstate *ds,
+ int *x, int *y, int expand)
{
int c = params->c, r = params->r, cr = c*r;
+ int ts;
+
+ ts = min(GETTILESIZE(cr, *x), GETTILESIZE(cr, *y));
+ if (expand)
+ ds->tilesize = ts;
+ else
+ ds->tilesize = min(ts, PREFERRED_TILE_SIZE);
- *x = XSIZE(cr);
- *y = YSIZE(cr);
+ *x = SIZE(cr);
+ *y = SIZE(cr);
}
static float *game_colours(frontend *fe, game_state *state, int *ncolours)
ds->hl = snewn(cr*cr, unsigned char);
memset(ds->hl, 0, cr*cr);
ds->entered_items = snewn(cr*cr, int);
+ ds->tilesize = 0; /* not decided yet */
return ds;
}
* all games should start by drawing a big
* background-colour rectangle covering the whole window.
*/
- draw_rect(fe, 0, 0, XSIZE(cr), YSIZE(cr), COL_BACKGROUND);
+ draw_rect(fe, 0, 0, SIZE(cr), SIZE(cr), COL_BACKGROUND);
/*
* Draw the grid.
/* Mark obvious errors (ie, numbers which occur more than once
* in a single row, column, or box). */
- if ((ds->entered_items[x*cr+d-1] & 2) ||
- (ds->entered_items[y*cr+d-1] & 8) ||
- (ds->entered_items[((x/r)+(y/c)*c)*cr+d-1] & 32))
+ if (d && ((ds->entered_items[x*cr+d-1] & 2) ||
+ (ds->entered_items[y*cr+d-1] & 8) ||
+ (ds->entered_items[((x/r)+(y/c)*c)*cr+d-1] & 32)))
highlight |= 16;
draw_number(fe, ds, state, x, y, highlight);
* Update the _entire_ grid if necessary.
*/
if (!ds->started) {
- draw_update(fe, 0, 0, XSIZE(cr), YSIZE(cr));
+ draw_update(fe, 0, 0, SIZE(cr), SIZE(cr));
ds->started = TRUE;
}
}
TRUE, game_text_format,
new_ui,
free_ui,
+ game_changed_state,
make_move,
game_size,
game_colours,