chiark / gitweb /
Fix completion checking in Killer Solo.
[sgt-puzzles.git] / signpost.c
index 9dd8699521b5d7c24784858facf952306d679456..aa2e13af9abfa65ce51c0b663aead1a3cb32825d 100644 (file)
@@ -422,11 +422,12 @@ static game_params *custom_params(const config_item *cfg)
 
 static char *validate_params(const game_params *params, int full)
 {
-    if (params->w < 2 || params->h < 2)
-       return "Width and height must both be at least two";
-    if (params->w == 2 && params->h == 2)   /* leads to generation hang */
-       return "Width and height cannot both be two";
-
+    if (params->w < 1) return "Width must be at least one";
+    if (params->h < 1) return "Height must be at least one";
+    if (full && params->w == 1 && params->h == 1)
+       /* The UI doesn't let us move these from unsolved to solved,
+        * so we disallow generating (but not playing) them. */
+       return "Width and height cannot both be one";
     return NULL;
 }
 
@@ -623,6 +624,7 @@ static int new_game_fill(game_state *state, random_state *rs,
 
     state->dirs[taili] = 0;
     nfilled = 2;
+    assert(state->n > 1);
 
     while (nfilled < state->n) {
         /* Try and expand _from_ headi; keep going if there's only one
@@ -638,6 +640,8 @@ static int new_game_fill(game_state *state, random_state *rs,
             an = cell_adj(state, headi, aidx, adir);
         } while (an == 1);
 
+       if (nfilled == state->n) break;
+
         /* Try and expand _to_ taili; keep going if there's only one
          * place to go to. */
         an = cell_adj(state, taili, aidx, adir);
@@ -801,6 +805,9 @@ static char *new_game_desc(const game_params *params, random_state *rs,
     char *ret;
     int headi, taili;
 
+    /* this shouldn't happen (validate_params), but let's play it safe */
+    if (params->w == 1 && params->h == 1) return dupstr("1a");
+
 generate:
     blank_game_into(state);
 
@@ -1578,6 +1585,8 @@ static game_state *execute_move(const game_state *state, const char *move)
         si = sy*w+sx; ei = ey*w+ex;
         makelink(ret, si, ei);
     } else if (sscanf(move, "%c%d,%d", &c, &sx, &sy) == 3) {
+        int sset;
+
         if (c != 'C' && c != 'X') return NULL;
         if (!INGRID(state, sx, sy)) return NULL;
         si = sy*w+sx;
@@ -1586,11 +1595,12 @@ static game_state *execute_move(const game_state *state, const char *move)
 
         ret = dup_game(state);
 
-        if (c == 'C') {
+        sset = state->nums[si] / (state->n+1);
+        if (c == 'C' || (c == 'X' && sset == 0)) {
             /* Unlink the single cell we dragged from the board. */
             unlink_cell(ret, si);
         } else {
-            int i, set, sset = state->nums[si] / (state->n+1);
+            int i, set;
             for (i = 0; i < state->n; i++) {
                 /* Unlink all cells in the same set as the one we dragged
                  * from the board. */