+ /*
+ * And step along the list, recursing back into the
+ * main solver at every stage.
+ */
+ for (i = 0; i < j; i++) {
+ int ret;
+
+ memcpy(outgrid, ingrid, cr * cr);
+ outgrid[y*cr+x] = list[i];
+
+#ifdef STANDALONE_SOLVER
+ if (solver_show_working)
+ printf("%*sguessing %d at (%d,%d)\n",
+ solver_recurse_depth*4, "", list[i], x + 1, y + 1);
+ solver_recurse_depth++;
+#endif
+
+ ret = solver(cr, blocks, xtype, outgrid, maxdiff);
+
+#ifdef STANDALONE_SOLVER
+ solver_recurse_depth--;
+ if (solver_show_working) {
+ printf("%*sretracting %d at (%d,%d)\n",
+ solver_recurse_depth*4, "", list[i], x + 1, y + 1);
+ }
+#endif
+
+ /*
+ * If we have our first solution, copy it into the
+ * grid we will return.
+ */
+ if (diff == DIFF_IMPOSSIBLE && ret != DIFF_IMPOSSIBLE)
+ memcpy(grid, outgrid, cr*cr);
+
+ if (ret == DIFF_AMBIGUOUS)
+ diff = DIFF_AMBIGUOUS;
+ else if (ret == DIFF_IMPOSSIBLE)
+ /* do not change our return value */;
+ else {
+ /* the recursion turned up exactly one solution */
+ if (diff == DIFF_IMPOSSIBLE)
+ diff = DIFF_RECURSIVE;
+ else
+ diff = DIFF_AMBIGUOUS;
+ }
+
+ /*
+ * As soon as we've found more than one solution,
+ * give up immediately.
+ */
+ if (diff == DIFF_AMBIGUOUS)
+ break;
+ }
+
+ sfree(outgrid);
+ sfree(ingrid);
+ sfree(list);
+ }
+
+ } else {
+ /*
+ * We're forbidden to use recursion, so we just see whether
+ * our grid is fully solved, and return DIFF_IMPOSSIBLE
+ * otherwise.
+ */
+ for (y = 0; y < cr; y++)
+ for (x = 0; x < cr; x++)
+ if (!grid[y*cr+x])
+ diff = DIFF_IMPOSSIBLE;
+ }
+
+ got_result:;
+
+#ifdef STANDALONE_SOLVER
+ if (solver_show_working)
+ printf("%*s%s found\n",
+ solver_recurse_depth*4, "",
+ diff == DIFF_IMPOSSIBLE ? "no solution" :
+ diff == DIFF_AMBIGUOUS ? "multiple solutions" :
+ "one solution");
+#endif
+
+ sfree(usage->cube);
+ sfree(usage->row);
+ sfree(usage->col);
+ sfree(usage->blk);
+ sfree(usage);
+
+ solver_free_scratch(scratch);
+
+ return diff;
+}
+
+/* ----------------------------------------------------------------------
+ * End of solver code.
+ */
+
+/* ----------------------------------------------------------------------
+ * Solo filled-grid generator.
+ *
+ * This grid generator works by essentially trying to solve a grid
+ * starting from no clues, and not worrying that there's more than
+ * one possible solution. Unfortunately, it isn't computationally
+ * feasible to do this by calling the above solver with an empty
+ * grid, because that one needs to allocate a lot of scratch space
+ * at every recursion level. Instead, I have a much simpler
+ * algorithm which I shamelessly copied from a Python solver
+ * written by Andrew Wilkinson (which is GPLed, but I've reused
+ * only ideas and no code). It mostly just does the obvious
+ * recursive thing: pick an empty square, put one of the possible
+ * digits in it, recurse until all squares are filled, backtrack
+ * and change some choices if necessary.
+ *
+ * The clever bit is that every time it chooses which square to
+ * fill in next, it does so by counting the number of _possible_
+ * numbers that can go in each square, and it prioritises so that
+ * it picks a square with the _lowest_ number of possibilities. The
+ * idea is that filling in lots of the obvious bits (particularly
+ * any squares with only one possibility) will cut down on the list
+ * of possibilities for other squares and hence reduce the enormous
+ * search space as much as possible as early as possible.
+ */
+
+/*
+ * Internal data structure used in gridgen to keep track of
+ * progress.
+ */
+struct gridgen_coord { int x, y, r; };
+struct gridgen_usage {
+ int cr;
+ struct block_structure *blocks;
+ /* grid is a copy of the input grid, modified as we go along */
+ digit *grid;
+ /* row[y*cr+n-1] TRUE if digit n has been placed in row y */
+ unsigned char *row;
+ /* col[x*cr+n-1] TRUE if digit n has been placed in row x */
+ unsigned char *col;
+ /* blk[(y*c+x)*cr+n-1] TRUE if digit n has been placed in block (x,y) */
+ unsigned char *blk;
+ /* diag[i*cr+n-1] TRUE if digit n has been placed in diagonal i */
+ unsigned char *diag;
+ /* This lists all the empty spaces remaining in the grid. */
+ struct gridgen_coord *spaces;
+ int nspaces;
+ /* If we need randomisation in the solve, this is our random state. */
+ random_state *rs;
+};
+
+/*
+ * The real recursive step in the generating function.
+ *
+ * Return values: 1 means solution found, 0 means no solution
+ * found on this branch.
+ */
+static int gridgen_real(struct gridgen_usage *usage, digit *grid)
+{
+ int cr = usage->cr;
+ int i, j, n, sx, sy, bestm, bestr, ret;
+ int *digits;
+
+ /*
+ * Firstly, check for completion! If there are no spaces left
+ * in the grid, we have a solution.
+ */
+ if (usage->nspaces == 0) {
+ memcpy(grid, usage->grid, cr * cr);
+ return TRUE;
+ }
+
+ /*
+ * Otherwise, there must be at least one space. Find the most
+ * constrained space, using the `r' field as a tie-breaker.
+ */
+ bestm = cr+1; /* so that any space will beat it */
+ bestr = 0;
+ i = sx = sy = -1;
+ for (j = 0; j < usage->nspaces; j++) {
+ int x = usage->spaces[j].x, y = usage->spaces[j].y;
+ int m;
+
+ /*
+ * Find the number of digits that could go in this space.
+ */
+ m = 0;
+ for (n = 0; n < cr; n++)
+ if (!usage->row[y*cr+n] && !usage->col[x*cr+n] &&
+ !usage->blk[usage->blocks->whichblock[y*cr+x]*cr+n] &&
+ (!usage->diag || ((!ondiag0(y*cr+x) || !usage->diag[n]) &&
+ (!ondiag1(y*cr+x) || !usage->diag[cr+n]))))
+ m++;
+
+ if (m < bestm || (m == bestm && usage->spaces[j].r < bestr)) {
+ bestm = m;
+ bestr = usage->spaces[j].r;
+ sx = x;
+ sy = y;
+ i = j;
+ }
+ }
+
+ /*
+ * Swap that square into the final place in the spaces array,
+ * so that decrementing nspaces will remove it from the list.
+ */
+ if (i != usage->nspaces-1) {
+ struct gridgen_coord t;
+ t = usage->spaces[usage->nspaces-1];
+ usage->spaces[usage->nspaces-1] = usage->spaces[i];
+ usage->spaces[i] = t;
+ }
+
+ /*
+ * Now we've decided which square to start our recursion at,
+ * simply go through all possible values, shuffling them
+ * randomly first if necessary.
+ */
+ digits = snewn(bestm, int);
+ j = 0;
+ for (n = 0; n < cr; n++)
+ if (!usage->row[sy*cr+n] && !usage->col[sx*cr+n] &&
+ !usage->blk[usage->blocks->whichblock[sy*cr+sx]*cr+n] &&
+ (!usage->diag || ((!ondiag0(sy*cr+sx) || !usage->diag[n]) &&
+ (!ondiag1(sy*cr+sx) || !usage->diag[cr+n])))) {
+ digits[j++] = n+1;
+ }
+
+ if (usage->rs)
+ shuffle(digits, j, sizeof(*digits), usage->rs);
+
+ /* And finally, go through the digit list and actually recurse. */
+ ret = FALSE;
+ for (i = 0; i < j; i++) {
+ n = digits[i];
+
+ /* Update the usage structure to reflect the placing of this digit. */
+ usage->row[sy*cr+n-1] = usage->col[sx*cr+n-1] =
+ usage->blk[usage->blocks->whichblock[sy*cr+sx]*cr+n-1] = TRUE;
+ if (usage->diag) {
+ if (ondiag0(sy*cr+sx))
+ usage->diag[n-1] = TRUE;
+ if (ondiag1(sy*cr+sx))
+ usage->diag[cr+n-1] = TRUE;
+ }
+ usage->grid[sy*cr+sx] = n;
+ usage->nspaces--;
+
+ /* Call the solver recursively. Stop when we find a solution. */
+ if (gridgen_real(usage, grid))
+ ret = TRUE;
+
+ /* Revert the usage structure. */
+ usage->row[sy*cr+n-1] = usage->col[sx*cr+n-1] =
+ usage->blk[usage->blocks->whichblock[sy*cr+sx]*cr+n-1] = FALSE;
+ if (usage->diag) {
+ if (ondiag0(sy*cr+sx))
+ usage->diag[n-1] = FALSE;
+ if (ondiag1(sy*cr+sx))
+ usage->diag[cr+n-1] = FALSE;
+ }
+ usage->grid[sy*cr+sx] = 0;
+ usage->nspaces++;
+
+ if (ret)
+ break;
+ }
+
+ sfree(digits);
+ return ret;
+}
+
+/*
+ * Entry point to generator. You give it parameters and a starting
+ * grid, which is simply an array of cr*cr digits.
+ */
+static int gridgen(int cr, struct block_structure *blocks, int xtype,
+ digit *grid, random_state *rs)
+{
+ struct gridgen_usage *usage;
+ int x, y, ret;
+
+ /*
+ * Clear the grid to start with.
+ */
+ memset(grid, 0, cr*cr);
+
+ /*
+ * Create a gridgen_usage structure.
+ */
+ usage = snew(struct gridgen_usage);
+
+ usage->cr = cr;
+ usage->blocks = blocks;
+
+ usage->grid = snewn(cr * cr, digit);
+ memcpy(usage->grid, grid, cr * cr);
+
+ usage->row = snewn(cr * cr, unsigned char);
+ usage->col = snewn(cr * cr, unsigned char);
+ usage->blk = snewn(cr * cr, unsigned char);
+ memset(usage->row, FALSE, cr * cr);
+ memset(usage->col, FALSE, cr * cr);
+ memset(usage->blk, FALSE, cr * cr);
+
+ if (xtype) {
+ usage->diag = snewn(2 * cr, unsigned char);
+ memset(usage->diag, FALSE, 2 * cr);
+ } else {
+ usage->diag = NULL;
+ }