ref: f967bfa87b6ea08434501558e0c41184fdce333d
parent: 0d43753ff2e02f54dd35e6872be3dafa14d2ea7d
author: Chris Boyle <chris@boyle.name>
date: Wed Dec 21 15:01:25 EST 2016
Prevent starting in a solved state in Fifteen & Flood (cherry picked from Android port, commit cb38abdc71780bd9b393b90514396c338306fa69)
--- a/fifteen.c
+++ b/fifteen.c
@@ -156,6 +156,14 @@
return ret;
}
+static int is_completed(int *tiles, int n) {
+ int p;
+ for (p = 0; p < n; p++)
+ if (tiles[p] != (p < n-1 ? p+1 : 0))
+ return 0;
+ return 1;
+}
+
static char *new_game_desc(const game_params *params, random_state *rs,
char **aux, bool interactive)
{
@@ -171,81 +179,83 @@
tiles = snewn(n, int);
used = snewn(n, bool);
- for (i = 0; i < n; i++) {
- tiles[i] = -1;
- used[i] = false;
- }
+ do {
+ for (i = 0; i < n; i++) {
+ tiles[i] = -1;
+ used[i] = false;
+ }
- gap = random_upto(rs, n);
- tiles[gap] = 0;
- used[0] = true;
+ gap = random_upto(rs, n);
+ tiles[gap] = 0;
+ used[0] = true;
- /*
- * Place everything else except the last two tiles.
- */
- for (x = 0, i = n-1; i > 2; i--) {
- int k = random_upto(rs, i);
- int j;
+ /*
+ * Place everything else except the last two tiles.
+ */
+ for (x = 0, i = n - 1; i > 2; i--) {
+ int k = random_upto(rs, i);
+ int j;
- for (j = 0; j < n; j++)
- if (!used[j] && (k-- == 0))
- break;
+ for (j = 0; j < n; j++)
+ if (!used[j] && (k-- == 0))
+ break;
- assert(j < n && !used[j]);
- used[j] = true;
+ assert(j < n && !used[j]);
+ used[j] = true;
+ while (tiles[x] >= 0)
+ x++;
+ assert(x < n);
+ tiles[x] = j;
+ }
+
+ /*
+ * Find the last two locations, and the last two pieces.
+ */
while (tiles[x] >= 0)
x++;
assert(x < n);
- tiles[x] = j;
- }
-
- /*
- * Find the last two locations, and the last two pieces.
- */
- while (tiles[x] >= 0)
+ x1 = x;
x++;
- assert(x < n);
- x1 = x;
- x++;
- while (tiles[x] >= 0)
- x++;
- assert(x < n);
- x2 = x;
+ while (tiles[x] >= 0)
+ x++;
+ assert(x < n);
+ x2 = x;
- for (i = 0; i < n; i++)
- if (!used[i])
- break;
- p1 = i;
- for (i = p1+1; i < n; i++)
- if (!used[i])
- break;
- p2 = i;
+ for (i = 0; i < n; i++)
+ if (!used[i])
+ break;
+ p1 = i;
+ for (i = p1 + 1; i < n; i++)
+ if (!used[i])
+ break;
+ p2 = i;
- /*
- * Determine the required parity of the overall permutation.
- * This is the XOR of:
- *
- * - The chessboard parity ((x^y)&1) of the gap square. The
- * bottom right counts as even.
- *
- * - The parity of n. (The target permutation is 1,...,n-1,0
- * rather than 0,...,n-1; this is a cyclic permutation of
- * the starting point and hence is odd iff n is even.)
- */
- parity = PARITY_P(params, gap);
+ /*
+ * Determine the required parity of the overall permutation.
+ * This is the XOR of:
+ *
+ * - The chessboard parity ((x^y)&1) of the gap square. The
+ * bottom right counts as even.
+ *
+ * - The parity of n. (The target permutation is 1,...,n-1,0
+ * rather than 0,...,n-1; this is a cyclic permutation of
+ * the starting point and hence is odd iff n is even.)
+ */
+ parity = PARITY_P(params, gap);
- /*
- * Try the last two tiles one way round. If that fails, swap
- * them.
- */
- tiles[x1] = p1;
- tiles[x2] = p2;
- if (perm_parity(tiles, n) != parity) {
- tiles[x1] = p2;
- tiles[x2] = p1;
- assert(perm_parity(tiles, n) == parity);
- }
+ /*
+ * Try the last two tiles one way round. If that fails, swap
+ * them.
+ */
+ tiles[x1] = p1;
+ tiles[x2] = p2;
+ if (perm_parity(tiles, n) != parity) {
+ tiles[x1] = p2;
+ tiles[x2] = p1;
+ assert(perm_parity(tiles, n) == parity);
+ }
+ } while (is_completed(tiles, n));
/*
* Now construct the game description, by describing the tile
@@ -786,11 +796,8 @@
/*
* See if the game has been completed.
*/
- if (!ret->completed) {
+ if (!ret->completed && is_completed(ret->tiles, ret->n)) {
ret->completed = ret->movecount;
- for (p = 0; p < ret->n; p++)
- if (ret->tiles[p] != (p < ret->n-1 ? p+1 : 0))
- ret->completed = 0;
}
return ret;
--- a/flood.c
+++ b/flood.c
@@ -552,8 +552,10 @@
/*
* Invent a random grid.
*/
- for (i = 0; i < wh; i++)
- scratch->grid[i] = random_upto(rs, params->colours);
+ do {
+ for (i = 0; i < wh; i++)
+ scratch->grid[i] = random_upto(rs, params->colours);
+ } while (completed(w, h, scratch->grid));
/*
* Run the solver, and count how many moves it uses.