X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=singles.c;h=a9b1d9d3b3005de5c5d487a04d980a8f3ec3817b;hb=7cae89fb4b22c305b3fd98b4e1be065ad527a9f7;hp=6d583aa2e1e4d3069d5fa5203f70a03dd9b16451;hpb=15a4fbd1cdc2cc092bafe85b8ddd8b392bdbda7d;p=sgt-puzzles.git diff --git a/singles.c b/singles.c index 6d583aa..a9b1d9d 100644 --- a/singles.c +++ b/singles.c @@ -170,7 +170,7 @@ static void free_params(game_params *params) 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 */ @@ -200,7 +200,7 @@ static void decode_params(game_params *ret, char const *string) } } -static char *encode_params(game_params *params, int full) +static char *encode_params(const game_params *params, int full) { char data[256]; @@ -212,7 +212,7 @@ static char *encode_params(game_params *params, int full) return dupstr(data); } -static config_item *game_configure(game_params *params) +static config_item *game_configure(const game_params *params) { config_item *ret; char buf[80]; @@ -244,7 +244,7 @@ static config_item *game_configure(game_params *params) 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); @@ -255,7 +255,7 @@ static game_params *custom_params(config_item *cfg) return ret; } -static char *validate_params(game_params *params, int full) +static char *validate_params(const game_params *params, int full) { if (params->w < 2 || params->h < 2) return "Width and neight must be at least two"; @@ -292,7 +292,7 @@ static game_state *blank_game(int w, int h) return state; } -static game_state *dup_game(game_state *state) +static game_state *dup_game(const game_state *state) { game_state *ret = blank_game(state->w, state->h); @@ -333,7 +333,7 @@ static int c2n(char c) { return -1; } -static void unpick_desc(game_params *params, char *desc, +static void unpick_desc(const game_params *params, const char *desc, game_state **sout, char **mout) { game_state *state = blank_game(params->w, params->h); @@ -378,12 +378,12 @@ static char *generate_desc(game_state *state, int issolve) /* --- Useful game functions (completion, etc.) --- */ -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 len, x, y, i; char *ret, *p; @@ -535,16 +535,28 @@ static int check_complete(game_state *state, unsigned flags) for (y = 0; y < h; y++) /* check rows from (0,y) */ error += check_rowcol(state, y*w, 1, w, flags); - /* mark (all) white regions as an error if there is more than one. - * may want to make this less in-your-face (by only marking - * the smallest region as an error, for example -- but what if we - * have two regions of identical size?) */ - for (i = 0; i < state->n; i++) { - if (!(state->flags[i] & F_BLACK) && - dsf_size(dsf, i) < nwhite) { - error += 1; - if (flags & CC_MARK_ERRORS) - state->flags[i] |= F_ERROR; + /* If there's more than one white region, pick the largest one to + * be the canonical one (arbitrarily tie-breaking towards lower + * array indices), and mark all the others as erroneous. */ + { + int largest = 0, canonical = -1; + for (i = 0; i < state->n; i++) + if (!(state->flags[i] & F_BLACK)) { + int size = dsf_size(dsf, i); + if (largest < size) { + largest = size; + canonical = i; + } + } + + if (largest < nwhite) { + for (i = 0; i < state->n; i++) + if (!(state->flags[i] & F_BLACK) && + dsf_canonify(dsf, i) != canonical) { + error += 1; + if (flags & CC_MARK_ERRORS) + state->flags[i] |= F_ERROR; + } } } @@ -552,7 +564,8 @@ static int check_complete(game_state *state, unsigned flags) return (error > 0) ? 0 : 1; } -static char *game_state_diff(game_state *src, game_state *dst, int issolve) +static char *game_state_diff(const game_state *src, const game_state *dst, + int issolve) { char *ret = NULL, buf[80], c; int retlen = 0, x, y, i, k; @@ -1171,8 +1184,8 @@ static int solve_specific(game_state *state, int diff, int sneaky) return state->impossible ? -1 : check_complete(state, CC_MUST_FILL); } -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) { game_state *solved = dup_game(currstate); char *move = NULL; @@ -1207,7 +1220,7 @@ solved: the solver gets a headstart working out where they are. */ -static int new_game_is_good(game_params *params, +static int new_game_is_good(const game_params *params, game_state *state, game_state *tosolve) { int sret, sret_easy = 0; @@ -1289,7 +1302,7 @@ found: return j; } -static char *new_game_desc(game_params *params, random_state *rs, +static char *new_game_desc(const game_params *params, random_state *rs, char **aux, int interactive) { game_state *state = blank_game(params->w, params->h); @@ -1401,7 +1414,7 @@ randomise: return ret; } -static char *validate_desc(game_params *params, char *desc) +static char *validate_desc(const game_params *params, const char *desc) { char *ret = NULL; @@ -1409,7 +1422,8 @@ static char *validate_desc(game_params *params, char *desc) return ret; } -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) { game_state *state = NULL; @@ -1425,7 +1439,7 @@ struct game_ui { int show_black_nums; }; -static game_ui *new_ui(game_state *state) +static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); @@ -1440,17 +1454,17 @@ static void free_ui(game_ui *ui) 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) { if (!oldstate->completed && newstate->completed) ui->cshow = 0; @@ -1471,8 +1485,9 @@ struct game_drawstate { unsigned int *flags; }; -static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, - int mx, int my, int button) +static char *interpret_move(const game_state *state, game_ui *ui, + const game_drawstate *ds, + int mx, int my, int button) { char buf[80], c; int i, x = FROMCOORD(mx), y = FROMCOORD(my); @@ -1522,7 +1537,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds, return NULL; } -static game_state *execute_move(game_state *state, char *move) +static game_state *execute_move(const game_state *state, const char *move) { game_state *ret = dup_game(state); int x, y, i, n; @@ -1567,8 +1582,8 @@ badmove: * 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) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -1579,7 +1594,7 @@ static void game_compute_size(game_params *params, int tilesize, } static void game_set_size(drawing *dr, game_drawstate *ds, - game_params *params, int tilesize) + const game_params *params, int tilesize) { ds->tilesize = tilesize; } @@ -1608,7 +1623,7 @@ static float *game_colours(frontend *fe, int *ncolours) 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) { struct game_drawstate *ds = snew(struct game_drawstate); @@ -1673,9 +1688,10 @@ static void tile_redraw(drawing *dr, game_drawstate *ds, int x, int y, draw_update(dr, x, y, TILE_SIZE, TILE_SIZE); } -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 x, y, i, flash; unsigned int f; @@ -1720,14 +1736,14 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, ds->started = 1; } -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 && !newstate->used_solve) @@ -1735,17 +1751,17 @@ static float game_flash_length(game_state *oldstate, game_state *newstate, return 0.0F; } -static int game_status(game_state *state) +static int game_status(const game_state *state) { return state->completed ? +1 : 0; } -static int game_timing_state(game_state *state, game_ui *ui) +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; @@ -1755,7 +1771,7 @@ static void game_print_size(game_params *params, float *x, float *y) *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 ink = print_mono_colour(dr, 0); int paper = print_mono_colour(dr, 1);