Stop the analysis pass in Loopy's redraw routine from being
[sgt/puzzles] / unfinished / slide.c
index 8a954a3..38ef4d0 100644 (file)
@@ -5,9 +5,6 @@
 /*
  * TODO:
  * 
- *  - The dragging semantics are still subtly wrong in complex
- *    cases.
- * 
  *  - Improve the generator.
  *     * actually, we seem to be mostly sensible already now. I
  *      want more choice over the type of main block and location
@@ -654,7 +651,7 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
     int *list, nlist, pos;
     int tx, ty;
     int i, j;
-    int moves;
+    int moves = 0;                     /* placate optimiser */
 
     /*
      * Set up a board and fill it with singletons, except for a
@@ -824,6 +821,9 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
        }
     }
 
+    sfree(dsf);
+    sfree(list);
+    sfree(tried_merge);
     sfree(board2);
 
     *rtx = tx;
@@ -895,7 +895,7 @@ static char *validate_desc(game_params *params, char *desc)
 {
     int w = params->w, h = params->h, wh = w*h;
     int *active, *link;
-    int mains = 0, mpos = -1;
+    int mains = 0;
     int i, tx, ty, minmoves;
     char *ret;
 
@@ -966,7 +966,6 @@ static char *validate_desc(game_params *params, char *desc)
                link[i] = -1;
                if (strchr("mM", c) != NULL) {
                    mains++;
-                   mpos = i;
                }
                i++;
            }
@@ -1169,6 +1168,11 @@ static char *solve_game(game_state *state, game_state *currstate,
     return ret;
 }
 
+static int game_can_format_as_text_now(game_params *params)
+{
+    return TRUE;
+}
+
 static char *game_text_format(game_state *state)
 {
     return board_text_format(state->w, state->h, state->board,
@@ -1238,8 +1242,8 @@ struct game_drawstate {
     int started;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
-                           int x, int y, int button)
+static char *interpret_move(game_state *state, game_ui *ui,
+                            const game_drawstate *ds, int x, int y, int button)
 {
     int w = state->w, h = state->h, wh = w*h;
     int tx, ty, i, j;
@@ -1345,17 +1349,36 @@ static char *interpret_move(game_state *state, game_ui *ui, game_drawstate *ds,
         */
        return "";
     } else if (button == LEFT_DRAG && ui->dragging) {
+       int dist, distlimit, dx, dy, s, px, py;
+
        tx = FROMCOORD(x);
        ty = FROMCOORD(y);
 
        tx -= ui->drag_offset_x;
        ty -= ui->drag_offset_y;
-       if (tx < 0 || tx >= w || ty < 0 || ty >= h ||
-           !ui->reachable[ty*w+tx])
-           return NULL;               /* this drag has no effect */
 
-       ui->drag_currpos = ty*w+tx;
-       return "";
+       /*
+        * Now search outwards from (tx,ty), in order of Manhattan
+        * distance, until we find a reachable square.
+        */
+       distlimit = w+tx;
+       distlimit = max(distlimit, h+ty);
+       distlimit = max(distlimit, tx);
+       distlimit = max(distlimit, ty);
+       for (dist = 0; dist <= distlimit; dist++) {
+           for (dx = -dist; dx <= dist; dx++)
+               for (s = -1; s <= +1; s += 2) {
+                   dy = s * (dist - abs(dx));
+                   px = tx + dx;
+                   py = ty + dy;
+                   if (px >= 0 && px < w && py >= 0 && py < h &&
+                       ui->reachable[py*w+px]) {
+                       ui->drag_currpos = py*w+px;
+                       return "";
+                   }
+               }
+       }
+       return NULL;                   /* give up - this drag has no effect */
     } else if (button == LEFT_RELEASE && ui->dragging) {
        char data[256], *str;
 
@@ -1576,7 +1599,8 @@ static void game_compute_size(game_params *params, int tilesize,
                              int *x, int *y)
 {
     /* fool the macros */
-    struct dummy { int tilesize; } dummy = { tilesize }, *ds = &dummy;
+    struct dummy { int tilesize; } dummy, *ds = &dummy;
+    dummy.tilesize = tilesize;
 
     *x = params->w * TILESIZE + 2*BORDER;
     *y = params->h * TILESIZE + 2*BORDER;
@@ -2268,6 +2292,11 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
+static int game_status(game_state *state)
+{
+    return state->completed ? +1 : 0;
+}
+
 static int game_timing_state(game_state *state, game_ui *ui)
 {
     return TRUE;
@@ -2282,7 +2311,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize)
 }
 
 #ifdef COMBINED
-#define thegame nullgame
+#define thegame slide
 #endif
 
 const struct game thegame = {
@@ -2301,7 +2330,7 @@ const struct game thegame = {
     dup_game,
     free_game,
     TRUE, solve_game,
-    TRUE, game_text_format,
+    TRUE, game_can_format_as_text_now, game_text_format,
     new_ui,
     free_ui,
     encode_ui,
@@ -2316,6 +2345,7 @@ const struct game thegame = {
     game_redraw,
     game_anim_length,
     game_flash_length,
+    game_status,
     FALSE, FALSE, game_print_size, game_print,
     TRUE,                             /* wants_statusbar */
     FALSE, game_timing_state,
@@ -2332,14 +2362,17 @@ int main(int argc, char **argv)
     game_state *s;
     char *id = NULL, *desc, *err;
     int count = FALSE;
-    int ret, really_verbose = FALSE;
+    int ret;
     int *moves;
 
     while (--argc > 0) {
         char *p = *++argv;
+        /*
         if (!strcmp(p, "-v")) {
-            really_verbose = TRUE;
-        } else if (!strcmp(p, "-c")) {
+            verbose = TRUE;
+        } else
+        */
+        if (!strcmp(p, "-c")) {
             count = TRUE;
         } else if (*p == '-') {
             fprintf(stderr, "%s: unrecognised option `%s'\n", argv[0], p);