From: Simon Tatham Date: Sun, 12 Mar 2017 09:11:43 +0000 (+0000) Subject: Net: fix completion check if top left square is empty. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=0bcb32c9132020ffe2985b542951b05c6ab58b2a;p=sgt-puzzles.git Net: fix completion check if top left square is empty. A hand-typed grid is permitted to use the square type '0' (never generated by Net's own grid generator), which is a completely empty square. This requires an adjustment to the completion checker, so that such squares aren't required to be connected; otherwise, a grid containing one would be permanently uncompletable. However, the completion checker missed one case - it was unconditionally checking that all squares are connected to the _top left corner_, on the basis that (before I thought of the zero square) any source square is as good as any other if what you really want to know is whether they're all connected to each other. But that means that if the top left square _is_ the empty one, things to wrong - e.g. 5x5:02c328ade11adb129d7c3e524 would fail to give a completion flash. Fixed by starting the completion-checking search from the first non-empty square we find. --- diff --git a/net.c b/net.c index 349b13d..d3952a8 100644 --- a/net.c +++ b/net.c @@ -2390,24 +2390,31 @@ static game_state *execute_move(const game_state *from, const char *move) /* * Check whether the game has been completed. * - * For this purpose it doesn't matter where the source square - * is, because we can start from anywhere and correctly - * determine whether the game is completed. + * For this purpose it doesn't matter where the source square is, + * because we can start from anywhere (or, at least, any square + * that's non-empty!), and correctly determine whether the game is + * completed. */ { - unsigned char *active = compute_active(ret, 0, 0); - int x1, y1; + unsigned char *active; + int pos; int complete = TRUE; - for (x1 = 0; x1 < ret->width; x1++) - for (y1 = 0; y1 < ret->height; y1++) - if ((tile(ret, x1, y1) & 0xF) && !index(ret, active, x1, y1)) { + for (pos = 0; pos < ret->width * ret->height; pos++) + if (ret->tiles[pos] & 0xF) + break; + + if (pos < ret->width * ret->height) { + active = compute_active(ret, pos % ret->width, pos / ret->width); + + for (pos = 0; pos < ret->width * ret->height; pos++) + if ((ret->tiles[pos] & 0xF) && !active[pos]) { complete = FALSE; - goto break_label; /* break out of two loops at once */ - } - break_label: + break; + } - sfree(active); + sfree(active); + } if (complete) ret->completed = TRUE;