- /*
- * Try the last two tiles one way round. If that fails, swap
- * them.
- */
- tiles[x1] = p1;
- tiles[x2] = p2;
- if (perm_parity(tiles, n) != 0) {
- tiles[x1] = p2;
- tiles[x2] = p1;
- assert(perm_parity(tiles, n) == 0);
- }
+ /*
+ * Now save the move into the `prev' variables.
+ */
+ if (start == prevstart && offset == prevoffset) {
+ nrepeats++;
+ } else {
+ prevstart = start;
+ prevoffset = offset;
+ prevdirection = direction;
+ nrepeats = 1;
+ }
+
+ /*
+ * And make it.
+ */
+ if (direction < 0) {
+ start += (len-1) * offset;
+ offset = -offset;
+ }
+ tmp = tiles[start];
+ for (j = 0; j+1 < len; j++)
+ tiles[start + j*offset] = tiles[start + (j+1)*offset];
+ tiles[start + (len-1) * offset] = tmp;
+ }
+
+ } else {
+
+ used = snewn(n, int);
+
+ for (i = 0; i < n; i++) {
+ tiles[i] = -1;
+ used[i] = FALSE;
+ }
+
+ /*
+ * If both dimensions are odd, there is a parity
+ * constraint.
+ */
+ if (params->w & params->h & 1)
+ stop = 2;
+ else
+ stop = 0;
+
+ /*
+ * Place everything except (possibly) the last two tiles.
+ */
+ for (x = 0, i = n; i > stop; i--) {
+ int k = i > 1 ? random_upto(rs, i) : 0;
+ int j;
+
+ for (j = 0; j < n; j++)
+ if (!used[j] && (k-- == 0))
+ break;
+
+ assert(j < n && !used[j]);
+ used[j] = TRUE;
+
+ while (tiles[x] >= 0)
+ x++;
+ assert(x < n);
+ tiles[x] = j;
+ }
+
+ if (stop) {
+ /*
+ * Find the last two locations, and the last two
+ * pieces.
+ */
+ while (tiles[x] >= 0)
+ x++;
+ assert(x < n);
+ x1 = x;
+ 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;
+
+ /*
+ * Try the last two tiles one way round. If that fails,
+ * swap them.
+ */
+ tiles[x1] = p1;
+ tiles[x2] = p2;
+ if (perm_parity(tiles, n) != 0) {
+ tiles[x1] = p2;
+ tiles[x2] = p1;
+ assert(perm_parity(tiles, n) == 0);
+ }
+ }
+
+ sfree(used);