Implement the remaining modes of reasoning in nsolve, and thus
[sgt/puzzles] / solo.c
CommitLineData
1d8e8ad8 1/*
2 * solo.c: the number-placing puzzle most popularly known as `Sudoku'.
3 *
4 * TODO:
5 *
1d8e8ad8 6 * - can we do anything about nasty centring of text in GTK? It
7 * seems to be taking ascenders/descenders into account when
8 * centring. Ick.
9 *
ef57b17d 10 * - it might still be nice to do some prioritisation on the
11 * removal of numbers from the grid
12 * + one possibility is to try to minimise the maximum number
13 * of filled squares in any block, which in particular ought
14 * to enforce never leaving a completely filled block in the
15 * puzzle as presented.
16 * + be careful of being too clever here, though, until after
17 * I've tried implementing difficulty levels. It's not
18 * impossible that those might impose much more important
19 * constraints on this process.
1d8e8ad8 20 *
21 * - alternative interface modes
22 * + sudoku.com's Windows program has a palette of possible
23 * entries; you select a palette entry first and then click
24 * on the square you want it to go in, thus enabling
25 * mouse-only play. Useful for PDAs! I don't think it's
26 * actually incompatible with the current highlight-then-type
27 * approach: you _either_ highlight a palette entry and then
28 * click, _or_ you highlight a square and then type. At most
29 * one thing is ever highlighted at a time, so there's no way
30 * to confuse the two.
31 * + `pencil marks' might be useful for more subtle forms of
7c568a48 32 * deduction, now we can create puzzles that require them.
1d8e8ad8 33 */
34
35/*
36 * Solo puzzles need to be square overall (since each row and each
37 * column must contain one of every digit), but they need not be
38 * subdivided the same way internally. I am going to adopt a
39 * convention whereby I _always_ refer to `r' as the number of rows
40 * of _big_ divisions, and `c' as the number of columns of _big_
41 * divisions. Thus, a 2c by 3r puzzle looks something like this:
42 *
43 * 4 5 1 | 2 6 3
44 * 6 3 2 | 5 4 1
45 * ------+------ (Of course, you can't subdivide it the other way
46 * 1 4 5 | 6 3 2 or you'll get clashes; observe that the 4 in the
47 * 3 2 6 | 4 1 5 top left would conflict with the 4 in the second
48 * ------+------ box down on the left-hand side.)
49 * 5 1 4 | 3 2 6
50 * 2 6 3 | 1 5 4
51 *
52 * The need for a strong naming convention should now be clear:
53 * each small box is two rows of digits by three columns, while the
54 * overall puzzle has three rows of small boxes by two columns. So
55 * I will (hopefully) consistently use `r' to denote the number of
56 * rows _of small boxes_ (here 3), which is also the number of
57 * columns of digits in each small box; and `c' vice versa (here
58 * 2).
59 *
60 * I'm also going to choose arbitrarily to list c first wherever
61 * possible: the above is a 2x3 puzzle, not a 3x2 one.
62 */
63
64#include <stdio.h>
65#include <stdlib.h>
66#include <string.h>
67#include <assert.h>
68#include <ctype.h>
69#include <math.h>
70
7c568a48 71#ifdef STANDALONE_SOLVER
72#include <stdarg.h>
73int solver_show_working;
74#endif
75
1d8e8ad8 76#include "puzzles.h"
77
7c568a48 78#define max(x,y) ((x)>(y)?(x):(y))
79
1d8e8ad8 80/*
81 * To save space, I store digits internally as unsigned char. This
82 * imposes a hard limit of 255 on the order of the puzzle. Since
83 * even a 5x5 takes unacceptably long to generate, I don't see this
84 * as a serious limitation unless something _really_ impressive
85 * happens in computing technology; but here's a typedef anyway for
86 * general good practice.
87 */
88typedef unsigned char digit;
89#define ORDER_MAX 255
90
91#define TILE_SIZE 32
92#define BORDER 18
93
94#define FLASH_TIME 0.4F
95
ef57b17d 96enum { SYMM_NONE, SYMM_ROT2, SYMM_ROT4, SYMM_REF4 };
97
7c568a48 98enum { DIFF_BLOCK, DIFF_SIMPLE, DIFF_INTERSECT,
99 DIFF_SET, DIFF_RECURSIVE, DIFF_AMBIGUOUS, DIFF_IMPOSSIBLE };
100
1d8e8ad8 101enum {
102 COL_BACKGROUND,
ef57b17d 103 COL_GRID,
104 COL_CLUE,
105 COL_USER,
106 COL_HIGHLIGHT,
107 NCOLOURS
1d8e8ad8 108};
109
110struct game_params {
7c568a48 111 int c, r, symm, diff;
1d8e8ad8 112};
113
114struct game_state {
115 int c, r;
116 digit *grid;
117 unsigned char *immutable; /* marks which digits are clues */
118 int completed;
119};
120
121static game_params *default_params(void)
122{
123 game_params *ret = snew(game_params);
124
125 ret->c = ret->r = 3;
ef57b17d 126 ret->symm = SYMM_ROT2; /* a plausible default */
7c568a48 127 ret->diff = DIFF_SIMPLE; /* so is this */
1d8e8ad8 128
129 return ret;
130}
131
1d8e8ad8 132static void free_params(game_params *params)
133{
134 sfree(params);
135}
136
137static game_params *dup_params(game_params *params)
138{
139 game_params *ret = snew(game_params);
140 *ret = *params; /* structure copy */
141 return ret;
142}
143
7c568a48 144static int game_fetch_preset(int i, char **name, game_params **params)
145{
146 static struct {
147 char *title;
148 game_params params;
149 } presets[] = {
150 { "2x2 Trivial", { 2, 2, SYMM_ROT2, DIFF_BLOCK } },
151 { "2x3 Basic", { 2, 3, SYMM_ROT2, DIFF_SIMPLE } },
152 { "3x3 Basic", { 3, 3, SYMM_ROT2, DIFF_SIMPLE } },
153 { "3x3 Intermediate", { 3, 3, SYMM_ROT2, DIFF_INTERSECT } },
154 { "3x3 Advanced", { 3, 3, SYMM_ROT2, DIFF_SET } },
155 { "3x4 Basic", { 3, 4, SYMM_ROT2, DIFF_SIMPLE } },
156 { "4x4 Basic", { 4, 4, SYMM_ROT2, DIFF_SIMPLE } },
157 };
158
159 if (i < 0 || i >= lenof(presets))
160 return FALSE;
161
162 *name = dupstr(presets[i].title);
163 *params = dup_params(&presets[i].params);
164
165 return TRUE;
166}
167
1d8e8ad8 168static game_params *decode_params(char const *string)
169{
170 game_params *ret = default_params();
171
172 ret->c = ret->r = atoi(string);
ef57b17d 173 ret->symm = SYMM_ROT2;
1d8e8ad8 174 while (*string && isdigit((unsigned char)*string)) string++;
175 if (*string == 'x') {
176 string++;
177 ret->r = atoi(string);
178 while (*string && isdigit((unsigned char)*string)) string++;
179 }
7c568a48 180 while (*string) {
181 if (*string == 'r' || *string == 'm' || *string == 'a') {
182 int sn, sc;
183 sc = *string++;
184 sn = atoi(string);
185 while (*string && isdigit((unsigned char)*string)) string++;
186 if (sc == 'm' && sn == 4)
187 ret->symm = SYMM_REF4;
188 if (sc == 'r' && sn == 4)
189 ret->symm = SYMM_ROT4;
190 if (sc == 'r' && sn == 2)
191 ret->symm = SYMM_ROT2;
192 if (sc == 'a')
193 ret->symm = SYMM_NONE;
194 } else if (*string == 'd') {
195 string++;
196 if (*string == 't') /* trivial */
197 string++, ret->diff = DIFF_BLOCK;
198 else if (*string == 'b') /* basic */
199 string++, ret->diff = DIFF_SIMPLE;
200 else if (*string == 'i') /* intermediate */
201 string++, ret->diff = DIFF_INTERSECT;
202 else if (*string == 'a') /* advanced */
203 string++, ret->diff = DIFF_SET;
204 } else
205 string++; /* eat unknown character */
ef57b17d 206 }
1d8e8ad8 207
208 return ret;
209}
210
211static char *encode_params(game_params *params)
212{
213 char str[80];
214
ef57b17d 215 /*
216 * Symmetry is a game generation preference and hence is left
217 * out of the encoding. Users can add it back in as they see
218 * fit.
219 */
1d8e8ad8 220 sprintf(str, "%dx%d", params->c, params->r);
221 return dupstr(str);
222}
223
224static config_item *game_configure(game_params *params)
225{
226 config_item *ret;
227 char buf[80];
228
229 ret = snewn(5, config_item);
230
231 ret[0].name = "Columns of sub-blocks";
232 ret[0].type = C_STRING;
233 sprintf(buf, "%d", params->c);
234 ret[0].sval = dupstr(buf);
235 ret[0].ival = 0;
236
237 ret[1].name = "Rows of sub-blocks";
238 ret[1].type = C_STRING;
239 sprintf(buf, "%d", params->r);
240 ret[1].sval = dupstr(buf);
241 ret[1].ival = 0;
242
ef57b17d 243 ret[2].name = "Symmetry";
244 ret[2].type = C_CHOICES;
245 ret[2].sval = ":None:2-way rotation:4-way rotation:4-way mirror";
246 ret[2].ival = params->symm;
247
7c568a48 248 ret[3].name = "Difficulty";
249 ret[3].type = C_CHOICES;
250 ret[3].sval = ":Trivial:Basic:Intermediate:Advanced";
251 ret[3].ival = params->diff;
1d8e8ad8 252
7c568a48 253 ret[4].name = NULL;
254 ret[4].type = C_END;
255 ret[4].sval = NULL;
256 ret[4].ival = 0;
1d8e8ad8 257
258 return ret;
259}
260
261static game_params *custom_params(config_item *cfg)
262{
263 game_params *ret = snew(game_params);
264
c1f743c8 265 ret->c = atoi(cfg[0].sval);
266 ret->r = atoi(cfg[1].sval);
ef57b17d 267 ret->symm = cfg[2].ival;
7c568a48 268 ret->diff = cfg[3].ival;
1d8e8ad8 269
270 return ret;
271}
272
273static char *validate_params(game_params *params)
274{
275 if (params->c < 2 || params->r < 2)
276 return "Both dimensions must be at least 2";
277 if (params->c > ORDER_MAX || params->r > ORDER_MAX)
278 return "Dimensions greater than "STR(ORDER_MAX)" are not supported";
279 return NULL;
280}
281
282/* ----------------------------------------------------------------------
283 * Full recursive Solo solver.
284 *
285 * The algorithm for this solver is shamelessly copied from a
286 * Python solver written by Andrew Wilkinson (which is GPLed, but
287 * I've reused only ideas and no code). It mostly just does the
288 * obvious recursive thing: pick an empty square, put one of the
289 * possible digits in it, recurse until all squares are filled,
290 * backtrack and change some choices if necessary.
291 *
292 * The clever bit is that every time it chooses which square to
293 * fill in next, it does so by counting the number of _possible_
294 * numbers that can go in each square, and it prioritises so that
295 * it picks a square with the _lowest_ number of possibilities. The
296 * idea is that filling in lots of the obvious bits (particularly
297 * any squares with only one possibility) will cut down on the list
298 * of possibilities for other squares and hence reduce the enormous
299 * search space as much as possible as early as possible.
300 *
301 * In practice the algorithm appeared to work very well; run on
302 * sample problems from the Times it completed in well under a
303 * second on my G5 even when written in Python, and given an empty
304 * grid (so that in principle it would enumerate _all_ solved
305 * grids!) it found the first valid solution just as quickly. So
306 * with a bit more randomisation I see no reason not to use this as
307 * my grid generator.
308 */
309
310/*
311 * Internal data structure used in solver to keep track of
312 * progress.
313 */
314struct rsolve_coord { int x, y, r; };
315struct rsolve_usage {
316 int c, r, cr; /* cr == c*r */
317 /* grid is a copy of the input grid, modified as we go along */
318 digit *grid;
319 /* row[y*cr+n-1] TRUE if digit n has been placed in row y */
320 unsigned char *row;
321 /* col[x*cr+n-1] TRUE if digit n has been placed in row x */
322 unsigned char *col;
323 /* blk[(y*c+x)*cr+n-1] TRUE if digit n has been placed in block (x,y) */
324 unsigned char *blk;
325 /* This lists all the empty spaces remaining in the grid. */
326 struct rsolve_coord *spaces;
327 int nspaces;
328 /* If we need randomisation in the solve, this is our random state. */
329 random_state *rs;
330 /* Number of solutions so far found, and maximum number we care about. */
331 int solns, maxsolns;
332};
333
334/*
335 * The real recursive step in the solving function.
336 */
337static void rsolve_real(struct rsolve_usage *usage, digit *grid)
338{
339 int c = usage->c, r = usage->r, cr = usage->cr;
340 int i, j, n, sx, sy, bestm, bestr;
341 int *digits;
342
343 /*
344 * Firstly, check for completion! If there are no spaces left
345 * in the grid, we have a solution.
346 */
347 if (usage->nspaces == 0) {
348 if (!usage->solns) {
349 /*
350 * This is our first solution, so fill in the output grid.
351 */
352 memcpy(grid, usage->grid, cr * cr);
353 }
354 usage->solns++;
355 return;
356 }
357
358 /*
359 * Otherwise, there must be at least one space. Find the most
360 * constrained space, using the `r' field as a tie-breaker.
361 */
362 bestm = cr+1; /* so that any space will beat it */
363 bestr = 0;
364 i = sx = sy = -1;
365 for (j = 0; j < usage->nspaces; j++) {
366 int x = usage->spaces[j].x, y = usage->spaces[j].y;
367 int m;
368
369 /*
370 * Find the number of digits that could go in this space.
371 */
372 m = 0;
373 for (n = 0; n < cr; n++)
374 if (!usage->row[y*cr+n] && !usage->col[x*cr+n] &&
375 !usage->blk[((y/c)*c+(x/r))*cr+n])
376 m++;
377
378 if (m < bestm || (m == bestm && usage->spaces[j].r < bestr)) {
379 bestm = m;
380 bestr = usage->spaces[j].r;
381 sx = x;
382 sy = y;
383 i = j;
384 }
385 }
386
387 /*
388 * Swap that square into the final place in the spaces array,
389 * so that decrementing nspaces will remove it from the list.
390 */
391 if (i != usage->nspaces-1) {
392 struct rsolve_coord t;
393 t = usage->spaces[usage->nspaces-1];
394 usage->spaces[usage->nspaces-1] = usage->spaces[i];
395 usage->spaces[i] = t;
396 }
397
398 /*
399 * Now we've decided which square to start our recursion at,
400 * simply go through all possible values, shuffling them
401 * randomly first if necessary.
402 */
403 digits = snewn(bestm, int);
404 j = 0;
405 for (n = 0; n < cr; n++)
406 if (!usage->row[sy*cr+n] && !usage->col[sx*cr+n] &&
407 !usage->blk[((sy/c)*c+(sx/r))*cr+n]) {
408 digits[j++] = n+1;
409 }
410
411 if (usage->rs) {
412 /* shuffle */
413 for (i = j; i > 1; i--) {
414 int p = random_upto(usage->rs, i);
415 if (p != i-1) {
416 int t = digits[p];
417 digits[p] = digits[i-1];
418 digits[i-1] = t;
419 }
420 }
421 }
422
423 /* And finally, go through the digit list and actually recurse. */
424 for (i = 0; i < j; i++) {
425 n = digits[i];
426
427 /* Update the usage structure to reflect the placing of this digit. */
428 usage->row[sy*cr+n-1] = usage->col[sx*cr+n-1] =
429 usage->blk[((sy/c)*c+(sx/r))*cr+n-1] = TRUE;
430 usage->grid[sy*cr+sx] = n;
431 usage->nspaces--;
432
433 /* Call the solver recursively. */
434 rsolve_real(usage, grid);
435
436 /*
437 * If we have seen as many solutions as we need, terminate
438 * all processing immediately.
439 */
440 if (usage->solns >= usage->maxsolns)
441 break;
442
443 /* Revert the usage structure. */
444 usage->row[sy*cr+n-1] = usage->col[sx*cr+n-1] =
445 usage->blk[((sy/c)*c+(sx/r))*cr+n-1] = FALSE;
446 usage->grid[sy*cr+sx] = 0;
447 usage->nspaces++;
448 }
449
450 sfree(digits);
451}
452
453/*
454 * Entry point to solver. You give it dimensions and a starting
455 * grid, which is simply an array of N^4 digits. In that array, 0
456 * means an empty square, and 1..N mean a clue square.
457 *
458 * Return value is the number of solutions found; searching will
459 * stop after the provided `max'. (Thus, you can pass max==1 to
460 * indicate that you only care about finding _one_ solution, or
461 * max==2 to indicate that you want to know the difference between
462 * a unique and non-unique solution.) The input parameter `grid' is
463 * also filled in with the _first_ (or only) solution found by the
464 * solver.
465 */
466static int rsolve(int c, int r, digit *grid, random_state *rs, int max)
467{
468 struct rsolve_usage *usage;
469 int x, y, cr = c*r;
470 int ret;
471
472 /*
473 * Create an rsolve_usage structure.
474 */
475 usage = snew(struct rsolve_usage);
476
477 usage->c = c;
478 usage->r = r;
479 usage->cr = cr;
480
481 usage->grid = snewn(cr * cr, digit);
482 memcpy(usage->grid, grid, cr * cr);
483
484 usage->row = snewn(cr * cr, unsigned char);
485 usage->col = snewn(cr * cr, unsigned char);
486 usage->blk = snewn(cr * cr, unsigned char);
487 memset(usage->row, FALSE, cr * cr);
488 memset(usage->col, FALSE, cr * cr);
489 memset(usage->blk, FALSE, cr * cr);
490
491 usage->spaces = snewn(cr * cr, struct rsolve_coord);
492 usage->nspaces = 0;
493
494 usage->solns = 0;
495 usage->maxsolns = max;
496
497 usage->rs = rs;
498
499 /*
500 * Now fill it in with data from the input grid.
501 */
502 for (y = 0; y < cr; y++) {
503 for (x = 0; x < cr; x++) {
504 int v = grid[y*cr+x];
505 if (v == 0) {
506 usage->spaces[usage->nspaces].x = x;
507 usage->spaces[usage->nspaces].y = y;
508 if (rs)
509 usage->spaces[usage->nspaces].r = random_bits(rs, 31);
510 else
511 usage->spaces[usage->nspaces].r = usage->nspaces;
512 usage->nspaces++;
513 } else {
514 usage->row[y*cr+v-1] = TRUE;
515 usage->col[x*cr+v-1] = TRUE;
516 usage->blk[((y/c)*c+(x/r))*cr+v-1] = TRUE;
517 }
518 }
519 }
520
521 /*
522 * Run the real recursive solving function.
523 */
524 rsolve_real(usage, grid);
525 ret = usage->solns;
526
527 /*
528 * Clean up the usage structure now we have our answer.
529 */
530 sfree(usage->spaces);
531 sfree(usage->blk);
532 sfree(usage->col);
533 sfree(usage->row);
534 sfree(usage->grid);
535 sfree(usage);
536
537 /*
538 * And return.
539 */
540 return ret;
541}
542
543/* ----------------------------------------------------------------------
544 * End of recursive solver code.
545 */
546
547/* ----------------------------------------------------------------------
548 * Less capable non-recursive solver. This one is used to check
549 * solubility of a grid as we gradually remove numbers from it: by
550 * verifying a grid using this solver we can ensure it isn't _too_
551 * hard (e.g. does not actually require guessing and backtracking).
552 *
553 * It supports a variety of specific modes of reasoning. By
554 * enabling or disabling subsets of these modes we can arrange a
555 * range of difficulty levels.
556 */
557
558/*
559 * Modes of reasoning currently supported:
560 *
561 * - Positional elimination: a number must go in a particular
562 * square because all the other empty squares in a given
563 * row/col/blk are ruled out.
564 *
565 * - Numeric elimination: a square must have a particular number
566 * in because all the other numbers that could go in it are
567 * ruled out.
568 *
7c568a48 569 * - Intersectional analysis: given two domains which overlap
1d8e8ad8 570 * (hence one must be a block, and the other can be a row or
571 * col), if the possible locations for a particular number in
572 * one of the domains can be narrowed down to the overlap, then
573 * that number can be ruled out everywhere but the overlap in
574 * the other domain too.
575 *
7c568a48 576 * - Set elimination: if there is a subset of the empty squares
577 * within a domain such that the union of the possible numbers
578 * in that subset has the same size as the subset itself, then
579 * those numbers can be ruled out everywhere else in the domain.
580 * (For example, if there are five empty squares and the
581 * possible numbers in each are 12, 23, 13, 134 and 1345, then
582 * the first three empty squares form such a subset: the numbers
583 * 1, 2 and 3 _must_ be in those three squares in some
584 * permutation, and hence we can deduce none of them can be in
585 * the fourth or fifth squares.)
586 * + You can also see this the other way round, concentrating
587 * on numbers rather than squares: if there is a subset of
588 * the unplaced numbers within a domain such that the union
589 * of all their possible positions has the same size as the
590 * subset itself, then all other numbers can be ruled out for
591 * those positions. However, it turns out that this is
592 * exactly equivalent to the first formulation at all times:
593 * there is a 1-1 correspondence between suitable subsets of
594 * the unplaced numbers and suitable subsets of the unfilled
595 * places, found by taking the _complement_ of the union of
596 * the numbers' possible positions (or the spaces' possible
597 * contents).
1d8e8ad8 598 */
599
4846f788 600/*
601 * Within this solver, I'm going to transform all y-coordinates by
602 * inverting the significance of the block number and the position
603 * within the block. That is, we will start with the top row of
604 * each block in order, then the second row of each block in order,
605 * etc.
606 *
607 * This transformation has the enormous advantage that it means
608 * every row, column _and_ block is described by an arithmetic
609 * progression of coordinates within the cubic array, so that I can
610 * use the same very simple function to do blockwise, row-wise and
611 * column-wise elimination.
612 */
613#define YTRANS(y) (((y)%c)*r+(y)/c)
614#define YUNTRANS(y) (((y)%r)*c+(y)/r)
615
1d8e8ad8 616struct nsolve_usage {
617 int c, r, cr;
618 /*
619 * We set up a cubic array, indexed by x, y and digit; each
620 * element of this array is TRUE or FALSE according to whether
621 * or not that digit _could_ in principle go in that position.
622 *
623 * The way to index this array is cube[(x*cr+y)*cr+n-1].
4846f788 624 * y-coordinates in here are transformed.
1d8e8ad8 625 */
626 unsigned char *cube;
627 /*
628 * This is the grid in which we write down our final
4846f788 629 * deductions. y-coordinates in here are _not_ transformed.
1d8e8ad8 630 */
631 digit *grid;
632 /*
633 * Now we keep track, at a slightly higher level, of what we
634 * have yet to work out, to prevent doing the same deduction
635 * many times.
636 */
637 /* row[y*cr+n-1] TRUE if digit n has been placed in row y */
638 unsigned char *row;
639 /* col[x*cr+n-1] TRUE if digit n has been placed in row x */
640 unsigned char *col;
641 /* blk[(y*c+x)*cr+n-1] TRUE if digit n has been placed in block (x,y) */
642 unsigned char *blk;
643};
4846f788 644#define cubepos(x,y,n) (((x)*usage->cr+(y))*usage->cr+(n)-1)
645#define cube(x,y,n) (usage->cube[cubepos(x,y,n)])
1d8e8ad8 646
647/*
648 * Function called when we are certain that a particular square has
4846f788 649 * a particular number in it. The y-coordinate passed in here is
650 * transformed.
1d8e8ad8 651 */
652static void nsolve_place(struct nsolve_usage *usage, int x, int y, int n)
653{
654 int c = usage->c, r = usage->r, cr = usage->cr;
655 int i, j, bx, by;
656
657 assert(cube(x,y,n));
658
659 /*
660 * Rule out all other numbers in this square.
661 */
662 for (i = 1; i <= cr; i++)
663 if (i != n)
664 cube(x,y,i) = FALSE;
665
666 /*
667 * Rule out this number in all other positions in the row.
668 */
669 for (i = 0; i < cr; i++)
670 if (i != y)
671 cube(x,i,n) = FALSE;
672
673 /*
674 * Rule out this number in all other positions in the column.
675 */
676 for (i = 0; i < cr; i++)
677 if (i != x)
678 cube(i,y,n) = FALSE;
679
680 /*
681 * Rule out this number in all other positions in the block.
682 */
683 bx = (x/r)*r;
4846f788 684 by = y % r;
1d8e8ad8 685 for (i = 0; i < r; i++)
686 for (j = 0; j < c; j++)
4846f788 687 if (bx+i != x || by+j*r != y)
688 cube(bx+i,by+j*r,n) = FALSE;
1d8e8ad8 689
690 /*
691 * Enter the number in the result grid.
692 */
4846f788 693 usage->grid[YUNTRANS(y)*cr+x] = n;
1d8e8ad8 694
695 /*
696 * Cross out this number from the list of numbers left to place
697 * in its row, its column and its block.
698 */
699 usage->row[y*cr+n-1] = usage->col[x*cr+n-1] =
7c568a48 700 usage->blk[((y%r)*c+(x/r))*cr+n-1] = TRUE;
1d8e8ad8 701}
702
7c568a48 703static int nsolve_elim(struct nsolve_usage *usage, int start, int step
704#ifdef STANDALONE_SOLVER
705 , char *fmt, ...
706#endif
707 )
1d8e8ad8 708{
4846f788 709 int c = usage->c, r = usage->r, cr = c*r;
710 int fpos, m, i;
1d8e8ad8 711
712 /*
4846f788 713 * Count the number of set bits within this section of the
714 * cube.
1d8e8ad8 715 */
716 m = 0;
4846f788 717 fpos = -1;
718 for (i = 0; i < cr; i++)
719 if (usage->cube[start+i*step]) {
720 fpos = start+i*step;
1d8e8ad8 721 m++;
722 }
723
724 if (m == 1) {
4846f788 725 int x, y, n;
726 assert(fpos >= 0);
1d8e8ad8 727
4846f788 728 n = 1 + fpos % cr;
729 y = fpos / cr;
730 x = y / cr;
731 y %= cr;
1d8e8ad8 732
3ddae0ff 733 if (!usage->grid[YUNTRANS(y)*cr+x]) {
7c568a48 734#ifdef STANDALONE_SOLVER
735 if (solver_show_working) {
736 va_list ap;
737 va_start(ap, fmt);
738 vprintf(fmt, ap);
739 va_end(ap);
740 printf(":\n placing %d at (%d,%d)\n",
741 n, 1+x, 1+YUNTRANS(y));
742 }
743#endif
3ddae0ff 744 nsolve_place(usage, x, y, n);
745 return TRUE;
746 }
1d8e8ad8 747 }
748
749 return FALSE;
750}
751
7c568a48 752static int nsolve_intersect(struct nsolve_usage *usage,
753 int start1, int step1, int start2, int step2
754#ifdef STANDALONE_SOLVER
755 , char *fmt, ...
756#endif
757 )
758{
759 int c = usage->c, r = usage->r, cr = c*r;
760 int ret, i;
761
762 /*
763 * Loop over the first domain and see if there's any set bit
764 * not also in the second.
765 */
766 for (i = 0; i < cr; i++) {
767 int p = start1+i*step1;
768 if (usage->cube[p] &&
769 !(p >= start2 && p < start2+cr*step2 &&
770 (p - start2) % step2 == 0))
771 return FALSE; /* there is, so we can't deduce */
772 }
773
774 /*
775 * We have determined that all set bits in the first domain are
776 * within its overlap with the second. So loop over the second
777 * domain and remove all set bits that aren't also in that
778 * overlap; return TRUE iff we actually _did_ anything.
779 */
780 ret = FALSE;
781 for (i = 0; i < cr; i++) {
782 int p = start2+i*step2;
783 if (usage->cube[p] &&
784 !(p >= start1 && p < start1+cr*step1 && (p - start1) % step1 == 0))
785 {
786#ifdef STANDALONE_SOLVER
787 if (solver_show_working) {
788 int px, py, pn;
789
790 if (!ret) {
791 va_list ap;
792 va_start(ap, fmt);
793 vprintf(fmt, ap);
794 va_end(ap);
795 printf(":\n");
796 }
797
798 pn = 1 + p % cr;
799 py = p / cr;
800 px = py / cr;
801 py %= cr;
802
803 printf(" ruling out %d at (%d,%d)\n",
804 pn, 1+px, 1+YUNTRANS(py));
805 }
806#endif
807 ret = TRUE; /* we did something */
808 usage->cube[p] = 0;
809 }
810 }
811
812 return ret;
813}
814
815static int nsolve_set(struct nsolve_usage *usage,
816 int start, int step1, int step2
817#ifdef STANDALONE_SOLVER
818 , char *fmt, ...
819#endif
820 )
821{
822 int c = usage->c, r = usage->r, cr = c*r;
823 int i, j, n, count;
824 unsigned char *grid = snewn(cr*cr, unsigned char);
825 unsigned char *rowidx = snewn(cr, unsigned char);
826 unsigned char *colidx = snewn(cr, unsigned char);
827 unsigned char *set = snewn(cr, unsigned char);
828
829 /*
830 * We are passed a cr-by-cr matrix of booleans. Our first job
831 * is to winnow it by finding any definite placements - i.e.
832 * any row with a solitary 1 - and discarding that row and the
833 * column containing the 1.
834 */
835 memset(rowidx, TRUE, cr);
836 memset(colidx, TRUE, cr);
837 for (i = 0; i < cr; i++) {
838 int count = 0, first = -1;
839 for (j = 0; j < cr; j++)
840 if (usage->cube[start+i*step1+j*step2])
841 first = j, count++;
842 if (count == 0) {
843 /*
844 * This condition actually marks a completely insoluble
845 * (i.e. internally inconsistent) puzzle. We return and
846 * report no progress made.
847 */
848 return FALSE;
849 }
850 if (count == 1)
851 rowidx[i] = colidx[first] = FALSE;
852 }
853
854 /*
855 * Convert each of rowidx/colidx from a list of 0s and 1s to a
856 * list of the indices of the 1s.
857 */
858 for (i = j = 0; i < cr; i++)
859 if (rowidx[i])
860 rowidx[j++] = i;
861 n = j;
862 for (i = j = 0; i < cr; i++)
863 if (colidx[i])
864 colidx[j++] = i;
865 assert(n == j);
866
867 /*
868 * And create the smaller matrix.
869 */
870 for (i = 0; i < n; i++)
871 for (j = 0; j < n; j++)
872 grid[i*cr+j] = usage->cube[start+rowidx[i]*step1+colidx[j]*step2];
873
874 /*
875 * Having done that, we now have a matrix in which every row
876 * has at least two 1s in. Now we search to see if we can find
877 * a rectangle of zeroes (in the set-theoretic sense of
878 * `rectangle', i.e. a subset of rows crossed with a subset of
879 * columns) whose width and height add up to n.
880 */
881
882 memset(set, 0, n);
883 count = 0;
884 while (1) {
885 /*
886 * We have a candidate set. If its size is <=1 or >=n-1
887 * then we move on immediately.
888 */
889 if (count > 1 && count < n-1) {
890 /*
891 * The number of rows we need is n-count. See if we can
892 * find that many rows which each have a zero in all
893 * the positions listed in `set'.
894 */
895 int rows = 0;
896 for (i = 0; i < n; i++) {
897 int ok = TRUE;
898 for (j = 0; j < n; j++)
899 if (set[j] && grid[i*cr+j]) {
900 ok = FALSE;
901 break;
902 }
903 if (ok)
904 rows++;
905 }
906
907 /*
908 * We expect never to be able to get _more_ than
909 * n-count suitable rows: this would imply that (for
910 * example) there are four numbers which between them
911 * have at most three possible positions, and hence it
912 * indicates a faulty deduction before this point or
913 * even a bogus clue.
914 */
915 assert(rows <= n - count);
916 if (rows >= n - count) {
917 int progress = FALSE;
918
919 /*
920 * We've got one! Now, for each row which _doesn't_
921 * satisfy the criterion, eliminate all its set
922 * bits in the positions _not_ listed in `set'.
923 * Return TRUE (meaning progress has been made) if
924 * we successfully eliminated anything at all.
925 *
926 * This involves referring back through
927 * rowidx/colidx in order to work out which actual
928 * positions in the cube to meddle with.
929 */
930 for (i = 0; i < n; i++) {
931 int ok = TRUE;
932 for (j = 0; j < n; j++)
933 if (set[j] && grid[i*cr+j]) {
934 ok = FALSE;
935 break;
936 }
937 if (!ok) {
938 for (j = 0; j < n; j++)
939 if (!set[j] && grid[i*cr+j]) {
940 int fpos = (start+rowidx[i]*step1+
941 colidx[j]*step2);
942#ifdef STANDALONE_SOLVER
943 if (solver_show_working) {
944 int px, py, pn;
945
946 if (!progress) {
947 va_list ap;
948 va_start(ap, fmt);
949 vprintf(fmt, ap);
950 va_end(ap);
951 printf(":\n");
952 }
953
954 pn = 1 + fpos % cr;
955 py = fpos / cr;
956 px = py / cr;
957 py %= cr;
958
959 printf(" ruling out %d at (%d,%d)\n",
960 pn, 1+px, 1+YUNTRANS(py));
961 }
962#endif
963 progress = TRUE;
964 usage->cube[fpos] = FALSE;
965 }
966 }
967 }
968
969 if (progress) {
970 sfree(set);
971 sfree(colidx);
972 sfree(rowidx);
973 sfree(grid);
974 return TRUE;
975 }
976 }
977 }
978
979 /*
980 * Binary increment: change the rightmost 0 to a 1, and
981 * change all 1s to the right of it to 0s.
982 */
983 i = n;
984 while (i > 0 && set[i-1])
985 set[--i] = 0, count--;
986 if (i > 0)
987 set[--i] = 1, count++;
988 else
989 break; /* done */
990 }
991
992 sfree(set);
993 sfree(colidx);
994 sfree(rowidx);
995 sfree(grid);
996
997 return FALSE;
998}
999
1d8e8ad8 1000static int nsolve(int c, int r, digit *grid)
1001{
1002 struct nsolve_usage *usage;
1003 int cr = c*r;
1004 int x, y, n;
7c568a48 1005 int diff = DIFF_BLOCK;
1d8e8ad8 1006
1007 /*
1008 * Set up a usage structure as a clean slate (everything
1009 * possible).
1010 */
1011 usage = snew(struct nsolve_usage);
1012 usage->c = c;
1013 usage->r = r;
1014 usage->cr = cr;
1015 usage->cube = snewn(cr*cr*cr, unsigned char);
1016 usage->grid = grid; /* write straight back to the input */
1017 memset(usage->cube, TRUE, cr*cr*cr);
1018
1019 usage->row = snewn(cr * cr, unsigned char);
1020 usage->col = snewn(cr * cr, unsigned char);
1021 usage->blk = snewn(cr * cr, unsigned char);
1022 memset(usage->row, FALSE, cr * cr);
1023 memset(usage->col, FALSE, cr * cr);
1024 memset(usage->blk, FALSE, cr * cr);
1025
1026 /*
1027 * Place all the clue numbers we are given.
1028 */
1029 for (x = 0; x < cr; x++)
1030 for (y = 0; y < cr; y++)
1031 if (grid[y*cr+x])
4846f788 1032 nsolve_place(usage, x, YTRANS(y), grid[y*cr+x]);
1d8e8ad8 1033
1034 /*
1035 * Now loop over the grid repeatedly trying all permitted modes
1036 * of reasoning. The loop terminates if we complete an
1037 * iteration without making any progress; we then return
1038 * failure or success depending on whether the grid is full or
1039 * not.
1040 */
1041 while (1) {
7c568a48 1042 /*
1043 * I'd like to write `continue;' inside each of the
1044 * following loops, so that the solver returns here after
1045 * making some progress. However, I can't specify that I
1046 * want to continue an outer loop rather than the innermost
1047 * one, so I'm apologetically resorting to a goto.
1048 */
3ddae0ff 1049 cont:
1050
1d8e8ad8 1051 /*
1052 * Blockwise positional elimination.
1053 */
4846f788 1054 for (x = 0; x < cr; x += r)
1d8e8ad8 1055 for (y = 0; y < r; y++)
1056 for (n = 1; n <= cr; n++)
4846f788 1057 if (!usage->blk[(y*c+(x/r))*cr+n-1] &&
7c568a48 1058 nsolve_elim(usage, cubepos(x,y,n), r*cr
1059#ifdef STANDALONE_SOLVER
1060 , "positional elimination,"
1061 " block (%d,%d)", 1+x/r, 1+y
1062#endif
1063 )) {
1064 diff = max(diff, DIFF_BLOCK);
3ddae0ff 1065 goto cont;
7c568a48 1066 }
1d8e8ad8 1067
1068 /*
1069 * Row-wise positional elimination.
1070 */
1071 for (y = 0; y < cr; y++)
1072 for (n = 1; n <= cr; n++)
1073 if (!usage->row[y*cr+n-1] &&
7c568a48 1074 nsolve_elim(usage, cubepos(0,y,n), cr*cr
1075#ifdef STANDALONE_SOLVER
1076 , "positional elimination,"
1077 " row %d", 1+YUNTRANS(y)
1078#endif
1079 )) {
1080 diff = max(diff, DIFF_SIMPLE);
3ddae0ff 1081 goto cont;
7c568a48 1082 }
1d8e8ad8 1083 /*
1084 * Column-wise positional elimination.
1085 */
1086 for (x = 0; x < cr; x++)
1087 for (n = 1; n <= cr; n++)
1088 if (!usage->col[x*cr+n-1] &&
7c568a48 1089 nsolve_elim(usage, cubepos(x,0,n), cr
1090#ifdef STANDALONE_SOLVER
1091 , "positional elimination," " column %d", 1+x
1092#endif
1093 )) {
1094 diff = max(diff, DIFF_SIMPLE);
3ddae0ff 1095 goto cont;
7c568a48 1096 }
1d8e8ad8 1097
1098 /*
1099 * Numeric elimination.
1100 */
1101 for (x = 0; x < cr; x++)
1102 for (y = 0; y < cr; y++)
4846f788 1103 if (!usage->grid[YUNTRANS(y)*cr+x] &&
7c568a48 1104 nsolve_elim(usage, cubepos(x,y,1), 1
1105#ifdef STANDALONE_SOLVER
1106 , "numeric elimination at (%d,%d)", 1+x,
1107 1+YUNTRANS(y)
1108#endif
1109 )) {
1110 diff = max(diff, DIFF_SIMPLE);
1111 goto cont;
1112 }
1113
1114 /*
1115 * Intersectional analysis, rows vs blocks.
1116 */
1117 for (y = 0; y < cr; y++)
1118 for (x = 0; x < cr; x += r)
1119 for (n = 1; n <= cr; n++)
1120 if (!usage->row[y*cr+n-1] &&
1121 !usage->blk[((y%r)*c+(x/r))*cr+n-1] &&
1122 (nsolve_intersect(usage, cubepos(0,y,n), cr*cr,
1123 cubepos(x,y%r,n), r*cr
1124#ifdef STANDALONE_SOLVER
1125 , "intersectional analysis,"
1126 " row %d vs block (%d,%d)",
1127 1+YUNTRANS(y), 1+x, 1+y%r
1128#endif
1129 ) ||
1130 nsolve_intersect(usage, cubepos(x,y%r,n), r*cr,
1131 cubepos(0,y,n), cr*cr
1132#ifdef STANDALONE_SOLVER
1133 , "intersectional analysis,"
1134 " block (%d,%d) vs row %d",
1135 1+x, 1+y%r, 1+YUNTRANS(y)
1136#endif
1137 ))) {
1138 diff = max(diff, DIFF_INTERSECT);
1139 goto cont;
1140 }
1141
1142 /*
1143 * Intersectional analysis, columns vs blocks.
1144 */
1145 for (x = 0; x < cr; x++)
1146 for (y = 0; y < r; y++)
1147 for (n = 1; n <= cr; n++)
1148 if (!usage->col[x*cr+n-1] &&
1149 !usage->blk[(y*c+(x/r))*cr+n-1] &&
1150 (nsolve_intersect(usage, cubepos(x,0,n), cr,
1151 cubepos((x/r)*r,y,n), r*cr
1152#ifdef STANDALONE_SOLVER
1153 , "intersectional analysis,"
1154 " column %d vs block (%d,%d)",
1155 1+x, 1+x/r, 1+y
1156#endif
1157 ) ||
1158 nsolve_intersect(usage, cubepos((x/r)*r,y,n), r*cr,
1159 cubepos(x,0,n), cr
1160#ifdef STANDALONE_SOLVER
1161 , "intersectional analysis,"
1162 " block (%d,%d) vs column %d",
1163 1+x/r, 1+y, 1+x
1164#endif
1165 ))) {
1166 diff = max(diff, DIFF_INTERSECT);
1167 goto cont;
1168 }
1169
1170 /*
1171 * Blockwise set elimination.
1172 */
1173 for (x = 0; x < cr; x += r)
1174 for (y = 0; y < r; y++)
1175 if (nsolve_set(usage, cubepos(x,y,1), r*cr, 1
1176#ifdef STANDALONE_SOLVER
1177 , "set elimination, block (%d,%d)", 1+x/r, 1+y
1178#endif
1179 )) {
1180 diff = max(diff, DIFF_SET);
1181 goto cont;
1182 }
1183
1184 /*
1185 * Row-wise set elimination.
1186 */
1187 for (y = 0; y < cr; y++)
1188 if (nsolve_set(usage, cubepos(0,y,1), cr*cr, 1
1189#ifdef STANDALONE_SOLVER
1190 , "set elimination, row %d", 1+YUNTRANS(y)
1191#endif
1192 )) {
1193 diff = max(diff, DIFF_SET);
1194 goto cont;
1195 }
1196
1197 /*
1198 * Column-wise set elimination.
1199 */
1200 for (x = 0; x < cr; x++)
1201 if (nsolve_set(usage, cubepos(x,0,1), cr, 1
1202#ifdef STANDALONE_SOLVER
1203 , "set elimination, column %d", 1+x
1204#endif
1205 )) {
1206 diff = max(diff, DIFF_SET);
1207 goto cont;
1208 }
1d8e8ad8 1209
1210 /*
1211 * If we reach here, we have made no deductions in this
1212 * iteration, so the algorithm terminates.
1213 */
1214 break;
1215 }
1216
1217 sfree(usage->cube);
1218 sfree(usage->row);
1219 sfree(usage->col);
1220 sfree(usage->blk);
1221 sfree(usage);
1222
1223 for (x = 0; x < cr; x++)
1224 for (y = 0; y < cr; y++)
1225 if (!grid[y*cr+x])
7c568a48 1226 return DIFF_IMPOSSIBLE;
1227 return diff;
1d8e8ad8 1228}
1229
1230/* ----------------------------------------------------------------------
1231 * End of non-recursive solver code.
1232 */
1233
1234/*
1235 * Check whether a grid contains a valid complete puzzle.
1236 */
1237static int check_valid(int c, int r, digit *grid)
1238{
1239 int cr = c*r;
1240 unsigned char *used;
1241 int x, y, n;
1242
1243 used = snewn(cr, unsigned char);
1244
1245 /*
1246 * Check that each row contains precisely one of everything.
1247 */
1248 for (y = 0; y < cr; y++) {
1249 memset(used, FALSE, cr);
1250 for (x = 0; x < cr; x++)
1251 if (grid[y*cr+x] > 0 && grid[y*cr+x] <= cr)
1252 used[grid[y*cr+x]-1] = TRUE;
1253 for (n = 0; n < cr; n++)
1254 if (!used[n]) {
1255 sfree(used);
1256 return FALSE;
1257 }
1258 }
1259
1260 /*
1261 * Check that each column contains precisely one of everything.
1262 */
1263 for (x = 0; x < cr; x++) {
1264 memset(used, FALSE, cr);
1265 for (y = 0; y < cr; y++)
1266 if (grid[y*cr+x] > 0 && grid[y*cr+x] <= cr)
1267 used[grid[y*cr+x]-1] = TRUE;
1268 for (n = 0; n < cr; n++)
1269 if (!used[n]) {
1270 sfree(used);
1271 return FALSE;
1272 }
1273 }
1274
1275 /*
1276 * Check that each block contains precisely one of everything.
1277 */
1278 for (x = 0; x < cr; x += r) {
1279 for (y = 0; y < cr; y += c) {
1280 int xx, yy;
1281 memset(used, FALSE, cr);
1282 for (xx = x; xx < x+r; xx++)
1283 for (yy = 0; yy < y+c; yy++)
1284 if (grid[yy*cr+xx] > 0 && grid[yy*cr+xx] <= cr)
1285 used[grid[yy*cr+xx]-1] = TRUE;
1286 for (n = 0; n < cr; n++)
1287 if (!used[n]) {
1288 sfree(used);
1289 return FALSE;
1290 }
1291 }
1292 }
1293
1294 sfree(used);
1295 return TRUE;
1296}
1297
ef57b17d 1298static void symmetry_limit(game_params *params, int *xlim, int *ylim, int s)
1299{
1300 int c = params->c, r = params->r, cr = c*r;
1301
1302 switch (s) {
1303 case SYMM_NONE:
1304 *xlim = *ylim = cr;
1305 break;
1306 case SYMM_ROT2:
1307 *xlim = (cr+1) / 2;
1308 *ylim = cr;
1309 break;
1310 case SYMM_REF4:
1311 case SYMM_ROT4:
1312 *xlim = *ylim = (cr+1) / 2;
1313 break;
1314 }
1315}
1316
1317static int symmetries(game_params *params, int x, int y, int *output, int s)
1318{
1319 int c = params->c, r = params->r, cr = c*r;
1320 int i = 0;
1321
1322 *output++ = x;
1323 *output++ = y;
1324 i++;
1325
1326 switch (s) {
1327 case SYMM_NONE:
1328 break; /* just x,y is all we need */
1329 case SYMM_REF4:
1330 case SYMM_ROT4:
1331 switch (s) {
1332 case SYMM_REF4:
1333 *output++ = cr - 1 - x;
1334 *output++ = y;
1335 i++;
1336
1337 *output++ = x;
1338 *output++ = cr - 1 - y;
1339 i++;
1340 break;
1341 case SYMM_ROT4:
1342 *output++ = cr - 1 - y;
1343 *output++ = x;
1344 i++;
1345
1346 *output++ = y;
1347 *output++ = cr - 1 - x;
1348 i++;
1349 break;
1350 }
1351 /* fall through */
1352 case SYMM_ROT2:
1353 *output++ = cr - 1 - x;
1354 *output++ = cr - 1 - y;
1355 i++;
1356 break;
1357 }
1358
1359 return i;
1360}
1361
1d8e8ad8 1362static char *new_game_seed(game_params *params, random_state *rs)
1363{
1364 int c = params->c, r = params->r, cr = c*r;
1365 int area = cr*cr;
1366 digit *grid, *grid2;
1367 struct xy { int x, y; } *locs;
1368 int nlocs;
1369 int ret;
1370 char *seed;
ef57b17d 1371 int coords[16], ncoords;
1372 int xlim, ylim;
7c568a48 1373 int maxdiff;
1d8e8ad8 1374
1375 /*
7c568a48 1376 * Adjust the maximum difficulty level to be consistent with
1377 * the puzzle size: all 2x2 puzzles appear to be Trivial
1378 * (DIFF_BLOCK) so we cannot hold out for even a Basic
1379 * (DIFF_SIMPLE) one.
1d8e8ad8 1380 */
7c568a48 1381 maxdiff = params->diff;
1382 if (c == 2 && r == 2)
1383 maxdiff = DIFF_BLOCK;
1d8e8ad8 1384
7c568a48 1385 grid = snewn(area, digit);
ef57b17d 1386 locs = snewn(area, struct xy);
1d8e8ad8 1387 grid2 = snewn(area, digit);
1d8e8ad8 1388
7c568a48 1389 /*
1390 * Loop until we get a grid of the required difficulty. This is
1391 * nasty, but it seems to be unpleasantly hard to generate
1392 * difficult grids otherwise.
1393 */
1394 do {
1395 /*
1396 * Start the recursive solver with an empty grid to generate a
1397 * random solved state.
1398 */
1399 memset(grid, 0, area);
1400 ret = rsolve(c, r, grid, rs, 1);
1401 assert(ret == 1);
1402 assert(check_valid(c, r, grid));
1403
1404 /*
1405 * Now we have a solved grid, start removing things from it
1406 * while preserving solubility.
1407 */
1408 symmetry_limit(params, &xlim, &ylim, params->symm);
1409 while (1) {
1410 int x, y, i, j;
1411
1412 /*
1413 * Iterate over the grid and enumerate all the filled
1414 * squares we could empty.
1415 */
1416 nlocs = 0;
1417
1418 for (x = 0; x < xlim; x++)
1419 for (y = 0; y < ylim; y++)
1420 if (grid[y*cr+x]) {
1421 locs[nlocs].x = x;
1422 locs[nlocs].y = y;
1423 nlocs++;
1424 }
1425
1426 /*
1427 * Now shuffle that list.
1428 */
1429 for (i = nlocs; i > 1; i--) {
1430 int p = random_upto(rs, i);
1431 if (p != i-1) {
1432 struct xy t = locs[p];
1433 locs[p] = locs[i-1];
1434 locs[i-1] = t;
1435 }
1436 }
1437
1438 /*
1439 * Now loop over the shuffled list and, for each element,
1440 * see whether removing that element (and its reflections)
1441 * from the grid will still leave the grid soluble by
1442 * nsolve.
1443 */
1444 for (i = 0; i < nlocs; i++) {
1445 x = locs[i].x;
1446 y = locs[i].y;
1447
1448 memcpy(grid2, grid, area);
1449 ncoords = symmetries(params, x, y, coords, params->symm);
1450 for (j = 0; j < ncoords; j++)
1451 grid2[coords[2*j+1]*cr+coords[2*j]] = 0;
1452
1453 if (nsolve(c, r, grid2) <= maxdiff) {
1454 for (j = 0; j < ncoords; j++)
1455 grid[coords[2*j+1]*cr+coords[2*j]] = 0;
1456 break;
1457 }
1458 }
1459
1460 if (i == nlocs) {
1461 /*
1462 * There was nothing we could remove without destroying
1463 * solvability.
1464 */
1465 break;
1466 }
1467 }
1d8e8ad8 1468
7c568a48 1469 memcpy(grid2, grid, area);
1470 } while (nsolve(c, r, grid2) != maxdiff);
1d8e8ad8 1471
1d8e8ad8 1472 sfree(grid2);
1473 sfree(locs);
1474
1d8e8ad8 1475 /*
1476 * Now we have the grid as it will be presented to the user.
1477 * Encode it in a game seed.
1478 */
1479 {
1480 char *p;
1481 int run, i;
1482
1483 seed = snewn(5 * area, char);
1484 p = seed;
1485 run = 0;
1486 for (i = 0; i <= area; i++) {
1487 int n = (i < area ? grid[i] : -1);
1488
1489 if (!n)
1490 run++;
1491 else {
1492 if (run) {
1493 while (run > 0) {
1494 int c = 'a' - 1 + run;
1495 if (run > 26)
1496 c = 'z';
1497 *p++ = c;
1498 run -= c - ('a' - 1);
1499 }
1500 } else {
1501 /*
1502 * If there's a number in the very top left or
1503 * bottom right, there's no point putting an
1504 * unnecessary _ before or after it.
1505 */
1506 if (p > seed && n > 0)
1507 *p++ = '_';
1508 }
1509 if (n > 0)
1510 p += sprintf(p, "%d", n);
1511 run = 0;
1512 }
1513 }
1514 assert(p - seed < 5 * area);
1515 *p++ = '\0';
1516 seed = sresize(seed, p - seed, char);
1517 }
1518
1519 sfree(grid);
1520
1521 return seed;
1522}
1523
1524static char *validate_seed(game_params *params, char *seed)
1525{
1526 int area = params->r * params->r * params->c * params->c;
1527 int squares = 0;
1528
1529 while (*seed) {
1530 int n = *seed++;
1531 if (n >= 'a' && n <= 'z') {
1532 squares += n - 'a' + 1;
1533 } else if (n == '_') {
1534 /* do nothing */;
1535 } else if (n > '0' && n <= '9') {
1536 squares++;
1537 while (*seed >= '0' && *seed <= '9')
1538 seed++;
1539 } else
1540 return "Invalid character in game specification";
1541 }
1542
1543 if (squares < area)
1544 return "Not enough data to fill grid";
1545
1546 if (squares > area)
1547 return "Too much data to fit in grid";
1548
1549 return NULL;
1550}
1551
1552static game_state *new_game(game_params *params, char *seed)
1553{
1554 game_state *state = snew(game_state);
1555 int c = params->c, r = params->r, cr = c*r, area = cr * cr;
1556 int i;
1557
1558 state->c = params->c;
1559 state->r = params->r;
1560
1561 state->grid = snewn(area, digit);
1562 state->immutable = snewn(area, unsigned char);
1563 memset(state->immutable, FALSE, area);
1564
1565 state->completed = FALSE;
1566
1567 i = 0;
1568 while (*seed) {
1569 int n = *seed++;
1570 if (n >= 'a' && n <= 'z') {
1571 int run = n - 'a' + 1;
1572 assert(i + run <= area);
1573 while (run-- > 0)
1574 state->grid[i++] = 0;
1575 } else if (n == '_') {
1576 /* do nothing */;
1577 } else if (n > '0' && n <= '9') {
1578 assert(i < area);
1579 state->immutable[i] = TRUE;
1580 state->grid[i++] = atoi(seed-1);
1581 while (*seed >= '0' && *seed <= '9')
1582 seed++;
1583 } else {
1584 assert(!"We can't get here");
1585 }
1586 }
1587 assert(i == area);
1588
1589 return state;
1590}
1591
1592static game_state *dup_game(game_state *state)
1593{
1594 game_state *ret = snew(game_state);
1595 int c = state->c, r = state->r, cr = c*r, area = cr * cr;
1596
1597 ret->c = state->c;
1598 ret->r = state->r;
1599
1600 ret->grid = snewn(area, digit);
1601 memcpy(ret->grid, state->grid, area);
1602
1603 ret->immutable = snewn(area, unsigned char);
1604 memcpy(ret->immutable, state->immutable, area);
1605
1606 ret->completed = state->completed;
1607
1608 return ret;
1609}
1610
1611static void free_game(game_state *state)
1612{
1613 sfree(state->immutable);
1614 sfree(state->grid);
1615 sfree(state);
1616}
1617
1618struct game_ui {
1619 /*
1620 * These are the coordinates of the currently highlighted
1621 * square on the grid, or -1,-1 if there isn't one. When there
1622 * is, pressing a valid number or letter key or Space will
1623 * enter that number or letter in the grid.
1624 */
1625 int hx, hy;
1626};
1627
1628static game_ui *new_ui(game_state *state)
1629{
1630 game_ui *ui = snew(game_ui);
1631
1632 ui->hx = ui->hy = -1;
1633
1634 return ui;
1635}
1636
1637static void free_ui(game_ui *ui)
1638{
1639 sfree(ui);
1640}
1641
1642static game_state *make_move(game_state *from, game_ui *ui, int x, int y,
1643 int button)
1644{
1645 int c = from->c, r = from->r, cr = c*r;
1646 int tx, ty;
1647 game_state *ret;
1648
ae812854 1649 tx = (x + TILE_SIZE - BORDER) / TILE_SIZE - 1;
1650 ty = (y + TILE_SIZE - BORDER) / TILE_SIZE - 1;
1d8e8ad8 1651
1652 if (tx >= 0 && tx < cr && ty >= 0 && ty < cr && button == LEFT_BUTTON) {
1653 if (tx == ui->hx && ty == ui->hy) {
1654 ui->hx = ui->hy = -1;
1655 } else {
1656 ui->hx = tx;
1657 ui->hy = ty;
1658 }
1659 return from; /* UI activity occurred */
1660 }
1661
1662 if (ui->hx != -1 && ui->hy != -1 &&
1663 ((button >= '1' && button <= '9' && button - '0' <= cr) ||
1664 (button >= 'a' && button <= 'z' && button - 'a' + 10 <= cr) ||
1665 (button >= 'A' && button <= 'Z' && button - 'A' + 10 <= cr) ||
1666 button == ' ')) {
1667 int n = button - '0';
1668 if (button >= 'A' && button <= 'Z')
1669 n = button - 'A' + 10;
1670 if (button >= 'a' && button <= 'z')
1671 n = button - 'a' + 10;
1672 if (button == ' ')
1673 n = 0;
1674
1675 if (from->immutable[ui->hy*cr+ui->hx])
1676 return NULL; /* can't overwrite this square */
1677
1678 ret = dup_game(from);
1679 ret->grid[ui->hy*cr+ui->hx] = n;
1680 ui->hx = ui->hy = -1;
1681
1682 /*
1683 * We've made a real change to the grid. Check to see
1684 * if the game has been completed.
1685 */
1686 if (!ret->completed && check_valid(c, r, ret->grid)) {
1687 ret->completed = TRUE;
1688 }
1689
1690 return ret; /* made a valid move */
1691 }
1692
1693 return NULL;
1694}
1695
1696/* ----------------------------------------------------------------------
1697 * Drawing routines.
1698 */
1699
1700struct game_drawstate {
1701 int started;
1702 int c, r, cr;
1703 digit *grid;
1704 unsigned char *hl;
1705};
1706
1707#define XSIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
1708#define YSIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
1709
1710static void game_size(game_params *params, int *x, int *y)
1711{
1712 int c = params->c, r = params->r, cr = c*r;
1713
1714 *x = XSIZE(cr);
1715 *y = YSIZE(cr);
1716}
1717
1718static float *game_colours(frontend *fe, game_state *state, int *ncolours)
1719{
1720 float *ret = snewn(3 * NCOLOURS, float);
1721
1722 frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
1723
1724 ret[COL_GRID * 3 + 0] = 0.0F;
1725 ret[COL_GRID * 3 + 1] = 0.0F;
1726 ret[COL_GRID * 3 + 2] = 0.0F;
1727
1728 ret[COL_CLUE * 3 + 0] = 0.0F;
1729 ret[COL_CLUE * 3 + 1] = 0.0F;
1730 ret[COL_CLUE * 3 + 2] = 0.0F;
1731
1732 ret[COL_USER * 3 + 0] = 0.0F;
1733 ret[COL_USER * 3 + 1] = 0.6F * ret[COL_BACKGROUND * 3 + 1];
1734 ret[COL_USER * 3 + 2] = 0.0F;
1735
1736 ret[COL_HIGHLIGHT * 3 + 0] = 0.85F * ret[COL_BACKGROUND * 3 + 0];
1737 ret[COL_HIGHLIGHT * 3 + 1] = 0.85F * ret[COL_BACKGROUND * 3 + 1];
1738 ret[COL_HIGHLIGHT * 3 + 2] = 0.85F * ret[COL_BACKGROUND * 3 + 2];
1739
1740 *ncolours = NCOLOURS;
1741 return ret;
1742}
1743
1744static game_drawstate *game_new_drawstate(game_state *state)
1745{
1746 struct game_drawstate *ds = snew(struct game_drawstate);
1747 int c = state->c, r = state->r, cr = c*r;
1748
1749 ds->started = FALSE;
1750 ds->c = c;
1751 ds->r = r;
1752 ds->cr = cr;
1753 ds->grid = snewn(cr*cr, digit);
1754 memset(ds->grid, 0, cr*cr);
1755 ds->hl = snewn(cr*cr, unsigned char);
1756 memset(ds->hl, 0, cr*cr);
1757
1758 return ds;
1759}
1760
1761static void game_free_drawstate(game_drawstate *ds)
1762{
1763 sfree(ds->hl);
1764 sfree(ds->grid);
1765 sfree(ds);
1766}
1767
1768static void draw_number(frontend *fe, game_drawstate *ds, game_state *state,
1769 int x, int y, int hl)
1770{
1771 int c = state->c, r = state->r, cr = c*r;
1772 int tx, ty;
1773 int cx, cy, cw, ch;
1774 char str[2];
1775
1776 if (ds->grid[y*cr+x] == state->grid[y*cr+x] && ds->hl[y*cr+x] == hl)
1777 return; /* no change required */
1778
1779 tx = BORDER + x * TILE_SIZE + 2;
1780 ty = BORDER + y * TILE_SIZE + 2;
1781
1782 cx = tx;
1783 cy = ty;
1784 cw = TILE_SIZE-3;
1785 ch = TILE_SIZE-3;
1786
1787 if (x % r)
1788 cx--, cw++;
1789 if ((x+1) % r)
1790 cw++;
1791 if (y % c)
1792 cy--, ch++;
1793 if ((y+1) % c)
1794 ch++;
1795
1796 clip(fe, cx, cy, cw, ch);
1797
1798 /* background needs erasing? */
1799 if (ds->grid[y*cr+x] || ds->hl[y*cr+x] != hl)
1800 draw_rect(fe, cx, cy, cw, ch, hl ? COL_HIGHLIGHT : COL_BACKGROUND);
1801
1802 /* new number needs drawing? */
1803 if (state->grid[y*cr+x]) {
1804 str[1] = '\0';
1805 str[0] = state->grid[y*cr+x] + '0';
1806 if (str[0] > '9')
1807 str[0] += 'a' - ('9'+1);
1808 draw_text(fe, tx + TILE_SIZE/2, ty + TILE_SIZE/2,
1809 FONT_VARIABLE, TILE_SIZE/2, ALIGN_VCENTRE | ALIGN_HCENTRE,
1810 state->immutable[y*cr+x] ? COL_CLUE : COL_USER, str);
1811 }
1812
1813 unclip(fe);
1814
1815 draw_update(fe, cx, cy, cw, ch);
1816
1817 ds->grid[y*cr+x] = state->grid[y*cr+x];
1818 ds->hl[y*cr+x] = hl;
1819}
1820
1821static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
1822 game_state *state, int dir, game_ui *ui,
1823 float animtime, float flashtime)
1824{
1825 int c = state->c, r = state->r, cr = c*r;
1826 int x, y;
1827
1828 if (!ds->started) {
1829 /*
1830 * The initial contents of the window are not guaranteed
1831 * and can vary with front ends. To be on the safe side,
1832 * all games should start by drawing a big
1833 * background-colour rectangle covering the whole window.
1834 */
1835 draw_rect(fe, 0, 0, XSIZE(cr), YSIZE(cr), COL_BACKGROUND);
1836
1837 /*
1838 * Draw the grid.
1839 */
1840 for (x = 0; x <= cr; x++) {
1841 int thick = (x % r ? 0 : 1);
1842 draw_rect(fe, BORDER + x*TILE_SIZE - thick, BORDER-1,
1843 1+2*thick, cr*TILE_SIZE+3, COL_GRID);
1844 }
1845 for (y = 0; y <= cr; y++) {
1846 int thick = (y % c ? 0 : 1);
1847 draw_rect(fe, BORDER-1, BORDER + y*TILE_SIZE - thick,
1848 cr*TILE_SIZE+3, 1+2*thick, COL_GRID);
1849 }
1850 }
1851
1852 /*
1853 * Draw any numbers which need redrawing.
1854 */
1855 for (x = 0; x < cr; x++) {
1856 for (y = 0; y < cr; y++) {
1857 draw_number(fe, ds, state, x, y,
1858 (x == ui->hx && y == ui->hy) ||
1859 (flashtime > 0 &&
1860 (flashtime <= FLASH_TIME/3 ||
1861 flashtime >= FLASH_TIME*2/3)));
1862 }
1863 }
1864
1865 /*
1866 * Update the _entire_ grid if necessary.
1867 */
1868 if (!ds->started) {
1869 draw_update(fe, 0, 0, XSIZE(cr), YSIZE(cr));
1870 ds->started = TRUE;
1871 }
1872}
1873
1874static float game_anim_length(game_state *oldstate, game_state *newstate,
1875 int dir)
1876{
1877 return 0.0F;
1878}
1879
1880static float game_flash_length(game_state *oldstate, game_state *newstate,
1881 int dir)
1882{
1883 if (!oldstate->completed && newstate->completed)
1884 return FLASH_TIME;
1885 return 0.0F;
1886}
1887
1888static int game_wants_statusbar(void)
1889{
1890 return FALSE;
1891}
1892
1893#ifdef COMBINED
1894#define thegame solo
1895#endif
1896
1897const struct game thegame = {
1898 "Solo", "games.solo", TRUE,
1899 default_params,
1900 game_fetch_preset,
1901 decode_params,
1902 encode_params,
1903 free_params,
1904 dup_params,
1905 game_configure,
1906 custom_params,
1907 validate_params,
1908 new_game_seed,
1909 validate_seed,
1910 new_game,
1911 dup_game,
1912 free_game,
1913 new_ui,
1914 free_ui,
1915 make_move,
1916 game_size,
1917 game_colours,
1918 game_new_drawstate,
1919 game_free_drawstate,
1920 game_redraw,
1921 game_anim_length,
1922 game_flash_length,
1923 game_wants_statusbar,
1924};
3ddae0ff 1925
1926#ifdef STANDALONE_SOLVER
1927
7c568a48 1928/*
1929 * gcc -DSTANDALONE_SOLVER -o solosolver solo.c malloc.c
1930 */
1931
3ddae0ff 1932void frontend_default_colour(frontend *fe, float *output) {}
1933void draw_text(frontend *fe, int x, int y, int fonttype, int fontsize,
1934 int align, int colour, char *text) {}
1935void draw_rect(frontend *fe, int x, int y, int w, int h, int colour) {}
1936void draw_line(frontend *fe, int x1, int y1, int x2, int y2, int colour) {}
1937void draw_polygon(frontend *fe, int *coords, int npoints,
1938 int fill, int colour) {}
1939void clip(frontend *fe, int x, int y, int w, int h) {}
1940void unclip(frontend *fe) {}
1941void start_draw(frontend *fe) {}
1942void draw_update(frontend *fe, int x, int y, int w, int h) {}
1943void end_draw(frontend *fe) {}
7c568a48 1944unsigned long random_bits(random_state *state, int bits)
1945{ assert(!"Shouldn't get randomness"); return 0; }
1946unsigned long random_upto(random_state *state, unsigned long limit)
1947{ assert(!"Shouldn't get randomness"); return 0; }
3ddae0ff 1948
1949void fatal(char *fmt, ...)
1950{
1951 va_list ap;
1952
1953 fprintf(stderr, "fatal error: ");
1954
1955 va_start(ap, fmt);
1956 vfprintf(stderr, fmt, ap);
1957 va_end(ap);
1958
1959 fprintf(stderr, "\n");
1960 exit(1);
1961}
1962
1963int main(int argc, char **argv)
1964{
1965 game_params *p;
1966 game_state *s;
7c568a48 1967 int recurse = TRUE;
3ddae0ff 1968 char *id = NULL, *seed, *err;
1969 int y, x;
7c568a48 1970 int grade = FALSE;
3ddae0ff 1971
1972 while (--argc > 0) {
1973 char *p = *++argv;
1974 if (!strcmp(p, "-r")) {
1975 recurse = TRUE;
1976 } else if (!strcmp(p, "-n")) {
1977 recurse = FALSE;
7c568a48 1978 } else if (!strcmp(p, "-v")) {
1979 solver_show_working = TRUE;
1980 recurse = FALSE;
1981 } else if (!strcmp(p, "-g")) {
1982 grade = TRUE;
1983 recurse = FALSE;
3ddae0ff 1984 } else if (*p == '-') {
1985 fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0]);
1986 return 1;
1987 } else {
1988 id = p;
1989 }
1990 }
1991
1992 if (!id) {
7c568a48 1993 fprintf(stderr, "usage: %s [-n | -r | -g | -v] <game_id>\n", argv[0]);
3ddae0ff 1994 return 1;
1995 }
1996
1997 seed = strchr(id, ':');
1998 if (!seed) {
1999 fprintf(stderr, "%s: game id expects a colon in it\n", argv[0]);
2000 return 1;
2001 }
2002 *seed++ = '\0';
2003
2004 p = decode_params(id);
2005 err = validate_seed(p, seed);
2006 if (err) {
2007 fprintf(stderr, "%s: %s\n", argv[0], err);
2008 return 1;
2009 }
2010 s = new_game(p, seed);
2011
2012 if (recurse) {
2013 int ret = rsolve(p->c, p->r, s->grid, NULL, 2);
2014 if (ret > 1) {
7c568a48 2015 fprintf(stderr, "%s: rsolve: multiple solutions detected\n",
2016 argv[0]);
3ddae0ff 2017 }
2018 } else {
7c568a48 2019 int ret = nsolve(p->c, p->r, s->grid);
2020 if (grade) {
2021 if (ret == DIFF_IMPOSSIBLE) {
2022 /*
2023 * Now resort to rsolve to determine whether it's
2024 * really soluble.
2025 */
2026 ret = rsolve(p->c, p->r, s->grid, NULL, 2);
2027 if (ret == 0)
2028 ret = DIFF_IMPOSSIBLE;
2029 else if (ret == 1)
2030 ret = DIFF_RECURSIVE;
2031 else
2032 ret = DIFF_AMBIGUOUS;
2033 }
2034 printf("difficulty rating: %s\n",
2035 ret==DIFF_BLOCK ? "blockwise positional elimination only":
2036 ret==DIFF_SIMPLE ? "row/column/number elimination required":
2037 ret==DIFF_INTERSECT ? "intersectional analysis required":
2038 ret==DIFF_SET ? "set elimination required":
2039 ret==DIFF_RECURSIVE ? "guesswork and backtracking required":
2040 ret==DIFF_AMBIGUOUS ? "multiple solutions exist":
2041 ret==DIFF_IMPOSSIBLE ? "no solution exists":
2042 "INTERNAL ERROR: unrecognised difficulty code");
2043 }
3ddae0ff 2044 }
2045
2046 for (y = 0; y < p->c * p->r; y++) {
2047 for (x = 0; x < p->c * p->r; x++) {
7c568a48 2048 int c = s->grid[y * p->c * p->r + x];
2049 if (c == 0)
2050 c = ' ';
2051 else if (c <= 9)
2052 c = '0' + c;
2053 else
2054 c = 'a' + c-10;
2055 printf("%c", c);
2056 if (x+1 < p->c * p->r) {
2057 if ((x+1) % p->c)
2058 printf(" ");
2059 else
2060 printf(" | ");
2061 }
3ddae0ff 2062 }
2063 printf("\n");
7c568a48 2064 if (y+1 < p->c * p->r && (y+1) % p->r == 0) {
2065 for (x = 0; x < p->c * p->r; x++) {
2066 printf("-");
2067 if (x+1 < p->c * p->r) {
2068 if ((x+1) % p->c)
2069 printf("-");
2070 else
2071 printf("-+-");
2072 }
2073 }
2074 printf("\n");
2075 }
3ddae0ff 2076 }
2077 printf("\n");
2078
2079 return 0;
2080}
2081
2082#endif