shithub: puzzles

Download patch

ref: 1e6e3a815eb67a0d0d369fd0971cf9f3fd9fbf9a
parent: 59ac8a69af1330a6ea482154b05bc23ec33b594d
author: Simon Tatham <anakin@pobox.com>
date: Thu Apr 11 15:39:03 EDT 2019

Dominosa: be more careful about >= Hard layout.

Now we don't just ensure that alloc_try_hard arranged a confounder for
every domino; we also make sure that the full Basic-mode solver can't
place even a single domino with certainty.

--- a/dominosa.c
+++ b/dominosa.c
@@ -1916,9 +1916,45 @@
             if (!alloc_try_unique(as, rs))
                 continue;
         } else {
-            /* Try to arrange that there is no easy starting point */
+            /*
+             * For Hard puzzles and above, we'd like there not to be
+             * any easy toehold to start with.
+             *
+             * Mostly, that's arranged by alloc_try_hard, which will
+             * ensure that no domino starts off with only one
+             * potential placement. But a few other deductions
+             * possible at Basic level can still sneak through the
+             * cracks - for example, if the only two placements of one
+             * domino overlap in a square, and you therefore rule out
+             * some other domino that can use that square, you might
+             * then find that _that_ domino now has only one
+             * placement, and you've made a start.
+             *
+             * Of course, the main difficulty-level check will still
+             * guarantee that you have to do a harder deduction
+             * _somewhere_ in the grid. But it's more elegant if
+             * there's nowhere obvious to get started at all.
+             */
+            int di;
+            bool ok;
+
             if (!alloc_try_hard(as, rs))
                 continue;
+
+            solver_setup_grid(sc, as->numbers);
+            if (run_solver(sc, DIFF_BASIC) < 2)
+                continue;
+
+            ok = true;
+            for (di = 0; di < sc->dc; di++)
+                if (sc->dominoes[di].nplacements <= 1) {
+                    ok = false;
+                    break;
+                }
+
+            if (!ok) {
+                continue;
+            }
         }
 
         if (diff != DIFF_AMBIGUOUS) {