shithub: puzzles

Download patch

ref: f018ef97d34b9126744e63cc2112c302fcae4ab4
parent: 08009f3949b5cf6edfd36e904dd8abadb19dd7ba
author: Simon Tatham <anakin@pobox.com>
date: Sun Mar 12 10:11:34 EDT 2023

Galaxies: fix recursion depth limit in solver.

The static variable 'solver_recurse_depth' is _mostly_ used by the
standalone solver, to appropriately indent the solver diagnostics for
the current recursion level. So most uses of it are guarded by an
'#ifdef STANDALONE_SOLVER' statement, or some equivalent (such as
being inside the solvep() macro).

One exception is the check that limits the recursion depth to 5, to
avoid getting hung up forever on a too-hard game. Unfortunately, this
check depends on the variable actually incrementing when we recurse
another level - and it wasn't, because the increment itself was under
ifdef! So the generator in live Galaxies could recurse arbitrarily
deep, and generate puzzles that the standalone solver found too hard
_even_ at Unreasonable mode.

Removed the ifdefs, so that solver_recurse_depth is now incremented
and decremented. Also, make sure to initialise the depth to 0 at the
start of a solver run, just in case it had a bogus value left over
from a previous run.

--- a/galaxies.c
+++ b/galaxies.c
@@ -187,6 +187,7 @@
 };
 
 static bool check_complete(const game_state *state, int *dsf, int *colours);
+static int solver_state_inner(game_state *state, int maxdiff);
 static int solver_state(game_state *state, int maxdiff);
 static int solver_obvious(game_state *state);
 static int solver_obvious_dot(game_state *state, space *dot);
@@ -2415,9 +2416,7 @@
            solver_recurse_depth*4, "",
            rctx.best->x, rctx.best->y, rctx.bestn));
 
-#ifdef STANDALONE_SOLVER
     solver_recurse_depth++;
-#endif
 
     ingrid = snewn(gsz, space);
     memcpy(ingrid, state->grid, gsz * sizeof(space));
@@ -2432,7 +2431,7 @@
                          state->dots[n]->x, state->dots[n]->y,
                          "Attempting for recursion");
 
-        ret = solver_state(state, maxdiff);
+        ret = solver_state_inner(state, maxdiff);
 
         if (diff == DIFF_IMPOSSIBLE && ret != DIFF_IMPOSSIBLE) {
             /* we found our first solved grid; copy it away. */
@@ -2464,9 +2463,7 @@
             break;
     }
 
-#ifdef STANDALONE_SOLVER
     solver_recurse_depth--;
-#endif
 
     if (outgrid) {
         /* we found (at least one) soln; copy it back to state */
@@ -2477,7 +2474,7 @@
     return diff;
 }
 
-static int solver_state(game_state *state, int maxdiff)
+static int solver_state_inner(game_state *state, int maxdiff)
 {
     solver_ctx *sctx = new_solver(state);
     int ret, diff = DIFF_NORMAL;
@@ -2542,6 +2539,12 @@
 #endif
 
     return diff;
+}
+
+static int solver_state(game_state *state, int maxdiff)
+{
+    solver_recurse_depth = 0;
+    return solver_state_inner(state, maxdiff);
 }
 
 #ifndef EDITOR