+ if (!usage->grid[y*cr+x]) {
+ for (n = 1; n <= cr; n++)
+ scratch->indexlist[n-1] = cubepos(x, y, n);
+ ret = solver_elim(usage, scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "numeric elimination at (%d,%d)",
+ 1+x, 1+y
+#endif
+ );
+ if (ret < 0) {
+ diff = DIFF_IMPOSSIBLE;
+ goto got_result;
+ } else if (ret > 0) {
+ diff = max(diff, DIFF_SIMPLE);
+ goto cont;
+ }
+ }
+
+ if (maxdiff <= DIFF_SIMPLE)
+ break;
+
+ /*
+ * Intersectional analysis, rows vs blocks.
+ */
+ for (y = 0; y < cr; y++)
+ for (b = 0; b < cr; b++)
+ for (n = 1; n <= cr; n++) {
+ if (usage->row[y*cr+n-1] ||
+ usage->blk[b*cr+n-1])
+ continue;
+ for (i = 0; i < cr; i++) {
+ scratch->indexlist[i] = cubepos(i, y, n);
+ scratch->indexlist2[i] = cubepos2(usage->blocks->blocks[b][i], n);
+ }
+ /*
+ * solver_intersect() never returns -1.
+ */
+ if (solver_intersect(usage, scratch->indexlist,
+ scratch->indexlist2
+#ifdef STANDALONE_SOLVER
+ , "intersectional analysis,"
+ " %d in row %d vs block %s",
+ n, 1+y, usage->blocks->blocknames[b]
+#endif
+ ) ||
+ solver_intersect(usage, scratch->indexlist2,
+ scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "intersectional analysis,"
+ " %d in block %s vs row %d",
+ n, usage->blocks->blocknames[b], 1+y
+#endif
+ )) {
+ diff = max(diff, DIFF_INTERSECT);
+ goto cont;
+ }
+ }
+
+ /*
+ * Intersectional analysis, columns vs blocks.
+ */
+ for (x = 0; x < cr; x++)
+ for (b = 0; b < cr; b++)
+ for (n = 1; n <= cr; n++) {
+ if (usage->col[x*cr+n-1] ||
+ usage->blk[b*cr+n-1])
+ continue;
+ for (i = 0; i < cr; i++) {
+ scratch->indexlist[i] = cubepos(x, 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 column %d vs block %s",
+ n, 1+x, usage->blocks->blocknames[b]
+#endif
+ ) ||
+ solver_intersect(usage, scratch->indexlist2,
+ scratch->indexlist
+#ifdef STANDALONE_SOLVER
+ , "intersectional analysis,"
+ " %d in block %s vs column %d",
+ n, usage->blocks->blocknames[b], 1+x
+#endif
+ )) {
+ diff = max(diff, DIFF_INTERSECT);
+ goto cont;
+ }
+ }
+
+ 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, 1+x, 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], 1+x
+#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, 1+x, 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], 1+x
+#endif
+ )) {
+ diff = max(diff, DIFF_INTERSECT);
+ goto cont;
+ }
+ }
+ }
+
+ if (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 (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;
+ }