#define setmember(obj, field) ( (obj) . field = field )
-static char *nfmtstr(int n, char *fmt, ...) {
+static char *nfmtstr(int n, const char *fmt, ...) {
va_list va;
char *ret = snewn(n+1, char);
va_start(va, fmt);
ret[0].name = "Width";
ret[0].type = C_STRING;
- ret[0].sval = nfmtstr(10, "%d", params->w);
- ret[0].ival = 0;
+ ret[0].u.string.sval = nfmtstr(10, "%d", params->w);
ret[1].name = "Height";
ret[1].type = C_STRING;
- ret[1].sval = nfmtstr(10, "%d", params->h);
- ret[1].ival = 0;
+ ret[1].u.string.sval = nfmtstr(10, "%d", params->h);
ret[2].name = NULL;
ret[2].type = C_END;
- ret[2].sval = NULL;
- ret[2].ival = 0;
return ret;
}
static game_params *custom_params(const config_item *configuration)
{
game_params *ret = snew(game_params);
- ret->w = atoi(configuration[0].sval);
- ret->h = atoi(configuration[1].sval);
+ ret->w = atoi(configuration[0].u.string.sval);
+ ret->h = atoi(configuration[1].u.string.sval);
return ret;
}
static move *solve_internal(const game_state *state, move *base, int diff);
static char *solve_game(const game_state *orig, const game_state *curpos,
- const char *aux, char **error)
+ const char *aux, const char **error)
{
int const n = orig->params.w * orig->params.h;
move *const base = snewn(n, move);
return k;
}
-static char *validate_params(const game_params *params, int full)
+static const char *validate_params(const game_params *params, int full)
{
int const w = params->w, h = params->h;
if (w < 1) return "Error: width is less than 1";
return desc;
}
-static char *validate_desc(const game_params *params, const char *desc)
+static const char *validate_desc(const game_params *params, const char *desc)
{
int const n = params->w * params->h;
int squares = 0;
static char *game_text_format(const game_state *state)
{
- int cellsize, r, c, i, w_string, h_string, n_string;
+ int r, c, i, w_string, h_string, n_string;
+ char cellsize;
char *ret, *buf, *gridline;
int const w = state->params.w, h = state->params.h;
cellsize = 0; /* or may be used uninitialized */
for (c = 0; c < w; ++c) {
- for (r = 1; r < h; ++r) {
+ for (r = 0; r < h; ++r) {
puzzle_size k = state->grid[idx(r, c, w)];
int d;
for (d = 0; k; k /= 10, ++d);
enum {none, forwards, backwards, hint};
int const w = state->params.w, h = state->params.h;
int r = ui->r, c = ui->c, action = none, cell;
+ int shift = button & MOD_SHFT;
+ button &= ~shift;
if (IS_CURSOR_SELECT(button) && !ui->cursor_show) return NULL;
int i;
for (i = 0; i < 4 && cursors[i] != button; ++i);
assert (i < 4);
- if (!out_of_bounds(ui->r + dr[i], ui->c + dc[i], w, h)) {
+ if (shift) {
+ int pre_r = r, pre_c = c, do_pre, do_post;
+ cell = state->grid[idx(r, c, state->params.w)];
+ do_pre = (cell == EMPTY);
+
+ if (out_of_bounds(ui->r + dr[i], ui->c + dc[i], w, h)) {
+ if (do_pre)
+ return nfmtstr(40, "W,%d,%d", pre_r, pre_c);
+ else
+ return NULL;
+ }
+
+ ui->r += dr[i];
+ ui->c += dc[i];
+
+ cell = state->grid[idx(ui->r, ui->c, state->params.w)];
+ do_post = (cell == EMPTY);
+
+ /* (do_pre ? "..." : "") concat (do_post ? "..." : "") */
+ if (do_pre && do_post)
+ return nfmtstr(80, "W,%d,%dW,%d,%d",
+ pre_r, pre_c, ui->r, ui->c);
+ else if (do_pre)
+ return nfmtstr(40, "W,%d,%d", pre_r, pre_c);
+ else if (do_post)
+ return nfmtstr(40, "W,%d,%d", ui->r, ui->c);
+ else
+ return UI_UPDATE;
+
+ } else if (!out_of_bounds(ui->r + dr[i], ui->c + dc[i], w, h)) {
ui->r += dr[i];
ui->c += dc[i];
}
} else ui->cursor_show = TRUE;
- return "";
+ return UI_UPDATE;
}
if (action == hint) {
int biggest, canonical;
if (!report) {
- printf("dfs fail at %d\n", any_white_cell);
+ sfree(dsf);
goto found_error;
}
if (!ds->started) {
ds->started = TRUE;
draw_rect(dr, 0, 0, wpx, hpx, COL_BACKGROUND);
- draw_rect(dr, BORDER-1, BORDER-1,
- ds->tilesize*w+2, ds->tilesize*h+2, COL_GRID);
draw_update(dr, 0, 0, wpx, hpx);
}
cell.flash || cell.cursor ?
COL_LOWLIGHT : COL_BACKGROUND);
- draw_rect (draw, x, y, ts, ts, colour);
- draw_rect_outline(draw, x, y, ts, ts, COL_GRID);
+ draw_rect_outline(draw, x, y, ts + 1, ts + 1, COL_GRID);
+ draw_rect (draw, x + 1, y + 1, ts - 1, ts - 1, colour);
+ if (cell.error)
+ draw_rect_outline(draw, x + 1, y + 1, ts - 1, ts - 1, COL_ERROR);
switch (cell.value) {
case WHITE: draw_rect(draw, tx - dotsz / 2, ty - dotsz / 2, dotsz, dotsz,
cell.error ? COL_ERROR : COL_USER);
- case BLACK: break;
- case EMPTY:
- if (cell.error)
- draw_circle(draw, tx, ty, dotsz / 2, COL_ERROR, COL_GRID);
- break;
+ case BLACK: case EMPTY: break;
default:
{
int const colour = (cell.error ? COL_ERROR : COL_GRID);
}
}
- draw_update(draw, x, y, ts, ts);
+ draw_update(draw, x, y, ts + 1, ts + 1);
}
static int game_timing_state(const game_state *state, game_ui *ui)
struct game const thegame = {
"Range", "games.range", "range",
default_params,
- game_fetch_preset,
+ game_fetch_preset, NULL,
decode_params,
encode_params,
free_params,