chiark / gitweb /
Fix borders on the HTML menu bar.
[sgt-puzzles.git] / unfinished / slide.c
index 7482c735f34e4d2d94fd86ec0e3bbd9dd41b3973..9d4fce14612e1f8d11b959e8bca91306818078da 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
@@ -25,9 +22,6 @@
  *      target marker pale.
  *     * The cattle grid effect is still disgusting. Think of
  *      something completely different.
- *     * I think TRCIRC and BLCIRC should actually be drawn, as a
- *      pair of differently coloured octants. Haul out the
- *      Bresenham code, I suspect.
  *     * The highlight for next-piece-to-move in the solver is
  *      excessive, and the shadow blends in too well with the
  *      piece lowlights. Adjust both.
@@ -201,7 +195,7 @@ static void free_params(game_params *params)
     sfree(params);
 }
 
-static game_params *dup_params(game_params *params)
+static game_params *dup_params(const game_params *params)
 {
     game_params *ret = snew(game_params);
     *ret = *params;                   /* structure copy */
@@ -227,7 +221,7 @@ static void decode_params(game_params *params, char const *string)
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -240,7 +234,7 @@ static char *encode_params(game_params *params, int full)
     return dupstr(data);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -273,7 +267,7 @@ static config_item *game_configure(game_params *params)
     return ret;
 }
 
-static game_params *custom_params(config_item *cfg)
+static game_params *custom_params(const config_item *cfg)
 {
     game_params *ret = snew(game_params);
 
@@ -284,7 +278,7 @@ static game_params *custom_params(config_item *cfg)
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w > MAXWID)
        return "Width must be at most " STR(MAXWID);
