chiark / gitweb /
Having got Jigsaw mode generation working at reasonable speed, we
authorSimon Tatham <anakin@pobox.com>
Tue, 8 Apr 2008 10:30:18 +0000 (10:30 +0000)
committerSimon Tatham <anakin@pobox.com>
Tue, 8 Apr 2008 10:30:18 +0000 (10:30 +0000)
can now productise it.

[originally from svn r7979]

puzzles.but
solo.c

index e40a1fe7e8ce59a0b79820775884eb81ff2674fd..1e9e714af474589ebe45a52d5eb8662d8b45eed4 100644 (file)
@@ -861,9 +861,9 @@ menu are \e{Width} and \e{Height}, which are self-explanatory.
 
 \cfg{winhelp-topic}{games.solo}
 
-You have a square grid, which is divided into square or rectangular
-blocks. Each square must be filled in with a digit from 1 to the
-size of the grid, in such a way that
+You have a square grid, which is divided into as many equally sized
+sub-blocks as the grid has rows. Each square must be filled in with
+a digit from 1 to the size of the grid, in such a way that
 
 \b every row contains only one occurrence of each digit
 
@@ -871,13 +871,19 @@ size of the grid, in such a way that
 
 \b every block contains only one occurrence of each digit.
 
+\b (optionally, by default off) each of the square's two main
+diagonals contains only one occurrence of each digit.
+
 You are given some of the numbers as clues; your aim is to place the
 rest of the numbers correctly.
 
-The default puzzle size is 3\by\.3 (a 9\by\.9 actual grid, divided
-into nine 3\by\.3 blocks). You can also select sizes with
-rectangular blocks instead of square ones, such as 2\by\.3 (a
-6\by\.6 grid divided into six 3\by\.2 blocks).
+Under the default settings, the sub-blocks are square or
+rectangular. The default puzzle size is 3\by\.3 (a 9\by\.9 actual
+grid, divided into nine 3\by\.3 blocks). You can also select sizes
+with rectangular blocks instead of square ones, such as 2\by\.3 (a
+6\by\.6 grid divided into six 3\by\.2 blocks). Alternatively, you
+can select \q{jigsaw} mode, in which the sub-blocks are arbitrary
+shapes which differ between individual puzzles.
 
 If you select a puzzle size which requires more than 9 digits, the
 additional digits will be letters of the alphabet. For example, if
@@ -930,12 +936,19 @@ rows, into which the main grid is divided. (The size of a block is
 the inverse of this: for example, if you select 2 columns and 3 rows,
 each actual block will have 3 columns and 2 rows.)
 
-You can introduce an optional extra constraint on the puzzles,
-requiring that the two main diagonals of the grid also contain one
+If you tick the \q{X} checkbox, Solo will apply the optional extra
+constraint that the two main diagonals of the grid also contain one
 of every digit. (This is sometimes known as \q{Sudoku-X} in
 newspapers.) In this mode, the squares on the two main diagonals
 will be shaded slightly so that you know it's enabled.
 
+If you tick the \q{Jigsaw} checkbox, Solo will generate randomly
+shaped sub-blocks. In this mode, the actual grid size will be taken
+to be the product of the numbers entered in the \q{Columns} and
+\q{Rows} boxes. There is no reason why you have to enter a number
+greater than 1 in both boxes; Jigsaw mode has no constraint on the
+grid size, and it can even be a prime number if you feel like it.
+
 You can also configure the type of symmetry shown in the generated
 puzzles. More symmetry makes the puzzles look prettier but may also
 make them easier, since the symmetry constraints can force more
diff --git a/solo.c b/solo.c
index 4c032d821a84429f5f9769894c480e94e4fc47ca..1879a988792d80438be1a4a95fe4e0690dac2cea 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -3,26 +3,6 @@
  *
  * TODO:
  *
