X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=palisade.c;h=b9d578d0f7f05e1f55c61b95c52f231c86f5c5d4;hb=db313b3948d27244dd7c34c2609c66d6204d8931;hp=f7b379128505d5fa0a6d5c01efa391e4d1b226f6;hpb=d60e348aae16e718e1e7cc2b6e090956eb7e4b52;p=sgt-puzzles.git diff --git a/palisade.c b/palisade.c index f7b3791..b9d578d 100644 --- a/palisade.c +++ b/palisade.c @@ -511,10 +511,20 @@ static void dfs_dsf(int i, int w, borderflag *border, int *dsf, int black) static int is_solved(const game_params *params, clue *clues, borderflag *border) { - int wh = params->w * params->h, k = params->k, *dsf = snew_dsf(wh), i; + int w = params->w, h = params->h, wh = w*h, k = params->k; + int i, x, y; + int *dsf = snew_dsf(wh); assert (dsf[0] == UNVISITED); /* check: UNVISITED and dsf.c match up */ + /* + * A game is solved if: + * + * - the borders drawn on the grid divide it into connected + * components such that every square is in a component of the + * correct size + * - the borders also satisfy the clue set + */ for (i = 0; i < wh; ++i) { if (dsf[i] == UNVISITED) dfs_dsf(i, params->w, border, dsf, TRUE); if (dsf_size(dsf, i) != k) goto error; @@ -522,6 +532,26 @@ static int is_solved(const game_params *params, clue *clues, if (clues[i] != bitcount[border[i] & BORDER_MASK]) goto error; } + /* + * ... and thirdly: + * + * - there are no *stray* borders, in that every border is + * actually part of the division between two components. + * Otherwise you could cheat by finding a subdivision which did + * not *exceed* any clue square's counter, and then adding a + * few extra edges. + */ + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if (x+1 < w && (border[y*w+x] & BORDER_R) && + dsf_canonify(dsf, y*w+x) == dsf_canonify(dsf, y*w+(x+1))) + goto error; + if (y+1 < h && (border[y*w+x] & BORDER_D) && + dsf_canonify(dsf, y*w+x) == dsf_canonify(dsf, (y+1)*w+x)) + goto error; + } + } + sfree(dsf); return TRUE; @@ -667,17 +697,17 @@ static char *validate_desc(const game_params *params, const char *desc) int w = params->w, h = params->h, wh = w*h, squares = 0; for (/* nop */; *desc; ++desc) { - if (islower(*desc)) { + if (islower((unsigned char)*desc)) { squares += *desc - 'a' + 1; - } else if (isdigit(*desc)) { + } else if (isdigit((unsigned char)*desc)) { if (*desc > '4') { static char buf[] = "Invalid (too large) number: '5'"; - assert (isdigit(buf[lenof(buf) - 3])); + assert (isdigit((unsigned char)buf[lenof(buf) - 3])); buf[lenof(buf) - 3] = *desc; /* ... or 6, 7, 8, 9 :-) */ return buf; } ++squares; - } else if (isprint(*desc)) { + } else if (isprint((unsigned char)*desc)) { static char buf[] = "Invalid character in data: '?'"; buf[lenof(buf) - 3] = *desc; return buf; @@ -702,8 +732,8 @@ static game_state *new_game(midend *me, const game_params *params, setmem(state->shared->clues, EMPTY, wh); for (i = 0; *desc; ++desc) { - if (isdigit(*desc)) state->shared->clues[i++] = *desc - '0'; - else if (isalpha(*desc)) i += *desc - 'a' + 1; + if (isdigit((unsigned char)*desc)) state->shared->clues[i++] = *desc - '0'; + else if (isalpha((unsigned char)*desc)) i += *desc - 'a' + 1; } snewa(state->borders, wh); @@ -1317,7 +1347,7 @@ static void game_print(drawing *dr, const game_state *state, int tilesize) const struct game thegame = { "Palisade", "games.palisade", "palisade", default_params, - game_fetch_preset, + game_fetch_preset, NULL, decode_params, encode_params, free_params,