Minor improvement to initial loop generation.
[sgt/puzzles] / loopy.c
diff --git a/loopy.c b/loopy.c
index 5b95229..42e7856 100644 (file)
--- a/loopy.c
+++ b/loopy.c
@@ -227,15 +227,18 @@ static void free_solver_state(solver_state *sstate) {
         sfree(sstate->dot_atleastone);
         sfree(sstate->dot_atmostone);
         /*    sfree(sstate->dline_identical); */
+        sfree(sstate->dotdsf);
+        sfree(sstate->looplen);
+        sfree(sstate);
     }
 }
 
 static solver_state *dup_solver_state(solver_state *sstate) {
-    game_state *state = dup_game(sstate->state);
+    game_state *state;
 
     solver_state *ret = snew(solver_state);
 
-    ret->state = dup_game(state);
+    ret->state = state = dup_game(sstate->state);
 
     ret->dot_atmostone = snewn(DOT_COUNT(state), char);
     memcpy(ret->dot_atmostone, sstate->dot_atmostone, DOT_COUNT(state));
@@ -370,9 +373,14 @@ static game_params *default_params(void)
 {
     game_params *ret = snew(game_params);
 
+#ifdef SLOW_SYSTEM
+    ret->h = 4;
+    ret->w = 4;
+#else
     ret->h = 10;
     ret->w = 10;
-    ret->rec = 0; 
+#endif
+    ret->rec = 0;
 
     return ret;
 }
@@ -391,11 +399,13 @@ static const struct {
     { "4x4 Easy",   {  4,  4, 0 } },
     { "4x4 Hard",   {  4,  4, 2 } },
     { "7x7 Easy",   {  7,  7, 0 } },
-    { "7x7 Hard",   {  7,  7, 0 } },
+    { "7x7 Hard",   {  7,  7, 2 } },
     { "10x10 Easy", { 10, 10, 0 } },
+#ifndef SLOW_SYSTEM
     { "10x10 Hard", { 10, 10, 2 } },
     { "15x15 Easy", { 15, 15, 0 } },
-    { "20x30 Easy", { 20, 30, 0 } }
+    { "30x20 Easy", { 30, 20, 0 } }
+#endif
 };
 
 static int game_fetch_preset(int i, char **name, game_params **params)
@@ -503,7 +513,7 @@ static char *validate_params(game_params *params, int full)
  * light towards those with high scores */
 struct square { 
     int score;
-    int random;
+    unsigned long random;
     int x, y;
 };
 
@@ -535,10 +545,10 @@ static int square_sort_cmpfn(void *v1, void *v2)
         return r;
     }
 
-    r = s1->random - s2->random;
-    if (r) {
-       return r;
-    }
+    if (s1->random < s2->random)
+        return -1;
+    else if (s1->random > s2->random)
+        return 1;
 
     /*
      * It's _just_ possible that two squares might have been given
@@ -754,7 +764,16 @@ static char *new_fullyclued_board(game_params *params, random_state *rs)
         square = (struct square *)index234(lightable_squares_sorted, 0);
         assert(square);
 
-        if (square->score <= 0)
+       /*
+        * We never want to _decrease_ the loop's perimeter. Making
+        * moves that leave the perimeter the same is occasionally
+        * useful: if it were _never_ done then the user would be
+        * able to deduce illicitly that any degree-zero vertex was
+        * on the outside of the loop. So we do it sometimes but
+        * not always.
+        */
+        if (square->score < 0 || (square->score == 0 &&
+                                 random_upto(rs, 2) == 0))
             break;
 
         print_tree(lightable_squares_sorted);
@@ -811,6 +830,7 @@ static char *new_fullyclued_board(game_params *params, random_state *rs)
                 }
             }
         }
+        sfree(square);
 /*        printf("\n\n"); */
     }
 
@@ -883,6 +903,7 @@ static game_state *remove_clues(game_state *state, random_state *rs)
             ret = saved_ret;
         }
     }
+    sfree(square_list);
 
     return ret;
 }
