sfree(params);
}
-static game_params *dup_params(game_params *params)
+static game_params *dup_params(const game_params *params)
{
game_params *ret = snew(game_params);
*ret = *params; /* structure copy */
}
}
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
{
char buf[120];
return dupstr(buf);
}
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
{
config_item *ret;
char buf[80];
return ret;
}
-static game_params *custom_params(config_item *cfg)
+static game_params *custom_params(const config_item *cfg)
{
game_params *ret = snew(game_params);
return ret;
}
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
{
/*
* Generating anything under 4x4 runs into trouble of one kind
char *soln, struct solver_scratch *sc, int diff)
{
int x, y, d, i, j;
- char *mrow, *mrow1, *mrow2, *trow, *trow1, *trow2;
+ char *mrow, *trow, *trow1, *trow2;
/*
* Set up solver data.
* hasn't been set up yet.
*/
mrow = sc->mrows;
- mrow1 = sc->mrows + len;
- mrow2 = sc->mrows + 2*len;
trow = sc->trows;
trow1 = sc->trows + len;
trow2 = sc->trows + 2*len;
return 1;
}
-static char *new_game_desc(game_params *params, random_state *rs,
+static char *new_game_desc(const game_params *params_in, random_state *rs,
char **aux, int interactive)
{
+ game_params params_copy = *params_in; /* structure copy */
+ game_params *params = ¶ms_copy;
int w = params->w, h = params->h;
int ntrees = w * h / 5;
char *grid = snewn(w*h, char);
return ret;
}
-static char *validate_desc(game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
{
int w = params->w, h = params->h;
int area, i;
desc++;
}
+ if (area < w * h + 1)
+ return "Not enough data to fill grid";
+ else if (area > w * h + 1)
+ return "Too much data to fill grid";
for (i = 0; i < w+h; i++) {
if (!*desc)
return NULL;
}
-static game_state *new_game(midend *me, game_params *params, char *desc)
+static game_state *new_game(midend *me, const game_params *params,
+ const char *desc)
{
int w = params->w, h = params->h;
game_state *state = snew(game_state);
return state;
}
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
{
int w = state->p.w, h = state->p.h;
game_state *ret = snew(game_state);
sfree(state);
}
-static char *solve_game(game_state *state, game_state *currstate,
- char *aux, char **error)
+static char *solve_game(const game_state *state, const game_state *currstate,
+ const char *aux, char **error)
{
int w = state->p.w, h = state->p.h;
}
}
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
{
return TRUE;
}
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
{
int w = state->p.w, h = state->p.h;
char *ret, *p;
int cx, cy, cdisp; /* cursor position, and ?display. */
};
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
{
game_ui *ui = snew(game_ui);
ui->dsx = ui->dsy = -1;
sfree(ui);
}
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
{
return NULL;
}
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
{
}
-static void game_changed_state(game_ui *ui, game_state *oldstate,
- game_state *newstate)
+static void game_changed_state(game_ui *ui, const game_state *oldstate,
+ const game_state *newstate)
{
}
#define FLASH_TIME 0.30F
-static int drag_xform(game_ui *ui, int x, int y, int v)
+static int drag_xform(const game_ui *ui, int x, int y, int v)
{
int xmin, ymin, xmax, ymax;
ymin = min(ui->dsy, ui->dey);
ymax = max(ui->dsy, ui->dey);
+#ifndef STYLUS_BASED
/*
* Left-dragging has no effect, so we treat a left-drag as a
* single click on dsx,dsy.
xmin = xmax = ui->dsx;
ymin = ymax = ui->dsy;
}
+#endif
if (x < xmin || x > xmax || y < ymin || y > ymax)
return v; /* no change outside drag area */
* Results of a simple click. Left button sets blanks to
* tents; right button sets blanks to non-tents; either
* button clears a non-blank square.
+ * If stylus-based however, it loops instead.
*/
if (ui->drag_button == LEFT_BUTTON)
+#ifdef STYLUS_BASED
+ v = (v == BLANK ? TENT : (v == TENT ? NONTENT : BLANK));
+ else
+ v = (v == BLANK ? NONTENT : (v == NONTENT ? TENT : BLANK));
+#else
v = (v == BLANK ? TENT : BLANK);
else
v = (v == BLANK ? NONTENT : BLANK);
+#endif
} else {
/*
* Results of a drag. Left-dragging has no effect.
if (ui->drag_button == RIGHT_BUTTON)
v = (v == BLANK ? NONTENT : v);
else
+#ifdef STYLUS_BASED
+ v = (v == BLANK ? NONTENT : v);
+#else
/* do nothing */;
+#endif
}
return v;
}
-static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
- int x, int y, int button)
+static char *interpret_move(const game_state *state, game_ui *ui,
+ const game_drawstate *ds,
+ int x, int y, int button)
{
int w = state->p.w, h = state->p.h;
char tmpbuf[80];
return NULL;
}
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
{
int w = state->p.w, h = state->p.h;
char c;
* Drawing routines.
*/
-static void game_compute_size(game_params *params, int tilesize,
- int *x, int *y)
+static void game_compute_size(const game_params *params, int tilesize,
+ int *x, int *y)
{
/* fool the macros */
struct dummy { int tilesize; } dummy, *ds = &dummy;
}
static void game_set_size(drawing *dr, game_drawstate *ds,
- game_params *params, int tilesize)
+ const game_params *params, int tilesize)
{
ds->tilesize = tilesize;
}
return ret;
}
-static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
+static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
{
int w = state->p.w, h = state->p.h;
struct game_drawstate *ds = snew(struct game_drawstate);
ERR_OVERCOMMITTED
};
-static int *find_errors(game_state *state, char *grid)
+static int *find_errors(const game_state *state, char *grid)
{
int w = state->p.w, h = state->p.h;
int *ret = snewn(w*h + w + h, int);
* Also, that approach fares badly when you introduce the
* additional requirement that incomplete grids should have
* errors highlighted only when they can be proved to be errors
- * - so that a tree surrounded by BLANK squares should not be
- * marked as erroneous (it would be patronising, since the
- * overwhelming likelihood is not that the player has forgotten
- * to put a tree there but that they have merely not put one
- * there _yet), but one surrounded by NONTENTs should.
+ * - so that trees should not be marked as having too few tents
+ * if there are enough BLANK squares remaining around them that
+ * could be turned into the missing tents (to do so would be
+ * patronising, since the overwhelming likelihood is not that
+ * the player has forgotten to put a tree there but that they
+ * have merely not put one there _yet_). However, tents with too
+ * few trees can be marked immediately, since those are
+ * definitely player error.
*
* So I adopt an alternative approach, which is to consider the
* bipartite adjacency graph between trees and tents
/*
* Internal redraw function, used for printing as well as drawing.
*/
-static void int_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
- game_state *state, int dir, game_ui *ui,
+static void int_redraw(drawing *dr, game_drawstate *ds,
+ const game_state *oldstate, const game_state *state,
+ int dir, const game_ui *ui,
float animtime, float flashtime, int printing)
{
int w = state->p.w, h = state->p.h;
* currently active drag: we transform dsx,dsy but not anything
* else. (This seems to strike a good compromise between having
* the error highlights respond instantly to single clicks, but
- * not give constant feedback during a right-drag.)
+ * not giving constant feedback during a right-drag.)
*/
if (ui && ui->drag_button >= 0) {
tmpgrid = snewn(w*h, char);
* changed) the numbers.
*/
for (x = 0; x < w; x++) {
- if (ds->numbersdrawn[x] != errors[w*h+x]) {
+ if (printing || ds->numbersdrawn[x] != errors[w*h+x]) {
char buf[80];
draw_rect(dr, COORD(x), COORD(h)+1, TILESIZE, BRBORDER-1,
COL_BACKGROUND);
FONT_VARIABLE, TILESIZE/2, ALIGN_HCENTRE|ALIGN_VNORMAL,
(errors[w*h+x] ? COL_ERROR : COL_GRID), buf);
draw_update(dr, COORD(x), COORD(h)+1, TILESIZE, BRBORDER-1);
- ds->numbersdrawn[x] = errors[w*h+x];
+ if (!printing)
+ ds->numbersdrawn[x] = errors[w*h+x];
}
}
for (y = 0; y < h; y++) {
- if (ds->numbersdrawn[w+y] != errors[w*h+w+y]) {
+ if (printing || ds->numbersdrawn[w+y] != errors[w*h+w+y]) {
char buf[80];
draw_rect(dr, COORD(w)+1, COORD(y), BRBORDER-1, TILESIZE,
COL_BACKGROUND);
FONT_VARIABLE, TILESIZE/2, ALIGN_HRIGHT|ALIGN_VCENTRE,
(errors[w*h+w+y] ? COL_ERROR : COL_GRID), buf);
draw_update(dr, COORD(w)+1, COORD(y), BRBORDER-1, TILESIZE);
- ds->numbersdrawn[w+y] = errors[w*h+w+y];
+ if (!printing)
+ ds->numbersdrawn[w+y] = errors[w*h+w+y];
}
}
sfree(errors);
}
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
- game_state *state, int dir, game_ui *ui,
- float animtime, float flashtime)
+static void game_redraw(drawing *dr, game_drawstate *ds,
+ const game_state *oldstate, const game_state *state,
+ int dir, const game_ui *ui,
+ float animtime, float flashtime)
{
int_redraw(dr, ds, oldstate, state, dir, ui, animtime, flashtime, FALSE);
}
-static float game_anim_length(game_state *oldstate, game_state *newstate,
- int dir, game_ui *ui)
+static float game_anim_length(const game_state *oldstate,
+ const game_state *newstate, int dir, game_ui *ui)
{
return 0.0F;
}
-static float game_flash_length(game_state *oldstate, game_state *newstate,
- int dir, game_ui *ui)
+static float game_flash_length(const game_state *oldstate,
+ const game_state *newstate, int dir, game_ui *ui)
{
if (!oldstate->completed && newstate->completed &&
!oldstate->used_solve && !newstate->used_solve)
return 0.0F;
}
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_status(const game_state *state)
+{
+ return state->completed ? +1 : 0;
+}
+
+static int game_timing_state(const game_state *state, game_ui *ui)
{
return TRUE;
}
-static void game_print_size(game_params *params, float *x, float *y)
+static void game_print_size(const game_params *params, float *x, float *y)
{
int pw, ph;
*y = ph / 100.0F;
}
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
{
int c;
game_redraw,
game_anim_length,
game_flash_length,
+ game_status,
TRUE, FALSE, game_print_size, game_print,
FALSE, /* wants_statusbar */
FALSE, game_timing_state,