+
+#ifdef STANDALONE_SOLVER
+
+#include <stdarg.h>
+
+/*
+ * gcc -DSTANDALONE_SOLVER -o slantsolver slant.c malloc.c
+ */
+
+void frontend_default_colour(frontend *fe, float *output) {}
+void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
+ int align, int colour, char *text) {}
+void draw_rect(drawing *dr, int x, int y, int w, int h, int colour) {}
+void draw_rect_outline(drawing *dr, int x, int y, int w, int h, int colour) {}
+void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour) {}
+void draw_polygon(drawing *dr, int *coords, int npoints,
+ int fillcolour, int outlinecolour) {}
+void draw_circle(drawing *dr, int cx, int cy, int radius,
+ int fillcolour, int outlinecolour) {}
+void clip(drawing *dr, int x, int y, int w, int h) {}
+void unclip(drawing *dr) {}
+void start_draw(drawing *dr) {}
+void draw_update(drawing *dr, int x, int y, int w, int h) {}
+void end_draw(drawing *dr) {}
+int print_mono_colour(drawing *dr, int grey) { return 0; }
+void print_line_width(drawing *dr, int width) {}
+unsigned long random_bits(random_state *state, int bits)
+{ assert(!"Shouldn't get randomness"); return 0; }
+unsigned long random_upto(random_state *state, unsigned long limit)
+{ assert(!"Shouldn't get randomness"); return 0; }
+void shuffle(void *array, int nelts, int eltsize, random_state *rs)
+{ assert(!"Shouldn't get randomness"); }
+
+void fatal(char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "fatal error: ");
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ game_params *p;
+ game_state *s;
+ char *id = NULL, *desc, *err;
+ int grade = FALSE;
+ int ret, diff, really_verbose = FALSE;
+ struct solver_scratch *sc;
+
+ while (--argc > 0) {
+ char *p = *++argv;
+ if (!strcmp(p, "-v")) {
+ really_verbose = TRUE;
+ } else 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] <game_id>\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);
+
+ sc = new_scratch(p->w, p->h);
+
+ /*
+ * 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 < DIFFCOUNT; diff++) {
+ ret = slant_solve(p->w, p->h, s->clues->clues,
+ s->soln, sc, diff);
+ if (ret < 2)
+ break;
+ }
+
+ if (diff == DIFFCOUNT) {
+ 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", slant_diffnames[diff]);
+ } else {
+ verbose = really_verbose;
+ ret = slant_solve(p->w, p->h, s->clues->clues,
+ s->soln, sc, diff);
+ if (ret == 0)
+ printf("Puzzle is inconsistent\n");
+ else
+ fputs(game_text_format(s), stdout);
+ }
+ }
+
+ return 0;
+}
+
+#endif