chiark / gitweb /
Pattern: add a system of immutable pre-filled grid squares.
[sgt-puzzles.git] / pattern.c
1 /*
2  * pattern.c: the pattern-reconstruction game known as `nonograms'.
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <assert.h>
9 #include <ctype.h>
10 #include <math.h>
11
12 #include "puzzles.h"
13
14 enum {
15     COL_BACKGROUND,
16     COL_EMPTY,
17     COL_FULL,
18     COL_TEXT,
19     COL_UNKNOWN,
20     COL_GRID,
21     COL_CURSOR,
22     COL_ERROR,
23     NCOLOURS
24 };
25
26 #define PREFERRED_TILE_SIZE 24
27 #define TILE_SIZE (ds->tilesize)
28 #define BORDER (3 * TILE_SIZE / 4)
29 #define TLBORDER(d) ( (d) / 5 + 2 )
30 #define GUTTER (TILE_SIZE / 2)
31
32 #define FROMCOORD(d, x) \
33         ( ((x) - (BORDER + GUTTER + TILE_SIZE * TLBORDER(d))) / TILE_SIZE )
34
35 #define SIZE(d) (2*BORDER + GUTTER + TILE_SIZE * (TLBORDER(d) + (d)))
36 #define GETTILESIZE(d, w) ((double)w / (2.0 + (double)TLBORDER(d) + (double)(d)))
37
38 #define TOCOORD(d, x) (BORDER + GUTTER + TILE_SIZE * (TLBORDER(d) + (x)))
39
40 struct game_params {
41     int w, h;
42 };
43
44 #define GRID_UNKNOWN 2
45 #define GRID_FULL 1
46 #define GRID_EMPTY 0
47
48 typedef struct game_state_common {
49     /* Parts of the game state that don't change during play. */
50     int w, h;
51     int rowsize;
52     int *rowdata, *rowlen;
53     unsigned char *immutable;
54     int refcount;
55 } game_state_common;
56
57 struct game_state {
58     game_state_common *common;
59     unsigned char *grid;
60     int completed, cheated;
61 };
62
63 #define FLASH_TIME 0.13F
64
65 static game_params *default_params(void)
66 {
67     game_params *ret = snew(game_params);
68
69     ret->w = ret->h = 15;
70
71     return ret;
72 }
73
74 static const struct game_params pattern_presets[] = {
75     {10, 10},
76     {15, 15},
77     {20, 20},
78 #ifndef SLOW_SYSTEM
79     {25, 25},
80     {30, 30},
81 #endif
82 };
83
84 static int game_fetch_preset(int i, char **name, game_params **params)
85 {
86     game_params *ret;
87     char str[80];
88
89     if (i < 0 || i >= lenof(pattern_presets))
90         return FALSE;
91
92     ret = snew(game_params);
93     *ret = pattern_presets[i];
94
95     sprintf(str, "%dx%d", ret->w, ret->h);
96
97     *name = dupstr(str);
98     *params = ret;
99     return TRUE;
100 }
101
102 static void free_params(game_params *params)
103 {
104     sfree(params);
105 }
106
107 static game_params *dup_params(const game_params *params)
108 {
109     game_params *ret = snew(game_params);
110     *ret = *params;                    /* structure copy */
111     return ret;
112 }
113
114 static void decode_params(game_params *ret, char const *string)
115 {
116     char const *p = string;
117
118     ret->w = atoi(p);
119     while (*p && isdigit((unsigned char)*p)) p++;
120     if (*p == 'x') {
121         p++;
122         ret->h = atoi(p);
123         while (*p && isdigit((unsigned char)*p)) p++;
124     } else {
125         ret->h = ret->w;
126     }
127 }
128
129 static char *encode_params(const game_params *params, int full)
130 {
131     char ret[400];
132     int len;
133
134     len = sprintf(ret, "%dx%d", params->w, params->h);
135     assert(len < lenof(ret));
136     ret[len] = '\0';
137
138     return dupstr(ret);
139 }
140
141 static config_item *game_configure(const game_params *params)
142 {
143     config_item *ret;
144     char buf[80];
145
146     ret = snewn(3, config_item);
147
148     ret[0].name = "Width";
149     ret[0].type = C_STRING;
150     sprintf(buf, "%d", params->w);
151     ret[0].sval = dupstr(buf);
152     ret[0].ival = 0;
153
154     ret[1].name = "Height";
155     ret[1].type = C_STRING;
156     sprintf(buf, "%d", params->h);
157     ret[1].sval = dupstr(buf);
158     ret[1].ival = 0;
159
160     ret[2].name = NULL;
161     ret[2].type = C_END;
162     ret[2].sval = NULL;
163     ret[2].ival = 0;
164
165     return ret;
166 }
167
168 static game_params *custom_params(const config_item *cfg)
169 {
170     game_params *ret = snew(game_params);
171
172     ret->w = atoi(cfg[0].sval);
173     ret->h = atoi(cfg[1].sval);
174
175     return ret;
176 }
177
178 static char *validate_params(const game_params *params, int full)
179 {
180     if (params->w <= 0 || params->h <= 0)
181         return "Width and height must both be greater than zero";
182     return NULL;
183 }
184
185 /* ----------------------------------------------------------------------
186  * Puzzle generation code.
187  * 
188  * For this particular puzzle, it seemed important to me to ensure
189  * a unique solution. I do this the brute-force way, by having a
190  * solver algorithm alongside the generator, and repeatedly
191  * generating a random grid until I find one whose solution is
192  * unique. It turns out that this isn't too onerous on a modern PC
193  * provided you keep grid size below around 30. Any offers of
194  * better algorithms, however, will be very gratefully received.
195  * 
196  * Another annoyance of this approach is that it limits the
197  * available puzzles to those solvable by the algorithm I've used.
198  * My algorithm only ever considers a single row or column at any
199  * one time, which means it's incapable of solving the following
200  * difficult example (found by Bella Image around 1995/6, when she
201  * and I were both doing maths degrees):
202  * 
203  *        2  1  2  1 
204  *
205  *      +--+--+--+--+
206  * 1 1  |  |  |  |  |
207  *      +--+--+--+--+
208  *   2  |  |  |  |  |
209  *      +--+--+--+--+
210  *   1  |  |  |  |  |
211  *      +--+--+--+--+
212  *   1  |  |  |  |  |
213  *      +--+--+--+--+
214  * 
215  * Obviously this cannot be solved by a one-row-or-column-at-a-time
216  * algorithm (it would require at least one row or column reading
217  * `2 1', `1 2', `3' or `4' to get started). However, it can be
218  * proved to have a unique solution: if the top left square were
219  * empty, then the only option for the top row would be to fill the
220  * two squares in the 1 columns, which would imply the squares
221  * below those were empty, leaving no place for the 2 in the second
222  * row. Contradiction. Hence the top left square is full, and the
223  * unique solution follows easily from that starting point.
224  * 
225  * (The game ID for this puzzle is 4x4:2/1/2/1/1.1/2/1/1 , in case
226  * it's useful to anyone.)
227  */
228
229 static int float_compare(const void *av, const void *bv)
230 {
231     const float *a = (const float *)av;
232     const float *b = (const float *)bv;
233     if (*a < *b)
234         return -1;
235     else if (*a > *b)
236         return +1;
237     else
238         return 0;
239 }
240
241 static void generate(random_state *rs, int w, int h, unsigned char *retgrid)
242 {
243     float *fgrid;
244     float *fgrid2;
245     int step, i, j;
246     float threshold;
247
248     fgrid = snewn(w*h, float);
249
250     for (i = 0; i < h; i++) {
251         for (j = 0; j < w; j++) {
252             fgrid[i*w+j] = random_upto(rs, 100000000UL) / 100000000.F;
253         }
254     }
255
256     /*
257      * The above gives a completely random splattering of black and
258      * white cells. We want to gently bias this in favour of _some_
259      * reasonably thick areas of white and black, while retaining
260      * some randomness and fine detail.
261      * 
262      * So we evolve the starting grid using a cellular automaton.
263      * Currently, I'm doing something very simple indeed, which is
264      * to set each square to the average of the surrounding nine
265      * cells (or the average of fewer, if we're on a corner).
266      */
267     for (step = 0; step < 1; step++) {
268         fgrid2 = snewn(w*h, float);
269
270         for (i = 0; i < h; i++) {
271             for (j = 0; j < w; j++) {
272                 float sx, xbar;
273                 int n, p, q;
274
275                 /*
276                  * Compute the average of the surrounding cells.
277                  */
278                 n = 0;
279                 sx = 0.F;
280                 for (p = -1; p <= +1; p++) {
281                     for (q = -1; q <= +1; q++) {
282                         if (i+p < 0 || i+p >= h || j+q < 0 || j+q >= w)
283                             continue;
284                         /*
285                          * An additional special case not mentioned
286                          * above: if a grid dimension is 2xn then
287                          * we do not average across that dimension
288                          * at all. Otherwise a 2x2 grid would
289                          * contain four identical squares.
290                          */
291                         if ((h==2 && p!=0) || (w==2 && q!=0))
292                             continue;
293                         n++;
294                         sx += fgrid[(i+p)*w+(j+q)];
295                     }
296                 }
297                 xbar = sx / n;
298
299                 fgrid2[i*w+j] = xbar;
300             }
301         }
302
303         sfree(fgrid);
304         fgrid = fgrid2;
305     }
306
307     fgrid2 = snewn(w*h, float);
308     memcpy(fgrid2, fgrid, w*h*sizeof(float));
309     qsort(fgrid2, w*h, sizeof(float), float_compare);
310     threshold = fgrid2[w*h/2];
311     sfree(fgrid2);
312
313     for (i = 0; i < h; i++) {
314         for (j = 0; j < w; j++) {
315             retgrid[i*w+j] = (fgrid[i*w+j] >= threshold ? GRID_FULL :
316                               GRID_EMPTY);
317         }
318     }
319
320     sfree(fgrid);
321 }
322
323 static int compute_rowdata(int *ret, unsigned char *start, int len, int step)
324 {
325     int i, n;
326
327     n = 0;
328
329     for (i = 0; i < len; i++) {
330         if (start[i*step] == GRID_FULL) {
331             int runlen = 1;
332             while (i+runlen < len && start[(i+runlen)*step] == GRID_FULL)
333                 runlen++;
334             ret[n++] = runlen;
335             i += runlen;
336         }
337
338         if (i < len && start[i*step] == GRID_UNKNOWN)
339             return -1;
340     }
341
342     return n;
343 }
344
345 #define UNKNOWN 0
346 #define BLOCK 1
347 #define DOT 2
348 #define STILL_UNKNOWN 3
349
350 #ifdef STANDALONE_SOLVER
351 int verbose = FALSE;
352 #endif
353
354 static int do_recurse(unsigned char *known, unsigned char *deduced,
355                        unsigned char *row,
356                        unsigned char *minpos_done, unsigned char *maxpos_done,
357                        unsigned char *minpos_ok, unsigned char *maxpos_ok,
358                        int *data, int len,
359                        int freespace, int ndone, int lowest)
360 {
361     int i, j, k;
362
363
364     /* This algorithm basically tries all possible ways the given rows of
365      * black blocks can be laid out in the row/column being examined.
366      * Special care is taken to avoid checking the tail of a row/column
367      * if the same conditions have already been checked during this recursion
368      * The algorithm also takes care to cut its losses as soon as an
369      * invalid (partial) solution is detected.
370      */
371     if (data[ndone]) {
372         if (lowest >= minpos_done[ndone] && lowest <= maxpos_done[ndone]) {
373             if (lowest >= minpos_ok[ndone] && lowest <= maxpos_ok[ndone]) {
374                 for (i=0; i<lowest; i++)
375                     deduced[i] |= row[i];
376             }
377             return lowest >= minpos_ok[ndone] && lowest <= maxpos_ok[ndone];
378         } else {
379             if (lowest < minpos_done[ndone]) minpos_done[ndone] = lowest;
380             if (lowest > maxpos_done[ndone]) maxpos_done[ndone] = lowest;
381         }
382         for (i=0; i<=freespace; i++) {
383             j = lowest;
384             for (k=0; k<i; k++) {
385                 if (known[j] == BLOCK) goto next_iter;
386                 row[j++] = DOT;
387             }
388             for (k=0; k<data[ndone]; k++) {
389                 if (known[j] == DOT) goto next_iter;
390                 row[j++] = BLOCK;
391             }
392             if (j < len) {
393                 if (known[j] == BLOCK) goto next_iter;
394                 row[j++] = DOT;
395             }
396             if (do_recurse(known, deduced, row, minpos_done, maxpos_done,
397                            minpos_ok, maxpos_ok, data, len, freespace-i, ndone+1, j)) {
398                 if (lowest < minpos_ok[ndone]) minpos_ok[ndone] = lowest;
399                 if (lowest + i > maxpos_ok[ndone]) maxpos_ok[ndone] = lowest + i;
400                 if (lowest + i > maxpos_done[ndone]) maxpos_done[ndone] = lowest + i;
401             }
402             next_iter:
403             j++;
404         }
405         return lowest >= minpos_ok[ndone] && lowest <= maxpos_ok[ndone];
406     } else {
407         for (i=lowest; i<len; i++) {
408             if (known[i] == BLOCK) return FALSE;
409             row[i] = DOT;
410             }
411         for (i=0; i<len; i++)
412             deduced[i] |= row[i];
413         return TRUE;
414     }
415 }
416
417
418 static int do_row(unsigned char *known, unsigned char *deduced,
419                   unsigned char *row,
420                   unsigned char *minpos_done, unsigned char *maxpos_done,
421                   unsigned char *minpos_ok, unsigned char *maxpos_ok,
422                   unsigned char *start, int len, int step, int *data,
423                   unsigned int *changed
424 #ifdef STANDALONE_SOLVER
425                   , const char *rowcol, int index, int cluewid
426 #endif
427                   )
428 {
429     int rowlen, i, freespace, done_any;
430
431     freespace = len+1;
432     for (rowlen = 0; data[rowlen]; rowlen++) {
433         minpos_done[rowlen] = minpos_ok[rowlen] = len - 1;
434         maxpos_done[rowlen] = maxpos_ok[rowlen] = 0;
435         freespace -= data[rowlen]+1;
436     }
437
438     for (i = 0; i < len; i++) {
439         known[i] = start[i*step];
440         deduced[i] = 0;
441     }
442     for (i = len - 1; i >= 0 && known[i] == DOT; i--)
443         freespace--;
444
445     if (rowlen == 0) {
446         memset(deduced, DOT, len);
447     } else {
448         do_recurse(known, deduced, row, minpos_done, maxpos_done, minpos_ok,
449                    maxpos_ok, data, len, freespace, 0, 0);
450     }
451
452     done_any = FALSE;
453     for (i=0; i<len; i++)
454         if (deduced[i] && deduced[i] != STILL_UNKNOWN && !known[i]) {
455             start[i*step] = deduced[i];
456             if (changed) changed[i]++;
457             done_any = TRUE;
458         }
459 #ifdef STANDALONE_SOLVER
460     if (verbose && done_any) {
461         char buf[80];
462         int thiscluewid;
463         printf("%s %2d: [", rowcol, index);
464         for (thiscluewid = -1, i = 0; data[i]; i++)
465             thiscluewid += sprintf(buf, " %d", data[i]);
466         printf("%*s", cluewid - thiscluewid, "");
467         for (i = 0; data[i]; i++)
468             printf(" %d", data[i]);
469         printf(" ] ");
470         for (i = 0; i < len; i++)
471             putchar(known[i] == BLOCK ? '#' :
472                     known[i] == DOT ? '.' : '?');
473         printf(" -> ");
474         for (i = 0; i < len; i++)
475             putchar(start[i*step] == BLOCK ? '#' :
476                     start[i*step] == DOT ? '.' : '?');
477         putchar('\n');
478     }
479 #endif
480     return done_any;
481 }
482
483 static int solve_puzzle(const game_state *state, unsigned char *grid,
484                         int w, int h,
485                         unsigned char *matrix, unsigned char *workspace,
486                         unsigned int *changed_h, unsigned int *changed_w,
487                         int *rowdata
488 #ifdef STANDALONE_SOLVER
489                         , int cluewid
490 #else
491                         , int dummy
492 #endif
493                         )
494 {
495     int i, j, ok, max;
496     int max_h, max_w;
497
498     assert((state!=NULL) ^ (grid!=NULL));
499
500     max = max(w, h);
501
502     memset(matrix, 0, w*h);
503     if (state) {
504         for (i=0; i<w*h; i++) {
505             if (state->common->immutable[i])
506                 matrix[i] = state->grid[i];
507         }
508     }
509
510     /* For each column, compute how many squares can be deduced
511      * from just the row-data and initial clues.
512      * Later, changed_* will hold how many squares were changed
513      * in every row/column in the previous iteration
514      * Changed_* is used to choose the next rows / cols to re-examine
515      */
516     for (i=0; i<h; i++) {
517         int freespace, rowlen;
518         if (state) {
519             memcpy(rowdata, state->common->rowdata + state->common->rowsize*(w+i), max*sizeof(int));
520             rowlen = state->common->rowlen[w+i];
521         } else {
522             rowlen = compute_rowdata(rowdata, grid+i*w, w, 1);
523         }
524         rowdata[rowlen] = 0;
525         if (rowlen == 0) {
526             changed_h[i] = w;
527         } else {
528             for (j=0, freespace=w+1; rowdata[j]; j++)
529                 freespace -= rowdata[j] + 1;
530             for (j=0, changed_h[i]=0; rowdata[j]; j++)
531                 if (rowdata[j] > freespace)
532                     changed_h[i] += rowdata[j] - freespace;
533         }
534         for (j = 0; j < w; j++)
535             if (matrix[i*w+j])
536                 changed_h[i]++;
537     }
538     for (i=0,max_h=0; i<h; i++)
539         if (changed_h[i] > max_h)
540             max_h = changed_h[i];
541     for (i=0; i<w; i++) {
542         int freespace, rowlen;
543         if (state) {
544             memcpy(rowdata, state->common->rowdata + state->common->rowsize*i, max*sizeof(int));
545             rowlen = state->common->rowlen[i];
546         } else {
547             rowlen = compute_rowdata(rowdata, grid+i, h, w);
548         }
549         rowdata[rowlen] = 0;
550         if (rowlen == 0) {
551             changed_w[i] = h;
552         } else {
553             for (j=0, freespace=h+1; rowdata[j]; j++)
554                 freespace -= rowdata[j] + 1;
555             for (j=0, changed_w[i]=0; rowdata[j]; j++)
556                 if (rowdata[j] > freespace)
557                     changed_w[i] += rowdata[j] - freespace;
558         }
559         for (j = 0; j < h; j++)
560             if (matrix[j*w+i])
561                 changed_w[i]++;
562     }
563     for (i=0,max_w=0; i<w; i++)
564         if (changed_w[i] > max_w)
565             max_w = changed_w[i];
566
567     /* Solve the puzzle.
568      * Process rows/columns individually. Deductions involving more than one
569      * row and/or column at a time are not supported.
570      * Take care to only process rows/columns which have been changed since they
571      * were previously processed.
572      * Also, prioritize rows/columns which have had the most changes since their
573      * previous processing, as they promise the greatest benefit.
574      * Extremely rectangular grids (e.g. 10x20, 15x40, etc.) are not treated specially.
575      */
576     do {
577         for (; max_h && max_h >= max_w; max_h--) {
578             for (i=0; i<h; i++) {
579                 if (changed_h[i] >= max_h) {
580                     if (state) {
581                         memcpy(rowdata, state->common->rowdata + state->common->rowsize*(w+i), max*sizeof(int));
582                         rowdata[state->common->rowlen[w+i]] = 0;
583                     } else {
584                         rowdata[compute_rowdata(rowdata, grid+i*w, w, 1)] = 0;
585                     }
586                     do_row(workspace, workspace+max, workspace+2*max,
587                            workspace+3*max, workspace+4*max,
588                            workspace+5*max, workspace+6*max,
589                            matrix+i*w, w, 1, rowdata, changed_w
590 #ifdef STANDALONE_SOLVER
591                            , "row", i+1, cluewid
592 #endif
593                            );
594                     changed_h[i] = 0;
595                 }
596             }
597             for (i=0,max_w=0; i<w; i++)
598                 if (changed_w[i] > max_w)
599                     max_w = changed_w[i];
600         }
601         for (; max_w && max_w >= max_h; max_w--) {
602             for (i=0; i<w; i++) {
603                 if (changed_w[i] >= max_w) {
604                     if (state) {
605                         memcpy(rowdata, state->common->rowdata + state->common->rowsize*i, max*sizeof(int));
606                         rowdata[state->common->rowlen[i]] = 0;
607                     } else {
608                         rowdata[compute_rowdata(rowdata, grid+i, h, w)] = 0;
609                     }
610                     do_row(workspace, workspace+max, workspace+2*max,
611                            workspace+3*max, workspace+4*max,
612                            workspace+5*max, workspace+6*max,
613                            matrix+i, h, w, rowdata, changed_h
614 #ifdef STANDALONE_SOLVER
615                            , "col", i+1, cluewid
616 #endif
617                            );
618                     changed_w[i] = 0;
619                 }
620             }
621             for (i=0,max_h=0; i<h; i++)
622                 if (changed_h[i] > max_h)
623                     max_h = changed_h[i];
624         }
625     } while (max_h>0 || max_w>0);
626
627     ok = TRUE;
628     for (i=0; i<h; i++) {
629         for (j=0; j<w; j++) {
630             if (matrix[i*w+j] == UNKNOWN)
631                 ok = FALSE;
632         }
633     }
634
635     return ok;
636 }
637
638 static unsigned char *generate_soluble(random_state *rs, int w, int h)
639 {
640     int i, j, ok, ntries, max;
641     unsigned char *grid, *matrix, *workspace;
642     unsigned int *changed_h, *changed_w;
643     int *rowdata;
644
645     max = max(w, h);
646
647     grid = snewn(w*h, unsigned char);
648     /* Allocate this here, to avoid having to reallocate it again for every geneerated grid */
649     matrix = snewn(w*h, unsigned char);
650     workspace = snewn(max*7, unsigned char);
651     changed_h = snewn(max+1, unsigned int);
652     changed_w = snewn(max+1, unsigned int);
653     rowdata = snewn(max+1, int);
654
655     ntries = 0;
656
657     do {
658         ntries++;
659
660         generate(rs, w, h, grid);
661
662         /*
663          * The game is a bit too easy if any row or column is
664          * completely black or completely white. An exception is
665          * made for rows/columns that are under 3 squares,
666          * otherwise nothing will ever be successfully generated.
667          */
668         ok = TRUE;
669         if (w > 2) {
670             for (i = 0; i < h; i++) {
671                 int colours = 0;
672                 for (j = 0; j < w; j++)
673                     colours |= (grid[i*w+j] == GRID_FULL ? 2 : 1);
674                 if (colours != 3)
675                     ok = FALSE;
676             }
677         }
678         if (h > 2) {
679             for (j = 0; j < w; j++) {
680                 int colours = 0;
681                 for (i = 0; i < h; i++)
682                     colours |= (grid[i*w+j] == GRID_FULL ? 2 : 1);
683                 if (colours != 3)
684                     ok = FALSE;
685             }
686         }
687         if (!ok)
688             continue;
689
690         ok = solve_puzzle(NULL, grid, w, h, matrix, workspace,
691                           changed_h, changed_w, rowdata, 0);
692     } while (!ok);
693
694     sfree(matrix);
695     sfree(workspace);
696     sfree(changed_h);
697     sfree(changed_w);
698     sfree(rowdata);
699     return grid;
700 }
701
702 static char *new_game_desc(const game_params *params, random_state *rs,
703                            char **aux, int interactive)
704 {
705     unsigned char *grid;
706     int i, j, max, rowlen, *rowdata;
707     char intbuf[80], *desc;
708     int desclen, descpos;
709
710     grid = generate_soluble(rs, params->w, params->h);
711     max = max(params->w, params->h);
712     rowdata = snewn(max, int);
713
714     /*
715      * Save the solved game in aux.
716      */
717     {
718         char *ai = snewn(params->w * params->h + 2, char);
719
720         /*
721          * String format is exactly the same as a solve move, so we
722          * can just dupstr this in solve_game().
723          */
724
725         ai[0] = 'S';
726
727         for (i = 0; i < params->w * params->h; i++)
728             ai[i+1] = grid[i] ? '1' : '0';
729
730         ai[params->w * params->h + 1] = '\0';
731
732         *aux = ai;
733     }
734
735     /*
736      * Seed is a slash-separated list of row contents; each row
737      * contents section is a dot-separated list of integers. Row
738      * contents are listed in the order (columns left to right,
739      * then rows top to bottom).
740      * 
741      * Simplest way to handle memory allocation is to make two
742      * passes, first computing the seed size and then writing it
743      * out.
744      */
745     desclen = 0;
746     for (i = 0; i < params->w + params->h; i++) {
747         if (i < params->w)
748             rowlen = compute_rowdata(rowdata, grid+i, params->h, params->w);
749         else
750             rowlen = compute_rowdata(rowdata, grid+(i-params->w)*params->w,
751                                      params->w, 1);
752         if (rowlen > 0) {
753             for (j = 0; j < rowlen; j++) {
754                 desclen += 1 + sprintf(intbuf, "%d", rowdata[j]);
755             }
756         } else {
757             desclen++;
758         }
759     }
760     desc = snewn(desclen, char);
761     descpos = 0;
762     for (i = 0; i < params->w + params->h; i++) {
763         if (i < params->w)
764             rowlen = compute_rowdata(rowdata, grid+i, params->h, params->w);
765         else
766             rowlen = compute_rowdata(rowdata, grid+(i-params->w)*params->w,
767                                      params->w, 1);
768         if (rowlen > 0) {
769             for (j = 0; j < rowlen; j++) {
770                 int len = sprintf(desc+descpos, "%d", rowdata[j]);
771                 if (j+1 < rowlen)
772                     desc[descpos + len] = '.';
773                 else
774                     desc[descpos + len] = '/';
775                 descpos += len+1;
776             }
777         } else {
778             desc[descpos++] = '/';
779         }
780     }
781     assert(descpos == desclen);
782     assert(desc[desclen-1] == '/');
783     desc[desclen-1] = '\0';
784     sfree(rowdata);
785     sfree(grid);
786     return desc;
787 }
788
789 static char *validate_desc(const game_params *params, const char *desc)
790 {
791     int i, n, rowspace;
792     const char *p;
793
794     for (i = 0; i < params->w + params->h; i++) {
795         if (i < params->w)
796             rowspace = params->h + 1;
797         else
798             rowspace = params->w + 1;
799
800         if (*desc && isdigit((unsigned char)*desc)) {
801             do {
802                 p = desc;
803                 while (*desc && isdigit((unsigned char)*desc)) desc++;
804                 n = atoi(p);
805                 rowspace -= n+1;
806
807                 if (rowspace < 0) {
808                     if (i < params->w)
809                         return "at least one column contains more numbers than will fit";
810                     else
811                         return "at least one row contains more numbers than will fit";
812                 }
813             } while (*desc++ == '.');
814         } else {
815             desc++;                    /* expect a slash immediately */
816         }
817
818         if (desc[-1] == '/') {
819             if (i+1 == params->w + params->h)
820                 return "too many row/column specifications";
821         } else if (desc[-1] == '\0' || desc[-1] == ',') {
822             if (i+1 < params->w + params->h)
823                 return "too few row/column specifications";
824         } else
825             return "unrecognised character in game specification";
826     }
827
828     if (desc[-1] == ',') {
829         /*
830          * Optional extra piece of game description which fills in
831          * some grid squares as extra clues.
832          */
833         i = 0;
834         while (i < params->w * params->h) {
835             int c = (unsigned char)*desc++;
836             if ((c >= 'a' && c <= 'z') ||
837                 (c >= 'A' && c <= 'Z')) {
838                 int len = tolower(c) - 'a';
839                 i += len;
840                 if (len < 25 && i < params->w*params->h)
841                     i++;
842                 if (i > params->w * params->h) {
843                     return "too much data in clue-squares section";
844                 }
845             } else if (!c) {
846                 return "too little data in clue-squares section";
847             } else {
848                 return "unrecognised character in clue-squares section";
849             }
850         }
851         if (*desc) {
852             return "too much data in clue-squares section";
853         }
854     }
855
856     return NULL;
857 }
858
859 static game_state *new_game(midend *me, const game_params *params,
860                             const char *desc)
861 {
862     int i;
863     const char *p;
864     game_state *state = snew(game_state);
865
866     state->common = snew(game_state_common);
867     state->common->refcount = 1;
868
869     state->common->w = params->w;
870     state->common->h = params->h;
871
872     state->grid = snewn(state->common->w * state->common->h, unsigned char);
873     memset(state->grid, GRID_UNKNOWN, state->common->w * state->common->h);
874
875     state->common->immutable = snewn(state->common->w * state->common->h,
876                                      unsigned char);
877     memset(state->common->immutable, 0, state->common->w * state->common->h);
878
879     state->common->rowsize = max(state->common->w, state->common->h);
880     state->common->rowdata = snewn(state->common->rowsize * (state->common->w + state->common->h), int);
881     state->common->rowlen = snewn(state->common->w + state->common->h, int);
882
883     state->completed = state->cheated = FALSE;
884
885     for (i = 0; i < params->w + params->h; i++) {
886         state->common->rowlen[i] = 0;
887         if (*desc && isdigit((unsigned char)*desc)) {
888             do {
889                 p = desc;
890                 while (*desc && isdigit((unsigned char)*desc)) desc++;
891                 state->common->rowdata[state->common->rowsize * i + state->common->rowlen[i]++] =
892                     atoi(p);
893             } while (*desc++ == '.');
894         } else {
895             desc++;                    /* expect a slash immediately */
896         }
897     }
898
899     if (desc[-1] == ',') {
900         /*
901          * Optional extra piece of game description which fills in
902          * some grid squares as extra clues.
903          */
904         i = 0;
905         while (i < params->w * params->h) {
906             int c = (unsigned char)*desc++;
907             int full = isupper(c), len = tolower(c) - 'a';
908             i += len;
909             if (len < 25 && i < params->w*params->h) {
910                 state->grid[i] = full ? GRID_FULL : GRID_EMPTY;
911                 state->common->immutable[i] = TRUE;
912                 i++;
913             }
914         }
915     }
916
917     return state;
918 }
919
920 static game_state *dup_game(const game_state *state)
921 {
922     game_state *ret = snew(game_state);
923
924     ret->common = state->common;
925     ret->common->refcount++;
926
927     ret->grid = snewn(ret->common->w * ret->common->h, unsigned char);
928     memcpy(ret->grid, state->grid, ret->common->w * ret->common->h);
929
930     ret->completed = state->completed;
931     ret->cheated = state->cheated;
932
933     return ret;
934 }
935
936 static void free_game(game_state *state)
937 {
938     if (--state->common->refcount == 0) {
939         sfree(state->common->rowdata);
940         sfree(state->common->rowlen);
941         sfree(state->common->immutable);
942         sfree(state->common);
943     }
944     sfree(state->grid);
945     sfree(state);
946 }
947
948 static char *solve_game(const game_state *state, const game_state *currstate,
949                         const char *ai, char **error)
950 {
951     unsigned char *matrix;
952     int w = state->common->w, h = state->common->h;
953     int i;
954     char *ret;
955     int max, ok;
956     unsigned char *workspace;
957     unsigned int *changed_h, *changed_w;
958     int *rowdata;
959
960     /*
961      * If we already have the solved state in ai, copy it out.
962      */
963     if (ai)
964         return dupstr(ai);
965
966     max = max(w, h);
967     matrix = snewn(w*h, unsigned char);
968     workspace = snewn(max*7, unsigned char);
969     changed_h = snewn(max+1, unsigned int);
970     changed_w = snewn(max+1, unsigned int);
971     rowdata = snewn(max+1, int);
972
973     ok = solve_puzzle(state, NULL, w, h, matrix, workspace,
974                       changed_h, changed_w, rowdata, 0);
975
976     sfree(workspace);
977     sfree(changed_h);
978     sfree(changed_w);
979     sfree(rowdata);
980
981     if (!ok) {
982         sfree(matrix);
983         *error = "Solving algorithm cannot complete this puzzle";
984         return NULL;
985     }
986
987     ret = snewn(w*h+2, char);
988     ret[0] = 'S';
989     for (i = 0; i < w*h; i++) {
990         assert(matrix[i] == BLOCK || matrix[i] == DOT);
991         ret[i+1] = (matrix[i] == BLOCK ? '1' : '0');
992     }
993     ret[w*h+1] = '\0';
994
995     sfree(matrix);
996
997     return ret;
998 }
999
1000 static int game_can_format_as_text_now(const game_params *params)
1001 {
1002     return TRUE;
1003 }
1004
1005 static char *game_text_format(const game_state *state)
1006 {
1007     int w = state->common->w, h = state->common->h, i, j;
1008     int left_gap = 0, top_gap = 0, ch = 2, cw = 1, limit = 1;
1009
1010     int len, topleft, lw, lh, gw, gh; /* {line,grid}_{width,height} */
1011     char *board, *buf;
1012
1013     for (i = 0; i < w; ++i) {
1014         top_gap = max(top_gap, state->common->rowlen[i]);
1015         for (j = 0; j < state->common->rowlen[i]; ++j)
1016             while (state->common->rowdata[i*state->common->rowsize + j] >= limit) {
1017                 ++cw;
1018                 limit *= 10;
1019             }
1020     }
1021     for (i = 0; i < h; ++i) {
1022         int rowlen = 0, predecessors = FALSE;
1023         for (j = 0; j < state->common->rowlen[i+w]; ++j) {
1024             int copy = state->common->rowdata[(i+w)*state->common->rowsize + j];
1025             rowlen += predecessors;
1026             predecessors = TRUE;
1027             do ++rowlen; while (copy /= 10);
1028         }
1029         left_gap = max(left_gap, rowlen);
1030     }
1031
1032     cw = max(cw, 3);
1033
1034     gw = w*cw + 2;
1035     gh = h*ch + 1;
1036     lw = gw + left_gap;
1037     lh = gh + top_gap;
1038     len = lw * lh;
1039     topleft = lw * top_gap + left_gap;
1040
1041     board = snewn(len + 1, char);
1042     sprintf(board, "%*s\n", len - 2, "");
1043
1044     for (i = 0; i < lh; ++i) {
1045         board[lw - 1 + i*lw] = '\n';
1046         if (i < top_gap) continue;
1047         board[lw - 2 + i*lw] = ((i - top_gap) % ch ? '|' : '+');
1048     }
1049
1050     for (i = 0; i < w; ++i) {
1051         for (j = 0; j < state->common->rowlen[i]; ++j) {
1052             int cell = topleft + i*cw + 1 + lw*(j - state->common->rowlen[i]);
1053             int nch = sprintf(board + cell, "%*d", cw - 1,
1054                               state->common->rowdata[i*state->common->rowsize + j]);
1055             board[cell + nch] = ' '; /* de-NUL-ify */
1056         }
1057     }
1058
1059     buf = snewn(left_gap, char);
1060     for (i = 0; i < h; ++i) {
1061         char *p = buf, *start = board + top_gap*lw + left_gap + (i*ch+1)*lw;
1062         for (j = 0; j < state->common->rowlen[i+w]; ++j) {
1063             if (p > buf) *p++ = ' ';
1064             p += sprintf(p, "%d", state->common->rowdata[(i+w)*state->common->rowsize + j]);
1065         }
1066         memcpy(start - (p - buf), buf, p - buf);
1067     }
1068
1069     for (i = 0; i < w; ++i) {
1070         for (j = 0; j < h; ++j) {
1071             int cell = topleft + i*cw + j*ch*lw;
1072             int center = cell + cw/2 + (ch/2)*lw;
1073             int dx, dy;
1074             board[cell] = 0 ? center : '+';
1075             for (dx = 1; dx < cw; ++dx) board[cell + dx] = '-';
1076             for (dy = 1; dy < ch; ++dy) board[cell + dy*lw] = '|';
1077             if (state->grid[i*w+j] == GRID_UNKNOWN) continue;
1078             for (dx = 1; dx < cw; ++dx)
1079                 for (dy = 1; dy < ch; ++dy)
1080                     board[cell + dx + dy*lw] =
1081                         state->grid[i*w+j] == GRID_FULL ? '#' : '.';
1082         }
1083     }
1084
1085     memcpy(board + topleft + h*ch*lw, board + topleft, gw - 1);
1086
1087     sfree(buf);
1088
1089     return board;
1090 }
1091
1092 struct game_ui {
1093     int dragging;
1094     int drag_start_x;
1095     int drag_start_y;
1096     int drag_end_x;
1097     int drag_end_y;
1098     int drag, release, state;
1099     int cur_x, cur_y, cur_visible;
1100 };
1101
1102 static game_ui *new_ui(const game_state *state)
1103 {
1104     game_ui *ret;
1105
1106     ret = snew(game_ui);
1107     ret->dragging = FALSE;
1108     ret->cur_x = ret->cur_y = ret->cur_visible = 0;
1109
1110     return ret;
1111 }
1112
1113 static void free_ui(game_ui *ui)
1114 {
1115     sfree(ui);
1116 }
1117
1118 static char *encode_ui(const game_ui *ui)
1119 {
1120     return NULL;
1121 }
1122
1123 static void decode_ui(game_ui *ui, const char *encoding)
1124 {
1125 }
1126
1127 static void game_changed_state(game_ui *ui, const game_state *oldstate,
1128                                const game_state *newstate)
1129 {
1130 }
1131
1132 struct game_drawstate {
1133     int started;
1134     int w, h;
1135     int tilesize;
1136     unsigned char *visible, *numcolours;
1137     int cur_x, cur_y;
1138 };
1139
1140 static char *interpret_move(const game_state *state, game_ui *ui,
1141                             const game_drawstate *ds,
1142                             int x, int y, int button)
1143 {
1144     int control = button & MOD_CTRL, shift = button & MOD_SHFT;
1145     button &= ~MOD_MASK;
1146
1147     x = FROMCOORD(state->common->w, x);
1148     y = FROMCOORD(state->common->h, y);
1149
1150     if (x >= 0 && x < state->common->w && y >= 0 && y < state->common->h &&
1151         (button == LEFT_BUTTON || button == RIGHT_BUTTON ||
1152          button == MIDDLE_BUTTON)) {
1153 #ifdef STYLUS_BASED
1154         int currstate = state->grid[y * state->common->w + x];
1155 #endif
1156
1157         ui->dragging = TRUE;
1158
1159         if (button == LEFT_BUTTON) {
1160             ui->drag = LEFT_DRAG;
1161             ui->release = LEFT_RELEASE;
1162 #ifdef STYLUS_BASED
1163             ui->state = (currstate + 2) % 3; /* FULL -> EMPTY -> UNKNOWN */
1164 #else
1165             ui->state = GRID_FULL;
1166 #endif
1167         } else if (button == RIGHT_BUTTON) {
1168             ui->drag = RIGHT_DRAG;
1169             ui->release = RIGHT_RELEASE;
1170 #ifdef STYLUS_BASED
1171             ui->state = (currstate + 1) % 3; /* EMPTY -> FULL -> UNKNOWN */
1172 #else
1173             ui->state = GRID_EMPTY;
1174 #endif
1175         } else /* if (button == MIDDLE_BUTTON) */ {
1176             ui->drag = MIDDLE_DRAG;
1177             ui->release = MIDDLE_RELEASE;
1178             ui->state = GRID_UNKNOWN;
1179         }
1180
1181         ui->drag_start_x = ui->drag_end_x = x;
1182         ui->drag_start_y = ui->drag_end_y = y;
1183         ui->cur_visible = 0;
1184
1185         return "";                     /* UI activity occurred */
1186     }
1187
1188     if (ui->dragging && button == ui->drag) {
1189         /*
1190          * There doesn't seem much point in allowing a rectangle
1191          * drag; people will generally only want to drag a single
1192          * horizontal or vertical line, so we make that easy by
1193          * snapping to it.
1194          * 
1195          * Exception: if we're _middle_-button dragging to tag
1196          * things as UNKNOWN, we may well want to trash an entire
1197          * area and start over!
1198          */
1199         if (ui->state != GRID_UNKNOWN) {
1200             if (abs(x - ui->drag_start_x) > abs(y - ui->drag_start_y))
1201                 y = ui->drag_start_y;
1202             else
1203                 x = ui->drag_start_x;
1204         }
1205
1206         if (x < 0) x = 0;
1207         if (y < 0) y = 0;
1208         if (x >= state->common->w) x = state->common->w - 1;
1209         if (y >= state->common->h) y = state->common->h - 1;
1210
1211         ui->drag_end_x = x;
1212         ui->drag_end_y = y;
1213
1214         return "";                     /* UI activity occurred */
1215     }
1216
1217     if (ui->dragging && button == ui->release) {
1218         int x1, x2, y1, y2, xx, yy;
1219         int move_needed = FALSE;
1220
1221         x1 = min(ui->drag_start_x, ui->drag_end_x);
1222         x2 = max(ui->drag_start_x, ui->drag_end_x);
1223         y1 = min(ui->drag_start_y, ui->drag_end_y);
1224         y2 = max(ui->drag_start_y, ui->drag_end_y);
1225
1226         for (yy = y1; yy <= y2; yy++)
1227             for (xx = x1; xx <= x2; xx++)
1228                 if (!state->common->immutable[yy * state->common->w + xx] &&
1229                     state->grid[yy * state->common->w + xx] != ui->state)
1230                     move_needed = TRUE;
1231
1232         ui->dragging = FALSE;
1233
1234         if (move_needed) {
1235             char buf[80];
1236             sprintf(buf, "%c%d,%d,%d,%d",
1237                     (char)(ui->state == GRID_FULL ? 'F' :
1238                            ui->state == GRID_EMPTY ? 'E' : 'U'),
1239                     x1, y1, x2-x1+1, y2-y1+1);
1240             return dupstr(buf);
1241         } else
1242             return "";                 /* UI activity occurred */
1243     }
1244
1245     if (IS_CURSOR_MOVE(button)) {
1246         int x = ui->cur_x, y = ui->cur_y, newstate;
1247         char buf[80];
1248         move_cursor(button, &ui->cur_x, &ui->cur_y, state->common->w, state->common->h, 0);
1249         ui->cur_visible = 1;
1250         if (!control && !shift) return "";
1251
1252         newstate = control ? shift ? GRID_UNKNOWN : GRID_FULL : GRID_EMPTY;
1253         if (state->grid[y * state->common->w + x] == newstate &&
1254             state->grid[ui->cur_y * state->common->w + ui->cur_x] == newstate)
1255             return "";
1256
1257         sprintf(buf, "%c%d,%d,%d,%d", control ? shift ? 'U' : 'F' : 'E',
1258                 min(x, ui->cur_x), min(y, ui->cur_y),
1259                 abs(x - ui->cur_x) + 1, abs(y - ui->cur_y) + 1);
1260         return dupstr(buf);
1261     }
1262
1263     if (IS_CURSOR_SELECT(button)) {
1264         int currstate = state->grid[ui->cur_y * state->common->w + ui->cur_x];
1265         int newstate;
1266         char buf[80];
1267
1268         if (!ui->cur_visible) {
1269             ui->cur_visible = 1;
1270             return "";
1271         }
1272
1273         if (button == CURSOR_SELECT2)
1274             newstate = currstate == GRID_UNKNOWN ? GRID_EMPTY :
1275                 currstate == GRID_EMPTY ? GRID_FULL : GRID_UNKNOWN;
1276         else
1277             newstate = currstate == GRID_UNKNOWN ? GRID_FULL :
1278                 currstate == GRID_FULL ? GRID_EMPTY : GRID_UNKNOWN;
1279
1280         sprintf(buf, "%c%d,%d,%d,%d",
1281                 (char)(newstate == GRID_FULL ? 'F' :
1282                        newstate == GRID_EMPTY ? 'E' : 'U'),
1283                 ui->cur_x, ui->cur_y, 1, 1);
1284         return dupstr(buf);
1285     }
1286
1287     return NULL;
1288 }
1289
1290 static game_state *execute_move(const game_state *from, const char *move)
1291 {
1292     game_state *ret;
1293     int x1, x2, y1, y2, xx, yy;
1294     int val;
1295
1296     if (move[0] == 'S' &&
1297         strlen(move) == from->common->w * from->common->h + 1) {
1298         int i;
1299
1300         ret = dup_game(from);
1301
1302         for (i = 0; i < ret->common->w * ret->common->h; i++)
1303             ret->grid[i] = (move[i+1] == '1' ? GRID_FULL : GRID_EMPTY);
1304
1305         ret->completed = ret->cheated = TRUE;
1306
1307         return ret;
1308     } else if ((move[0] == 'F' || move[0] == 'E' || move[0] == 'U') &&
1309         sscanf(move+1, "%d,%d,%d,%d", &x1, &y1, &x2, &y2) == 4 &&
1310         x1 >= 0 && x2 >= 0 && x1+x2 <= from->common->w &&
1311         y1 >= 0 && y2 >= 0 && y1+y2 <= from->common->h) {
1312
1313         x2 += x1;
1314         y2 += y1;
1315         val = (move[0] == 'F' ? GRID_FULL :
1316                  move[0] == 'E' ? GRID_EMPTY : GRID_UNKNOWN);
1317
1318         ret = dup_game(from);
1319         for (yy = y1; yy < y2; yy++)
1320             for (xx = x1; xx < x2; xx++)
1321                 if (!ret->common->immutable[yy * ret->common->w + xx])
1322                     ret->grid[yy * ret->common->w + xx] = val;
1323
1324         /*
1325          * An actual change, so check to see if we've completed the
1326          * game.
1327          */
1328         if (!ret->completed) {
1329             int *rowdata = snewn(ret->common->rowsize, int);
1330             int i, len;
1331
1332             ret->completed = TRUE;
1333
1334             for (i=0; i<ret->common->w; i++) {
1335                 len = compute_rowdata(rowdata, ret->grid+i,
1336                                       ret->common->h, ret->common->w);
1337                 if (len != ret->common->rowlen[i] ||
1338                     memcmp(ret->common->rowdata+i*ret->common->rowsize,
1339                            rowdata, len * sizeof(int))) {
1340                     ret->completed = FALSE;
1341                     break;
1342                 }
1343             }
1344             for (i=0; i<ret->common->h; i++) {
1345                 len = compute_rowdata(rowdata, ret->grid+i*ret->common->w,
1346                                       ret->common->w, 1);
1347                 if (len != ret->common->rowlen[i+ret->common->w] ||
1348                     memcmp(ret->common->rowdata +
1349                            (i+ret->common->w)*ret->common->rowsize,
1350                            rowdata, len * sizeof(int))) {
1351                     ret->completed = FALSE;
1352                     break;
1353                 }
1354             }
1355
1356             sfree(rowdata);
1357         }
1358
1359         return ret;
1360     } else
1361         return NULL;
1362 }
1363
1364 /* ----------------------------------------------------------------------
1365  * Error-checking during gameplay.
1366  */
1367
1368 /*
1369  * The difficulty in error-checking Pattern is to make the error check
1370  * _weak_ enough. The most obvious way would be to check each row and
1371  * column by calling (a modified form of) do_row() to recursively
1372  * analyse the row contents against the clue set and see if the
1373  * GRID_UNKNOWNs could be filled in in any way that would end up
1374  * correct. However, this turns out to be such a strong error check as
1375  * to constitute a spoiler in many situations: you make a typo while
1376  * trying to fill in one row, and not only does the row light up to
1377  * indicate an error, but several columns crossed by the move also
1378  * light up and draw your attention to deductions you hadn't even
1379  * noticed you could make.
1380  *
1381  * So instead I restrict error-checking to 'complete runs' within a
1382  * row, by which I mean contiguous sequences of GRID_FULL bounded at
1383  * both ends by either GRID_EMPTY or the ends of the row. We identify
1384  * all the complete runs in a row, and verify that _those_ are
1385  * consistent with the row's clue list. Sequences of complete runs
1386  * separated by solid GRID_EMPTY are required to match contiguous
1387  * sequences in the clue list, whereas if there's at least one
1388  * GRID_UNKNOWN between any two complete runs then those two need not
1389  * be contiguous in the clue list.
1390  *
1391  * To simplify the edge cases, I pretend that the clue list for the
1392  * row is extended with a 0 at each end, and I also pretend that the
1393  * grid data for the row is extended with a GRID_EMPTY and a
1394  * zero-length run at each end. This permits the contiguity checker to
1395  * handle the fiddly end effects (e.g. if the first contiguous
1396  * sequence of complete runs in the grid matches _something_ in the
1397  * clue list but not at the beginning, this is allowable iff there's a
1398  * GRID_UNKNOWN before the first one) with minimal faff, since the end
1399  * effects just drop out as special cases of the normal inter-run
1400  * handling (in this code the above case is not 'at the end of the
1401  * clue list' at all, but between the implicit initial zero run and
1402  * the first nonzero one).
1403  *
1404  * We must also be a little careful about how we search for a
1405  * contiguous sequence of runs. In the clue list (1 1 2 1 2 3),
1406  * suppose we see a GRID_UNKNOWN and then a length-1 run. We search
1407  * for 1 in the clue list and find it at the very beginning. But now
1408  * suppose we find a length-2 run with no GRID_UNKNOWN before it. We
1409  * can't naively look at the next clue from the 1 we found, because
1410  * that'll be the second 1 and won't match. Instead, we must backtrack
1411  * by observing that the 2 we've just found must be contiguous with
1412  * the 1 we've already seen, so we search for the sequence (1 2) and
1413  * find it starting at the second 1. Now if we see a 3, we must
1414  * rethink again and search for (1 2 3).
1415  */
1416
1417 struct errcheck_state {
1418     /*
1419      * rowdata and rowlen point at the clue data for this row in the
1420      * game state.
1421      */
1422     int *rowdata;
1423     int rowlen;
1424     /*
1425      * rowpos indicates the lowest position where it would be valid to
1426      * see our next run length. It might be equal to rowlen,
1427      * indicating that the next run would have to be the terminating 0.
1428      */
1429     int rowpos;
1430     /*
1431      * ncontig indicates how many runs we've seen in a contiguous
1432      * block. This is taken into account when searching for the next
1433      * run we find, unless ncontig is zeroed out first by encountering
1434      * a GRID_UNKNOWN.
1435      */
1436     int ncontig;
1437 };
1438
1439 static int errcheck_found_run(struct errcheck_state *es, int r)
1440 {
1441 /* Macro to handle the pretence that rowdata has a 0 at each end */
1442 #define ROWDATA(k) ((k)<0 || (k)>=es->rowlen ? 0 : es->rowdata[(k)])
1443
1444     /*
1445      * See if we can find this new run length at a position where it
1446      * also matches the last 'ncontig' runs we've seen.
1447      */
1448     int i, newpos;
1449     for (newpos = es->rowpos; newpos <= es->rowlen; newpos++) {
1450
1451         if (ROWDATA(newpos) != r)
1452             goto notfound;
1453
1454         for (i = 1; i <= es->ncontig; i++)
1455             if (ROWDATA(newpos - i) != ROWDATA(es->rowpos - i))
1456                 goto notfound;
1457
1458         es->rowpos = newpos+1;
1459         es->ncontig++;
1460         return TRUE;
1461
1462       notfound:;
1463     }
1464
1465     return FALSE;
1466
1467 #undef ROWDATA
1468 }
1469
1470 static int check_errors(const game_state *state, int i)
1471 {
1472     int start, step, end, j;
1473     int val, runlen;
1474     struct errcheck_state aes, *es = &aes;
1475
1476     es->rowlen = state->common->rowlen[i];
1477     es->rowdata = state->common->rowdata + state->common->rowsize * i;
1478     /* Pretend that we've already encountered the initial zero run */
1479     es->ncontig = 1;
1480     es->rowpos = 0;
1481
1482     if (i < state->common->w) {
1483         start = i;
1484         step = state->common->w;
1485         end = start + step * state->common->h;
1486     } else {
1487         start = (i - state->common->w) * state->common->w;
1488         step = 1;
1489         end = start + step * state->common->w;
1490     }
1491
1492     runlen = -1;
1493     for (j = start - step; j <= end; j += step) {
1494         if (j < start || j == end)
1495             val = GRID_EMPTY;
1496         else
1497             val = state->grid[j];
1498
1499         if (val == GRID_UNKNOWN) {
1500             runlen = -1;
1501             es->ncontig = 0;
1502         } else if (val == GRID_FULL) {
1503             if (runlen >= 0)
1504                 runlen++;
1505         } else if (val == GRID_EMPTY) {
1506             if (runlen > 0) {
1507                 if (!errcheck_found_run(es, runlen))
1508                     return TRUE;       /* error! */
1509             }
1510             runlen = 0;
1511         }
1512     }
1513
1514     /* Signal end-of-row by sending errcheck_found_run the terminating
1515      * zero run, which will be marked as contiguous with the previous
1516      * run if and only if there hasn't been a GRID_UNKNOWN before. */
1517     if (!errcheck_found_run(es, 0))
1518         return TRUE;                   /* error at the last minute! */
1519
1520     return FALSE;                      /* no error */
1521 }
1522
1523 /* ----------------------------------------------------------------------
1524  * Drawing routines.
1525  */
1526
1527 static void game_compute_size(const game_params *params, int tilesize,
1528                               int *x, int *y)
1529 {
1530     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
1531     struct { int tilesize; } ads, *ds = &ads;
1532     ads.tilesize = tilesize;
1533
1534     *x = SIZE(params->w);
1535     *y = SIZE(params->h);
1536 }
1537
1538 static void game_set_size(drawing *dr, game_drawstate *ds,
1539                           const game_params *params, int tilesize)
1540 {
1541     ds->tilesize = tilesize;
1542 }
1543
1544 static float *game_colours(frontend *fe, int *ncolours)
1545 {
1546     float *ret = snewn(3 * NCOLOURS, float);
1547     int i;
1548
1549     frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
1550
1551     for (i = 0; i < 3; i++) {
1552         ret[COL_GRID    * 3 + i] = 0.3F;
1553         ret[COL_UNKNOWN * 3 + i] = 0.5F;
1554         ret[COL_TEXT    * 3 + i] = 0.0F;
1555         ret[COL_FULL    * 3 + i] = 0.0F;
1556         ret[COL_EMPTY   * 3 + i] = 1.0F;
1557     }
1558     ret[COL_CURSOR * 3 + 0] = 1.0F;
1559     ret[COL_CURSOR * 3 + 1] = 0.25F;
1560     ret[COL_CURSOR * 3 + 2] = 0.25F;
1561     ret[COL_ERROR * 3 + 0] = 1.0F;
1562     ret[COL_ERROR * 3 + 1] = 0.0F;
1563     ret[COL_ERROR * 3 + 2] = 0.0F;
1564
1565     *ncolours = NCOLOURS;
1566     return ret;
1567 }
1568
1569 static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
1570 {
1571     struct game_drawstate *ds = snew(struct game_drawstate);
1572
1573     ds->started = FALSE;
1574     ds->w = state->common->w;
1575     ds->h = state->common->h;
1576     ds->visible = snewn(ds->w * ds->h, unsigned char);
1577     ds->tilesize = 0;                  /* not decided yet */
1578     memset(ds->visible, 255, ds->w * ds->h);
1579     ds->numcolours = snewn(ds->w + ds->h, unsigned char);
1580     memset(ds->numcolours, 255, ds->w + ds->h);
1581     ds->cur_x = ds->cur_y = 0;
1582
1583     return ds;
1584 }
1585
1586 static void game_free_drawstate(drawing *dr, game_drawstate *ds)
1587 {
1588     sfree(ds->visible);
1589     sfree(ds);
1590 }
1591
1592 static void grid_square(drawing *dr, game_drawstate *ds,
1593                         int y, int x, int state, int cur)
1594 {
1595     int xl, xr, yt, yb, dx, dy, dw, dh;
1596
1597     draw_rect(dr, TOCOORD(ds->w, x), TOCOORD(ds->h, y),
1598               TILE_SIZE, TILE_SIZE, COL_GRID);
1599
1600     xl = (x % 5 == 0 ? 1 : 0);
1601     yt = (y % 5 == 0 ? 1 : 0);
1602     xr = (x % 5 == 4 || x == ds->w-1 ? 1 : 0);
1603     yb = (y % 5 == 4 || y == ds->h-1 ? 1 : 0);
1604
1605     dx = TOCOORD(ds->w, x) + 1 + xl;
1606     dy = TOCOORD(ds->h, y) + 1 + yt;
1607     dw = TILE_SIZE - xl - xr - 1;
1608     dh = TILE_SIZE - yt - yb - 1;
1609
1610     draw_rect(dr, dx, dy, dw, dh,
1611               (state == GRID_FULL ? COL_FULL :
1612                state == GRID_EMPTY ? COL_EMPTY : COL_UNKNOWN));
1613     if (cur) {
1614         draw_rect_outline(dr, dx, dy, dw, dh, COL_CURSOR);
1615         draw_rect_outline(dr, dx+1, dy+1, dw-2, dh-2, COL_CURSOR);
1616     }
1617
1618     draw_update(dr, TOCOORD(ds->w, x), TOCOORD(ds->h, y),
1619                 TILE_SIZE, TILE_SIZE);
1620 }
1621
1622 /*
1623  * Draw the numbers for a single row or column.
1624  */
1625 static void draw_numbers(drawing *dr, game_drawstate *ds,
1626                          const game_state *state, int i, int erase, int colour)
1627 {
1628     int rowlen = state->common->rowlen[i];
1629     int *rowdata = state->common->rowdata + state->common->rowsize * i;
1630     int nfit;
1631     int j;
1632
1633     if (erase) {
1634         if (i < state->common->w) {
1635             draw_rect(dr, TOCOORD(state->common->w, i), 0,
1636                       TILE_SIZE, BORDER + TLBORDER(state->common->h) * TILE_SIZE,
1637                       COL_BACKGROUND);
1638         } else {
1639             draw_rect(dr, 0, TOCOORD(state->common->h, i - state->common->w),
1640                       BORDER + TLBORDER(state->common->w) * TILE_SIZE, TILE_SIZE,
1641                       COL_BACKGROUND);
1642         }
1643     }
1644
1645     /*
1646      * Normally I space the numbers out by the same distance as the
1647      * tile size. However, if there are more numbers than available
1648      * spaces, I have to squash them up a bit.
1649      */
1650     if (i < state->common->w)
1651         nfit = TLBORDER(state->common->h);
1652     else
1653         nfit = TLBORDER(state->common->w);
1654     nfit = max(rowlen, nfit) - 1;
1655     assert(nfit > 0);
1656
1657     for (j = 0; j < rowlen; j++) {
1658         int x, y;
1659         char str[80];
1660
1661         if (i < state->common->w) {
1662             x = TOCOORD(state->common->w, i);
1663             y = BORDER + TILE_SIZE * (TLBORDER(state->common->h)-1);
1664             y -= ((rowlen-j-1)*TILE_SIZE) * (TLBORDER(state->common->h)-1) / nfit;
1665         } else {
1666             y = TOCOORD(state->common->h, i - state->common->w);
1667             x = BORDER + TILE_SIZE * (TLBORDER(state->common->w)-1);
1668             x -= ((rowlen-j-1)*TILE_SIZE) * (TLBORDER(state->common->w)-1) / nfit;
1669         }
1670
1671         sprintf(str, "%d", rowdata[j]);
1672         draw_text(dr, x+TILE_SIZE/2, y+TILE_SIZE/2, FONT_VARIABLE,
1673                   TILE_SIZE/2, ALIGN_HCENTRE | ALIGN_VCENTRE, colour, str);
1674     }
1675
1676     if (i < state->common->w) {
1677         draw_update(dr, TOCOORD(state->common->w, i), 0,
1678                     TILE_SIZE, BORDER + TLBORDER(state->common->h) * TILE_SIZE);
1679     } else {
1680         draw_update(dr, 0, TOCOORD(state->common->h, i - state->common->w),
1681                     BORDER + TLBORDER(state->common->w) * TILE_SIZE, TILE_SIZE);
1682     }
1683 }
1684
1685 static void game_redraw(drawing *dr, game_drawstate *ds,
1686                         const game_state *oldstate, const game_state *state,
1687                         int dir, const game_ui *ui,
1688                         float animtime, float flashtime)
1689 {
1690     int i, j;
1691     int x1, x2, y1, y2;
1692     int cx, cy, cmoved;
1693
1694     if (!ds->started) {
1695         /*
1696          * The initial contents of the window are not guaranteed
1697          * and can vary with front ends. To be on the safe side,
1698          * all games should start by drawing a big background-
1699          * colour rectangle covering the whole window.
1700          */
1701         draw_rect(dr, 0, 0, SIZE(ds->w), SIZE(ds->h), COL_BACKGROUND);
1702
1703         /*
1704          * Draw the grid outline.
1705          */
1706         draw_rect(dr, TOCOORD(ds->w, 0) - 1, TOCOORD(ds->h, 0) - 1,
1707                   ds->w * TILE_SIZE + 3, ds->h * TILE_SIZE + 3,
1708                   COL_GRID);
1709
1710         ds->started = TRUE;
1711
1712         draw_update(dr, 0, 0, SIZE(ds->w), SIZE(ds->h));
1713     }
1714
1715     if (ui->dragging) {
1716         x1 = min(ui->drag_start_x, ui->drag_end_x);
1717         x2 = max(ui->drag_start_x, ui->drag_end_x);
1718         y1 = min(ui->drag_start_y, ui->drag_end_y);
1719         y2 = max(ui->drag_start_y, ui->drag_end_y);
1720     } else {
1721         x1 = x2 = y1 = y2 = -1;        /* placate gcc warnings */
1722     }
1723
1724     if (ui->cur_visible) {
1725         cx = ui->cur_x; cy = ui->cur_y;
1726     } else {
1727         cx = cy = -1;
1728     }
1729     cmoved = (cx != ds->cur_x || cy != ds->cur_y);
1730
1731     /*
1732      * Now draw any grid squares which have changed since last
1733      * redraw.
1734      */
1735     for (i = 0; i < ds->h; i++) {
1736         for (j = 0; j < ds->w; j++) {
1737             int val, cc = 0;
1738
1739             /*
1740              * Work out what state this square should be drawn in,
1741              * taking any current drag operation into account.
1742              */
1743             if (ui->dragging && x1 <= j && j <= x2 && y1 <= i && i <= y2 &&
1744                 !state->common->immutable[i * state->common->w + j])
1745                 val = ui->state;
1746             else
1747                 val = state->grid[i * state->common->w + j];
1748
1749             if (cmoved) {
1750                 /* the cursor has moved; if we were the old or
1751                  * the new cursor position we need to redraw. */
1752                 if (j == cx && i == cy) cc = 1;
1753                 if (j == ds->cur_x && i == ds->cur_y) cc = 1;
1754             }
1755
1756             /*
1757              * Briefly invert everything twice during a completion
1758              * flash.
1759              */
1760             if (flashtime > 0 &&
1761                 (flashtime <= FLASH_TIME/3 || flashtime >= FLASH_TIME*2/3) &&
1762                 val != GRID_UNKNOWN)
1763                 val = (GRID_FULL ^ GRID_EMPTY) ^ val;
1764
1765             if (ds->visible[i * ds->w + j] != val || cc) {
1766                 grid_square(dr, ds, i, j, val,
1767                             (j == cx && i == cy));
1768                 ds->visible[i * ds->w + j] = val;
1769             }
1770         }
1771     }
1772     ds->cur_x = cx; ds->cur_y = cy;
1773
1774     /*
1775      * Redraw any numbers which have changed their colour due to error
1776      * indication.
1777      */
1778     for (i = 0; i < state->common->w + state->common->h; i++) {
1779         int colour = check_errors(state, i) ? COL_ERROR : COL_TEXT;
1780         if (ds->numcolours[i] != colour) {
1781             draw_numbers(dr, ds, state, i, TRUE, colour);
1782             ds->numcolours[i] = colour;
1783         }
1784     }
1785 }
1786
1787 static float game_anim_length(const game_state *oldstate,
1788                               const game_state *newstate, int dir, game_ui *ui)
1789 {
1790     return 0.0F;
1791 }
1792
1793 static float game_flash_length(const game_state *oldstate,
1794                                const game_state *newstate, int dir, game_ui *ui)
1795 {
1796     if (!oldstate->completed && newstate->completed &&
1797         !oldstate->cheated && !newstate->cheated)
1798         return FLASH_TIME;
1799     return 0.0F;
1800 }
1801
1802 static int game_status(const game_state *state)
1803 {
1804     return state->completed ? +1 : 0;
1805 }
1806
1807 static int game_timing_state(const game_state *state, game_ui *ui)
1808 {
1809     return TRUE;
1810 }
1811
1812 static void game_print_size(const game_params *params, float *x, float *y)
1813 {
1814     int pw, ph;
1815
1816     /*
1817      * I'll use 5mm squares by default.
1818      */
1819     game_compute_size(params, 500, &pw, &ph);
1820     *x = pw / 100.0F;
1821     *y = ph / 100.0F;
1822 }
1823
1824 static void game_print(drawing *dr, const game_state *state, int tilesize)
1825 {
1826     int w = state->common->w, h = state->common->h;
1827     int ink = print_mono_colour(dr, 0);
1828     int x, y, i;
1829
1830     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
1831     game_drawstate ads, *ds = &ads;
1832     game_set_size(dr, ds, NULL, tilesize);
1833
1834     /*
1835      * Border.
1836      */
1837     print_line_width(dr, TILE_SIZE / 16);
1838     draw_rect_outline(dr, TOCOORD(w, 0), TOCOORD(h, 0),
1839                       w*TILE_SIZE, h*TILE_SIZE, ink);
1840
1841     /*
1842      * Grid.
1843      */
1844     for (x = 1; x < w; x++) {
1845         print_line_width(dr, TILE_SIZE / (x % 5 ? 128 : 24));
1846         draw_line(dr, TOCOORD(w, x), TOCOORD(h, 0),
1847                   TOCOORD(w, x), TOCOORD(h, h), ink);
1848     }
1849     for (y = 1; y < h; y++) {
1850         print_line_width(dr, TILE_SIZE / (y % 5 ? 128 : 24));
1851         draw_line(dr, TOCOORD(w, 0), TOCOORD(h, y),
1852                   TOCOORD(w, w), TOCOORD(h, y), ink);
1853     }
1854
1855     /*
1856      * Clues.
1857      */
1858     for (i = 0; i < state->common->w + state->common->h; i++)
1859         draw_numbers(dr, ds, state, i, FALSE, ink);
1860
1861     /*
1862      * Solution.
1863      */
1864     print_line_width(dr, TILE_SIZE / 128);
1865     for (y = 0; y < h; y++)
1866         for (x = 0; x < w; x++) {
1867             if (state->grid[y*w+x] == GRID_FULL)
1868                 draw_rect(dr, TOCOORD(w, x), TOCOORD(h, y),
1869                           TILE_SIZE, TILE_SIZE, ink);
1870             else if (state->grid[y*w+x] == GRID_EMPTY)
1871                 draw_circle(dr, TOCOORD(w, x) + TILE_SIZE/2,
1872                             TOCOORD(h, y) + TILE_SIZE/2,
1873                             TILE_SIZE/12, ink, ink);
1874         }
1875 }
1876
1877 #ifdef COMBINED
1878 #define thegame pattern
1879 #endif
1880
1881 const struct game thegame = {
1882     "Pattern", "games.pattern", "pattern",
1883     default_params,
1884     game_fetch_preset,
1885     decode_params,
1886     encode_params,
1887     free_params,
1888     dup_params,
1889     TRUE, game_configure, custom_params,
1890     validate_params,
1891     new_game_desc,
1892     validate_desc,
1893     new_game,
1894     dup_game,
1895     free_game,
1896     TRUE, solve_game,
1897     TRUE, game_can_format_as_text_now, game_text_format,
1898     new_ui,
1899     free_ui,
1900     encode_ui,
1901     decode_ui,
1902     game_changed_state,
1903     interpret_move,
1904     execute_move,
1905     PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
1906     game_colours,
1907     game_new_drawstate,
1908     game_free_drawstate,
1909     game_redraw,
1910     game_anim_length,
1911     game_flash_length,
1912     game_status,
1913     TRUE, FALSE, game_print_size, game_print,
1914     FALSE,                             /* wants_statusbar */
1915     FALSE, game_timing_state,
1916     REQUIRE_RBUTTON,                   /* flags */
1917 };
1918
1919 #ifdef STANDALONE_SOLVER
1920
1921 int main(int argc, char **argv)
1922 {
1923     game_params *p;
1924     game_state *s;
1925     char *id = NULL, *desc, *err;
1926
1927     while (--argc > 0) {
1928         char *p = *++argv;
1929         if (*p == '-') {
1930             if (!strcmp(p, "-v")) {
1931                 verbose = TRUE;
1932             } else {
1933                 fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);
1934                 return 1;
1935             }
1936         } else {
1937             id = p;
1938         }
1939     }
1940
1941     if (!id) {
1942         fprintf(stderr, "usage: %s <game_id>\n", argv[0]);
1943         return 1;
1944     }
1945
1946     desc = strchr(id, ':');
1947     if (!desc) {
1948         fprintf(stderr, "%s: game id expects a colon in it\n", argv[0]);
1949         return 1;
1950     }
1951     *desc++ = '\0';
1952
1953     p = default_params();
1954     decode_params(p, id);
1955     err = validate_desc(p, desc);
1956     if (err) {
1957         fprintf(stderr, "%s: %s\n", argv[0], err);
1958         return 1;
1959     }
1960     s = new_game(NULL, p, desc);
1961
1962     {
1963         int w = p->w, h = p->h, i, j, max, cluewid = 0;
1964         unsigned char *matrix, *workspace;
1965         unsigned int *changed_h, *changed_w;
1966         int *rowdata;
1967
1968         matrix = snewn(w*h, unsigned char);
1969         max = max(w, h);
1970         workspace = snewn(max*7, unsigned char);
1971         changed_h = snewn(max+1, unsigned int);
1972         changed_w = snewn(max+1, unsigned int);
1973         rowdata = snewn(max+1, int);
1974
1975         if (verbose) {
1976             int thiswid;
1977             /*
1978              * Work out the maximum text width of the clue numbers
1979              * in a row or column, so we can print the solver's
1980              * working in a nicely lined up way.
1981              */
1982             for (i = 0; i < (w+h); i++) {
1983                 char buf[80];
1984                 for (thiswid = -1, j = 0; j < s->common->rowlen[i]; j++)
1985                     thiswid += sprintf
1986                         (buf, " %d",
1987                          s->common->rowdata[s->common->rowsize*i+j]);
1988                 if (cluewid < thiswid)
1989                     cluewid = thiswid;
1990             }
1991         }
1992
1993         solve_puzzle(s, NULL, w, h, matrix, workspace,
1994                      changed_h, changed_w, rowdata, cluewid);
1995
1996         for (i = 0; i < h; i++) {
1997             for (j = 0; j < w; j++) {
1998                 int c = (matrix[i*w+j] == UNKNOWN ? '?' :
1999                          matrix[i*w+j] == BLOCK ? '#' :
2000                          matrix[i*w+j] == DOT ? '.' :
2001                          '!');
2002                 putchar(c);
2003             }
2004             printf("\n");
2005         }
2006     }
2007
2008     return 0;
2009 }
2010
2011 #endif
2012
2013 /* vim: set shiftwidth=4 tabstop=8: */