ref: cb5e49ef1da51f6bd956739c9af5bdea3d99ee07
parent: 272beef5f98fecc59c975ea920c601836a6bb08c
author: Simon Tatham <anakin@pobox.com>
date: Thu Aug 24 15:38:29 EDT 2017
Net: fix assertion failure on insoluble puzzles. The solver code still had an assumption, which must have dated before the Solve menu option was introduced, that all puzzles presented to it had at least one valid solution, and was enforcing that assumption by assert(). Now the solver returns a more sensible failure code which solve_game() can convert into a proper error message.
--- a/net.c
+++ b/net.c
@@ -459,6 +459,11 @@
return ret;
}
+/*
+ * Return values: -1 means puzzle was proved inconsistent, 0 means we
+ * failed to narrow down to a unique solution, +1 means we solved it
+ * fully.
+ */
static int net_solver(int w, int h, unsigned char *tiles,
unsigned char *barriers, int wrapping)
{
@@ -733,7 +738,11 @@
#endif
}
- assert(j > 0); /* we can't lose _all_ possibilities! */
+ if (j == 0) {
+ /* If we've ruled out all possible orientations for a
+ * tile, then our puzzle has no solution at all. */
+ return -1;
+ }
if (j < i) {
done_something = TRUE;
@@ -813,7 +822,7 @@
/*
* Mark all completely determined tiles as locked.
*/
- j = TRUE;
+ j = +1;
for (i = 0; i < w*h; i++) {
if (tilestate[i * 4 + 1] == 255) {
assert(tilestate[i * 4 + 0] != 255);
@@ -820,7 +829,7 @@
tiles[i] = tilestate[i * 4] | LOCKED;
} else {
tiles[i] &= ~LOCKED;
- j = FALSE;
+ j = 0;
}
}
@@ -1334,7 +1343,7 @@
/*
* Run the solver to check unique solubility.
*/
- while (!net_solver(w, h, tiles, NULL, params->wrapping)) {
+ while (net_solver(w, h, tiles, NULL, params->wrapping) != 1) {
int n = 0;
/*
@@ -1758,9 +1767,17 @@
* Run the internal solver on the provided grid. This might
* not yield a complete solution.
*/
+ int solver_result;
+
memcpy(tiles, state->tiles, state->width * state->height);
- net_solver(state->width, state->height, tiles,
- state->barriers, state->wrapping);
+ solver_result = net_solver(state->width, state->height, tiles,
+ state->barriers, state->wrapping);
+
+ if (solver_result < 0) {
+ *error = "No solution exists for this puzzle";
+ sfree(tiles);
+ return NULL;
+ }
} else {
for (i = 0; i < state->width * state->height; i++) {
int c = aux[i];