chiark / gitweb /
Cleanup: the `mouse_priorities' field in the back end has been a
[sgt-puzzles.git] / slant.c
1 /*
2  * slant.c: Puzzle from nikoli.co.jp involving drawing a diagonal
3  * line through each square of a grid.
4  */
5
6 /*
7  * In this puzzle you have a grid of squares, each of which must
8  * contain a diagonal line; you also have clue numbers placed at
9  * _points_ of that grid, which means there's a (w+1) x (h+1) array
10  * of possible clue positions.
11  * 
12  * I'm therefore going to adopt a rigid convention throughout this
13  * source file of using w and h for the dimensions of the grid of
14  * squares, and W and H for the dimensions of the grid of points.
15  * Thus, W == w+1 and H == h+1 always.
16  * 
17  * Clue arrays will be W*H `signed char's, and the clue at each
18  * point will be a number from 0 to 4, or -1 if there's no clue.
19  * 
20  * Solution arrays will be W*H `signed char's, and the number at
21  * each point will be +1 for a forward slash (/), -1 for a
22  * backslash (\), and 0 for unknown.
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <ctype.h>
30 #include <math.h>
31
32 #include "puzzles.h"
33
34 enum {
35     COL_BACKGROUND,
36     COL_GRID,
37     COL_INK,
38     COL_SLANT1,
39     COL_SLANT2,
40     COL_ERROR,
41     NCOLOURS
42 };
43
44 /*
45  * In standalone solver mode, `verbose' is a variable which can be
46  * set by command-line option; in debugging mode it's simply always
47  * true.
48  */
49 #if defined STANDALONE_SOLVER
50 #define SOLVER_DIAGNOSTICS
51 int verbose = FALSE;
52 #elif defined SOLVER_DIAGNOSTICS
53 #define verbose TRUE
54 #endif
55
56 /*
57  * Difficulty levels. I do some macro ickery here to ensure that my
58  * enum and the various forms of my name list always match up.
59  */
60 #define DIFFLIST(A) \
61     A(EASY,Easy,e) \
62     A(HARD,Hard,h)
63 #define ENUM(upper,title,lower) DIFF_ ## upper,
64 #define TITLE(upper,title,lower) #title,
65 #define ENCODE(upper,title,lower) #lower
66 #define CONFIG(upper,title,lower) ":" #title
67 enum { DIFFLIST(ENUM) DIFFCOUNT };
68 static char const *const slant_diffnames[] = { DIFFLIST(TITLE) };
69 static char const slant_diffchars[] = DIFFLIST(ENCODE);
70 #define DIFFCONFIG DIFFLIST(CONFIG)
71
72 struct game_params {
73     int w, h, diff;
74 };
75
76 typedef struct game_clues {
77     int w, h;
78     signed char *clues;
79     int *tmpdsf;
80     int refcount;
81 } game_clues;
82
83 #define ERR_VERTEX 1
84 #define ERR_SQUARE 2
85 #define ERR_SQUARE_TMP 4
86
87 struct game_state {
88     struct game_params p;
89     game_clues *clues;
90     signed char *soln;
91     unsigned char *errors;
92     int completed;
93     int used_solve;                    /* used to suppress completion flash */
94 };
95
96 static game_params *default_params(void)
97 {
98     game_params *ret = snew(game_params);
99
100     ret->w = ret->h = 8;
101     ret->diff = DIFF_EASY;
102
103     return ret;
104 }
105
106 static const struct game_params slant_presets[] = {
107     {5, 5, DIFF_EASY},
108     {5, 5, DIFF_HARD},
109     {8, 8, DIFF_EASY},
110     {8, 8, DIFF_HARD},
111     {12, 10, DIFF_EASY},
112     {12, 10, DIFF_HARD},
113 };
114
115 static int game_fetch_preset(int i, char **name, game_params **params)
116 {
117     game_params *ret;
118     char str[80];
119
120     if (i < 0 || i >= lenof(slant_presets))
121         return FALSE;
122
123     ret = snew(game_params);
124     *ret = slant_presets[i];
125
126     sprintf(str, "%dx%d %s", ret->w, ret->h, slant_diffnames[ret->diff]);
127
128     *name = dupstr(str);
129     *params = ret;
130     return TRUE;
131 }
132
133 static void free_params(game_params *params)
134 {
135     sfree(params);
136 }
137
138 static game_params *dup_params(game_params *params)
139 {
140     game_params *ret = snew(game_params);
141     *ret = *params;                    /* structure copy */
142     return ret;
143 }
144
145 static void decode_params(game_params *ret, char const *string)
146 {
147     ret->w = ret->h = atoi(string);
148     while (*string && isdigit((unsigned char)*string)) string++;
149     if (*string == 'x') {
150         string++;
151         ret->h = atoi(string);
152         while (*string && isdigit((unsigned char)*string)) string++;
153     }
154     if (*string == 'd') {
155         int i;
156         string++;
157         for (i = 0; i < DIFFCOUNT; i++)
158             if (*string == slant_diffchars[i])
159                 ret->diff = i;
160         if (*string) string++;
161     }
162 }
163
164 static char *encode_params(game_params *params, int full)
165 {
166     char data[256];
167
168     sprintf(data, "%dx%d", params->w, params->h);
169     if (full)
170         sprintf(data + strlen(data), "d%c", slant_diffchars[params->diff]);
171
172     return dupstr(data);
173 }
174
175 static config_item *game_configure(game_params *params)
176 {
177     config_item *ret;
178     char buf[80];
179
180     ret = snewn(4, config_item);
181
182     ret[0].name = "Width";
183     ret[0].type = C_STRING;
184     sprintf(buf, "%d", params->w);
185     ret[0].sval = dupstr(buf);
186     ret[0].ival = 0;
187
188     ret[1].name = "Height";
189     ret[1].type = C_STRING;
190     sprintf(buf, "%d", params->h);
191     ret[1].sval = dupstr(buf);
192     ret[1].ival = 0;
193
194     ret[2].name = "Difficulty";
195     ret[2].type = C_CHOICES;
196     ret[2].sval = DIFFCONFIG;
197     ret[2].ival = params->diff;
198
199     ret[3].name = NULL;
200     ret[3].type = C_END;
201     ret[3].sval = NULL;
202     ret[3].ival = 0;
203
204     return ret;
205 }
206
207 static game_params *custom_params(config_item *cfg)
208 {
209     game_params *ret = snew(game_params);
210
211     ret->w = atoi(cfg[0].sval);
212     ret->h = atoi(cfg[1].sval);
213     ret->diff = cfg[2].ival;
214
215     return ret;
216 }
217
218 static char *validate_params(game_params *params, int full)
219 {
220     /*
221      * (At least at the time of writing this comment) The grid
222      * generator is actually capable of handling even zero grid
223      * dimensions without crashing. Puzzles with a zero-area grid
224      * are a bit boring, though, because they're already solved :-)
225      * And puzzles with a dimension of 1 can't be made Hard, which
226      * means the simplest thing is to forbid them altogether.
227      */
228
229     if (params->w < 2 || params->h < 2)
230         return "Width and height must both be at least two";
231
232     return NULL;
233 }
234
235 /*
236  * Scratch space for solver.
237  */
238 struct solver_scratch {
239     /*
240      * Disjoint set forest which tracks the connected sets of
241      * points.
242      */
243     int *connected;
244
245     /*
246      * Counts the number of possible exits from each connected set
247      * of points. (That is, the number of possible _simultaneous_
248      * exits: an unconnected point labelled 2 has an exit count of
249      * 2 even if all four possible edges are still under
250      * consideration.)
251      */
252     int *exits;
253
254     /*
255      * Tracks whether each connected set of points includes a
256      * border point.
257      */
258     unsigned char *border;
259
260     /*
261      * Another disjoint set forest. This one tracks _squares_ which
262      * are known to slant in the same direction.
263      */
264     int *equiv;
265
266     /*
267      * Stores slash values which we know for an equivalence class.
268      * When we fill in a square, we set slashval[canonify(x)] to
269      * the same value as soln[x], so that we can then spot other
270      * squares equivalent to it and fill them in immediately via
271      * their known equivalence.
272      */
273     signed char *slashval;
274
275     /*
276      * Useful to have this information automatically passed to
277      * solver subroutines. (This pointer is not dynamically
278      * allocated by new_scratch and free_scratch.)
279      */
280     const signed char *clues;
281 };
282
283 static struct solver_scratch *new_scratch(int w, int h)
284 {
285     int W = w+1, H = h+1;
286     struct solver_scratch *ret = snew(struct solver_scratch);
287     ret->connected = snewn(W*H, int);
288     ret->exits = snewn(W*H, int);
289     ret->border = snewn(W*H, unsigned char);
290     ret->equiv = snewn(w*h, int);
291     ret->slashval = snewn(w*h, signed char);
292     return ret;
293 }
294
295 static void free_scratch(struct solver_scratch *sc)
296 {
297     sfree(sc->slashval);
298     sfree(sc->equiv);
299     sfree(sc->border);
300     sfree(sc->exits);
301     sfree(sc->connected);
302     sfree(sc);
303 }
304
305 /*
306  * Wrapper on dsf_merge() which updates the `exits' and `border'
307  * arrays.
308  */
309 static void merge_vertices(int *connected,
310                            struct solver_scratch *sc, int i, int j)
311 {
312     int exits = -1, border = FALSE;    /* initialise to placate optimiser */
313
314     if (sc) {
315         i = dsf_canonify(connected, i);
316         j = dsf_canonify(connected, j);
317
318         /*
319          * We have used one possible exit from each of the two
320          * classes. Thus, the viable exit count of the new class is
321          * the sum of the old exit counts minus two.
322          */
323         exits = sc->exits[i] + sc->exits[j] - 2;
324
325         border = sc->border[i] || sc->border[j];
326     }
327
328     dsf_merge(connected, i, j);
329
330     if (sc) {
331         i = dsf_canonify(connected, i);
332         sc->exits[i] = exits;
333         sc->border[i] = border;
334     }
335 }
336
337 /*
338  * Called when we have just blocked one way out of a particular
339  * point. If that point is a non-clue point (thus has a variable
340  * number of exits), we have therefore decreased its potential exit
341  * count, so we must decrement the exit count for the group as a
342  * whole.
343  */
344 static void decr_exits(struct solver_scratch *sc, int i)
345 {
346     if (sc->clues[i] < 0) {
347         i = dsf_canonify(sc->connected, i);
348         sc->exits[i]--;
349     }
350 }
351
352 static void fill_square(int w, int h, int x, int y, int v,
353                         signed char *soln,
354                         int *connected, struct solver_scratch *sc)
355 {
356     int W = w+1 /*, H = h+1 */;
357
358     assert(x >= 0 && x < w && y >= 0 && y < h);
359
360     if (soln[y*w+x] != 0) {
361         return;                        /* do nothing */
362     }
363
364 #ifdef SOLVER_DIAGNOSTICS
365     if (verbose)
366         printf("  placing %c in %d,%d\n", v == -1 ? '\\' : '/', x, y);
367 #endif
368
369     soln[y*w+x] = v;
370
371     if (sc) {
372         int c = dsf_canonify(sc->equiv, y*w+x);
373         sc->slashval[c] = v;
374     }
375
376     if (v < 0) {
377         merge_vertices(connected, sc, y*W+x, (y+1)*W+(x+1));
378         if (sc) {
379             decr_exits(sc, y*W+(x+1));
380             decr_exits(sc, (y+1)*W+x);
381         }
382     } else {
383         merge_vertices(connected, sc, y*W+(x+1), (y+1)*W+x);
384         if (sc) {
385             decr_exits(sc, y*W+x);
386             decr_exits(sc, (y+1)*W+(x+1));
387         }
388     }
389 }
390
391 /*
392  * Solver. Returns 0 for impossibility, 1 for success, 2 for
393  * ambiguity or failure to converge.
394  */
395 static int slant_solve(int w, int h, const signed char *clues,
396                        signed char *soln, struct solver_scratch *sc,
397                        int difficulty)
398 {
399     int W = w+1, H = h+1;
400     int x, y, i, j;
401     int done_something;
402
403     /*
404      * Clear the output.
405      */
406     memset(soln, 0, w*h);
407
408     sc->clues = clues;
409
410     /*
411      * Establish a disjoint set forest for tracking connectedness
412      * between grid points.
413      */
414     for (i = 0; i < W*H; i++)
415         sc->connected[i] = i;          /* initially all distinct */
416
417     /*
418      * Establish a disjoint set forest for tracking which squares
419      * are known to slant in the same direction.
420      */
421     for (i = 0; i < w*h; i++)
422         sc->equiv[i] = i;              /* initially all distinct */
423
424     /*
425      * Clear the slashval array.
426      */
427     memset(sc->slashval, 0, w*h);
428
429     /*
430      * Initialise the `exits' and `border' arrays. Theses is used
431      * to do second-order loop avoidance: the dual of the no loops
432      * constraint is that every point must be somehow connected to
433      * the border of the grid (otherwise there would be a solid
434      * loop around it which prevented this).
435      * 
436      * I define a `dead end' to be a connected group of points
437      * which contains no border point, and which can form at most
438      * one new connection outside itself. Then I forbid placing an
439      * edge so that it connects together two dead-end groups, since
440      * this would yield a non-border-connected isolated subgraph
441      * with no further scope to extend it.
442      */
443     for (y = 0; y < H; y++)
444         for (x = 0; x < W; x++) {
445             if (y == 0 || y == H-1 || x == 0 || x == W-1)
446                 sc->border[y*W+x] = TRUE;
447             else
448                 sc->border[y*W+x] = FALSE;
449
450             if (clues[y*W+x] < 0)
451                 sc->exits[y*W+x] = 4;
452             else
453                 sc->exits[y*W+x] = clues[y*W+x];
454         }
455
456     /*
457      * Make a one-off preliminary pass over the grid looking for
458      * starting-point arrangements. The ones we need to spot are:
459      * 
460      *  - two adjacent 1s in the centre of the grid imply that each
461      *    one's single line points towards the other. (If either 1
462      *    were connected on the far side, the two squares shared
463      *    between the 1s would both link to the other 1 as a
464      *    consequence of neither linking to the first.) Thus, we
465      *    can fill in the four squares around them.
466      * 
467      *  - dually, two adjacent 3s imply that each one's _non_-line
468      *    points towards the other.
469      * 
470      *  - if the pair of 1s and 3s is not _adjacent_ but is
471      *    separated by one or more 2s, the reasoning still applies.
472      * 
473      * This is more advanced than just spotting obvious starting
474      * squares such as central 4s and edge 2s, so we disable it on
475      * DIFF_EASY.
476      * 
477      * (I don't like this loop; it feels grubby to me. My
478      * mathematical intuition feels there ought to be some more
479      * general deductive form which contains this loop as a special
480      * case, but I can't bring it to mind right now.)
481      */
482     if (difficulty > DIFF_EASY) {
483         for (y = 1; y+1 < H; y++)
484             for (x = 1; x+1 < W; x++) {
485                 int v = clues[y*W+x], s, x2, y2, dx, dy;
486                 if (v != 1 && v != 3)
487                     continue;
488                 /* Slash value of the square up and left of (x,y). */
489                 s = (v == 1 ? +1 : -1);
490
491                 /* Look in each direction once. */
492                 for (dy = 0; dy < 2; dy++) {
493                     dx = 1 - dy;
494                     x2 = x+dx;
495                     y2 = y+dy;
496                     if (x2+1 >= W || y2+1 >= H)
497                         continue;              /* too close to the border */
498                     while (x2+dx+1 < W && y2+dy+1 < H && clues[y2*W+x2] == 2)
499                         x2 += dx, y2 += dy;
500                     if (clues[y2*W+x2] == v) {
501 #ifdef SOLVER_DIAGNOSTICS
502                         if (verbose)
503                             printf("found adjacent %ds at %d,%d and %d,%d\n",
504                                    v, x, y, x2, y2);
505 #endif
506                         fill_square(w, h, x-1, y-1, s, soln,
507                                     sc->connected, sc);
508                         fill_square(w, h, x-1+dy, y-1+dx, -s, soln,
509                                     sc->connected, sc);
510                         fill_square(w, h, x2, y2, s, soln,
511                                     sc->connected, sc);
512                         fill_square(w, h, x2-dy, y2-dx, -s, soln,
513                                     sc->connected, sc);
514                     }
515                 }
516             }
517     }
518
519     /*
520      * Repeatedly try to deduce something until we can't.
521      */
522     do {
523         done_something = FALSE;
524
525         /*
526          * Any clue point with the number of remaining lines equal
527          * to zero or to the number of remaining undecided
528          * neighbouring squares can be filled in completely.
529          */
530         for (y = 0; y < H; y++)
531             for (x = 0; x < W; x++) {
532                 struct {
533                     int pos, slash;
534                 } neighbours[4];
535                 int nneighbours;
536                 int nu, nl, c, s, eq, eq2, last, meq, mj1, mj2;
537
538                 if ((c = clues[y*W+x]) < 0)
539                     continue;
540
541                 /*
542                  * We have a clue point. Start by listing its
543                  * neighbouring squares, in order around the point,
544                  * together with the type of slash that would be
545                  * required in that square to connect to the point.
546                  */
547                 nneighbours = 0;
548                 if (x > 0 && y > 0) {
549                     neighbours[nneighbours].pos = (y-1)*w+(x-1);
550                     neighbours[nneighbours].slash = -1;
551                     nneighbours++;
552                 }
553                 if (x > 0 && y < h) {
554                     neighbours[nneighbours].pos = y*w+(x-1);
555                     neighbours[nneighbours].slash = +1;
556                     nneighbours++;
557                 }
558                 if (x < w && y < h) {
559                     neighbours[nneighbours].pos = y*w+x;
560                     neighbours[nneighbours].slash = -1;
561                     nneighbours++;
562                 }
563                 if (x < w && y > 0) {
564                     neighbours[nneighbours].pos = (y-1)*w+x;
565                     neighbours[nneighbours].slash = +1;
566                     nneighbours++;
567                 }
568
569                 /*
570                  * Count up the number of undecided neighbours, and
571                  * also the number of lines already present.
572                  *
573                  * If we're not on DIFF_EASY, then in this loop we
574                  * also track whether we've seen two adjacent empty
575                  * squares belonging to the same equivalence class
576                  * (meaning they have the same type of slash). If
577                  * so, we count them jointly as one line.
578                  */
579                 nu = 0;
580                 nl = c;
581                 last = neighbours[nneighbours-1].pos;
582                 if (soln[last] == 0)
583                     eq = dsf_canonify(sc->equiv, last);
584                 else
585                     eq = -1;
586                 meq = mj1 = mj2 = -1;
587                 for (i = 0; i < nneighbours; i++) {
588                     j = neighbours[i].pos;
589                     s = neighbours[i].slash;
590                     if (soln[j] == 0) {
591                         nu++;          /* undecided */
592                         if (meq < 0 && difficulty > DIFF_EASY) {
593                             eq2 = dsf_canonify(sc->equiv, j);
594                             if (eq == eq2 && last != j) {
595                                 /*
596                                  * We've found an equivalent pair.
597                                  * Mark it. This also inhibits any
598                                  * further equivalence tracking
599                                  * around this square, since we can
600                                  * only handle one pair (and in
601                                  * particular we want to avoid
602                                  * being misled by two overlapping
603                                  * equivalence pairs).
604                                  */
605                                 meq = eq;
606                                 mj1 = last;
607                                 mj2 = j;
608                                 nl--;   /* count one line */
609                                 nu -= 2;   /* and lose two undecideds */
610                             } else
611                                 eq = eq2;
612                         }
613                     } else {
614                         eq = -1;
615                         if (soln[j] == s)
616                             nl--;      /* here's a line */
617                     }
618                     last = j;
619                 }
620
621                 /*
622                  * Check the counts.
623                  */
624                 if (nl < 0 || nl > nu) {
625                     /*
626                      * No consistent value for this at all!
627                      */
628 #ifdef SOLVER_DIAGNOSTICS
629                     if (verbose)
630                         printf("need %d / %d lines around clue point at %d,%d!\n",
631                                nl, nu, x, y);
632 #endif
633                     return 0;          /* impossible */
634                 }
635
636                 if (nu > 0 && (nl == 0 || nl == nu)) {
637 #ifdef SOLVER_DIAGNOSTICS
638                     if (verbose) {
639                         if (meq >= 0)
640                             printf("partially (since %d,%d == %d,%d) ",
641                                    mj1%w, mj1/w, mj2%w, mj2/w);
642                         printf("%s around clue point at %d,%d\n",
643                                nl ? "filling" : "emptying", x, y);
644                     }
645 #endif
646                     for (i = 0; i < nneighbours; i++) {
647                         j = neighbours[i].pos;
648                         s = neighbours[i].slash;
649                         if (soln[j] == 0 && j != mj1 && j != mj2)
650                             fill_square(w, h, j%w, j/w, (nl ? s : -s), soln,
651                                         sc->connected, sc);
652                     }
653
654                     done_something = TRUE;
655                 } else if (nu == 2 && nl == 1 && difficulty > DIFF_EASY) {
656                     /*
657                      * If we have precisely two undecided squares
658                      * and precisely one line to place between
659                      * them, _and_ those squares are adjacent, then
660                      * we can mark them as equivalent to one
661                      * another.
662                      * 
663                      * This even applies if meq >= 0: if we have a
664                      * 2 clue point and two of its neighbours are
665                      * already marked equivalent, we can indeed
666                      * mark the other two as equivalent.
667                      * 
668                      * We don't bother with this on DIFF_EASY,
669                      * since we wouldn't have used the results
670                      * anyway.
671                      */
672                     last = -1;
673                     for (i = 0; i < nneighbours; i++) {
674                         j = neighbours[i].pos;
675                         if (soln[j] == 0 && j != mj1 && j != mj2) {
676                             if (last < 0)
677                                 last = i;
678                             else if (last == i-1 || (last == 0 && i == 3))
679                                 break; /* found a pair */
680                         }
681                     }
682                     if (i < nneighbours) {
683                         int sv1, sv2;
684
685                         assert(last >= 0);
686                         /*
687                          * neighbours[last] and neighbours[i] are
688                          * the pair. Mark them equivalent.
689                          */
690 #ifdef SOLVER_DIAGNOSTICS
691                         if (verbose) {
692                             if (meq >= 0)
693                                 printf("since %d,%d == %d,%d, ",
694                                        mj1%w, mj1/w, mj2%w, mj2/w);
695                         }
696 #endif
697                         mj1 = neighbours[last].pos;
698                         mj2 = neighbours[i].pos;
699 #ifdef SOLVER_DIAGNOSTICS
700                         if (verbose)
701                             printf("clue point at %d,%d implies %d,%d == %d,"
702                                    "%d\n", x, y, mj1%w, mj1/w, mj2%w, mj2/w);
703 #endif
704                         mj1 = dsf_canonify(sc->equiv, mj1);
705                         sv1 = sc->slashval[mj1];
706                         mj2 = dsf_canonify(sc->equiv, mj2);
707                         sv2 = sc->slashval[mj2];
708                         if (sv1 != 0 && sv2 != 0 && sv1 != sv2) {
709 #ifdef SOLVER_DIAGNOSTICS
710                             if (verbose)
711                                 printf("merged two equivalence classes with"
712                                        " different slash values!\n");
713 #endif
714                             return 0;
715                         }
716                         sv1 = sv1 ? sv1 : sv2;
717                         dsf_merge(sc->equiv, mj1, mj2);
718                         mj1 = dsf_canonify(sc->equiv, mj1);
719                         sc->slashval[mj1] = sv1;
720                     }
721                 }
722             }
723
724         if (done_something)
725             continue;
726
727         /*
728          * Failing that, we now apply the second condition, which
729          * is that no square may be filled in such a way as to form
730          * a loop. Also in this loop (since it's over squares
731          * rather than points), we check slashval to see if we've
732          * already filled in another square in the same equivalence
733          * class.
734          * 
735          * The slashval check is disabled on DIFF_EASY, as is dead
736          * end avoidance. Only _immediate_ loop avoidance remains.
737          */
738         for (y = 0; y < h; y++)
739             for (x = 0; x < w; x++) {
740                 int fs, bs, v;
741                 int c1, c2;
742 #ifdef SOLVER_DIAGNOSTICS
743                 char *reason = "<internal error>";
744 #endif
745
746                 if (soln[y*w+x])
747                     continue;          /* got this one already */
748
749                 fs = FALSE;
750                 bs = FALSE;
751
752                 if (difficulty > DIFF_EASY)
753                     v = sc->slashval[dsf_canonify(sc->equiv, y*w+x)];
754                 else
755                     v = 0;
756
757                 /*
758                  * Try to rule out connectivity between (x,y) and
759                  * (x+1,y+1); if successful, we will deduce that we
760                  * must have a forward slash.
761                  */
762                 c1 = dsf_canonify(sc->connected, y*W+x);
763                 c2 = dsf_canonify(sc->connected, (y+1)*W+(x+1));
764                 if (c1 == c2) {
765                     fs = TRUE;
766 #ifdef SOLVER_DIAGNOSTICS
767                     reason = "simple loop avoidance";
768 #endif
769                 }
770                 if (difficulty > DIFF_EASY &&
771                     !sc->border[c1] && !sc->border[c2] &&
772                     sc->exits[c1] <= 1 && sc->exits[c2] <= 1) {
773                     fs = TRUE;
774 #ifdef SOLVER_DIAGNOSTICS
775                     reason = "dead end avoidance";
776 #endif
777                 }
778                 if (v == +1) {
779                     fs = TRUE;
780 #ifdef SOLVER_DIAGNOSTICS
781                     reason = "equivalence to an already filled square";
782 #endif
783                 }
784
785                 /*
786                  * Now do the same between (x+1,y) and (x,y+1), to
787                  * see if we are required to have a backslash.
788                  */
789                 c1 = dsf_canonify(sc->connected, y*W+(x+1));
790                 c2 = dsf_canonify(sc->connected, (y+1)*W+x);
791                 if (c1 == c2) {
792                     bs = TRUE;
793 #ifdef SOLVER_DIAGNOSTICS
794                     reason = "simple loop avoidance";
795 #endif
796                 }
797                 if (difficulty > DIFF_EASY &&
798                     !sc->border[c1] && !sc->border[c2] &&
799                     sc->exits[c1] <= 1 && sc->exits[c2] <= 1) {
800                     bs = TRUE;
801 #ifdef SOLVER_DIAGNOSTICS
802                     reason = "dead end avoidance";
803 #endif
804                 }
805                 if (v == -1) {
806                     bs = TRUE;
807 #ifdef SOLVER_DIAGNOSTICS
808                     reason = "equivalence to an already filled square";
809 #endif
810                 }
811
812                 if (fs && bs) {
813                     /*
814                      * No consistent value for this at all!
815                      */
816 #ifdef SOLVER_DIAGNOSTICS
817                     if (verbose)
818                         printf("%d,%d has no consistent slash!\n", x, y);
819 #endif
820                     return 0;          /* impossible */
821                 }
822
823                 if (fs) {
824 #ifdef SOLVER_DIAGNOSTICS
825                     if (verbose)
826                         printf("employing %s\n", reason);
827 #endif
828                     fill_square(w, h, x, y, +1, soln, sc->connected, sc);
829                     done_something = TRUE;
830                 } else if (bs) {
831 #ifdef SOLVER_DIAGNOSTICS
832                     if (verbose)
833                         printf("employing %s\n", reason);
834 #endif
835                     fill_square(w, h, x, y, -1, soln, sc->connected, sc);
836                     done_something = TRUE;
837                 }
838             }
839
840     } while (done_something);
841
842     /*
843      * Solver can make no more progress. See if the grid is full.
844      */
845     for (i = 0; i < w*h; i++)
846         if (!soln[i])
847             return 2;                  /* failed to converge */
848     return 1;                          /* success */
849 }
850
851 /*
852  * Filled-grid generator.
853  */
854 static void slant_generate(int w, int h, signed char *soln, random_state *rs)
855 {
856     int W = w+1, H = h+1;
857     int x, y, i;
858     int *connected, *indices;
859
860     /*
861      * Clear the output.
862      */
863     memset(soln, 0, w*h);
864
865     /*
866      * Establish a disjoint set forest for tracking connectedness
867      * between grid points.
868      */
869     connected = snewn(W*H, int);
870     for (i = 0; i < W*H; i++)
871         connected[i] = i;                      /* initially all distinct */
872
873     /*
874      * Prepare a list of the squares in the grid, and fill them in
875      * in a random order.
876      */
877     indices = snewn(w*h, int);
878     for (i = 0; i < w*h; i++)
879         indices[i] = i;
880     shuffle(indices, w*h, sizeof(*indices), rs);
881
882     /*
883      * Fill in each one in turn.
884      */
885     for (i = 0; i < w*h; i++) {
886         int fs, bs, v;
887
888         y = indices[i] / w;
889         x = indices[i] % w;
890
891         fs = (dsf_canonify(connected, y*W+x) ==
892               dsf_canonify(connected, (y+1)*W+(x+1)));
893         bs = (dsf_canonify(connected, (y+1)*W+x) ==
894               dsf_canonify(connected, y*W+(x+1)));
895
896         /*
897          * It isn't possible to get into a situation where we
898          * aren't allowed to place _either_ type of slash in a
899          * square. Thus, filled-grid generation never has to
900          * backtrack.
901          * 
902          * Proof (thanks to Gareth Taylor):
903          * 
904          * If it were possible, it would have to be because there
905          * was an existing path (not using this square) between the
906          * top-left and bottom-right corners of this square, and
907          * another between the other two. These two paths would
908          * have to cross at some point.
909          * 
910          * Obviously they can't cross in the middle of a square, so
911          * they must cross by sharing a point in common. But this
912          * isn't possible either: if you chessboard-colour all the
913          * points on the grid, you find that any continuous
914          * diagonal path is entirely composed of points of the same
915          * colour. And one of our two hypothetical paths is between
916          * two black points, and the other is between two white
917          * points - therefore they can have no point in common. []
918          */
919         assert(!(fs && bs));
920
921         v = fs ? +1 : bs ? -1 : 2 * random_upto(rs, 2) - 1;
922         fill_square(w, h, x, y, v, soln, connected, NULL);
923     }
924
925     sfree(indices);
926     sfree(connected);
927 }
928
929 static char *new_game_desc(game_params *params, random_state *rs,
930                            char **aux, int interactive)
931 {
932     int w = params->w, h = params->h, W = w+1, H = h+1;
933     signed char *soln, *tmpsoln, *clues;
934     int *clueindices;
935     struct solver_scratch *sc;
936     int x, y, v, i, j;
937     char *desc;
938
939     soln = snewn(w*h, signed char);
940     tmpsoln = snewn(w*h, signed char);
941     clues = snewn(W*H, signed char);
942     clueindices = snewn(W*H, int);
943     sc = new_scratch(w, h);
944
945     do {
946         /*
947          * Create the filled grid.
948          */
949         slant_generate(w, h, soln, rs);
950
951         /*
952          * Fill in the complete set of clues.
953          */
954         for (y = 0; y < H; y++)
955             for (x = 0; x < W; x++) {
956                 v = 0;
957
958                 if (x > 0 && y > 0 && soln[(y-1)*w+(x-1)] == -1) v++;
959                 if (x > 0 && y < h && soln[y*w+(x-1)] == +1) v++;
960                 if (x < w && y > 0 && soln[(y-1)*w+x] == +1) v++;
961                 if (x < w && y < h && soln[y*w+x] == -1) v++;
962
963                 clues[y*W+x] = v;
964             }
965
966         /*
967          * With all clue points filled in, all puzzles are easy: we can
968          * simply process the clue points in lexicographic order, and
969          * at each clue point we will always have at most one square
970          * undecided, which we can then fill in uniquely.
971          */
972         assert(slant_solve(w, h, clues, tmpsoln, sc, DIFF_EASY) == 1);
973
974         /*
975          * Remove as many clues as possible while retaining solubility.
976          *
977          * In DIFF_HARD mode, we prioritise the removal of obvious
978          * starting points (4s, 0s, border 2s and corner 1s), on
979          * the grounds that having as few of these as possible
980          * seems like a good thing. In particular, we can often get
981          * away without _any_ completely obvious starting points,
982          * which is even better.
983          */
984         for (i = 0; i < W*H; i++)
985             clueindices[i] = i;
986         shuffle(clueindices, W*H, sizeof(*clueindices), rs);
987         for (j = 0; j < 2; j++) {
988             for (i = 0; i < W*H; i++) {
989                 int pass, yb, xb;
990
991                 y = clueindices[i] / W;
992                 x = clueindices[i] % W;
993                 v = clues[y*W+x];
994
995                 /*
996                  * Identify which pass we should process this point
997                  * in. If it's an obvious start point, _or_ we're
998                  * in DIFF_EASY, then it goes in pass 0; otherwise
999                  * pass 1.
1000                  */
1001                 xb = (x == 0 || x == W-1);
1002                 yb = (y == 0 || y == H-1);
1003                 if (params->diff == DIFF_EASY || v == 4 || v == 0 ||
1004                     (v == 2 && (xb||yb)) || (v == 1 && xb && yb))
1005                     pass = 0;
1006                 else
1007                     pass = 1;
1008
1009                 if (pass == j) {
1010                     clues[y*W+x] = -1;
1011                     if (slant_solve(w, h, clues, tmpsoln, sc,
1012                                     params->diff) != 1)
1013                         clues[y*W+x] = v;              /* put it back */
1014                 }
1015             }
1016         }
1017
1018         /*
1019          * And finally, verify that the grid is of _at least_ the
1020          * requested difficulty, by running the solver one level
1021          * down and verifying that it can't manage it.
1022          */
1023     } while (params->diff > 0 &&
1024              slant_solve(w, h, clues, tmpsoln, sc, params->diff - 1) <= 1);
1025
1026     /*
1027      * Now we have the clue set as it will be presented to the
1028      * user. Encode it in a game desc.
1029      */
1030     {
1031         char *p;
1032         int run, i;
1033
1034         desc = snewn(W*H+1, char);
1035         p = desc;
1036         run = 0;
1037         for (i = 0; i <= W*H; i++) {
1038             int n = (i < W*H ? clues[i] : -2);
1039
1040             if (n == -1)
1041                 run++;
1042             else {
1043                 if (run) {
1044                     while (run > 0) {
1045                         int c = 'a' - 1 + run;
1046                         if (run > 26)
1047                             c = 'z';
1048                         *p++ = c;
1049                         run -= c - ('a' - 1);
1050                     }
1051                 }
1052                 if (n >= 0)
1053                     *p++ = '0' + n;
1054                 run = 0;
1055             }
1056         }
1057         assert(p - desc <= W*H);
1058         *p++ = '\0';
1059         desc = sresize(desc, p - desc, char);
1060     }
1061
1062     /*
1063      * Encode the solution as an aux_info.
1064      */
1065     {
1066         char *auxbuf;
1067         *aux = auxbuf = snewn(w*h+1, char);
1068         for (i = 0; i < w*h; i++)
1069             auxbuf[i] = soln[i] < 0 ? '\\' : '/';
1070         auxbuf[w*h] = '\0';
1071     }
1072
1073     free_scratch(sc);
1074     sfree(clueindices);
1075     sfree(clues);
1076     sfree(tmpsoln);
1077     sfree(soln);
1078
1079     return desc;
1080 }
1081
1082 static char *validate_desc(game_params *params, char *desc)
1083 {
1084     int w = params->w, h = params->h, W = w+1, H = h+1;
1085     int area = W*H;
1086     int squares = 0;
1087
1088     while (*desc) {
1089         int n = *desc++;
1090         if (n >= 'a' && n <= 'z') {
1091             squares += n - 'a' + 1;
1092         } else if (n >= '0' && n <= '4') {
1093             squares++;
1094         } else
1095             return "Invalid character in game description";
1096     }
1097
1098     if (squares < area)
1099         return "Not enough data to fill grid";
1100
1101     if (squares > area)
1102         return "Too much data to fit in grid";
1103
1104     return NULL;
1105 }
1106
1107 static game_state *new_game(midend *me, game_params *params, char *desc)
1108 {
1109     int w = params->w, h = params->h, W = w+1, H = h+1;
1110     game_state *state = snew(game_state);
1111     int area = W*H;
1112     int squares = 0;
1113
1114     state->p = *params;
1115     state->soln = snewn(w*h, signed char);
1116     memset(state->soln, 0, w*h);
1117     state->completed = state->used_solve = FALSE;
1118     state->errors = snewn(W*H, unsigned char);
1119     memset(state->errors, 0, W*H);
1120
1121     state->clues = snew(game_clues);
1122     state->clues->w = w;
1123     state->clues->h = h;
1124     state->clues->clues = snewn(W*H, signed char);
1125     state->clues->refcount = 1;
1126     state->clues->tmpdsf = snewn(W*H, int);
1127     memset(state->clues->clues, -1, W*H);
1128     while (*desc) {
1129         int n = *desc++;
1130         if (n >= 'a' && n <= 'z') {
1131             squares += n - 'a' + 1;
1132         } else if (n >= '0' && n <= '4') {
1133             state->clues->clues[squares++] = n - '0';
1134         } else
1135             assert(!"can't get here");
1136     }
1137     assert(squares == area);
1138
1139     return state;
1140 }
1141
1142 static game_state *dup_game(game_state *state)
1143 {
1144     int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
1145     game_state *ret = snew(game_state);
1146
1147     ret->p = state->p;
1148     ret->clues = state->clues;
1149     ret->clues->refcount++;
1150     ret->completed = state->completed;
1151     ret->used_solve = state->used_solve;
1152
1153     ret->soln = snewn(w*h, signed char);
1154     memcpy(ret->soln, state->soln, w*h);
1155
1156     ret->errors = snewn(W*H, unsigned char);
1157     memcpy(ret->errors, state->errors, W*H);
1158
1159     return ret;
1160 }
1161
1162 static void free_game(game_state *state)
1163 {
1164     sfree(state->errors);
1165     sfree(state->soln);
1166     assert(state->clues);
1167     if (--state->clues->refcount <= 0) {
1168         sfree(state->clues->clues);
1169         sfree(state->clues->tmpdsf);
1170         sfree(state->clues);
1171     }
1172     sfree(state);
1173 }
1174
1175 /*
1176  * Utility function to return the current degree of a vertex. If
1177  * `anti' is set, it returns the number of filled-in edges
1178  * surrounding the point which _don't_ connect to it; thus 4 minus
1179  * its anti-degree is the maximum degree it could have if all the
1180  * empty spaces around it were filled in.
1181  * 
1182  * (Yes, _4_ minus its anti-degree even if it's a border vertex.)
1183  * 
1184  * If ret > 0, *sx and *sy are set to the coordinates of one of the
1185  * squares that contributed to it.
1186  */
1187 static int vertex_degree(int w, int h, signed char *soln, int x, int y,
1188                          int anti, int *sx, int *sy)
1189 {
1190     int ret = 0;
1191
1192     assert(x >= 0 && x <= w && y >= 0 && y <= h);
1193     if (x > 0 && y > 0 && soln[(y-1)*w+(x-1)] - anti < 0) {
1194         if (sx) *sx = x-1;
1195         if (sy) *sy = y-1;
1196         ret++;
1197     }
1198     if (x > 0 && y < h && soln[y*w+(x-1)] + anti > 0) {
1199         if (sx) *sx = x-1;
1200         if (sy) *sy = y;
1201         ret++;
1202     }
1203     if (x < w && y > 0 && soln[(y-1)*w+x] + anti > 0) {
1204         if (sx) *sx = x;
1205         if (sy) *sy = y-1;
1206         ret++;
1207     }
1208     if (x < w && y < h && soln[y*w+x] - anti < 0) {
1209         if (sx) *sx = x;
1210         if (sy) *sy = y;
1211         ret++;
1212     }
1213
1214     return anti ? 4 - ret : ret;
1215 }
1216
1217 static int check_completion(game_state *state)
1218 {
1219     int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
1220     int i, x, y, err = FALSE;
1221     int *dsf;
1222
1223     memset(state->errors, 0, W*H);
1224
1225     /*
1226      * To detect loops in the grid, we iterate through each edge
1227      * building up a dsf of connected components, and raise the
1228      * alarm whenever we find an edge that connects two
1229      * already-connected vertices.
1230      * 
1231      * We use the `tmpdsf' scratch space in the shared clues
1232      * structure, to avoid mallocing too often.
1233      * 
1234      * When we find such an edge, we then search around the grid to
1235      * find the loop it is a part of, so that we can highlight it
1236      * as an error for the user. We do this by the hand-on-one-wall
1237      * technique: the search will follow branches off the inside of
1238      * the loop, discover they're dead ends, and unhighlight them
1239      * again when returning to the actual loop.
1240      * 
1241      * This technique guarantees that every loop it tracks will
1242      * surround a disjoint area of the grid (since if an existing
1243      * loop appears on the boundary of a new one, so that there are
1244      * multiple possible paths that would come back to the starting
1245      * point, it will pick the one that allows it to turn right
1246      * most sharply and hence the one that does not re-surround the
1247      * area of the previous one). Thus, the total time taken in
1248      * searching round loops is linear in the grid area since every
1249      * edge is visited at most twice.
1250      */
1251     dsf = state->clues->tmpdsf;
1252     for (i = 0; i < W*H; i++)
1253         dsf[i] = i;                    /* initially all distinct */
1254     for (y = 0; y < h; y++)
1255         for (x = 0; x < w; x++) {
1256             int i1, i2;
1257
1258             if (state->soln[y*w+x] == 0)
1259                 continue;
1260             if (state->soln[y*w+x] < 0) {
1261                 i1 = y*W+x;
1262                 i2 = (y+1)*W+(x+1);
1263             } else {
1264                 i1 = y*W+(x+1);
1265                 i2 = (y+1)*W+x;
1266             }
1267
1268             /*
1269              * Our edge connects i1 with i2. If they're already
1270              * connected, flag an error. Otherwise, link them.
1271              */
1272             if (dsf_canonify(dsf, i1) == dsf_canonify(dsf, i2)) {
1273                 int x1, y1, x2, y2, dx, dy, dt, pass;
1274
1275                 err = TRUE;
1276
1277                 /*
1278                  * Now search around the boundary of the loop to
1279                  * highlight it.
1280                  * 
1281                  * We have to do this in two passes. The first
1282                  * time, we toggle ERR_SQUARE_TMP on each edge;
1283                  * this pass terminates with ERR_SQUARE_TMP set on
1284                  * exactly the loop edges. In the second pass, we
1285                  * trace round that loop again and turn
1286                  * ERR_SQUARE_TMP into ERR_SQUARE. We have to do
1287                  * this because otherwise we might cancel part of a
1288                  * loop highlighted in a previous iteration of the
1289                  * outer loop.
1290                  */
1291
1292                 for (pass = 0; pass < 2; pass++) {
1293
1294                     x1 = i1 % W;
1295                     y1 = i1 / W;
1296                     x2 = i2 % W;
1297                     y2 = i2 / W;
1298
1299                     do {
1300                         /* Mark this edge. */
1301                         if (pass == 0) {
1302                             state->errors[min(y1,y2)*W+min(x1,x2)] ^=
1303                                 ERR_SQUARE_TMP;
1304                         } else {
1305                             state->errors[min(y1,y2)*W+min(x1,x2)] |=
1306                                 ERR_SQUARE;
1307                             state->errors[min(y1,y2)*W+min(x1,x2)] &=
1308                                 ~ERR_SQUARE_TMP;
1309                         }
1310
1311                         /*
1312                          * Progress to the next edge by turning as
1313                          * sharply right as possible. In fact we do
1314                          * this by facing back along the edge and
1315                          * turning _left_ until we see an edge we
1316                          * can follow.
1317                          */
1318                         dx = x1 - x2;
1319                         dy = y1 - y2;
1320
1321                         for (i = 0; i < 4; i++) {
1322                             /*
1323                              * Rotate (dx,dy) to the left.
1324                              */
1325                             dt = dx; dx = dy; dy = -dt;
1326
1327                             /*
1328                              * See if (x2,y2) has an edge in direction
1329                              * (dx,dy).
1330                              */
1331                             if (x2+dx < 0 || x2+dx >= W ||
1332                                 y2+dy < 0 || y2+dy >= H)
1333                                 continue;  /* off the side of the grid */
1334                             /* In the second pass, ignore unmarked edges. */
1335                             if (pass == 1 &&
1336                                 !(state->errors[(y2-(dy<0))*W+x2-(dx<0)] &
1337                                   ERR_SQUARE_TMP))
1338                                 continue;
1339                             if (state->soln[(y2-(dy<0))*w+x2-(dx<0)] ==
1340                                 (dx==dy ? -1 : +1))
1341                                 break;
1342                         }
1343
1344                         /*
1345                          * In pass 0, we expect to have found
1346                          * _some_ edge we can follow, even if it
1347                          * was found by rotating all the way round
1348                          * and going back the way we came.
1349                          * 
1350                          * In pass 1, because we're removing the
1351                          * mark on each edge that allows us to
1352                          * follow it, we expect to find _no_ edge
1353                          * we can follow when we've come all the
1354                          * way round the loop.
1355                          */
1356                         if (pass == 1 && i == 4)
1357                             break;
1358                         assert(i < 4);
1359
1360                         /*
1361                          * Set x1,y1 to x2,y2, and x2,y2 to be the
1362                          * other end of the new edge.
1363                          */
1364                         x1 = x2;
1365                         y1 = y2;
1366                         x2 += dx;
1367                         y2 += dy;
1368                     } while (y2*W+x2 != i2);
1369
1370                 }
1371                 
1372             } else
1373                 dsf_merge(dsf, i1, i2);
1374         }
1375
1376     /*
1377      * Now go through and check the degree of each clue vertex, and
1378      * mark it with ERR_VERTEX if it cannot be fulfilled.
1379      */
1380     for (y = 0; y < H; y++)
1381         for (x = 0; x < W; x++) {
1382             int c;
1383
1384             if ((c = state->clues->clues[y*W+x]) < 0)
1385                 continue;
1386
1387             /*
1388              * Check to see if there are too many connections to
1389              * this vertex _or_ too many non-connections. Either is
1390              * grounds for marking the vertex as erroneous.
1391              */
1392             if (vertex_degree(w, h, state->soln, x, y,
1393                               FALSE, NULL, NULL) > c ||
1394                 vertex_degree(w, h, state->soln, x, y,
1395                               TRUE, NULL, NULL) > 4-c) {
1396                 state->errors[y*W+x] |= ERR_VERTEX;
1397                 err = TRUE;
1398             }
1399         }
1400
1401     /*
1402      * Now our actual victory condition is that (a) none of the
1403      * above code marked anything as erroneous, and (b) every
1404      * square has an edge in it.
1405      */
1406
1407     if (err)
1408         return FALSE;
1409
1410     for (y = 0; y < h; y++)
1411         for (x = 0; x < w; x++)
1412             if (state->soln[y*w+x] == 0)
1413                 return FALSE;
1414
1415     return TRUE;
1416 }
1417
1418 static char *solve_game(game_state *state, game_state *currstate,
1419                         char *aux, char **error)
1420 {
1421     int w = state->p.w, h = state->p.h;
1422     signed char *soln;
1423     int bs, ret;
1424     int free_soln = FALSE;
1425     char *move, buf[80];
1426     int movelen, movesize;
1427     int x, y;
1428
1429     if (aux) {
1430         /*
1431          * If we already have the solution, save ourselves some
1432          * time.
1433          */
1434         soln = (signed char *)aux;
1435         bs = (signed char)'\\';
1436         free_soln = FALSE;
1437     } else {
1438         struct solver_scratch *sc = new_scratch(w, h);
1439         soln = snewn(w*h, signed char);
1440         bs = -1;
1441         ret = slant_solve(w, h, state->clues->clues, soln, sc, DIFF_HARD);
1442         free_scratch(sc);
1443         if (ret != 1) {
1444             sfree(soln);
1445             if (ret == 0)
1446                 *error = "This puzzle is not self-consistent";
1447             else
1448                 *error = "Unable to find a unique solution for this puzzle";
1449             return NULL;
1450         }
1451         free_soln = TRUE;
1452     }
1453
1454     /*
1455      * Construct a move string which turns the current state into
1456      * the solved state.
1457      */
1458     movesize = 256;
1459     move = snewn(movesize, char);
1460     movelen = 0;
1461     move[movelen++] = 'S';
1462     move[movelen] = '\0';
1463     for (y = 0; y < h; y++)
1464         for (x = 0; x < w; x++) {
1465             int v = (soln[y*w+x] == bs ? -1 : +1);
1466             if (state->soln[y*w+x] != v) {
1467                 int len = sprintf(buf, ";%c%d,%d", (int)(v < 0 ? '\\' : '/'), x, y);
1468                 if (movelen + len >= movesize) {
1469                     movesize = movelen + len + 256;
1470                     move = sresize(move, movesize, char);
1471                 }
1472                 strcpy(move + movelen, buf);
1473                 movelen += len;
1474             }
1475         }
1476
1477     if (free_soln)
1478         sfree(soln);
1479
1480     return move;
1481 }
1482
1483 static char *game_text_format(game_state *state)
1484 {
1485     int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
1486     int x, y, len;
1487     char *ret, *p;
1488
1489     /*
1490      * There are h+H rows of w+W columns.
1491      */
1492     len = (h+H) * (w+W+1) + 1;
1493     ret = snewn(len, char);
1494     p = ret;
1495
1496     for (y = 0; y < H; y++) {
1497         for (x = 0; x < W; x++) {
1498             if (state->clues->clues[y*W+x] >= 0)
1499                 *p++ = state->clues->clues[y*W+x] + '0';
1500             else
1501                 *p++ = '+';
1502             if (x < w)
1503                 *p++ = '-';
1504         }
1505         *p++ = '\n';
1506         if (y < h) {
1507             for (x = 0; x < W; x++) {
1508                 *p++ = '|';
1509                 if (x < w) {
1510                     if (state->soln[y*w+x] != 0)
1511                         *p++ = (state->soln[y*w+x] < 0 ? '\\' : '/');
1512                     else
1513                         *p++ = ' ';
1514                 }
1515             }
1516             *p++ = '\n';
1517         }
1518     }
1519     *p++ = '\0';
1520
1521     assert(p - ret == len);
1522     return ret;
1523 }
1524
1525 static game_ui *new_ui(game_state *state)
1526 {
1527     return NULL;
1528 }
1529
1530 static void free_ui(game_ui *ui)
1531 {
1532 }
1533
1534 static char *encode_ui(game_ui *ui)
1535 {
1536     return NULL;
1537 }
1538
1539 static void decode_ui(game_ui *ui, char *encoding)
1540 {
1541 }
1542
1543 static void game_changed_state(game_ui *ui, game_state *oldstate,
1544                                game_state *newstate)
1545 {
1546 }
1547
1548 #define PREFERRED_TILESIZE 32
1549 #define TILESIZE (ds->tilesize)
1550 #define BORDER TILESIZE
1551 #define CLUE_RADIUS (TILESIZE / 3)
1552 #define CLUE_TEXTSIZE (TILESIZE / 2)
1553 #define COORD(x)  ( (x) * TILESIZE + BORDER )
1554 #define FROMCOORD(x)  ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
1555
1556 #define FLASH_TIME 0.30F
1557
1558 /*
1559  * Bit fields in the `grid' and `todraw' elements of the drawstate.
1560  */
1561 #define BACKSLASH 0x00000001L
1562 #define FORWSLASH 0x00000002L
1563 #define L_T       0x00000004L
1564 #define ERR_L_T   0x00000008L
1565 #define L_B       0x00000010L
1566 #define ERR_L_B   0x00000020L
1567 #define T_L       0x00000040L
1568 #define ERR_T_L   0x00000080L
1569 #define T_R       0x00000100L
1570 #define ERR_T_R   0x00000200L
1571 #define C_TL      0x00000400L
1572 #define ERR_C_TL  0x00000800L
1573 #define FLASH     0x00001000L
1574 #define ERRSLASH  0x00002000L
1575 #define ERR_TL    0x00004000L
1576 #define ERR_TR    0x00008000L
1577 #define ERR_BL    0x00010000L
1578 #define ERR_BR    0x00020000L
1579
1580 struct game_drawstate {
1581     int tilesize;
1582     int started;
1583     long *grid;
1584     long *todraw;
1585 };
1586
1587 static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
1588                             int x, int y, int button)
1589 {
1590     int w = state->p.w, h = state->p.h;
1591
1592     if (button == LEFT_BUTTON || button == RIGHT_BUTTON) {
1593         int v;
1594         char buf[80];
1595
1596         /*
1597          * This is an utterly awful hack which I should really sort out
1598          * by means of a proper configuration mechanism. One Slant
1599          * player has observed that they prefer the mouse buttons to
1600          * function exactly the opposite way round, so here's a
1601          * mechanism for environment-based configuration. I cache the
1602          * result in a global variable - yuck! - to avoid repeated
1603          * lookups.
1604          */
1605         {
1606             static int swap_buttons = -1;
1607             if (swap_buttons < 0) {
1608                 char *env = getenv("SLANT_SWAP_BUTTONS");
1609                 swap_buttons = (env && (env[0] == 'y' || env[0] == 'Y'));
1610             }
1611             if (swap_buttons) {
1612                 if (button == LEFT_BUTTON)
1613                     button = RIGHT_BUTTON;
1614                 else
1615                     button = LEFT_BUTTON;
1616             }
1617         }
1618
1619         x = FROMCOORD(x);
1620         y = FROMCOORD(y);
1621         if (x < 0 || y < 0 || x >= w || y >= h)
1622             return NULL;
1623
1624         if (button == LEFT_BUTTON) {
1625             /*
1626              * Left-clicking cycles blank -> \ -> / -> blank.
1627              */
1628             v = state->soln[y*w+x] - 1;
1629             if (v == -2)
1630                 v = +1;
1631         } else {
1632             /*
1633              * Right-clicking cycles blank -> / -> \ -> blank.
1634              */
1635             v = state->soln[y*w+x] + 1;
1636             if (v == +2)
1637                 v = -1;
1638         }
1639
1640         sprintf(buf, "%c%d,%d", (int)(v==-1 ? '\\' : v==+1 ? '/' : 'C'), x, y);
1641         return dupstr(buf);
1642     }
1643
1644     return NULL;
1645 }
1646
1647 static game_state *execute_move(game_state *state, char *move)
1648 {
1649     int w = state->p.w, h = state->p.h;
1650     char c;
1651     int x, y, n;
1652     game_state *ret = dup_game(state);
1653
1654     while (*move) {
1655         c = *move;
1656         if (c == 'S') {
1657             ret->used_solve = TRUE;
1658             move++;
1659         } else if (c == '\\' || c == '/' || c == 'C') {
1660             move++;
1661             if (sscanf(move, "%d,%d%n", &x, &y, &n) != 2 ||
1662                 x < 0 || y < 0 || x >= w || y >= h) {
1663                 free_game(ret);
1664                 return NULL;
1665             }
1666             ret->soln[y*w+x] = (c == '\\' ? -1 : c == '/' ? +1 : 0);
1667             move += n;
1668         } else {
1669             free_game(ret);
1670             return NULL;
1671         }
1672         if (*move == ';')
1673             move++;
1674         else if (*move) {
1675             free_game(ret);
1676             return NULL;
1677         }
1678     }
1679
1680     /*
1681      * We never clear the `completed' flag, but we must always
1682      * re-run the completion check because it also highlights
1683      * errors in the grid.
1684      */
1685     ret->completed = check_completion(ret) || ret->completed;
1686
1687     return ret;
1688 }
1689
1690 /* ----------------------------------------------------------------------
1691  * Drawing routines.
1692  */
1693
1694 static void game_compute_size(game_params *params, int tilesize,
1695                               int *x, int *y)
1696 {
1697     /* fool the macros */
1698     struct dummy { int tilesize; } dummy = { tilesize }, *ds = &dummy;
1699
1700     *x = 2 * BORDER + params->w * TILESIZE + 1;
1701     *y = 2 * BORDER + params->h * TILESIZE + 1;
1702 }
1703
1704 static void game_set_size(drawing *dr, game_drawstate *ds,
1705                           game_params *params, int tilesize)
1706 {
1707     ds->tilesize = tilesize;
1708 }
1709
1710 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
1711 {
1712     float *ret = snewn(3 * NCOLOURS, float);
1713
1714     frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
1715
1716     ret[COL_GRID * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 0.7F;
1717     ret[COL_GRID * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] * 0.7F;
1718     ret[COL_GRID * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] * 0.7F;
1719
1720     ret[COL_INK * 3 + 0] = 0.0F;
1721     ret[COL_INK * 3 + 1] = 0.0F;
1722     ret[COL_INK * 3 + 2] = 0.0F;
1723
1724     ret[COL_SLANT1 * 3 + 0] = 0.0F;
1725     ret[COL_SLANT1 * 3 + 1] = 0.0F;
1726     ret[COL_SLANT1 * 3 + 2] = 0.0F;
1727
1728     ret[COL_SLANT2 * 3 + 0] = 0.0F;
1729     ret[COL_SLANT2 * 3 + 1] = 0.0F;
1730     ret[COL_SLANT2 * 3 + 2] = 0.0F;
1731
1732     ret[COL_ERROR * 3 + 0] = 1.0F;
1733     ret[COL_ERROR * 3 + 1] = 0.0F;
1734     ret[COL_ERROR * 3 + 2] = 0.0F;
1735
1736     *ncolours = NCOLOURS;
1737     return ret;
1738 }
1739
1740 static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
1741 {
1742     int w = state->p.w, h = state->p.h;
1743     int i;
1744     struct game_drawstate *ds = snew(struct game_drawstate);
1745
1746     ds->tilesize = 0;
1747     ds->started = FALSE;
1748     ds->grid = snewn((w+2)*(h+2), long);
1749     ds->todraw = snewn((w+2)*(h+2), long);
1750     for (i = 0; i < (w+2)*(h+2); i++)
1751         ds->grid[i] = ds->todraw[i] = -1;
1752
1753     return ds;
1754 }
1755
1756 static void game_free_drawstate(drawing *dr, game_drawstate *ds)
1757 {
1758     sfree(ds->todraw);
1759     sfree(ds->grid);
1760     sfree(ds);
1761 }
1762
1763 static void draw_clue(drawing *dr, game_drawstate *ds,
1764                       int x, int y, long v, long err, int bg, int colour)
1765 {
1766     char p[2];
1767     int ccol = colour >= 0 ? colour : ((x ^ y) & 1) ? COL_SLANT1 : COL_SLANT2;
1768     int tcol = colour >= 0 ? colour : err ? COL_ERROR : COL_INK;
1769
1770     if (v < 0)
1771         return;
1772
1773     p[0] = v + '0';
1774     p[1] = '\0';
1775     draw_circle(dr, COORD(x), COORD(y), CLUE_RADIUS,
1776                 bg >= 0 ? bg : COL_BACKGROUND, ccol);
1777     draw_text(dr, COORD(x), COORD(y), FONT_VARIABLE,
1778               CLUE_TEXTSIZE, ALIGN_VCENTRE|ALIGN_HCENTRE, tcol, p);
1779 }
1780
1781 static void draw_tile(drawing *dr, game_drawstate *ds, game_clues *clues,
1782                       int x, int y, long v)
1783 {
1784     int w = clues->w, h = clues->h, W = w+1 /*, H = h+1 */;
1785     int chesscolour = (x ^ y) & 1;
1786     int fscol = chesscolour ? COL_SLANT2 : COL_SLANT1;
1787     int bscol = chesscolour ? COL_SLANT1 : COL_SLANT2;
1788
1789     clip(dr, COORD(x), COORD(y), TILESIZE, TILESIZE);
1790
1791     draw_rect(dr, COORD(x), COORD(y), TILESIZE, TILESIZE,
1792               (v & FLASH) ? COL_GRID : COL_BACKGROUND);
1793
1794     /*
1795      * Draw the grid lines.
1796      */
1797     if (x >= 0 && x < w && y >= 0)
1798         draw_rect(dr, COORD(x), COORD(y), TILESIZE+1, 1, COL_GRID);
1799     if (x >= 0 && x < w && y < h)
1800         draw_rect(dr, COORD(x), COORD(y+1), TILESIZE+1, 1, COL_GRID);
1801     if (y >= 0 && y < h && x >= 0)
1802         draw_rect(dr, COORD(x), COORD(y), 1, TILESIZE+1, COL_GRID);
1803     if (y >= 0 && y < h && x < w)
1804         draw_rect(dr, COORD(x+1), COORD(y), 1, TILESIZE+1, COL_GRID);
1805     if (x == -1 && y == -1)
1806         draw_rect(dr, COORD(x+1), COORD(y+1), 1, 1, COL_GRID);
1807     if (x == -1 && y == h)
1808         draw_rect(dr, COORD(x+1), COORD(y), 1, 1, COL_GRID);
1809     if (x == w && y == -1)
1810         draw_rect(dr, COORD(x), COORD(y+1), 1, 1, COL_GRID);
1811     if (x == w && y == h)
1812         draw_rect(dr, COORD(x), COORD(y), 1, 1, COL_GRID);
1813
1814     /*
1815      * Draw the slash.
1816      */
1817     if (v & BACKSLASH) {
1818         int scol = (v & ERRSLASH) ? COL_ERROR : bscol;
1819         draw_line(dr, COORD(x), COORD(y), COORD(x+1), COORD(y+1), scol);
1820         draw_line(dr, COORD(x)+1, COORD(y), COORD(x+1), COORD(y+1)-1,
1821                   scol);
1822         draw_line(dr, COORD(x), COORD(y)+1, COORD(x+1)-1, COORD(y+1),
1823                   scol);
1824     } else if (v & FORWSLASH) {
1825         int scol = (v & ERRSLASH) ? COL_ERROR : fscol;
1826         draw_line(dr, COORD(x+1), COORD(y), COORD(x), COORD(y+1), scol);
1827         draw_line(dr, COORD(x+1)-1, COORD(y), COORD(x), COORD(y+1)-1,
1828                   scol);
1829         draw_line(dr, COORD(x+1), COORD(y)+1, COORD(x)+1, COORD(y+1),
1830                   scol);
1831     }
1832
1833     /*
1834      * Draw dots on the grid corners that appear if a slash is in a
1835      * neighbouring cell.
1836      */
1837     if (v & (L_T | BACKSLASH))
1838         draw_rect(dr, COORD(x), COORD(y)+1, 1, 1,
1839                   (v & ERR_L_T ? COL_ERROR : bscol));
1840     if (v & (L_B | FORWSLASH))
1841         draw_rect(dr, COORD(x), COORD(y+1)-1, 1, 1,
1842                   (v & ERR_L_B ? COL_ERROR : fscol));
1843     if (v & (T_L | BACKSLASH))
1844         draw_rect(dr, COORD(x)+1, COORD(y), 1, 1,
1845                   (v & ERR_T_L ? COL_ERROR : bscol));
1846     if (v & (T_R | FORWSLASH))
1847         draw_rect(dr, COORD(x+1)-1, COORD(y), 1, 1,
1848                   (v & ERR_T_R ? COL_ERROR : fscol));
1849     if (v & (C_TL | BACKSLASH))
1850         draw_rect(dr, COORD(x), COORD(y), 1, 1,
1851                   (v & ERR_C_TL ? COL_ERROR : bscol));
1852
1853     /*
1854      * And finally the clues at the corners.
1855      */
1856     if (x >= 0 && y >= 0)
1857         draw_clue(dr, ds, x, y, clues->clues[y*W+x], v & ERR_TL, -1, -1);
1858     if (x < w && y >= 0)
1859         draw_clue(dr, ds, x+1, y, clues->clues[y*W+(x+1)], v & ERR_TR, -1, -1);
1860     if (x >= 0 && y < h)
1861         draw_clue(dr, ds, x, y+1, clues->clues[(y+1)*W+x], v & ERR_BL, -1, -1);
1862     if (x < w && y < h)
1863         draw_clue(dr, ds, x+1, y+1, clues->clues[(y+1)*W+(x+1)], v & ERR_BR,
1864                   -1, -1);
1865
1866     unclip(dr);
1867     draw_update(dr, COORD(x), COORD(y), TILESIZE, TILESIZE);
1868 }
1869
1870 static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
1871                         game_state *state, int dir, game_ui *ui,
1872                         float animtime, float flashtime)
1873 {
1874     int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
1875     int x, y;
1876     int flashing;
1877
1878     if (flashtime > 0)
1879         flashing = (int)(flashtime * 3 / FLASH_TIME) != 1;
1880     else
1881         flashing = FALSE;
1882
1883     if (!ds->started) {
1884         int ww, wh;
1885         game_compute_size(&state->p, TILESIZE, &ww, &wh);
1886         draw_rect(dr, 0, 0, ww, wh, COL_BACKGROUND);
1887         draw_update(dr, 0, 0, ww, wh);
1888         ds->started = TRUE;
1889     }
1890
1891     /*
1892      * Loop over the grid and work out where all the slashes are.
1893      * We need to do this because a slash in one square affects the
1894      * drawing of the next one along.
1895      */
1896     for (y = -1; y <= h; y++)
1897         for (x = -1; x <= w; x++) {
1898             if (x >= 0 && x < w && y >= 0 && y < h)
1899                 ds->todraw[(y+1)*(w+2)+(x+1)] = flashing ? FLASH : 0;
1900             else
1901                 ds->todraw[(y+1)*(w+2)+(x+1)] = 0;
1902         }
1903
1904     for (y = 0; y < h; y++) {
1905         for (x = 0; x < w; x++) {
1906             int err = state->errors[y*W+x] & ERR_SQUARE;
1907
1908             if (state->soln[y*w+x] < 0) {
1909                 ds->todraw[(y+1)*(w+2)+(x+1)] |= BACKSLASH;
1910                 ds->todraw[(y+2)*(w+2)+(x+1)] |= T_R;
1911                 ds->todraw[(y+1)*(w+2)+(x+2)] |= L_B;
1912                 ds->todraw[(y+2)*(w+2)+(x+2)] |= C_TL;
1913                 if (err) {
1914                     ds->todraw[(y+1)*(w+2)+(x+1)] |= ERRSLASH | 
1915                         ERR_T_L | ERR_L_T | ERR_C_TL;
1916                     ds->todraw[(y+2)*(w+2)+(x+1)] |= ERR_T_R;
1917                     ds->todraw[(y+1)*(w+2)+(x+2)] |= ERR_L_B;
1918                     ds->todraw[(y+2)*(w+2)+(x+2)] |= ERR_C_TL;
1919                 }
1920             } else if (state->soln[y*w+x] > 0) {
1921                 ds->todraw[(y+1)*(w+2)+(x+1)] |= FORWSLASH;
1922                 ds->todraw[(y+1)*(w+2)+(x+2)] |= L_T | C_TL;
1923                 ds->todraw[(y+2)*(w+2)+(x+1)] |= T_L | C_TL;
1924                 if (err) {
1925                     ds->todraw[(y+1)*(w+2)+(x+1)] |= ERRSLASH |
1926                         ERR_L_B | ERR_T_R;
1927                     ds->todraw[(y+1)*(w+2)+(x+2)] |= ERR_L_T | ERR_C_TL;
1928                     ds->todraw[(y+2)*(w+2)+(x+1)] |= ERR_T_L | ERR_C_TL;
1929                 }
1930             }
1931         }
1932     }
1933
1934     for (y = 0; y < H; y++)
1935         for (x = 0; x < W; x++)
1936             if (state->errors[y*W+x] & ERR_VERTEX) {
1937                 ds->todraw[y*(w+2)+x] |= ERR_BR;
1938                 ds->todraw[y*(w+2)+(x+1)] |= ERR_BL;
1939                 ds->todraw[(y+1)*(w+2)+x] |= ERR_TR;
1940                 ds->todraw[(y+1)*(w+2)+(x+1)] |= ERR_TL;
1941             }
1942
1943     /*
1944      * Now go through and draw the grid squares.
1945      */
1946     for (y = -1; y <= h; y++) {
1947         for (x = -1; x <= w; x++) {
1948             if (ds->todraw[(y+1)*(w+2)+(x+1)] != ds->grid[(y+1)*(w+2)+(x+1)]) {
1949                 draw_tile(dr, ds, state->clues, x, y,
1950                           ds->todraw[(y+1)*(w+2)+(x+1)]);
1951                 ds->grid[(y+1)*(w+2)+(x+1)] = ds->todraw[(y+1)*(w+2)+(x+1)];
1952             }
1953         }
1954     }
1955 }
1956
1957 static float game_anim_length(game_state *oldstate, game_state *newstate,
1958                               int dir, game_ui *ui)
1959 {
1960     return 0.0F;
1961 }
1962
1963 static float game_flash_length(game_state *oldstate, game_state *newstate,
1964                                int dir, game_ui *ui)
1965 {
1966     if (!oldstate->completed && newstate->completed &&
1967         !oldstate->used_solve && !newstate->used_solve)
1968         return FLASH_TIME;
1969
1970     return 0.0F;
1971 }
1972
1973 static int game_wants_statusbar(void)
1974 {
1975     return FALSE;
1976 }
1977
1978 static int game_timing_state(game_state *state, game_ui *ui)
1979 {
1980     return TRUE;
1981 }
1982
1983 static void game_print_size(game_params *params, float *x, float *y)
1984 {
1985     int pw, ph;
1986
1987     /*
1988      * I'll use 6mm squares by default.
1989      */
1990     game_compute_size(params, 600, &pw, &ph);
1991     *x = pw / 100.0;
1992     *y = ph / 100.0;
1993 }
1994
1995 static void game_print(drawing *dr, game_state *state, int tilesize)
1996 {
1997     int w = state->p.w, h = state->p.h, W = w+1;
1998     int ink = print_mono_colour(dr, 0);
1999     int paper = print_mono_colour(dr, 1);
2000     int x, y;
2001
2002     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
2003     game_drawstate ads, *ds = &ads;
2004     game_set_size(dr, ds, NULL, tilesize);
2005
2006     /*
2007      * Border.
2008      */
2009     print_line_width(dr, TILESIZE / 16);
2010     draw_rect_outline(dr, COORD(0), COORD(0), w*TILESIZE, h*TILESIZE, ink);
2011
2012     /*
2013      * Grid.
2014      */
2015     print_line_width(dr, TILESIZE / 24);
2016     for (x = 1; x < w; x++)
2017         draw_line(dr, COORD(x), COORD(0), COORD(x), COORD(h), ink);
2018     for (y = 1; y < h; y++)
2019         draw_line(dr, COORD(0), COORD(y), COORD(w), COORD(y), ink);
2020
2021     /*
2022      * Solution.
2023      */
2024     print_line_width(dr, TILESIZE / 12);
2025     for (y = 0; y < h; y++)
2026         for (x = 0; x < w; x++)
2027             if (state->soln[y*w+x]) {
2028                 int ly, ry;
2029                 /*
2030                  * To prevent nasty line-ending artefacts at
2031                  * corners, I'll do something slightly cunning
2032                  * here.
2033                  */
2034                 clip(dr, COORD(x), COORD(y), TILESIZE, TILESIZE);
2035                 if (state->soln[y*w+x] < 0)
2036                     ly = y-1, ry = y+2;
2037                 else
2038                     ry = y-1, ly = y+2;
2039                 draw_line(dr, COORD(x-1), COORD(ly), COORD(x+2), COORD(ry),
2040                           ink);
2041                 unclip(dr);
2042             }
2043
2044     /*
2045      * Clues.
2046      */
2047     print_line_width(dr, TILESIZE / 24);
2048     for (y = 0; y <= h; y++)
2049         for (x = 0; x <= w; x++)
2050             draw_clue(dr, ds, x, y, state->clues->clues[y*W+x],
2051                       FALSE, paper, ink);
2052 }
2053
2054 #ifdef COMBINED
2055 #define thegame slant
2056 #endif
2057
2058 const struct game thegame = {
2059     "Slant", "games.slant",
2060     default_params,
2061     game_fetch_preset,
2062     decode_params,
2063     encode_params,
2064     free_params,
2065     dup_params,
2066     TRUE, game_configure, custom_params,
2067     validate_params,
2068     new_game_desc,
2069     validate_desc,
2070     new_game,
2071     dup_game,
2072     free_game,
2073     TRUE, solve_game,
2074     TRUE, game_text_format,
2075     new_ui,
2076     free_ui,
2077     encode_ui,
2078     decode_ui,
2079     game_changed_state,
2080     interpret_move,
2081     execute_move,
2082     PREFERRED_TILESIZE, game_compute_size, game_set_size,
2083     game_colours,
2084     game_new_drawstate,
2085     game_free_drawstate,
2086     game_redraw,
2087     game_anim_length,
2088     game_flash_length,
2089     TRUE, FALSE, game_print_size, game_print,
2090     game_wants_statusbar,
2091     FALSE, game_timing_state,
2092     0,                                 /* flags */
2093 };
2094
2095 #ifdef STANDALONE_SOLVER
2096
2097 #include <stdarg.h>
2098
2099 int main(int argc, char **argv)
2100 {
2101     game_params *p;
2102     game_state *s;
2103     char *id = NULL, *desc, *err;
2104     int grade = FALSE;
2105     int ret, diff, really_verbose = FALSE;
2106     struct solver_scratch *sc;
2107
2108     while (--argc > 0) {
2109         char *p = *++argv;
2110         if (!strcmp(p, "-v")) {
2111             really_verbose = TRUE;
2112         } else if (!strcmp(p, "-g")) {
2113             grade = TRUE;
2114         } else if (*p == '-') {
2115             fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
2116             return 1;
2117         } else {
2118             id = p;
2119         }
2120     }
2121
2122     if (!id) {
2123         fprintf(stderr, "usage: %s [-g | -v] <game_id>\n", argv[0]);
2124         return 1;
2125     }
2126
2127     desc = strchr(id, ':');
2128     if (!desc) {
2129         fprintf(stderr, "%s: game id expects a colon in it\n", argv[0]);
2130         return 1;
2131     }
2132     *desc++ = '\0';
2133
2134     p = default_params();
2135     decode_params(p, id);
2136     err = validate_desc(p, desc);
2137     if (err) {
2138         fprintf(stderr, "%s: %s\n", argv[0], err);
2139         return 1;
2140     }
2141     s = new_game(NULL, p, desc);
2142
2143     sc = new_scratch(p->w, p->h);
2144
2145     /*
2146      * When solving an Easy puzzle, we don't want to bother the
2147      * user with Hard-level deductions. For this reason, we grade
2148      * the puzzle internally before doing anything else.
2149      */
2150     ret = -1;                          /* placate optimiser */
2151     for (diff = 0; diff < DIFFCOUNT; diff++) {
2152         ret = slant_solve(p->w, p->h, s->clues->clues,
2153                           s->soln, sc, diff);
2154         if (ret < 2)
2155             break;
2156     }
2157
2158     if (diff == DIFFCOUNT) {
2159         if (grade)
2160             printf("Difficulty rating: harder than Hard, or ambiguous\n");
2161         else
2162             printf("Unable to find a unique solution\n");
2163     } else {
2164         if (grade) {
2165             if (ret == 0)
2166                 printf("Difficulty rating: impossible (no solution exists)\n");
2167             else if (ret == 1)
2168                 printf("Difficulty rating: %s\n", slant_diffnames[diff]);
2169         } else {
2170             verbose = really_verbose;
2171             ret = slant_solve(p->w, p->h, s->clues->clues,
2172                               s->soln, sc, diff);
2173             if (ret == 0)
2174                 printf("Puzzle is inconsistent\n");
2175             else
2176                 fputs(game_text_format(s), stdout);
2177         }
2178     }
2179
2180     return 0;
2181 }
2182
2183 #endif