+ }
+
+ if (usage->diag) {
+ /*
+ * Intersectional analysis, \-diagonal vs blocks.
+ */
+ for (b = 0; b < cr; b++)
+ for (n = 1; n <= cr; n++) {
+ if (usage->diag[n-1] ||
+ usage->blk[b*cr+n-1])
+ continue;
+ for (i = 0; i < cr; i++) {
+ scratch->indexlist[i] = cubepos2(diag0(i), n);
+ scratch->indexlist2[i] = cubepos2(usage->blocks->blocks[b][i], n);
+ }
+ if (solver_intersect(usage, scratch->indexlist,
+ scratch->indexlist2
+#ifdef STANDALONE_SOLVER
+ , "intersectional analysis,"
+ " %d in \\-diagonal vs block %s",
+ n, usage->blocks->blocknames[b]
+#endif
+ ) ||
+ solver_intersect(usage, scratch->indexlist2,
+ scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "intersectional analysis,"
+ " %d in block %s vs \\-diagonal",
+ n, usage->blocks->blocknames[b]
+#endif
+ )) {
+ diff = max(diff, DIFF_INTERSECT);
+ goto cont;
+ }
+ }
+
+ /*
+ * Intersectional analysis, /-diagonal vs blocks.
+ */
+ for (b = 0; b < cr; b++)
+ for (n = 1; n <= cr; n++) {
+ if (usage->diag[cr+n-1] ||
+ usage->blk[b*cr+n-1])
+ continue;
+ for (i = 0; i < cr; i++) {
+ scratch->indexlist[i] = cubepos2(diag1(i), n);
+ scratch->indexlist2[i] = cubepos2(usage->blocks->blocks[b][i], n);
+ }
+ if (solver_intersect(usage, scratch->indexlist,
+ scratch->indexlist2
+#ifdef STANDALONE_SOLVER
+ , "intersectional analysis,"
+ " %d in /-diagonal vs block %s",
+ n, usage->blocks->blocknames[b]
+#endif
+ ) ||
+ solver_intersect(usage, scratch->indexlist2,
+ scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "intersectional analysis,"
+ " %d in block %s vs /-diagonal",
+ n, usage->blocks->blocknames[b]
+#endif
+ )) {
+ diff = max(diff, DIFF_INTERSECT);
+ goto cont;
+ }
+ }
+ }
+
+ if (dlev->maxdiff <= DIFF_INTERSECT)
+ break;
+
+ /*
+ * Blockwise set elimination.
+ */
+ for (b = 0; b < cr; b++) {
+ for (i = 0; i < cr; i++)
+ for (n = 1; n <= cr; n++)
+ scratch->indexlist[i*cr+n-1] = cubepos2(usage->blocks->blocks[b][i], n);
+ ret = solver_set(usage, scratch, scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "set elimination, block %s",
+ usage->blocks->blocknames[b]
+#endif
+ );
+ if (ret < 0) {
+ diff = DIFF_IMPOSSIBLE;
+ goto got_result;
+ } else if (ret > 0) {
+ diff = max(diff, DIFF_SET);
+ goto cont;
+ }
+ }
+
+ /*
+ * Row-wise set elimination.
+ */
+ for (y = 0; y < cr; y++) {
+ for (x = 0; x < cr; x++)
+ for (n = 1; n <= cr; n++)
+ scratch->indexlist[x*cr+n-1] = cubepos(x, y, n);
+ ret = solver_set(usage, scratch, scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "set elimination, row %d", 1+y
+#endif
+ );
+ if (ret < 0) {
+ diff = DIFF_IMPOSSIBLE;
+ goto got_result;
+ } else if (ret > 0) {
+ diff = max(diff, DIFF_SET);
+ goto cont;
+ }
+ }
+
+ /*
+ * Column-wise set elimination.
+ */
+ for (x = 0; x < cr; x++) {
+ for (y = 0; y < cr; y++)
+ for (n = 1; n <= cr; n++)
+ scratch->indexlist[y*cr+n-1] = cubepos(x, y, n);
+ ret = solver_set(usage, scratch, scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "set elimination, column %d", 1+x
+#endif
+ );
+ if (ret < 0) {
+ diff = DIFF_IMPOSSIBLE;
+ goto got_result;
+ } else if (ret > 0) {
+ diff = max(diff, DIFF_SET);
+ goto cont;
+ }
+ }
+
+ if (usage->diag) {
+ /*
+ * \-diagonal set elimination.
+ */
+ for (i = 0; i < cr; i++)
+ for (n = 1; n <= cr; n++)
+ scratch->indexlist[i*cr+n-1] = cubepos2(diag0(i), n);
+ ret = solver_set(usage, scratch, scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "set elimination, \\-diagonal"
+#endif
+ );
+ if (ret < 0) {
+ diff = DIFF_IMPOSSIBLE;
+ goto got_result;
+ } else if (ret > 0) {
+ diff = max(diff, DIFF_SET);
+ goto cont;
+ }
+
+ /*
+ * /-diagonal set elimination.
+ */
+ for (i = 0; i < cr; i++)
+ for (n = 1; n <= cr; n++)
+ scratch->indexlist[i*cr+n-1] = cubepos2(diag1(i), n);
+ ret = solver_set(usage, scratch, scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "set elimination, /-diagonal"
+#endif
+ );
+ if (ret < 0) {
+ diff = DIFF_IMPOSSIBLE;
+ goto got_result;
+ } else if (ret > 0) {
+ diff = max(diff, DIFF_SET);
+ goto cont;
+ }
+ }
+
+ if (dlev->maxdiff <= DIFF_SET)
+ break;
+
+ /*
+ * Row-vs-column set elimination on a single number.
+ */
+ for (n = 1; n <= cr; n++) {
+ for (y = 0; y < cr; y++)
+ for (x = 0; x < cr; x++)
+ scratch->indexlist[y*cr+x] = cubepos(x, y, n);
+ ret = solver_set(usage, scratch, scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "positional set elimination, number %d", n
+#endif
+ );
+ if (ret < 0) {
+ diff = DIFF_IMPOSSIBLE;
+ goto got_result;
+ } else if (ret > 0) {
+ diff = max(diff, DIFF_EXTREME);
+ goto cont;
+ }
+ }
+
+ /*
+ * Forcing chains.
+ */
+ if (solver_forcing(usage, scratch)) {
+ diff = max(diff, DIFF_EXTREME);
+ goto cont;
+ }
+
+ /*
+ * If we reach here, we have made no deductions in this
+ * iteration, so the algorithm terminates.
+ */
+ break;
+ }
+
+ /*
+ * Last chance: if we haven't fully solved the puzzle yet, try
+ * recursing based on guesses for a particular square. We pick
+ * one of the most constrained empty squares we can find, which
+ * has the effect of pruning the search tree as much as
+ * possible.
+ */
+ if (dlev->maxdiff >= DIFF_RECURSIVE) {
+ int best, bestcount;
+
+ best = -1;
+ bestcount = cr+1;
+
+ for (y = 0; y < cr; y++)
+ for (x = 0; x < cr; x++)
+ if (!grid[y*cr+x]) {
+ int count;
+
+ /*
+ * An unfilled square. Count the number of
+ * possible digits in it.
+ */
+ count = 0;
+ for (n = 1; n <= cr; n++)
+ if (cube(x,y,n))
+ count++;
+
+ /*
+ * We should have found any impossibilities
+ * already, so this can safely be an assert.
+ */
+ assert(count > 1);
+
+ if (count < bestcount) {
+ bestcount = count;
+ best = y*cr+x;
+ }
+ }
+
+ if (best != -1) {
+ int i, j;
+ digit *list, *ingrid, *outgrid;
+
+ diff = DIFF_IMPOSSIBLE; /* no solution found yet */
+
+ /*
+ * Attempt recursion.
+ */
+ y = best / cr;
+ x = best % cr;
+
+ list = snewn(cr, digit);
+ ingrid = snewn(cr * cr, digit);
+ outgrid = snewn(cr * cr, digit);
+ memcpy(ingrid, grid, cr * cr);
+
+ /* Make a list of the possible digits. */
+ for (j = 0, n = 1; n <= cr; n++)
+ if (cube(x,y,n))
+ list[j++] = n;
+
+#ifdef STANDALONE_SOLVER
+ if (solver_show_working) {
+ char *sep = "";
+ printf("%*srecursing on (%d,%d) [",
+ solver_recurse_depth*4, "", x + 1, y + 1);
+ for (i = 0; i < j; i++) {
+ printf("%s%d", sep, list[i]);
+ sep = " or ";
+ }
+ printf("]\n");
+ }
+#endif
+
+ /*
+ * And step along the list, recursing back into the
+ * main solver at every stage.
+ */
+ for (i = 0; i < j; i++) {
+ 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
+
+ solver(cr, blocks, kblocks, xtype, outgrid, kgrid, dlev);
+
+#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 && dlev->diff != DIFF_IMPOSSIBLE)
+ memcpy(grid, outgrid, cr*cr);
+
+ if (dlev->diff == DIFF_AMBIGUOUS)
+ diff = DIFF_AMBIGUOUS;
+ else if (dlev->diff == 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:
+ dlev->diff = diff;
+ dlev->kdiff = kdiff;
+
+#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->sq2region);
+ sfree(usage->regions);
+ sfree(usage->cube);
+ sfree(usage->row);
+ sfree(usage->col);
+ sfree(usage->blk);
+ if (usage->kblocks) {
+ free_block_structure(usage->kblocks);
+ free_block_structure(usage->extra_cages);
+ sfree(usage->extra_clues);
+ }
+ if (usage->kclues) sfree(usage->kclues);
+ sfree(usage);
+
+ solver_free_scratch(scratch);
+}
+
+/* ----------------------------------------------------------------------
+ * End of solver code.
+ */
+
+/* ----------------------------------------------------------------------
+ * Killer set generator.
+ */
+
+/* ----------------------------------------------------------------------
+ * 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.
+ *
+ * The use of bit sets implies that we support puzzles up to a size of
+ * 32x32 (less if anyone finds a 16-bit machine to compile this on).
+ */
+
+/*
+ * 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, *kblocks;
+ /* grid is a copy of the input grid, modified as we go along */
+ digit *grid;
+ /*
+ * Bitsets. In each of them, bit n is set if digit n has been placed
+ * in the corresponding region. row, col and blk are used for all
+ * puzzles. cge is used only for killer puzzles, and diag is used
+ * only for x-type puzzles.
+ * All of these have cr entries, except diag which only has 2,
+ * and cge, which has as many entries as kblocks.
+ */
+ unsigned int *row, *col, *blk, *cge, *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;
+};
+
+static void gridgen_place(struct gridgen_usage *usage, int x, int y, digit n)
+{
+ unsigned int bit = 1 << n;
+ int cr = usage->cr;
+ usage->row[y] |= bit;
+ usage->col[x] |= bit;
+ usage->blk[usage->blocks->whichblock[y*cr+x]] |= bit;
+ if (usage->cge)
+ usage->cge[usage->kblocks->whichblock[y*cr+x]] |= bit;
+ if (usage->diag) {
+ if (ondiag0(y*cr+x))
+ usage->diag[0] |= bit;
+ if (ondiag1(y*cr+x))
+ usage->diag[1] |= bit;
+ }
+ usage->grid[y*cr+x] = n;
+}
+
+static void gridgen_remove(struct gridgen_usage *usage, int x, int y, digit n)
+{
+ unsigned int mask = ~(1 << n);
+ int cr = usage->cr;
+ usage->row[y] &= mask;
+ usage->col[x] &= mask;
+ usage->blk[usage->blocks->whichblock[y*cr+x]] &= mask;
+ if (usage->cge)
+ usage->cge[usage->kblocks->whichblock[y*cr+x]] &= mask;
+ if (usage->diag) {
+ if (ondiag0(y*cr+x))
+ usage->diag[0] &= mask;
+ if (ondiag1(y*cr+x))
+ usage->diag[1] &= mask;
+ }
+ usage->grid[y*cr+x] = 0;
+}
+
+#define N_SINGLE 32
+
+/*
+ * 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 *steps)
+{
+ int cr = usage->cr;
+ int i, j, n, sx, sy, bestm, bestr, ret;
+ int *digits;
+ unsigned int used;
+
+ /*
+ * Firstly, check for completion! If there are no spaces left
+ * in the grid, we have a solution.
+ */
+ if (usage->nspaces == 0)
+ return TRUE;
+
+ /*
+ * Next, abandon generation if we went over our steps limit.
+ */
+ if (*steps <= 0)
+ return FALSE;
+ (*steps)--;
+
+ /*
+ * 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;
+ used = ~0;
+ i = sx = sy = -1;
+ for (j = 0; j < usage->nspaces; j++) {
+ int x = usage->spaces[j].x, y = usage->spaces[j].y;
+ unsigned int used_xy;
+ int m;
+
+ m = usage->blocks->whichblock[y*cr+x];
+ used_xy = usage->row[y] | usage->col[x] | usage->blk[m];
+ if (usage->cge != NULL)
+ used_xy |= usage->cge[usage->kblocks->whichblock[y*cr+x]];
+ if (usage->cge != NULL)
+ used_xy |= usage->cge[usage->kblocks->whichblock[y*cr+x]];
+ if (usage->diag != NULL) {
+ if (ondiag0(y*cr+x))
+ used_xy |= usage->diag[0];
+ if (ondiag1(y*cr+x))
+ used_xy |= usage->diag[1];
+ }
+
+ /*
+ * Find the number of digits that could go in this space.
+ */
+ m = 0;
+ for (n = 1; n <= cr; n++) {
+ unsigned int bit = 1 << n;
+ if ((used_xy & bit) == 0)
+ m++;
+ }
+ if (m < bestm || (m == bestm && usage->spaces[j].r < bestr)) {
+ bestm = m;
+ bestr = usage->spaces[j].r;
+ sx = x;
+ sy = y;
+ i = j;
+ used = used_xy;
+ }
+ }
+
+ /*
+ * 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 = 1; n <= cr; n++) {
+ unsigned int bit = 1 << n;
+
+ if ((used & bit) == 0)
+ digits[j++] = n;
+ }
+
+ 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. */
+ gridgen_place(usage, sx, sy, n);
+ usage->nspaces--;
+
+ /* Call the solver recursively. Stop when we find a solution. */
+ if (gridgen_real(usage, grid, steps)) {
+ ret = TRUE;
+ break;
+ }
+
+ /* Revert the usage structure. */
+ gridgen_remove(usage, sx, sy, n);
+ usage->nspaces++;
+ }
+
+ 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,
+ struct block_structure *kblocks, int xtype,
+ digit *grid, random_state *rs, int maxsteps)
+{
+ 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 = grid;
+
+ usage->row = snewn(cr, unsigned int);
+ usage->col = snewn(cr, unsigned int);
+ usage->blk = snewn(cr, unsigned int);
+ if (kblocks != NULL) {
+ usage->kblocks = kblocks;
+ usage->cge = snewn(usage->kblocks->nr_blocks, unsigned int);
+ memset(usage->cge, FALSE, kblocks->nr_blocks * sizeof *usage->cge);
+ } else {
+ usage->cge = NULL;
+ }