From 5030d87903191d581586ecda2382ad5bcd70f63d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 5 Feb 2023 10:29:42 +0000 Subject: latin_solver_alloc: handle clashing numbers in input grid. In the setup phase of the centralised latin.c solver, we start by going over the input grid containing already-placed clue numbers, and calling latin_solver_place to enter each on into the solver's data structure. This has the side effect of ruling out each number from the rest of the row and column, and _also_ checking by assertion that the number being placed is not ruled out. Those are a bad combination, because it means that if you give an obviously inconsistent input grid to latin_solver_alloc (e.g. with two identical numbers in a row already), it will fail an assertion. In that situation, you want the solver run as a whole to return diff_impossible so that the error is reported cleanly. This assertion failure could be provoked by giving either Towers or Group a manually-constructed game description inconsistent in that way, and hitting Solve. Worse, it could be provoked during live play in Unequal, by filling in a number clashing with a clue and then pressing 'h' to get hints. --- unequal.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'unequal.c') diff --git a/unequal.c b/unequal.c index ed03c0b..f2328b6 100644 --- a/unequal.c +++ b/unequal.c @@ -890,13 +890,14 @@ static int solver_state(game_state *state, int maxdiff) struct latin_solver solver; int diff; - latin_solver_alloc(&solver, state->nums, state->order); - - diff = latin_solver_main(&solver, maxdiff, - DIFF_LATIN, DIFF_SET, DIFF_EXTREME, - DIFF_EXTREME, DIFF_RECURSIVE, - unequal_solvers, unequal_valid, ctx, - clone_ctx, free_ctx); + if (!latin_solver_alloc(&solver, state->nums, state->order)) + diff = latin_solver_main(&solver, maxdiff, + DIFF_LATIN, DIFF_SET, DIFF_EXTREME, + DIFF_EXTREME, DIFF_RECURSIVE, + unequal_solvers, unequal_valid, ctx, + clone_ctx, free_ctx); + else + diff = DIFF_IMPOSSIBLE; memcpy(state->hints, solver.cube, state->order*state->order*state->order); @@ -2256,13 +2257,14 @@ static int solve(game_params *p, char *desc, int debug) solver_show_working = debug; game_debug(state); - latin_solver_alloc(&solver, state->nums, state->order); - - diff = latin_solver_main(&solver, DIFF_RECURSIVE, - DIFF_LATIN, DIFF_SET, DIFF_EXTREME, - DIFF_EXTREME, DIFF_RECURSIVE, - unequal_solvers, unequal_valid, ctx, - clone_ctx, free_ctx); + if (latin_solver_alloc(&solver, state->nums, state->order)) + diff = latin_solver_main(&solver, DIFF_RECURSIVE, + DIFF_LATIN, DIFF_SET, DIFF_EXTREME, + DIFF_EXTREME, DIFF_RECURSIVE, + unequal_solvers, unequal_valid, ctx, + clone_ctx, free_ctx); + else + diff = DIFF_IMPOSSIBLE; free_ctx(ctx); -- cgit v1.1