Prepare to release sgt-puzzles (20170606.272beef-1).
[sgt-puzzles.git] / unruly.c
blobf418efa7769e1629e8c487bd8d5939a9549228e8
1 /*
2 * unruly.c: Implementation for Binary Puzzles.
3 * (C) 2012 Lennard Sprong
4 * Created for Simon Tatham's Portable Puzzle Collection
5 * See LICENCE for licence details
7 * Objective of the game: Fill the grid with zeros and ones, with the
8 * following rules:
9 * - There can't be a run of three or more equal numbers.
10 * - Each row and column contains an equal amount of zeros and ones.
12 * This puzzle type is known under several names, including
13 * Tohu-Wa-Vohu, One and Two and Binairo.
15 * Some variants include an extra constraint, stating that no two rows or two
16 * columns may contain the same exact sequence of zeros and ones.
17 * This rule is rarely used, so it is not enabled in the default presets
18 * (but it can be selected via the Custom configurer).
20 * More information:
21 * http://www.janko.at/Raetsel/Tohu-Wa-Vohu/index.htm
25 * Possible future improvements:
27 * More solver cleverness
29 * - a counting-based deduction in which you find groups of squares
30 * which must each contain at least one of a given colour, plus
31 * other squares which are already known to be that colour, and see
32 * if you have any squares left over when you've worked out where
33 * they all have to be. This is a generalisation of the current
34 * check_near_complete: where that only covers rows with three
35 * unfilled squares, this would handle more, such as
36 * 0 . . 1 0 1 . . 0 .
37 * in which each of the two-square gaps must contain a 0, and there
38 * are three 0s placed, and that means the rightmost square can't
39 * be a 0.
41 * - an 'Unreasonable' difficulty level, supporting recursion and
42 * backtracking.
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <assert.h>
49 #include <ctype.h>
50 #include <math.h>
52 #include "puzzles.h"
54 #ifdef STANDALONE_SOLVER
55 int solver_verbose = FALSE;
56 #endif
58 enum {
59 COL_BACKGROUND,
60 COL_GRID,
61 COL_EMPTY,
63 * When editing this enum, maintain the invariants
64 * COL_n_HIGHLIGHT = COL_n + 1
65 * COL_n_LOWLIGHT = COL_n + 2
67 COL_0,
68 COL_0_HIGHLIGHT,
69 COL_0_LOWLIGHT,
70 COL_1,
71 COL_1_HIGHLIGHT,
72 COL_1_LOWLIGHT,
73 COL_CURSOR,
74 COL_ERROR,
75 NCOLOURS
78 struct game_params {
79 int w2, h2; /* full grid width and height respectively */
80 int unique; /* should row and column patterns be unique? */
81 int diff;
83 #define DIFFLIST(A) \
84 A(EASY,Easy, e) \
85 A(NORMAL,Normal, n) \
87 #define ENUM(upper,title,lower) DIFF_ ## upper,
88 #define TITLE(upper,title,lower) #title,
89 #define ENCODE(upper,title,lower) #lower
90 #define CONFIG(upper,title,lower) ":" #title
91 enum { DIFFLIST(ENUM) DIFFCOUNT };
92 static char const *const unruly_diffnames[] = { DIFFLIST(TITLE) };
94 static char const unruly_diffchars[] = DIFFLIST(ENCODE);
95 #define DIFFCONFIG DIFFLIST(CONFIG)
97 const static struct game_params unruly_presets[] = {
98 { 8, 8, FALSE, DIFF_EASY},
99 { 8, 8, FALSE, DIFF_NORMAL},
100 {10, 10, FALSE, DIFF_EASY},
101 {10, 10, FALSE, DIFF_NORMAL},
102 {14, 14, FALSE, DIFF_EASY},
103 {14, 14, FALSE, DIFF_NORMAL}
106 #define DEFAULT_PRESET 0
108 enum {
109 EMPTY,
110 N_ONE,
111 N_ZERO,
112 BOGUS
115 #define FE_HOR_ROW_LEFT 0x0001
116 #define FE_HOR_ROW_MID 0x0003
117 #define FE_HOR_ROW_RIGHT 0x0002
119 #define FE_VER_ROW_TOP 0x0004
120 #define FE_VER_ROW_MID 0x000C
121 #define FE_VER_ROW_BOTTOM 0x0008
123 #define FE_COUNT 0x0010
125 #define FE_ROW_MATCH 0x0020
126 #define FE_COL_MATCH 0x0040
128 #define FF_ONE 0x0080
129 #define FF_ZERO 0x0100
130 #define FF_CURSOR 0x0200
132 #define FF_FLASH1 0x0400
133 #define FF_FLASH2 0x0800
134 #define FF_IMMUTABLE 0x1000
136 struct game_state {
137 int w2, h2;
138 int unique;
139 char *grid;
140 unsigned char *immutable;
142 int completed, cheated;
145 static game_params *default_params(void)
147 game_params *ret = snew(game_params);
149 *ret = unruly_presets[DEFAULT_PRESET]; /* structure copy */
151 return ret;
154 static int game_fetch_preset(int i, char **name, game_params **params)
156 game_params *ret;
157 char buf[80];
159 if (i < 0 || i >= lenof(unruly_presets))
160 return FALSE;
162 ret = snew(game_params);
163 *ret = unruly_presets[i]; /* structure copy */
165 sprintf(buf, "%dx%d %s", ret->w2, ret->h2, unruly_diffnames[ret->diff]);
167 *name = dupstr(buf);
168 *params = ret;
169 return TRUE;
172 static void free_params(game_params *params)
174 sfree(params);
177 static game_params *dup_params(const game_params *params)
179 game_params *ret = snew(game_params);
180 *ret = *params; /* structure copy */
181 return ret;
184 static void decode_params(game_params *params, char const *string)
186 char const *p = string;
188 params->unique = FALSE;
190 params->w2 = atoi(p);
191 while (*p && isdigit((unsigned char)*p)) p++;
192 if (*p == 'x') {
193 p++;
194 params->h2 = atoi(p);
195 while (*p && isdigit((unsigned char)*p)) p++;
196 } else {
197 params->h2 = params->w2;
200 if (*p == 'u') {
201 p++;
202 params->unique = TRUE;
205 if (*p == 'd') {
206 int i;
207 p++;
208 params->diff = DIFFCOUNT + 1; /* ...which is invalid */
209 if (*p) {
210 for (i = 0; i < DIFFCOUNT; i++) {
211 if (*p == unruly_diffchars[i])
212 params->diff = i;
214 p++;
219 static char *encode_params(const game_params *params, int full)
221 char buf[80];
223 sprintf(buf, "%dx%d", params->w2, params->h2);
224 if (params->unique)
225 strcat(buf, "u");
226 if (full)
227 sprintf(buf + strlen(buf), "d%c", unruly_diffchars[params->diff]);
229 return dupstr(buf);
232 static config_item *game_configure(const game_params *params)
234 config_item *ret;
235 char buf[80];
237 ret = snewn(5, config_item);
239 ret[0].name = "Width";
240 ret[0].type = C_STRING;
241 sprintf(buf, "%d", params->w2);
242 ret[0].sval = dupstr(buf);
243 ret[0].ival = 0;
245 ret[1].name = "Height";
246 ret[1].type = C_STRING;
247 sprintf(buf, "%d", params->h2);
248 ret[1].sval = dupstr(buf);
249 ret[1].ival = 0;
251 ret[2].name = "Unique rows and columns";
252 ret[2].type = C_BOOLEAN;
253 ret[2].ival = params->unique;
255 ret[3].name = "Difficulty";
256 ret[3].type = C_CHOICES;
257 ret[3].sval = DIFFCONFIG;
258 ret[3].ival = params->diff;
260 ret[4].name = NULL;
261 ret[4].type = C_END;
262 ret[4].sval = NULL;
263 ret[4].ival = 0;
265 return ret;
268 static game_params *custom_params(const config_item *cfg)
270 game_params *ret = snew(game_params);
272 ret->w2 = atoi(cfg[0].sval);
273 ret->h2 = atoi(cfg[1].sval);
274 ret->unique = cfg[2].ival;
275 ret->diff = cfg[3].ival;
277 return ret;
280 static char *validate_params(const game_params *params, int full)
282 if ((params->w2 & 1) || (params->h2 & 1))
283 return "Width and height must both be even";
284 if (params->w2 < 6 || params->h2 < 6)
285 return "Width and height must be at least 6";
286 if (params->unique) {
287 static const long A177790[] = {
289 * The nth element of this array gives the number of
290 * distinct possible Unruly rows of length 2n (that is,
291 * containing exactly n 1s and n 0s and not containing
292 * three consecutive elements the same) for as long as
293 * those numbers fit in a 32-bit signed int.
295 * So in unique-rows mode, if the puzzle width is 2n, then
296 * the height must be at most (this array)[n], and vice
297 * versa.
299 * This is sequence A177790 in the Online Encyclopedia of
300 * Integer Sequences: http://oeis.org/A177790
302 1L, 2L, 6L, 14L, 34L, 84L, 208L, 518L, 1296L, 3254L,
303 8196L, 20700L, 52404L, 132942L, 337878L, 860142L,
304 2192902L, 5598144L, 14308378L, 36610970L, 93770358L,
305 240390602L, 616787116L, 1583765724L
307 if (params->w2 < 2*lenof(A177790) &&
308 params->h2 > A177790[params->w2/2]) {
309 return "Puzzle is too tall for unique-rows mode";
311 if (params->h2 < 2*lenof(A177790) &&
312 params->w2 > A177790[params->h2/2]) {
313 return "Puzzle is too long for unique-rows mode";
316 if (params->diff >= DIFFCOUNT)
317 return "Unknown difficulty rating";
319 return NULL;
322 static char *validate_desc(const game_params *params, const char *desc)
324 int w2 = params->w2, h2 = params->h2;
325 int s = w2 * h2;
327 const char *p = desc;
328 int pos = 0;
330 while (*p) {
331 if (*p >= 'a' && *p < 'z')
332 pos += 1 + (*p - 'a');
333 else if (*p >= 'A' && *p < 'Z')
334 pos += 1 + (*p - 'A');
335 else if (*p == 'Z' || *p == 'z')
336 pos += 25;
337 else
338 return "Description contains invalid characters";
340 ++p;
343 if (pos < s+1)
344 return "Description too short";
345 if (pos > s+1)
346 return "Description too long";
348 return NULL;
351 static game_state *blank_state(int w2, int h2, int unique)
353 game_state *state = snew(game_state);
354 int s = w2 * h2;
356 state->w2 = w2;
357 state->h2 = h2;
358 state->unique = unique;
359 state->grid = snewn(s, char);
360 state->immutable = snewn(s, unsigned char);
362 memset(state->grid, EMPTY, s);
363 memset(state->immutable, FALSE, s);
365 state->completed = state->cheated = FALSE;
367 return state;
370 static game_state *new_game(midend *me, const game_params *params,
371 const char *desc)
373 int w2 = params->w2, h2 = params->h2;
374 int s = w2 * h2;
376 game_state *state = blank_state(w2, h2, params->unique);
378 const char *p = desc;
379 int pos = 0;
381 while (*p) {
382 if (*p >= 'a' && *p < 'z') {
383 pos += (*p - 'a');
384 if (pos < s) {
385 state->grid[pos] = N_ZERO;
386 state->immutable[pos] = TRUE;
388 pos++;
389 } else if (*p >= 'A' && *p < 'Z') {
390 pos += (*p - 'A');
391 if (pos < s) {
392 state->grid[pos] = N_ONE;
393 state->immutable[pos] = TRUE;
395 pos++;
396 } else if (*p == 'Z' || *p == 'z') {
397 pos += 25;
398 } else
399 assert(!"Description contains invalid characters");
401 ++p;
403 assert(pos == s+1);
405 return state;
408 static game_state *dup_game(const game_state *state)
410 int w2 = state->w2, h2 = state->h2;
411 int s = w2 * h2;
413 game_state *ret = blank_state(w2, h2, state->unique);
415 memcpy(ret->grid, state->grid, s);
416 memcpy(ret->immutable, state->immutable, s);
418 ret->completed = state->completed;
419 ret->cheated = state->cheated;
421 return ret;
424 static void free_game(game_state *state)
426 sfree(state->grid);
427 sfree(state->immutable);
429 sfree(state);
432 static int game_can_format_as_text_now(const game_params *params)
434 return TRUE;
437 static char *game_text_format(const game_state *state)
439 int w2 = state->w2, h2 = state->h2;
440 int lr = w2*2 + 1;
442 char *ret = snewn(lr * h2 + 1, char);
443 char *p = ret;
445 int x, y;
446 for (y = 0; y < h2; y++) {
447 for (x = 0; x < w2; x++) {
448 /* Place number */
449 char c = state->grid[y * w2 + x];
450 *p++ = (c == N_ONE ? '1' : c == N_ZERO ? '0' : '.');
451 *p++ = ' ';
453 /* End line */
454 *p++ = '\n';
456 /* End with NUL */
457 *p++ = '\0';
459 return ret;
462 /* ****** *
463 * Solver *
464 * ****** */
466 struct unruly_scratch {
467 int *ones_rows;
468 int *ones_cols;
469 int *zeros_rows;
470 int *zeros_cols;
473 static void unruly_solver_update_remaining(const game_state *state,
474 struct unruly_scratch *scratch)
476 int w2 = state->w2, h2 = state->h2;
477 int x, y;
479 /* Reset all scratch data */
480 memset(scratch->ones_rows, 0, h2 * sizeof(int));
481 memset(scratch->ones_cols, 0, w2 * sizeof(int));
482 memset(scratch->zeros_rows, 0, h2 * sizeof(int));
483 memset(scratch->zeros_cols, 0, w2 * sizeof(int));
485 for (x = 0; x < w2; x++)
486 for (y = 0; y < h2; y++) {
487 if (state->grid[y * w2 + x] == N_ONE) {
488 scratch->ones_rows[y]++;
489 scratch->ones_cols[x]++;
490 } else if (state->grid[y * w2 + x] == N_ZERO) {
491 scratch->zeros_rows[y]++;
492 scratch->zeros_cols[x]++;
497 static struct unruly_scratch *unruly_new_scratch(const game_state *state)
499 int w2 = state->w2, h2 = state->h2;
501 struct unruly_scratch *ret = snew(struct unruly_scratch);
503 ret->ones_rows = snewn(h2, int);
504 ret->ones_cols = snewn(w2, int);
505 ret->zeros_rows = snewn(h2, int);
506 ret->zeros_cols = snewn(w2, int);
508 unruly_solver_update_remaining(state, ret);
510 return ret;
513 static void unruly_free_scratch(struct unruly_scratch *scratch)
515 sfree(scratch->ones_rows);
516 sfree(scratch->ones_cols);
517 sfree(scratch->zeros_rows);
518 sfree(scratch->zeros_cols);
520 sfree(scratch);
523 static int unruly_solver_check_threes(game_state *state, int *rowcount,
524 int *colcount, int horizontal,
525 char check, char block)
527 int w2 = state->w2, h2 = state->h2;
529 int dx = horizontal ? 1 : 0, dy = 1 - dx;
530 int sx = dx, sy = dy;
531 int ex = w2 - dx, ey = h2 - dy;
533 int x, y;
534 int ret = 0;
536 /* Check for any three squares which almost form three in a row */
537 for (y = sy; y < ey; y++) {
538 for (x = sx; x < ex; x++) {
539 int i1 = (y-dy) * w2 + (x-dx);
540 int i2 = y * w2 + x;
541 int i3 = (y+dy) * w2 + (x+dx);
543 if (state->grid[i1] == check && state->grid[i2] == check
544 && state->grid[i3] == EMPTY) {
545 ret++;
546 #ifdef STANDALONE_SOLVER
547 if (solver_verbose) {
548 printf("Solver: %i,%i and %i,%i confirm %c at %i,%i\n",
549 i1 % w2, i1 / w2, i2 % w2, i2 / w2,
550 (block == N_ONE ? '1' : '0'), i3 % w2,
551 i3 / w2);
553 #endif
554 state->grid[i3] = block;
555 rowcount[i3 / w2]++;
556 colcount[i3 % w2]++;
558 if (state->grid[i1] == check && state->grid[i2] == EMPTY
559 && state->grid[i3] == check) {
560 ret++;
561 #ifdef STANDALONE_SOLVER
562 if (solver_verbose) {
563 printf("Solver: %i,%i and %i,%i confirm %c at %i,%i\n",
564 i1 % w2, i1 / w2, i3 % w2, i3 / w2,
565 (block == N_ONE ? '1' : '0'), i2 % w2,
566 i2 / w2);
568 #endif
569 state->grid[i2] = block;
570 rowcount[i2 / w2]++;
571 colcount[i2 % w2]++;
573 if (state->grid[i1] == EMPTY && state->grid[i2] == check
574 && state->grid[i3] == check) {
575 ret++;
576 #ifdef STANDALONE_SOLVER
577 if (solver_verbose) {
578 printf("Solver: %i,%i and %i,%i confirm %c at %i,%i\n",
579 i2 % w2, i2 / w2, i3 % w2, i3 / w2,
580 (block == N_ONE ? '1' : '0'), i1 % w2,
581 i1 / w2);
583 #endif
584 state->grid[i1] = block;
585 rowcount[i1 / w2]++;
586 colcount[i1 % w2]++;
591 return ret;
594 static int unruly_solver_check_all_threes(game_state *state,
595 struct unruly_scratch *scratch)
597 int ret = 0;
599 ret +=
600 unruly_solver_check_threes(state, scratch->zeros_rows,
601 scratch->zeros_cols, TRUE, N_ONE, N_ZERO);
602 ret +=
603 unruly_solver_check_threes(state, scratch->ones_rows,
604 scratch->ones_cols, TRUE, N_ZERO, N_ONE);
605 ret +=
606 unruly_solver_check_threes(state, scratch->zeros_rows,
607 scratch->zeros_cols, FALSE, N_ONE,
608 N_ZERO);
609 ret +=
610 unruly_solver_check_threes(state, scratch->ones_rows,
611 scratch->ones_cols, FALSE, N_ZERO, N_ONE);
613 return ret;
616 static int unruly_solver_check_uniques(game_state *state, int *rowcount,
617 int horizontal, char check, char block,
618 struct unruly_scratch *scratch)
620 int w2 = state->w2, h2 = state->h2;
622 int rmult = (horizontal ? w2 : 1);
623 int cmult = (horizontal ? 1 : w2);
624 int nr = (horizontal ? h2 : w2);
625 int nc = (horizontal ? w2 : h2);
626 int max = nc / 2;
628 int r, r2, c;
629 int ret = 0;
632 * Find each row that has max entries of type 'check', and see if
633 * all those entries match those in any row with max-1 entries. If
634 * so, set the last non-matching entry of the latter row to ensure
635 * that it's different.
637 for (r = 0; r < nr; r++) {
638 if (rowcount[r] != max)
639 continue;
640 for (r2 = 0; r2 < nr; r2++) {
641 int nmatch = 0, nonmatch = -1;
642 if (rowcount[r2] != max-1)
643 continue;
644 for (c = 0; c < nc; c++) {
645 if (state->grid[r*rmult + c*cmult] == check) {
646 if (state->grid[r2*rmult + c*cmult] == check)
647 nmatch++;
648 else
649 nonmatch = c;
652 if (nmatch == max-1) {
653 int i1 = r2 * rmult + nonmatch * cmult;
654 assert(nonmatch != -1);
655 if (state->grid[i1] == block)
656 continue;
657 assert(state->grid[i1] == EMPTY);
658 #ifdef STANDALONE_SOLVER
659 if (solver_verbose) {
660 printf("Solver: matching %s %i, %i gives %c at %i,%i\n",
661 horizontal ? "rows" : "cols",
662 r, r2, (block == N_ONE ? '1' : '0'), i1 % w2,
663 i1 / w2);
665 #endif
666 state->grid[i1] = block;
667 if (block == N_ONE) {
668 scratch->ones_rows[i1 / w2]++;
669 scratch->ones_cols[i1 % w2]++;
670 } else {
671 scratch->zeros_rows[i1 / w2]++;
672 scratch->zeros_cols[i1 % w2]++;
674 ret++;
678 return ret;
681 static int unruly_solver_check_all_uniques(game_state *state,
682 struct unruly_scratch *scratch)
684 int ret = 0;
686 ret += unruly_solver_check_uniques(state, scratch->ones_rows,
687 TRUE, N_ONE, N_ZERO, scratch);
688 ret += unruly_solver_check_uniques(state, scratch->zeros_rows,
689 TRUE, N_ZERO, N_ONE, scratch);
690 ret += unruly_solver_check_uniques(state, scratch->ones_cols,
691 FALSE, N_ONE, N_ZERO, scratch);
692 ret += unruly_solver_check_uniques(state, scratch->zeros_cols,
693 FALSE, N_ZERO, N_ONE, scratch);
695 return ret;
698 static int unruly_solver_fill_row(game_state *state, int i, int horizontal,
699 int *rowcount, int *colcount, char fill)
701 int ret = 0;
702 int w2 = state->w2, h2 = state->h2;
703 int j;
705 #ifdef STANDALONE_SOLVER
706 if (solver_verbose) {
707 printf("Solver: Filling %s %i with %c:",
708 (horizontal ? "Row" : "Col"), i,
709 (fill == N_ZERO ? '0' : '1'));
711 #endif
712 /* Place a number in every empty square in a row/column */
713 for (j = 0; j < (horizontal ? w2 : h2); j++) {
714 int p = (horizontal ? i * w2 + j : j * w2 + i);
716 if (state->grid[p] == EMPTY) {
717 #ifdef STANDALONE_SOLVER
718 if (solver_verbose) {
719 printf(" (%i,%i)", (horizontal ? j : i),
720 (horizontal ? i : j));
722 #endif
723 ret++;
724 state->grid[p] = fill;
725 rowcount[(horizontal ? i : j)]++;
726 colcount[(horizontal ? j : i)]++;
730 #ifdef STANDALONE_SOLVER
731 if (solver_verbose) {
732 printf("\n");
734 #endif
736 return ret;
739 static int unruly_solver_check_complete_nums(game_state *state,
740 int *complete, int horizontal,
741 int *rowcount, int *colcount,
742 char fill)
744 int w2 = state->w2, h2 = state->h2;
745 int count = (horizontal ? h2 : w2); /* number of rows to check */
746 int target = (horizontal ? w2 : h2) / 2; /* target number of 0s/1s */
747 int *other = (horizontal ? rowcount : colcount);
749 int ret = 0;
751 int i;
752 /* Check for completed rows/cols for one number, then fill in the rest */
753 for (i = 0; i < count; i++) {
754 if (complete[i] == target && other[i] < target) {
755 #ifdef STANDALONE_SOLVER
756 if (solver_verbose) {
757 printf("Solver: Row %i satisfied for %c\n", i,
758 (fill != N_ZERO ? '0' : '1'));
760 #endif
761 ret += unruly_solver_fill_row(state, i, horizontal, rowcount,
762 colcount, fill);
766 return ret;
769 static int unruly_solver_check_all_complete_nums(game_state *state,
770 struct unruly_scratch *scratch)
772 int ret = 0;
774 ret +=
775 unruly_solver_check_complete_nums(state, scratch->ones_rows, TRUE,
776 scratch->zeros_rows,
777 scratch->zeros_cols, N_ZERO);
778 ret +=
779 unruly_solver_check_complete_nums(state, scratch->ones_cols, FALSE,
780 scratch->zeros_rows,
781 scratch->zeros_cols, N_ZERO);
782 ret +=
783 unruly_solver_check_complete_nums(state, scratch->zeros_rows, TRUE,
784 scratch->ones_rows,
785 scratch->ones_cols, N_ONE);
786 ret +=
787 unruly_solver_check_complete_nums(state, scratch->zeros_cols, FALSE,
788 scratch->ones_rows,
789 scratch->ones_cols, N_ONE);
791 return ret;
794 static int unruly_solver_check_near_complete(game_state *state,
795 int *complete, int horizontal,
796 int *rowcount, int *colcount,
797 char fill)
799 int w2 = state->w2, h2 = state->h2;
800 int w = w2/2, h = h2/2;
802 int dx = horizontal ? 1 : 0, dy = 1 - dx;
804 int sx = dx, sy = dy;
805 int ex = w2 - dx, ey = h2 - dy;
807 int x, y;
808 int ret = 0;
811 * This function checks for a row with one Y remaining, then looks
812 * for positions that could cause the remaining squares in the row
813 * to make 3 X's in a row. Example:
815 * Consider the following row:
816 * 1 1 0 . . .
817 * If the last 1 was placed in the last square, the remaining
818 * squares would be 0:
819 * 1 1 0 0 0 1
820 * This violates the 3 in a row rule. We now know that the last 1
821 * shouldn't be in the last cell.
822 * 1 1 0 . . 0
825 /* Check for any two blank and one filled square */
826 for (y = sy; y < ey; y++) {
827 /* One type must have 1 remaining, the other at least 2 */
828 if (horizontal && (complete[y] < w - 1 || rowcount[y] > w - 2))
829 continue;
831 for (x = sx; x < ex; x++) {
832 int i, i1, i2, i3;
833 if (!horizontal
834 && (complete[x] < h - 1 || colcount[x] > h - 2))
835 continue;
837 i = (horizontal ? y : x);
838 i1 = (y-dy) * w2 + (x-dx);
839 i2 = y * w2 + x;
840 i3 = (y+dy) * w2 + (x+dx);
842 if (state->grid[i1] == fill && state->grid[i2] == EMPTY
843 && state->grid[i3] == EMPTY) {
845 * Temporarily fill the empty spaces with something else.
846 * This avoids raising the counts for the row and column
848 state->grid[i2] = BOGUS;
849 state->grid[i3] = BOGUS;
851 #ifdef STANDALONE_SOLVER
852 if (solver_verbose) {
853 printf("Solver: Row %i nearly satisfied for %c\n", i,
854 (fill != N_ZERO ? '0' : '1'));
856 #endif
857 ret +=
858 unruly_solver_fill_row(state, i, horizontal, rowcount,
859 colcount, fill);
861 state->grid[i2] = EMPTY;
862 state->grid[i3] = EMPTY;
865 else if (state->grid[i1] == EMPTY && state->grid[i2] == fill
866 && state->grid[i3] == EMPTY) {
867 state->grid[i1] = BOGUS;
868 state->grid[i3] = BOGUS;
870 #ifdef STANDALONE_SOLVER
871 if (solver_verbose) {
872 printf("Solver: Row %i nearly satisfied for %c\n", i,
873 (fill != N_ZERO ? '0' : '1'));
875 #endif
876 ret +=
877 unruly_solver_fill_row(state, i, horizontal, rowcount,
878 colcount, fill);
880 state->grid[i1] = EMPTY;
881 state->grid[i3] = EMPTY;
884 else if (state->grid[i1] == EMPTY && state->grid[i2] == EMPTY
885 && state->grid[i3] == fill) {
886 state->grid[i1] = BOGUS;
887 state->grid[i2] = BOGUS;
889 #ifdef STANDALONE_SOLVER
890 if (solver_verbose) {
891 printf("Solver: Row %i nearly satisfied for %c\n", i,
892 (fill != N_ZERO ? '0' : '1'));
894 #endif
895 ret +=
896 unruly_solver_fill_row(state, i, horizontal, rowcount,
897 colcount, fill);
899 state->grid[i1] = EMPTY;
900 state->grid[i2] = EMPTY;
903 else if (state->grid[i1] == EMPTY && state->grid[i2] == EMPTY
904 && state->grid[i3] == EMPTY) {
905 state->grid[i1] = BOGUS;
906 state->grid[i2] = BOGUS;
907 state->grid[i3] = BOGUS;
909 #ifdef STANDALONE_SOLVER
910 if (solver_verbose) {
911 printf("Solver: Row %i nearly satisfied for %c\n", i,
912 (fill != N_ZERO ? '0' : '1'));
914 #endif
915 ret +=
916 unruly_solver_fill_row(state, i, horizontal, rowcount,
917 colcount, fill);
919 state->grid[i1] = EMPTY;
920 state->grid[i2] = EMPTY;
921 state->grid[i3] = EMPTY;
926 return ret;
929 static int unruly_solver_check_all_near_complete(game_state *state,
930 struct unruly_scratch *scratch)
932 int ret = 0;
934 ret +=
935 unruly_solver_check_near_complete(state, scratch->ones_rows, TRUE,
936 scratch->zeros_rows,
937 scratch->zeros_cols, N_ZERO);
938 ret +=
939 unruly_solver_check_near_complete(state, scratch->ones_cols, FALSE,
940 scratch->zeros_rows,
941 scratch->zeros_cols, N_ZERO);
942 ret +=
943 unruly_solver_check_near_complete(state, scratch->zeros_rows, TRUE,
944 scratch->ones_rows,
945 scratch->ones_cols, N_ONE);
946 ret +=
947 unruly_solver_check_near_complete(state, scratch->zeros_cols, FALSE,
948 scratch->ones_rows,
949 scratch->ones_cols, N_ONE);
951 return ret;
954 static int unruly_validate_rows(const game_state *state, int horizontal,
955 char check, int *errors)
957 int w2 = state->w2, h2 = state->h2;
959 int dx = horizontal ? 1 : 0, dy = 1 - dx;
961 int sx = dx, sy = dy;
962 int ex = w2 - dx, ey = h2 - dy;
964 int x, y;
965 int ret = 0;
967 int err1 = (horizontal ? FE_HOR_ROW_LEFT : FE_VER_ROW_TOP);
968 int err2 = (horizontal ? FE_HOR_ROW_MID : FE_VER_ROW_MID);
969 int err3 = (horizontal ? FE_HOR_ROW_RIGHT : FE_VER_ROW_BOTTOM);
971 /* Check for any three in a row, and mark errors accordingly (if
972 * required) */
973 for (y = sy; y < ey; y++) {
974 for (x = sx; x < ex; x++) {
975 int i1 = (y-dy) * w2 + (x-dx);
976 int i2 = y * w2 + x;
977 int i3 = (y+dy) * w2 + (x+dx);
979 if (state->grid[i1] == check && state->grid[i2] == check
980 && state->grid[i3] == check) {
981 ret++;
982 if (errors) {
983 errors[i1] |= err1;
984 errors[i2] |= err2;
985 errors[i3] |= err3;
991 return ret;
994 static int unruly_validate_unique(const game_state *state, int horizontal,
995 int *errors)
997 int w2 = state->w2, h2 = state->h2;
999 int rmult = (horizontal ? w2 : 1);
1000 int cmult = (horizontal ? 1 : w2);
1001 int nr = (horizontal ? h2 : w2);
1002 int nc = (horizontal ? w2 : h2);
1003 int err = (horizontal ? FE_ROW_MATCH : FE_COL_MATCH);
1005 int r, r2, c;
1006 int ret = 0;
1008 /* Check for any two full rows matching exactly, and mark errors
1009 * accordingly (if required) */
1010 for (r = 0; r < nr; r++) {
1011 int nfull = 0;
1012 for (c = 0; c < nc; c++)
1013 if (state->grid[r*rmult + c*cmult] != EMPTY)
1014 nfull++;
1015 if (nfull != nc)
1016 continue;
1017 for (r2 = r+1; r2 < nr; r2++) {
1018 int match = TRUE;
1019 for (c = 0; c < nc; c++)
1020 if (state->grid[r*rmult + c*cmult] !=
1021 state->grid[r2*rmult + c*cmult])
1022 match = FALSE;
1023 if (match) {
1024 if (errors) {
1025 for (c = 0; c < nc; c++) {
1026 errors[r*rmult + c*cmult] |= err;
1027 errors[r2*rmult + c*cmult] |= err;
1030 ret++;
1035 return ret;
1038 static int unruly_validate_all_rows(const game_state *state, int *errors)
1040 int errcount = 0;
1042 errcount += unruly_validate_rows(state, TRUE, N_ONE, errors);
1043 errcount += unruly_validate_rows(state, FALSE, N_ONE, errors);
1044 errcount += unruly_validate_rows(state, TRUE, N_ZERO, errors);
1045 errcount += unruly_validate_rows(state, FALSE, N_ZERO, errors);
1047 if (state->unique) {
1048 errcount += unruly_validate_unique(state, TRUE, errors);
1049 errcount += unruly_validate_unique(state, FALSE, errors);
1052 if (errcount)
1053 return -1;
1054 return 0;
1057 static int unruly_validate_counts(const game_state *state,
1058 struct unruly_scratch *scratch, int *errors)
1060 int w2 = state->w2, h2 = state->h2;
1061 int w = w2/2, h = h2/2;
1062 char below = FALSE;
1063 char above = FALSE;
1064 int i;
1066 /* See if all rows/columns are satisfied. If one is exceeded,
1067 * mark it as an error (if required)
1070 char hasscratch = TRUE;
1071 if (!scratch) {
1072 scratch = unruly_new_scratch(state);
1073 hasscratch = FALSE;
1076 for (i = 0; i < w2; i++) {
1077 if (scratch->ones_cols[i] < h)
1078 below = TRUE;
1079 if (scratch->zeros_cols[i] < h)
1080 below = TRUE;
1082 if (scratch->ones_cols[i] > h) {
1083 above = TRUE;
1084 if (errors)
1085 errors[2*h2 + i] = TRUE;
1086 } else if (errors)
1087 errors[2*h2 + i] = FALSE;
1089 if (scratch->zeros_cols[i] > h) {
1090 above = TRUE;
1091 if (errors)
1092 errors[2*h2 + w2 + i] = TRUE;
1093 } else if (errors)
1094 errors[2*h2 + w2 + i] = FALSE;
1096 for (i = 0; i < h2; i++) {
1097 if (scratch->ones_rows[i] < w)
1098 below = TRUE;
1099 if (scratch->zeros_rows[i] < w)
1100 below = TRUE;
1102 if (scratch->ones_rows[i] > w) {
1103 above = TRUE;
1104 if (errors)
1105 errors[i] = TRUE;
1106 } else if (errors)
1107 errors[i] = FALSE;
1109 if (scratch->zeros_rows[i] > w) {
1110 above = TRUE;
1111 if (errors)
1112 errors[h2 + i] = TRUE;
1113 } else if (errors)
1114 errors[h2 + i] = FALSE;
1117 if (!hasscratch)
1118 unruly_free_scratch(scratch);
1120 return (above ? -1 : below ? 1 : 0);
1123 static int unruly_solve_game(game_state *state,
1124 struct unruly_scratch *scratch, int diff)
1126 int done, maxdiff = -1;
1128 while (TRUE) {
1129 done = 0;
1131 /* Check for impending 3's */
1132 done += unruly_solver_check_all_threes(state, scratch);
1134 /* Keep using the simpler techniques while they produce results */
1135 if (done) {
1136 if (maxdiff < DIFF_EASY)
1137 maxdiff = DIFF_EASY;
1138 continue;
1141 /* Check for completed rows */
1142 done += unruly_solver_check_all_complete_nums(state, scratch);
1144 if (done) {
1145 if (maxdiff < DIFF_EASY)
1146 maxdiff = DIFF_EASY;
1147 continue;
1150 /* Check for impending failures of row/column uniqueness, if
1151 * it's enabled in this game mode */
1152 if (state->unique) {
1153 done += unruly_solver_check_all_uniques(state, scratch);
1155 if (done) {
1156 if (maxdiff < DIFF_EASY)
1157 maxdiff = DIFF_EASY;
1158 continue;
1162 /* Normal techniques */
1163 if (diff < DIFF_NORMAL)
1164 break;
1166 /* Check for nearly completed rows */
1167 done += unruly_solver_check_all_near_complete(state, scratch);
1169 if (done) {
1170 if (maxdiff < DIFF_NORMAL)
1171 maxdiff = DIFF_NORMAL;
1172 continue;
1175 break;
1177 return maxdiff;
1180 static char *solve_game(const game_state *state, const game_state *currstate,
1181 const char *aux, char **error)
1183 game_state *solved = dup_game(state);
1184 struct unruly_scratch *scratch = unruly_new_scratch(solved);
1185 char *ret = NULL;
1186 int result;
1188 unruly_solve_game(solved, scratch, DIFFCOUNT);
1190 result = unruly_validate_counts(solved, scratch, NULL);
1191 if (unruly_validate_all_rows(solved, NULL) == -1)
1192 result = -1;
1194 if (result == 0) {
1195 int w2 = solved->w2, h2 = solved->h2;
1196 int s = w2 * h2;
1197 char *p;
1198 int i;
1200 ret = snewn(s + 2, char);
1201 p = ret;
1202 *p++ = 'S';
1204 for (i = 0; i < s; i++)
1205 *p++ = (solved->grid[i] == N_ONE ? '1' : '0');
1207 *p++ = '\0';
1208 } else if (result == 1)
1209 *error = "No solution found.";
1210 else if (result == -1)
1211 *error = "Puzzle is invalid.";
1213 free_game(solved);
1214 unruly_free_scratch(scratch);
1215 return ret;
1218 /* ********* *
1219 * Generator *
1220 * ********* */
1222 static int unruly_fill_game(game_state *state, struct unruly_scratch *scratch,
1223 random_state *rs)
1226 int w2 = state->w2, h2 = state->h2;
1227 int s = w2 * h2;
1228 int i, j;
1229 int *spaces;
1231 #ifdef STANDALONE_SOLVER
1232 if (solver_verbose) {
1233 printf("Generator: Attempt to fill grid\n");
1235 #endif
1237 /* Generate random array of spaces */
1238 spaces = snewn(s, int);
1239 for (i = 0; i < s; i++)
1240 spaces[i] = i;
1241 shuffle(spaces, s, sizeof(*spaces), rs);
1244 * Construct a valid filled grid by repeatedly picking an unfilled
1245 * space and fill it, then calling the solver to fill in any
1246 * spaces forced by the change.
1248 for (j = 0; j < s; j++) {
1249 i = spaces[j];
1251 if (state->grid[i] != EMPTY)
1252 continue;
1254 if (random_upto(rs, 2)) {
1255 state->grid[i] = N_ONE;
1256 scratch->ones_rows[i / w2]++;
1257 scratch->ones_cols[i % w2]++;
1258 } else {
1259 state->grid[i] = N_ZERO;
1260 scratch->zeros_rows[i / w2]++;
1261 scratch->zeros_cols[i % w2]++;
1264 unruly_solve_game(state, scratch, DIFFCOUNT);
1266 sfree(spaces);
1268 if (unruly_validate_all_rows(state, NULL) != 0
1269 || unruly_validate_counts(state, scratch, NULL) != 0)
1270 return FALSE;
1272 return TRUE;
1275 static char *new_game_desc(const game_params *params, random_state *rs,
1276 char **aux, int interactive)
1278 #ifdef STANDALONE_SOLVER
1279 char *debug;
1280 int temp_verbose = FALSE;
1281 #endif
1283 int w2 = params->w2, h2 = params->h2;
1284 int s = w2 * h2;
1285 int *spaces;
1286 int i, j, run;
1287 char *ret, *p;
1289 game_state *state;
1290 struct unruly_scratch *scratch;
1292 int attempts = 0;
1294 while (1) {
1296 while (TRUE) {
1297 attempts++;
1298 state = blank_state(w2, h2, params->unique);
1299 scratch = unruly_new_scratch(state);
1300 if (unruly_fill_game(state, scratch, rs))
1301 break;
1302 free_game(state);
1303 unruly_free_scratch(scratch);
1306 #ifdef STANDALONE_SOLVER
1307 if (solver_verbose) {
1308 printf("Puzzle generated in %i attempts\n", attempts);
1309 debug = game_text_format(state);
1310 fputs(debug, stdout);
1311 sfree(debug);
1313 temp_verbose = solver_verbose;
1314 solver_verbose = FALSE;
1316 #endif
1318 unruly_free_scratch(scratch);
1320 /* Generate random array of spaces */
1321 spaces = snewn(s, int);
1322 for (i = 0; i < s; i++)
1323 spaces[i] = i;
1324 shuffle(spaces, s, sizeof(*spaces), rs);
1327 * Winnow the clues by starting from our filled grid, repeatedly
1328 * picking a filled space and emptying it, as long as the solver
1329 * reports that the puzzle can still be solved after doing so.
1331 for (j = 0; j < s; j++) {
1332 char c;
1333 game_state *solver;
1335 i = spaces[j];
1337 c = state->grid[i];
1338 state->grid[i] = EMPTY;
1340 solver = dup_game(state);
1341 scratch = unruly_new_scratch(state);
1343 unruly_solve_game(solver, scratch, params->diff);
1345 if (unruly_validate_counts(solver, scratch, NULL) != 0)
1346 state->grid[i] = c;
1348 free_game(solver);
1349 unruly_free_scratch(scratch);
1351 sfree(spaces);
1353 #ifdef STANDALONE_SOLVER
1354 if (temp_verbose) {
1355 solver_verbose = TRUE;
1357 printf("Final puzzle:\n");
1358 debug = game_text_format(state);
1359 fputs(debug, stdout);
1360 sfree(debug);
1362 #endif
1365 * See if the game has accidentally come out too easy.
1367 if (params->diff > 0) {
1368 int ok;
1369 game_state *solver;
1371 solver = dup_game(state);
1372 scratch = unruly_new_scratch(state);
1374 unruly_solve_game(solver, scratch, params->diff - 1);
1376 ok = unruly_validate_counts(solver, scratch, NULL);
1378 free_game(solver);
1379 unruly_free_scratch(scratch);
1381 if (ok)
1382 break;
1383 } else {
1385 * Puzzles of the easiest difficulty can't be too easy.
1387 break;
1391 /* Encode description */
1392 ret = snewn(s + 1, char);
1393 p = ret;
1394 run = 0;
1395 for (i = 0; i < s+1; i++) {
1396 if (i == s || state->grid[i] == N_ZERO) {
1397 while (run > 24) {
1398 *p++ = 'z';
1399 run -= 25;
1401 *p++ = 'a' + run;
1402 run = 0;
1403 } else if (state->grid[i] == N_ONE) {
1404 while (run > 24) {
1405 *p++ = 'Z';
1406 run -= 25;
1408 *p++ = 'A' + run;
1409 run = 0;
1410 } else {
1411 run++;
1414 *p = '\0';
1416 free_game(state);
1418 return ret;
1421 /* ************** *
1422 * User Interface *
1423 * ************** */
1425 struct game_ui {
1426 int cx, cy;
1427 char cursor;
1430 static game_ui *new_ui(const game_state *state)
1432 game_ui *ret = snew(game_ui);
1434 ret->cx = ret->cy = 0;
1435 ret->cursor = FALSE;
1437 return ret;
1440 static void free_ui(game_ui *ui)
1442 sfree(ui);
1445 static char *encode_ui(const game_ui *ui)
1447 return NULL;
1450 static void decode_ui(game_ui *ui, const char *encoding)
1454 static void game_changed_state(game_ui *ui, const game_state *oldstate,
1455 const game_state *newstate)
1459 struct game_drawstate {
1460 int tilesize;
1461 int w2, h2;
1462 int started;
1464 int *gridfs;
1465 int *rowfs;
1467 int *grid;
1470 static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
1472 struct game_drawstate *ds = snew(struct game_drawstate);
1474 int w2 = state->w2, h2 = state->h2;
1475 int s = w2 * h2;
1476 int i;
1478 ds->tilesize = 0;
1479 ds->w2 = w2;
1480 ds->h2 = h2;
1481 ds->started = FALSE;
1483 ds->gridfs = snewn(s, int);
1484 ds->rowfs = snewn(2 * (w2 + h2), int);
1486 ds->grid = snewn(s, int);
1487 for (i = 0; i < s; i++)
1488 ds->grid[i] = -1;
1490 return ds;
1493 static void game_free_drawstate(drawing *dr, game_drawstate *ds)
1495 sfree(ds->gridfs);
1496 sfree(ds->rowfs);
1497 sfree(ds->grid);
1498 sfree(ds);
1501 #define COORD(x) ( (x) * ds->tilesize + ds->tilesize/2 )
1502 #define FROMCOORD(x) ( ((x)-(ds->tilesize/2)) / ds->tilesize )
1504 static char *interpret_move(const game_state *state, game_ui *ui,
1505 const game_drawstate *ds,
1506 int ox, int oy, int button)
1508 int hx = ui->cx;
1509 int hy = ui->cy;
1511 int gx = FROMCOORD(ox);
1512 int gy = FROMCOORD(oy);
1514 int w2 = state->w2, h2 = state->h2;
1516 button &= ~MOD_MASK;
1518 /* Mouse click */
1519 if (button == LEFT_BUTTON || button == RIGHT_BUTTON ||
1520 button == MIDDLE_BUTTON) {
1521 if (ox >= (ds->tilesize / 2) && gx < w2
1522 && oy >= (ds->tilesize / 2) && gy < h2) {
1523 hx = gx;
1524 hy = gy;
1525 ui->cursor = FALSE;
1526 } else
1527 return NULL;
1530 /* Keyboard move */
1531 if (IS_CURSOR_MOVE(button)) {
1532 move_cursor(button, &ui->cx, &ui->cy, w2, h2, 0);
1533 ui->cursor = TRUE;
1534 return "";
1537 /* Place one */
1538 if ((ui->cursor && (button == CURSOR_SELECT || button == CURSOR_SELECT2
1539 || button == '\b' || button == '0' || button == '1'
1540 || button == '2')) ||
1541 button == LEFT_BUTTON || button == RIGHT_BUTTON ||
1542 button == MIDDLE_BUTTON) {
1543 char buf[80];
1544 char c, i;
1546 if (state->immutable[hy * w2 + hx])
1547 return NULL;
1549 c = '-';
1550 i = state->grid[hy * w2 + hx];
1552 if (button == '0' || button == '2')
1553 c = '0';
1554 else if (button == '1')
1555 c = '1';
1556 else if (button == MIDDLE_BUTTON)
1557 c = '-';
1559 /* Cycle through options */
1560 else if (button == CURSOR_SELECT2 || button == RIGHT_BUTTON)
1561 c = (i == EMPTY ? '0' : i == N_ZERO ? '1' : '-');
1562 else if (button == CURSOR_SELECT || button == LEFT_BUTTON)
1563 c = (i == EMPTY ? '1' : i == N_ONE ? '0' : '-');
1565 if (state->grid[hy * w2 + hx] ==
1566 (c == '0' ? N_ZERO : c == '1' ? N_ONE : EMPTY))
1567 return NULL; /* don't put no-ops on the undo chain */
1569 sprintf(buf, "P%c,%d,%d", c, hx, hy);
1571 return dupstr(buf);
1573 return NULL;
1576 static game_state *execute_move(const game_state *state, const char *move)
1578 int w2 = state->w2, h2 = state->h2;
1579 int s = w2 * h2;
1580 int x, y, i;
1581 char c;
1583 game_state *ret;
1585 if (move[0] == 'S') {
1586 const char *p;
1588 ret = dup_game(state);
1589 p = move + 1;
1591 for (i = 0; i < s; i++) {
1593 if (!*p || !(*p == '1' || *p == '0')) {
1594 free_game(ret);
1595 return NULL;
1598 ret->grid[i] = (*p == '1' ? N_ONE : N_ZERO);
1599 p++;
1602 ret->completed = ret->cheated = TRUE;
1603 return ret;
1604 } else if (move[0] == 'P'
1605 && sscanf(move + 1, "%c,%d,%d", &c, &x, &y) == 3 && x >= 0
1606 && x < w2 && y >= 0 && y < h2 && (c == '-' || c == '0'
1607 || c == '1')) {
1608 ret = dup_game(state);
1609 i = y * w2 + x;
1611 if (state->immutable[i]) {
1612 free_game(ret);
1613 return NULL;
1616 ret->grid[i] = (c == '1' ? N_ONE : c == '0' ? N_ZERO : EMPTY);
1618 if (!ret->completed && unruly_validate_counts(ret, NULL, NULL) == 0
1619 && (unruly_validate_all_rows(ret, NULL) == 0))
1620 ret->completed = TRUE;
1622 return ret;
1625 return NULL;
1628 /* ----------------------------------------------------------------------
1629 * Drawing routines.
1632 static void game_compute_size(const game_params *params, int tilesize,
1633 int *x, int *y)
1635 *x = tilesize * (params->w2 + 1);
1636 *y = tilesize * (params->h2 + 1);
1639 static void game_set_size(drawing *dr, game_drawstate *ds,
1640 const game_params *params, int tilesize)
1642 ds->tilesize = tilesize;
1645 static float *game_colours(frontend *fe, int *ncolours)
1647 float *ret = snewn(3 * NCOLOURS, float);
1648 int i;
1650 frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
1652 for (i = 0; i < 3; i++) {
1653 ret[COL_1 * 3 + i] = 0.2F;
1654 ret[COL_1_HIGHLIGHT * 3 + i] = 0.4F;
1655 ret[COL_1_LOWLIGHT * 3 + i] = 0.0F;
1656 ret[COL_0 * 3 + i] = 0.95F;
1657 ret[COL_0_HIGHLIGHT * 3 + i] = 1.0F;
1658 ret[COL_0_LOWLIGHT * 3 + i] = 0.9F;
1659 ret[COL_EMPTY * 3 + i] = 0.5F;
1660 ret[COL_GRID * 3 + i] = 0.3F;
1662 game_mkhighlight_specific(fe, ret, COL_0, COL_0_HIGHLIGHT, COL_0_LOWLIGHT);
1663 game_mkhighlight_specific(fe, ret, COL_1, COL_1_HIGHLIGHT, COL_1_LOWLIGHT);
1665 ret[COL_ERROR * 3 + 0] = 1.0F;
1666 ret[COL_ERROR * 3 + 1] = 0.0F;
1667 ret[COL_ERROR * 3 + 2] = 0.0F;
1669 ret[COL_CURSOR * 3 + 0] = 0.0F;
1670 ret[COL_CURSOR * 3 + 1] = 0.7F;
1671 ret[COL_CURSOR * 3 + 2] = 0.0F;
1673 *ncolours = NCOLOURS;
1674 return ret;
1677 static void unruly_draw_err_rectangle(drawing *dr, int x, int y, int w, int h,
1678 int tilesize)
1680 double thick = tilesize / 10;
1681 double margin = tilesize / 20;
1683 draw_rect(dr, x+margin, y+margin, w-2*margin, thick, COL_ERROR);
1684 draw_rect(dr, x+margin, y+margin, thick, h-2*margin, COL_ERROR);
1685 draw_rect(dr, x+margin, y+h-margin-thick, w-2*margin, thick, COL_ERROR);
1686 draw_rect(dr, x+w-margin-thick, y+margin, thick, h-2*margin, COL_ERROR);
1689 static void unruly_draw_tile(drawing *dr, int x, int y, int tilesize, int tile)
1691 clip(dr, x, y, tilesize, tilesize);
1693 /* Draw the grid edge first, so the tile can overwrite it */
1694 draw_rect(dr, x, y, tilesize, tilesize, COL_GRID);
1696 /* Background of the tile */
1698 int val = (tile & FF_ZERO ? 0 : tile & FF_ONE ? 2 : 1);
1699 val = (val == 0 ? COL_0 : val == 2 ? COL_1 : COL_EMPTY);
1701 if ((tile & (FF_FLASH1 | FF_FLASH2)) &&
1702 (val == COL_0 || val == COL_1)) {
1703 val += (tile & FF_FLASH1 ? 1 : 2);
1706 draw_rect(dr, x, y, tilesize-1, tilesize-1, val);
1708 if ((val == COL_0 || val == COL_1) && (tile & FF_IMMUTABLE)) {
1709 draw_rect(dr, x + tilesize/6, y + tilesize/6,
1710 tilesize - 2*(tilesize/6) - 2, 1, val + 2);
1711 draw_rect(dr, x + tilesize/6, y + tilesize/6,
1712 1, tilesize - 2*(tilesize/6) - 2, val + 2);
1713 draw_rect(dr, x + tilesize/6 + 1, y + tilesize - tilesize/6 - 2,
1714 tilesize - 2*(tilesize/6) - 2, 1, val + 1);
1715 draw_rect(dr, x + tilesize - tilesize/6 - 2, y + tilesize/6 + 1,
1716 1, tilesize - 2*(tilesize/6) - 2, val + 1);
1720 /* 3-in-a-row errors */
1721 if (tile & (FE_HOR_ROW_LEFT | FE_HOR_ROW_RIGHT)) {
1722 int left = x, right = x + tilesize - 1;
1723 if ((tile & FE_HOR_ROW_LEFT))
1724 right += tilesize/2;
1725 if ((tile & FE_HOR_ROW_RIGHT))
1726 left -= tilesize/2;
1727 unruly_draw_err_rectangle(dr, left, y, right-left, tilesize-1, tilesize);
1729 if (tile & (FE_VER_ROW_TOP | FE_VER_ROW_BOTTOM)) {
1730 int top = y, bottom = y + tilesize - 1;
1731 if ((tile & FE_VER_ROW_TOP))
1732 bottom += tilesize/2;
1733 if ((tile & FE_VER_ROW_BOTTOM))
1734 top -= tilesize/2;
1735 unruly_draw_err_rectangle(dr, x, top, tilesize-1, bottom-top, tilesize);
1738 /* Count errors */
1739 if (tile & FE_COUNT) {
1740 draw_text(dr, x + tilesize/2, y + tilesize/2, FONT_VARIABLE,
1741 tilesize/2, ALIGN_HCENTRE | ALIGN_VCENTRE, COL_ERROR, "!");
1744 /* Row-match errors */
1745 if (tile & FE_ROW_MATCH) {
1746 draw_rect(dr, x, y+tilesize/2-tilesize/12,
1747 tilesize, 2*(tilesize/12), COL_ERROR);
1749 if (tile & FE_COL_MATCH) {
1750 draw_rect(dr, x+tilesize/2-tilesize/12, y,
1751 2*(tilesize/12), tilesize, COL_ERROR);
1754 /* Cursor rectangle */
1755 if (tile & FF_CURSOR) {
1756 draw_rect(dr, x, y, tilesize/12, tilesize-1, COL_CURSOR);
1757 draw_rect(dr, x, y, tilesize-1, tilesize/12, COL_CURSOR);
1758 draw_rect(dr, x+tilesize-1-tilesize/12, y, tilesize/12, tilesize-1,
1759 COL_CURSOR);
1760 draw_rect(dr, x, y+tilesize-1-tilesize/12, tilesize-1, tilesize/12,
1761 COL_CURSOR);
1764 unclip(dr);
1765 draw_update(dr, x, y, tilesize, tilesize);
1768 #define TILE_SIZE (ds->tilesize)
1769 #define DEFAULT_TILE_SIZE 32
1770 #define FLASH_FRAME 0.12F
1771 #define FLASH_TIME (FLASH_FRAME * 3)
1773 static void game_redraw(drawing *dr, game_drawstate *ds,
1774 const game_state *oldstate, const game_state *state,
1775 int dir, const game_ui *ui,
1776 float animtime, float flashtime)
1778 int w2 = state->w2, h2 = state->h2;
1779 int s = w2 * h2;
1780 int flash;
1781 int x, y, i;
1783 if (!ds->started) {
1784 /* Main window background */
1785 draw_rect(dr, 0, 0, TILE_SIZE * (w2+1), TILE_SIZE * (h2+1),
1786 COL_BACKGROUND);
1787 /* Outer edge of grid */
1788 draw_rect(dr, COORD(0)-TILE_SIZE/10, COORD(0)-TILE_SIZE/10,
1789 TILE_SIZE*w2 + 2*(TILE_SIZE/10) - 1,
1790 TILE_SIZE*h2 + 2*(TILE_SIZE/10) - 1, COL_GRID);
1792 draw_update(dr, 0, 0, TILE_SIZE * (w2+1), TILE_SIZE * (h2+1));
1793 ds->started = TRUE;
1796 flash = 0;
1797 if (flashtime > 0)
1798 flash = (int)(flashtime / FLASH_FRAME) == 1 ? FF_FLASH2 : FF_FLASH1;
1800 for (i = 0; i < s; i++)
1801 ds->gridfs[i] = 0;
1802 unruly_validate_all_rows(state, ds->gridfs);
1803 for (i = 0; i < 2 * (h2 + w2); i++)
1804 ds->rowfs[i] = 0;
1805 unruly_validate_counts(state, NULL, ds->rowfs);
1807 for (y = 0; y < h2; y++) {
1808 for (x = 0; x < w2; x++) {
1809 int tile;
1811 i = y * w2 + x;
1813 tile = ds->gridfs[i];
1815 if (state->grid[i] == N_ONE) {
1816 tile |= FF_ONE;
1817 if (ds->rowfs[y] || ds->rowfs[2*h2 + x])
1818 tile |= FE_COUNT;
1819 } else if (state->grid[i] == N_ZERO) {
1820 tile |= FF_ZERO;
1821 if (ds->rowfs[h2 + y] || ds->rowfs[2*h2 + w2 + x])
1822 tile |= FE_COUNT;
1825 tile |= flash;
1827 if (state->immutable[i])
1828 tile |= FF_IMMUTABLE;
1830 if (ui->cursor && ui->cx == x && ui->cy == y)
1831 tile |= FF_CURSOR;
1833 if (ds->grid[i] != tile) {
1834 ds->grid[i] = tile;
1835 unruly_draw_tile(dr, COORD(x), COORD(y), TILE_SIZE, tile);
1841 static float game_anim_length(const game_state *oldstate,
1842 const game_state *newstate, int dir, game_ui *ui)
1844 return 0.0F;
1847 static float game_flash_length(const game_state *oldstate,
1848 const game_state *newstate, int dir, game_ui *ui)
1850 if (!oldstate->completed && newstate->completed &&
1851 !oldstate->cheated && !newstate->cheated)
1852 return FLASH_TIME;
1853 return 0.0F;
1856 static int game_status(const game_state *state)
1858 return state->completed ? +1 : 0;
1861 static int game_timing_state(const game_state *state, game_ui *ui)
1863 return TRUE;
1866 static void game_print_size(const game_params *params, float *x, float *y)
1868 int pw, ph;
1870 /* Using 7mm squares */
1871 game_compute_size(params, 700, &pw, &ph);
1872 *x = pw / 100.0F;
1873 *y = ph / 100.0F;
1876 static void game_print(drawing *dr, const game_state *state, int tilesize)
1878 int w2 = state->w2, h2 = state->h2;
1879 int x, y;
1881 int ink = print_mono_colour(dr, 0);
1883 for (y = 0; y < h2; y++)
1884 for (x = 0; x < w2; x++) {
1885 int tx = x * tilesize + (tilesize / 2);
1886 int ty = y * tilesize + (tilesize / 2);
1888 /* Draw the border */
1889 int coords[8];
1890 coords[0] = tx;
1891 coords[1] = ty - 1;
1892 coords[2] = tx + tilesize;
1893 coords[3] = ty - 1;
1894 coords[4] = tx + tilesize;
1895 coords[5] = ty + tilesize - 1;
1896 coords[6] = tx;
1897 coords[7] = ty + tilesize - 1;
1898 draw_polygon(dr, coords, 4, -1, ink);
1900 if (state->grid[y * w2 + x] == N_ONE)
1901 draw_rect(dr, tx, ty, tilesize, tilesize, ink);
1902 else if (state->grid[y * w2 + x] == N_ZERO)
1903 draw_circle(dr, tx + tilesize/2, ty + tilesize/2,
1904 tilesize/12, ink, ink);
1908 #ifdef COMBINED
1909 #define thegame unruly
1910 #endif
1912 const struct game thegame = {
1913 "Unruly", "games.unruly", "unruly",
1914 default_params,
1915 game_fetch_preset, NULL,
1916 decode_params,
1917 encode_params,
1918 free_params,
1919 dup_params,
1920 TRUE, game_configure, custom_params,
1921 validate_params,
1922 new_game_desc,
1923 validate_desc,
1924 new_game,
1925 dup_game,
1926 free_game,
1927 TRUE, solve_game,
1928 TRUE, game_can_format_as_text_now, game_text_format,
1929 new_ui,
1930 free_ui,
1931 encode_ui,
1932 decode_ui,
1933 game_changed_state,
1934 interpret_move,
1935 execute_move,
1936 DEFAULT_TILE_SIZE, game_compute_size, game_set_size,
1937 game_colours,
1938 game_new_drawstate,
1939 game_free_drawstate,
1940 game_redraw,
1941 game_anim_length,
1942 game_flash_length,
1943 game_status,
1944 TRUE, FALSE, game_print_size, game_print,
1945 FALSE, /* wants_statusbar */
1946 FALSE, game_timing_state,
1947 0, /* flags */
1950 /* ***************** *
1951 * Standalone solver *
1952 * ***************** */
1954 #ifdef STANDALONE_SOLVER
1955 #include <time.h>
1956 #include <stdarg.h>
1958 /* Most of the standalone solver code was copied from unequal.c and singles.c */
1960 const char *quis;
1962 static void usage_exit(const char *msg)
1964 if (msg)
1965 fprintf(stderr, "%s: %s\n", quis, msg);
1966 fprintf(stderr,
1967 "Usage: %s [-v] [--seed SEED] <params> | [game_id [game_id ...]]\n",
1968 quis);
1969 exit(1);
1972 int main(int argc, char *argv[])
1974 random_state *rs;
1975 time_t seed = time(NULL);
1977 game_params *params = NULL;
1979 char *id = NULL, *desc = NULL, *err;
1981 quis = argv[0];
1983 while (--argc > 0) {
1984 char *p = *++argv;
1985 if (!strcmp(p, "--seed")) {
1986 if (argc == 0)
1987 usage_exit("--seed needs an argument");
1988 seed = (time_t) atoi(*++argv);
1989 argc--;
1990 } else if (!strcmp(p, "-v"))
1991 solver_verbose = TRUE;
1992 else if (*p == '-')
1993 usage_exit("unrecognised option");
1994 else
1995 id = p;
1998 if (id) {
1999 desc = strchr(id, ':');
2000 if (desc)
2001 *desc++ = '\0';
2003 params = default_params();
2004 decode_params(params, id);
2005 err = validate_params(params, TRUE);
2006 if (err) {
2007 fprintf(stderr, "Parameters are invalid\n");
2008 fprintf(stderr, "%s: %s", argv[0], err);
2009 exit(1);
2013 if (!desc) {
2014 char *desc_gen, *aux;
2015 rs = random_new((void *) &seed, sizeof(time_t));
2016 if (!params)
2017 params = default_params();
2018 printf("Generating puzzle with parameters %s\n",
2019 encode_params(params, TRUE));
2020 desc_gen = new_game_desc(params, rs, &aux, FALSE);
2022 if (!solver_verbose) {
2023 char *fmt = game_text_format(new_game(NULL, params, desc_gen));
2024 fputs(fmt, stdout);
2025 sfree(fmt);
2028 printf("Game ID: %s\n", desc_gen);
2029 } else {
2030 game_state *input;
2031 struct unruly_scratch *scratch;
2032 int maxdiff, errcode;
2034 err = validate_desc(params, desc);
2035 if (err) {
2036 fprintf(stderr, "Description is invalid\n");
2037 fprintf(stderr, "%s", err);
2038 exit(1);
2041 input = new_game(NULL, params, desc);
2042 scratch = unruly_new_scratch(input);
2044 maxdiff = unruly_solve_game(input, scratch, DIFFCOUNT);
2046 errcode = unruly_validate_counts(input, scratch, NULL);
2047 if (unruly_validate_all_rows(input, NULL) == -1)
2048 errcode = -1;
2050 if (errcode != -1) {
2051 char *fmt = game_text_format(input);
2052 fputs(fmt, stdout);
2053 sfree(fmt);
2054 if (maxdiff < 0)
2055 printf("Difficulty: already solved!\n");
2056 else
2057 printf("Difficulty: %s\n", unruly_diffnames[maxdiff]);
2060 if (errcode == 1)
2061 printf("No solution found.\n");
2062 else if (errcode == -1)
2063 printf("Puzzle is invalid.\n");
2065 free_game(input);
2066 unruly_free_scratch(scratch);
2069 return 0;
2071 #endif