mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Having got Jigsaw mode generation working at reasonable speed, we
can now productise it. [originally from svn r7979]
This commit is contained in:
31
puzzles.but
31
puzzles.but
@ -861,9 +861,9 @@ menu are \e{Width} and \e{Height}, which are self-explanatory.
|
|||||||
|
|
||||||
\cfg{winhelp-topic}{games.solo}
|
\cfg{winhelp-topic}{games.solo}
|
||||||
|
|
||||||
You have a square grid, which is divided into square or rectangular
|
You have a square grid, which is divided into as many equally sized
|
||||||
blocks. Each square must be filled in with a digit from 1 to the
|
sub-blocks as the grid has rows. Each square must be filled in with
|
||||||
size of the grid, in such a way that
|
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
|
\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 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
|
You are given some of the numbers as clues; your aim is to place the
|
||||||
rest of the numbers correctly.
|
rest of the numbers correctly.
|
||||||
|
|
||||||
The default puzzle size is 3\by\.3 (a 9\by\.9 actual grid, divided
|
Under the default settings, the sub-blocks are square or
|
||||||
into nine 3\by\.3 blocks). You can also select sizes with
|
rectangular. The default puzzle size is 3\by\.3 (a 9\by\.9 actual
|
||||||
rectangular blocks instead of square ones, such as 2\by\.3 (a
|
grid, divided into nine 3\by\.3 blocks). You can also select sizes
|
||||||
6\by\.6 grid divided into six 3\by\.2 blocks).
|
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
|
If you select a puzzle size which requires more than 9 digits, the
|
||||||
additional digits will be letters of the alphabet. For example, if
|
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,
|
the inverse of this: for example, if you select 2 columns and 3 rows,
|
||||||
each actual block will have 3 columns and 2 rows.)
|
each actual block will have 3 columns and 2 rows.)
|
||||||
|
|
||||||
You can introduce an optional extra constraint on the puzzles,
|
If you tick the \q{X} checkbox, Solo will apply the optional extra
|
||||||
requiring that the two main diagonals of the grid also contain one
|
constraint that the two main diagonals of the grid also contain one
|
||||||
of every digit. (This is sometimes known as \q{Sudoku-X} in
|
of every digit. (This is sometimes known as \q{Sudoku-X} in
|
||||||
newspapers.) In this mode, the squares on the two main diagonals
|
newspapers.) In this mode, the squares on the two main diagonals
|
||||||
will be shaded slightly so that you know it's enabled.
|
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
|
You can also configure the type of symmetry shown in the generated
|
||||||
puzzles. More symmetry makes the puzzles look prettier but may also
|
puzzles. More symmetry makes the puzzles look prettier but may also
|
||||||
make them easier, since the symmetry constraints can force more
|
make them easier, since the symmetry constraints can force more
|
||||||
|
62
solo.c
62
solo.c
@ -3,26 +3,6 @@
|
|||||||
*
|
*
|
||||||
* TODO:
|
* 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
|
* - reports from users are that `Trivial'-mode puzzles are still
|
||||||
* rather hard compared to newspapers' easy ones, so some better
|
* rather hard compared to newspapers' easy ones, so some better
|
||||||
* low-end difficulty grading would be nice
|
* 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 Advanced X", { 3, 3, SYMM_ROT2, DIFF_SET, TRUE } },
|
||||||
{ "3x3 Extreme", { 3, 3, SYMM_ROT2, DIFF_EXTREME, FALSE } },
|
{ "3x3 Extreme", { 3, 3, SYMM_ROT2, DIFF_EXTREME, FALSE } },
|
||||||
{ "3x3 Unreasonable", { 3, 3, SYMM_ROT2, DIFF_RECURSIVE, 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
|
#ifndef SLOW_SYSTEM
|
||||||
{ "3x4 Basic", { 3, 4, SYMM_ROT2, DIFF_SIMPLE, FALSE } },
|
{ "3x4 Basic", { 3, 4, SYMM_ROT2, DIFF_SIMPLE, FALSE } },
|
||||||
{ "4x4 Basic", { 4, 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;
|
config_item *ret;
|
||||||
char buf[80];
|
char buf[80];
|
||||||
|
|
||||||
ret = snewn(6, config_item);
|
ret = snewn(7, config_item);
|
||||||
|
|
||||||
ret[0].name = "Columns of sub-blocks";
|
ret[0].name = "Columns of sub-blocks";
|
||||||
ret[0].type = C_STRING;
|
ret[0].type = C_STRING;
|
||||||
@ -395,22 +378,27 @@ static config_item *game_configure(game_params *params)
|
|||||||
ret[2].sval = NULL;
|
ret[2].sval = NULL;
|
||||||
ret[2].ival = params->xtype;
|
ret[2].ival = params->xtype;
|
||||||
|
|
||||||
ret[3].name = "Symmetry";
|
ret[3].name = "Jigsaw (irregularly shaped sub-blocks)";
|
||||||
ret[3].type = C_CHOICES;
|
ret[3].type = C_BOOLEAN;
|
||||||
ret[3].sval = ":None:2-way rotation:4-way rotation:2-way mirror:"
|
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:"
|
"2-way diagonal mirror:4-way mirror:4-way diagonal mirror:"
|
||||||
"8-way mirror";
|
"8-way mirror";
|
||||||
ret[3].ival = params->symm;
|
ret[4].ival = params->symm;
|
||||||
|
|
||||||
ret[4].name = "Difficulty";
|
ret[5].name = "Difficulty";
|
||||||
ret[4].type = C_CHOICES;
|
ret[5].type = C_CHOICES;
|
||||||
ret[4].sval = ":Trivial:Basic:Intermediate:Advanced:Extreme:Unreasonable";
|
ret[5].sval = ":Trivial:Basic:Intermediate:Advanced:Extreme:Unreasonable";
|
||||||
ret[4].ival = params->diff;
|
ret[5].ival = params->diff;
|
||||||
|
|
||||||
ret[5].name = NULL;
|
ret[6].name = NULL;
|
||||||
ret[5].type = C_END;
|
ret[6].type = C_END;
|
||||||
ret[5].sval = NULL;
|
ret[6].sval = NULL;
|
||||||
ret[5].ival = 0;
|
ret[6].ival = 0;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -422,8 +410,12 @@ static game_params *custom_params(config_item *cfg)
|
|||||||
ret->c = atoi(cfg[0].sval);
|
ret->c = atoi(cfg[0].sval);
|
||||||
ret->r = atoi(cfg[1].sval);
|
ret->r = atoi(cfg[1].sval);
|
||||||
ret->xtype = cfg[2].ival;
|
ret->xtype = cfg[2].ival;
|
||||||
ret->symm = cfg[3].ival;
|
if (cfg[3].ival) {
|
||||||
ret->diff = cfg[4].ival;
|
ret->c *= ret->r;
|
||||||
|
ret->r = 1;
|
||||||
|
}
|
||||||
|
ret->symm = cfg[4].ival;
|
||||||
|
ret->diff = cfg[5].ival;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user