shithub: puzzles

Download patch

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;