@@ -927,23 +948,23 @@ static char *new_game_desc(game_params *params, random_state *rs,
         for (i = 0; i < params->w; ++i) {
             if (CLUE_AT(state, i, j) == ' ') {
                 if (empty_count > 25) {
-                    dp += sprintf(dp, "%c", empty_count + 'a' - 1);
+                    dp += sprintf(dp, "%c", (int)(empty_count + 'a' - 1));
                     empty_count = 0;
                 }
                 empty_count++;
             } else {
                 if (empty_count) {
-                    dp += sprintf(dp, "%c", empty_count + 'a' - 1);
+                    dp += sprintf(dp, "%c", (int)(empty_count + 'a' - 1));
                     empty_count = 0;
                 }
-                dp += sprintf(dp, "%c", CLUE_AT(state, i, j));
+                dp += sprintf(dp, "%c", (int)(CLUE_AT(state, i, j)));
             }
         }
     }
     if (empty_count)
-        dp += sprintf(dp, "%c", empty_count + 'a' - 1);
+        dp += sprintf(dp, "%c", (int)(empty_count + 'a' - 1));
 
-    sfree(state);
+    free_game(state);
     retval = dupstr(description);
     sfree(description);
     
@@ -1162,7 +1183,7 @@ static int loop_status(game_state *state)
 
 /* Sums the lengths of the numbers in range [0,n) */
 /* See equivalent function in solo.c for justification of this. */
-int len_0_to_n(int n)
+static int len_0_to_n(int n)
 {
     int len = 1; /* Counting 0 as a bit of a special case */
     int i;
@@ -1236,7 +1257,7 @@ static char *encode_solve_move(const game_state *state)
 
     /* No point in doing sums like that if they're going to be wrong */
     assert(strlen(ret) <= (size_t)len);
-    return dupstr(ret);
+    return ret;
 }
 
 /* BEGIN SOLVER IMPLEMENTATION */
@@ -2021,7 +2042,7 @@ static char *game_text_format(game_state *state)
         rp += sprintf(rp, " \n");
         for (i = 0; i < state->w; ++i) {
             DRAW_VL;
-            rp += sprintf(rp, "%c", CLUE_AT(state, i, j));
+            rp += sprintf(rp, "%c", (int)(CLUE_AT(state, i, j)));
         }
         DRAW_VL;
         rp += sprintf(rp, "\n");
@@ -2160,7 +2181,7 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
     }
 
 
-    sprintf(buf, "%d,%d%c%c", i, j, hl_selected ? 'h' : 'v', button_char);
+    sprintf(buf, "%d,%d%c%c", i, j, (int)(hl_selected ? 'h' : 'v'), (int)button_char);
     ret = dupstr(buf);
 
     return ret;
@@ -2447,7 +2468,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
 #define CLEAR_VL(i, j) do {                                                \
                            draw_rect(dr,                                   \
                                  BORDER + i * TILE_SIZE - CROSS_SIZE,      \
-                                 BORDER + j * TILE_SIZE + LINEWIDTH/2,     \
+                                 BORDER + j * TILE_SIZE + LINEWIDTH - LINEWIDTH/2,     \
                                  CROSS_SIZE * 2,                           \
                                  TILE_SIZE - LINEWIDTH,                    \
                                  COL_BACKGROUND);                          \
@@ -2460,7 +2481,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
 
 #define CLEAR_HL(i, j) do {                                                \
                            draw_rect(dr,                                   \
-                                 BORDER + i * TILE_SIZE + LINEWIDTH/2,     \
+                                 BORDER + i * TILE_SIZE + LINEWIDTH - LINEWIDTH/2,     \
                                  BORDER + j * TILE_SIZE - CROSS_SIZE,      \
                                  TILE_SIZE - LINEWIDTH,                    \
                                  CROSS_SIZE * 2,                           \
@@ -2487,7 +2508,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
                         CLEAR_VL(i, j);
                         draw_rect(dr,
                                   BORDER + i * TILE_SIZE - LINEWIDTH/2,
-                                  BORDER + j * TILE_SIZE + LINEWIDTH/2,
+                                  BORDER + j * TILE_SIZE + LINEWIDTH - LINEWIDTH/2,
                                   LINEWIDTH, TILE_SIZE - LINEWIDTH, 
                                   line_colour);
                     }
@@ -2528,7 +2549,7 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
                         flash_changed) {
                         CLEAR_HL(i, j);
                         draw_rect(dr,
-                                  BORDER + i * TILE_SIZE + LINEWIDTH/2,
+                                  BORDER + i * TILE_SIZE + LINEWIDTH - LINEWIDTH/2,
                                   BORDER + j * TILE_SIZE - LINEWIDTH/2,
                                   TILE_SIZE - LINEWIDTH, LINEWIDTH, 
                                   line_colour);