From 5ca896811985d588fbcb659bdac5d28e892b4b80 Mon Sep 17 00:00:00 2001 From: simon Date: Wed, 7 Jan 2009 21:55:21 +0000 Subject: [PATCH] Standalone solver for Loopy. Bit half-hearted, since the solver doesn't have diagnostics embedded and the ASCII formatter can't print non-square puzzles anyway; but it can grade difficulty, which is what I most immediately want it for. git-svn-id: svn://svn.tartarus.org/sgt/puzzles@8397 cda61777-01e9-0310-a592-d414129be87e --- loopy.R | 3 ++ loopy.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) diff --git a/loopy.R b/loopy.R index 507b60c..e77f9c7 100644 --- a/loopy.R +++ b/loopy.R @@ -6,6 +6,9 @@ loopy : [X] GTK COMMON loopy LOOPY_EXTRA loopy-icon|no-icon loopy : [G] WINDOWS COMMON loopy LOOPY_EXTRA loopy.res|noicon.res +loopysolver : [U] loopy[STANDALONE_SOLVER] LOOPY_EXTRA STANDALONE m.lib +loopysolver : [C] loopy[STANDALONE_SOLVER] LOOPY_EXTRA STANDALONE + ALL += loopy[COMBINED] LOOPY_EXTRA !begin gtk diff --git a/loopy.c b/loopy.c index 39dec98..d877149 100644 --- a/loopy.c +++ b/loopy.c @@ -3635,3 +3635,130 @@ const struct game thegame = { FALSE, game_timing_state, 0, /* mouse_priorities */ }; + +#ifdef STANDALONE_SOLVER + +/* + * Half-hearted standalone solver. It can't output the solution to + * anything but a square puzzle, and it can't log the deductions + * it makes either. But it can solve square puzzles, and more + * importantly it can use its solver to grade the difficulty of + * any puzzle you give it. + */ + +#include + +int main(int argc, char **argv) +{ + game_params *p; + game_state *s; + char *id = NULL, *desc, *err; + int grade = FALSE; + int ret, diff; +#if 0 /* verbose solver not supported here (yet) */ + int really_verbose = FALSE; +#endif + + while (--argc > 0) { + char *p = *++argv; +#if 0 /* verbose solver not supported here (yet) */ + if (!strcmp(p, "-v")) { + really_verbose = TRUE; + } else +#endif + if (!strcmp(p, "-g")) { + grade = TRUE; + } else if (*p == '-') { + fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p); + return 1; + } else { + id = p; + } + } + + if (!id) { + fprintf(stderr, "usage: %s [-g | -v] \n", argv[0]); + return 1; + } + + desc = strchr(id, ':'); + if (!desc) { + fprintf(stderr, "%s: game id expects a colon in it\n", argv[0]); + return 1; + } + *desc++ = '\0'; + + p = default_params(); + decode_params(p, id); + err = validate_desc(p, desc); + if (err) { + fprintf(stderr, "%s: %s\n", argv[0], err); + return 1; + } + s = new_game(NULL, p, desc); + + /* + * When solving an Easy puzzle, we don't want to bother the + * user with Hard-level deductions. For this reason, we grade + * the puzzle internally before doing anything else. + */ + ret = -1; /* placate optimiser */ + for (diff = 0; diff < DIFF_MAX; diff++) { + solver_state *sstate_new; + solver_state *sstate = new_solver_state((game_state *)s, diff); + + sstate_new = solve_game_rec(sstate, diff); + + if (sstate_new->solver_status == SOLVER_MISTAKE) + ret = 0; + else if (sstate_new->solver_status == SOLVER_SOLVED) + ret = 1; + else + ret = 2; + + free_solver_state(sstate_new); + free_solver_state(sstate); + + if (ret < 2) + break; + } + + if (diff == DIFF_MAX) { + if (grade) + printf("Difficulty rating: harder than Hard, or ambiguous\n"); + else + printf("Unable to find a unique solution\n"); + } else { + if (grade) { + if (ret == 0) + printf("Difficulty rating: impossible (no solution exists)\n"); + else if (ret == 1) + printf("Difficulty rating: %s\n", diffnames[diff]); + } else { + solver_state *sstate_new; + solver_state *sstate = new_solver_state((game_state *)s, diff); + + /* If we supported a verbose solver, we'd set verbosity here */ + + sstate_new = solve_game_rec(sstate, diff); + + if (sstate_new->solver_status == SOLVER_MISTAKE) + printf("Puzzle is inconsistent\n"); + else { + assert(sstate_new->solver_status == SOLVER_SOLVED); + if (s->grid_type == 0) { + fputs(game_text_format(sstate_new->state), stdout); + } else { + printf("Unable to output non-square grids\n"); + } + } + + free_solver_state(sstate_new); + free_solver_state(sstate); + } + } + + return 0; +} + +#endif -- 2.11.0