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