+static int solver_adjacent(game_solver *usolver)
+{
+ struct latin_solver *solver = &usolver->latin;
+ int nchanged = 0, x, y, i, n, o = usolver->latin.o, nx, ny, gd;
+
+ /* Update possible values based on known values and adjacency clues. */
+
+ for (x = 0; x < o; x++) {
+ for (y = 0; y < o; y++) {
+ if (grid(x, y) == 0) continue;
+
+ /* We have a definite number here. Make sure that any
+ * adjacent possibles reflect the adjacent/non-adjacent clue. */
+
+ for (i = 0; i < 4; i++) {
+ int isadjacent = (GRID(usolver->state, flags, x, y) & adjthan[i].f);
+
+ nx = x + adjthan[i].dx, ny = y + adjthan[i].dy;
+ if (nx < 0 || ny < 0 || nx >= o || ny >= o)
+ continue;
+
+ for (n = 0; n < o; n++) {
+ /* Continue past numbers the adjacent square _could_ be,
+ * given the clue we have. */
+ gd = abs((n+1) - grid(x, y));
+ if (isadjacent && (gd == 1)) continue;
+ if (!isadjacent && (gd != 1)) continue;
+
+ if (cube(nx, ny, n+1) == FALSE)
+ continue; /* already discounted this possibility. */
+
+#ifdef STANDALONE_SOLVER
+ if (solver_show_working) {
+ printf("%*sadjacent elimination, (%d,%d):%d %s (%d,%d):\n",
+ solver_recurse_depth*4, "",
+ x, y, grid(x, y), isadjacent ? "|" : "!|", nx, ny);
+ printf("%*s ruling out %d at (%d,%d)\n",
+ solver_recurse_depth*4, "", n+1, nx, ny);
+ }
+#endif
+ cube(nx, ny, n+1) = FALSE;
+ nchanged++;
+ }
+ }
+ }
+ }
+
+ return nchanged;
+}
+
+static int solver_adjacent_set(game_solver *usolver)
+{
+ struct latin_solver *solver = &usolver->latin;
+ int x, y, i, n, nn, o = usolver->latin.o, nx, ny, gd;
+ int nchanged = 0, *scratch = snewn(o, int);
+
+ /* Update possible values based on other possible values
+ * of adjacent squares, and adjacency clues. */
+
+ for (x = 0; x < o; x++) {
+ for (y = 0; y < o; y++) {
+ for (i = 0; i < o; i++) {
+ int isadjacent = (GRID(usolver->state, flags, x, y) & adjthan[i].f);
+
+ nx = x + adjthan[i].dx, ny = y + adjthan[i].dy;
+ if (nx < 0 || ny < 0 || nx >= o || ny >= o)
+ continue;
+
+ /* We know the current possibles for the square (x,y)
+ * and also the adjacency clue from (x,y) to (nx,ny).
+ * Construct a maximum set of possibles for (nx,ny)
+ * in scratch, based on these constraints... */
+
+ memset(scratch, 0, o*sizeof(int));
+
+ for (n = 0; n < o; n++) {
+ if (cube(x, y, n+1) == FALSE) continue;
+
+ for (nn = 0; nn < o; nn++) {
+ if (n == nn) continue;
+
+ gd = abs(nn - n);
+ if (isadjacent && (gd != 1)) continue;
+ if (!isadjacent && (gd == 1)) continue;
+
+ scratch[nn] = 1;
+ }
+ }
+
+ /* ...and remove any possibilities for (nx,ny) that are
+ * currently set but are not indicated in scratch. */
+ for (n = 0; n < o; n++) {
+ if (scratch[n] == 1) continue;
+ if (cube(nx, ny, n+1) == FALSE) continue;
+
+#ifdef STANDALONE_SOLVER
+ if (solver_show_working) {
+ printf("%*sadjacent possible elimination, (%d,%d) %s (%d,%d):\n",
+ solver_recurse_depth*4, "",
+ x, y, isadjacent ? "|" : "!|", nx, ny);
+ printf("%*s ruling out %d at (%d,%d)\n",
+ solver_recurse_depth*4, "", n+1, nx, ny);
+ }
+#endif
+ cube(nx, ny, n+1) = FALSE;
+ nchanged++;
+ }
+ }
+ }
+ }
+
+ return nchanged;
+}
+