@@ -657,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
@@ -827,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;
@@ -840,7 +837,7 @@ static void generate_board(int w, int h, int *rtx, int *rty, int *minmoves,
  * End of solver/generator code.
  */
 
-static char *new_game_desc(game_params *params, random_state *rs,
+static char *new_game_desc(const game_params *params, random_state *rs,
                           char **aux, int interactive)
 {
     int w = params->w, h = params->h, wh = w*h;
@@ -894,11 +891,11 @@ static char *new_game_desc(game_params *params, random_state *rs,
     return ret;
 }
 
-static char *validate_desc(game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const 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;
 
@@ -969,7 +966,6 @@ static char *validate_desc(game_params *params, char *desc)
                link[i] = -1;
                if (strchr("mM", c) != NULL) {
                    mains++;
-                   mpos = i;
                }
                i++;
            }
@@ -1005,7 +1001,8 @@ static char *validate_desc(game_params *params, char *desc)
     return ret;
 }
 
-static game_state *new_game(midend *me, game_params *params, char *desc)
+static game_state *new_game(midend *me, const game_params *params,
+                            const char *desc)
 {
     int w = params->w, h = params->h, wh = w*h;
     game_state *state;
@@ -1087,7 +1084,7 @@ static game_state *new_game(midend *me, game_params *params, char *desc)
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->w, h = state->h, wh = w*h;
     game_state *ret = snew(game_state);
@@ -1128,8 +1125,8 @@ static void free_game(game_state *state)
     sfree(state);
 }
 
-static char *solve_game(game_state *state, game_state *currstate,
-                       char *aux, char **error)
+static char *solve_game(const game_state *state, const game_state *currstate,
+                        const char *aux, char **error)
 {
     int *moves;
     int nmoves;
@@ -1172,7 +1169,12 @@ static char *solve_game(game_state *state, game_state *currstate,
     return ret;
 }
 
-static char *game_text_format(game_state *state)
+static int game_can_format_as_text_now(const game_params *params)
+{
+    return TRUE;
+}
+
+static char *game_text_format(const game_state *state)
 {
     return board_text_format(state->w, state->h, state->board,
                             state->imm->forcefield);
@@ -1187,7 +1189,7 @@ struct game_ui {
     int *bfs_queue;                   /* used as scratch in interpret_move */
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     int w = state->w, h = state->h, wh = w*h;
     game_ui *ui = snew(game_ui);
@@ -1209,17 +1211,17 @@ static void free_ui(game_ui *ui)
     sfree(ui);
 }
 
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
 {
     return NULL;
 }
 
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
 {
 }
 
-static void game_changed_state(game_ui *ui, game_state *oldstate,
-                               game_state *newstate)
+static void game_changed_state(game_ui *ui, const game_state *oldstate,
+                               const game_state *newstate)
 {
 }
 
@@ -1241,8 +1243,9 @@ 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(const 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;
@@ -1348,17 +1351,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;
 
@@ -1438,7 +1460,7 @@ static int move_piece(int w, int h, const unsigned char *src,
     return TRUE;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     int w = state->w, h = state->h /* , wh = w*h */;
     char c;
@@ -1575,18 +1597,19 @@ static game_state *execute_move(game_state *state, char *move)
  * Drawing routines.
  */
 
-static void game_compute_size(game_params *params, int tilesize,
-                             int *x, int *y)
+static void game_compute_size(const 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;
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-                         game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1646,7 +1669,7 @@ static float *game_colours(frontend *fe, int *ncolours)
     return ret;
 }
 
-static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
+static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
 {
     int w = state->w, h = state->h, wh = w*h;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1703,7 +1726,8 @@ static void game_free_drawstate(drawing *dr, game_drawstate *ds)
 #define TYPE_TRCIRC 0x5000
 #define TYPE_BLCIRC 0x6000
 #define TYPE_BRCIRC 0x7000
-static void maybe_rect(drawing *dr, int x, int y, int w, int h, int coltype)
+static void maybe_rect(drawing *dr, int x, int y, int w, int h,
+                      int coltype, int col2)
 {
     int colour = coltype & COL_MASK, type = coltype & TYPE_MASK;
 
@@ -1718,13 +1742,54 @@ static void maybe_rect(drawing *dr, int x, int y, int w, int h, int coltype)
 
        cx = x;
        cy = y;
-       assert(w == h);
        r = w-1;
        if (type & 0x1000)
            cx += r;
        if (type & 0x2000)
            cy += r;
-       draw_circle(dr, cx, cy, r, colour, colour);
+
+       if (col2 == -1 || col2 == coltype) {
+           assert(w == h);
+           draw_circle(dr, cx, cy, r, colour, colour);
+       } else {
+           /*
+            * We aim to draw a quadrant of a circle in two
+            * different colours. We do this using Bresenham's
+            * algorithm directly, because the Puzzles drawing API
+            * doesn't have a draw-sector primitive.
+            */
+           int bx, by, bd, bd2;
+           int xm = (type & 0x1000 ? -1 : +1);
+           int ym = (type & 0x2000 ? -1 : +1);
+
+           by = r;
+           bx = 0;
+           bd = 0;
+           while (by >= bx) {
+               /*
+                * Plot the point.
+                */
+               {
+                   int x1 = cx+xm*bx, y1 = cy+ym*bx;
+                   int x2, y2;
+
+                   x2 = cx+xm*by; y2 = y1;
+                   draw_rect(dr, min(x1,x2), min(y1,y2),
+                             abs(x1-x2)+1, abs(y1-y2)+1, colour);
+                   x2 = x1; y2 = cy+ym*by;
+                   draw_rect(dr, min(x1,x2), min(y1,y2),
+                             abs(x1-x2)+1, abs(y1-y2)+1, col2);
+               }
+
+               bd += 2*bx + 1;
+               bd2 = bd - (2*by - 1);
+               if (abs(bd2) < abs(bd)) {
+                   bd = bd2;
+                   by--;
+               }
+               bx++;
+           }
+       }
 
        unclip(dr);
     }
@@ -1734,6 +1799,8 @@ static void draw_wallpart(drawing *dr, game_drawstate *ds,
                          int tx, int ty, unsigned long val,
                          int cl, int cc, int ch)
 {
+    int coords[6];
+
     draw_rect(dr, tx, ty, TILESIZE, TILESIZE, cc);
     if (val & PIECE_LBORDER)
        draw_rect(dr, tx, ty, HIGHLIGHT_WIDTH, TILESIZE,
@@ -1746,12 +1813,60 @@ static void draw_wallpart(drawing *dr, game_drawstate *ds,
     if (val & PIECE_BBORDER)
        draw_rect(dr, tx, ty+TILESIZE-HIGHLIGHT_WIDTH,
                  TILESIZE, HIGHLIGHT_WIDTH, cl);
-    if (!((PIECE_BBORDER | PIECE_LBORDER) &~ val))
+    if (!((PIECE_BBORDER | PIECE_LBORDER) &~ val)) {
        draw_rect(dr, tx, ty+TILESIZE-HIGHLIGHT_WIDTH,
-                 HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, cc);
-    if (!((PIECE_TBORDER | PIECE_RBORDER) &~ val))
+                 HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, cl);
+       clip(dr, tx, ty+TILESIZE-HIGHLIGHT_WIDTH,
+            HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH);
+       coords[0] = tx - 1;
+       coords[1] = ty + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[2] = tx + HIGHLIGHT_WIDTH;
+       coords[3] = ty + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[4] = tx - 1;
+       coords[5] = ty + TILESIZE;
+       draw_polygon(dr, coords, 3, ch, ch);
+       unclip(dr);
+    } else if (val & PIECE_BLCORNER) {
+       draw_rect(dr, tx, ty+TILESIZE-HIGHLIGHT_WIDTH,
+                 HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, ch);
+       clip(dr, tx, ty+TILESIZE-HIGHLIGHT_WIDTH,
+            HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH);
+       coords[0] = tx - 1;
+       coords[1] = ty + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[2] = tx + HIGHLIGHT_WIDTH;
+       coords[3] = ty + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[4] = tx - 1;
+       coords[5] = ty + TILESIZE;
+       draw_polygon(dr, coords, 3, cl, cl);
+       unclip(dr);
+    }
+    if (!((PIECE_TBORDER | PIECE_RBORDER) &~ val)) {
        draw_rect(dr, tx+TILESIZE-HIGHLIGHT_WIDTH, ty,
-                 HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, cc);
+                 HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, cl);
+       clip(dr, tx+TILESIZE-HIGHLIGHT_WIDTH, ty,
+            HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH);
+       coords[0] = tx + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[1] = ty - 1;
+       coords[2] = tx + TILESIZE;
+       coords[3] = ty - 1;
+       coords[4] = tx + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[5] = ty + HIGHLIGHT_WIDTH;
+       draw_polygon(dr, coords, 3, ch, ch);
+       unclip(dr);
+    } else if (val & PIECE_TRCORNER) {
+       draw_rect(dr, tx+TILESIZE-HIGHLIGHT_WIDTH, ty,
+                 HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, ch);
+       clip(dr, tx+TILESIZE-HIGHLIGHT_WIDTH, ty,
+            HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH);
+       coords[0] = tx + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[1] = ty - 1;
+       coords[2] = tx + TILESIZE;
+       coords[3] = ty - 1;
+       coords[4] = tx + TILESIZE - HIGHLIGHT_WIDTH - 1;
+       coords[5] = ty + HIGHLIGHT_WIDTH;
+       draw_polygon(dr, coords, 3, cl, cl);
+       unclip(dr);
+    }
     if (val & PIECE_TLCORNER)
        draw_rect(dr, tx, ty, HIGHLIGHT_WIDTH, HIGHLIGHT_WIDTH, ch);
     if (val & PIECE_BRCORNER)
@@ -1810,79 +1925,86 @@ static void draw_piecepart(drawing *dr, game_drawstate *ds,
 
     maybe_rect(dr, RECT(0,0),
               (val & (PIECE_TLCORNER | PIECE_TBORDER |
-                      PIECE_LBORDER)) ? -1 : cc);
+                      PIECE_LBORDER)) ? -1 : cc, -1);
     maybe_rect(dr, RECT(1,0),
               (val & PIECE_TLCORNER) ? ch : (val & PIECE_TBORDER) ? -1 :
-              (val & PIECE_LBORDER) ? ch : cc);
+              (val & PIECE_LBORDER) ? ch : cc, -1);
     maybe_rect(dr, RECT(2,0),
-              (val & PIECE_TBORDER) ? -1 : cc);
+              (val & PIECE_TBORDER) ? -1 : cc, -1);
     maybe_rect(dr, RECT(3,0),
               (val & PIECE_TRCORNER) ? cl : (val & PIECE_TBORDER) ? -1 :
-              (val & PIECE_RBORDER) ? cl : cc);
+              (val & PIECE_RBORDER) ? cl : cc, -1);
     maybe_rect(dr, RECT(4,0),
               (val & (PIECE_TRCORNER | PIECE_TBORDER |
-                      PIECE_RBORDER)) ? -1 : cc);
+                      PIECE_RBORDER)) ? -1 : cc, -1);
     maybe_rect(dr, RECT(0,1),
               (val & PIECE_TLCORNER) ? ch : (val & PIECE_LBORDER) ? -1 :
-              (val & PIECE_TBORDER) ? ch : cc);
+              (val & PIECE_TBORDER) ? ch : cc, -1);
     maybe_rect(dr, RECT(1,1),
-              (val & PIECE_TLCORNER) ? cc : -1);
+              (val & PIECE_TLCORNER) ? cc : -1, -1);
     maybe_rect(dr, RECT(1,1),
               (val & PIECE_TLCORNER) ? ch | TYPE_TLCIRC :
               !((PIECE_TBORDER | PIECE_LBORDER) &~ val) ? ch | TYPE_BRCIRC :
-              (val & (PIECE_TBORDER | PIECE_LBORDER)) ? ch : cc);
+              (val & (PIECE_TBORDER | PIECE_LBORDER)) ? ch : cc, -1);
     maybe_rect(dr, RECT(2,1),
-              (val & PIECE_TBORDER) ? ch : cc);
+              (val & PIECE_TBORDER) ? ch : cc, -1);
+    maybe_rect(dr, RECT(3,1),
+              (val & PIECE_TRCORNER) ? cc : -1, -1);
     maybe_rect(dr, RECT(3,1),
               (val & (PIECE_TBORDER | PIECE_RBORDER)) == PIECE_TBORDER ? ch :
               (val & (PIECE_TBORDER | PIECE_RBORDER)) == PIECE_RBORDER ? cl :
-              !((PIECE_TBORDER|PIECE_RBORDER) &~ val) ? cc | TYPE_BLCIRC :
-              cc);
+              !((PIECE_TBORDER|PIECE_RBORDER) &~ val) ? cl | TYPE_BLCIRC :
+              (val & PIECE_TRCORNER) ? cl | TYPE_TRCIRC :
+              cc, ch);
     maybe_rect(dr, RECT(4,1),
               (val & PIECE_TRCORNER) ? ch : (val & PIECE_RBORDER) ? -1 :
-              (val & PIECE_TBORDER) ? ch : cc);
+              (val & PIECE_TBORDER) ? ch : cc, -1);
     maybe_rect(dr, RECT(0,2),
-              (val & PIECE_LBORDER) ? -1 : cc);
+              (val & PIECE_LBORDER) ? -1 : cc, -1);
     maybe_rect(dr, RECT(1,2),
-              (val & PIECE_LBORDER) ? ch : cc);
+              (val & PIECE_LBORDER) ? ch : cc, -1);
     maybe_rect(dr, RECT(2,2),
-              cc);
+              cc, -1);
     maybe_rect(dr, RECT(3,2),
-              (val & PIECE_RBORDER) ? cl : cc);
+              (val & PIECE_RBORDER) ? cl : cc, -1);
     maybe_rect(dr, RECT(4,2),
-              (val & PIECE_RBORDER) ? -1 : cc);
+              (val & PIECE_RBORDER) ? -1 : cc, -1);
     maybe_rect(dr, RECT(0,3),
               (val & PIECE_BLCORNER) ? cl : (val & PIECE_LBORDER) ? -1 :
-              (val & PIECE_BBORDER) ? cl : cc);
+              (val & PIECE_BBORDER) ? cl : cc, -1);
+    maybe_rect(dr, RECT(1,3),
+              (val & PIECE_BLCORNER) ? cc : -1, -1);
     maybe_rect(dr, RECT(1,3),
               (val & (PIECE_BBORDER | PIECE_LBORDER)) == PIECE_BBORDER ? cl :
               (val & (PIECE_BBORDER | PIECE_LBORDER)) == PIECE_LBORDER ? ch :
-              !((PIECE_BBORDER|PIECE_LBORDER) &~ val) ? cc | TYPE_TRCIRC :
-              cc);
+              !((PIECE_BBORDER|PIECE_LBORDER) &~ val) ? ch | TYPE_TRCIRC :
+              (val & PIECE_BLCORNER) ? ch | TYPE_BLCIRC :
+              cc, cl);
     maybe_rect(dr, RECT(2,3),
-              (val & PIECE_BBORDER) ? cl : cc);
+              (val & PIECE_BBORDER) ? cl : cc, -1);
     maybe_rect(dr, RECT(3,3),
-              (val & PIECE_BRCORNER) ? cc : -1);
+              (val & PIECE_BRCORNER) ? cc : -1, -1);
     maybe_rect(dr, RECT(3,3),
               (val & PIECE_BRCORNER) ? cl | TYPE_BRCIRC :
               !((PIECE_BBORDER | PIECE_RBORDER) &~ val) ? cl | TYPE_TLCIRC :
-              (val & (PIECE_BBORDER | PIECE_RBORDER)) ? cl : cc);
+              (val & (PIECE_BBORDER | PIECE_RBORDER)) ? cl : cc, -1);
     maybe_rect(dr, RECT(4,3),
               (val & PIECE_BRCORNER) ? cl : (val & PIECE_RBORDER) ? -1 :
-              (val & PIECE_BBORDER) ? cl : cc);
+              (val & PIECE_BBORDER) ? cl : cc, -1);
     maybe_rect(dr, RECT(0,4),
-              (val & (PIECE_BLCORNER | PIECE_BBORDER | PIECE_LBORDER)) ? -1 : cc);
+              (val & (PIECE_BLCORNER | PIECE_BBORDER |
+                      PIECE_LBORDER)) ? -1 : cc, -1);
     maybe_rect(dr, RECT(1,4),
               (val & PIECE_BLCORNER) ? ch : (val & PIECE_BBORDER) ? -1 :
-              (val & PIECE_LBORDER) ? ch : cc);
+              (val & PIECE_LBORDER) ? ch : cc, -1);
     maybe_rect(dr, RECT(2,4),
-              (val & PIECE_BBORDER) ? -1 : cc);
+              (val & PIECE_BBORDER) ? -1 : cc, -1);
     maybe_rect(dr, RECT(3,4),
               (val & PIECE_BRCORNER) ? cl : (val & PIECE_BBORDER) ? -1 :
-              (val & PIECE_RBORDER) ? cl : cc);
+              (val & PIECE_RBORDER) ? cl : cc, -1);
     maybe_rect(dr, RECT(4,4),
               (val & (PIECE_BRCORNER | PIECE_BBORDER |
-                      PIECE_RBORDER)) ? -1 : cc);
+                      PIECE_RBORDER)) ? -1 : cc, -1);
 
 #undef RECT
 }
