shithub: puzzles

Download patch

ref: 67496e74f68db900d8117be6de3c75285c29c489
parent: d3f825c98c2877ca3e2763492ba99973c1b9dc5f
author: Simon Tatham <anakin@pobox.com>
date: Sun Aug 27 09:22:45 EDT 2023

Singles: prevent hangs at low puzzle sizes.

A user reports that trying to generate a 2x2 or 3x3 puzzle at Tricky
difficulty causes the generator to hang, for the usual reason that
there aren't any - puzzles of that size are either ambiguous or Easy.

The usual response in this code base is to quietly downgrade the
puzzle difficulty when absolutely necessary, so here's some code to do
that (and also for 2x3, which the user didn't test, but unsurprisingly
behaves the same way).

--- a/singles.c
+++ b/singles.c
@@ -1308,9 +1308,10 @@
     return j;
 }
 
-static char *new_game_desc(const game_params *params, random_state *rs,
+static char *new_game_desc(const game_params *params_orig, random_state *rs,
 			   char **aux, bool interactive)
 {
+    game_params *params = dup_params(params_orig);
     game_state *state = blank_game(params->w, params->h);
     game_state *tosolve = blank_game(params->w, params->h);
     int i, j, *scratch, *rownums, *colnums, x, y, ntries;
@@ -1319,6 +1320,12 @@
     digit *latin;
     struct solver_state *ss = solver_state_new(state);
 
+    /* Downgrade difficulty to Easy for puzzles so tiny that they aren't
+     * possible to generate at Tricky. These are 2x2, 2x3 and 3x3, i.e.
+     * any puzzle that doesn't have one dimension at least 4. */
+    if ((w < 4 || h < 4) && params->diff > DIFF_EASY)
+        params->diff = DIFF_EASY;
+
     scratch = snewn(state->n, int);
     rownums = snewn(h*o, int);
     colnums = snewn(w*o, int);
@@ -1412,6 +1419,7 @@
 
     free_game(tosolve);
     free_game(state);
+    free_params(params);
     solver_state_free(ss);
     sfree(scratch);
     sfree(rownums);