Initial checkin of `Solo', the number-placing puzzle popularised by
[sgt/puzzles] / solo.c
CommitLineData
1d8e8ad8 1/*
2 * solo.c: the number-placing puzzle most popularly known as `Sudoku'.
3 *
4 * TODO:
5 *
6 * - finalise game name
7 *
8 * - can we do anything about nasty centring of text in GTK? It
9 * seems to be taking ascenders/descenders into account when
10 * centring. Ick.
11 *
12 * - implement stronger modes of reasoning in nsolve, thus
13 * enabling harder puzzles
14 *
15 * - configurable difficulty levels
16 *
17 * - vary the symmetry (rotational or none)?
18 *
19 * - try for cleverer ways of reducing the solved grid; they seem
20 * to be coming out a bit full for the most part, and in
21 * particular it's inexcusable to leave a grid with an entire
22 * block (or presumably row or column) filled! I _hope_ we can
23 * do this simply by better prioritising (somehow) the possible
24 * removals.
25 * + one simple option might be to work the other way: start
26 * with an empty grid and gradually _add_ numbers until it
27 * becomes solvable? Perhaps there might be some heuristic
28 * which enables us to pinpoint the most critical clues and
29 * thus add as few as possible.
30 *
31 * - alternative interface modes
32 * + sudoku.com's Windows program has a palette of possible
33 * entries; you select a palette entry first and then click
34 * on the square you want it to go in, thus enabling
35 * mouse-only play. Useful for PDAs! I don't think it's
36 * actually incompatible with the current highlight-then-type
37 * approach: you _either_ highlight a palette entry and then
38 * click, _or_ you highlight a square and then type. At most
39 * one thing is ever highlighted at a time, so there's no way
40 * to confuse the two.
41 * + `pencil marks' might be useful for more subtle forms of
42 * deduction, once we implement creation of puzzles that
43 * require it.
44 */
45
46/*
47 * Solo puzzles need to be square overall (since each row and each
48 * column must contain one of every digit), but they need not be
49 * subdivided the same way internally. I am going to adopt a
50 * convention whereby I _always_ refer to `r' as the number of rows
51 * of _big_ divisions, and `c' as the number of columns of _big_
52 * divisions. Thus, a 2c by 3r puzzle looks something like this:
53 *
54 * 4 5 1 | 2 6 3
55 * 6 3 2 | 5 4 1
56 * ------+------ (Of course, you can't subdivide it the other way
57 * 1 4 5 | 6 3 2 or you'll get clashes; observe that the 4 in the
58 * 3 2 6 | 4 1 5 top left would conflict with the 4 in the second
59 * ------+------ box down on the left-hand side.)
60 * 5 1 4 | 3 2 6
61 * 2 6 3 | 1 5 4
62 *
63 * The need for a strong naming convention should now be clear:
64 * each small box is two rows of digits by three columns, while the
65 * overall puzzle has three rows of small boxes by two columns. So
66 * I will (hopefully) consistently use `r' to denote the number of
67 * rows _of small boxes_ (here 3), which is also the number of
68 * columns of digits in each small box; and `c' vice versa (here
69 * 2).
70 *
71 * I'm also going to choose arbitrarily to list c first wherever
72 * possible: the above is a 2x3 puzzle, not a 3x2 one.
73 */
74
75#include <stdio.h>
76#include <stdlib.h>
77#include <string.h>
78#include <assert.h>
79#include <ctype.h>
80#include <math.h>
81
82#include "puzzles.h"
83
84/*
85 * To save space, I store digits internally as unsigned char. This
86 * imposes a hard limit of 255 on the order of the puzzle. Since
87 * even a 5x5 takes unacceptably long to generate, I don't see this
88 * as a serious limitation unless something _really_ impressive
89 * happens in computing technology; but here's a typedef anyway for
90 * general good practice.
91 */
92typedef unsigned char digit;
93#define ORDER_MAX 255
94
95#define TILE_SIZE 32
96#define BORDER 18
97
98#define FLASH_TIME 0.4F
99
100enum {
101 COL_BACKGROUND,
102 COL_GRID,
103 COL_CLUE,
104 COL_USER,
105 COL_HIGHLIGHT,
106 NCOLOURS
107};
108
109struct game_params {
110 int c, r;
111};
112
113struct game_state {
114 int c, r;
115 digit *grid;
116 unsigned char *immutable; /* marks which digits are clues */
117 int completed;
118};
119
120static game_params *default_params(void)
121{
122 game_params *ret = snew(game_params);
123
124 ret->c = ret->r = 3;
125
126 return ret;
127}
128
129static int game_fetch_preset(int i, char **name, game_params **params)
130{
131 game_params *ret;
132 int c, r;
133 char buf[80];
134
135 switch (i) {
136 case 0: c = 2, r = 2; break;
137 case 1: c = 2, r = 3; break;
138 case 2: c = 3, r = 3; break;
139 case 3: c = 3, r = 4; break;
140 case 4: c = 4, r = 4; break;
141 default: return FALSE;
142 }
143
144 sprintf(buf, "%dx%d", c, r);
145 *name = dupstr(buf);
146 *params = ret = snew(game_params);
147 ret->c = c;
148 ret->r = r;
149 /* FIXME: difficulty presets? */
150 return TRUE;
151}
152
153static void free_params(game_params *params)
154{
155 sfree(params);
156}
157
158static game_params *dup_params(game_params *params)
159{
160 game_params *ret = snew(game_params);
161 *ret = *params; /* structure copy */
162 return ret;
163}
164
165static game_params *decode_params(char const *string)
166{
167 game_params *ret = default_params();
168
169 ret->c = ret->r = atoi(string);
170 while (*string && isdigit((unsigned char)*string)) string++;
171 if (*string == 'x') {
172 string++;
173 ret->r = atoi(string);
174 while (*string && isdigit((unsigned char)*string)) string++;
175 }
176 /* FIXME: difficulty levels */
177
178 return ret;
179}
180
181static char *encode_params(game_params *params)
182{
183 char str[80];
184
185 sprintf(str, "%dx%d", params->c, params->r);
186 return dupstr(str);
187}
188
189static config_item *game_configure(game_params *params)
190{
191 config_item *ret;
192 char buf[80];
193
194 ret = snewn(5, config_item);
195
196 ret[0].name = "Columns of sub-blocks";
197 ret[0].type = C_STRING;
198 sprintf(buf, "%d", params->c);
199 ret[0].sval = dupstr(buf);
200 ret[0].ival = 0;
201
202 ret[1].name = "Rows of sub-blocks";
203 ret[1].type = C_STRING;
204 sprintf(buf, "%d", params->r);
205 ret[1].sval = dupstr(buf);
206 ret[1].ival = 0;
207
208 /*
209 * FIXME: difficulty level.
210 */
211
212 ret[2].name = NULL;
213 ret[2].type = C_END;
214 ret[2].sval = NULL;
215 ret[2].ival = 0;
216
217 return ret;
218}
219
220static game_params *custom_params(config_item *cfg)
221{
222 game_params *ret = snew(game_params);
223
224 ret->c = atof(cfg[0].sval);
225 ret->r = atof(cfg[1].sval);
226
227 return ret;
228}
229
230static char *validate_params(game_params *params)
231{
232 if (params->c < 2 || params->r < 2)
233 return "Both dimensions must be at least 2";
234 if (params->c > ORDER_MAX || params->r > ORDER_MAX)
235 return "Dimensions greater than "STR(ORDER_MAX)" are not supported";
236 return NULL;
237}
238
239/* ----------------------------------------------------------------------
240 * Full recursive Solo solver.
241 *
242 * The algorithm for this solver is shamelessly copied from a
243 * Python solver written by Andrew Wilkinson (which is GPLed, but
244 * I've reused only ideas and no code). It mostly just does the
245 * obvious recursive thing: pick an empty square, put one of the
246 * possible digits in it, recurse until all squares are filled,
247 * backtrack and change some choices if necessary.
248 *
249 * The clever bit is that every time it chooses which square to
250 * fill in next, it does so by counting the number of _possible_
251 * numbers that can go in each square, and it prioritises so that
252 * it picks a square with the _lowest_ number of possibilities. The
253 * idea is that filling in lots of the obvious bits (particularly
254 * any squares with only one possibility) will cut down on the list
255 * of possibilities for other squares and hence reduce the enormous
256 * search space as much as possible as early as possible.
257 *
258 * In practice the algorithm appeared to work very well; run on
259 * sample problems from the Times it completed in well under a
260 * second on my G5 even when written in Python, and given an empty
261 * grid (so that in principle it would enumerate _all_ solved
262 * grids!) it found the first valid solution just as quickly. So
263 * with a bit more randomisation I see no reason not to use this as
264 * my grid generator.
265 */
266
267/*
268 * Internal data structure used in solver to keep track of
269 * progress.
270 */
271struct rsolve_coord { int x, y, r; };
272struct rsolve_usage {
273 int c, r, cr; /* cr == c*r */
274 /* grid is a copy of the input grid, modified as we go along */
275 digit *grid;
276 /* row[y*cr+n-1] TRUE if digit n has been placed in row y */
277 unsigned char *row;
278 /* col[x*cr+n-1] TRUE if digit n has been placed in row x */
279 unsigned char *col;
280 /* blk[(y*c+x)*cr+n-1] TRUE if digit n has been placed in block (x,y) */
281 unsigned char *blk;
282 /* This lists all the empty spaces remaining in the grid. */
283 struct rsolve_coord *spaces;
284 int nspaces;
285 /* If we need randomisation in the solve, this is our random state. */
286 random_state *rs;
287 /* Number of solutions so far found, and maximum number we care about. */
288 int solns, maxsolns;
289};
290
291/*
292 * The real recursive step in the solving function.
293 */
294static void rsolve_real(struct rsolve_usage *usage, digit *grid)
295{
296 int c = usage->c, r = usage->r, cr = usage->cr;
297 int i, j, n, sx, sy, bestm, bestr;
298 int *digits;
299
300 /*
301 * Firstly, check for completion! If there are no spaces left
302 * in the grid, we have a solution.
303 */
304 if (usage->nspaces == 0) {
305 if (!usage->solns) {
306 /*
307 * This is our first solution, so fill in the output grid.
308 */
309 memcpy(grid, usage->grid, cr * cr);
310 }
311 usage->solns++;
312 return;
313 }
314
315 /*
316 * Otherwise, there must be at least one space. Find the most
317 * constrained space, using the `r' field as a tie-breaker.
318 */
319 bestm = cr+1; /* so that any space will beat it */
320 bestr = 0;
321 i = sx = sy = -1;
322 for (j = 0; j < usage->nspaces; j++) {
323 int x = usage->spaces[j].x, y = usage->spaces[j].y;
324 int m;
325
326 /*
327 * Find the number of digits that could go in this space.
328 */
329 m = 0;
330 for (n = 0; n < cr; n++)
331 if (!usage->row[y*cr+n] && !usage->col[x*cr+n] &&
332 !usage->blk[((y/c)*c+(x/r))*cr+n])
333 m++;
334
335 if (m < bestm || (m == bestm && usage->spaces[j].r < bestr)) {
336 bestm = m;
337 bestr = usage->spaces[j].r;
338 sx = x;
339 sy = y;
340 i = j;
341 }
342 }
343
344 /*
345 * Swap that square into the final place in the spaces array,
346 * so that decrementing nspaces will remove it from the list.
347 */
348 if (i != usage->nspaces-1) {
349 struct rsolve_coord t;
350 t = usage->spaces[usage->nspaces-1];
351 usage->spaces[usage->nspaces-1] = usage->spaces[i];
352 usage->spaces[i] = t;
353 }
354
355 /*
356 * Now we've decided which square to start our recursion at,
357 * simply go through all possible values, shuffling them
358 * randomly first if necessary.
359 */
360 digits = snewn(bestm, int);
361 j = 0;
362 for (n = 0; n < cr; n++)
363 if (!usage->row[sy*cr+n] && !usage->col[sx*cr+n] &&
364 !usage->blk[((sy/c)*c+(sx/r))*cr+n]) {
365 digits[j++] = n+1;
366 }
367
368 if (usage->rs) {
369 /* shuffle */
370 for (i = j; i > 1; i--) {
371 int p = random_upto(usage->rs, i);
372 if (p != i-1) {
373 int t = digits[p];
374 digits[p] = digits[i-1];
375 digits[i-1] = t;
376 }
377 }
378 }
379
380 /* And finally, go through the digit list and actually recurse. */
381 for (i = 0; i < j; i++) {
382 n = digits[i];
383
384 /* Update the usage structure to reflect the placing of this digit. */
385 usage->row[sy*cr+n-1] = usage->col[sx*cr+n-1] =
386 usage->blk[((sy/c)*c+(sx/r))*cr+n-1] = TRUE;
387 usage->grid[sy*cr+sx] = n;
388 usage->nspaces--;
389
390 /* Call the solver recursively. */
391 rsolve_real(usage, grid);
392
393 /*
394 * If we have seen as many solutions as we need, terminate
395 * all processing immediately.
396 */
397 if (usage->solns >= usage->maxsolns)
398 break;
399
400 /* Revert the usage structure. */
401 usage->row[sy*cr+n-1] = usage->col[sx*cr+n-1] =
402 usage->blk[((sy/c)*c+(sx/r))*cr+n-1] = FALSE;
403 usage->grid[sy*cr+sx] = 0;
404 usage->nspaces++;
405 }
406
407 sfree(digits);
408}
409
410/*
411 * Entry point to solver. You give it dimensions and a starting
412 * grid, which is simply an array of N^4 digits. In that array, 0
413 * means an empty square, and 1..N mean a clue square.
414 *
415 * Return value is the number of solutions found; searching will
416 * stop after the provided `max'. (Thus, you can pass max==1 to
417 * indicate that you only care about finding _one_ solution, or
418 * max==2 to indicate that you want to know the difference between
419 * a unique and non-unique solution.) The input parameter `grid' is
420 * also filled in with the _first_ (or only) solution found by the
421 * solver.
422 */
423static int rsolve(int c, int r, digit *grid, random_state *rs, int max)
424{
425 struct rsolve_usage *usage;
426 int x, y, cr = c*r;
427 int ret;
428
429 /*
430 * Create an rsolve_usage structure.
431 */
432 usage = snew(struct rsolve_usage);
433
434 usage->c = c;
435 usage->r = r;
436 usage->cr = cr;
437
438 usage->grid = snewn(cr * cr, digit);
439 memcpy(usage->grid, grid, cr * cr);
440
441 usage->row = snewn(cr * cr, unsigned char);
442 usage->col = snewn(cr * cr, unsigned char);
443 usage->blk = snewn(cr * cr, unsigned char);
444 memset(usage->row, FALSE, cr * cr);
445 memset(usage->col, FALSE, cr * cr);
446 memset(usage->blk, FALSE, cr * cr);
447
448 usage->spaces = snewn(cr * cr, struct rsolve_coord);
449 usage->nspaces = 0;
450
451 usage->solns = 0;
452 usage->maxsolns = max;
453
454 usage->rs = rs;
455
456 /*
457 * Now fill it in with data from the input grid.
458 */
459 for (y = 0; y < cr; y++) {
460 for (x = 0; x < cr; x++) {
461 int v = grid[y*cr+x];
462 if (v == 0) {
463 usage->spaces[usage->nspaces].x = x;
464 usage->spaces[usage->nspaces].y = y;
465 if (rs)
466 usage->spaces[usage->nspaces].r = random_bits(rs, 31);
467 else
468 usage->spaces[usage->nspaces].r = usage->nspaces;
469 usage->nspaces++;
470 } else {
471 usage->row[y*cr+v-1] = TRUE;
472 usage->col[x*cr+v-1] = TRUE;
473 usage->blk[((y/c)*c+(x/r))*cr+v-1] = TRUE;
474 }
475 }
476 }
477
478 /*
479 * Run the real recursive solving function.
480 */
481 rsolve_real(usage, grid);
482 ret = usage->solns;
483
484 /*
485 * Clean up the usage structure now we have our answer.
486 */
487 sfree(usage->spaces);
488 sfree(usage->blk);
489 sfree(usage->col);
490 sfree(usage->row);
491 sfree(usage->grid);
492 sfree(usage);
493
494 /*
495 * And return.
496 */
497 return ret;
498}
499
500/* ----------------------------------------------------------------------
501 * End of recursive solver code.
502 */
503
504/* ----------------------------------------------------------------------
505 * Less capable non-recursive solver. This one is used to check
506 * solubility of a grid as we gradually remove numbers from it: by
507 * verifying a grid using this solver we can ensure it isn't _too_
508 * hard (e.g. does not actually require guessing and backtracking).
509 *
510 * It supports a variety of specific modes of reasoning. By
511 * enabling or disabling subsets of these modes we can arrange a
512 * range of difficulty levels.
513 */
514
515/*
516 * Modes of reasoning currently supported:
517 *
518 * - Positional elimination: a number must go in a particular
519 * square because all the other empty squares in a given
520 * row/col/blk are ruled out.
521 *
522 * - Numeric elimination: a square must have a particular number
523 * in because all the other numbers that could go in it are
524 * ruled out.
525 *
526 * More advanced modes of reasoning I'd like to support in future:
527 *
528 * - Intersectional elimination: given two domains which overlap
529 * (hence one must be a block, and the other can be a row or
530 * col), if the possible locations for a particular number in
531 * one of the domains can be narrowed down to the overlap, then
532 * that number can be ruled out everywhere but the overlap in
533 * the other domain too.
534 *
535 * - Setwise numeric elimination: if there is a subset of the
536 * empty squares within a domain such that the union of the
537 * possible numbers in that subset has the same size as the
538 * subset itself, then those numbers can be ruled out everywhere
539 * else in the domain. (For example, if there are five empty
540 * squares and the possible numbers in each are 12, 23, 13, 134
541 * and 1345, then the first three empty squares form such a
542 * subset: the numbers 1, 2 and 3 _must_ be in those three
543 * squares in some permutation, and hence we can deduce none of
544 * them can be in the fourth or fifth squares.)
545 */
546
547struct nsolve_usage {
548 int c, r, cr;
549 /*
550 * We set up a cubic array, indexed by x, y and digit; each
551 * element of this array is TRUE or FALSE according to whether
552 * or not that digit _could_ in principle go in that position.
553 *
554 * The way to index this array is cube[(x*cr+y)*cr+n-1].
555 */
556 unsigned char *cube;
557 /*
558 * This is the grid in which we write down our final
559 * deductions.
560 */
561 digit *grid;
562 /*
563 * Now we keep track, at a slightly higher level, of what we
564 * have yet to work out, to prevent doing the same deduction
565 * many times.
566 */
567 /* row[y*cr+n-1] TRUE if digit n has been placed in row y */
568 unsigned char *row;
569 /* col[x*cr+n-1] TRUE if digit n has been placed in row x */
570 unsigned char *col;
571 /* blk[(y*c+x)*cr+n-1] TRUE if digit n has been placed in block (x,y) */
572 unsigned char *blk;
573};
574#define cube(x,y,n) (usage->cube[((x)*usage->cr+(y))*usage->cr+(n)-1])
575
576/*
577 * Function called when we are certain that a particular square has
578 * a particular number in it.
579 */
580static void nsolve_place(struct nsolve_usage *usage, int x, int y, int n)
581{
582 int c = usage->c, r = usage->r, cr = usage->cr;
583 int i, j, bx, by;
584
585 assert(cube(x,y,n));
586
587 /*
588 * Rule out all other numbers in this square.
589 */
590 for (i = 1; i <= cr; i++)
591 if (i != n)
592 cube(x,y,i) = FALSE;
593
594 /*
595 * Rule out this number in all other positions in the row.
596 */
597 for (i = 0; i < cr; i++)
598 if (i != y)
599 cube(x,i,n) = FALSE;
600
601 /*
602 * Rule out this number in all other positions in the column.
603 */
604 for (i = 0; i < cr; i++)
605 if (i != x)
606 cube(i,y,n) = FALSE;
607
608 /*
609 * Rule out this number in all other positions in the block.
610 */
611 bx = (x/r)*r;
612 by = (y/c)*c;
613 for (i = 0; i < r; i++)
614 for (j = 0; j < c; j++)
615 if (bx+i != x || by+j != y)
616 cube(bx+i,by+j,n) = FALSE;
617
618 /*
619 * Enter the number in the result grid.
620 */
621 usage->grid[y*cr+x] = n;
622
623 /*
624 * Cross out this number from the list of numbers left to place
625 * in its row, its column and its block.
626 */
627 usage->row[y*cr+n-1] = usage->col[x*cr+n-1] =
628 usage->blk[((y/c)*c+(x/r))*cr+n-1] = TRUE;
629}
630
631static int nsolve_blk_pos_elim(struct nsolve_usage *usage,
632 int x, int y, int n)
633{
634 int c = usage->c, r = usage->r;
635 int i, j, fx, fy, m;
636
637 x *= r;
638 y *= c;
639
640 /*
641 * Count the possible positions within this block where this
642 * number could appear.
643 */
644 m = 0;
645 fx = fy = -1;
646 for (i = 0; i < r; i++)
647 for (j = 0; j < c; j++)
648 if (cube(x+i,y+j,n)) {
649 fx = x+i;
650 fy = y+j;
651 m++;
652 }
653
654 if (m == 1) {
655 assert(fx >= 0 && fy >= 0);
656 nsolve_place(usage, fx, fy, n);
657 return TRUE;
658 }
659
660 return FALSE;
661}
662
663static int nsolve_row_pos_elim(struct nsolve_usage *usage,
664 int y, int n)
665{
666 int cr = usage->cr;
667 int x, fx, m;
668
669 /*
670 * Count the possible positions within this row where this
671 * number could appear.
672 */
673 m = 0;
674 fx = -1;
675 for (x = 0; x < cr; x++)
676 if (cube(x,y,n)) {
677 fx = x;
678 m++;
679 }
680
681 if (m == 1) {
682 assert(fx >= 0);
683 nsolve_place(usage, fx, y, n);
684 return TRUE;
685 }
686
687 return FALSE;
688}
689
690static int nsolve_col_pos_elim(struct nsolve_usage *usage,
691 int x, int n)
692{
693 int cr = usage->cr;
694 int y, fy, m;
695
696 /*
697 * Count the possible positions within this column where this
698 * number could appear.
699 */
700 m = 0;
701 fy = -1;
702 for (y = 0; y < cr; y++)
703 if (cube(x,y,n)) {
704 fy = y;
705 m++;
706 }
707
708 if (m == 1) {
709 assert(fy >= 0);
710 nsolve_place(usage, x, fy, n);
711 return TRUE;
712 }
713
714 return FALSE;
715}
716
717static int nsolve_num_elim(struct nsolve_usage *usage,
718 int x, int y)
719{
720 int cr = usage->cr;
721 int n, fn, m;
722
723 /*
724 * Count the possible numbers that could appear in this square.
725 */
726 m = 0;
727 fn = -1;
728 for (n = 1; n <= cr; n++)
729 if (cube(x,y,n)) {
730 fn = n;
731 m++;
732 }
733
734 if (m == 1) {
735 assert(fn > 0);
736 nsolve_place(usage, x, y, fn);
737 return TRUE;
738 }
739
740 return FALSE;
741}
742
743static int nsolve(int c, int r, digit *grid)
744{
745 struct nsolve_usage *usage;
746 int cr = c*r;
747 int x, y, n;
748
749 /*
750 * Set up a usage structure as a clean slate (everything
751 * possible).
752 */
753 usage = snew(struct nsolve_usage);
754 usage->c = c;
755 usage->r = r;
756 usage->cr = cr;
757 usage->cube = snewn(cr*cr*cr, unsigned char);
758 usage->grid = grid; /* write straight back to the input */
759 memset(usage->cube, TRUE, cr*cr*cr);
760
761 usage->row = snewn(cr * cr, unsigned char);
762 usage->col = snewn(cr * cr, unsigned char);
763 usage->blk = snewn(cr * cr, unsigned char);
764 memset(usage->row, FALSE, cr * cr);
765 memset(usage->col, FALSE, cr * cr);
766 memset(usage->blk, FALSE, cr * cr);
767
768 /*
769 * Place all the clue numbers we are given.
770 */
771 for (x = 0; x < cr; x++)
772 for (y = 0; y < cr; y++)
773 if (grid[y*cr+x])
774 nsolve_place(usage, x, y, grid[y*cr+x]);
775
776 /*
777 * Now loop over the grid repeatedly trying all permitted modes
778 * of reasoning. The loop terminates if we complete an
779 * iteration without making any progress; we then return
780 * failure or success depending on whether the grid is full or
781 * not.
782 */
783 while (1) {
784 /*
785 * Blockwise positional elimination.
786 */
787 for (x = 0; x < c; x++)
788 for (y = 0; y < r; y++)
789 for (n = 1; n <= cr; n++)
790 if (!usage->blk[((y/c)*c+(x/r))*cr+n-1] &&
791 nsolve_blk_pos_elim(usage, x, y, n))
792 continue;
793
794 /*
795 * Row-wise positional elimination.
796 */
797 for (y = 0; y < cr; y++)
798 for (n = 1; n <= cr; n++)
799 if (!usage->row[y*cr+n-1] &&
800 nsolve_row_pos_elim(usage, y, n))
801 continue;
802 /*
803 * Column-wise positional elimination.
804 */
805 for (x = 0; x < cr; x++)
806 for (n = 1; n <= cr; n++)
807 if (!usage->col[x*cr+n-1] &&
808 nsolve_col_pos_elim(usage, x, n))
809 continue;
810
811 /*
812 * Numeric elimination.
813 */
814 for (x = 0; x < cr; x++)
815 for (y = 0; y < cr; y++)
816 if (!usage->grid[y*cr+x] &&
817 nsolve_num_elim(usage, x, y))
818 continue;
819
820 /*
821 * If we reach here, we have made no deductions in this
822 * iteration, so the algorithm terminates.
823 */
824 break;
825 }
826
827 sfree(usage->cube);
828 sfree(usage->row);
829 sfree(usage->col);
830 sfree(usage->blk);
831 sfree(usage);
832
833 for (x = 0; x < cr; x++)
834 for (y = 0; y < cr; y++)
835 if (!grid[y*cr+x])
836 return FALSE;
837 return TRUE;
838}
839
840/* ----------------------------------------------------------------------
841 * End of non-recursive solver code.
842 */
843
844/*
845 * Check whether a grid contains a valid complete puzzle.
846 */
847static int check_valid(int c, int r, digit *grid)
848{
849 int cr = c*r;
850 unsigned char *used;
851 int x, y, n;
852
853 used = snewn(cr, unsigned char);
854
855 /*
856 * Check that each row contains precisely one of everything.
857 */
858 for (y = 0; y < cr; y++) {
859 memset(used, FALSE, cr);
860 for (x = 0; x < cr; x++)
861 if (grid[y*cr+x] > 0 && grid[y*cr+x] <= cr)
862 used[grid[y*cr+x]-1] = TRUE;
863 for (n = 0; n < cr; n++)
864 if (!used[n]) {
865 sfree(used);
866 return FALSE;
867 }
868 }
869
870 /*
871 * Check that each column contains precisely one of everything.
872 */
873 for (x = 0; x < cr; x++) {
874 memset(used, FALSE, cr);
875 for (y = 0; y < cr; y++)
876 if (grid[y*cr+x] > 0 && grid[y*cr+x] <= cr)
877 used[grid[y*cr+x]-1] = TRUE;
878 for (n = 0; n < cr; n++)
879 if (!used[n]) {
880 sfree(used);
881 return FALSE;
882 }
883 }
884
885 /*
886 * Check that each block contains precisely one of everything.
887 */
888 for (x = 0; x < cr; x += r) {
889 for (y = 0; y < cr; y += c) {
890 int xx, yy;
891 memset(used, FALSE, cr);
892 for (xx = x; xx < x+r; xx++)
893 for (yy = 0; yy < y+c; yy++)
894 if (grid[yy*cr+xx] > 0 && grid[yy*cr+xx] <= cr)
895 used[grid[yy*cr+xx]-1] = TRUE;
896 for (n = 0; n < cr; n++)
897 if (!used[n]) {
898 sfree(used);
899 return FALSE;
900 }
901 }
902 }
903
904 sfree(used);
905 return TRUE;
906}
907
908static char *new_game_seed(game_params *params, random_state *rs)
909{
910 int c = params->c, r = params->r, cr = c*r;
911 int area = cr*cr;
912 digit *grid, *grid2;
913 struct xy { int x, y; } *locs;
914 int nlocs;
915 int ret;
916 char *seed;
917
918 /*
919 * Start the recursive solver with an empty grid to generate a
920 * random solved state.
921 */
922 grid = snewn(area, digit);
923 memset(grid, 0, area);
924 ret = rsolve(c, r, grid, rs, 1);
925 assert(ret == 1);
926 assert(check_valid(c, r, grid));
927
928#ifdef DEBUG
929 memcpy(grid,
930 "\x0\x1\x0\x0\x6\x0\x0\x0\x0"
931 "\x5\x0\x0\x7\x0\x4\x0\x2\x0"
932 "\x0\x0\x6\x1\x0\x0\x0\x0\x0"
933 "\x8\x9\x7\x0\x0\x0\x0\x0\x0"
934 "\x0\x0\x3\x0\x4\x0\x9\x0\x0"
935 "\x0\x0\x0\x0\x0\x0\x8\x7\x6"
936 "\x0\x0\x0\x0\x0\x9\x1\x0\x0"
937 "\x0\x3\x0\x6\x0\x5\x0\x0\x7"
938 "\x0\x0\x0\x0\x8\x0\x0\x5\x0"
939 , area);
940
941 {
942 int y, x;
943 for (y = 0; y < cr; y++) {
944 for (x = 0; x < cr; x++) {
945 printf("%2.0d", grid[y*cr+x]);
946 }
947 printf("\n");
948 }
949 printf("\n");
950 }
951
952 nsolve(c, r, grid);
953
954 {
955 int y, x;
956 for (y = 0; y < cr; y++) {
957 for (x = 0; x < cr; x++) {
958 printf("%2.0d", grid[y*cr+x]);
959 }
960 printf("\n");
961 }
962 printf("\n");
963 }
964#endif
965
966 /*
967 * Now we have a solved grid, start removing things from it
968 * while preserving solubility.
969 */
970 locs = snewn((cr+1)/2 * (cr+1)/2, struct xy);
971 grid2 = snewn(area, digit);
972 while (1) {
973 int x, y, i;
974
975 /*
976 * Iterate over the top left corner of the grid and
977 * enumerate all the filled squares we could empty.
978 */
979 nlocs = 0;
980
981 for (x = 0; 2*x < cr; x++)
982 for (y = 0; 2*y < cr; y++)
983 if (grid[y*cr+x]) {
984 locs[nlocs].x = x;
985 locs[nlocs].y = y;
986 nlocs++;
987 }
988
989 /*
990 * Now shuffle that list.
991 */
992 for (i = nlocs; i > 1; i--) {
993 int p = random_upto(rs, i);
994 if (p != i-1) {
995 struct xy t = locs[p];
996 locs[p] = locs[i-1];
997 locs[i-1] = t;
998 }
999 }
1000
1001 /*
1002 * Now loop over the shuffled list and, for each element,
1003 * see whether removing that element (and its reflections)
1004 * from the grid will still leave the grid soluble by
1005 * nsolve.
1006 */
1007 for (i = 0; i < nlocs; i++) {
1008 x = locs[i].x;
1009 y = locs[i].y;
1010
1011 memcpy(grid2, grid, area);
1012 grid2[y*cr+x] = 0;
1013 grid2[y*cr+cr-1-x] = 0;
1014 grid2[(cr-1-y)*cr+x] = 0;
1015 grid2[(cr-1-y)*cr+cr-1-x] = 0;
1016
1017 if (nsolve(c, r, grid2)) {
1018 grid[y*cr+x] = 0;
1019 grid[y*cr+cr-1-x] = 0;
1020 grid[(cr-1-y)*cr+x] = 0;
1021 grid[(cr-1-y)*cr+cr-1-x] = 0;
1022 break;
1023 }
1024 }
1025
1026 if (i == nlocs) {
1027 /*
1028 * There was nothing we could remove without destroying
1029 * solvability.
1030 */
1031 break;
1032 }
1033 }
1034 sfree(grid2);
1035 sfree(locs);
1036
1037#ifdef DEBUG
1038 {
1039 int y, x;
1040 for (y = 0; y < cr; y++) {
1041 for (x = 0; x < cr; x++) {
1042 printf("%2.0d", grid[y*cr+x]);
1043 }
1044 printf("\n");
1045 }
1046 printf("\n");
1047 }
1048#endif
1049
1050 /*
1051 * Now we have the grid as it will be presented to the user.
1052 * Encode it in a game seed.
1053 */
1054 {
1055 char *p;
1056 int run, i;
1057
1058 seed = snewn(5 * area, char);
1059 p = seed;
1060 run = 0;
1061 for (i = 0; i <= area; i++) {
1062 int n = (i < area ? grid[i] : -1);
1063
1064 if (!n)
1065 run++;
1066 else {
1067 if (run) {
1068 while (run > 0) {
1069 int c = 'a' - 1 + run;
1070 if (run > 26)
1071 c = 'z';
1072 *p++ = c;
1073 run -= c - ('a' - 1);
1074 }
1075 } else {
1076 /*
1077 * If there's a number in the very top left or
1078 * bottom right, there's no point putting an
1079 * unnecessary _ before or after it.
1080 */
1081 if (p > seed && n > 0)
1082 *p++ = '_';
1083 }
1084 if (n > 0)
1085 p += sprintf(p, "%d", n);
1086 run = 0;
1087 }
1088 }
1089 assert(p - seed < 5 * area);
1090 *p++ = '\0';
1091 seed = sresize(seed, p - seed, char);
1092 }
1093
1094 sfree(grid);
1095
1096 return seed;
1097}
1098
1099static char *validate_seed(game_params *params, char *seed)
1100{
1101 int area = params->r * params->r * params->c * params->c;
1102 int squares = 0;
1103
1104 while (*seed) {
1105 int n = *seed++;
1106 if (n >= 'a' && n <= 'z') {
1107 squares += n - 'a' + 1;
1108 } else if (n == '_') {
1109 /* do nothing */;
1110 } else if (n > '0' && n <= '9') {
1111 squares++;
1112 while (*seed >= '0' && *seed <= '9')
1113 seed++;
1114 } else
1115 return "Invalid character in game specification";
1116 }
1117
1118 if (squares < area)
1119 return "Not enough data to fill grid";
1120
1121 if (squares > area)
1122 return "Too much data to fit in grid";
1123
1124 return NULL;
1125}
1126
1127static game_state *new_game(game_params *params, char *seed)
1128{
1129 game_state *state = snew(game_state);
1130 int c = params->c, r = params->r, cr = c*r, area = cr * cr;
1131 int i;
1132
1133 state->c = params->c;
1134 state->r = params->r;
1135
1136 state->grid = snewn(area, digit);
1137 state->immutable = snewn(area, unsigned char);
1138 memset(state->immutable, FALSE, area);
1139
1140 state->completed = FALSE;
1141
1142 i = 0;
1143 while (*seed) {
1144 int n = *seed++;
1145 if (n >= 'a' && n <= 'z') {
1146 int run = n - 'a' + 1;
1147 assert(i + run <= area);
1148 while (run-- > 0)
1149 state->grid[i++] = 0;
1150 } else if (n == '_') {
1151 /* do nothing */;
1152 } else if (n > '0' && n <= '9') {
1153 assert(i < area);
1154 state->immutable[i] = TRUE;
1155 state->grid[i++] = atoi(seed-1);
1156 while (*seed >= '0' && *seed <= '9')
1157 seed++;
1158 } else {
1159 assert(!"We can't get here");
1160 }
1161 }
1162 assert(i == area);
1163
1164 return state;
1165}
1166
1167static game_state *dup_game(game_state *state)
1168{
1169 game_state *ret = snew(game_state);
1170 int c = state->c, r = state->r, cr = c*r, area = cr * cr;
1171
1172 ret->c = state->c;
1173 ret->r = state->r;
1174
1175 ret->grid = snewn(area, digit);
1176 memcpy(ret->grid, state->grid, area);
1177
1178 ret->immutable = snewn(area, unsigned char);
1179 memcpy(ret->immutable, state->immutable, area);
1180
1181 ret->completed = state->completed;
1182
1183 return ret;
1184}
1185
1186static void free_game(game_state *state)
1187{
1188 sfree(state->immutable);
1189 sfree(state->grid);
1190 sfree(state);
1191}
1192
1193struct game_ui {
1194 /*
1195 * These are the coordinates of the currently highlighted
1196 * square on the grid, or -1,-1 if there isn't one. When there
1197 * is, pressing a valid number or letter key or Space will
1198 * enter that number or letter in the grid.
1199 */
1200 int hx, hy;
1201};
1202
1203static game_ui *new_ui(game_state *state)
1204{
1205 game_ui *ui = snew(game_ui);
1206
1207 ui->hx = ui->hy = -1;
1208
1209 return ui;
1210}
1211
1212static void free_ui(game_ui *ui)
1213{
1214 sfree(ui);
1215}
1216
1217static game_state *make_move(game_state *from, game_ui *ui, int x, int y,
1218 int button)
1219{
1220 int c = from->c, r = from->r, cr = c*r;
1221 int tx, ty;
1222 game_state *ret;
1223
1224 tx = (x - BORDER) / TILE_SIZE;
1225 ty = (y - BORDER) / TILE_SIZE;
1226
1227 if (tx >= 0 && tx < cr && ty >= 0 && ty < cr && button == LEFT_BUTTON) {
1228 if (tx == ui->hx && ty == ui->hy) {
1229 ui->hx = ui->hy = -1;
1230 } else {
1231 ui->hx = tx;
1232 ui->hy = ty;
1233 }
1234 return from; /* UI activity occurred */
1235 }
1236
1237 if (ui->hx != -1 && ui->hy != -1 &&
1238 ((button >= '1' && button <= '9' && button - '0' <= cr) ||
1239 (button >= 'a' && button <= 'z' && button - 'a' + 10 <= cr) ||
1240 (button >= 'A' && button <= 'Z' && button - 'A' + 10 <= cr) ||
1241 button == ' ')) {
1242 int n = button - '0';
1243 if (button >= 'A' && button <= 'Z')
1244 n = button - 'A' + 10;
1245 if (button >= 'a' && button <= 'z')
1246 n = button - 'a' + 10;
1247 if (button == ' ')
1248 n = 0;
1249
1250 if (from->immutable[ui->hy*cr+ui->hx])
1251 return NULL; /* can't overwrite this square */
1252
1253 ret = dup_game(from);
1254 ret->grid[ui->hy*cr+ui->hx] = n;
1255 ui->hx = ui->hy = -1;
1256
1257 /*
1258 * We've made a real change to the grid. Check to see
1259 * if the game has been completed.
1260 */
1261 if (!ret->completed && check_valid(c, r, ret->grid)) {
1262 ret->completed = TRUE;
1263 }
1264
1265 return ret; /* made a valid move */
1266 }
1267
1268 return NULL;
1269}
1270
1271/* ----------------------------------------------------------------------
1272 * Drawing routines.
1273 */
1274
1275struct game_drawstate {
1276 int started;
1277 int c, r, cr;
1278 digit *grid;
1279 unsigned char *hl;
1280};
1281
1282#define XSIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
1283#define YSIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
1284
1285static void game_size(game_params *params, int *x, int *y)
1286{
1287 int c = params->c, r = params->r, cr = c*r;
1288
1289 *x = XSIZE(cr);
1290 *y = YSIZE(cr);
1291}
1292
1293static float *game_colours(frontend *fe, game_state *state, int *ncolours)
1294{
1295 float *ret = snewn(3 * NCOLOURS, float);
1296
1297 frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
1298
1299 ret[COL_GRID * 3 + 0] = 0.0F;
1300 ret[COL_GRID * 3 + 1] = 0.0F;
1301 ret[COL_GRID * 3 + 2] = 0.0F;
1302
1303 ret[COL_CLUE * 3 + 0] = 0.0F;
1304 ret[COL_CLUE * 3 + 1] = 0.0F;
1305 ret[COL_CLUE * 3 + 2] = 0.0F;
1306
1307 ret[COL_USER * 3 + 0] = 0.0F;
1308 ret[COL_USER * 3 + 1] = 0.6F * ret[COL_BACKGROUND * 3 + 1];
1309 ret[COL_USER * 3 + 2] = 0.0F;
1310
1311 ret[COL_HIGHLIGHT * 3 + 0] = 0.85F * ret[COL_BACKGROUND * 3 + 0];
1312 ret[COL_HIGHLIGHT * 3 + 1] = 0.85F * ret[COL_BACKGROUND * 3 + 1];
1313 ret[COL_HIGHLIGHT * 3 + 2] = 0.85F * ret[COL_BACKGROUND * 3 + 2];
1314
1315 *ncolours = NCOLOURS;
1316 return ret;
1317}
1318
1319static game_drawstate *game_new_drawstate(game_state *state)
1320{
1321 struct game_drawstate *ds = snew(struct game_drawstate);
1322 int c = state->c, r = state->r, cr = c*r;
1323
1324 ds->started = FALSE;
1325 ds->c = c;
1326 ds->r = r;
1327 ds->cr = cr;
1328 ds->grid = snewn(cr*cr, digit);
1329 memset(ds->grid, 0, cr*cr);
1330 ds->hl = snewn(cr*cr, unsigned char);
1331 memset(ds->hl, 0, cr*cr);
1332
1333 return ds;
1334}
1335
1336static void game_free_drawstate(game_drawstate *ds)
1337{
1338 sfree(ds->hl);
1339 sfree(ds->grid);
1340 sfree(ds);
1341}
1342
1343static void draw_number(frontend *fe, game_drawstate *ds, game_state *state,
1344 int x, int y, int hl)
1345{
1346 int c = state->c, r = state->r, cr = c*r;
1347 int tx, ty;
1348 int cx, cy, cw, ch;
1349 char str[2];
1350
1351 if (ds->grid[y*cr+x] == state->grid[y*cr+x] && ds->hl[y*cr+x] == hl)
1352 return; /* no change required */
1353
1354 tx = BORDER + x * TILE_SIZE + 2;
1355 ty = BORDER + y * TILE_SIZE + 2;
1356
1357 cx = tx;
1358 cy = ty;
1359 cw = TILE_SIZE-3;
1360 ch = TILE_SIZE-3;
1361
1362 if (x % r)
1363 cx--, cw++;
1364 if ((x+1) % r)
1365 cw++;
1366 if (y % c)
1367 cy--, ch++;
1368 if ((y+1) % c)
1369 ch++;
1370
1371 clip(fe, cx, cy, cw, ch);
1372
1373 /* background needs erasing? */
1374 if (ds->grid[y*cr+x] || ds->hl[y*cr+x] != hl)
1375 draw_rect(fe, cx, cy, cw, ch, hl ? COL_HIGHLIGHT : COL_BACKGROUND);
1376
1377 /* new number needs drawing? */
1378 if (state->grid[y*cr+x]) {
1379 str[1] = '\0';
1380 str[0] = state->grid[y*cr+x] + '0';
1381 if (str[0] > '9')
1382 str[0] += 'a' - ('9'+1);
1383 draw_text(fe, tx + TILE_SIZE/2, ty + TILE_SIZE/2,
1384 FONT_VARIABLE, TILE_SIZE/2, ALIGN_VCENTRE | ALIGN_HCENTRE,
1385 state->immutable[y*cr+x] ? COL_CLUE : COL_USER, str);
1386 }
1387
1388 unclip(fe);
1389
1390 draw_update(fe, cx, cy, cw, ch);
1391
1392 ds->grid[y*cr+x] = state->grid[y*cr+x];
1393 ds->hl[y*cr+x] = hl;
1394}
1395
1396static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
1397 game_state *state, int dir, game_ui *ui,
1398 float animtime, float flashtime)
1399{
1400 int c = state->c, r = state->r, cr = c*r;
1401 int x, y;
1402
1403 if (!ds->started) {
1404 /*
1405 * The initial contents of the window are not guaranteed
1406 * and can vary with front ends. To be on the safe side,
1407 * all games should start by drawing a big
1408 * background-colour rectangle covering the whole window.
1409 */
1410 draw_rect(fe, 0, 0, XSIZE(cr), YSIZE(cr), COL_BACKGROUND);
1411
1412 /*
1413 * Draw the grid.
1414 */
1415 for (x = 0; x <= cr; x++) {
1416 int thick = (x % r ? 0 : 1);
1417 draw_rect(fe, BORDER + x*TILE_SIZE - thick, BORDER-1,
1418 1+2*thick, cr*TILE_SIZE+3, COL_GRID);
1419 }
1420 for (y = 0; y <= cr; y++) {
1421 int thick = (y % c ? 0 : 1);
1422 draw_rect(fe, BORDER-1, BORDER + y*TILE_SIZE - thick,
1423 cr*TILE_SIZE+3, 1+2*thick, COL_GRID);
1424 }
1425 }
1426
1427 /*
1428 * Draw any numbers which need redrawing.
1429 */
1430 for (x = 0; x < cr; x++) {
1431 for (y = 0; y < cr; y++) {
1432 draw_number(fe, ds, state, x, y,
1433 (x == ui->hx && y == ui->hy) ||
1434 (flashtime > 0 &&
1435 (flashtime <= FLASH_TIME/3 ||
1436 flashtime >= FLASH_TIME*2/3)));
1437 }
1438 }
1439
1440 /*
1441 * Update the _entire_ grid if necessary.
1442 */
1443 if (!ds->started) {
1444 draw_update(fe, 0, 0, XSIZE(cr), YSIZE(cr));
1445 ds->started = TRUE;
1446 }
1447}
1448
1449static float game_anim_length(game_state *oldstate, game_state *newstate,
1450 int dir)
1451{
1452 return 0.0F;
1453}
1454
1455static float game_flash_length(game_state *oldstate, game_state *newstate,
1456 int dir)
1457{
1458 if (!oldstate->completed && newstate->completed)
1459 return FLASH_TIME;
1460 return 0.0F;
1461}
1462
1463static int game_wants_statusbar(void)
1464{
1465 return FALSE;
1466}
1467
1468#ifdef COMBINED
1469#define thegame solo
1470#endif
1471
1472const struct game thegame = {
1473 "Solo", "games.solo", TRUE,
1474 default_params,
1475 game_fetch_preset,
1476 decode_params,
1477 encode_params,
1478 free_params,
1479 dup_params,
1480 game_configure,
1481 custom_params,
1482 validate_params,
1483 new_game_seed,
1484 validate_seed,
1485 new_game,
1486 dup_game,
1487 free_game,
1488 new_ui,
1489 free_ui,
1490 make_move,
1491 game_size,
1492 game_colours,
1493 game_new_drawstate,
1494 game_free_drawstate,
1495 game_redraw,
1496 game_anim_length,
1497 game_flash_length,
1498 game_wants_statusbar,
1499};