@@ -1995,9 +2117,10 @@ static unsigned long find_piecepart(int w, int h, int *dsf, int x, int y)
     return val;
 }
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                       game_state *state, int dir, game_ui *ui,
-                       float animtime, float flashtime)
+static void game_redraw(drawing *dr, game_drawstate *ds,
+                        const game_state *oldstate, const game_state *state,
+                        int dir, const game_ui *ui,
+                        float animtime, float flashtime)
 {
     int w = state->w, h = state->h, wh = w*h;
     unsigned char *board;
@@ -2157,14 +2280,14 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
     sfree(board);
 }
 
-static float game_anim_length(game_state *oldstate, game_state *newstate,
-                             int dir, game_ui *ui)
+static float game_anim_length(const game_state *oldstate,
+                              const game_state *newstate, int dir, game_ui *ui)
 {
     return 0.0F;
 }
 
-static float game_flash_length(game_state *oldstate, game_state *newstate,
-                              int dir, game_ui *ui)
+static float game_flash_length(const game_state *oldstate,
+                               const game_state *newstate, int dir, game_ui *ui)
 {
     if (oldstate->completed < 0 && newstate->completed >= 0)
         return FLASH_TIME;
@@ -2172,27 +2295,32 @@ static float game_flash_length(game_state *oldstate, game_state *newstate,
     return 0.0F;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_status(const game_state *state)
+{
+    return state->completed ? +1 : 0;
+}
+
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     return TRUE;
 }
 
-static void game_print_size(game_params *params, float *x, float *y)
+static void game_print_size(const game_params *params, float *x, float *y)
 {
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
 }
 
 #ifdef COMBINED
-#define thegame nullgame
+#define thegame slide
 #endif
 
 const struct game thegame = {
     "Slide", NULL, NULL,
     default_params,
-    game_fetch_preset,
+    game_fetch_preset, NULL,
     decode_params,
     encode_params,
     free_params,
@@ -2205,7 +2333,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,
@@ -2220,6 +2348,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,
@@ -2236,14 +2365,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);