Arrange that random seeds are as harmonised as they can reasonably
[sgt/puzzles] / mines.c
diff --git a/mines.c b/mines.c
index 4fa63d1..5afefe6 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -237,12 +237,22 @@ static game_params *custom_params(config_item *cfg)
 
 static char *validate_params(game_params *params)
 {
-    if (params->w <= 0 && params->h <= 0)
-       return "Width and height must both be greater than zero";
-    if (params->w <= 0)
-       return "Width must be greater than zero";
-    if (params->h <= 0)
-       return "Height must be greater than zero";
+    /*
+     * Lower limit on grid size: each dimension must be at least 3.
+     * 1 is theoretically workable if rather boring, but 2 is a
+     * real problem: there is often _no_ way to generate a uniquely
+     * solvable 2xn Mines grid. You either run into two mines
+     * blocking the way and no idea what's behind them, or one mine
+     * and no way to know which of the two rows it's in. If the
+     * mine count is even you can create a soluble grid by packing
+     * all the mines at one end (so what when you hit a two-mine
+     * wall there are only as many covered squares left as there
+     * are mines); but if it's odd, you are doomed, because you
+     * _have_ to have a gap somewhere which you can't determine the
+     * position of.
+     */
+    if (params->w <= 2 || params->h <= 2)
+       return "Width and height must both be greater than two";
     if (params->n > params->w * params->h - 9)
        return "Too many mines for grid size";
 
@@ -2031,12 +2041,24 @@ static char *new_mine_layout(int w, int h, int n, int x, int y, int unique,
 static char *new_game_desc(game_params *params, random_state *rs,
                           game_aux_info **aux, int interactive)
 {
+    /*
+     * We generate the coordinates of an initial click even if they
+     * aren't actually used. This has the effect of harmonising the
+     * random number usage between interactive and batch use: if
+     * you use `mines --generate' with an explicit random seed, you
+     * should get exactly the same results as if you type the same
+     * random seed into the interactive game and click in the same
+     * initial location. (Of course you won't get the same grid if
+     * you click in a _different_ initial location, but there's
+     * nothing to be done about that.)
+     */
+    int x = random_upto(rs, params->w);
+    int y = random_upto(rs, params->h);
+
     if (!interactive) {
        /*
         * For batch-generated grids, pre-open one square.
         */
-       int x = random_upto(rs, params->w);
-       int y = random_upto(rs, params->h);
        signed char *grid;
        char *desc;