ref: 0bcb32c9132020ffe2985b542951b05c6ab58b2a
parent: 1f613ba31f2599bf29c35d5a46cc81594f6844ea
author: Simon Tatham <anakin@pobox.com>
date: Sun Mar 12 05:11:43 EDT 2017
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.
--- a/net.c
+++ b/net.c
@@ -2390,24 +2390,31 @@
/*
* 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;