chiark / gitweb /
Cleanup: remove the game_state parameter to game_colours(). No game
[sgt-puzzles.git] / mines.c
1 /*
2  * mines.c: Minesweeper clone with sophisticated grid generation.
3  * 
4  * Still TODO:
5  *
6  *  - think about configurably supporting question marks. Once,
7  *    that is, we've thought about configurability in general!
8  */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <assert.h>
14 #include <ctype.h>
15 #include <math.h>
16
17 #include "tree234.h"
18 #include "puzzles.h"
19
20 enum {
21     COL_BACKGROUND, COL_BACKGROUND2,
22     COL_1, COL_2, COL_3, COL_4, COL_5, COL_6, COL_7, COL_8,
23     COL_MINE, COL_BANG, COL_CROSS, COL_FLAG, COL_FLAGBASE, COL_QUERY,
24     COL_HIGHLIGHT, COL_LOWLIGHT,
25     NCOLOURS
26 };
27
28 #define PREFERRED_TILE_SIZE 20
29 #define TILE_SIZE (ds->tilesize)
30 #define BORDER (TILE_SIZE * 3 / 2)
31 #define HIGHLIGHT_WIDTH (TILE_SIZE / 10)
32 #define OUTER_HIGHLIGHT_WIDTH (BORDER / 10)
33 #define COORD(x)  ( (x) * TILE_SIZE + BORDER )
34 #define FROMCOORD(x)  ( ((x) - BORDER + TILE_SIZE) / TILE_SIZE - 1 )
35
36 #define FLASH_FRAME 0.13F
37
38 struct game_params {
39     int w, h, n;
40     int unique;
41 };
42
43 struct mine_layout {
44     /*
45      * This structure is shared between all the game_states for a
46      * given instance of the puzzle, so we reference-count it.
47      */
48     int refcount;
49     char *mines;
50     /*
51      * If we haven't yet actually generated the mine layout, here's
52      * all the data we will need to do so.
53      */
54     int n, unique;
55     random_state *rs;
56     midend *me;                /* to give back the new game desc */
57 };
58
59 struct game_state {
60     int w, h, n, dead, won;
61     int used_solve, just_used_solve;
62     struct mine_layout *layout;        /* real mine positions */
63     signed char *grid;                         /* player knowledge */
64     /*
65      * Each item in the `grid' array is one of the following values:
66      * 
67      *  - 0 to 8 mean the square is open and has a surrounding mine
68      *    count.
69      * 
70      *  - -1 means the square is marked as a mine.
71      * 
72      *  - -2 means the square is unknown.
73      * 
74      *  - -3 means the square is marked with a question mark
75      *    (FIXME: do we even want to bother with this?).
76      * 
77      *  - 64 means the square has had a mine revealed when the game
78      *    was lost.
79      * 
80      *  - 65 means the square had a mine revealed and this was the
81      *    one the player hits.
82      * 
83      *  - 66 means the square has a crossed-out mine because the
84      *    player had incorrectly marked it.
85      */
86 };
87
88 static game_params *default_params(void)
89 {
90     game_params *ret = snew(game_params);
91
92     ret->w = ret->h = 9;
93     ret->n = 10;
94     ret->unique = TRUE;
95
96     return ret;
97 }
98
99 static const struct game_params mines_presets[] = {
100   {9, 9, 10, TRUE},
101   {9, 9, 35, TRUE},
102   {16, 16, 40, TRUE},
103   {16, 16, 99, TRUE},
104   {30, 16, 99, TRUE},
105   {30, 16, 170, TRUE},
106 };
107
108 static int game_fetch_preset(int i, char **name, game_params **params)
109 {
110     game_params *ret;
111     char str[80];
112
113     if (i < 0 || i >= lenof(mines_presets))
114         return FALSE;
115
116     ret = snew(game_params);
117     *ret = mines_presets[i];
118
119     sprintf(str, "%dx%d, %d mines", ret->w, ret->h, ret->n);
120
121     *name = dupstr(str);
122     *params = ret;
123     return TRUE;
124 }
125
126 static void free_params(game_params *params)
127 {
128     sfree(params);
129 }
130
131 static game_params *dup_params(game_params *params)
132 {
133     game_params *ret = snew(game_params);
134     *ret = *params;                    /* structure copy */
135     return ret;
136 }
137
138 static void decode_params(game_params *params, char const *string)
139 {
140     char const *p = string;
141
142     params->w = atoi(p);
143     while (*p && isdigit((unsigned char)*p)) p++;
144     if (*p == 'x') {
145         p++;
146         params->h = atoi(p);
147         while (*p && isdigit((unsigned char)*p)) p++;
148     } else {
149         params->h = params->w;
150     }
151     if (*p == 'n') {
152         p++;
153         params->n = atoi(p);
154         while (*p && (*p == '.' || isdigit((unsigned char)*p))) p++;
155     } else {
156         params->n = params->w * params->h / 10;
157     }
158
159     while (*p) {
160         if (*p == 'a') {
161             p++;
162             params->unique = FALSE;
163         } else
164             p++;                       /* skip any other gunk */
165     }
166 }
167
168 static char *encode_params(game_params *params, int full)
169 {
170     char ret[400];
171     int len;
172
173     len = sprintf(ret, "%dx%d", params->w, params->h);
174     /*
175      * Mine count is a generation-time parameter, since it can be
176      * deduced from the mine bitmap!
177      */
178     if (full)
179         len += sprintf(ret+len, "n%d", params->n);
180     if (full && !params->unique)
181         ret[len++] = 'a';
182     assert(len < lenof(ret));
183     ret[len] = '\0';
184
185     return dupstr(ret);
186 }
187
188 static config_item *game_configure(game_params *params)
189 {
190     config_item *ret;
191     char buf[80];
192
193     ret = snewn(5, config_item);
194
195     ret[0].name = "Width";
196     ret[0].type = C_STRING;
197     sprintf(buf, "%d", params->w);
198     ret[0].sval = dupstr(buf);
199     ret[0].ival = 0;
200
201     ret[1].name = "Height";
202     ret[1].type = C_STRING;
203     sprintf(buf, "%d", params->h);
204     ret[1].sval = dupstr(buf);
205     ret[1].ival = 0;
206
207     ret[2].name = "Mines";
208     ret[2].type = C_STRING;
209     sprintf(buf, "%d", params->n);
210     ret[2].sval = dupstr(buf);
211     ret[2].ival = 0;
212
213     ret[3].name = "Ensure solubility";
214     ret[3].type = C_BOOLEAN;
215     ret[3].sval = NULL;
216     ret[3].ival = params->unique;
217
218     ret[4].name = NULL;
219     ret[4].type = C_END;
220     ret[4].sval = NULL;
221     ret[4].ival = 0;
222
223     return ret;
224 }
225
226 static game_params *custom_params(config_item *cfg)
227 {
228     game_params *ret = snew(game_params);
229
230     ret->w = atoi(cfg[0].sval);
231     ret->h = atoi(cfg[1].sval);
232     ret->n = atoi(cfg[2].sval);
233     if (strchr(cfg[2].sval, '%'))
234         ret->n = ret->n * (ret->w * ret->h) / 100;
235     ret->unique = cfg[3].ival;
236
237     return ret;
238 }
239
240 static char *validate_params(game_params *params, int full)
241 {
242     /*
243      * Lower limit on grid size: each dimension must be at least 3.
244      * 1 is theoretically workable if rather boring, but 2 is a
245      * real problem: there is often _no_ way to generate a uniquely
246      * solvable 2xn Mines grid. You either run into two mines
247      * blocking the way and no idea what's behind them, or one mine
248      * and no way to know which of the two rows it's in. If the
249      * mine count is even you can create a soluble grid by packing
250      * all the mines at one end (so what when you hit a two-mine
251      * wall there are only as many covered squares left as there
252      * are mines); but if it's odd, you are doomed, because you
253      * _have_ to have a gap somewhere which you can't determine the
254      * position of.
255      */
256     if (full && params->unique && (params->w <= 2 || params->h <= 2))
257         return "Width and height must both be greater than two";
258     if (params->n > params->w * params->h - 9)
259         return "Too many mines for grid size";
260
261     /*
262      * FIXME: Need more constraints here. Not sure what the
263      * sensible limits for Minesweeper actually are. The limits
264      * probably ought to change, however, depending on uniqueness.
265      */
266
267     return NULL;
268 }
269
270 /* ----------------------------------------------------------------------
271  * Minesweeper solver, used to ensure the generated grids are
272  * solvable without having to take risks.
273  */
274
275 /*
276  * Count the bits in a word. Only needs to cope with 16 bits.
277  */
278 static int bitcount16(int inword)
279 {
280     unsigned int word = inword;
281
282     word = ((word & 0xAAAA) >> 1) + (word & 0x5555);
283     word = ((word & 0xCCCC) >> 2) + (word & 0x3333);
284     word = ((word & 0xF0F0) >> 4) + (word & 0x0F0F);
285     word = ((word & 0xFF00) >> 8) + (word & 0x00FF);
286
287     return (int)word;
288 }
289
290 /*
291  * We use a tree234 to store a large number of small localised
292  * sets, each with a mine count. We also keep some of those sets
293  * linked together into a to-do list.
294  */
295 struct set {
296     short x, y, mask, mines;
297     int todo;
298     struct set *prev, *next;
299 };
300
301 static int setcmp(void *av, void *bv)
302 {
303     struct set *a = (struct set *)av;
304     struct set *b = (struct set *)bv;
305
306     if (a->y < b->y)
307         return -1;
308     else if (a->y > b->y)
309         return +1;
310     else if (a->x < b->x)
311         return -1;
312     else if (a->x > b->x)
313         return +1;
314     else if (a->mask < b->mask)
315         return -1;
316     else if (a->mask > b->mask)
317         return +1;
318     else
319         return 0;
320 }
321
322 struct setstore {
323     tree234 *sets;
324     struct set *todo_head, *todo_tail;
325 };
326
327 static struct setstore *ss_new(void)
328 {
329     struct setstore *ss = snew(struct setstore);
330     ss->sets = newtree234(setcmp);
331     ss->todo_head = ss->todo_tail = NULL;
332     return ss;
333 }
334
335 /*
336  * Take two input sets, in the form (x,y,mask). Munge the first by
337  * taking either its intersection with the second or its difference
338  * with the second. Return the new mask part of the first set.
339  */
340 static int setmunge(int x1, int y1, int mask1, int x2, int y2, int mask2,
341                     int diff)
342 {
343     /*
344      * Adjust the second set so that it has the same x,y
345      * coordinates as the first.
346      */
347     if (abs(x2-x1) >= 3 || abs(y2-y1) >= 3) {
348         mask2 = 0;
349     } else {
350         while (x2 > x1) {
351             mask2 &= ~(4|32|256);
352             mask2 <<= 1;
353             x2--;
354         }
355         while (x2 < x1) {
356             mask2 &= ~(1|8|64);
357             mask2 >>= 1;
358             x2++;
359         }
360         while (y2 > y1) {
361             mask2 &= ~(64|128|256);
362             mask2 <<= 3;
363             y2--;
364         }
365         while (y2 < y1) {
366             mask2 &= ~(1|2|4);
367             mask2 >>= 3;
368             y2++;
369         }
370     }
371
372     /*
373      * Invert the second set if `diff' is set (we're after A &~ B
374      * rather than A & B).
375      */
376     if (diff)
377         mask2 ^= 511;
378
379     /*
380      * Now all that's left is a logical AND.
381      */
382     return mask1 & mask2;
383 }
384
385 static void ss_add_todo(struct setstore *ss, struct set *s)
386 {
387     if (s->todo)
388         return;                        /* already on it */
389
390 #ifdef SOLVER_DIAGNOSTICS
391     printf("adding set on todo list: %d,%d %03x %d\n",
392            s->x, s->y, s->mask, s->mines);
393 #endif
394
395     s->prev = ss->todo_tail;
396     if (s->prev)
397         s->prev->next = s;
398     else
399         ss->todo_head = s;
400     ss->todo_tail = s;
401     s->next = NULL;
402     s->todo = TRUE;
403 }
404
405 static void ss_add(struct setstore *ss, int x, int y, int mask, int mines)
406 {
407     struct set *s;
408
409     assert(mask != 0);
410
411     /*
412      * Normalise so that x and y are genuinely the bounding
413      * rectangle.
414      */
415     while (!(mask & (1|8|64)))
416         mask >>= 1, x++;
417     while (!(mask & (1|2|4)))
418         mask >>= 3, y++;
419
420     /*
421      * Create a set structure and add it to the tree.
422      */
423     s = snew(struct set);
424     s->x = x;
425     s->y = y;
426     s->mask = mask;
427     s->mines = mines;
428     s->todo = FALSE;
429     if (add234(ss->sets, s) != s) {
430         /*
431          * This set already existed! Free it and return.
432          */
433         sfree(s);
434         return;
435     }
436
437     /*
438      * We've added a new set to the tree, so put it on the todo
439      * list.
440      */
441     ss_add_todo(ss, s);
442 }
443
444 static void ss_remove(struct setstore *ss, struct set *s)
445 {
446     struct set *next = s->next, *prev = s->prev;
447
448 #ifdef SOLVER_DIAGNOSTICS
449     printf("removing set %d,%d %03x\n", s->x, s->y, s->mask);
450 #endif
451     /*
452      * Remove s from the todo list.
453      */
454     if (prev)
455         prev->next = next;
456     else if (s == ss->todo_head)
457         ss->todo_head = next;
458
459     if (next)
460         next->prev = prev;
461     else if (s == ss->todo_tail)
462         ss->todo_tail = prev;
463
464     s->todo = FALSE;
465
466     /*
467      * Remove s from the tree.
468      */
469     del234(ss->sets, s);
470
471     /*
472      * Destroy the actual set structure.
473      */
474     sfree(s);
475 }
476
477 /*
478  * Return a dynamically allocated list of all the sets which
479  * overlap a provided input set.
480  */
481 static struct set **ss_overlap(struct setstore *ss, int x, int y, int mask)
482 {
483     struct set **ret = NULL;
484     int nret = 0, retsize = 0;
485     int xx, yy;
486
487     for (xx = x-3; xx < x+3; xx++)
488         for (yy = y-3; yy < y+3; yy++) {
489             struct set stmp, *s;
490             int pos;
491
492             /*
493              * Find the first set with these top left coordinates.
494              */
495             stmp.x = xx;
496             stmp.y = yy;
497             stmp.mask = 0;
498
499             if (findrelpos234(ss->sets, &stmp, NULL, REL234_GE, &pos)) {
500                 while ((s = index234(ss->sets, pos)) != NULL &&
501                        s->x == xx && s->y == yy) {
502                     /*
503                      * This set potentially overlaps the input one.
504                      * Compute the intersection to see if they
505                      * really overlap, and add it to the list if
506                      * so.
507                      */
508                     if (setmunge(x, y, mask, s->x, s->y, s->mask, FALSE)) {
509                         /*
510                          * There's an overlap.
511                          */
512                         if (nret >= retsize) {
513                             retsize = nret + 32;
514                             ret = sresize(ret, retsize, struct set *);
515                         }
516                         ret[nret++] = s;
517                     }
518
519                     pos++;
520                 }
521             }
522         }
523
524     ret = sresize(ret, nret+1, struct set *);
525     ret[nret] = NULL;
526
527     return ret;
528 }
529
530 /*
531  * Get an element from the head of the set todo list.
532  */
533 static struct set *ss_todo(struct setstore *ss)
534 {
535     if (ss->todo_head) {
536         struct set *ret = ss->todo_head;
537         ss->todo_head = ret->next;
538         if (ss->todo_head)
539             ss->todo_head->prev = NULL;
540         else
541             ss->todo_tail = NULL;
542         ret->next = ret->prev = NULL;
543         ret->todo = FALSE;
544         return ret;
545     } else {
546         return NULL;
547     }
548 }
549
550 struct squaretodo {
551     int *next;
552     int head, tail;
553 };
554
555 static void std_add(struct squaretodo *std, int i)
556 {
557     if (std->tail >= 0)
558         std->next[std->tail] = i;
559     else
560         std->head = i;
561     std->tail = i;
562     std->next[i] = -1;
563 }
564
565 typedef int (*open_cb)(void *, int, int);
566
567 static void known_squares(int w, int h, struct squaretodo *std,
568                           signed char *grid,
569                           open_cb open, void *openctx,
570                           int x, int y, int mask, int mine)
571 {
572     int xx, yy, bit;
573
574     bit = 1;
575
576     for (yy = 0; yy < 3; yy++)
577         for (xx = 0; xx < 3; xx++) {
578             if (mask & bit) {
579                 int i = (y + yy) * w + (x + xx);
580
581                 /*
582                  * It's possible that this square is _already_
583                  * known, in which case we don't try to add it to
584                  * the list twice.
585                  */
586                 if (grid[i] == -2) {
587
588                     if (mine) {
589                         grid[i] = -1;   /* and don't open it! */
590                     } else {
591                         grid[i] = open(openctx, x + xx, y + yy);
592                         assert(grid[i] != -1);   /* *bang* */
593                     }
594                     std_add(std, i);
595
596                 }
597             }
598             bit <<= 1;
599         }
600 }
601
602 /*
603  * This is data returned from the `perturb' function. It details
604  * which squares have become mines and which have become clear. The
605  * solver is (of course) expected to honourably not use that
606  * knowledge directly, but to efficently adjust its internal data
607  * structures and proceed based on only the information it
608  * legitimately has.
609  */
610 struct perturbation {
611     int x, y;
612     int delta;                         /* +1 == become a mine; -1 == cleared */
613 };
614 struct perturbations {
615     int n;
616     struct perturbation *changes;
617 };
618
619 /*
620  * Main solver entry point. You give it a grid of existing
621  * knowledge (-1 for a square known to be a mine, 0-8 for empty
622  * squares with a given number of neighbours, -2 for completely
623  * unknown), plus a function which you can call to open new squares
624  * once you're confident of them. It fills in as much more of the
625  * grid as it can.
626  * 
627  * Return value is:
628  * 
629  *  - -1 means deduction stalled and nothing could be done
630  *  - 0 means deduction succeeded fully
631  *  - >0 means deduction succeeded but some number of perturbation
632  *    steps were required; the exact return value is the number of
633  *    perturb calls.
634  */
635
636 typedef struct perturbations *(*perturb_cb) (void *, signed char *, int, int, int);
637
638 static int minesolve(int w, int h, int n, signed char *grid,
639                      open_cb open,
640                      perturb_cb perturb,
641                      void *ctx, random_state *rs)
642 {
643     struct setstore *ss = ss_new();
644     struct set **list;
645     struct squaretodo astd, *std = &astd;
646     int x, y, i, j;
647     int nperturbs = 0;
648
649     /*
650      * Set up a linked list of squares with known contents, so that
651      * we can process them one by one.
652      */
653     std->next = snewn(w*h, int);
654     std->head = std->tail = -1;
655
656     /*
657      * Initialise that list with all known squares in the input
658      * grid.
659      */
660     for (y = 0; y < h; y++) {
661         for (x = 0; x < w; x++) {
662             i = y*w+x;
663             if (grid[i] != -2)
664                 std_add(std, i);
665         }
666     }
667
668     /*
669      * Main deductive loop.
670      */
671     while (1) {
672         int done_something = FALSE;
673         struct set *s;
674
675         /*
676          * If there are any known squares on the todo list, process
677          * them and construct a set for each.
678          */
679         while (std->head != -1) {
680             i = std->head;
681 #ifdef SOLVER_DIAGNOSTICS
682             printf("known square at %d,%d [%d]\n", i%w, i/w, grid[i]);
683 #endif
684             std->head = std->next[i];
685             if (std->head == -1)
686                 std->tail = -1;
687
688             x = i % w;
689             y = i / w;
690
691             if (grid[i] >= 0) {
692                 int dx, dy, mines, bit, val;
693 #ifdef SOLVER_DIAGNOSTICS
694                 printf("creating set around this square\n");
695 #endif
696                 /*
697                  * Empty square. Construct the set of non-known squares
698                  * around this one, and determine its mine count.
699                  */
700                 mines = grid[i];
701                 bit = 1;
702                 val = 0;
703                 for (dy = -1; dy <= +1; dy++) {
704                     for (dx = -1; dx <= +1; dx++) {
705 #ifdef SOLVER_DIAGNOSTICS
706                         printf("grid %d,%d = %d\n", x+dx, y+dy, grid[i+dy*w+dx]);
707 #endif
708                         if (x+dx < 0 || x+dx >= w || y+dy < 0 || y+dy >= h)
709                             /* ignore this one */;
710                         else if (grid[i+dy*w+dx] == -1)
711                             mines--;
712                         else if (grid[i+dy*w+dx] == -2)
713                             val |= bit;
714                         bit <<= 1;
715                     }
716                 }
717                 if (val)
718                     ss_add(ss, x-1, y-1, val, mines);
719             }
720
721             /*
722              * Now, whether the square is empty or full, we must
723              * find any set which contains it and replace it with
724              * one which does not.
725              */
726             {
727 #ifdef SOLVER_DIAGNOSTICS
728                 printf("finding sets containing known square %d,%d\n", x, y);
729 #endif
730                 list = ss_overlap(ss, x, y, 1);
731
732                 for (j = 0; list[j]; j++) {
733                     int newmask, newmines;
734
735                     s = list[j];
736
737                     /*
738                      * Compute the mask for this set minus the
739                      * newly known square.
740                      */
741                     newmask = setmunge(s->x, s->y, s->mask, x, y, 1, TRUE);
742
743                     /*
744                      * Compute the new mine count.
745                      */
746                     newmines = s->mines - (grid[i] == -1);
747
748                     /*
749                      * Insert the new set into the collection,
750                      * unless it's been whittled right down to
751                      * nothing.
752                      */
753                     if (newmask)
754                         ss_add(ss, s->x, s->y, newmask, newmines);
755
756                     /*
757                      * Destroy the old one; it is actually obsolete.
758                      */
759                     ss_remove(ss, s);
760                 }
761
762                 sfree(list);
763             }
764
765             /*
766              * Marking a fresh square as known certainly counts as
767              * doing something.
768              */
769             done_something = TRUE;
770         }
771
772         /*
773          * Now pick a set off the to-do list and attempt deductions
774          * based on it.
775          */
776         if ((s = ss_todo(ss)) != NULL) {
777
778 #ifdef SOLVER_DIAGNOSTICS
779             printf("set to do: %d,%d %03x %d\n", s->x, s->y, s->mask, s->mines);
780 #endif
781             /*
782              * Firstly, see if this set has a mine count of zero or
783              * of its own cardinality.
784              */
785             if (s->mines == 0 || s->mines == bitcount16(s->mask)) {
786                 /*
787                  * If so, we can immediately mark all the squares
788                  * in the set as known.
789                  */
790 #ifdef SOLVER_DIAGNOSTICS
791                 printf("easy\n");
792 #endif
793                 known_squares(w, h, std, grid, open, ctx,
794                               s->x, s->y, s->mask, (s->mines != 0));
795
796                 /*
797                  * Having done that, we need do nothing further
798                  * with this set; marking all the squares in it as
799                  * known will eventually eliminate it, and will
800                  * also permit further deductions about anything
801                  * that overlaps it.
802                  */
803                 continue;
804             }
805
806             /*
807              * Failing that, we now search through all the sets
808              * which overlap this one.
809              */
810             list = ss_overlap(ss, s->x, s->y, s->mask);
811
812             for (j = 0; list[j]; j++) {
813                 struct set *s2 = list[j];
814                 int swing, s2wing, swc, s2wc;
815
816                 /*
817                  * Find the non-overlapping parts s2-s and s-s2,
818                  * and their cardinalities.
819                  * 
820                  * I'm going to refer to these parts as `wings'
821                  * surrounding the central part common to both
822                  * sets. The `s wing' is s-s2; the `s2 wing' is
823                  * s2-s.
824                  */
825                 swing = setmunge(s->x, s->y, s->mask, s2->x, s2->y, s2->mask,
826                                  TRUE);
827                 s2wing = setmunge(s2->x, s2->y, s2->mask, s->x, s->y, s->mask,
828                                  TRUE);
829                 swc = bitcount16(swing);
830                 s2wc = bitcount16(s2wing);
831
832                 /*
833                  * If one set has more mines than the other, and
834                  * the number of extra mines is equal to the
835                  * cardinality of that set's wing, then we can mark
836                  * every square in the wing as a known mine, and
837                  * every square in the other wing as known clear.
838                  */
839                 if (swc == s->mines - s2->mines ||
840                     s2wc == s2->mines - s->mines) {
841                     known_squares(w, h, std, grid, open, ctx,
842                                   s->x, s->y, swing,
843                                   (swc == s->mines - s2->mines));
844                     known_squares(w, h, std, grid, open, ctx,
845                                   s2->x, s2->y, s2wing,
846                                   (s2wc == s2->mines - s->mines));
847                     continue;
848                 }
849
850                 /*
851                  * Failing that, see if one set is a subset of the
852                  * other. If so, we can divide up the mine count of
853                  * the larger set between the smaller set and its
854                  * complement, even if neither smaller set ends up
855                  * being immediately clearable.
856                  */
857                 if (swc == 0 && s2wc != 0) {
858                     /* s is a subset of s2. */
859                     assert(s2->mines > s->mines);
860                     ss_add(ss, s2->x, s2->y, s2wing, s2->mines - s->mines);
861                 } else if (s2wc == 0 && swc != 0) {
862                     /* s2 is a subset of s. */
863                     assert(s->mines > s2->mines);
864                     ss_add(ss, s->x, s->y, swing, s->mines - s2->mines);
865                 }
866             }
867
868             sfree(list);
869
870             /*
871              * In this situation we have definitely done
872              * _something_, even if it's only reducing the size of
873              * our to-do list.
874              */
875             done_something = TRUE;
876         } else if (n >= 0) {
877             /*
878              * We have nothing left on our todo list, which means
879              * all localised deductions have failed. Our next step
880              * is to resort to global deduction based on the total
881              * mine count. This is computationally expensive
882              * compared to any of the above deductions, which is
883              * why we only ever do it when all else fails, so that
884              * hopefully it won't have to happen too often.
885              * 
886              * If you pass n<0 into this solver, that informs it
887              * that you do not know the total mine count, so it
888              * won't even attempt these deductions.
889              */
890
891             int minesleft, squaresleft;
892             int nsets, setused[10], cursor;
893
894             /*
895              * Start by scanning the current grid state to work out
896              * how many unknown squares we still have, and how many
897              * mines are to be placed in them.
898              */
899             squaresleft = 0;
900             minesleft = n;
901             for (i = 0; i < w*h; i++) {
902                 if (grid[i] == -1)
903                     minesleft--;
904                 else if (grid[i] == -2)
905                     squaresleft++;
906             }
907
908 #ifdef SOLVER_DIAGNOSTICS
909             printf("global deduction time: squaresleft=%d minesleft=%d\n",
910                    squaresleft, minesleft);
911             for (y = 0; y < h; y++) {
912                 for (x = 0; x < w; x++) {
913                     int v = grid[y*w+x];
914                     if (v == -1)
915                         putchar('*');
916                     else if (v == -2)
917                         putchar('?');
918                     else if (v == 0)
919                         putchar('-');
920                     else
921                         putchar('0' + v);
922                 }
923                 putchar('\n');
924             }
925 #endif
926
927             /*
928              * If there _are_ no unknown squares, we have actually
929              * finished.
930              */
931             if (squaresleft == 0) {
932                 assert(minesleft == 0);
933                 break;
934             }
935
936             /*
937              * First really simple case: if there are no more mines
938              * left, or if there are exactly as many mines left as
939              * squares to play them in, then it's all easy.
940              */
941             if (minesleft == 0 || minesleft == squaresleft) {
942                 for (i = 0; i < w*h; i++)
943                     if (grid[i] == -2)
944                         known_squares(w, h, std, grid, open, ctx,
945                                       i % w, i / w, 1, minesleft != 0);
946                 continue;              /* now go back to main deductive loop */
947             }
948
949             /*
950              * Failing that, we have to do some _real_ work.
951              * Ideally what we do here is to try every single
952              * combination of the currently available sets, in an
953              * attempt to find a disjoint union (i.e. a set of
954              * squares with a known mine count between them) such
955              * that the remaining unknown squares _not_ contained
956              * in that union either contain no mines or are all
957              * mines.
958              * 
959              * Actually enumerating all 2^n possibilities will get
960              * a bit slow for large n, so I artificially cap this
961              * recursion at n=10 to avoid too much pain.
962              */
963             nsets = count234(ss->sets);
964             if (nsets <= lenof(setused)) {
965                 /*
966                  * Doing this with actual recursive function calls
967                  * would get fiddly because a load of local
968                  * variables from this function would have to be
969                  * passed down through the recursion. So instead
970                  * I'm going to use a virtual recursion within this
971                  * function. The way this works is:
972                  * 
973                  *  - we have an array `setused', such that
974                  *    setused[n] is 0 or 1 depending on whether set
975                  *    n is currently in the union we are
976                  *    considering.
977                  * 
978                  *  - we have a value `cursor' which indicates how
979                  *    much of `setused' we have so far filled in.
980                  *    It's conceptually the recursion depth.
981                  * 
982                  * We begin by setting `cursor' to zero. Then:
983                  * 
984                  *  - if cursor can advance, we advance it by one.
985                  *    We set the value in `setused' that it went
986                  *    past to 1 if that set is disjoint from
987                  *    anything else currently in `setused', or to 0
988                  *    otherwise.
989                  * 
990                  *  - If cursor cannot advance because it has
991                  *    reached the end of the setused list, then we
992                  *    have a maximal disjoint union. Check to see
993                  *    whether its mine count has any useful
994                  *    properties. If so, mark all the squares not
995                  *    in the union as known and terminate.
996                  * 
997                  *  - If cursor has reached the end of setused and
998                  *    the algorithm _hasn't_ terminated, back
999                  *    cursor up to the nearest 1, turn it into a 0
1000                  *    and advance cursor just past it.
1001                  * 
1002                  *  - If we attempt to back up to the nearest 1 and
1003                  *    there isn't one at all, then we have gone
1004                  *    through all disjoint unions of sets in the
1005                  *    list and none of them has been helpful, so we
1006                  *    give up.
1007                  */
1008                 struct set *sets[lenof(setused)];
1009                 for (i = 0; i < nsets; i++)
1010                     sets[i] = index234(ss->sets, i);
1011
1012                 cursor = 0;
1013                 while (1) {
1014
1015                     if (cursor < nsets) {
1016                         int ok = TRUE;
1017
1018                         /* See if any existing set overlaps this one. */
1019                         for (i = 0; i < cursor; i++)
1020                             if (setused[i] &&
1021                                 setmunge(sets[cursor]->x,
1022                                          sets[cursor]->y,
1023                                          sets[cursor]->mask,
1024                                          sets[i]->x, sets[i]->y, sets[i]->mask,
1025                                          FALSE)) {
1026                                 ok = FALSE;
1027                                 break;
1028                             }
1029
1030                         if (ok) {
1031                             /*
1032                              * We're adding this set to our union,
1033                              * so adjust minesleft and squaresleft
1034                              * appropriately.
1035                              */
1036                             minesleft -= sets[cursor]->mines;
1037                             squaresleft -= bitcount16(sets[cursor]->mask);
1038                         }
1039
1040                         setused[cursor++] = ok;
1041                     } else {
1042 #ifdef SOLVER_DIAGNOSTICS
1043                         printf("trying a set combination with %d %d\n",
1044                                squaresleft, minesleft);
1045 #endif /* SOLVER_DIAGNOSTICS */
1046
1047                         /*
1048                          * We've reached the end. See if we've got
1049                          * anything interesting.
1050                          */
1051                         if (squaresleft > 0 &&
1052                             (minesleft == 0 || minesleft == squaresleft)) {
1053                             /*
1054                              * We have! There is at least one
1055                              * square not contained within the set
1056                              * union we've just found, and we can
1057                              * deduce that either all such squares
1058                              * are mines or all are not (depending
1059                              * on whether minesleft==0). So now all
1060                              * we have to do is actually go through
1061                              * the grid, find those squares, and
1062                              * mark them.
1063                              */
1064                             for (i = 0; i < w*h; i++)
1065                                 if (grid[i] == -2) {
1066                                     int outside = TRUE;
1067                                     y = i / w;
1068                                     x = i % w;
1069                                     for (j = 0; j < nsets; j++)
1070                                         if (setused[j] &&
1071                                             setmunge(sets[j]->x, sets[j]->y,
1072                                                      sets[j]->mask, x, y, 1,
1073                                                      FALSE)) {
1074                                             outside = FALSE;
1075                                             break;
1076                                         }
1077                                     if (outside)
1078                                         known_squares(w, h, std, grid,
1079                                                       open, ctx,
1080                                                       x, y, 1, minesleft != 0);
1081                                 }
1082
1083                             done_something = TRUE;
1084                             break;     /* return to main deductive loop */
1085                         }
1086
1087                         /*
1088                          * If we reach here, then this union hasn't
1089                          * done us any good, so move on to the
1090                          * next. Backtrack cursor to the nearest 1,
1091                          * change it to a 0 and continue.
1092                          */
1093                         while (--cursor >= 0 && !setused[cursor]);
1094                         if (cursor >= 0) {
1095                             assert(setused[cursor]);
1096
1097                             /*
1098                              * We're removing this set from our
1099                              * union, so re-increment minesleft and
1100                              * squaresleft.
1101                              */
1102                             minesleft += sets[cursor]->mines;
1103                             squaresleft += bitcount16(sets[cursor]->mask);
1104
1105                             setused[cursor++] = 0;
1106                         } else {
1107                             /*
1108                              * We've backtracked all the way to the
1109                              * start without finding a single 1,
1110                              * which means that our virtual
1111                              * recursion is complete and nothing
1112                              * helped.
1113                              */
1114                             break;
1115                         }
1116                     }
1117
1118                 }
1119
1120             }
1121         }
1122
1123         if (done_something)
1124             continue;
1125
1126 #ifdef SOLVER_DIAGNOSTICS
1127         /*
1128          * Dump the current known state of the grid.
1129          */
1130         printf("solver ran out of steam, ret=%d, grid:\n", nperturbs);
1131         for (y = 0; y < h; y++) {
1132             for (x = 0; x < w; x++) {
1133                 int v = grid[y*w+x];
1134                 if (v == -1)
1135                     putchar('*');
1136                 else if (v == -2)
1137                     putchar('?');
1138                 else if (v == 0)
1139                     putchar('-');
1140                 else
1141                     putchar('0' + v);
1142             }
1143             putchar('\n');
1144         }
1145
1146         {
1147             struct set *s;
1148
1149             for (i = 0; (s = index234(ss->sets, i)) != NULL; i++)
1150                 printf("remaining set: %d,%d %03x %d\n", s->x, s->y, s->mask, s->mines);
1151         }
1152 #endif
1153
1154         /*
1155          * Now we really are at our wits' end as far as solving
1156          * this grid goes. Our only remaining option is to call
1157          * a perturb function and ask it to modify the grid to
1158          * make it easier.
1159          */
1160         if (perturb) {
1161             struct perturbations *ret;
1162             struct set *s;
1163
1164             nperturbs++;
1165
1166             /*
1167              * Choose a set at random from the current selection,
1168              * and ask the perturb function to either fill or empty
1169              * it.
1170              * 
1171              * If we have no sets at all, we must give up.
1172              */
1173             if (count234(ss->sets) == 0) {
1174 #ifdef SOLVER_DIAGNOSTICS
1175                 printf("perturbing on entire unknown set\n");
1176 #endif
1177                 ret = perturb(ctx, grid, 0, 0, 0);
1178             } else {
1179                 s = index234(ss->sets, random_upto(rs, count234(ss->sets)));
1180 #ifdef SOLVER_DIAGNOSTICS
1181                 printf("perturbing on set %d,%d %03x\n", s->x, s->y, s->mask);
1182 #endif
1183                 ret = perturb(ctx, grid, s->x, s->y, s->mask);
1184             }
1185
1186             if (ret) {
1187                 assert(ret->n > 0);    /* otherwise should have been NULL */
1188
1189                 /*
1190                  * A number of squares have been fiddled with, and
1191                  * the returned structure tells us which. Adjust
1192                  * the mine count in any set which overlaps one of
1193                  * those squares, and put them back on the to-do
1194                  * list. Also, if the square itself is marked as a
1195                  * known non-mine, put it back on the squares-to-do
1196                  * list.
1197                  */
1198                 for (i = 0; i < ret->n; i++) {
1199 #ifdef SOLVER_DIAGNOSTICS
1200                     printf("perturbation %s mine at %d,%d\n",
1201                            ret->changes[i].delta > 0 ? "added" : "removed",
1202                            ret->changes[i].x, ret->changes[i].y);
1203 #endif
1204
1205                     if (ret->changes[i].delta < 0 &&
1206                         grid[ret->changes[i].y*w+ret->changes[i].x] != -2) {
1207                         std_add(std, ret->changes[i].y*w+ret->changes[i].x);
1208                     }
1209
1210                     list = ss_overlap(ss,
1211                                       ret->changes[i].x, ret->changes[i].y, 1);
1212
1213                     for (j = 0; list[j]; j++) {
1214                         list[j]->mines += ret->changes[i].delta;
1215                         ss_add_todo(ss, list[j]);
1216                     }
1217
1218                     sfree(list);
1219                 }
1220
1221                 /*
1222                  * Now free the returned data.
1223                  */
1224                 sfree(ret->changes);
1225                 sfree(ret);
1226
1227 #ifdef SOLVER_DIAGNOSTICS
1228                 /*
1229                  * Dump the current known state of the grid.
1230                  */
1231                 printf("state after perturbation:\n");
1232                 for (y = 0; y < h; y++) {
1233                     for (x = 0; x < w; x++) {
1234                         int v = grid[y*w+x];
1235                         if (v == -1)
1236                             putchar('*');
1237                         else if (v == -2)
1238                             putchar('?');
1239                         else if (v == 0)
1240                             putchar('-');
1241                         else
1242                             putchar('0' + v);
1243                     }
1244                     putchar('\n');
1245                 }
1246
1247                 {
1248                     struct set *s;
1249
1250                     for (i = 0; (s = index234(ss->sets, i)) != NULL; i++)
1251                         printf("remaining set: %d,%d %03x %d\n", s->x, s->y, s->mask, s->mines);
1252                 }
1253 #endif
1254
1255                 /*
1256                  * And now we can go back round the deductive loop.
1257                  */
1258                 continue;
1259             }
1260         }
1261
1262         /*
1263          * If we get here, even that didn't work (either we didn't
1264          * have a perturb function or it returned failure), so we
1265          * give up entirely.
1266          */
1267         break;
1268     }
1269
1270     /*
1271      * See if we've got any unknown squares left.
1272      */
1273     for (y = 0; y < h; y++)
1274         for (x = 0; x < w; x++)
1275             if (grid[y*w+x] == -2) {
1276                 nperturbs = -1;        /* failed to complete */
1277                 break;
1278             }
1279
1280     /*
1281      * Free the set list and square-todo list.
1282      */
1283     {
1284         struct set *s;
1285         while ((s = delpos234(ss->sets, 0)) != NULL)
1286             sfree(s);
1287         freetree234(ss->sets);
1288         sfree(ss);
1289         sfree(std->next);
1290     }
1291
1292     return nperturbs;
1293 }
1294
1295 /* ----------------------------------------------------------------------
1296  * Grid generator which uses the above solver.
1297  */
1298
1299 struct minectx {
1300     char *grid;
1301     int w, h;
1302     int sx, sy;
1303     int allow_big_perturbs;
1304     random_state *rs;
1305 };
1306
1307 static int mineopen(void *vctx, int x, int y)
1308 {
1309     struct minectx *ctx = (struct minectx *)vctx;
1310     int i, j, n;
1311
1312     assert(x >= 0 && x < ctx->w && y >= 0 && y < ctx->h);
1313     if (ctx->grid[y * ctx->w + x])
1314         return -1;                     /* *bang* */
1315
1316     n = 0;
1317     for (i = -1; i <= +1; i++) {
1318         if (x + i < 0 || x + i >= ctx->w)
1319             continue;
1320         for (j = -1; j <= +1; j++) {
1321             if (y + j < 0 || y + j >= ctx->h)
1322                 continue;
1323             if (i == 0 && j == 0)
1324                 continue;
1325             if (ctx->grid[(y+j) * ctx->w + (x+i)])
1326                 n++;
1327         }
1328     }
1329
1330     return n;
1331 }
1332
1333 /* Structure used internally to mineperturb(). */
1334 struct square {
1335     int x, y, type, random;
1336 };
1337 static int squarecmp(const void *av, const void *bv)
1338 {
1339     const struct square *a = (const struct square *)av;
1340     const struct square *b = (const struct square *)bv;
1341     if (a->type < b->type)
1342         return -1;
1343     else if (a->type > b->type)
1344         return +1;
1345     else if (a->random < b->random)
1346         return -1;
1347     else if (a->random > b->random)
1348         return +1;
1349     else if (a->y < b->y)
1350         return -1;
1351     else if (a->y > b->y)
1352         return +1;
1353     else if (a->x < b->x)
1354         return -1;
1355     else if (a->x > b->x)
1356         return +1;
1357     return 0;
1358 }
1359
1360 /*
1361  * Normally this function is passed an (x,y,mask) set description.
1362  * On occasions, though, there is no _localised_ set being used,
1363  * and the set being perturbed is supposed to be the entirety of
1364  * the unreachable area. This is signified by the special case
1365  * mask==0: in this case, anything labelled -2 in the grid is part
1366  * of the set.
1367  * 
1368  * Allowing perturbation in this special case appears to make it
1369  * guaranteeably possible to generate a workable grid for any mine
1370  * density, but they tend to be a bit boring, with mines packed
1371  * densely into far corners of the grid and the remainder being
1372  * less dense than one might like. Therefore, to improve overall
1373  * grid quality I disable this feature for the first few attempts,
1374  * and fall back to it after no useful grid has been generated.
1375  */
1376 static struct perturbations *mineperturb(void *vctx, signed char *grid,
1377                                          int setx, int sety, int mask)
1378 {
1379     struct minectx *ctx = (struct minectx *)vctx;
1380     struct square *sqlist;
1381     int x, y, dx, dy, i, n, nfull, nempty;
1382     struct square **tofill, **toempty, **todo;
1383     int ntofill, ntoempty, ntodo, dtodo, dset;
1384     struct perturbations *ret;
1385     int *setlist;
1386
1387     if (!mask && !ctx->allow_big_perturbs)
1388         return NULL;
1389
1390     /*
1391      * Make a list of all the squares in the grid which we can
1392      * possibly use. This list should be in preference order, which
1393      * means
1394      * 
1395      *  - first, unknown squares on the boundary of known space
1396      *  - next, unknown squares beyond that boundary
1397      *  - as a very last resort, known squares, but not within one
1398      *    square of the starting position.
1399      * 
1400      * Each of these sections needs to be shuffled independently.
1401      * We do this by preparing list of all squares and then sorting
1402      * it with a random secondary key.
1403      */
1404     sqlist = snewn(ctx->w * ctx->h, struct square);
1405     n = 0;
1406     for (y = 0; y < ctx->h; y++)
1407         for (x = 0; x < ctx->w; x++) {
1408             /*
1409              * If this square is too near the starting position,
1410              * don't put it on the list at all.
1411              */
1412             if (abs(y - ctx->sy) <= 1 && abs(x - ctx->sx) <= 1)
1413                 continue;
1414
1415             /*
1416              * If this square is in the input set, also don't put
1417              * it on the list!
1418              */
1419             if ((mask == 0 && grid[y*ctx->w+x] == -2) ||
1420                 (x >= setx && x < setx + 3 &&
1421                  y >= sety && y < sety + 3 &&
1422                  mask & (1 << ((y-sety)*3+(x-setx)))))
1423                 continue;
1424
1425             sqlist[n].x = x;
1426             sqlist[n].y = y;
1427
1428             if (grid[y*ctx->w+x] != -2) {
1429                 sqlist[n].type = 3;    /* known square */
1430             } else {
1431                 /*
1432                  * Unknown square. Examine everything around it and
1433                  * see if it borders on any known squares. If it
1434                  * does, it's class 1, otherwise it's 2.
1435                  */
1436
1437                 sqlist[n].type = 2;
1438
1439                 for (dy = -1; dy <= +1; dy++)
1440                     for (dx = -1; dx <= +1; dx++)
1441                         if (x+dx >= 0 && x+dx < ctx->w &&
1442                             y+dy >= 0 && y+dy < ctx->h &&
1443                             grid[(y+dy)*ctx->w+(x+dx)] != -2) {
1444                             sqlist[n].type = 1;
1445                             break;
1446                         }
1447             }
1448
1449             /*
1450              * Finally, a random number to cause qsort to
1451              * shuffle within each group.
1452              */
1453             sqlist[n].random = random_bits(ctx->rs, 31);
1454
1455             n++;
1456         }
1457
1458     qsort(sqlist, n, sizeof(struct square), squarecmp);
1459
1460     /*
1461      * Now count up the number of full and empty squares in the set
1462      * we've been provided.
1463      */
1464     nfull = nempty = 0;
1465     if (mask) {
1466         for (dy = 0; dy < 3; dy++)
1467             for (dx = 0; dx < 3; dx++)
1468                 if (mask & (1 << (dy*3+dx))) {
1469                     assert(setx+dx <= ctx->w);
1470                     assert(sety+dy <= ctx->h);
1471                     if (ctx->grid[(sety+dy)*ctx->w+(setx+dx)])
1472                         nfull++;
1473                     else
1474                         nempty++;
1475                 }
1476     } else {
1477         for (y = 0; y < ctx->h; y++)
1478             for (x = 0; x < ctx->w; x++)
1479                 if (grid[y*ctx->w+x] == -2) {
1480                     if (ctx->grid[y*ctx->w+x])
1481                         nfull++;
1482                     else
1483                         nempty++;
1484                 }
1485     }
1486
1487     /*
1488      * Now go through our sorted list until we find either `nfull'
1489      * empty squares, or `nempty' full squares; these will be
1490      * swapped with the appropriate squares in the set to either
1491      * fill or empty the set while keeping the same number of mines
1492      * overall.
1493      */
1494     ntofill = ntoempty = 0;
1495     if (mask) {
1496         tofill = snewn(9, struct square *);
1497         toempty = snewn(9, struct square *);
1498     } else {
1499         tofill = snewn(ctx->w * ctx->h, struct square *);
1500         toempty = snewn(ctx->w * ctx->h, struct square *);
1501     }
1502     for (i = 0; i < n; i++) {
1503         struct square *sq = &sqlist[i];
1504         if (ctx->grid[sq->y * ctx->w + sq->x])
1505             toempty[ntoempty++] = sq;
1506         else
1507             tofill[ntofill++] = sq;
1508         if (ntofill == nfull || ntoempty == nempty)
1509             break;
1510     }
1511
1512     /*
1513      * If we haven't found enough empty squares outside the set to
1514      * empty it into _or_ enough full squares outside it to fill it
1515      * up with, we'll have to settle for doing only a partial job.
1516      * In this case we choose to always _fill_ the set (because
1517      * this case will tend to crop up when we're working with very
1518      * high mine densities and the only way to get a solvable grid
1519      * is going to be to pack most of the mines solidly around the
1520      * edges). So now our job is to make a list of the empty
1521      * squares in the set, and shuffle that list so that we fill a
1522      * random selection of them.
1523      */
1524     if (ntofill != nfull && ntoempty != nempty) {
1525         int k;
1526
1527         assert(ntoempty != 0);
1528
1529         setlist = snewn(ctx->w * ctx->h, int);
1530         i = 0;
1531         if (mask) {
1532             for (dy = 0; dy < 3; dy++)
1533                 for (dx = 0; dx < 3; dx++)
1534                     if (mask & (1 << (dy*3+dx))) {
1535                         assert(setx+dx <= ctx->w);
1536                         assert(sety+dy <= ctx->h);
1537                         if (!ctx->grid[(sety+dy)*ctx->w+(setx+dx)])
1538                             setlist[i++] = (sety+dy)*ctx->w+(setx+dx);
1539                     }
1540         } else {
1541             for (y = 0; y < ctx->h; y++)
1542                 for (x = 0; x < ctx->w; x++)
1543                     if (grid[y*ctx->w+x] == -2) {
1544                         if (!ctx->grid[y*ctx->w+x])
1545                             setlist[i++] = y*ctx->w+x;
1546                     }
1547         }
1548         assert(i > ntoempty);
1549         /*
1550          * Now pick `ntoempty' items at random from the list.
1551          */
1552         for (k = 0; k < ntoempty; k++) {
1553             int index = k + random_upto(ctx->rs, i - k);
1554             int tmp;
1555
1556             tmp = setlist[k];
1557             setlist[k] = setlist[index];
1558             setlist[index] = tmp;
1559         }
1560     } else
1561         setlist = NULL;
1562
1563     /*
1564      * Now we're pretty much there. We need to either
1565      *  (a) put a mine in each of the empty squares in the set, and
1566      *      take one out of each square in `toempty'
1567      *  (b) take a mine out of each of the full squares in the set,
1568      *      and put one in each square in `tofill'
1569      * depending on which one we've found enough squares to do.
1570      * 
1571      * So we start by constructing our list of changes to return to
1572      * the solver, so that it can update its data structures
1573      * efficiently rather than having to rescan the whole grid.
1574      */
1575     ret = snew(struct perturbations);
1576     if (ntofill == nfull) {
1577         todo = tofill;
1578         ntodo = ntofill;
1579         dtodo = +1;
1580         dset = -1;
1581         sfree(toempty);
1582     } else {
1583         /*
1584          * (We also fall into this case if we've constructed a
1585          * setlist.)
1586          */
1587         todo = toempty;
1588         ntodo = ntoempty;
1589         dtodo = -1;
1590         dset = +1;
1591         sfree(tofill);
1592     }
1593     ret->n = 2 * ntodo;
1594     ret->changes = snewn(ret->n, struct perturbation);
1595     for (i = 0; i < ntodo; i++) {
1596         ret->changes[i].x = todo[i]->x;
1597         ret->changes[i].y = todo[i]->y;
1598         ret->changes[i].delta = dtodo;
1599     }
1600     /* now i == ntodo */
1601     if (setlist) {
1602         int j;
1603         assert(todo == toempty);
1604         for (j = 0; j < ntoempty; j++) {
1605             ret->changes[i].x = setlist[j] % ctx->w;
1606             ret->changes[i].y = setlist[j] / ctx->w;
1607             ret->changes[i].delta = dset;
1608             i++;
1609         }
1610         sfree(setlist);
1611     } else if (mask) {
1612         for (dy = 0; dy < 3; dy++)
1613             for (dx = 0; dx < 3; dx++)
1614                 if (mask & (1 << (dy*3+dx))) {
1615                     int currval = (ctx->grid[(sety+dy)*ctx->w+(setx+dx)] ? +1 : -1);
1616                     if (dset == -currval) {
1617                         ret->changes[i].x = setx + dx;
1618                         ret->changes[i].y = sety + dy;
1619                         ret->changes[i].delta = dset;
1620                         i++;
1621                     }
1622                 }
1623     } else {
1624         for (y = 0; y < ctx->h; y++)
1625             for (x = 0; x < ctx->w; x++)
1626                 if (grid[y*ctx->w+x] == -2) {
1627                     int currval = (ctx->grid[y*ctx->w+x] ? +1 : -1);
1628                     if (dset == -currval) {
1629                         ret->changes[i].x = x;
1630                         ret->changes[i].y = y;
1631                         ret->changes[i].delta = dset;
1632                         i++;
1633                     }
1634                 }
1635     }
1636     assert(i == ret->n);
1637
1638     sfree(sqlist);
1639     sfree(todo);
1640
1641     /*
1642      * Having set up the precise list of changes we're going to
1643      * make, we now simply make them and return.
1644      */
1645     for (i = 0; i < ret->n; i++) {
1646         int delta;
1647
1648         x = ret->changes[i].x;
1649         y = ret->changes[i].y;
1650         delta = ret->changes[i].delta;
1651
1652         /*
1653          * Check we're not trying to add an existing mine or remove
1654          * an absent one.
1655          */
1656         assert((delta < 0) ^ (ctx->grid[y*ctx->w+x] == 0));
1657
1658         /*
1659          * Actually make the change.
1660          */
1661         ctx->grid[y*ctx->w+x] = (delta > 0);
1662
1663         /*
1664          * Update any numbers already present in the grid.
1665          */
1666         for (dy = -1; dy <= +1; dy++)
1667             for (dx = -1; dx <= +1; dx++)
1668                 if (x+dx >= 0 && x+dx < ctx->w &&
1669                     y+dy >= 0 && y+dy < ctx->h &&
1670                     grid[(y+dy)*ctx->w+(x+dx)] != -2) {
1671                     if (dx == 0 && dy == 0) {
1672                         /*
1673                          * The square itself is marked as known in
1674                          * the grid. Mark it as a mine if it's a
1675                          * mine, or else work out its number.
1676                          */
1677                         if (delta > 0) {
1678                             grid[y*ctx->w+x] = -1;
1679                         } else {
1680                             int dx2, dy2, minecount = 0;
1681                             for (dy2 = -1; dy2 <= +1; dy2++)
1682                                 for (dx2 = -1; dx2 <= +1; dx2++)
1683                                     if (x+dx2 >= 0 && x+dx2 < ctx->w &&
1684                                         y+dy2 >= 0 && y+dy2 < ctx->h &&
1685                                         ctx->grid[(y+dy2)*ctx->w+(x+dx2)])
1686                                         minecount++;
1687                             grid[y*ctx->w+x] = minecount;
1688                         }
1689                     } else {
1690                         if (grid[(y+dy)*ctx->w+(x+dx)] >= 0)
1691                             grid[(y+dy)*ctx->w+(x+dx)] += delta;
1692                     }
1693                 }
1694     }
1695
1696 #ifdef GENERATION_DIAGNOSTICS
1697     {
1698         int yy, xx;
1699         printf("grid after perturbing:\n");
1700         for (yy = 0; yy < ctx->h; yy++) {
1701             for (xx = 0; xx < ctx->w; xx++) {
1702                 int v = ctx->grid[yy*ctx->w+xx];
1703                 if (yy == ctx->sy && xx == ctx->sx) {
1704                     assert(!v);
1705                     putchar('S');
1706                 } else if (v) {
1707                     putchar('*');
1708                 } else {
1709                     putchar('-');
1710                 }
1711             }
1712             putchar('\n');
1713         }
1714         printf("\n");
1715     }
1716 #endif
1717
1718     return ret;
1719 }
1720
1721 static char *minegen(int w, int h, int n, int x, int y, int unique,
1722                      random_state *rs)
1723 {
1724     char *ret = snewn(w*h, char);
1725     int success;
1726     int ntries = 0;
1727
1728     do {
1729         success = FALSE;
1730         ntries++;
1731
1732         memset(ret, 0, w*h);
1733
1734         /*
1735          * Start by placing n mines, none of which is at x,y or within
1736          * one square of it.
1737          */
1738         {
1739             int *tmp = snewn(w*h, int);
1740             int i, j, k, nn;
1741
1742             /*
1743              * Write down the list of possible mine locations.
1744              */
1745             k = 0;
1746             for (i = 0; i < h; i++)
1747                 for (j = 0; j < w; j++)
1748                     if (abs(i - y) > 1 || abs(j - x) > 1)
1749                         tmp[k++] = i*w+j;
1750
1751             /*
1752              * Now pick n off the list at random.
1753              */
1754             nn = n;
1755             while (nn-- > 0) {
1756                 i = random_upto(rs, k);
1757                 ret[tmp[i]] = 1;
1758                 tmp[i] = tmp[--k];
1759             }
1760
1761             sfree(tmp);
1762         }
1763
1764 #ifdef GENERATION_DIAGNOSTICS
1765         {
1766             int yy, xx;
1767             printf("grid after initial generation:\n");
1768             for (yy = 0; yy < h; yy++) {
1769                 for (xx = 0; xx < w; xx++) {
1770                     int v = ret[yy*w+xx];
1771                     if (yy == y && xx == x) {
1772                         assert(!v);
1773                         putchar('S');
1774                     } else if (v) {
1775                         putchar('*');
1776                     } else {
1777                         putchar('-');
1778                     }
1779                 }
1780                 putchar('\n');
1781             }
1782             printf("\n");
1783         }
1784 #endif
1785
1786         /*
1787          * Now set up a results grid to run the solver in, and a
1788          * context for the solver to open squares. Then run the solver
1789          * repeatedly; if the number of perturb steps ever goes up or
1790          * it ever returns -1, give up completely.
1791          *
1792          * We bypass this bit if we're not after a unique grid.
1793          */
1794         if (unique) {
1795             signed char *solvegrid = snewn(w*h, signed char);
1796             struct minectx actx, *ctx = &actx;
1797             int solveret, prevret = -2;
1798
1799             ctx->grid = ret;
1800             ctx->w = w;
1801             ctx->h = h;
1802             ctx->sx = x;
1803             ctx->sy = y;
1804             ctx->rs = rs;
1805             ctx->allow_big_perturbs = (ntries > 100);
1806
1807             while (1) {
1808                 memset(solvegrid, -2, w*h);
1809                 solvegrid[y*w+x] = mineopen(ctx, x, y);
1810                 assert(solvegrid[y*w+x] == 0); /* by deliberate arrangement */
1811
1812                 solveret =
1813                     minesolve(w, h, n, solvegrid, mineopen, mineperturb, ctx, rs);
1814                 if (solveret < 0 || (prevret >= 0 && solveret >= prevret)) {
1815                     success = FALSE;
1816                     break;
1817                 } else if (solveret == 0) {
1818                     success = TRUE;
1819                     break;
1820                 }
1821             }
1822
1823             sfree(solvegrid);
1824         } else {
1825             success = TRUE;
1826         }
1827
1828     } while (!success);
1829
1830     return ret;
1831 }
1832
1833 static char *describe_layout(char *grid, int area, int x, int y,
1834                              int obfuscate)
1835 {
1836     char *ret, *p;
1837     unsigned char *bmp;
1838     int i;
1839
1840     /*
1841      * Set up the mine bitmap and obfuscate it.
1842      */
1843     bmp = snewn((area + 7) / 8, unsigned char);
1844     memset(bmp, 0, (area + 7) / 8);
1845     for (i = 0; i < area; i++) {
1846         if (grid[i])
1847             bmp[i / 8] |= 0x80 >> (i % 8);
1848     }
1849     if (obfuscate)
1850         obfuscate_bitmap(bmp, area, FALSE);
1851
1852     /*
1853      * Now encode the resulting bitmap in hex. We can work to
1854      * nibble rather than byte granularity, since the obfuscation
1855      * function guarantees to return a bit string of the same
1856      * length as its input.
1857      */
1858     ret = snewn((area+3)/4 + 100, char);
1859     p = ret + sprintf(ret, "%d,%d,%s", x, y,
1860                       obfuscate ? "m" : "u");   /* 'm' == masked */
1861     for (i = 0; i < (area+3)/4; i++) {
1862         int v = bmp[i/2];
1863         if (i % 2 == 0)
1864             v >>= 4;
1865         *p++ = "0123456789abcdef"[v & 0xF];
1866     }
1867     *p = '\0';
1868
1869     sfree(bmp);
1870
1871     return ret;
1872 }
1873
1874 static char *new_mine_layout(int w, int h, int n, int x, int y, int unique,
1875                              random_state *rs, char **game_desc)
1876 {
1877     char *grid;
1878
1879 #ifdef TEST_OBFUSCATION
1880     static int tested_obfuscation = FALSE;
1881     if (!tested_obfuscation) {
1882         /*
1883          * A few simple test vectors for the obfuscator.
1884          * 
1885          * First test: the 28-bit stream 1234567. This divides up
1886          * into 1234 and 567[0]. The SHA of 56 70 30 (appending
1887          * "0") is 15ce8ab946640340bbb99f3f48fd2c45d1a31d30. Thus,
1888          * we XOR the 16-bit string 15CE into the input 1234 to get
1889          * 07FA. Next, we SHA that with "0": the SHA of 07 FA 30 is
1890          * 3370135c5e3da4fed937adc004a79533962b6391. So we XOR the
1891          * 12-bit string 337 into the input 567 to get 650. Thus
1892          * our output is 07FA650.
1893          */
1894         {
1895             unsigned char bmp1[] = "\x12\x34\x56\x70";
1896             obfuscate_bitmap(bmp1, 28, FALSE);
1897             printf("test 1 encode: %s\n",
1898                    memcmp(bmp1, "\x07\xfa\x65\x00", 4) ? "failed" : "passed");
1899             obfuscate_bitmap(bmp1, 28, TRUE);
1900             printf("test 1 decode: %s\n",
1901                    memcmp(bmp1, "\x12\x34\x56\x70", 4) ? "failed" : "passed");
1902         }
1903         /*
1904          * Second test: a long string to make sure we switch from
1905          * one SHA to the next correctly. My input string this time
1906          * is simply fifty bytes of zeroes.
1907          */
1908         {
1909             unsigned char bmp2[50];
1910             unsigned char bmp2a[50];
1911             memset(bmp2, 0, 50);
1912             memset(bmp2a, 0, 50);
1913             obfuscate_bitmap(bmp2, 50 * 8, FALSE);
1914             /*
1915              * SHA of twenty-five zero bytes plus "0" is
1916              * b202c07b990c01f6ff2d544707f60e506019b671. SHA of
1917              * twenty-five zero bytes plus "1" is
1918              * fcb1d8b5a2f6b592fe6780b36aa9d65dd7aa6db9. Thus our
1919              * first half becomes
1920              * b202c07b990c01f6ff2d544707f60e506019b671fcb1d8b5a2.
1921              * 
1922              * SHA of that lot plus "0" is
1923              * 10b0af913db85d37ca27f52a9f78bba3a80030db. SHA of the
1924              * same string plus "1" is
1925              * 3d01d8df78e76d382b8106f480135a1bc751d725. So the
1926              * second half becomes
1927              * 10b0af913db85d37ca27f52a9f78bba3a80030db3d01d8df78.
1928              */
1929             printf("test 2 encode: %s\n",
1930                    memcmp(bmp2, "\xb2\x02\xc0\x7b\x99\x0c\x01\xf6\xff\x2d\x54"
1931                           "\x47\x07\xf6\x0e\x50\x60\x19\xb6\x71\xfc\xb1\xd8"
1932                           "\xb5\xa2\x10\xb0\xaf\x91\x3d\xb8\x5d\x37\xca\x27"
1933                           "\xf5\x2a\x9f\x78\xbb\xa3\xa8\x00\x30\xdb\x3d\x01"
1934                           "\xd8\xdf\x78", 50) ? "failed" : "passed");
1935             obfuscate_bitmap(bmp2, 50 * 8, TRUE);
1936             printf("test 2 decode: %s\n",
1937                    memcmp(bmp2, bmp2a, 50) ? "failed" : "passed");
1938         }
1939     }
1940 #endif
1941
1942     grid = minegen(w, h, n, x, y, unique, rs);
1943
1944     if (game_desc)
1945         *game_desc = describe_layout(grid, w * h, x, y, TRUE);
1946
1947     return grid;
1948 }
1949
1950 static char *new_game_desc(game_params *params, random_state *rs,
1951                            char **aux, int interactive)
1952 {
1953     /*
1954      * We generate the coordinates of an initial click even if they
1955      * aren't actually used. This has the effect of harmonising the
1956      * random number usage between interactive and batch use: if
1957      * you use `mines --generate' with an explicit random seed, you
1958      * should get exactly the same results as if you type the same
1959      * random seed into the interactive game and click in the same
1960      * initial location. (Of course you won't get the same grid if
1961      * you click in a _different_ initial location, but there's
1962      * nothing to be done about that.)
1963      */
1964     int x = random_upto(rs, params->w);
1965     int y = random_upto(rs, params->h);
1966
1967     if (!interactive) {
1968         /*
1969          * For batch-generated grids, pre-open one square.
1970          */
1971         char *grid;
1972         char *desc;
1973
1974         grid = new_mine_layout(params->w, params->h, params->n,
1975                                x, y, params->unique, rs, &desc);
1976         sfree(grid);
1977         return desc;
1978     } else {
1979         char *rsdesc, *desc;
1980
1981         rsdesc = random_state_encode(rs);
1982         desc = snewn(strlen(rsdesc) + 100, char);
1983         sprintf(desc, "r%d,%c,%s", params->n, (char)(params->unique ? 'u' : 'a'), rsdesc);
1984         sfree(rsdesc);
1985         return desc;
1986     }
1987 }
1988
1989 static char *validate_desc(game_params *params, char *desc)
1990 {
1991     int wh = params->w * params->h;
1992     int x, y;
1993
1994     if (*desc == 'r') {
1995         desc++;
1996         if (!*desc || !isdigit((unsigned char)*desc))
1997             return "No initial mine count in game description";
1998         while (*desc && isdigit((unsigned char)*desc))
1999             desc++;                    /* skip over mine count */
2000         if (*desc != ',')
2001             return "No ',' after initial x-coordinate in game description";
2002         desc++;
2003         if (*desc != 'u' && *desc != 'a')
2004             return "No uniqueness specifier in game description";
2005         desc++;
2006         if (*desc != ',')
2007             return "No ',' after uniqueness specifier in game description";
2008         /* now ignore the rest */
2009     } else {
2010         if (*desc && isdigit((unsigned char)*desc)) {
2011             x = atoi(desc);
2012             if (x < 0 || x >= params->w)
2013                 return "Initial x-coordinate was out of range";
2014             while (*desc && isdigit((unsigned char)*desc))
2015                 desc++;                /* skip over x coordinate */
2016             if (*desc != ',')
2017                 return "No ',' after initial x-coordinate in game description";
2018             desc++;                    /* eat comma */
2019             if (!*desc || !isdigit((unsigned char)*desc))
2020                 return "No initial y-coordinate in game description";
2021             y = atoi(desc);
2022             if (y < 0 || y >= params->h)
2023                 return "Initial y-coordinate was out of range";
2024             while (*desc && isdigit((unsigned char)*desc))
2025                 desc++;                /* skip over y coordinate */
2026             if (*desc != ',')
2027                 return "No ',' after initial y-coordinate in game description";
2028             desc++;                    /* eat comma */
2029         }
2030         /* eat `m' for `masked' or `u' for `unmasked', if present */
2031         if (*desc == 'm' || *desc == 'u')
2032             desc++;
2033         /* now just check length of remainder */
2034         if (strlen(desc) != (wh+3)/4)
2035             return "Game description is wrong length";
2036     }
2037
2038     return NULL;
2039 }
2040
2041 static int open_square(game_state *state, int x, int y)
2042 {
2043     int w = state->w, h = state->h;
2044     int xx, yy, nmines, ncovered;
2045
2046     if (!state->layout->mines) {
2047         /*
2048          * We have a preliminary game in which the mine layout
2049          * hasn't been generated yet. Generate it based on the
2050          * initial click location.
2051          */
2052         char *desc, *privdesc;
2053         state->layout->mines = new_mine_layout(w, h, state->layout->n,
2054                                                x, y, state->layout->unique,
2055                                                state->layout->rs,
2056                                                &desc);
2057         /*
2058          * Find the trailing substring of the game description
2059          * corresponding to just the mine layout; we will use this
2060          * as our second `private' game ID for serialisation.
2061          */
2062         privdesc = desc;
2063         while (*privdesc && isdigit((unsigned char)*privdesc)) privdesc++;
2064         if (*privdesc == ',') privdesc++;
2065         while (*privdesc && isdigit((unsigned char)*privdesc)) privdesc++;
2066         if (*privdesc == ',') privdesc++;
2067         assert(*privdesc == 'm');
2068         midend_supersede_game_desc(state->layout->me, desc, privdesc);
2069         sfree(desc);
2070         random_free(state->layout->rs);
2071         state->layout->rs = NULL;
2072     }
2073
2074     if (state->layout->mines[y*w+x]) {
2075         /*
2076          * The player has landed on a mine. Bad luck. Expose the
2077          * mine that killed them, but not the rest (in case they
2078          * want to Undo and carry on playing).
2079          */
2080         state->dead = TRUE;
2081         state->grid[y*w+x] = 65;
2082         return -1;
2083     }
2084
2085     /*
2086      * Otherwise, the player has opened a safe square. Mark it to-do.
2087      */
2088     state->grid[y*w+x] = -10;          /* `todo' value internal to this func */
2089
2090     /*
2091      * Now go through the grid finding all `todo' values and
2092      * opening them. Every time one of them turns out to have no
2093      * neighbouring mines, we add all its unopened neighbours to
2094      * the list as well.
2095      * 
2096      * FIXME: We really ought to be able to do this better than
2097      * using repeated N^2 scans of the grid.
2098      */
2099     while (1) {
2100         int done_something = FALSE;
2101
2102         for (yy = 0; yy < h; yy++)
2103             for (xx = 0; xx < w; xx++)
2104                 if (state->grid[yy*w+xx] == -10) {
2105                     int dx, dy, v;
2106
2107                     assert(!state->layout->mines[yy*w+xx]);
2108
2109                     v = 0;
2110
2111                     for (dx = -1; dx <= +1; dx++)
2112                         for (dy = -1; dy <= +1; dy++)
2113                             if (xx+dx >= 0 && xx+dx < state->w &&
2114                                 yy+dy >= 0 && yy+dy < state->h &&
2115                                 state->layout->mines[(yy+dy)*w+(xx+dx)])
2116                                 v++;
2117
2118                     state->grid[yy*w+xx] = v;
2119
2120                     if (v == 0) {
2121                         for (dx = -1; dx <= +1; dx++)
2122                             for (dy = -1; dy <= +1; dy++)
2123                                 if (xx+dx >= 0 && xx+dx < state->w &&
2124                                     yy+dy >= 0 && yy+dy < state->h &&
2125                                     state->grid[(yy+dy)*w+(xx+dx)] == -2)
2126                                     state->grid[(yy+dy)*w+(xx+dx)] = -10;
2127                     }
2128
2129                     done_something = TRUE;
2130                 }
2131
2132         if (!done_something)
2133             break;
2134     }
2135
2136     /*
2137      * Finally, scan the grid and see if exactly as many squares
2138      * are still covered as there are mines. If so, set the `won'
2139      * flag and fill in mine markers on all covered squares.
2140      */
2141     nmines = ncovered = 0;
2142     for (yy = 0; yy < h; yy++)
2143         for (xx = 0; xx < w; xx++) {
2144             if (state->grid[yy*w+xx] < 0)
2145                 ncovered++;
2146             if (state->layout->mines[yy*w+xx])
2147                 nmines++;
2148         }
2149     assert(ncovered >= nmines);
2150     if (ncovered == nmines) {
2151         for (yy = 0; yy < h; yy++)
2152             for (xx = 0; xx < w; xx++) {
2153                 if (state->grid[yy*w+xx] < 0)
2154                     state->grid[yy*w+xx] = -1;
2155         }
2156         state->won = TRUE;
2157     }
2158
2159     return 0;
2160 }
2161
2162 static game_state *new_game(midend *me, game_params *params, char *desc)
2163 {
2164     game_state *state = snew(game_state);
2165     int i, wh, x, y, ret, masked;
2166     unsigned char *bmp;
2167
2168     state->w = params->w;
2169     state->h = params->h;
2170     state->n = params->n;
2171     state->dead = state->won = FALSE;
2172     state->used_solve = state->just_used_solve = FALSE;
2173
2174     wh = state->w * state->h;
2175
2176     state->layout = snew(struct mine_layout);
2177     memset(state->layout, 0, sizeof(struct mine_layout));
2178     state->layout->refcount = 1;
2179
2180     state->grid = snewn(wh, signed char);
2181     memset(state->grid, -2, wh);
2182
2183     if (*desc == 'r') {
2184         desc++;
2185         state->layout->n = atoi(desc);
2186         while (*desc && isdigit((unsigned char)*desc))
2187             desc++;                    /* skip over mine count */
2188         if (*desc) desc++;             /* eat comma */
2189         if (*desc == 'a')
2190             state->layout->unique = FALSE;
2191         else
2192             state->layout->unique = TRUE;
2193         desc++;
2194         if (*desc) desc++;             /* eat comma */
2195
2196         state->layout->mines = NULL;
2197         state->layout->rs = random_state_decode(desc);
2198         state->layout->me = me;
2199
2200     } else {
2201         state->layout->rs = NULL;
2202         state->layout->me = NULL;
2203         state->layout->mines = snewn(wh, char);
2204
2205         if (*desc && isdigit((unsigned char)*desc)) {
2206             x = atoi(desc);
2207             while (*desc && isdigit((unsigned char)*desc))
2208                 desc++;                /* skip over x coordinate */
2209             if (*desc) desc++;         /* eat comma */
2210             y = atoi(desc);
2211             while (*desc && isdigit((unsigned char)*desc))
2212                 desc++;                /* skip over y coordinate */
2213             if (*desc) desc++;         /* eat comma */
2214         } else {
2215             x = y = -1;
2216         }
2217
2218         if (*desc == 'm') {
2219             masked = TRUE;
2220             desc++;
2221         } else {
2222             if (*desc == 'u')
2223                 desc++;
2224             /*
2225              * We permit game IDs to be entered by hand without the
2226              * masking transformation.
2227              */
2228             masked = FALSE;
2229         }
2230
2231         bmp = snewn((wh + 7) / 8, unsigned char);
2232         memset(bmp, 0, (wh + 7) / 8);
2233         for (i = 0; i < (wh+3)/4; i++) {
2234             int c = desc[i];
2235             int v;
2236
2237             assert(c != 0);            /* validate_desc should have caught */
2238             if (c >= '0' && c <= '9')
2239                 v = c - '0';
2240             else if (c >= 'a' && c <= 'f')
2241                 v = c - 'a' + 10;
2242             else if (c >= 'A' && c <= 'F')
2243                 v = c - 'A' + 10;
2244             else
2245                 v = 0;
2246
2247             bmp[i / 2] |= v << (4 * (1 - (i % 2)));
2248         }
2249
2250         if (masked)
2251             obfuscate_bitmap(bmp, wh, TRUE);
2252
2253         memset(state->layout->mines, 0, wh);
2254         for (i = 0; i < wh; i++) {
2255             if (bmp[i / 8] & (0x80 >> (i % 8)))
2256                 state->layout->mines[i] = 1;
2257         }
2258
2259         if (x >= 0 && y >= 0)
2260             ret = open_square(state, x, y);
2261         sfree(bmp);
2262     }
2263
2264     return state;
2265 }
2266
2267 static game_state *dup_game(game_state *state)
2268 {
2269     game_state *ret = snew(game_state);
2270
2271     ret->w = state->w;
2272     ret->h = state->h;
2273     ret->n = state->n;
2274     ret->dead = state->dead;
2275     ret->won = state->won;
2276     ret->used_solve = state->used_solve;
2277     ret->just_used_solve = state->just_used_solve;
2278     ret->layout = state->layout;
2279     ret->layout->refcount++;
2280     ret->grid = snewn(ret->w * ret->h, signed char);
2281     memcpy(ret->grid, state->grid, ret->w * ret->h);
2282
2283     return ret;
2284 }
2285
2286 static void free_game(game_state *state)
2287 {
2288     if (--state->layout->refcount <= 0) {
2289         sfree(state->layout->mines);
2290         if (state->layout->rs)
2291             random_free(state->layout->rs);
2292         sfree(state->layout);
2293     }
2294     sfree(state->grid);
2295     sfree(state);
2296 }
2297
2298 static char *solve_game(game_state *state, game_state *currstate,
2299                         char *aux, char **error)
2300 {
2301     if (!state->layout->mines) {
2302         *error = "Game has not been started yet";
2303         return NULL;
2304     }
2305
2306     return dupstr("S");
2307 }
2308
2309 static char *game_text_format(game_state *state)
2310 {
2311     char *ret;
2312     int x, y;
2313
2314     ret = snewn((state->w + 1) * state->h + 1, char);
2315     for (y = 0; y < state->h; y++) {
2316         for (x = 0; x < state->w; x++) {
2317             int v = state->grid[y*state->w+x];
2318             if (v == 0)
2319                 v = '-';
2320             else if (v >= 1 && v <= 8)
2321                 v = '0' + v;
2322             else if (v == -1)
2323                 v = '*';
2324             else if (v == -2 || v == -3)
2325                 v = '?';
2326             else if (v >= 64)
2327                 v = '!';
2328             ret[y * (state->w+1) + x] = v;
2329         }
2330         ret[y * (state->w+1) + state->w] = '\n';
2331     }
2332     ret[(state->w + 1) * state->h] = '\0';
2333
2334     return ret;
2335 }
2336
2337 struct game_ui {
2338     int hx, hy, hradius;               /* for mouse-down highlights */
2339     int validradius;
2340     int flash_is_death;
2341     int deaths, completed;
2342 };
2343
2344 static game_ui *new_ui(game_state *state)
2345 {
2346     game_ui *ui = snew(game_ui);
2347     ui->hx = ui->hy = -1;
2348     ui->hradius = ui->validradius = 0;
2349     ui->deaths = 0;
2350     ui->completed = FALSE;
2351     ui->flash_is_death = FALSE;        /* *shrug* */
2352     return ui;
2353 }
2354
2355 static void free_ui(game_ui *ui)
2356 {
2357     sfree(ui);
2358 }
2359
2360 static char *encode_ui(game_ui *ui)
2361 {
2362     char buf[80];
2363     /*
2364      * The deaths counter and completion status need preserving
2365      * across a serialisation.
2366      */
2367     sprintf(buf, "D%d", ui->deaths);
2368     if (ui->completed)
2369         strcat(buf, "C");
2370     return dupstr(buf);
2371 }
2372
2373 static void decode_ui(game_ui *ui, char *encoding)
2374 {
2375     int p= 0;
2376     sscanf(encoding, "D%d%n", &ui->deaths, &p);
2377     if (encoding[p] == 'C')
2378         ui->completed = TRUE;
2379 }
2380
2381 static void game_changed_state(game_ui *ui, game_state *oldstate,
2382                                game_state *newstate)
2383 {
2384     if (newstate->won)
2385         ui->completed = TRUE;
2386 }
2387
2388 struct game_drawstate {
2389     int w, h, started, tilesize, bg;
2390     signed char *grid;
2391     /*
2392      * Items in this `grid' array have all the same values as in
2393      * the game_state grid, and in addition:
2394      * 
2395      *  - -10 means the tile was drawn `specially' as a result of a
2396      *    flash, so it will always need redrawing.
2397      * 
2398      *  - -22 and -23 mean the tile is highlighted for a possible
2399      *    click.
2400      */
2401 };
2402
2403 static char *interpret_move(game_state *from, game_ui *ui, game_drawstate *ds,
2404                             int x, int y, int button)
2405 {
2406     int cx, cy;
2407     char buf[256];
2408
2409     if (from->dead || from->won)
2410         return NULL;                   /* no further moves permitted */
2411
2412     if (!IS_MOUSE_DOWN(button) && !IS_MOUSE_DRAG(button) &&
2413         !IS_MOUSE_RELEASE(button))
2414         return NULL;
2415
2416     cx = FROMCOORD(x);
2417     cy = FROMCOORD(y);
2418
2419     if (button == LEFT_BUTTON || button == LEFT_DRAG ||
2420         button == MIDDLE_BUTTON || button == MIDDLE_DRAG) {
2421         if (cx < 0 || cx >= from->w || cy < 0 || cy >= from->h)
2422             return NULL;
2423
2424         /*
2425          * Mouse-downs and mouse-drags just cause highlighting
2426          * updates.
2427          */
2428         ui->hx = cx;
2429         ui->hy = cy;
2430         ui->hradius = (from->grid[cy*from->w+cx] >= 0 ? 1 : 0);
2431         if (button == LEFT_BUTTON)
2432             ui->validradius = ui->hradius;
2433         else if (button == MIDDLE_BUTTON)
2434             ui->validradius = 1;
2435         return "";
2436     }
2437
2438     if (button == RIGHT_BUTTON) {
2439         if (cx < 0 || cx >= from->w || cy < 0 || cy >= from->h)
2440             return NULL;
2441
2442         /*
2443          * Right-clicking only works on a covered square, and it
2444          * toggles between -1 (marked as mine) and -2 (not marked
2445          * as mine).
2446          *
2447          * FIXME: question marks.
2448          */
2449         if (from->grid[cy * from->w + cx] != -2 &&
2450             from->grid[cy * from->w + cx] != -1)
2451             return NULL;
2452
2453         sprintf(buf, "F%d,%d", cx, cy);
2454         return dupstr(buf);
2455     }
2456
2457     if (button == LEFT_RELEASE || button == MIDDLE_RELEASE) {
2458         ui->hx = ui->hy = -1;
2459         ui->hradius = 0;
2460
2461         /*
2462          * At this stage we must never return NULL: we have adjusted
2463          * the ui, so at worst we return "".
2464          */
2465         if (cx < 0 || cx >= from->w || cy < 0 || cy >= from->h)
2466             return "";
2467
2468         /*
2469          * Left-clicking on a covered square opens a tile. Not
2470          * permitted if the tile is marked as a mine, for safety.
2471          * (Unmark it and _then_ open it.)
2472          */
2473         if (button == LEFT_RELEASE &&
2474             (from->grid[cy * from->w + cx] == -2 ||
2475              from->grid[cy * from->w + cx] == -3) &&
2476             ui->validradius == 0) {
2477             /* Check if you've killed yourself. */
2478             if (from->layout->mines && from->layout->mines[cy * from->w + cx])
2479                 ui->deaths++;
2480
2481             sprintf(buf, "O%d,%d", cx, cy);
2482             return dupstr(buf);
2483         }
2484
2485         /*
2486          * Left-clicking or middle-clicking on an uncovered tile:
2487          * first we check to see if the number of mine markers
2488          * surrounding the tile is equal to its mine count, and if
2489          * so then we open all other surrounding squares.
2490          */
2491         if (from->grid[cy * from->w + cx] > 0 && ui->validradius == 1) {
2492             int dy, dx, n;
2493
2494             /* Count mine markers. */
2495             n = 0;
2496             for (dy = -1; dy <= +1; dy++)
2497                 for (dx = -1; dx <= +1; dx++)
2498                     if (cx+dx >= 0 && cx+dx < from->w &&
2499                         cy+dy >= 0 && cy+dy < from->h) {
2500                         if (from->grid[(cy+dy)*from->w+(cx+dx)] == -1)
2501                             n++;
2502                     }
2503
2504             if (n == from->grid[cy * from->w + cx]) {
2505
2506                 /*
2507                  * Now see if any of the squares we're clearing
2508                  * contains a mine (which will happen iff you've
2509                  * incorrectly marked the mines around the clicked
2510                  * square). If so, we open _just_ those squares, to
2511                  * reveal as little additional information as we
2512                  * can.
2513                  */
2514                 char *p = buf;
2515                 char *sep = "";
2516
2517                 for (dy = -1; dy <= +1; dy++)
2518                     for (dx = -1; dx <= +1; dx++)
2519                         if (cx+dx >= 0 && cx+dx < from->w &&
2520                             cy+dy >= 0 && cy+dy < from->h) {
2521                             if (from->grid[(cy+dy)*from->w+(cx+dx)] != -1 &&
2522                                 from->layout->mines &&
2523                                 from->layout->mines[(cy+dy)*from->w+(cx+dx)]) {
2524                                 p += sprintf(p, "%sO%d,%d", sep, cx+dx, cy+dy);
2525                                 sep = ";";
2526                             }
2527                         }
2528
2529                 if (p > buf) {
2530                     ui->deaths++;
2531                 } else {
2532                     sprintf(buf, "C%d,%d", cx, cy);
2533                 }
2534
2535                 return dupstr(buf);
2536             }
2537         }
2538
2539         return "";
2540     }
2541
2542     return NULL;
2543 }
2544
2545 static game_state *execute_move(game_state *from, char *move)
2546 {
2547     int cy, cx;
2548     game_state *ret;
2549
2550     if (!strcmp(move, "S")) {
2551         /*
2552          * Simply expose the entire grid as if it were a completed
2553          * solution.
2554          */
2555         int yy, xx;
2556
2557         ret = dup_game(from);
2558         for (yy = 0; yy < ret->h; yy++)
2559             for (xx = 0; xx < ret->w; xx++) {
2560
2561                 if (ret->layout->mines[yy*ret->w+xx]) {
2562                     ret->grid[yy*ret->w+xx] = -1;
2563                 } else {
2564                     int dx, dy, v;
2565
2566                     v = 0;
2567
2568                     for (dx = -1; dx <= +1; dx++)
2569                         for (dy = -1; dy <= +1; dy++)
2570                             if (xx+dx >= 0 && xx+dx < ret->w &&
2571                                 yy+dy >= 0 && yy+dy < ret->h &&
2572                                 ret->layout->mines[(yy+dy)*ret->w+(xx+dx)])
2573                                 v++;
2574
2575                     ret->grid[yy*ret->w+xx] = v;
2576                 }
2577             }
2578         ret->used_solve = ret->just_used_solve = TRUE;
2579         ret->won = TRUE;
2580
2581         return ret;
2582     } else {
2583         ret = dup_game(from);
2584         ret->just_used_solve = FALSE;
2585
2586         while (*move) {
2587             if (move[0] == 'F' &&
2588                 sscanf(move+1, "%d,%d", &cx, &cy) == 2 &&
2589                 cx >= 0 && cx < from->w && cy >= 0 && cy < from->h) {
2590                 ret->grid[cy * from->w + cx] ^= (-2 ^ -1);
2591             } else if (move[0] == 'O' &&
2592                        sscanf(move+1, "%d,%d", &cx, &cy) == 2 &&
2593                        cx >= 0 && cx < from->w && cy >= 0 && cy < from->h) {
2594                 open_square(ret, cx, cy);
2595             } else if (move[0] == 'C' &&
2596                        sscanf(move+1, "%d,%d", &cx, &cy) == 2 &&
2597                        cx >= 0 && cx < from->w && cy >= 0 && cy < from->h) {
2598                 int dx, dy;
2599
2600                 for (dy = -1; dy <= +1; dy++)
2601                     for (dx = -1; dx <= +1; dx++)
2602                         if (cx+dx >= 0 && cx+dx < ret->w &&
2603                             cy+dy >= 0 && cy+dy < ret->h &&
2604                             (ret->grid[(cy+dy)*ret->w+(cx+dx)] == -2 ||
2605                              ret->grid[(cy+dy)*ret->w+(cx+dx)] == -3))
2606                             open_square(ret, cx+dx, cy+dy);
2607             } else {
2608                 free_game(ret);
2609                 return NULL;
2610             }
2611
2612             while (*move && *move != ';') move++;
2613             if (*move) move++;
2614         }
2615
2616         return ret;
2617     }
2618 }
2619
2620 /* ----------------------------------------------------------------------
2621  * Drawing routines.
2622  */
2623
2624 static void game_compute_size(game_params *params, int tilesize,
2625                               int *x, int *y)
2626 {
2627     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
2628     struct { int tilesize; } ads, *ds = &ads;
2629     ads.tilesize = tilesize;
2630
2631     *x = BORDER * 2 + TILE_SIZE * params->w;
2632     *y = BORDER * 2 + TILE_SIZE * params->h;
2633 }
2634
2635 static void game_set_size(drawing *dr, game_drawstate *ds,
2636                           game_params *params, int tilesize)
2637 {
2638     ds->tilesize = tilesize;
2639 }
2640
2641 static float *game_colours(frontend *fe, int *ncolours)
2642 {
2643     float *ret = snewn(3 * NCOLOURS, float);
2644
2645     frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
2646
2647     ret[COL_BACKGROUND2 * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 19.0 / 20.0;
2648     ret[COL_BACKGROUND2 * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] * 19.0 / 20.0;
2649     ret[COL_BACKGROUND2 * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] * 19.0 / 20.0;
2650
2651     ret[COL_1 * 3 + 0] = 0.0F;
2652     ret[COL_1 * 3 + 1] = 0.0F;
2653     ret[COL_1 * 3 + 2] = 1.0F;
2654
2655     ret[COL_2 * 3 + 0] = 0.0F;
2656     ret[COL_2 * 3 + 1] = 0.5F;
2657     ret[COL_2 * 3 + 2] = 0.0F;
2658
2659     ret[COL_3 * 3 + 0] = 1.0F;
2660     ret[COL_3 * 3 + 1] = 0.0F;
2661     ret[COL_3 * 3 + 2] = 0.0F;
2662
2663     ret[COL_4 * 3 + 0] = 0.0F;
2664     ret[COL_4 * 3 + 1] = 0.0F;
2665     ret[COL_4 * 3 + 2] = 0.5F;
2666
2667     ret[COL_5 * 3 + 0] = 0.5F;
2668     ret[COL_5 * 3 + 1] = 0.0F;
2669     ret[COL_5 * 3 + 2] = 0.0F;
2670
2671     ret[COL_6 * 3 + 0] = 0.0F;
2672     ret[COL_6 * 3 + 1] = 0.5F;
2673     ret[COL_6 * 3 + 2] = 0.5F;
2674
2675     ret[COL_7 * 3 + 0] = 0.0F;
2676     ret[COL_7 * 3 + 1] = 0.0F;
2677     ret[COL_7 * 3 + 2] = 0.0F;
2678
2679     ret[COL_8 * 3 + 0] = 0.5F;
2680     ret[COL_8 * 3 + 1] = 0.5F;
2681     ret[COL_8 * 3 + 2] = 0.5F;
2682
2683     ret[COL_MINE * 3 + 0] = 0.0F;
2684     ret[COL_MINE * 3 + 1] = 0.0F;
2685     ret[COL_MINE * 3 + 2] = 0.0F;
2686
2687     ret[COL_BANG * 3 + 0] = 1.0F;
2688     ret[COL_BANG * 3 + 1] = 0.0F;
2689     ret[COL_BANG * 3 + 2] = 0.0F;
2690
2691     ret[COL_CROSS * 3 + 0] = 1.0F;
2692     ret[COL_CROSS * 3 + 1] = 0.0F;
2693     ret[COL_CROSS * 3 + 2] = 0.0F;
2694
2695     ret[COL_FLAG * 3 + 0] = 1.0F;
2696     ret[COL_FLAG * 3 + 1] = 0.0F;
2697     ret[COL_FLAG * 3 + 2] = 0.0F;
2698
2699     ret[COL_FLAGBASE * 3 + 0] = 0.0F;
2700     ret[COL_FLAGBASE * 3 + 1] = 0.0F;
2701     ret[COL_FLAGBASE * 3 + 2] = 0.0F;
2702
2703     ret[COL_QUERY * 3 + 0] = 0.0F;
2704     ret[COL_QUERY * 3 + 1] = 0.0F;
2705     ret[COL_QUERY * 3 + 2] = 0.0F;
2706
2707     ret[COL_HIGHLIGHT * 3 + 0] = 1.0F;
2708     ret[COL_HIGHLIGHT * 3 + 1] = 1.0F;
2709     ret[COL_HIGHLIGHT * 3 + 2] = 1.0F;
2710
2711     ret[COL_LOWLIGHT * 3 + 0] = ret[COL_BACKGROUND * 3 + 0] * 2.0 / 3.0;
2712     ret[COL_LOWLIGHT * 3 + 1] = ret[COL_BACKGROUND * 3 + 1] * 2.0 / 3.0;
2713     ret[COL_LOWLIGHT * 3 + 2] = ret[COL_BACKGROUND * 3 + 2] * 2.0 / 3.0;
2714
2715     *ncolours = NCOLOURS;
2716     return ret;
2717 }
2718
2719 static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
2720 {
2721     struct game_drawstate *ds = snew(struct game_drawstate);
2722
2723     ds->w = state->w;
2724     ds->h = state->h;
2725     ds->started = FALSE;
2726     ds->tilesize = 0;                  /* not decided yet */
2727     ds->grid = snewn(ds->w * ds->h, signed char);
2728     ds->bg = -1;
2729
2730     memset(ds->grid, -99, ds->w * ds->h);
2731
2732     return ds;
2733 }
2734
2735 static void game_free_drawstate(drawing *dr, game_drawstate *ds)
2736 {
2737     sfree(ds->grid);
2738     sfree(ds);
2739 }
2740
2741 static void draw_tile(drawing *dr, game_drawstate *ds,
2742                       int x, int y, int v, int bg)
2743 {
2744     if (v < 0) {
2745         int coords[12];
2746         int hl = 0;
2747
2748         if (v == -22 || v == -23) {
2749             v += 20;
2750
2751             /*
2752              * Omit the highlights in this case.
2753              */
2754             draw_rect(dr, x, y, TILE_SIZE, TILE_SIZE,
2755                       bg == COL_BACKGROUND ? COL_BACKGROUND2 : bg);
2756             draw_line(dr, x, y, x + TILE_SIZE - 1, y, COL_LOWLIGHT);
2757             draw_line(dr, x, y, x, y + TILE_SIZE - 1, COL_LOWLIGHT);
2758         } else {
2759             /*
2760              * Draw highlights to indicate the square is covered.
2761              */
2762             coords[0] = x + TILE_SIZE - 1;
2763             coords[1] = y + TILE_SIZE - 1;
2764             coords[2] = x + TILE_SIZE - 1;
2765             coords[3] = y;
2766             coords[4] = x;
2767             coords[5] = y + TILE_SIZE - 1;
2768             draw_polygon(dr, coords, 3, COL_LOWLIGHT ^ hl, COL_LOWLIGHT ^ hl);
2769
2770             coords[0] = x;
2771             coords[1] = y;
2772             draw_polygon(dr, coords, 3, COL_HIGHLIGHT ^ hl,
2773                          COL_HIGHLIGHT ^ hl);
2774
2775             draw_rect(dr, x + HIGHLIGHT_WIDTH, y + HIGHLIGHT_WIDTH,
2776                       TILE_SIZE - 2*HIGHLIGHT_WIDTH, TILE_SIZE - 2*HIGHLIGHT_WIDTH,
2777                       bg);
2778         }
2779
2780         if (v == -1) {
2781             /*
2782              * Draw a flag.
2783              */
2784 #define SETCOORD(n, dx, dy) do { \
2785     coords[(n)*2+0] = x + TILE_SIZE * (dx); \
2786     coords[(n)*2+1] = y + TILE_SIZE * (dy); \
2787 } while (0)
2788             SETCOORD(0, 0.6, 0.35);
2789             SETCOORD(1, 0.6, 0.7);
2790             SETCOORD(2, 0.8, 0.8);
2791             SETCOORD(3, 0.25, 0.8);
2792             SETCOORD(4, 0.55, 0.7);
2793             SETCOORD(5, 0.55, 0.35);
2794             draw_polygon(dr, coords, 6, COL_FLAGBASE, COL_FLAGBASE);
2795
2796             SETCOORD(0, 0.6, 0.2);
2797             SETCOORD(1, 0.6, 0.5);
2798             SETCOORD(2, 0.2, 0.35);
2799             draw_polygon(dr, coords, 3, COL_FLAG, COL_FLAG);
2800 #undef SETCOORD
2801
2802         } else if (v == -3) {
2803             /*
2804              * Draw a question mark.
2805              */
2806             draw_text(dr, x + TILE_SIZE / 2, y + TILE_SIZE / 2,
2807                       FONT_VARIABLE, TILE_SIZE * 6 / 8,
2808                       ALIGN_VCENTRE | ALIGN_HCENTRE,
2809                       COL_QUERY, "?");
2810         }
2811     } else {
2812         /*
2813          * Clear the square to the background colour, and draw thin
2814          * grid lines along the top and left.
2815          * 
2816          * Exception is that for value 65 (mine we've just trodden
2817          * on), we clear the square to COL_BANG.
2818          */
2819         draw_rect(dr, x, y, TILE_SIZE, TILE_SIZE,
2820                   (v == 65 ? COL_BANG :
2821                    bg == COL_BACKGROUND ? COL_BACKGROUND2 : bg));
2822         draw_line(dr, x, y, x + TILE_SIZE - 1, y, COL_LOWLIGHT);
2823         draw_line(dr, x, y, x, y + TILE_SIZE - 1, COL_LOWLIGHT);
2824
2825         if (v > 0 && v <= 8) {
2826             /*
2827              * Mark a number.
2828              */
2829             char str[2];
2830             str[0] = v + '0';
2831             str[1] = '\0';
2832             draw_text(dr, x + TILE_SIZE / 2, y + TILE_SIZE / 2,
2833                       FONT_VARIABLE, TILE_SIZE * 7 / 8,
2834                       ALIGN_VCENTRE | ALIGN_HCENTRE,
2835                       (COL_1 - 1) + v, str);
2836
2837         } else if (v >= 64) {
2838             /*
2839              * Mark a mine.
2840              * 
2841              * FIXME: this could be done better!
2842              */
2843 #if 0
2844             draw_text(dr, x + TILE_SIZE / 2, y + TILE_SIZE / 2,
2845                       FONT_VARIABLE, TILE_SIZE * 7 / 8,
2846                       ALIGN_VCENTRE | ALIGN_HCENTRE,
2847                       COL_MINE, "*");
2848 #else
2849             {
2850                 int cx = x + TILE_SIZE / 2;
2851                 int cy = y + TILE_SIZE / 2;
2852                 int r = TILE_SIZE / 2 - 3;
2853                 int coords[4*5*2];
2854                 int xdx = 1, xdy = 0, ydx = 0, ydy = 1;
2855                 int tdx, tdy, i;
2856
2857                 for (i = 0; i < 4*5*2; i += 5*2) {
2858                     coords[i+2*0+0] = cx - r/6*xdx + r*4/5*ydx;
2859                     coords[i+2*0+1] = cy - r/6*xdy + r*4/5*ydy;
2860                     coords[i+2*1+0] = cx - r/6*xdx + r*ydx;
2861                     coords[i+2*1+1] = cy - r/6*xdy + r*ydy;
2862                     coords[i+2*2+0] = cx + r/6*xdx + r*ydx;
2863                     coords[i+2*2+1] = cy + r/6*xdy + r*ydy;
2864                     coords[i+2*3+0] = cx + r/6*xdx + r*4/5*ydx;
2865                     coords[i+2*3+1] = cy + r/6*xdy + r*4/5*ydy;
2866                     coords[i+2*4+0] = cx + r*3/5*xdx + r*3/5*ydx;
2867                     coords[i+2*4+1] = cy + r*3/5*xdy + r*3/5*ydy;
2868
2869                     tdx = ydx;
2870                     tdy = ydy;
2871                     ydx = xdx;
2872                     ydy = xdy;
2873                     xdx = -tdx;
2874                     xdy = -tdy;
2875                 }
2876
2877                 draw_polygon(dr, coords, 5*4, COL_MINE, COL_MINE);
2878
2879                 draw_rect(dr, cx-r/3, cy-r/3, r/3, r/4, COL_HIGHLIGHT);
2880             }
2881 #endif
2882
2883             if (v == 66) {
2884                 /*
2885                  * Cross through the mine.
2886                  */
2887                 int dx;
2888                 for (dx = -1; dx <= +1; dx++) {
2889                     draw_line(dr, x + 3 + dx, y + 2,
2890                               x + TILE_SIZE - 3 + dx,
2891                               y + TILE_SIZE - 2, COL_CROSS);
2892                     draw_line(dr, x + TILE_SIZE - 3 + dx, y + 2,
2893                               x + 3 + dx, y + TILE_SIZE - 2,
2894                               COL_CROSS);
2895                 }
2896             }
2897         }
2898     }
2899
2900     draw_update(dr, x, y, TILE_SIZE, TILE_SIZE);
2901 }
2902
2903 static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
2904                         game_state *state, int dir, game_ui *ui,
2905                         float animtime, float flashtime)
2906 {
2907     int x, y;
2908     int mines, markers, bg;
2909
2910     if (flashtime) {
2911         int frame = (flashtime / FLASH_FRAME);
2912         if (frame % 2)
2913             bg = (ui->flash_is_death ? COL_BACKGROUND : COL_LOWLIGHT);
2914         else
2915             bg = (ui->flash_is_death ? COL_BANG : COL_HIGHLIGHT);
2916     } else
2917         bg = COL_BACKGROUND;
2918
2919     if (!ds->started) {
2920         int coords[10];
2921
2922         draw_rect(dr, 0, 0,
2923                   TILE_SIZE * state->w + 2 * BORDER,
2924                   TILE_SIZE * state->h + 2 * BORDER, COL_BACKGROUND);
2925         draw_update(dr, 0, 0,
2926                     TILE_SIZE * state->w + 2 * BORDER,
2927                     TILE_SIZE * state->h + 2 * BORDER);
2928
2929         /*
2930          * Recessed area containing the whole puzzle.
2931          */
2932         coords[0] = COORD(state->w) + OUTER_HIGHLIGHT_WIDTH - 1;
2933         coords[1] = COORD(state->h) + OUTER_HIGHLIGHT_WIDTH - 1;
2934         coords[2] = COORD(state->w) + OUTER_HIGHLIGHT_WIDTH - 1;
2935         coords[3] = COORD(0) - OUTER_HIGHLIGHT_WIDTH;
2936         coords[4] = coords[2] - TILE_SIZE;
2937         coords[5] = coords[3] + TILE_SIZE;
2938         coords[8] = COORD(0) - OUTER_HIGHLIGHT_WIDTH;
2939         coords[9] = COORD(state->h) + OUTER_HIGHLIGHT_WIDTH - 1;
2940         coords[6] = coords[8] + TILE_SIZE;
2941         coords[7] = coords[9] - TILE_SIZE;
2942         draw_polygon(dr, coords, 5, COL_HIGHLIGHT, COL_HIGHLIGHT);
2943
2944         coords[1] = COORD(0) - OUTER_HIGHLIGHT_WIDTH;
2945         coords[0] = COORD(0) - OUTER_HIGHLIGHT_WIDTH;
2946         draw_polygon(dr, coords, 5, COL_LOWLIGHT, COL_LOWLIGHT);
2947
2948         ds->started = TRUE;
2949     }
2950
2951     /*
2952      * Now draw the tiles. Also in this loop, count up the number
2953      * of mines and mine markers.
2954      */
2955     mines = markers = 0;
2956     for (y = 0; y < ds->h; y++)
2957         for (x = 0; x < ds->w; x++) {
2958             int v = state->grid[y*ds->w+x];
2959
2960             if (v == -1)
2961                 markers++;
2962             if (state->layout->mines && state->layout->mines[y*ds->w+x])
2963                 mines++;
2964
2965             if ((v == -2 || v == -3) &&
2966                 (abs(x-ui->hx) <= ui->hradius && abs(y-ui->hy) <= ui->hradius))
2967                 v -= 20;
2968
2969             if (ds->grid[y*ds->w+x] != v || bg != ds->bg) {
2970                 draw_tile(dr, ds, COORD(x), COORD(y), v, bg);
2971                 ds->grid[y*ds->w+x] = v;
2972             }
2973         }
2974     ds->bg = bg;
2975
2976     if (!state->layout->mines)
2977         mines = state->layout->n;
2978
2979     /*
2980      * Update the status bar.
2981      */
2982     {
2983         char statusbar[512];
2984         if (state->dead) {
2985             sprintf(statusbar, "DEAD!");
2986         } else if (state->won) {
2987             if (state->used_solve)
2988                 sprintf(statusbar, "Auto-solved.");
2989             else
2990                 sprintf(statusbar, "COMPLETED!");
2991         } else {
2992             sprintf(statusbar, "Marked: %d / %d", markers, mines);
2993         }
2994         if (ui->deaths)
2995             sprintf(statusbar + strlen(statusbar),
2996                     "  Deaths: %d", ui->deaths);
2997         status_bar(dr, statusbar);
2998     }
2999 }
3000
3001 static float game_anim_length(game_state *oldstate, game_state *newstate,
3002                               int dir, game_ui *ui)
3003 {
3004     return 0.0F;
3005 }
3006
3007 static float game_flash_length(game_state *oldstate, game_state *newstate,
3008                                int dir, game_ui *ui)
3009 {
3010     if (oldstate->used_solve || newstate->used_solve)
3011         return 0.0F;
3012
3013     if (dir > 0 && !oldstate->dead && !oldstate->won) {
3014         if (newstate->dead) {
3015             ui->flash_is_death = TRUE;
3016             return 3 * FLASH_FRAME;
3017         }
3018         if (newstate->won) {
3019             ui->flash_is_death = FALSE;
3020             return 2 * FLASH_FRAME;
3021         }
3022     }
3023     return 0.0F;
3024 }
3025
3026 static int game_wants_statusbar(void)
3027 {
3028     return TRUE;
3029 }
3030
3031 static int game_timing_state(game_state *state, game_ui *ui)
3032 {
3033     if (state->dead || state->won || ui->completed || !state->layout->mines)
3034         return FALSE;
3035     return TRUE;
3036 }
3037
3038 static void game_print_size(game_params *params, float *x, float *y)
3039 {
3040 }
3041
3042 static void game_print(drawing *dr, game_state *state, int tilesize)
3043 {
3044 }
3045
3046 #ifdef COMBINED
3047 #define thegame mines
3048 #endif
3049
3050 const struct game thegame = {
3051     "Mines", "games.mines",
3052     default_params,
3053     game_fetch_preset,
3054     decode_params,
3055     encode_params,
3056     free_params,
3057     dup_params,
3058     TRUE, game_configure, custom_params,
3059     validate_params,
3060     new_game_desc,
3061     validate_desc,
3062     new_game,
3063     dup_game,
3064     free_game,
3065     TRUE, solve_game,
3066     TRUE, game_text_format,
3067     new_ui,
3068     free_ui,
3069     encode_ui,
3070     decode_ui,
3071     game_changed_state,
3072     interpret_move,
3073     execute_move,
3074     PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
3075     game_colours,
3076     game_new_drawstate,
3077     game_free_drawstate,
3078     game_redraw,
3079     game_anim_length,
3080     game_flash_length,
3081     FALSE, FALSE, game_print_size, game_print,
3082     game_wants_statusbar,
3083     TRUE, game_timing_state,
3084     BUTTON_BEATS(LEFT_BUTTON, RIGHT_BUTTON),
3085 };
3086
3087 #ifdef STANDALONE_OBFUSCATOR
3088
3089 /*
3090  * Vaguely useful stand-alone program which translates between
3091  * obfuscated and clear Mines game descriptions. Pass in a game
3092  * description on the command line, and if it's clear it will be
3093  * obfuscated and vice versa. The output text should also be a
3094  * valid game ID describing the same game. Like this:
3095  *
3096  * $ ./mineobfusc 9x9:4,4,mb071b49fbd1cb6a0d5868
3097  * 9x9:4,4,004000007c00010022080
3098  * $ ./mineobfusc 9x9:4,4,004000007c00010022080
3099  * 9x9:4,4,mb071b49fbd1cb6a0d5868
3100  */
3101
3102 int main(int argc, char **argv)
3103 {
3104     game_params *p;
3105     game_state *s;
3106     char *id = NULL, *desc, *err;
3107     int y, x;
3108
3109     while (--argc > 0) {
3110         char *p = *++argv;
3111         if (*p == '-') {
3112             fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
3113             return 1;
3114         } else {
3115             id = p;
3116         }
3117     }
3118
3119     if (!id) {
3120         fprintf(stderr, "usage: %s <game_id>\n", argv[0]);
3121         return 1;
3122     }
3123
3124     desc = strchr(id, ':');
3125     if (!desc) {
3126         fprintf(stderr, "%s: game id expects a colon in it\n", argv[0]);
3127         return 1;
3128     }
3129     *desc++ = '\0';
3130
3131     p = default_params();
3132     decode_params(p, id);
3133     err = validate_desc(p, desc);
3134     if (err) {
3135         fprintf(stderr, "%s: %s\n", argv[0], err);
3136         return 1;
3137     }
3138     s = new_game(NULL, p, desc);
3139
3140     x = atoi(desc);
3141     while (*desc && *desc != ',') desc++;
3142     if (*desc) desc++;
3143     y = atoi(desc);
3144     while (*desc && *desc != ',') desc++;
3145     if (*desc) desc++;
3146
3147     printf("%s:%s\n", id, describe_layout(s->layout->mines,
3148                                           p->w * p->h,
3149                                           x, y,
3150                                           (*desc != 'm')));
3151
3152     return 0;
3153 }
3154
3155 #endif