+ if (done_something)
+ continue;
+
+ /*
+ * Now see what we can do with the vbitmap array. All
+ * vbitmap deductions are disabled at Easy level.
+ */
+ if (difficulty <= DIFF_EASY)
+ continue;
+
+ for (y = 0; y < h; y++)
+ for (x = 0; x < w; x++) {
+ int s, c;
+
+ /*
+ * Any line already placed in a square must rule
+ * out any type of v which contradicts it.
+ */
+ if ((s = soln[y*w+x]) != 0) {
+ if (x > 0)
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y, (s < 0 ? 0x1 : 0x2),
+ "contradicts known edge at (%d,%d)",x,y);
+ if (x+1 < w)
+ done_something |=
+ vbitmap_clear(w, h, sc, x, y, (s < 0 ? 0x2 : 0x1),
+ "contradicts known edge at (%d,%d)",x,y);
+ if (y > 0)
+ done_something |=
+ vbitmap_clear(w, h, sc, x, y-1, (s < 0 ? 0x4 : 0x8),
+ "contradicts known edge at (%d,%d)",x,y);
+ if (y+1 < h)
+ done_something |=
+ vbitmap_clear(w, h, sc, x, y, (s < 0 ? 0x8 : 0x4),
+ "contradicts known edge at (%d,%d)",x,y);
+ }
+
+ /*
+ * If both types of v are ruled out for a pair of
+ * adjacent squares, mark them as equivalent.
+ */
+ if (x+1 < w && !(sc->vbitmap[y*w+x] & 0x3)) {
+ int n1 = y*w+x, n2 = y*w+(x+1);
+ if (dsf_canonify(sc->equiv, n1) !=
+ dsf_canonify(sc->equiv, n2)) {
+ dsf_merge(sc->equiv, n1, n2);
+ done_something = TRUE;
+#ifdef SOLVER_DIAGNOSTICS
+ if (verbose)
+ printf("(%d,%d) and (%d,%d) must be equivalent"
+ " because both v-shapes are ruled out\n",
+ x, y, x+1, y);
+#endif
+ }
+ }
+ if (y+1 < h && !(sc->vbitmap[y*w+x] & 0xC)) {
+ int n1 = y*w+x, n2 = (y+1)*w+x;
+ if (dsf_canonify(sc->equiv, n1) !=
+ dsf_canonify(sc->equiv, n2)) {
+ dsf_merge(sc->equiv, n1, n2);
+ done_something = TRUE;
+#ifdef SOLVER_DIAGNOSTICS
+ if (verbose)
+ printf("(%d,%d) and (%d,%d) must be equivalent"
+ " because both v-shapes are ruled out\n",
+ x, y, x, y+1);
+#endif
+ }
+ }
+
+ /*
+ * The remaining work in this loop only works
+ * around non-edge clue points.
+ */
+ if (y == 0 || x == 0)
+ continue;
+ if ((c = clues[y*W+x]) < 0)
+ continue;
+
+ /*
+ * x,y marks a clue point not on the grid edge. See
+ * if this clue point allows us to rule out any v
+ * shapes.
+ */
+
+ if (c == 1) {
+ /*
+ * A 1 clue can never have any v shape pointing
+ * at it.
+ */
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y-1, 0x5,
+ "points at 1 clue at (%d,%d)", x, y);
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y, 0x2,
+ "points at 1 clue at (%d,%d)", x, y);
+ done_something |=
+ vbitmap_clear(w, h, sc, x, y-1, 0x8,
+ "points at 1 clue at (%d,%d)", x, y);
+ } else if (c == 3) {
+ /*
+ * A 3 clue can never have any v shape pointing
+ * away from it.
+ */
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y-1, 0xA,
+ "points away from 3 clue at (%d,%d)", x, y);
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y, 0x1,
+ "points away from 3 clue at (%d,%d)", x, y);
+ done_something |=
+ vbitmap_clear(w, h, sc, x, y-1, 0x4,
+ "points away from 3 clue at (%d,%d)", x, y);
+ } else if (c == 2) {
+ /*
+ * If a 2 clue has any kind of v ruled out on
+ * one side of it, the same v is ruled out on
+ * the other side.
+ */
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y-1,
+ (sc->vbitmap[(y )*w+(x-1)] & 0x3) ^ 0x3,
+ "propagated by 2 clue at (%d,%d)", x, y);
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y-1,
+ (sc->vbitmap[(y-1)*w+(x )] & 0xC) ^ 0xC,
+ "propagated by 2 clue at (%d,%d)", x, y);
+ done_something |=
+ vbitmap_clear(w, h, sc, x-1, y,
+ (sc->vbitmap[(y-1)*w+(x-1)] & 0x3) ^ 0x3,
+ "propagated by 2 clue at (%d,%d)", x, y);
+ done_something |=
+ vbitmap_clear(w, h, sc, x, y-1,
+ (sc->vbitmap[(y-1)*w+(x-1)] & 0xC) ^ 0xC,
+ "propagated by 2 clue at (%d,%d)", x, y);
+ }
+
+#undef CLEARBITS
+
+ }
+