}
#endif
-struct game_aux_info {
- int w, h;
- unsigned char *vedge; /* (w+1) x h */
- unsigned char *hedge; /* w x (h+1) */
-};
-
static char *new_game_desc(game_params *params, random_state *rs,
- game_aux_info **aux, int interactive)
+ char **aux, int interactive)
{
int *grid, *numbers = NULL;
int x, y, y2, y2last, yx, run, i, nsquares;
}
/*
- * Store the rectangle data in the game_aux_info.
+ * Store the solution in aux.
*/
{
- game_aux_info *ai = snew(game_aux_info);
+ char *ai;
+ int len;
- ai->w = params->w;
- ai->h = params->h;
- ai->vedge = snewn(ai->w * ai->h, unsigned char);
- ai->hedge = snewn(ai->w * ai->h, unsigned char);
+ len = 2 + (params->w-1)*params->h + (params->h-1)*params->w;
+ ai = snewn(len, char);
+
+ ai[0] = 'S';
+
+ p = ai+1;
for (y = 0; y < params->h; y++)
- for (x = 1; x < params->w; x++) {
- vedge(ai, x, y) =
- index(params, grid, x, y) != index(params, grid, x-1, y);
- }
+ for (x = 1; x < params->w; x++)
+ *p++ = (index(params, grid, x, y) !=
+ index(params, grid, x-1, y) ? '1' : '0');
+
for (y = 1; y < params->h; y++)
- for (x = 0; x < params->w; x++) {
- hedge(ai, x, y) =
- index(params, grid, x, y) != index(params, grid, x, y-1);
- }
+ for (x = 0; x < params->w; x++)
+ *p++ = (index(params, grid, x, y) !=
+ index(params, grid, x, y-1) ? '1' : '0');
+
+ assert(p - ai == len-1);
+ *p = '\0';
*aux = ai;
}
return desc;
}
-static void game_free_aux_info(game_aux_info *ai)
-{
- sfree(ai->vedge);
- sfree(ai->hedge);
- sfree(ai);
-}
-
static char *validate_desc(game_params *params, char *desc)
{
int area = params->w * params->h;
}
static char *solve_game(game_state *state, game_state *currstate,
- game_aux_info *ai, char **error)
+ char *ai, char **error)
{
unsigned char *vedge, *hedge;
- int edges_need_freeing;
int x, y, len;
char *ret, *p;
+ int i, j, n;
+ struct numberdata *nd;
- if (!ai) {
- int i, j, n;
- struct numberdata *nd;
-
- /*
- * Attempt the in-built solver.
- */
-
- /* Set up each number's (very short) candidate position list. */
- for (i = n = 0; i < state->h * state->w; i++)
- if (state->grid[i])
- n++;
-
- nd = snewn(n, struct numberdata);
-
- for (i = j = 0; i < state->h * state->w; i++)
- if (state->grid[i]) {
- nd[j].area = state->grid[i];
- nd[j].npoints = 1;
- nd[j].points = snewn(1, struct point);
- nd[j].points[0].x = i % state->w;
- nd[j].points[0].y = i / state->w;
- j++;
- }
+ if (ai)
+ return dupstr(ai);
- assert(j == n);
+ /*
+ * Attempt the in-built solver.
+ */
- vedge = snewn(state->w * state->h, unsigned char);
- hedge = snewn(state->w * state->h, unsigned char);
- memset(vedge, 0, state->w * state->h);
- memset(hedge, 0, state->w * state->h);
- edges_need_freeing = TRUE;
+ /* Set up each number's (very short) candidate position list. */
+ for (i = n = 0; i < state->h * state->w; i++)
+ if (state->grid[i])
+ n++;
+
+ nd = snewn(n, struct numberdata);
+
+ for (i = j = 0; i < state->h * state->w; i++)
+ if (state->grid[i]) {
+ nd[j].area = state->grid[i];
+ nd[j].npoints = 1;
+ nd[j].points = snewn(1, struct point);
+ nd[j].points[0].x = i % state->w;
+ nd[j].points[0].y = i / state->w;
+ j++;
+ }
- rect_solver(state->w, state->h, n, nd, hedge, vedge, NULL);
+ assert(j == n);
- /*
- * Clean up.
- */
- for (i = 0; i < n; i++)
- sfree(nd[i].points);
- sfree(nd);
- } else {
- assert(state->w == ai->w);
- assert(state->h == ai->h);
- vedge = ai->vedge;
- hedge = ai->hedge;
- edges_need_freeing = FALSE;
- }
+ vedge = snewn(state->w * state->h, unsigned char);
+ hedge = snewn(state->w * state->h, unsigned char);
+ memset(vedge, 0, state->w * state->h);
+ memset(hedge, 0, state->w * state->h);
+
+ rect_solver(state->w, state->h, n, nd, hedge, vedge, NULL);
+
+ /*
+ * Clean up.
+ */
+ for (i = 0; i < n; i++)
+ sfree(nd[i].points);
+ sfree(nd);
len = 2 + (state->w-1)*state->h + (state->h-1)*state->w;
ret = snewn(len, char);
p = ret;
*p++ = 'S';
for (y = 0; y < state->h; y++)
- for (x = 1; x < state->w; x++)
- *p++ = vedge[y*state->w+x] ? '1' : '0';
+ for (x = 1; x < state->w; x++)
+ *p++ = vedge[y*state->w+x] ? '1' : '0';
for (y = 1; y < state->h; y++)
for (x = 0; x < state->w; x++)
*p++ = hedge[y*state->w+x] ? '1' : '0';
*p++ = '\0';
assert(p - ret == len);
- if (edges_need_freeing) {
- sfree(vedge);
- sfree(hedge);
- }
+ sfree(vedge);
+ sfree(hedge);
return ret;
}
sfree(ui);
}
-char *encode_ui(game_ui *ui)
+static char *encode_ui(game_ui *ui)
{
return NULL;
}
-void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, char *encoding)
{
}
coord_round(FROMCOORD((float)x), FROMCOORD((float)y), &xc, &yc);
- if (startdrag) {
+ if (startdrag &&
+ xc >= 0 && xc <= 2*from->w &&
+ yc >= 0 && yc <= 2*from->h) {
+
ui->drag_start_x = xc;
ui->drag_start_y = yc;
ui->drag_end_x = xc;
active = TRUE;
}
- if (xc != ui->drag_end_x || yc != ui->drag_end_y) {
+ if (ui->drag_start_x >= 0 &&
+ (xc != ui->drag_end_x || yc != ui->drag_end_y)) {
int t;
ui->drag_end_x = xc;
ret = NULL;
- if (enddrag) {
+ if (enddrag && (ui->drag_start_x >= 0)) {
if (xc >= 0 && xc <= 2*from->w &&
yc >= 0 && yc <= 2*from->h) {
#define COLOUR(k) ( (k)==1 ? COL_LINE : COL_DRAG )
#define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) )
-static void game_size(game_params *params, game_drawstate *ds,
- int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+ int *x, int *y)
{
- int tsx, tsy, ts;
- /*
- * Each window dimension equals the tile size times 1.5 more
- * than the grid dimension (the border is 3/4 the width of the
- * tiles).
- *
- * We must cast to unsigned before multiplying by two, because
- * *x might be INT_MAX.
- */
- tsx = 2 * (unsigned)*x / (2 * params->w + 3);
- tsy = 2 * (unsigned)*y / (2 * params->h + 3);
- ts = min(tsx, tsy);
- if (expand)
- ds->tilesize = ts;
- else
- ds->tilesize = min(ts, PREFERRED_TILE_SIZE);
+ /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+ struct { int tilesize; } ads, *ds = &ads;
+ ads.tilesize = tilesize;
*x = params->w * TILE_SIZE + 2*BORDER + 1;
*y = params->h * TILE_SIZE + 2*BORDER + 1;
}
+static void game_set_size(game_drawstate *ds, game_params *params,
+ int tilesize)
+{
+ ds->tilesize = tilesize;
+}
+
static float *game_colours(frontend *fe, game_state *state, int *ncolours)
{
float *ret = snewn(3 * NCOLOURS, float);
TRUE, game_configure, custom_params,
validate_params,
new_game_desc,
- game_free_aux_info,
validate_desc,
new_game,
dup_game,
game_changed_state,
interpret_move,
execute_move,
- game_size,
+ PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
game_colours,
game_new_drawstate,
game_free_drawstate,