- *  - Jigsaw Sudoku is currently an undocumented feature enabled
- *    by setting r (`Rows of sub-blocks' in the GUI configurer) to
- *    1. The reason it's undocumented is because they're rather
- *    erratic to generate, because gridgen tends to hang up for
- *    ages. I think this is because some jigsaw block layouts
- *    simply do not admit very many valid filled grids (and
- *    perhaps some have none at all).
- *     + To fix this, I think probably the solution is a change in
- *      grid generation policy: gridgen needs to have less of an
- *      all-or-nothing attitude and instead make only a limited
- *      amount of effort to construct a filled grid before giving
- *      up and trying a new layout. (Come to think of it, this
- *      same change might also make 5x5 standard Sudoku more
- *      practical to generate, if correctly tuned.)
- *     + If I get this fixed, other work needed on jigsaw mode is:
- *       * introduce a GUI config checkbox. game_configure()
- *         ticks this box iff r==1; if it's ticked in a call to
- *         custom_params(), we replace (c, r) with (c*r, 1).
- *        * document it.
- *
  *  - reports from users are that `Trivial'-mode puzzles are still
  *    rather hard compared to newspapers' easy ones, so some better
  *    low-end difficulty grading would be nice
@@ -258,6 +238,9 @@ static int game_fetch_preset(int i, char **name, game_params **params)
         { "3x3 Advanced X", { 3, 3, SYMM_ROT2, DIFF_SET, TRUE } },
         { "3x3 Extreme", { 3, 3, SYMM_ROT2, DIFF_EXTREME, FALSE } },
         { "3x3 Unreasonable", { 3, 3, SYMM_ROT2, DIFF_RECURSIVE, FALSE } },
+        { "9 Jigsaw Basic", { 9, 1, SYMM_ROT2, DIFF_SIMPLE, FALSE } },
+        { "9 Jigsaw Basic X", { 9, 1, SYMM_ROT2, DIFF_SIMPLE, TRUE } },
+        { "9 Jigsaw Advanced", { 9, 1, SYMM_ROT2, DIFF_SET, FALSE } },
 #ifndef SLOW_SYSTEM
         { "3x4 Basic", { 3, 4, SYMM_ROT2, DIFF_SIMPLE, FALSE } },
         { "4x4 Basic", { 4, 4, SYMM_ROT2, DIFF_SIMPLE, FALSE } },
@@ -376,7 +359,7 @@ static config_item *game_configure(game_params *params)
     config_item *ret;
     char buf[80];
 
-    ret = snewn(6, config_item);
+    ret = snewn(7, config_item);
 
     ret[0].name = "Columns of sub-blocks";
     ret[0].type = C_STRING;
@@ -395,22 +378,27 @@ static config_item *game_configure(game_params *params)
     ret[2].sval = NULL;
     ret[2].ival = params->xtype;
 
-    ret[3].name = "Symmetry";
-    ret[3].type = C_CHOICES;
-    ret[3].sval = ":None:2-way rotation:4-way rotation:2-way mirror:"
+    ret[3].name = "Jigsaw (irregularly shaped sub-blocks)";
+    ret[3].type = C_BOOLEAN;
+    ret[3].sval = NULL;
+    ret[3].ival = (params->r == 1);
+
+    ret[4].name = "Symmetry";
+    ret[4].type = C_CHOICES;
+    ret[4].sval = ":None:2-way rotation:4-way rotation:2-way mirror:"
         "2-way diagonal mirror:4-way mirror:4-way diagonal mirror:"
         "8-way mirror";
-    ret[3].ival = params->symm;
+    ret[4].ival = params->symm;
 
-    ret[4].name = "Difficulty";
-    ret[4].type = C_CHOICES;
-    ret[4].sval = ":Trivial:Basic:Intermediate:Advanced:Extreme:Unreasonable";
-    ret[4].ival = params->diff;
+    ret[5].name = "Difficulty";
+    ret[5].type = C_CHOICES;
+    ret[5].sval = ":Trivial:Basic:Intermediate:Advanced:Extreme:Unreasonable";
+    ret[5].ival = params->diff;
 
-    ret[5].name = NULL;
-    ret[5].type = C_END;
-    ret[5].sval = NULL;
-    ret[5].ival = 0;
+    ret[6].name = NULL;
+    ret[6].type = C_END;
+    ret[6].sval = NULL;
+    ret[6].ival = 0;
 
     return ret;
 }
@@ -422,8 +410,12 @@ static game_params *custom_params(config_item *cfg)
     ret->c = atoi(cfg[0].sval);
     ret->r = atoi(cfg[1].sval);
     ret->xtype = cfg[2].ival;
-    ret->symm = cfg[3].ival;
-    ret->diff = cfg[4].ival;
+    if (cfg[3].ival) {
+       ret->c *= ret->r;
+       ret->r = 1;
+    }
+    ret->symm = cfg[4].ival;
+    ret->diff = cfg[5].ival;
 
     return ret;
 }