shithub: puzzles

Download patch

ref: 251b21c41813055d9c416378508b1ee038bc3dac
parent: 339329449f4db72e4754f21c14295303ffe0ea5d
author: Simon Tatham <anakin@pobox.com>
date: Sat Apr 13 06:37:32 EDT 2013

Giant const patch of doom: add a 'const' to every parameter in every
puzzle backend function which ought to have it, and propagate those
consts through to per-puzzle subroutines as needed.

I've recently had to do that to a few specific parameters which were
being misused by particular puzzles (r9657, r9830), which suggests
that it's probably a good idea to do the whole lot pre-emptively
before the next such problem shows up.

[originally from svn r9832]
[r9657 == 3b250baa02a7332510685948bf17576c397b8ceb]
[r9830 == 0b93de904a98f119b1a95d3a53029f1ed4bfb9b3]

--- a/blackbox.c
+++ b/blackbox.c
@@ -87,7 +87,7 @@
     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 */
@@ -129,7 +129,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char str[256];
 
@@ -138,7 +138,7 @@
     return dupstr(str);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -174,7 +174,7 @@
     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);
 
@@ -188,7 +188,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+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";
@@ -251,7 +251,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int nballs, dlen = strlen(desc), i;
     unsigned char *bmp;
@@ -328,7 +328,8 @@
 };
 #endif
 
-static int range2grid(game_state *state, int rangeno, int *x, int *y, int *direction)
+static int range2grid(const game_state *state, int rangeno, int *x, int *y,
+                      int *direction)
 {
     if (rangeno < 0)
         return 0;
@@ -367,7 +368,7 @@
     return 0;
 }
 
-static int grid2range(game_state *state, int x, int y, int *rangeno)
+static int grid2range(const game_state *state, int x, int y, int *rangeno)
 {
     int ret, x1 = state->w+1, y1 = state->h+1;
 
@@ -391,7 +392,8 @@
     return 1;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int dlen = strlen(desc), i;
@@ -427,7 +429,7 @@
 
 #define XFER(x) ret->x = state->x
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -459,18 +461,18 @@
     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)
 {
     return dupstr("S");
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -482,7 +484,7 @@
     int flash_laser; /* 0 = never, 1 = always, 2 = if anim. */
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->flash_laserno = LASER_EMPTY;
@@ -502,7 +504,7 @@
     sfree(ui);
 }
 
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
 {
     char buf[80];
     /*
@@ -512,13 +514,13 @@
     return dupstr(buf);
 }
 
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
 {
     sscanf(encoding, "E%d", &ui->errors);
 }
 
-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)
 {
     /*
      * If we've encountered a `justwrong' state as a result of
@@ -879,8 +881,9 @@
     int flash_laserno, isflash;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 gx = -1, gy = -1, rangeno = -1, wouldflash = 0;
     enum { NONE, TOGGLE_BALL, TOGGLE_LOCK, FIRE, REVEAL,
@@ -987,7 +990,7 @@
     return dupstr(buf);
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     game_state *ret = dup_game(from);
     int gx = -1, gy = -1, rangeno = -1;
@@ -1094,8 +1097,8 @@
  * 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)
 {
     /* Border is ts/2, to make things easier.
      * Thus we have (width) + 2 (firing range*2) + 1 (border*2) tiles
@@ -1105,7 +1108,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
     ds->crad = (tilesize-1)/2;
@@ -1150,7 +1153,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -1181,8 +1184,9 @@
 }
 
 
-static void draw_arena_tile(drawing *dr, game_state *gs, game_drawstate *ds,
-                            game_ui *ui, int ax, int ay, int force, int isflash)
+static void draw_arena_tile(drawing *dr, const game_state *gs,
+                            game_drawstate *ds, const game_ui *ui,
+                            int ax, int ay, int force, int isflash)
 {
     int gx = ax+1, gy = ay+1;
     int gs_tile = GRID(gs, gx, gy), ds_tile = GRID(ds, gx, gy);
@@ -1262,8 +1266,9 @@
     GRID(ds,gx,gy) = gs_tile;
 }
 
-static void draw_laser_tile(drawing *dr, game_state *gs, game_drawstate *ds,
-                            game_ui *ui, int lno, int force)
+static void draw_laser_tile(drawing *dr, const game_state *gs,
+                            game_drawstate *ds, const game_ui *ui,
+                            int lno, int force)
 {
     int gx, gy, dx, dy, unused;
     int wrong, omitted, reflect, hit, laserval, flash = 0, tmp;
@@ -1333,9 +1338,10 @@
 
 #define CUR_ANIM 0.2F
 
-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 i, x, y, ts = TILE_SIZE, isflash = 0, force = 0;
 
@@ -1447,14 +1453,14 @@
     }
 }
 
-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 (ui->flash_laser == 2) ? CUR_ANIM : 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->reveal && newstate->reveal)
         return 4.0F * FLASH_FRAME;
@@ -1462,7 +1468,7 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     if (state->reveal) {
         /*
@@ -1479,16 +1485,16 @@
     return 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/bridges.c
+++ b/bridges.c
@@ -210,12 +210,12 @@
     }
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int x, y, len, nl;
     char *ret, *p;
@@ -679,7 +679,7 @@
     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 */
@@ -722,7 +722,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[80];
 
@@ -738,7 +738,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -790,7 +790,7 @@
     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);
 
@@ -805,7 +805,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 3 || params->h < 3)
         return "Width and height must be at least 3";
@@ -862,7 +862,7 @@
     return ret;
 }
 
-static char *game_state_diff(game_state *src, game_state *dest)
+static char *game_state_diff(const game_state *src, const game_state *dest)
 {
     int movesize = 256, movelen = 0;
     char *move = snewn(movesize, char), buf[80];
@@ -1781,7 +1781,7 @@
     return ret;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
     int wh = state->w*state->h;
@@ -2015,7 +2015,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int i, wh = params->w * params->h;
 
@@ -2043,7 +2043,7 @@
     return NULL;
 }
 
-static game_state *new_game_sub(game_params *params, char *desc)
+static game_state *new_game_sub(const game_params *params, const char *desc)
 {
     game_state *state = new_state(params);
     int x, y, run = 0;
@@ -2095,7 +2095,8 @@
     return state;
 }
 
-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)
 {
     return new_game_sub(params, desc);
 }
@@ -2118,7 +2119,7 @@
     return "";
 }
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui_cancel_drag(ui);
@@ -2134,17 +2135,17 @@
     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)
 {
 }
 
@@ -2157,7 +2158,7 @@
     int show_hints;
 };
 
-static char *update_drag_dst(game_state *state, game_ui *ui,
+static char *update_drag_dst(const game_state *state, game_ui *ui,
                              const game_drawstate *ds, int nx, int ny)
 {
     int ox, oy, dx, dy, i, currl, maxb;
@@ -2229,7 +2230,7 @@
     return "";
 }
 
-static char *finish_drag(game_state *state, game_ui *ui)
+static char *finish_drag(const game_state *state, game_ui *ui)
 {
     char buf[80];
 
@@ -2253,8 +2254,9 @@
     return dupstr(buf);
 }
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 gx = FROMCOORD(x), gy = FROMCOORD(y);
     char buf[80], *ret;
@@ -2391,7 +2393,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     game_state *ret = dup_game(state);
     int x1, y1, x2, y2, nl, n;
@@ -2458,8 +2460,8 @@
     return NULL;
 }
 
-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)
 {
     char *ret;
     game_state *solved;
@@ -2490,8 +2492,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -2502,7 +2504,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -2537,7 +2539,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int wh = state->w*state->h;
@@ -2604,7 +2606,8 @@
     draw_line(dr, ox+off, oy, ox,     oy+off, col);
 }
 
-static int between_island(game_state *state, int sx, int sy, int dx, int dy)
+static int between_island(const game_state *state, int sx, int sy,
+                          int dx, int dy)
 {
     int x = sx - dx, y = sy - dy;
 
@@ -2622,8 +2625,8 @@
     return 0;
 }
 
-static void lines_lvlh(game_state *state, game_ui *ui, int x, int y, grid_type v,
-                       int *lv_r, int *lh_r)
+static void lines_lvlh(const game_state *state, const game_ui *ui,
+                       int x, int y, grid_type v, int *lv_r, int *lh_r)
 {
     int lh = 0, lv = 0;
 
@@ -2639,7 +2642,7 @@
 }
 
 static void dsf_debug_draw(drawing *dr,
-                           game_state *state, game_drawstate *ds,
+                           const game_state *state, game_drawstate *ds,
                            int x, int y)
 {
 #ifdef DRAW_DSF
@@ -2653,8 +2656,8 @@
 #endif
 }
 
-static void lines_redraw(drawing *dr,
-                         game_state *state, game_drawstate *ds, game_ui *ui,
+static void lines_redraw(drawing *dr, const game_state *state,
+                         game_drawstate *ds, const game_ui *ui,
                          int x, int y, grid_type v, int lv, int lh)
 {
     int ox = COORD(x), oy = COORD(y);
@@ -2707,7 +2710,7 @@
     (((is)->count < 10) ? (TILE_SIZE*7)/10 : (TILE_SIZE*5)/10)
 
 static void island_redraw(drawing *dr,
-                          game_state *state, game_drawstate *ds,
+                          const game_state *state, game_drawstate *ds,
                           struct island *is, grid_type v)
 {
     /* These overlap the edges of their squares, which is why they're drawn later.
@@ -2741,9 +2744,10 @@
     draw_update(dr, ox - orad, oy - orad, updatesz, updatesz);
 }
 
-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 x, y, force = 0, i, j, redraw, lv, lh;
     grid_type v, dsv, flash = 0;
@@ -2850,14 +2854,14 @@
     }
 }
 
-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 && newstate->completed &&
         !oldstate->solved && !newstate->solved)
@@ -2866,17 +2870,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2886,7 +2890,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int ts)
+static void game_print(drawing *dr, const game_state *state, int ts)
 {
     int ink = print_mono_colour(dr, 0);
     int paper = print_mono_colour(dr, 1);
--- a/cube.c
+++ b/cube.c
@@ -280,7 +280,7 @@
     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 */
@@ -304,7 +304,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -482,7 +482,7 @@
         return d1*d1 + d2*d2 + 4*d1*d2;
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret = snewn(4, config_item);
     char buf[80];
@@ -512,7 +512,7 @@
     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);
 
@@ -538,7 +538,7 @@
     classes[thisclass]++;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     int classes[5];
     int i;
@@ -846,7 +846,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int area = grid_area(params->d1, params->d2, solids[params->solid]->order);
     int i, j;
@@ -874,7 +874,8 @@
     return NULL;
 }
 
-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)
 {
     game_grid *grid = snew(game_grid);
     game_state *state = snew(game_state);
@@ -903,7 +904,7 @@
      * the game description.
      */
     {
-	char *p = desc;
+	const char *p = desc;
 	int i, j, v;
 
 	j = 8;
@@ -960,7 +961,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -1002,23 +1003,23 @@
     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)
 {
     return NULL;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     return NULL;
 }
@@ -1027,17 +1028,17 @@
 {
 }
 
-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)
 {
 }
 
@@ -1049,7 +1050,7 @@
 /*
  * Code shared between interpret_move() and execute_move().
  */
-static int find_move_dest(game_state *from, int direction,
+static int find_move_dest(const game_state *from, int direction,
 			  int *skey, int *dkey)
 {
     int mask, dest, i, j;
@@ -1101,8 +1102,9 @@
     return dest;
 }
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 direction, mask, i;
     int skey[2], dkey[2];
@@ -1222,7 +1224,7 @@
     return NULL;		       /* should never happen */
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     game_state *ret;
     float angle;
@@ -1463,7 +1465,7 @@
     }
 }
 
-static struct bbox find_bbox(game_params *params)
+static struct bbox find_bbox(const game_params *params)
 {
     struct bbox bb;
 
@@ -1485,8 +1487,8 @@
 #define YSIZE(gs, bb, solid) \
     ((int)(((bb).d - (bb).u + 2*(solid)->border) * gs))
 
-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)
 {
     struct bbox bb = find_bbox(params);
 
@@ -1495,7 +1497,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     struct bbox bb = find_bbox(params);
 
@@ -1522,7 +1524,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -1537,14 +1539,15 @@
     sfree(ds);
 }
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                        game_state *state, int dir, game_ui *ui,
+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 i, j;
     struct bbox bb = find_bbox(&state->params);
     struct solid *poly;
-    int *pkey, *gkey;
+    const int *pkey, *gkey;
     float t[3];
     float angle;
     int square;
@@ -1553,7 +1556,7 @@
 	      YSIZE(GRID_SCALE, bb, state->solid), COL_BACKGROUND);
 
     if (dir < 0) {
-        game_state *t;
+        const game_state *t;
 
         /*
          * This is an Undo. So reverse the order of the states, and
@@ -1697,33 +1700,33 @@
     }
 }
 
-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 ROLLTIME;
 }
 
-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)
 {
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/dominosa.c
+++ b/dominosa.c
@@ -133,7 +133,7 @@
     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 */
@@ -148,7 +148,7 @@
         params->unique = FALSE;
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[80];
     sprintf(buf, "%d", params->n);
@@ -157,7 +157,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -183,7 +183,7 @@
     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);
 
@@ -193,7 +193,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->n < 1)
         return "Maximum face number must be at least one";
@@ -746,7 +746,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int n = params->n, w = n+2, h = n+1, wh = w*h;
     int *occurrences;
@@ -797,7 +797,8 @@
     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 n = params->n, w = n+2, h = n+1, wh = w*h;
     game_state *state = snew(game_state);
@@ -840,7 +841,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int n = state->params.n, w = n+2, h = n+1, wh = w*h;
     game_state *ret = snew(game_state);
@@ -871,8 +872,8 @@
     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 n = state->params.n, w = n+2, h = n+1, wh = w*h;
     int *placements;
@@ -941,12 +942,12 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -955,7 +956,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cur_x = ui->cur_y = 0;
@@ -968,17 +969,17 @@
     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)
 {
     if (!oldstate->completed && newstate->completed)
         ui->cur_visible = 0;
@@ -1001,8 +1002,9 @@
     unsigned long *visible;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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;
     char buf[80];
@@ -1075,7 +1077,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     int n = state->params.n, w = n+2, h = n+1, wh = w*h;
     int d1, d2, d3, p;
@@ -1230,8 +1232,8 @@
  * 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)
 {
     int n = params->n, w = n+2, h = n+1;
 
@@ -1244,7 +1246,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1279,7 +1281,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1328,7 +1330,7 @@
 #define CEDGE_OFF       (TILESIZE / 8)
 #define IS_EMPTY(s,x,y) ((s)->grid[(y)*(s)->w+(x)] == ((y)*(s)->w+(x)))
 
-static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
+static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
                       int x, int y, int type)
 {
     int w = state->w /*, h = state->h */;
@@ -1433,9 +1435,10 @@
     unclip(dr);
 }
 
-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 n = state->params.n, w = state->w, h = state->h, wh = w*h;
     int x, y, i;
@@ -1520,14 +1523,14 @@
     sfree(used);
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -1535,17 +1538,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -1557,7 +1560,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->w, h = state->h;
     int c, x, y;
--- a/fifteen.c
+++ b/fifteen.c
@@ -70,7 +70,7 @@
     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 */
@@ -87,7 +87,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -96,7 +96,7 @@
     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];
@@ -123,7 +123,7 @@
     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);
 
@@ -133,7 +133,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+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";
@@ -271,9 +271,10 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
-    char *p, *err;
+    const char *p;
+    char *err;
     int i, area;
     int *used;
 
@@ -286,7 +287,7 @@
 	used[i] = FALSE;
 
     for (i = 0; i < area; i++) {
-	char *q = p;
+	const char *q = p;
 	int n;
 
 	if (*p < '0' || *p > '9') {
@@ -322,11 +323,12 @@
     return err;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int i;
-    char *p;
+    const char *p;
 
     state->w = params->w;
     state->h = params->h;
@@ -354,7 +356,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -377,18 +379,18 @@
     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)
 {
     return dupstr("S");
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     char *ret, *p, buf[80];
     int x, y, col, maxlen;
@@ -430,7 +432,7 @@
     return ret;
 }
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     return NULL;
 }
@@ -439,17 +441,17 @@
 {
 }
 
-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)
 {
 }
 
@@ -460,8 +462,9 @@
     int tilesize;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 gx, gy, dx, dy;
     char buf[80];
@@ -497,7 +500,7 @@
     return dupstr(buf);
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int gx, gy, dx, dy, ux, uy, up, p;
     game_state *ret;
@@ -570,8 +573,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -582,7 +585,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -601,7 +604,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -624,7 +627,7 @@
     sfree(ds);
 }
 
-static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
+static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
                       int x, int y, int tile, int flash_colour)
 {
     if (tile == 0) {
@@ -658,9 +661,10 @@
     draw_update(dr, x, y, TILE_SIZE, TILE_SIZE);
 }
 
-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 i, pass, bgcolour;
 
@@ -814,14 +818,14 @@
     }
 }
 
-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 ANIM_TIME;
 }
 
-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 && newstate->completed &&
 	!oldstate->used_solve && !newstate->used_solve)
@@ -830,21 +834,21 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/filling.c
+++ b/filling.c
@@ -135,7 +135,7 @@
     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; /* struct copy */
@@ -149,7 +149,7 @@
     if (*string == 'x') ret->h = atoi(++string);
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[64];
     sprintf(buf, "%dx%d", params->w, params->h);
@@ -156,7 +156,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[64];
@@ -183,7 +183,7 @@
     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);
 
@@ -193,7 +193,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 1) return "Width must be at least one";
     if (params->h < 1) return "Height must be at least one";
@@ -277,12 +277,12 @@
     return repr;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     const int w = state->shared->params.w;
     const int h = state->shared->params.h;
@@ -312,7 +312,7 @@
     }
 }
 
-static game_state *new_game(midend *, game_params *, char *);
+static game_state *new_game(midend *, const game_params *, const char *);
 static void free_game(game_state *);
 
 #define SENTINEL sz
@@ -786,7 +786,6 @@
 
     if (solution) {
         int i;
-        assert(*solution == NULL);
         *solution = snewn(sz + 2, char);
         **solution = 's';
         for (i = 0; i < sz; ++i) (*solution)[i + 1] = ss.board[i] + '0';
@@ -906,7 +905,7 @@
     return game_description;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int i;
     const int sz = params->w * params->h;
@@ -924,7 +923,8 @@
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int sz = params->w * params->h;
@@ -941,7 +941,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     const int sz = state->shared->params.w * state->shared->params.h;
     game_state *ret = snew(game_state);
@@ -966,14 +966,16 @@
     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)
 {
     if (aux == NULL) {
         const int w = state->shared->params.w;
         const int h = state->shared->params.h;
-        if (!solver(state->board, w, h, &aux))
+	char *new_aux;
+        if (!solver(state->board, w, h, &new_aux))
             *error = "Sorry, I couldn't find a solution";
+	return new_aux;
     }
     return dupstr(aux);
 }
@@ -987,7 +989,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1004,17 +1006,17 @@
     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)
 {
     /* Clear any selection */
     if (ui->sel) {
@@ -1036,7 +1038,8 @@
     int *dsf_scratch, *border_scratch;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds,
+static char *interpret_move(const game_state *state, game_ui *ui,
+                            const game_drawstate *ds,
                             int x, int y, int button)
 {
     const int w = state->shared->params.w;
@@ -1135,7 +1138,7 @@
     return move ? move : "";
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     game_state *new_state = NULL;
     const int sz = state->shared->params.w * state->shared->params.h;
@@ -1204,7 +1207,7 @@
     NCOLOURS
 };
 
-static void game_compute_size(game_params *params, int tilesize,
+static void game_compute_size(const game_params *params, int tilesize,
                               int *x, int *y)
 {
     *x = (params->w + 1) * tilesize;
@@ -1212,7 +1215,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-                          game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1251,7 +1254,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1420,8 +1423,8 @@
 		TILE_SIZE);
 }
 
-static void draw_grid(drawing *dr, game_drawstate *ds, game_state *state,
-                      game_ui *ui, int flashy, int borders, int shading)
+static void draw_grid(drawing *dr, game_drawstate *ds, const game_state *state,
+                      const game_ui *ui, int flashy, int borders, int shading)
 {
     const int w = state->shared->params.w;
     const int h = state->shared->params.h;
@@ -1577,8 +1580,9 @@
         }
 }
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                        game_state *state, int dir, game_ui *ui,
+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)
 {
     const int w = state->shared->params.w;
@@ -1614,14 +1618,14 @@
     draw_grid(dr, ds, state, ui, flashy, TRUE, TRUE);
 }
 
-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)
 {
     assert(oldstate);
     assert(newstate);
@@ -1633,17 +1637,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -1655,7 +1659,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     const int w = state->shared->params.w;
     const int h = state->shared->params.h;
--- a/flip.c
+++ b/flip.c
@@ -106,7 +106,7 @@
     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 */
@@ -131,7 +131,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -141,7 +141,7 @@
     return dupstr(data);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret = snewn(4, config_item);
     char buf[80];
@@ -171,7 +171,7 @@
     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);
 
@@ -182,7 +182,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w <= 0 || params->h <= 0)
         return "Width and height must both be greater than zero";
@@ -208,7 +208,7 @@
     return ret;
 }
 
-static void decode_bitmap(unsigned char *bmp, int len, char *hex)
+static void decode_bitmap(unsigned char *bmp, int len, const char *hex)
 {
     int slen = (len + 3) / 4;
     int i;
@@ -596,7 +596,7 @@
     return ret;
 }
 
-static char *validate_desc(const 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 mlen = (wh*wh+3)/4, glen = (wh+3)/4;
@@ -613,7 +613,8 @@
     return NULL;
 }
 
-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;
     int mlen = (wh*wh+3)/4;
@@ -636,7 +637,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -671,8 +672,8 @@
 	row1[i] ^= row2[i];
 }
 
-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 w = state->w, h = state->h, wh = w * h;
     unsigned char *equations, *solution, *shortest;
@@ -853,12 +854,12 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -867,7 +868,7 @@
     int cx, cy, cdraw;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cx = ui->cy = ui->cdraw = 0;
@@ -879,17 +880,17 @@
     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)
 {
 }
 
@@ -899,8 +900,9 @@
     int tilesize;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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;
     char buf[80], *nullret = NULL;
@@ -954,7 +956,7 @@
     return nullret;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int w = from->w, h = from->h, wh = w * h;
     game_state *ret;
@@ -1005,8 +1007,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1017,7 +1019,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1056,7 +1058,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1078,9 +1080,8 @@
     sfree(ds);
 }
 
-static void draw_tile(drawing *dr, game_drawstate *ds,
-		      game_state *state, int x, int y, int tile, int anim,
-		      float animtime)
+static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
+                      int x, int y, int tile, int anim, float animtime)
 {
     int w = ds->w, h = ds->h, wh = w * h;
     int bx = x * TILE_SIZE + BORDER, by = y * TILE_SIZE + BORDER;
@@ -1155,9 +1156,10 @@
     draw_update(dr, bx+1, by+1, TILE_SIZE-1, TILE_SIZE-1);
 }
 
-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 = ds->w, h = ds->h, wh = w * h;
     int i, flashframe;
@@ -1236,14 +1238,14 @@
     }
 }
 
-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 ANIM_TIME;
 }
 
-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 && newstate->completed)
         return FLASH_FRAME * (max((newstate->w+1)/2, (newstate->h+1)/2)+1);
@@ -1251,21 +1253,21 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/galaxies.c
+++ b/galaxies.c
@@ -194,7 +194,7 @@
     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 */
@@ -221,7 +221,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char str[80];
     sprintf(str, "%dx%d", params->w, params->h);
@@ -230,7 +230,7 @@
     return dupstr(str);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -262,7 +262,7 @@
     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);
 
@@ -273,7 +273,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 3 || params->h < 3)
         return "Width and height must both be at least 3";
@@ -302,7 +302,7 @@
     space->flags &= ~F_DOT;
 }
 
-static void remove_assoc(game_state *state, space *tile) {
+static void remove_assoc(const game_state *state, space *tile) {
     if (tile->flags & F_TILE_ASSOC) {
         SPACE(state, tile->dotx, tile->doty).nassoc--;
         tile->flags &= ~F_TILE_ASSOC;
@@ -311,7 +311,7 @@
     }
 }
 
-static void add_assoc(game_state *state, space *tile, space *dot) {
+static void add_assoc(const game_state *state, space *tile, space *dot) {
     remove_assoc(state, tile);
 
 #ifdef STANDALONE_PICTURE_GENERATOR
@@ -327,7 +327,7 @@
            tile->x, tile->y, dot->x, dot->y, dot->nassoc));*/
 }
 
-static struct space *sp2dot(game_state *state, int x, int y)
+static struct space *sp2dot(const game_state *state, int x, int y)
 {
     struct space *sp = &SPACE(state, x, y);
     if (!(sp->flags & F_TILE_ASSOC)) return NULL;
@@ -336,12 +336,12 @@
 
 #define IS_VERTICAL_EDGE(x) ((x % 2) == 0)
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int maxlen = (state->sx+1)*state->sy, x, y;
     char *ret, *p;
@@ -398,7 +398,7 @@
     return ret;
 }
 
-static void dbg_state(game_state *state)
+static void dbg_state(const game_state *state)
 {
 #ifdef DEBUGGING
     char *temp = game_text_format(state);
@@ -617,7 +617,8 @@
 
 /* Returns a move string for use by 'solve', including the initial
  * 'S' if issolve is true. */
-static char *diff_game(game_state *src, game_state *dest, int issolve)
+static char *diff_game(const game_state *src, const game_state *dest,
+                       int issolve)
 {
     int movelen = 0, movesize = 256, x, y, len;
     char *move = snewn(movesize, char), buf[80], *sep = "";
@@ -819,7 +820,7 @@
     if (cleardots) game_update_dots(state);
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = blank_game(state->w, state->h);
 
@@ -1230,7 +1231,7 @@
     dbg_state(state);
 }
 
-static int check_complete(game_state *state, int *dsf, int *colours);
+static int check_complete(const game_state *state, int *dsf, int *colours);
 static int solver_state(game_state *state, int maxdiff);
 
 static char *new_game_desc(const game_params *params, random_state *rs,
@@ -1480,7 +1481,7 @@
     return (ret == -1) ? 1 : 0;
 }
 
-static game_state *load_game(const game_params *params, char *desc,
+static game_state *load_game(const game_params *params, const char *desc,
                              char **why_r)
 {
     game_state *state = blank_game(params->w, params->h);
@@ -1528,7 +1529,7 @@
     return NULL;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     char *why = NULL;
     game_state *dummy = load_game(params, desc, &why);
@@ -1540,7 +1541,8 @@
     return why;
 }
 
-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)
 {
     game_state *state = load_game(params, desc, NULL);
     if (!state) {
@@ -2212,8 +2214,8 @@
 }
 
 #ifndef EDITOR
-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)
 {
     game_state *tosolve;
     char *ret;
@@ -2263,7 +2265,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->dragging = FALSE;
@@ -2277,17 +2279,17 @@
     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)
 {
 }
 
@@ -2369,8 +2371,9 @@
 #endif
 
 #ifdef EDITOR
-static char *interpret_move(game_state *state, game_ui *ui, const 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)
 {
     char buf[80];
     int px, py;
@@ -2404,8 +2407,9 @@
     return NULL;
 }
 #else
-static char *interpret_move(game_state *state, game_ui *ui, const 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)
 {
     /* UI operations (play mode):
      *
@@ -2610,7 +2614,7 @@
 }
 #endif
 
-static int check_complete(game_state *state, int *dsf, int *colours)
+static int check_complete(const game_state *state, int *dsf, int *colours)
 {
     int w = state->w, h = state->h;
     int x, y, i, ret;
@@ -2787,7 +2791,7 @@
     return ret;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     int x, y, ax, ay, n, dx, dy;
     game_state *ret = dup_game(state);
@@ -2907,8 +2911,8 @@
  * we may want to drag from them, for example.
  */
 
-static void game_compute_size(game_params *params, int sz,
-			      int *x, int *y)
+static void game_compute_size(const game_params *params, int sz,
+                              int *x, int *y)
 {
     struct { int tilesize, w, h; } ads, *ds = &ads;
 
@@ -2921,7 +2925,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int sz)
+                          const game_params *params, int sz)
 {
     ds->tilesize = sz;
 
@@ -2988,7 +2992,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -3145,9 +3149,10 @@
     draw_update(dr, lx, ly, TILE_SIZE, TILE_SIZE);
 }
 
-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 = ds->w, h = ds->h;
     int x, y, flashing = FALSE;
@@ -3332,14 +3337,14 @@
 #endif
 }
 
-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 && newstate->completed) &&
         !(newstate->used_solve))
@@ -3348,18 +3353,18 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     return TRUE;
 }
 
 #ifndef EDITOR
-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)
 {
    int pw, ph;
 
@@ -3372,7 +3377,7 @@
    *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int sz)
+static void game_print(drawing *dr, const game_state *state, int sz)
 {
     int w = state->w, h = state->h;
     int white, black, blackish;
--- a/grid.c
+++ b/grid.c
@@ -1397,7 +1397,7 @@
     *yextent = height * a;
 }
 
-static grid *grid_new_square(int width, int height, char *desc)
+static grid *grid_new_square(int width, int height, const char *desc)
 {
     int x, y;
     /* Side length */
@@ -1460,7 +1460,7 @@
     *yextent = (2 * b * (height-1)) + 3*b;
 }
 
-static grid *grid_new_honeycomb(int width, int height, char *desc)
+static grid *grid_new_honeycomb(int width, int height, const char *desc)
 {
     int x, y;
     int a = HONEY_A;
@@ -1530,7 +1530,7 @@
 }
 
 static char *grid_validate_desc_triangular(grid_type type, int width,
-                                           int height, char *desc)
+                                           int height, const char *desc)
 {
     /*
      * Triangular grids: an absent description is valid (indicating
@@ -1549,7 +1549,7 @@
 
 /* Doesn't use the previous method of generation, it pre-dates it!
  * A triangular grid is just about simple enough to do by "brute force" */
-static grid *grid_new_triangular(int width, int height, char *desc)
+static grid *grid_new_triangular(int width, int height, const char *desc)
 {
     int x,y;
     int version = (desc == NULL ? -1 : atoi(desc));
@@ -1726,7 +1726,7 @@
     *yextent = (a+b) * (height-1) + a + b;
 }
 
-static grid *grid_new_snubsquare(int width, int height, char *desc)
+static grid *grid_new_snubsquare(int width, int height, const char *desc)
 {
     int x, y;
     int a = SNUBSQUARE_A;
@@ -1839,7 +1839,7 @@
     *yextent = 2*b*(height-1) + 2*b;
 }
 
-static grid *grid_new_cairo(int width, int height, char *desc)
+static grid *grid_new_cairo(int width, int height, const char *desc)
 {
     int x, y;
     int a = CAIRO_A;
@@ -1946,7 +1946,7 @@
     *yextent = (2*a + 2*b) * (height-1) + 3*b + a;
 }
 
-static grid *grid_new_greathexagonal(int width, int height, char *desc)
+static grid *grid_new_greathexagonal(int width, int height, const char *desc)
 {
     int x, y;
     int a = GREATHEX_A;
@@ -2076,7 +2076,7 @@
     *yextent = (2*a + b) * height;
 }
 
-static grid *grid_new_octagonal(int width, int height, char *desc)
+static grid *grid_new_octagonal(int width, int height, const char *desc)
 {
     int x, y;
     int a = OCTAGONAL_A;
@@ -2159,7 +2159,7 @@
     *yextent = 6*a * (height-1) + 8*a;
 }
 
-static grid *grid_new_kites(int width, int height, char *desc)
+static grid *grid_new_kites(int width, int height, const char *desc)
 {
     int x, y;
     int a = KITE_A;
@@ -2283,7 +2283,7 @@
     *yextent = (5*qy-4*py) * (height-1) + 4*qy + 2*ry;
 }
 
-static grid *grid_new_floret(int width, int height, char *desc)
+static grid *grid_new_floret(int width, int height, const char *desc)
 {
     int x, y;
     /* Vectors for sides; weird numbers needed to keep puzzle aligned with window
@@ -2388,7 +2388,7 @@
     *yextent = (3*a + 2*b) * (height-1) + 2*(2*a + b);
 }
 
-static grid *grid_new_dodecagonal(int width, int height, char *desc)
+static grid *grid_new_dodecagonal(int width, int height, const char *desc)
 {
     int x, y;
     int a = DODEC_A;
@@ -2468,7 +2468,7 @@
     *yextent = (3*a + 3*b) * (height-1) + 2*(2*a + b);
 }
 
-static grid *grid_new_greatdodecagonal(int width, int height, char *desc)
+static grid *grid_new_greatdodecagonal(int width, int height, const char *desc)
 {
     int x, y;
     /* Vector for side of triangle - ratio is close to sqrt(3) */
@@ -2668,7 +2668,8 @@
     return dupstr(gd);
 }
 
-static char *grid_validate_desc_penrose(grid_type type, int width, int height, char *desc)
+static char *grid_validate_desc_penrose(grid_type type, int width, int height,
+                                        const char *desc)
 {
     int tilesize = PENROSE_TILESIZE, startsz, depth, xoff, yoff, aoff, inner_radius;
     double outer_radius;
@@ -2698,7 +2699,7 @@
  * to pick.
  */
 
-static grid *grid_new_penrose(int width, int height, int which, char *desc)
+static grid *grid_new_penrose(int width, int height, int which, const char *desc)
 {
     int max_faces, max_dots, tilesize = PENROSE_TILESIZE;
     int xsz, ysz, xoff, yoff, aoff;
@@ -2790,12 +2791,12 @@
     grid_size_penrose(width, height, tilesize, xextent, yextent);
 }
 
-static grid *grid_new_penrose_p2_kite(int width, int height, char *desc)
+static grid *grid_new_penrose_p2_kite(int width, int height, const char *desc)
 {
     return grid_new_penrose(width, height, PENROSE_P2, desc);
 }
 
-static grid *grid_new_penrose_p3_thick(int width, int height, char *desc)
+static grid *grid_new_penrose_p3_thick(int width, int height, const char *desc)
 {
     return grid_new_penrose(width, height, PENROSE_P3, desc);
 }
@@ -2805,7 +2806,7 @@
 #define FNNEW(upper,lower) &grid_new_ ## lower,
 #define FNSZ(upper,lower) &grid_size_ ## lower,
 
-static grid *(*(grid_news[]))(int, int, char*) = { GRIDGEN_LIST(FNNEW) };
+static grid *(*(grid_news[]))(int, int, const char*) = { GRIDGEN_LIST(FNNEW) };
 static void(*(grid_sizes[]))(int, int, int*, int*, int*) = { GRIDGEN_LIST(FNSZ) };
 
 char *grid_new_desc(grid_type type, int width, int height, random_state *rs)
@@ -2819,7 +2820,8 @@
     }
 }
 
-char *grid_validate_desc(grid_type type, int width, int height, char *desc)
+char *grid_validate_desc(grid_type type, int width, int height,
+                         const char *desc)
 {
     if (type == GRID_PENROSE_P2 || type == GRID_PENROSE_P3) {
         return grid_validate_desc_penrose(type, width, height, desc);
@@ -2832,7 +2834,7 @@
     }
 }
 
-grid *grid_new(grid_type type, int width, int height, char *desc)
+grid *grid_new(grid_type type, int width, int height, const char *desc)
 {
     char *err = grid_validate_desc(type, width, height, desc);
     if (err) assert(!"Invalid grid description.");
--- a/grid.h
+++ b/grid.h
@@ -115,9 +115,10 @@
 /* Free directly after use if non-NULL. Will never contain an underscore
  * (so clients can safely use that as a separator). */
 char *grid_new_desc(grid_type type, int width, int height, random_state *rs);
-char *grid_validate_desc(grid_type type, int width, int height, char *desc);
+char *grid_validate_desc(grid_type type, int width, int height,
+                         const char *desc);
 
-grid *grid_new(grid_type type, int width, int height, char *desc);
+grid *grid_new(grid_type type, int width, int height, const char *desc);
 
 void grid_free(grid *g);
 
--- a/guess.c
+++ b/guess.c
@@ -66,7 +66,7 @@
     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 */
@@ -145,7 +145,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -156,7 +156,7 @@
     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];
@@ -199,7 +199,7 @@
     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);
 
@@ -213,7 +213,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->ncolours < 2 || params->npegs < 2)
 	return "Trivial solutions are uninteresting";
@@ -287,7 +287,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     unsigned char *bmp;
     int i;
@@ -310,7 +310,8 @@
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     unsigned char *bmp;
@@ -335,7 +336,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
     int i;
@@ -365,23 +366,23 @@
     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)
 {
     return dupstr("S");
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
 
-static int is_markable(game_params *params, pegrow pegs)
+static int is_markable(const game_params *params, pegrow pegs)
 {
     int i, nset = 0, nrequired, ret = 0;
     pegrow colcount = new_pegrow(params->ncolours);
@@ -422,7 +423,7 @@
     int show_labels;                   /* label the colours with letters */
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     memset(ui, 0, sizeof(game_ui));
@@ -441,7 +442,7 @@
     sfree(ui);
 }
 
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
 {
     char *ret, *p, *sep;
     int i;
@@ -463,10 +464,10 @@
     return sresize(ret, p - ret, char);
 }
 
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
 {
     int i;
-    char *p = encoding;
+    const char *p = encoding;
     for (i = 0; i < ui->curr_pegs->npegs; i++) {
         ui->curr_pegs->pegs[i] = atoi(p);
         while (*p && isdigit((unsigned char)*p)) p++;
@@ -481,8 +482,8 @@
     ui->markable = is_markable(&ui->params, ui->curr_pegs);
 }
 
-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)
 {
     int i;
 
@@ -564,7 +565,7 @@
     int drag_col, blit_ox, blit_oy;
 };
 
-static void set_peg(game_params *params, game_ui *ui, int peg, int col)
+static void set_peg(const game_params *params, game_ui *ui, int peg, int col)
 {
     ui->curr_pegs->pegs[peg] = col;
     ui->markable = is_markable(params, ui->curr_pegs);
@@ -610,7 +611,7 @@
     return nc_place;
 }
 
-static char *encode_move(game_state *from, game_ui *ui)
+static char *encode_move(const game_state *from, game_ui *ui)
 {
     char *buf, *p, *sep;
     int len, i;
@@ -632,8 +633,9 @@
     return buf;
 }
 
-static char *interpret_move(game_state *from, game_ui *ui, const game_drawstate *ds,
-			    int x, int y, int button)
+static char *interpret_move(const game_state *from, game_ui *ui,
+                            const game_drawstate *ds,
+                            int x, int y, int button)
 {
     int over_col = 0;           /* one-indexed */
     int over_guess = -1;        /* zero-indexed */
@@ -782,11 +784,11 @@
     return ret;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int i, nc_place;
     game_state *ret;
-    char *p;
+    const char *p;
 
     if (!strcmp(move, "S")) {
 	ret = dup_game(from);
@@ -842,8 +844,8 @@
 
 #define BORDER    0.5
 
-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)
 {
     double hmul, vmul_c, vmul_g, vmul;
     int hintw = (params->npegs+1)/2;
@@ -870,7 +872,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     int colh, guessh;
 
@@ -1004,7 +1006,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1206,9 +1208,10 @@
     draw_update(dr, ox-off-1, oy, 2, PEGSZ);
 }
 
-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 i, new_move;
 
@@ -1300,19 +1303,19 @@
     ds->started = 1;
 }
 
-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)
 {
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     /*
      * We return nonzero whenever the solution has been revealed, even
@@ -1323,16 +1326,16 @@
     return state->solved;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/inertia.c
+++ b/inertia.c
@@ -101,7 +101,7 @@
     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 */
@@ -149,7 +149,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -158,7 +158,7 @@
     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];
@@ -185,7 +185,7 @@
     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);
 
@@ -195,7 +195,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     /*
      * Avoid completely degenerate cases which only have one
@@ -589,7 +589,7 @@
     return gengrid(params->w, params->h, rs);
 }
 
-static char *validate_desc(const 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 starts = 0, gems = 0, i;
@@ -617,7 +617,8 @@
     return NULL;
 }
 
-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;
     int i;
@@ -654,7 +655,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->p.w, h = state->p.h, wh = w*h;
     game_state *ret = snew(game_state);
@@ -731,8 +732,8 @@
 	return 0;
 }
 
-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 w = state->p.w, h = state->p.h, wh = w*h;
     int *nodes, *nodeindex, *edges, *backedges, *edgei, *backedgei, *circuit;
@@ -1445,12 +1446,12 @@
     return soln;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -1463,7 +1464,7 @@
     int just_died;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->anim_length = 0.0F;
@@ -1479,7 +1480,7 @@
     sfree(ui);
 }
 
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
 {
     char buf[80];
     /*
@@ -1489,14 +1490,14 @@
     return dupstr(buf);
 }
 
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
 {
     int p = 0;
     sscanf(encoding, "D%d%n", &ui->deaths, &p);
 }
 
-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)
 {
     /*
      * Increment the deaths counter. We only do this if
@@ -1534,8 +1535,9 @@
 #define COORD(x)  ( (x) * TILESIZE + BORDER )
 #define FROMCOORD(x)  ( ((x) - BORDER + TILESIZE) / TILESIZE - 1 )
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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->p.w, h = state->p.h /*, wh = w*h */;
     int dir;
@@ -1609,7 +1611,7 @@
     return dupstr(buf);
 }
 
-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->p.w, h = state->p.h /*, wh = w*h */;
     int dir;
@@ -1705,8 +1707,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1717,7 +1719,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 
@@ -1767,7 +1769,7 @@
     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->p.w, h = state->p.h, wh = w*h;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1930,9 +1932,10 @@
 #define BASE_ANIM_LENGTH 0.1F
 #define FLASH_LENGTH 0.3F
 
-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->p.w, h = state->p.h /*, wh = w*h */;
     int x, y;
@@ -2110,8 +2113,8 @@
     ds->player_bg_saved = TRUE;
 }
 
-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)
 {
     int dist;
     if (dir > 0)
@@ -2122,8 +2125,8 @@
     return ui->anim_length;
 }
 
-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->dead && newstate->dead) {
 	ui->flashtype = FLASH_DEAD;
@@ -2135,7 +2138,7 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     /*
      * We never report the game as lost, on the grounds that if the
@@ -2145,16 +2148,16 @@
     return state->gems == 0 ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/keen.c
+++ b/keen.c
@@ -123,7 +123,7 @@
     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 */
@@ -151,7 +151,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[80];
 
@@ -162,7 +162,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -188,7 +188,7 @@
     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);
 
@@ -198,7 +198,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 3 || params->w > 9)
         return "Grid size must be between 3 and 9";
@@ -1145,7 +1145,7 @@
  * Gameplay.
  */
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->w, a = w*w;
     int *dsf;
@@ -1193,7 +1193,8 @@
     return NULL;
 }
 
-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, a = w*w;
     game_state *state = snew(game_state);
@@ -1252,7 +1253,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->par.w, a = w*w;
     game_state *ret = snew(game_state);
@@ -1285,8 +1286,8 @@
     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 w = state->par.w, a = w*w;
     int i, ret;
@@ -1320,12 +1321,12 @@
     return out;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -1357,7 +1358,7 @@
     int hcursor;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1372,17 +1373,17 @@
     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)
 {
     int w = newstate->par.w;
     /*
@@ -1421,7 +1422,7 @@
     char *minus_sign, *times_sign, *divide_sign;
 };
 
-static int check_errors(game_state *state, long *errors)
+static int check_errors(const game_state *state, long *errors)
 {
     int w = state->par.w, a = w*w;
     int i, j, x, y, errs = FALSE;
@@ -1528,8 +1529,9 @@
     return errs;
 }
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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->par.w;
     int tx, ty;
@@ -1615,7 +1617,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int w = from->par.w, a = w*w;
     game_state *ret;
@@ -1678,8 +1680,8 @@
 
 #define SIZE(w) ((w) * TILESIZE + 2*BORDER)
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1689,7 +1691,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1728,7 +1730,7 @@
 static const char *const times_signs[] = { "\xC3\x97", "*" };
 static const char *const divide_signs[] = { "\xC3\xB7", "/" };
 
-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->par.w, a = w*w;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1949,9 +1951,10 @@
     draw_update(dr, cx, cy, cw, ch);
 }
 
-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->par.w /*, a = w*w */;
     int x, y;
@@ -2006,14 +2009,14 @@
     }
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -2021,12 +2024,12 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     if (state->completed)
 	return FALSE;
@@ -2033,7 +2036,7 @@
     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)
 {
     int pw, ph;
 
@@ -2176,7 +2179,7 @@
     sfree(coords);
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->par.w;
     int ink = print_mono_colour(dr, 0);
--- a/lightup.c
+++ b/lightup.c
@@ -157,7 +157,8 @@
 
 /* Fills in (doesn't allocate) a surrounds structure with the grid locations
  * around a given square, taking account of the edges. */
-static void get_surrounds(game_state *state, int ox, int oy, surrounds *s)
+static void get_surrounds(const game_state *state, int ox, int oy,
+                          surrounds *s)
 {
     assert(ox >= 0 && ox < state->w && oy >= 0 && oy < state->h);
     s->npoints = 0;
@@ -229,7 +230,7 @@
     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 */
@@ -273,7 +274,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[80];
 
@@ -288,7 +289,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -333,7 +334,7 @@
     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);
 
@@ -346,7 +347,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 2 || params->h < 2)
         return "Width and height must be at least 2";
@@ -382,7 +383,7 @@
     return ret;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -479,7 +480,7 @@
     return 0;
 }
 
-static int number_wrong(game_state *state, int x, int y)
+static int number_wrong(const game_state *state, int x, int y)
 {
     surrounds s;
     int i, n, empty, lights = GRID(state, lights, x, y);
@@ -1628,7 +1629,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int i;
     for (i = 0; i < params->w*params->h; i++) {
@@ -1650,7 +1651,8 @@
     return NULL;
 }
 
-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)
 {
     game_state *ret = new_state(params);
     int x,y;
@@ -1697,8 +1699,8 @@
     return ret;
 }
 
-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)
 {
     game_state *solved;
     char *move = NULL, buf[80];
@@ -1753,7 +1755,7 @@
     return move;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
@@ -1762,7 +1764,7 @@
  * character per cell (like debug_state) but that comes out tiny.
  * 'L' is used for 'light here' because 'O' looks too much like '0'
  * (black square with no surrounding lights). */
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w = state->w, h = state->h, W = w+1, H = h+1;
     int x, y, len, lights;
@@ -1817,7 +1819,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cur_x = ui->cur_y = ui->cur_visible = 0;
@@ -1829,19 +1831,19 @@
     sfree(ui);
 }
 
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
 {
     /* nothing to encode. */
     return NULL;
 }
 
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
 {
     /* nothing to decode. */
 }
 
-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)
 {
     if (newstate->completed)
         ui->cur_visible = 0;
@@ -1873,8 +1875,9 @@
             (pc)) -1 (nil)
         (nil))
  */
-static char *interpret_move(game_state *state, game_ui *ui, const 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)
 {
     enum { NONE, FLIP_LIGHT, FLIP_IMPOSSIBLE } action = NONE;
     int cx = -1, cy = -1;
@@ -1942,7 +1945,7 @@
     return dupstr(buf);
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     game_state *ret = dup_game(state);
     int x, y, n, flags;
@@ -1992,8 +1995,8 @@
  */
 
 /* XXX entirely cloned from fifteen.c; separate out? */
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -2004,7 +2007,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
     ds->crad = 3*(tilesize-1)/8;
@@ -2037,7 +2040,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -2067,8 +2070,8 @@
 #define HINT_OVERLAPS
 #define HINT_NUMBERS
 
-static unsigned int tile_flags(game_drawstate *ds, game_state *state, game_ui *ui,
-                               int x, int y, int flashing)
+static unsigned int tile_flags(game_drawstate *ds, const game_state *state,
+                               const game_ui *ui, int x, int y, int flashing)
 {
     unsigned int flags = GRID(state, flags, x, y);
     int lights = GRID(state, lights, x, y);
@@ -2102,8 +2105,8 @@
     return ret;
 }
 
-static void tile_redraw(drawing *dr, game_drawstate *ds, game_state *state,
-                        int x, int y)
+static void tile_redraw(drawing *dr, game_drawstate *ds,
+                        const game_state *state, int x, int y)
 {
     unsigned int ds_flags = GRID(ds, flags, x, y);
     int dx = COORD(x), dy = COORD(y);
@@ -2156,9 +2159,10 @@
     draw_update(dr, dx, dy, TILE_SIZE, TILE_SIZE);
 }
 
-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 flashing = FALSE;
     int x,y;
@@ -2192,14 +2196,14 @@
     }
 }
 
-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 && newstate->completed &&
         !oldstate->used_solve && !newstate->used_solve)
@@ -2207,17 +2211,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2229,7 +2233,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->w, h = state->h;
     int ink = print_mono_colour(dr, 0);
--- a/loopy.c
+++ b/loopy.c
@@ -231,7 +231,7 @@
     char *clue_satisfied;
 };
 
-static char *validate_desc(const game_params *params, char *desc);
+static char *validate_desc(const game_params *params, const char *desc);
 static int dot_order(const game_state* state, int i, char line_type);
 static int face_order(const game_state* state, int i, char line_type);
 static solver_state *solve_game_rec(const solver_state *sstate);
@@ -277,7 +277,8 @@
 /* Generates a (dynamically allocated) new grid, according to the
  * type and size requested in params.  Does nothing if the grid is already
  * generated. */
-static grid *loopy_generate_grid(const game_params *params, char *grid_desc)
+static grid *loopy_generate_grid(const game_params *params,
+                                 const char *grid_desc)
 {
     return grid_new(grid_types[params->type], params->w, params->h, grid_desc);
 }
@@ -306,7 +307,7 @@
  * General struct manipulation and other straightforward code
  */
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -340,7 +341,7 @@
     }
 }
 
-static solver_state *new_solver_state(game_state *state, int diff) {
+static solver_state *new_solver_state(const game_state *state, int diff) {
     int i;
     int num_dots = state->game_grid->num_dots;
     int num_faces = state->game_grid->num_faces;
@@ -479,7 +480,7 @@
     return ret;
 }
 
-static game_params *dup_params(game_params *params)
+static game_params *dup_params(const game_params *params)
 {
     game_params *ret = snew(game_params);
 
@@ -574,7 +575,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char str[80];
     sprintf(str, "%dx%dt%d", params->w, params->h, params->type);
@@ -583,7 +584,7 @@
     return dupstr(str);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -620,7 +621,7 @@
     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);
 
@@ -632,7 +633,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->type < 0 || params->type >= NUM_GRID_TYPES)
         return "Illegal grid type";
@@ -694,7 +695,7 @@
 /* Splits up a (optional) grid_desc from the game desc. Returns the
  * grid_desc (which needs freeing) and updates the desc pointer to
  * start of real desc, or returns NULL if no desc. */
-static char *extract_grid_desc(char **desc)
+static char *extract_grid_desc(const char **desc)
 {
     char *sep = strchr(*desc, GRID_DESC_SEP), *gd;
     int gd_len;
@@ -713,7 +714,7 @@
 
 /* We require that the params pass the test in validate_params and that the
  * description fills the entire game area */
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int count = 0;
     grid *g;
@@ -802,7 +803,7 @@
     return ret;
 }
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     return NULL;
 }
@@ -811,21 +812,21 @@
 {
 }
 
-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)
 {
 }
 
-static void game_compute_size(game_params *params, int tilesize,
+static void game_compute_size(const game_params *params, int tilesize,
                               int *x, int *y)
 {
     int grid_width, grid_height, rendered_width, rendered_height;
@@ -842,7 +843,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -891,7 +892,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int num_faces = state->game_grid->num_faces;
@@ -926,18 +927,18 @@
     sfree(ds);
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     return TRUE;
 }
 
-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 int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     if (params->type != 0)
         return FALSE;
@@ -944,7 +945,7 @@
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w, h, W, H;
     int x, y, i;
@@ -1426,7 +1427,8 @@
     return retval;
 }
 
-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 i;
     game_state *state = snew(game_state);
@@ -2784,8 +2786,8 @@
     return sstate;
 }
 
-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)
 {
     char *soln = NULL;
     solver_state *sstate, *new_sstate;
@@ -2813,7 +2815,8 @@
  * Drawing and mouse-handling
  */
 
-static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds,
+static char *interpret_move(const game_state *state, game_ui *ui,
+                            const game_drawstate *ds,
                             int x, int y, int button)
 {
     grid *g = state->game_grid;
@@ -2888,7 +2891,7 @@
     return ret;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     int i;
     game_state *newstate = dup_game(state);
@@ -2992,7 +2995,7 @@
 }
 
 static void game_redraw_clue(drawing *dr, game_drawstate *ds,
-			     game_state *state, int i)
+			     const game_state *state, int i)
 {
     grid *g = state->game_grid;
     grid_face *f = g->faces + i;
@@ -3051,7 +3054,7 @@
 #define NPHASES lenof(loopy_line_redraw_phases)
 
 static void game_redraw_line(drawing *dr, game_drawstate *ds,
-			     game_state *state, int i, int phase)
+			     const game_state *state, int i, int phase)
 {
     grid *g = state->game_grid;
     grid_edge *e = g->edges + i;
@@ -3093,7 +3096,7 @@
 }
 
 static void game_redraw_dot(drawing *dr, game_drawstate *ds,
-			    game_state *state, int i)
+			    const game_state *state, int i)
 {
     grid *g = state->game_grid;
     grid_dot *d = g->dots + i;
@@ -3115,7 +3118,8 @@
 }
 
 static void game_redraw_in_rect(drawing *dr, game_drawstate *ds,
-                                game_state *state, int x, int y, int w, int h)
+                                const game_state *state,
+                                int x, int y, int w, int h)
 {
     grid *g = state->game_grid;
     int i, phase;
@@ -3148,8 +3152,9 @@
     draw_update(dr, x, y, w, h);
 }
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                        game_state *state, int dir, game_ui *ui,
+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)
 {
 #define REDRAW_OBJECTS_LIMIT 16		/* Somewhat arbitrary tradeoff */
@@ -3280,8 +3285,8 @@
     ds->started = TRUE;
 }
 
-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->solved  &&  newstate->solved &&
         !oldstate->cheated && !newstate->cheated) {
@@ -3291,12 +3296,12 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->solved ? +1 : 0;
 }
 
-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)
 {
     int pw, ph;
 
@@ -3308,7 +3313,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int ink = print_mono_colour(dr, 0);
     int i;
--- a/magnets.c
+++ b/magnets.c
@@ -138,7 +138,7 @@
     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 */
@@ -172,7 +172,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[256];
     sprintf(buf, "%dx%d", params->w, params->h);
@@ -183,7 +183,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[64];
@@ -220,7 +220,7 @@
     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);
 
@@ -232,7 +232,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 2) return "Width must be at least one";
     if (params->h < 2) return "Height must be at least one";
@@ -317,7 +317,7 @@
     return ret;
 }
 
-static game_state *dup_game(game_state *src)
+static game_state *dup_game(const game_state *src)
 {
     game_state *dest = snew(game_state);
 
@@ -395,7 +395,8 @@
     return -1;
 }
 
-static char *readrow(char *desc, int n, int *array, int off, const char **prob)
+static const char *readrow(const char *desc, int n, int *array, int off,
+                           const char **prob)
 {
     int i, num;
     char c;
@@ -422,7 +423,7 @@
     return NULL;
 }
 
-static game_state *new_game_int(const game_params *params, char *desc,
+static game_state *new_game_int(const game_params *params, const char *desc,
                                 const char **prob)
 {
     game_state *state = new_state(params->w, params->h);
@@ -530,7 +531,7 @@
     return state;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     const char *prob;
     game_state *st = new_game_int(params, desc, &prob);
@@ -539,7 +540,8 @@
     return NULL;
 }
 
-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)
 {
     const char *prob;
     game_state *st = new_game_int(params, desc, &prob);
@@ -580,7 +582,7 @@
     return desc;
 }
 
-static void game_text_hborder(game_state *state, char **p_r)
+static void game_text_hborder(const game_state *state, char **p_r)
 {
     char *p = *p_r;
     int x;
@@ -594,12 +596,12 @@
     *p_r = p;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int len, x, y, i;
     char *ret, *p;
@@ -680,7 +682,7 @@
     const char *name;
 } rowcol;
 
-static rowcol mkrowcol(game_state *state, int num, int roworcol)
+static rowcol mkrowcol(const game_state *state, int num, int roworcol)
 {
     rowcol rc;
 
@@ -705,7 +707,8 @@
     return rc;
 }
 
-static int count_rowcol(game_state *state, int num, int roworcol, int which)
+static int count_rowcol(const game_state *state, int num, int roworcol,
+                        int which)
 {
     int i, count = 0;
     rowcol rc = mkrowcol(state, num, roworcol);
@@ -1393,7 +1396,8 @@
 }
 
 
-static char *game_state_diff(game_state *src, game_state *dst, int issolve)
+static char *game_state_diff(const game_state *src, const game_state *dst,
+                             int issolve)
 {
     char *ret = NULL, buf[80], c;
     int retlen = 0, x, y, i, k;
@@ -1432,7 +1436,7 @@
     return ret;
 }
 
-static void solve_from_aux(game_state *state, char *aux)
+static void solve_from_aux(const game_state *state, const char *aux)
 {
     int i;
     assert(strlen(aux) == state->wh);
@@ -1442,8 +1446,8 @@
     }
 }
 
-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)
 {
     game_state *solved = dup_game(currstate);
     char *move = NULL;
@@ -1701,7 +1705,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cur_x = ui->cur_y = 0;
@@ -1714,17 +1718,17 @@
     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)
 {
     if (!oldstate->completed && newstate->completed)
         ui->cur_visible = 0;
@@ -1755,8 +1759,9 @@
 #define COORD(x) ( (x+1) * TILE_SIZE + BORDER )
 #define FROMCOORD(x) ( (x - BORDER) / TILE_SIZE - 1 )
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 gx = FROMCOORD(x), gy = FROMCOORD(y), idx, curr;
     char *nullret = NULL, buf[80], movech;
@@ -1818,7 +1823,7 @@
     return dupstr(buf);
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     game_state *ret = dup_game(state);
     int x, y, n, idx, idx2;
@@ -1878,8 +1883,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1890,7 +1895,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1928,7 +1933,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -2128,9 +2133,10 @@
 }
 
 
-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 x, y, w = state->w, h = state->h, which, i, j, flash;
     unsigned long c = 0;
@@ -2219,14 +2225,14 @@
     ds->started = 1;
 }
 
-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 && newstate->completed &&
         !oldstate->solved && !newstate->solved)
@@ -2234,17 +2240,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2256,7 +2262,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->w, h = state->h;
     int ink = print_mono_colour(dr, 0);
--- a/map.c
+++ b/map.c
@@ -155,7 +155,7 @@
     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 */
@@ -192,7 +192,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[400];
 
@@ -203,7 +203,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -241,7 +241,7 @@
     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);
 
@@ -253,7 +253,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 2 || params->h < 2)
 	return "Width and height must be at least two";
@@ -1704,11 +1704,12 @@
     return ret;
 }
 
-static char *parse_edge_list(const game_params *params, char **desc, int *map)
+static char *parse_edge_list(const game_params *params, const char **desc,
+                             int *map)
 {
     int w = params->w, h = params->h, wh = w*h, n = params->n;
     int i, k, pos, state;
-    char *p = *desc;
+    const char *p = *desc;
 
     dsf_init(map+wh, wh);
 
@@ -1780,7 +1781,7 @@
     return NULL;
 }
 
-static char *validate_desc(const 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, n = params->n;
     int area;
@@ -1815,11 +1816,12 @@
     return NULL;
 }
 
-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, n = params->n;
     int i, pos;
-    char *p;
+    const char *p;
     game_state *state = snew(game_state);
 
     state->p = *params;
@@ -2154,7 +2156,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -2188,8 +2190,8 @@
     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)
 {
     if (!aux) {
 	/*
@@ -2248,12 +2250,12 @@
     return dupstr(aux);
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -2275,7 +2277,7 @@
     int cur_x, cur_y, cur_visible, cur_moved, cur_lastmove;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->dragx = ui->dragy = -1;
@@ -2292,17 +2294,17 @@
     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)
 {
 }
 
@@ -2342,8 +2344,8 @@
                            ((button) == CURSOR_UP)    ? -1 : 0)
 
 
-static int region_from_coords(game_state *state, const game_drawstate *ds,
-                              int x, int y)
+static int region_from_coords(const game_state *state,
+                              const game_drawstate *ds, int x, int y)
 {
     int w = state->p.w, h = state->p.h, wh = w*h /*, n = state->p.n */;
     int tx = FROMCOORD(x), ty = FROMCOORD(y);
@@ -2361,8 +2363,9 @@
     return state->map->map[quadrant * wh + ty*w+tx];
 }
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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)
 {
     char *bufp, buf[256];
     int alt_button;
@@ -2497,7 +2500,7 @@
     }
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     int n = state->p.n;
     game_state *ret = dup_game(state);
@@ -2578,8 +2581,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -2590,7 +2593,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 
@@ -2643,7 +2646,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -2702,7 +2705,7 @@
 }
 
 static void draw_square(drawing *dr, game_drawstate *ds,
-			game_params *params, struct map *map,
+			const game_params *params, struct map *map,
 			int x, int y, unsigned long v)
 {
     int w = params->w, h = params->h, wh = w*h;
@@ -2831,9 +2834,10 @@
     draw_update(dr, COORD(x), COORD(y), TILESIZE, TILESIZE);
 }
 
-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->p.w, h = state->p.h, wh = w*h, n = state->p.n;
     int x, y, i;
@@ -3001,14 +3005,14 @@
     }
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated) {
@@ -3025,17 +3029,17 @@
 	return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -3049,7 +3053,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->p.w, h = state->p.h, wh = w*h, n = state->p.n;
     int ink, c[FOUR], i;
--- a/mines.c
+++ b/mines.c
@@ -136,7 +136,7 @@
     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 */
@@ -173,7 +173,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[400];
     int len;
@@ -193,7 +193,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -231,7 +231,7 @@
     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);
 
@@ -245,7 +245,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     /*
      * Lower limit on grid size: each dimension must be at least 3.
@@ -1994,7 +1994,7 @@
     }
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int wh = params->w * params->h;
     int x, y;
@@ -2167,7 +2167,8 @@
     return 0;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int i, wh, x, y, masked;
@@ -2272,7 +2273,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -2302,8 +2303,8 @@
     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)
 {
     if (!state->layout->mines) {
 	*error = "Game has not been started yet";
@@ -2313,12 +2314,12 @@
     return dupstr("S");
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     char *ret;
     int x, y;
@@ -2354,7 +2355,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->hx = ui->hy = -1;
@@ -2371,7 +2372,7 @@
     sfree(ui);
 }
 
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
 {
     char buf[80];
     /*
@@ -2384,7 +2385,7 @@
     return dupstr(buf);
 }
 
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
 {
     int p= 0;
     sscanf(encoding, "D%d%n", &ui->deaths, &p);
@@ -2392,8 +2393,8 @@
 	ui->completed = TRUE;
 }
 
-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)
 {
     if (newstate->won)
 	ui->completed = TRUE;
@@ -2415,8 +2416,9 @@
     int cur_x, cur_y; /* -1, -1 for no cursor displayed. */
 };
 
-static char *interpret_move(game_state *from, game_ui *ui, const game_drawstate *ds,
-			    int x, int y, int button)
+static char *interpret_move(const game_state *from, game_ui *ui,
+                            const game_drawstate *ds,
+                            int x, int y, int button)
 {
     int cx, cy;
     char buf[256];
@@ -2590,7 +2592,7 @@
     }
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int cy, cx;
     game_state *ret;
@@ -2691,8 +2693,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -2703,7 +2705,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -2795,7 +2797,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -2953,9 +2955,10 @@
     draw_update(dr, x, y, TILE_SIZE, TILE_SIZE);
 }
 
-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 x, y;
     int mines, markers, bg;
@@ -3082,14 +3085,14 @@
     }
 }
 
-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->used_solve || newstate->used_solve)
         return 0.0F;
@@ -3107,7 +3110,7 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     /*
      * We report the game as lost only if the player has used the
@@ -3117,7 +3120,7 @@
     return state->won ? (state->used_solve ? -1 : +1) : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     if (state->dead || state->won || ui->completed || !state->layout->mines)
 	return FALSE;
@@ -3124,11 +3127,11 @@
     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)
 {
 }
 
--- a/net.c
+++ b/net.c
@@ -205,7 +205,7 @@
     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 */
@@ -242,7 +242,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[400];
     int len;
@@ -260,7 +260,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -303,7 +303,7 @@
     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);
 
@@ -316,7 +316,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->width <= 0 || params->height <= 0)
 	return "Width and height must both be greater than zero";
@@ -1545,7 +1545,7 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->width, h = params->height;
     int i;
@@ -1575,7 +1575,8 @@
  * Construct an initial game state, given a description and parameters.
  */
 
-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)
 {
     game_state *state;
     int w, h, x, y;
@@ -1661,7 +1662,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret;
 
@@ -1689,8 +1690,8 @@
     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)
 {
     unsigned char *tiles;
     char *ret;
@@ -1784,12 +1785,12 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -1805,7 +1806,7 @@
  * completed - just call this function and see whether every square
  * is marked active.
  */
-static unsigned char *compute_active(game_state *state, int cx, int cy)
+static unsigned char *compute_active(const game_state *state, int cx, int cy)
 {
     unsigned char *active;
     tree234 *todo;
@@ -1866,7 +1867,7 @@
 #endif
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     void *seed;
     int seedsize;
@@ -1888,7 +1889,7 @@
     sfree(ui);
 }
 
-static char *encode_ui(game_ui *ui)
+static char *encode_ui(const game_ui *ui)
 {
     char buf[120];
     /*
@@ -1899,14 +1900,14 @@
     return dupstr(buf);
 }
 
-static void decode_ui(game_ui *ui, char *encoding)
+static void decode_ui(game_ui *ui, const char *encoding)
 {
     sscanf(encoding, "O%d,%d;C%d,%d",
 	   &ui->org_x, &ui->org_y, &ui->cx, &ui->cy);
 }
 
-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)
 {
 }
 
@@ -1921,8 +1922,9 @@
 /* ----------------------------------------------------------------------
  * Process a move.
  */
-static char *interpret_move(game_state *state, game_ui *ui,
-			    const 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)
 {
     char *nullret;
     int tx = -1, ty = -1, dir = 0;
@@ -2194,7 +2196,7 @@
     }
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     game_state *ret;
     int tx = -1, ty = -1, n, noanim, orig;
@@ -2285,7 +2287,7 @@
  * Routines for drawing the game position on the screen.
  */
 
-static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
+static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
 {
     game_drawstate *ds = snew(game_drawstate);
 
@@ -2306,8 +2308,8 @@
     sfree(ds);
 }
 
-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)
 {
     *x = WINDOW_OFFSET * 2 + tilesize * params->width + TILE_BORDER;
     *y = WINDOW_OFFSET * 2 + tilesize * params->height + TILE_BORDER;
@@ -2314,7 +2316,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -2447,7 +2449,7 @@
 /*
  * draw_tile() is passed physical coordinates
  */
-static void draw_tile(drawing *dr, game_state *state, game_drawstate *ds,
+static void draw_tile(drawing *dr, const game_state *state, game_drawstate *ds,
                       int x, int y, int tile, int src, float angle, int cursor)
 {
     int bx = WINDOW_OFFSET + TILE_SIZE * x;
@@ -2663,8 +2665,10 @@
     draw_update(dr, bx, by, TILE_SIZE+TILE_BORDER, TILE_SIZE+TILE_BORDER);
 }
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                 game_state *state, int dir, game_ui *ui, float t, float ft)
+static void game_redraw(drawing *dr, game_drawstate *ds,
+                        const game_state *oldstate, const game_state *state,
+                        int dir, const game_ui *ui,
+                        float t, float ft)
 {
     int x, y, tx, ty, frame, last_rotate_dir, moved_origin = FALSE;
     unsigned char *active;
@@ -2828,8 +2832,8 @@
     sfree(active);
 }
 
-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)
 {
     int last_rotate_dir;
 
@@ -2844,8 +2848,8 @@
     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 the game has just been completed, we display a completion
@@ -2864,17 +2868,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2932,7 +2936,7 @@
     }
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->width, h = state->height;
     int ink = print_mono_colour(dr, 0);
--- a/netslide.c
+++ b/netslide.c
@@ -197,7 +197,7 @@
     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 */
@@ -232,7 +232,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[400];
     int len;
@@ -252,7 +252,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -296,7 +296,7 @@
     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);
 
@@ -309,7 +309,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->width <= 1 || params->height <= 1)
 	return "Width and height must both be greater than one";
@@ -696,7 +696,7 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->width, h = params->height;
     int i;
@@ -726,7 +726,8 @@
  * Construct an initial game state, given a description and parameters.
  */
 
-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)
 {
     game_state *state;
     int w, h, x, y;
@@ -852,7 +853,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret;
 
@@ -884,8 +885,8 @@
     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)
 {
     if (!aux) {
 	*error = "Solution not known for this puzzle";
@@ -895,12 +896,12 @@
     return dupstr(aux);
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -919,7 +920,7 @@
  * squares in the moving_row and moving_col are always inactive - this
  * is so that "current" doesn't appear to jump across moving lines.
  */
-static unsigned char *compute_active(game_state *state,
+static unsigned char *compute_active(const game_state *state,
                                      int moving_row, int moving_col)
 {
     unsigned char *active;
@@ -976,7 +977,7 @@
     int cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cur_x = 0;
@@ -991,12 +992,12 @@
     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)
 {
 }
 
@@ -1042,8 +1043,8 @@
     slide_col_int(state->width, state->height, state->tiles, dir, col);
 }
 
-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)
 {
 }
 
@@ -1055,8 +1056,9 @@
     int cur_x, cur_y;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui,
-			    const 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 cx, cy;
     int dx, dy;
@@ -1127,7 +1129,7 @@
     return dupstr(buf);
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     game_state *ret;
     int c, d, col;
@@ -1202,7 +1204,7 @@
  * Routines for drawing the game position on the screen.
  */
 
-static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
+static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
 {
     game_drawstate *ds = snew(game_drawstate);
 
@@ -1223,8 +1225,8 @@
     sfree(ds);
 }
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1235,7 +1237,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1374,7 +1376,7 @@
     }
 }
 
-static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
+static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
                       int x, int y, int tile, float xshift, float yshift)
 {
     int bx = BORDER + WINDOW_OFFSET + TILE_SIZE * x + (int)(xshift * TILE_SIZE);
@@ -1513,7 +1515,7 @@
 }
 
 static void draw_tile_barriers(drawing *dr, game_drawstate *ds,
-                               game_state *state, int x, int y)
+                               const game_state *state, int x, int y)
 {
     int phase;
     int dir;
@@ -1580,8 +1582,10 @@
                 TILE_SIZE, TILE_SIZE);
 }
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                 game_state *state, int dir, game_ui *ui, float t, float ft)
+static void game_redraw(drawing *dr, game_drawstate *ds,
+                        const game_state *oldstate, const game_state *state,
+                        int dir, const game_ui *ui,
+                        float t, float ft)
 {
     int x, y, frame;
     unsigned char *active;
@@ -1669,7 +1673,7 @@
      * backwards.
      */
     if (oldstate && oldstate->move_count > state->move_count) {
-        game_state * tmpstate = state;
+        const game_state * tmpstate = state;
         state = oldstate;
         oldstate = tmpstate;
         t = ANIM_TIME - t;
@@ -1795,14 +1799,14 @@
     sfree(active);
 }
 
-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 ANIM_TIME;
 }
 
-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 the game has just been completed, we display a completion
@@ -1826,21 +1830,21 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     return FALSE;
 }
 
-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)
 {
 }
 
--- a/nullgame.c
+++ b/nullgame.c
@@ -52,7 +52,7 @@
     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 */
@@ -63,22 +63,22 @@
 {
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     return dupstr("FIXME");
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     return NULL;
 }
 
-static game_params *custom_params(config_item *cfg)
+static game_params *custom_params(const config_item *cfg)
 {
     return NULL;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     return NULL;
 }
@@ -89,12 +89,13 @@
     return dupstr("FIXME");
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
 
@@ -103,7 +104,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -117,23 +118,23 @@
     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)
 {
     return NULL;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     return NULL;
 }
@@ -142,17 +143,17 @@
 {
 }
 
-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)
 {
 }
 
@@ -161,13 +162,14 @@
     int FIXME;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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)
 {
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     return NULL;
 }
@@ -176,14 +178,14 @@
  * 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)
 {
     *x = *y = 10 * tilesize;	       /* FIXME */
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -198,7 +200,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -213,9 +215,10 @@
     sfree(ds);
 }
 
-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)
 {
     /*
      * The initial contents of the window are not guaranteed and
@@ -227,33 +230,33 @@
     draw_update(dr, 0, 0, 10*ds->tilesize, 10*ds->tilesize);
 }
 
-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)
 {
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/pattern.c
+++ b/pattern.c
@@ -97,7 +97,7 @@
     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 */
@@ -119,7 +119,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[400];
     int len;
@@ -131,7 +131,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -158,7 +158,7 @@
     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);
 
@@ -168,7 +168,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w <= 0 || params->h <= 0)
 	return "Width and height must both be greater than zero";
@@ -468,7 +468,8 @@
     return done_any;
 }
 
-static int solve_puzzle(game_state *state, unsigned char *grid, int w, int h,
+static int solve_puzzle(const game_state *state, unsigned char *grid,
+                        int w, int h,
 			unsigned char *matrix, unsigned char *workspace,
 			unsigned int *changed_h, unsigned int *changed_w,
 			int *rowdata
@@ -749,10 +750,10 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int i, n, rowspace;
-    char *p;
+    const char *p;
 
     for (i = 0; i < params->w + params->h; i++) {
         if (i < params->w)
@@ -791,10 +792,11 @@
     return NULL;
 }
 
-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 i;
-    char *p;
+    const char *p;
     game_state *state = snew(game_state);
 
     state->w = params->w;
@@ -826,7 +828,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -858,8 +860,8 @@
     sfree(state);
 }
 
-static char *solve_game(game_state *state, game_state *currstate,
-			char *ai, char **error)
+static char *solve_game(const game_state *state, const game_state *currstate,
+                        const char *ai, char **error)
 {
     unsigned char *matrix;
     int w = state->w, h = state->h;
@@ -910,12 +912,12 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -930,7 +932,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ret;
 
@@ -946,17 +948,17 @@
     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)
 {
 }
 
@@ -968,8 +970,9 @@
     int cur_x, cur_y;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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)
 {
     button &= ~MOD_MASK;
 
@@ -1102,7 +1105,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     game_state *ret;
     int x1, x2, y1, y2, xx, yy;
@@ -1279,7 +1282,7 @@
 #undef ROWDATA
 }
 
-static int check_errors(game_state *state, int i)
+static int check_errors(const game_state *state, int i)
 {
     int start, step, end, j;
     int val, runlen;
@@ -1336,8 +1339,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1348,7 +1351,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1378,7 +1381,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -1434,8 +1437,8 @@
 /*
  * Draw the numbers for a single row or column.
  */
-static void draw_numbers(drawing *dr, game_drawstate *ds, game_state *state,
-			 int i, int erase, int colour)
+static void draw_numbers(drawing *dr, game_drawstate *ds,
+                         const game_state *state, int i, int erase, int colour)
 {
     int rowlen = state->rowlen[i];
     int *rowdata = state->rowdata + state->rowsize * i;
@@ -1494,8 +1497,9 @@
     }
 }
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                        game_state *state, int dir, game_ui *ui,
+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 i, j;
@@ -1594,14 +1598,14 @@
     }
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -1609,17 +1613,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -1631,7 +1635,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->w, h = state->h;
     int ink = print_mono_colour(dr, 0);
--- a/pearl.c
+++ b/pearl.c
@@ -180,7 +180,7 @@
     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 */
@@ -214,7 +214,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[256];
     sprintf(buf, "%dx%d", params->w, params->h);
@@ -225,7 +225,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[64];
@@ -262,7 +262,7 @@
     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);
 
@@ -274,7 +274,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 5) return "Width must be at least five";
     if (params->h < 5) return "Height must be at least five";
@@ -1393,7 +1393,7 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int i, sizesofar;
     const int totalsize = params->w * params->h;
@@ -1416,7 +1416,8 @@
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int i, j, sz = params->w*params->h;
@@ -1452,7 +1453,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
     int sz = state->shared->sz, i;
@@ -1674,8 +1675,8 @@
     return move;
 }
 
-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)
 {
     game_state *solved = dup_game(state);
     int i, ret, sz = state->shared->sz;
@@ -1719,12 +1720,12 @@
     return move;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return FALSE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -1739,7 +1740,7 @@
     int cursor_active;     /* TRUE iff cursor is shown */
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     int sz = state->shared->sz;
@@ -1758,17 +1759,17 @@
     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)
 {
 }
 
@@ -1818,7 +1819,8 @@
     char *draglines;            /* size w*h; lines flipped by current drag */
 };
 
-static void update_ui_drag(game_state *state, game_ui *ui, int gx, int gy)
+static void update_ui_drag(const game_state *state, game_ui *ui,
+                           int gx, int gy)
 {
     int /* sz = state->shared->sz, */ w = state->shared->w;
     int i, ox, oy, pos;
@@ -1902,9 +1904,10 @@
  *         to state newstate, each of which equals either 0 or dir]
  *     }
  */
-static void interpret_ui_drag(game_state *state, game_ui *ui, int *clearing,
-                              int i, int *sx, int *sy, int *dx, int *dy,
-                              int *dir, int *oldstate, int *newstate)
+static void interpret_ui_drag(const game_state *state, const game_ui *ui,
+                              int *clearing, int i, int *sx, int *sy,
+                              int *dx, int *dy, int *dir,
+                              int *oldstate, int *newstate)
 {
     int w = state->shared->w;
     int sp = ui->dragcoords[i], dp = ui->dragcoords[i+1];
@@ -1933,7 +1936,7 @@
     }
 }
 
-static char *mark_in_direction(game_state *state, int x, int y, int dir,
+static char *mark_in_direction(const game_state *state, int x, int y, int dir,
 			       int ismark, char *buf)
 {
     int w = state->shared->w /*, h = state->shared->h, sz = state->shared->sz */;
@@ -1960,8 +1963,9 @@
     (btn) == CURSOR_DOWN ? D : (btn) == CURSOR_UP ? U :\
     (btn) == CURSOR_LEFT ? L : R)
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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->shared->w, h = state->shared->h /*, sz = state->shared->sz */;
     int gx = FROMCOORD(x), gy = FROMCOORD(y), i;
@@ -2102,7 +2106,7 @@
     return NULL;
 }
 
-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->shared->w, h = state->shared->h;
     char c;
@@ -2177,8 +2181,8 @@
 
 #define FLASH_TIME 0.5F
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int halfsz; } ads, *ds = &ads;
@@ -2189,7 +2193,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->halfsz = (tilesize-1)/2;
 }
@@ -2228,7 +2232,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -2287,7 +2291,7 @@
     }
 }
 
-static void draw_square(drawing *dr, game_drawstate *ds, game_ui *ui,
+static void draw_square(drawing *dr, game_drawstate *ds, const game_ui *ui,
                         int x, int y, unsigned int lflags, char clue)
 {
     int ox = COORD(x), oy = COORD(y);
@@ -2364,9 +2368,10 @@
     draw_update(dr, ox, oy, TILE_SIZE, TILE_SIZE);
 }
 
-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->shared->w, h = state->shared->h, sz = state->shared->sz;
     int x, y, force = 0, flashing = 0;
@@ -2439,14 +2444,14 @@
     }
 }
 
-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 && newstate->completed &&
         !oldstate->used_solve && !newstate->used_solve)
@@ -2455,17 +2460,17 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2477,7 +2482,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->shared->w, h = state->shared->h, x, y;
     int black = print_mono_colour(dr, 0);
--- a/pegs.c
+++ b/pegs.c
@@ -102,7 +102,7 @@
     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 */
@@ -129,7 +129,7 @@
 	    params->type = i;
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char str[80];
 
@@ -141,7 +141,7 @@
     return dupstr(str);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret = snewn(4, config_item);
     char buf[80];
@@ -171,7 +171,7 @@
     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);
 
@@ -182,7 +182,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (full && (params->w <= 3 || params->h <= 3))
 	return "Width and height must both be greater than three";
@@ -660,7 +660,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int len = params->w * params->h;
 
@@ -672,7 +672,8 @@
     return NULL;
 }
 
-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;
     game_state *state = snew(game_state);
@@ -689,7 +690,7 @@
     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;
     game_state *ret = snew(game_state);
@@ -709,18 +710,18 @@
     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)
 {
     return NULL;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w = state->w, h = state->h;
     int x, y;
@@ -746,7 +747,7 @@
     int cur_x, cur_y, cur_visible, cur_jumping;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     int x, y, v;
@@ -776,17 +777,17 @@
     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)
 {
     /*
      * Cancel a drag, in case the source square has become
@@ -814,8 +815,9 @@
     int bgcolour;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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;
     char buf[80];
@@ -942,7 +944,7 @@
     return NULL;
 }
 
-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;
     int sx, sy, tx, ty;
@@ -997,8 +999,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1009,7 +1011,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 
@@ -1037,7 +1039,7 @@
     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;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1100,9 +1102,10 @@
     draw_update(dr, x, y, TILESIZE, TILESIZE);
 }
 
-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;
     int x, y;
@@ -1255,14 +1258,14 @@
     ds->bgcolour = bgcolour;
 }
 
-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 && newstate->completed)
         return 2 * FLASH_FRAME;
@@ -1270,7 +1273,7 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     /*
      * Dead-end situations are assumed to be rescuable by Undo, so we
@@ -1279,16 +1282,16 @@
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/puzzles.h
+++ b/puzzles.h
@@ -404,13 +404,13 @@
 /*
  * random.c
  */
-random_state *random_new(char *seed, int len);
+random_state *random_new(const char *seed, int len);
 random_state *random_copy(random_state *tocopy);
 unsigned long random_bits(random_state *state, int bits);
 unsigned long random_upto(random_state *state, unsigned long limit);
 void random_free(random_state *state);
 char *random_state_encode(random_state *state);
-random_state *random_state_decode(char *input);
+random_state *random_state_decode(const char *input);
 /* random.c also exports SHA, which occasionally comes in useful. */
 #if __STDC_VERSION__ >= 199901L
 #include <stdint.h>
@@ -427,9 +427,9 @@
     uint32 lenhi, lenlo;
 } SHA_State;
 void SHA_Init(SHA_State *s);
-void SHA_Bytes(SHA_State *s, void *p, int len);
+void SHA_Bytes(SHA_State *s, const void *p, int len);
 void SHA_Final(SHA_State *s, unsigned char *output);
-void SHA_Simple(void *p, int len, unsigned char *output);
+void SHA_Simple(const void *p, int len, unsigned char *output);
 
 /*
  * printing.c
@@ -480,55 +480,57 @@
     game_params *(*default_params)(void);
     int (*fetch_preset)(int i, char **name, game_params **params);
     void (*decode_params)(game_params *, char const *string);
-    char *(*encode_params)(game_params *, int full);
+    char *(*encode_params)(const game_params *, int full);
     void (*free_params)(game_params *params);
-    game_params *(*dup_params)(game_params *params);
+    game_params *(*dup_params)(const game_params *params);
     int can_configure;
-    config_item *(*configure)(game_params *params);
-    game_params *(*custom_params)(config_item *cfg);
-    char *(*validate_params)(game_params *params, int full);
+    config_item *(*configure)(const game_params *params);
+    game_params *(*custom_params)(const config_item *cfg);
+    char *(*validate_params)(const game_params *params, int full);
     char *(*new_desc)(const game_params *params, random_state *rs,
 		      char **aux, int interactive);
-    char *(*validate_desc)(const game_params *params, char *desc);
-    game_state *(*new_game)(midend *me, game_params *params, char *desc);
-    game_state *(*dup_game)(game_state *state);
+    char *(*validate_desc)(const game_params *params, const char *desc);
+    game_state *(*new_game)(midend *me, const game_params *params,
+                            const char *desc);
+    game_state *(*dup_game)(const game_state *state);
     void (*free_game)(game_state *state);
     int can_solve;
-    char *(*solve)(game_state *orig, game_state *curr,
-                   char *aux, char **error);
+    char *(*solve)(const game_state *orig, const game_state *curr,
+                   const char *aux, char **error);
     int can_format_as_text_ever;
-    int (*can_format_as_text_now)(game_params *params);
-    char *(*text_format)(game_state *state);
-    game_ui *(*new_ui)(game_state *state);
+    int (*can_format_as_text_now)(const game_params *params);
+    char *(*text_format)(const game_state *state);
+    game_ui *(*new_ui)(const game_state *state);
     void (*free_ui)(game_ui *ui);
-    char *(*encode_ui)(game_ui *ui);
-    void (*decode_ui)(game_ui *ui, char *encoding);
-    void (*changed_state)(game_ui *ui, game_state *oldstate,
-                          game_state *newstate);
-    char *(*interpret_move)(game_state *state, game_ui *ui,
+    char *(*encode_ui)(const game_ui *ui);
+    void (*decode_ui)(game_ui *ui, const char *encoding);
+    void (*changed_state)(game_ui *ui, const game_state *oldstate,
+                          const game_state *newstate);
+    char *(*interpret_move)(const game_state *state, game_ui *ui,
                             const game_drawstate *ds, int x, int y, int button);
-    game_state *(*execute_move)(game_state *state, char *move);
+    game_state *(*execute_move)(const game_state *state, const char *move);
     int preferred_tilesize;
-    void (*compute_size)(game_params *params, int tilesize, int *x, int *y);
+    void (*compute_size)(const game_params *params, int tilesize,
+                         int *x, int *y);
     void (*set_size)(drawing *dr, game_drawstate *ds,
-		     game_params *params, int tilesize);
+		     const game_params *params, int tilesize);
     float *(*colours)(frontend *fe, int *ncolours);
-    game_drawstate *(*new_drawstate)(drawing *dr, game_state *state);
+    game_drawstate *(*new_drawstate)(drawing *dr, const game_state *state);
     void (*free_drawstate)(drawing *dr, game_drawstate *ds);
-    void (*redraw)(drawing *dr, game_drawstate *ds, game_state *oldstate,
-		   game_state *newstate, int dir, game_ui *ui, float anim_time,
-		   float flash_time);
-    float (*anim_length)(game_state *oldstate, game_state *newstate, int dir,
-			 game_ui *ui);
-    float (*flash_length)(game_state *oldstate, game_state *newstate, int dir,
-			  game_ui *ui);
-    int (*status)(game_state *state);
+    void (*redraw)(drawing *dr, game_drawstate *ds, const game_state *oldstate,
+		   const game_state *newstate, int dir, const game_ui *ui,
+                   float anim_time, float flash_time);
+    float (*anim_length)(const game_state *oldstate,
+                         const game_state *newstate, int dir, game_ui *ui);
+    float (*flash_length)(const game_state *oldstate,
+                          const game_state *newstate, int dir, game_ui *ui);
+    int (*status)(const game_state *state);
     int can_print, can_print_in_colour;
-    void (*print_size)(game_params *params, float *x, float *y);
-    void (*print)(drawing *dr, game_state *state, int tilesize);
+    void (*print_size)(const game_params *params, float *x, float *y);
+    void (*print)(drawing *dr, const game_state *state, int tilesize);
     int wants_statusbar;
     int is_timed;
-    int (*timing_state)(game_state *state, game_ui *ui);
+    int (*timing_state)(const game_state *state, game_ui *ui);
     int flags;
 };
 
--- a/random.c
+++ b/random.c
@@ -107,7 +107,7 @@
     s->lenhi = s->lenlo = 0;
 }
 
-void SHA_Bytes(SHA_State * s, void *p, int len)
+void SHA_Bytes(SHA_State * s, const void *p, int len)
 {
     unsigned char *q = (unsigned char *) p;
     uint32 wordblock[16];
@@ -188,7 +188,7 @@
     }
 }
 
-void SHA_Simple(void *p, int len, unsigned char *output)
+void SHA_Simple(const void *p, int len, unsigned char *output)
 {
     SHA_State s;
 
@@ -207,7 +207,7 @@
     int pos;
 };
 
-random_state *random_new(char *seed, int len)
+random_state *random_new(const char *seed, int len)
 {
     random_state *state;
 
@@ -304,7 +304,7 @@
     return dupstr(retbuf);
 }
 
-random_state *random_state_decode(char *input)
+random_state *random_state_decode(const char *input)
 {
     random_state *state;
     int pos, byte, digits;
--- a/range.c
+++ b/range.c
@@ -99,7 +99,7 @@
     return ret;
 }
 
-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 */
@@ -138,7 +138,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char str[80];
     sprintf(str, "%dx%d", params->w, params->h);
@@ -145,7 +145,7 @@
     return dupstr(str);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
 
@@ -169,7 +169,7 @@
     return ret;
 }
 
-static game_params *custom_params(config_item *configuration)
+static game_params *custom_params(const config_item *configuration)
 {
     game_params *ret = snew(game_params);
     ret->w = atoi(configuration[0].sval);
@@ -182,7 +182,7 @@
     memcpy(dst, src, n * sizeof (type)); \
 } while (0)
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
     int const n = state->params.w * state->params.h;
@@ -292,10 +292,10 @@
     DIFF_RECURSION
 };
 
-static move *solve_internal(game_state *state, move *base, int diff);
+static move *solve_internal(const game_state *state, move *base, int diff);
 
-static char *solve_game(game_state *orig, game_state *curpos,
-                        char *aux, char **error)
+static char *solve_game(const game_state *orig, const game_state *curpos,
+                        const char *aux, char **error)
 {
     int const n = orig->params.w * orig->params.h;
     move *const base = snewn(n, move);
@@ -319,7 +319,7 @@
     return ret;
 }
 
-static square *find_clues(game_state *state, int *ret_nclues);
+static square *find_clues(const game_state *state, int *ret_nclues);
 static move *do_solve(game_state *state,
                       int nclues,
                       const square *clues,
@@ -327,7 +327,7 @@
                       int difficulty);
 
 /* new_game_desc entry point in the solver subsystem */
-static move *solve_internal(game_state *state, move *base, int diff)
+static move *solve_internal(const game_state *state, move *base, int diff)
 {
     int nclues;
     square *const clues = find_clues(state, &nclues);
@@ -371,7 +371,7 @@
 
 static int runlength(puzzle_size r, puzzle_size c,
                      puzzle_size dr, puzzle_size dc,
-                     game_state *state, int colourmask)
+                     const game_state *state, int colourmask)
 {
     int const w = state->params.w, h = state->params.h;
     int sz = 0;
@@ -615,7 +615,7 @@
     return buf;
 }
 
-static square *find_clues(game_state *state, int *ret_nclues)
+static square *find_clues(const game_state *state, int *ret_nclues)
 {
     int r, c, i, nclues = 0;
     square *ret = snewn(state->params.w * state->params.h, struct square);
@@ -893,7 +893,7 @@
     return k;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     int const w = params->w, h = params->h;
     if (w < 1) return "Error: width is less than 1";
@@ -1060,7 +1060,7 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int const n = params->w * params->h;
     int squares = 0;
@@ -1092,10 +1092,11 @@
     return NULL;
 }
 
-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 i;
-    char *p;
+    const char *p;
 
     int const n = params->w * params->h;
     game_state *state = snew(game_state);
@@ -1134,12 +1135,12 @@
  * User interface: ascii
  */
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int cellsize, r, c, i, w_string, h_string, n_string;
     char *ret, *buf, *gridline;
@@ -1208,7 +1209,7 @@
     unsigned int cursor_show: 1;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     struct game_ui *ui = snew(game_ui);
     ui->r = ui->c = 0;
@@ -1221,12 +1222,12 @@
     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)
 {
 }
 
@@ -1248,7 +1249,8 @@
 #define COORD(x) ((x) * TILESIZE + BORDER)
 #define FROMCOORD(x) (((x) - BORDER) / TILESIZE)
 
-static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds,
+static char *interpret_move(const game_state *state, game_ui *ui,
+                            const game_drawstate *ds,
                             int x, int y, int button)
 {
     enum {none, forwards, backwards, hint};
@@ -1359,7 +1361,7 @@
     return NULL;
 }
 
-static int find_errors(game_state *state, int *report)
+static int find_errors(const game_state *state, int *report)
 {
     int const w = state->params.w, h = state->params.h, n = w * h;
 
@@ -1430,7 +1432,7 @@
     return TRUE;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     signed int r, c, value, nchars, ntok;
     signed char what_to_do;
@@ -1468,13 +1470,13 @@
     return NULL;
 }
 
-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)
 {
 }
 
-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;
 }
@@ -1481,8 +1483,8 @@
 
 #define FLASH_TIME 0.7F
 
-static float game_flash_length(game_state *from, game_state *to,
-                               int dir, game_ui *ui)
+static float game_flash_length(const game_state *from,
+                               const game_state *to, int dir, game_ui *ui)
 {
     if (!from->was_solved && to->was_solved && !to->has_cheated)
         return FLASH_TIME;
@@ -1489,7 +1491,7 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->was_solved ? +1 : 0;
 }
@@ -1513,7 +1515,7 @@
     NCOLOURS
 };
 
-static void game_compute_size(game_params *params, int tilesize,
+static void game_compute_size(const game_params *params, int tilesize,
                               int *x, int *y)
 {
     *x = (1 + params->w) * tilesize;
@@ -1521,7 +1523,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-                          game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1551,7 +1553,7 @@
     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 const w = state->params.w, h = state->params.h, n = w * h;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1587,8 +1589,9 @@
 static void draw_cell(drawing *dr, game_drawstate *ds, int r, int c,
                       drawcell cell);
 
-static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-                        game_state *state, int dir, game_ui *ui,
+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 const w = state->params.w, h = state->params.h, n = w * h;
@@ -1663,7 +1666,7 @@
     draw_update(draw, x, y, ts, ts);
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     puts("warning: game_timing_state was called (this shouldn't happen)");
     return FALSE; /* the (non-existing) timer should not be running */
@@ -1673,7 +1676,7 @@
  * User interface: print
  */
 
-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)
 {
     int print_width, print_height;
     game_compute_size(params, 800, &print_width, &print_height);
@@ -1681,7 +1684,7 @@
     *y = print_height / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int const w = state->params.w, h = state->params.h;
     game_drawstate ds_obj, *ds = &ds_obj;
--- a/rect.c
+++ b/rect.c
@@ -129,7 +129,7 @@
     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 */
@@ -157,7 +157,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -170,7 +170,7 @@
     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];
@@ -208,7 +208,7 @@
     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);
 
@@ -220,7 +220,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w <= 0 || params->h <= 0)
 	return "Width and height must both be greater than zero";
@@ -1778,7 +1778,7 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int area = params->w * params->h;
     int squares = 0;
@@ -1899,7 +1899,8 @@
     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)
 {
     game_state *state = snew(game_state);
     int x, y, i, area;
@@ -1944,7 +1945,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -1977,8 +1978,8 @@
     sfree(state);
 }
 
-static char *solve_game(game_state *state, game_state *currstate,
-			char *ai, char **error)
+static char *solve_game(const game_state *state, const game_state *currstate,
+                        const char *ai, char **error)
 {
     unsigned char *vedge, *hedge;
     int x, y, len;
@@ -2046,12 +2047,12 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     char *ret, *p, buf[80];
     int i, x, y, col, maxlen;
@@ -2186,7 +2187,7 @@
     int cur_x, cur_y, cur_visible, cur_dragging;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->drag_start_x = -1;
@@ -2207,12 +2208,12 @@
     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)
 {
 }
 
@@ -2303,7 +2304,7 @@
 /*
  * Returns TRUE if it has made any change to the grid.
  */
-static int grid_draw_rect(game_state *state,
+static int grid_draw_rect(const game_state *state,
 			  unsigned char *hedge, unsigned char *vedge,
 			  int c, int really, int outline,
 			  int x1, int y1, int x2, int y2)
@@ -2348,7 +2349,7 @@
     return changed;
 }
 
-static int ui_draw_rect(game_state *state, game_ui *ui,
+static int ui_draw_rect(const game_state *state, const game_ui *ui,
 			unsigned char *hedge, unsigned char *vedge, int c,
 			int really, int outline)
 {
@@ -2356,8 +2357,8 @@
 			  ui->x1, ui->y1, ui->x2, ui->y2);
 }
 
-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)
 {
 }
 
@@ -2367,8 +2368,9 @@
     unsigned long *visible;
 };
 
-static char *interpret_move(game_state *from, game_ui *ui, const game_drawstate *ds,
-			    int x, int y, int button)
+static char *interpret_move(const game_state *from, game_ui *ui,
+                            const game_drawstate *ds,
+                            int x, int y, int button)
 {
     int xc, yc;
     int startdrag = FALSE, enddrag = FALSE, active = FALSE, erasing = FALSE;
@@ -2533,13 +2535,13 @@
 	return NULL;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     game_state *ret;
     int x1, y1, x2, y2, mode;
 
     if (move[0] == 'S') {
-	char *p = move+1;
+	const char *p = move+1;
 	int x, y;
 
 	ret = dup_game(from);
@@ -2620,8 +2622,8 @@
 #define COLOUR(k) ( (k)==1 ? COL_LINE : (k)==2 ? COL_DRAG : COL_DRAGERASE )
 #define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) )
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -2632,7 +2634,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -2675,7 +2677,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -2697,7 +2699,7 @@
     sfree(ds);
 }
 
-static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
+static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
                       int x, int y, unsigned char *hedge, unsigned char *vedge,
                       unsigned char *corners, unsigned long bgflags)
 {
@@ -2754,9 +2756,10 @@
     draw_update(dr, cx, cy, TILE_SIZE+1, TILE_SIZE+1);
 }
 
-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 x, y;
     unsigned char *hedge, *vedge, *corners;
@@ -2867,14 +2870,14 @@
     sfree(corners);
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -2882,17 +2885,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2904,7 +2907,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->w, h = state->h;
     int ink = print_mono_colour(dr, 0);
--- a/samegame.c
+++ b/samegame.c
@@ -121,7 +121,7 @@
     TILE(gs,x2,y2) = t;                   \
 } while (0)
 
-static int npoints(game_params *params, int nsel)
+static int npoints(const game_params *params, int nsel)
 {
     int sdiff = nsel - params->scoresub;
     return (sdiff > 0) ? sdiff * sdiff : 0;
@@ -181,7 +181,7 @@
     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 */
@@ -221,7 +221,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[80];
 
@@ -231,7 +231,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -274,7 +274,7 @@
     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);
 
@@ -287,7 +287,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 1 || params->h < 1)
 	return "Width and height must both be positive";
@@ -948,13 +948,13 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int area = params->w * params->h, i;
-    char *p = desc;
+    const char *p = desc;
 
     for (i = 0; i < area; i++) {
-	char *q = p;
+	const char *q = p;
 	int n;
 
 	if (!isdigit((unsigned char)*p))
@@ -975,10 +975,11 @@
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
-    char *p = desc;
+    const char *p = desc;
     int i;
 
     state->params = *params; /* struct copy */
@@ -998,7 +999,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -1016,18 +1017,18 @@
     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)
 {
     return NULL;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     char *ret, *p;
     int x, y, maxlen;
@@ -1057,7 +1058,7 @@
     int xsel, ysel, displaysel;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1077,16 +1078,16 @@
     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 sel_clear(game_ui *ui, game_state *state)
+static void sel_clear(game_ui *ui, const game_state *state)
 {
     int i;
 
@@ -1096,8 +1097,8 @@
 }
 
 
-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)
 {
     sel_clear(ui, newstate);
 
@@ -1110,7 +1111,7 @@
 	ui->displaysel = 0;
 }
 
-static char *sel_movedesc(game_ui *ui, game_state *state)
+static char *sel_movedesc(game_ui *ui, const game_state *state)
 {
     int i;
     char *ret, *sep, buf[80];
@@ -1143,7 +1144,7 @@
     return sresize(ret, retlen, char);
 }
 
-static void sel_expand(game_ui *ui, game_state *state, int tx, int ty)
+static void sel_expand(game_ui *ui, const game_state *state, int tx, int ty)
 {
     int ns = 1, nadded, x, y, c;
 
@@ -1267,8 +1268,9 @@
     int *tiles; /* contains colour and SELECTED. */
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 tx, ty;
     char *ret = "";
@@ -1309,7 +1311,7 @@
     return ret;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int i, n;
     game_state *ret;
@@ -1348,14 +1350,14 @@
  */
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilegap = 2;
     ds->tileinner = tilesize - ds->tilegap;
 }
 
-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)
 {
     /* Ick: fake up tile size variables for macro expansion purposes */
     game_drawstate ads, *ds = &ads;
@@ -1427,7 +1429,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1497,9 +1499,10 @@
     draw_update(dr, COORD(x), COORD(y), TILE_SIZE, TILE_SIZE);
 }
 
-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 bgcolour, x, y;
 
@@ -1595,14 +1598,14 @@
     }
 }
 
-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->complete && newstate->complete) ||
         (!oldstate->impossible && newstate->impossible))
@@ -1611,7 +1614,7 @@
 	return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     /*
      * Dead-end situations are assumed to be rescuable by Undo, so we
@@ -1620,16 +1623,16 @@
     return state->complete ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/signpost.c
+++ b/signpost.c
@@ -92,7 +92,8 @@
     return whichdir(fromi%w, fromi/w, toi%w, toi/w);
 }
 
-static int ispointing(game_state *state, int fromx, int fromy, int tox, int toy)
+static int ispointing(const game_state *state, int fromx, int fromy,
+                      int tox, int toy)
 {
     int w = state->w, dir = state->dirs[fromy*w+fromx];
 
@@ -119,7 +120,7 @@
 /* Taking the number 'num', work out the gap between it and the next
  * available number up or down (depending on d). Return 1 if the region
  * at (x,y) will fit in that gap, or 0 otherwise. */
-static int move_couldfit(game_state *state, int num, int d, int x, int y)
+static int move_couldfit(const game_state *state, int num, int d, int x, int y)
 {
     int n, gap, i = y*state->w+x, sz;
 
@@ -144,7 +145,7 @@
     return (sz > gap) ? 0 : 1;
 }
 
-static int isvalidmove(game_state *state, int clever,
+static int isvalidmove(const game_state *state, int clever,
                        int fromx, int fromy, int tox, int toy)
 {
     int w = state->w, from = fromy*w+fromx, to = toy*w+tox;
@@ -196,13 +197,13 @@
     state->prev[to] = from;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     if (params->w * params->h >= 100) return 0;
     return 1;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int len = state->h * 2 * (4*state->w + 1) + state->h + 2;
     int x, y, i, num, n, set;
@@ -339,7 +340,7 @@
     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 */
@@ -363,7 +364,7 @@
 
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -376,7 +377,7 @@
     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];
@@ -408,7 +409,7 @@
     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);
 
@@ -419,7 +420,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+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";
@@ -463,7 +464,7 @@
     return state;
 }
 
-static void dup_game_to(game_state *to, game_state *from)
+static void dup_game_to(game_state *to, const game_state *from)
 {
     to->completed = from->completed;
     to->used_solve = from->used_solve;
@@ -480,7 +481,7 @@
     memcpy(to->numsi, from->numsi, (to->n+1)*sizeof(int));
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = blank_game(state->w, state->h);
     dup_game_to(ret, state);
@@ -499,7 +500,7 @@
     sfree(state);
 }
 
-static void unpick_desc(const game_params *params, char *desc,
+static void unpick_desc(const game_params *params, const char *desc,
                         game_state **sout, char **mout)
 {
     game_state *state = blank_game(params->w, params->h);
@@ -840,7 +841,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     char *ret = NULL;
 
@@ -1202,7 +1203,8 @@
     if (error) return 0;
     return complete;
 }
-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)
 {
     game_state *state = NULL;
 
@@ -1332,8 +1334,8 @@
     return ret;
 }
 
-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)
 {
     game_state *tosolve;
     char *ret = NULL;
@@ -1371,7 +1373,7 @@
     int dx, dy;         /* pixel coords of drag posn */
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1391,17 +1393,17 @@
     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)
 {
     if (!oldstate->completed && newstate->completed)
         ui->cshow = ui->dragging = 0;
@@ -1418,8 +1420,9 @@
     blitter *dragb;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds,
-			    int mx, int my, int button)
+static char *interpret_move(const game_state *state, game_ui *ui,
+                            const game_drawstate *ds,
+                            int mx, int my, int button)
 {
     int x = FROMCOORD(mx), y = FROMCOORD(my), w = state->w;
     char buf[80];
@@ -1539,7 +1542,7 @@
     }
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     game_state *ret = NULL;
     int sx, sy, ex, ey, si, ei, w = state->w;
@@ -1615,8 +1618,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize, order; } ads, *ds = &ads;
@@ -1627,7 +1630,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
     assert(TILE_SIZE > 0);
@@ -1706,7 +1709,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1963,7 +1966,8 @@
 }
 
 static void draw_drag_indicator(drawing *dr, game_drawstate *ds,
-                                game_state *state, game_ui *ui, int validdrag)
+                                const game_state *state, const game_ui *ui,
+                                int validdrag)
 {
     int dir, w = ds->w, acol = COL_ARROW;
     int fx = FROMCOORD(ui->dx), fy = FROMCOORD(ui->dy);
@@ -2007,9 +2011,10 @@
     draw_arrow(dr, ui->dx, ui->dy, ARROW_HALFSZ, ang, acol, acol);
 }
 
-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 x, y, i, w = ds->w, dirp, force = 0;
     unsigned int f;
@@ -2139,14 +2144,14 @@
     if (!ds->started) ds->started = TRUE;
 }
 
-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 &&
         newstate->completed && !newstate->used_solve)
@@ -2155,17 +2160,17 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2174,7 +2179,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int ink = print_mono_colour(dr, 0);
     int x, y;
--- a/singles.c
+++ b/singles.c
@@ -170,7 +170,7 @@
     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 */
@@ -200,7 +200,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -212,7 +212,7 @@
     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];
@@ -244,7 +244,7 @@
     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);
 
@@ -255,7 +255,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 2 || params->h < 2)
 	return "Width and neight must be at least two";
@@ -292,7 +292,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = blank_game(state->w, state->h);
 
@@ -333,7 +333,7 @@
     return -1;
 }
 
-static void unpick_desc(const game_params *params, char *desc,
+static void unpick_desc(const game_params *params, const char *desc,
                         game_state **sout, char **mout)
 {
     game_state *state = blank_game(params->w, params->h);
@@ -378,12 +378,12 @@
 
 /* --- Useful game functions (completion, etc.) --- */
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int len, x, y, i;
     char *ret, *p;
@@ -552,7 +552,8 @@
     return (error > 0) ? 0 : 1;
 }
 
-static char *game_state_diff(game_state *src, game_state *dst, int issolve)
+static char *game_state_diff(const game_state *src, const game_state *dst,
+                             int issolve)
 {
     char *ret = NULL, buf[80], c;
     int retlen = 0, x, y, i, k;
@@ -1171,8 +1172,8 @@
     return state->impossible ? -1 : check_complete(state, CC_MUST_FILL);
 }
 
-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)
 {
     game_state *solved = dup_game(currstate);
     char *move = NULL;
@@ -1401,7 +1402,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     char *ret = NULL;
 
@@ -1409,7 +1410,8 @@
     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)
 {
     game_state *state = NULL;
 
@@ -1425,7 +1427,7 @@
     int show_black_nums;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1440,17 +1442,17 @@
     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)
 {
     if (!oldstate->completed && newstate->completed)
         ui->cshow = 0;
@@ -1471,8 +1473,9 @@
     unsigned int *flags;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds,
-			    int mx, int my, int button)
+static char *interpret_move(const game_state *state, game_ui *ui,
+                            const game_drawstate *ds,
+                            int mx, int my, int button)
 {
     char buf[80], c;
     int i, x = FROMCOORD(mx), y = FROMCOORD(my);
@@ -1522,7 +1525,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     game_state *ret = dup_game(state);
     int x, y, i, n;
@@ -1567,8 +1570,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1579,7 +1582,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1608,7 +1611,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -1673,9 +1676,10 @@
     draw_update(dr, x, y, TILE_SIZE, TILE_SIZE);
 }
 
-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 x, y, i, flash;
     unsigned int f;
@@ -1720,14 +1724,14 @@
     ds->started = 1;
 }
 
-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 &&
         newstate->completed && !newstate->used_solve)
@@ -1735,17 +1739,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -1755,7 +1759,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int ink = print_mono_colour(dr, 0);
     int paper = print_mono_colour(dr, 1);
--- a/sixteen.c
+++ b/sixteen.c
@@ -88,7 +88,7 @@
     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 */
@@ -114,7 +114,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -127,7 +127,7 @@
     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];
@@ -160,7 +160,7 @@
     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);
 
@@ -171,7 +171,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+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";
@@ -398,9 +398,10 @@
 }
 
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
-    char *p, *err;
+    const char *p;
+    char *err;
     int i, area;
     int *used;
 
@@ -413,7 +414,7 @@
 	used[i] = FALSE;
 
     for (i = 0; i < area; i++) {
-	char *q = p;
+	const char *q = p;
 	int n;
 
 	if (*p < '0' || *p > '9') {
@@ -449,11 +450,12 @@
     return err;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int i;
-    char *p;
+    const char *p;
 
     state->w = params->w;
     state->h = params->h;
@@ -479,7 +481,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -503,18 +505,18 @@
     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)
 {
     return dupstr("S");
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     char *ret, *p, buf[80];
     int x, y, col, maxlen;
@@ -558,7 +560,7 @@
     int cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cur_x = 0;
@@ -573,17 +575,17 @@
   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)
 {
 }
 
@@ -595,8 +597,9 @@
     int cur_x, cur_y;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 cx = -1, cy = -1, dx, dy;
     char buf[80];
@@ -657,7 +660,7 @@
     return dupstr(buf);
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int cx, cy, dx, dy;
     int tx, ty, n;
@@ -725,8 +728,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -737,7 +740,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -756,7 +759,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -781,7 +784,7 @@
 }
 
 static void draw_tile(drawing *dr, game_drawstate *ds,
-                      game_state *state, int x, int y,
+                      const game_state *state, int x, int y,
                       int tile, int flash_colour)
 {
     if (tile == 0) {
@@ -856,9 +859,10 @@
                 TILE_SIZE, TILE_SIZE);
 }
 
-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 i, bgcolour;
     int cur_x = -1, cur_y = -1;
@@ -1057,14 +1061,14 @@
     }
 }
 
-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 ANIM_TIME;
 }
 
-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 && newstate->completed &&
 	!oldstate->used_solve && !newstate->used_solve)
@@ -1073,21 +1077,21 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/slant.c
+++ b/slant.c
@@ -137,7 +137,7 @@
     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 */
@@ -163,7 +163,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -174,7 +174,7 @@
     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];
@@ -206,7 +206,7 @@
     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);
 
@@ -217,7 +217,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     /*
      * (At least at the time of writing this comment) The grid
@@ -1216,7 +1216,7 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->w, h = params->h, W = w+1, H = h+1;
     int area = W*H;
@@ -1241,7 +1241,8 @@
     return NULL;
 }
 
-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, W = w+1, H = h+1;
     game_state *state = snew(game_state);
@@ -1276,7 +1277,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
     game_state *ret = snew(game_state);
@@ -1484,8 +1485,8 @@
     return TRUE;
 }
 
-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 w = state->p.w, h = state->p.h;
     signed char *soln;
@@ -1549,12 +1550,12 @@
     return move;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w = state->p.w, h = state->p.h, W = w+1, H = h+1;
     int x, y, len;
@@ -1600,7 +1601,7 @@
     int cur_x, cur_y, cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->cur_x = ui->cur_y = ui->cur_visible = 0;
@@ -1612,17 +1613,17 @@
     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)
 {
 }
 
@@ -1666,8 +1667,9 @@
     long *todraw;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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->p.w, h = state->p.h;
     int v;
@@ -1742,7 +1744,7 @@
     return NULL;
 }
 
-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->p.w, h = state->p.h;
     char c;
@@ -1789,8 +1791,8 @@
  * 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, *ds = &dummy;
@@ -1801,7 +1803,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1841,7 +1843,7 @@
     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->p.w, h = state->p.h;
     int i;
@@ -1974,9 +1976,10 @@
     draw_update(dr, COORD(x), COORD(y), TILESIZE, TILESIZE);
 }
 
-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->p.w, h = state->p.h, W = w+1, H = h+1;
     int x, y;
@@ -2063,14 +2066,14 @@
     }
 }
 
-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 && newstate->completed &&
 	!oldstate->used_solve && !newstate->used_solve)
@@ -2079,17 +2082,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2101,7 +2104,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->p.w, h = state->p.h, W = w+1;
     int ink = print_mono_colour(dr, 0);
--- a/solo.c
+++ b/solo.c
@@ -289,7 +289,7 @@
     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 */
@@ -399,7 +399,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char str[80];
 
@@ -435,7 +435,7 @@
     return dupstr(str);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -489,7 +489,7 @@
     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);
 
@@ -508,7 +508,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->c < 2)
 	return "Both dimensions must be at least 2";
@@ -3789,7 +3789,7 @@
     return desc;
 }
 
-static char *spec_to_grid(char *desc, digit *grid, int area)
+static const char *spec_to_grid(const char *desc, digit *grid, int area)
 {
     int i = 0;
     while (*desc && *desc != ',') {
@@ -3819,9 +3819,9 @@
  * end of the block spec, and return an error string or NULL if everything
  * is OK. The DSF is stored in *PDSF.
  */
-static char *spec_to_dsf(char **pdesc, int **pdsf, int cr, int area)
+static char *spec_to_dsf(const char **pdesc, int **pdsf, int cr, int area)
 {
-    char *desc = *pdesc;
+    const char *desc = *pdesc;
     int pos = 0;
     int *dsf;
 
@@ -3883,9 +3883,9 @@
     return NULL;
 }
 
-static char *validate_grid_desc(char **pdesc, int range, int area)
+static char *validate_grid_desc(const char **pdesc, int range, int area)
 {
-    char *desc = *pdesc;
+    const char *desc = *pdesc;
     int squares = 0;
     while (*desc && *desc != ',') {
         int n = *desc++;
@@ -3913,7 +3913,7 @@
     return NULL;
 }
 
-static char *validate_block_desc(char **pdesc, int cr, int area,
+static char *validate_block_desc(const char **pdesc, int cr, int area,
 				 int min_nr_blocks, int max_nr_blocks,
 				 int min_nr_squares, int max_nr_squares)
 {
@@ -3990,7 +3990,7 @@
     return NULL;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int cr = params->c * params->r, area = cr*cr;
     char *err;
@@ -4034,7 +4034,8 @@
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int c = params->c, r = params->r, cr = c*r, area = cr * cr;
@@ -4136,7 +4137,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
     int cr = state->cr, area = cr * cr;
@@ -4186,8 +4187,8 @@
     sfree(state);
 }
 
-static char *solve_game(game_state *state, game_state *currstate,
-			char *ai, char **error)
+static char *solve_game(const game_state *state, const game_state *currstate,
+                        const char *ai, char **error)
 {
     int cr = state->cr;
     char *ret;
@@ -4414,7 +4415,7 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     /*
      * Formatting Killer puzzles as text is currently unsupported. I
@@ -4427,7 +4428,7 @@
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     assert(!state->kblocks);
     return grid_text_format(state->cr, state->blocks, state->xtype,
@@ -4461,7 +4462,7 @@
     int hcursor;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -4476,17 +4477,17 @@
     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)
 {
     int cr = newstate->cr;
     /*
@@ -4512,8 +4513,9 @@
     int nregions, *entered_items;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 cr = state->cr;
     int tx, ty;
@@ -4611,7 +4613,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int cr = from->cr;
     game_state *ret;
@@ -4618,7 +4620,7 @@
     int x, y, n;
 
     if (move[0] == 'S') {
-	char *p;
+	const char *p;
 
 	ret = dup_game(from);
 	ret->completed = ret->cheated = TRUE;
@@ -4670,8 +4672,8 @@
 #define SIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
 #define GETTILESIZE(cr, w) ( (double)(w-1) / (double)(cr+1) )
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -4682,7 +4684,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -4729,7 +4731,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int cr = state->cr;
@@ -4765,8 +4767,8 @@
     sfree(ds);
 }
 
-static void draw_number(drawing *dr, game_drawstate *ds, game_state *state,
-			int x, int y, int hl)
+static void draw_number(drawing *dr, game_drawstate *ds,
+                        const game_state *state, int x, int y, int hl)
 {
     int cr = state->cr;
     int tx, ty, tw, th;
@@ -5048,9 +5050,10 @@
     ds->hl[y*cr+x] = hl;
 }
 
-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 cr = state->cr;
     int x, y;
@@ -5180,14 +5183,14 @@
     }
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -5195,12 +5198,12 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     if (state->completed)
 	return FALSE;
@@ -5207,7 +5210,7 @@
     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)
 {
     int pw, ph;
 
@@ -5234,7 +5237,7 @@
  * the interior of the affected squares.
  */
 static void outline_block_structure(drawing *dr, game_drawstate *ds,
-				    game_state *state,
+				    const game_state *state,
 				    struct block_structure *blocks,
 				    int ink, int inset)
 {
@@ -5390,7 +5393,7 @@
     sfree(coords);
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int cr = state->cr;
     int ink = print_mono_colour(dr, 0);
--- a/tents.c
+++ b/tents.c
@@ -324,7 +324,7 @@
     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 */
@@ -350,7 +350,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[120];
 
@@ -361,7 +361,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -393,7 +393,7 @@
     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);
 
@@ -404,7 +404,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     /*
      * Generating anything under 4x4 runs into trouble of one kind
@@ -1190,7 +1190,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->w, h = params->h;
     int area, i;
@@ -1229,7 +1229,8 @@
     return NULL;
 }
 
-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;
     game_state *state = snew(game_state);
@@ -1288,7 +1289,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->p.w, h = state->p.h;
     game_state *ret = snew(game_state);
@@ -1314,8 +1315,8 @@
     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 w = state->p.w, h = state->p.h;
 
@@ -1364,12 +1365,12 @@
     }
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w = state->p.w, h = state->p.h;
     char *ret, *p;
@@ -1413,7 +1414,7 @@
     int cx, cy, cdisp;                 /* cursor position, and ?display. */
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->dsx = ui->dsy = -1;
@@ -1429,17 +1430,17 @@
     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)
 {
 }
 
@@ -1460,7 +1461,7 @@
 
 #define FLASH_TIME 0.30F
 
-static int drag_xform(game_ui *ui, int x, int y, int v)
+static int drag_xform(const game_ui *ui, int x, int y, int v)
 {
     int xmin, ymin, xmax, ymax;
 
@@ -1522,8 +1523,9 @@
     return v;
 }
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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->p.w, h = state->p.h;
     char tmpbuf[80];
@@ -1658,7 +1660,7 @@
     return NULL;
 }
 
-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->p.w, h = state->p.h;
     char c;
@@ -1846,8 +1848,8 @@
  * 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, *ds = &dummy;
@@ -1858,7 +1860,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1905,7 +1907,7 @@
     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->p.w, h = state->p.h;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1944,7 +1946,7 @@
     ERR_OVERCOMMITTED
 };
 
-static int *find_errors(game_state *state, char *grid)
+static int *find_errors(const game_state *state, char *grid)
 {
     int w = state->p.w, h = state->p.h;
     int *ret = snewn(w*h + w + h, int);
@@ -2365,8 +2367,9 @@
 /*
  * Internal redraw function, used for printing as well as drawing.
  */
-static void int_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate,
-		       game_state *state, int dir, game_ui *ui,
+static void int_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 printing)
 {
     int w = state->p.w, h = state->p.h;
@@ -2501,21 +2504,22 @@
     sfree(errors);
 }
 
-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_redraw(dr, ds, oldstate, state, dir, ui, animtime, flashtime, FALSE);
 }
 
-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 && newstate->completed &&
 	!oldstate->used_solve && !newstate->used_solve)
@@ -2524,17 +2528,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -2546,7 +2550,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int c;
 
--- a/towers.c
+++ b/towers.c
@@ -167,7 +167,7 @@
     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 */
@@ -195,7 +195,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[80];
 
@@ -206,7 +206,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -232,7 +232,7 @@
     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);
 
@@ -242,7 +242,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 3 || params->w > 9)
         return "Grid size must be between 3 and 9";
@@ -803,7 +803,7 @@
  * Gameplay.
  */
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->w, a = w*w;
     const char *p = desc;
@@ -868,7 +868,8 @@
     return NULL;
 }
 
-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, a = w*w;
     game_state *state = snew(game_state);
@@ -931,7 +932,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->par.w, a = w*w;
     game_state *ret = snew(game_state);
@@ -964,8 +965,8 @@
     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 w = state->par.w, a = w*w;
     int i, ret;
@@ -998,12 +999,12 @@
     return out;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w = state->par.w /* , a = w*w */;
     char *ret;
@@ -1102,7 +1103,7 @@
     int hcursor;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1117,17 +1118,17 @@
     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)
 {
     int w = newstate->par.w;
     /*
@@ -1171,7 +1172,7 @@
     int *errtmp;
 };
 
-static int check_errors(game_state *state, int *errors)
+static int check_errors(const game_state *state, int *errors)
 {
     int w = state->par.w /*, a = w*w */;
     int W = w+2, A = W*W;	       /* the errors array is (w+2) square */
@@ -1255,8 +1256,9 @@
     return errs;
 }
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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->par.w;
     int tx, ty;
@@ -1383,7 +1385,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int w = from->par.w, a = w*w;
     game_state *ret;
@@ -1448,8 +1450,8 @@
 
 #define SIZE(w) ((w) * TILESIZE + 2*BORDER)
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1459,7 +1461,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1494,7 +1496,7 @@
     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->par.w /*, a = w*w */;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1689,9 +1691,10 @@
     }
 }
 
-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->par.w /*, a = w*w */;
     int i, x, y;
@@ -1793,14 +1796,14 @@
     }
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -1808,12 +1811,12 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     if (state->completed)
 	return FALSE;
@@ -1820,7 +1823,7 @@
     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)
 {
     int pw, ph;
 
@@ -1832,7 +1835,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->par.w;
     int ink = print_mono_colour(dr, 0);
--- a/twiddle.c
+++ b/twiddle.c
@@ -70,7 +70,7 @@
     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 */
@@ -133,7 +133,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[256];
     sprintf(buf, "%dx%dn%d%s%s", params->w, params->h, params->n,
@@ -146,7 +146,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -195,7 +195,7 @@
     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);
 
@@ -209,7 +209,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->n < 2)
 	return "Rotating block size must be at least two";
@@ -430,9 +430,9 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
-    char *p;
+    const char *p;
     int w = params->w, h = params->h, wh = w*h;
     int i;
 
@@ -459,12 +459,13 @@
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
     int w = params->w, h = params->h, n = params->n, wh = w*h;
     int i;
-    char *p;
+    const char *p;
 
     state->w = w;
     state->h = h;
@@ -499,7 +500,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -539,18 +540,18 @@
 	return 0;
 }
 
-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)
 {
     return dupstr("S");
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     char *ret, *p, buf[80];
     int i, x, y, col, o, maxlen;
@@ -602,7 +603,7 @@
     int cur_visible;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -618,17 +619,17 @@
     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)
 {
 }
 
@@ -640,8 +641,9 @@
     int cur_x, cur_y;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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, n = state->n /* , wh = w*h */;
     char buf[80];
@@ -731,7 +733,7 @@
     return dupstr(buf);
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     game_state *ret;
     int w = from->w, h = from->h, n = from->n, wh = w*h;
@@ -782,8 +784,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -794,7 +796,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -822,7 +824,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -872,7 +874,7 @@
 #define CUR_BOTTOM      4
 #define CUR_LEFT        8
 
-static void draw_tile(drawing *dr, game_drawstate *ds, game_state *state,
+static void draw_tile(drawing *dr, game_drawstate *ds, const game_state *state,
                       int x, int y, int tile, int flash_colour,
                       struct rotation *rot, unsigned cedges)
 {
@@ -1053,15 +1055,30 @@
     return colours[(int)((angle + 2*PI) / (PI/16)) & 31];
 }
 
-static float game_anim_length(game_state *oldstate, game_state *newstate,
-			      int dir, game_ui *ui)
+static float game_anim_length_real(const game_state *oldstate,
+                                   const game_state *newstate, int dir,
+                                   const game_ui *ui)
 {
+    /*
+     * Our game_anim_length doesn't need to modify its game_ui, so
+     * this is the real function which declares ui as const. We must
+     * wrap this for the backend structure with a version that has ui
+     * non-const, but we still need this version to call from within
+     * game_redraw which only has a const ui available.
+     */
     return (float)(ANIM_PER_BLKSIZE_UNIT * sqrt(newstate->n-1));
 }
 
-static float game_flash_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 game_anim_length_real(oldstate, newstate, dir, ui);
+
+}
+
+static float game_flash_length(const game_state *oldstate,
+                               const game_state *newstate, int dir, game_ui *ui)
+{
     if (!oldstate->completed && newstate->completed &&
 	!oldstate->used_solve && !newstate->used_solve)
         return 2 * FLASH_FRAME;
@@ -1069,14 +1086,15 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-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 i, bgcolour;
     struct rotation srot, *rot;
@@ -1133,7 +1151,7 @@
      */
     if (oldstate) {
 	float angle;
-	float anim_max = game_anim_length(oldstate, state, dir, ui);
+	float anim_max = game_anim_length_real(oldstate, state, dir, ui);
 
 	if (dir > 0) {
 	    lastx = state->lastx;
@@ -1243,16 +1261,16 @@
     }
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/undead.c
+++ b/undead.c
@@ -113,7 +113,8 @@
     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 */
     return ret;
@@ -142,7 +143,8 @@
     return;
 }
 
-static char *encode_params(game_params *params, int full) {
+static char *encode_params(const game_params *params, int full)
+{
     char buf[256];
     sprintf(buf, "%dx%d", params->w, params->h);
     if (full)
@@ -150,7 +152,8 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params) {
+static config_item *game_configure(const game_params *params)
+{
     config_item *ret;
     char buf[64];
 
@@ -181,7 +184,8 @@
     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);
 
     ret->w = atoi(cfg[0].sval);
@@ -190,7 +194,8 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full) {
+static char *validate_params(const game_params *params, int full)
+{
     if ((params->w * params->h ) > 54)  return "Grid is too big";
     if (params->w < 3)                  return "Width must be at least 3";
     if (params->h < 3)                  return "Height must be at least 3";
@@ -293,7 +298,8 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state) {
+static game_state *dup_game(const game_state *state)
+{
     game_state *ret = snew(game_state);
 
     ret->common = state->common;
@@ -1299,7 +1305,9 @@
     return;
 }
 
-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 i;
     int n;
     int count;
@@ -1419,7 +1427,8 @@
     return state;
 }
 
-static char *validate_desc(const game_params *params, char *desc) {
+static char *validate_desc(const game_params *params, const char *desc)
+{
     int i;
     int w = params->w, h = params->h;
     int wh = w*h;
@@ -1426,7 +1435,7 @@
     int area;
     int monsters;
     int monster_count;
-    char *desc_s = desc;
+    const char *desc_s = desc;
         
     for (i=0;i<3;i++) {
         if (!*desc) return "Faulty game description";
@@ -1470,7 +1479,9 @@
     return NULL;
 }
 
-static char *solve_game(game_state *state_start, game_state *currstate, char *aux, char **error) {
+static char *solve_game(const game_state *state_start, const game_state *currstate,
+                        const char *aux, char **error)
+{
     int p;
     int *old_guess;
     int iterative_depth;
@@ -1553,11 +1564,13 @@
     return move;
 }
 
-static int game_can_format_as_text_now(game_params *params) {
+static int game_can_format_as_text_now(const game_params *params)
+{
     return TRUE;
 }
 
-static char *game_text_format(game_state *state) {
+static char *game_text_format(const game_state *state)
+{
     int w,h,c,r,xi,g;
     char *ret;
     char buf[120];
@@ -1602,7 +1615,8 @@
     int ascii;
 };
 
-static game_ui *new_ui(game_state *state) {
+static game_ui *new_ui(const game_state *state)
+{
     game_ui *ui = snew(game_ui);
     ui->hx = ui->hy = 0;
     ui->hpencil = ui->hshow = ui->hcursor = 0;
@@ -1615,15 +1629,19 @@
     return;
 }
 
-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)
+{
     return;
 }
 
-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)
+{
     /* See solo.c; if we were pencil-mode highlighting and
      * somehow a square has just been properly filled, cancel
      * pencil mode. */
@@ -1653,8 +1671,9 @@
 #define TILESIZE (ds->tilesize)
 #define BORDER (TILESIZE/4)
 
-static char *interpret_move(game_state *state, game_ui *ui,
-                            const 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 gx,gy;
     int g,xi;
@@ -1921,7 +1940,8 @@
     return correct;
 }
 
-static game_state *execute_move(game_state *state, char *move) {
+static game_state *execute_move(const game_state *state, const char *move)
+{
     int x,n,p,i;
     char c;
     int correct; 
@@ -1979,8 +1999,9 @@
 
 #define PREFERRED_TILE_SIZE 64
 
-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)
+{
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
     ads.tilesize = tilesize;
@@ -1991,7 +2012,8 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-                          game_params *params, int tilesize) {
+                          const game_params *params, int tilesize)
+{
     ds->tilesize = tilesize;
     return;
 }
@@ -1998,7 +2020,8 @@
 
 #define COLOUR(ret, i, r, g, b)     ((ret[3*(i)+0] = (r)), (ret[3*(i)+1] = (g)), (ret[3*(i)+2] = (b)))
 
-static float *game_colours(frontend *fe, int *ncolours) {
+static float *game_colours(frontend *fe, int *ncolours)
+{
     float *ret = snewn(3 * NCOLOURS, float);
 
     frontend_default_colour(fe, &ret[COL_BACKGROUND * 3]);
@@ -2039,7 +2062,8 @@
     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 i;
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -2082,7 +2106,8 @@
 }
 
 static void draw_cell_background(drawing *dr, game_drawstate *ds,
-                                 game_state *state, game_ui *ui, int x, int y) {
+                                 const game_state *state, const game_ui *ui,
+                                 int x, int y) {
 
     int hon;
     int dx,dy;
@@ -2247,7 +2272,7 @@
 }
 
 static void draw_monster_count(drawing *dr, game_drawstate *ds,
-                               game_state *state, int c, int hflash) {
+                               const game_state *state, int c, int hflash) {
     int dx,dy,dh;
     char buf[8];
     char bufm[8];
@@ -2292,7 +2317,8 @@
     return;
 }
 
-static void draw_path_hint(drawing *dr, game_drawstate *ds, game_state *state,
+static void draw_path_hint(drawing *dr, game_drawstate *ds,
+                           const game_state *state,
                            int i, int hflash, int start) {
     int dx,dy,x,y;
     int p,error;
@@ -2312,8 +2338,9 @@
     return;
 }
 
-static void draw_mirror(drawing *dr, game_drawstate *ds, game_state *state,
-                        int x, int y, int hflash, int mirror) {
+static void draw_mirror(drawing *dr, game_drawstate *ds,
+                        const game_state *state, int x, int y,
+                        int hflash, int mirror) {
     int dx,dy,mx1,my1,mx2,my2;
     dx = BORDER+(x* ds->tilesize)+(TILESIZE/2);
     dy = BORDER+(y* ds->tilesize)+(TILESIZE/2)+TILESIZE;
@@ -2337,8 +2364,9 @@
     return;
 }
 
-static void draw_big_monster(drawing *dr, game_drawstate *ds, game_state *state,
-                             int x, int y, int hflash, int monster)
+static void draw_big_monster(drawing *dr, game_drawstate *ds,
+                             const game_state *state, int x, int y,
+                             int hflash, int monster)
 {
     int dx,dy;
     char buf[10];
@@ -2360,8 +2388,9 @@
     return;
 }
 
-static void draw_pencils(drawing *dr, game_drawstate *ds, game_state *state,
-                         int x, int y, int pencil) {
+static void draw_pencils(drawing *dr, game_drawstate *ds,
+                         const game_state *state, int x, int y, int pencil)
+{
     int dx, dy;
     int monsters[4];
     int i, j, px, py;
@@ -2402,9 +2431,11 @@
 
 #define FLASH_TIME 0.7F
 
-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 i,j,x,y,xy;
     int stale, xi, c, hflash, hchanged, changed_ascii;
 
@@ -2541,29 +2572,35 @@
     return;
 }
 
-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)
+{
     return (!oldstate->solved && newstate->solved && !oldstate->cheated &&
             !newstate->cheated) ? FLASH_TIME : 0.0F;
 }
 
-static int game_status(game_state *state) {
+static int game_status(const game_state *state)
+{
     return state->solved;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui) {
+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
--- a/unequal.c
+++ b/unequal.c
@@ -156,7 +156,7 @@
     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 */
@@ -190,7 +190,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[80];
 
@@ -203,7 +203,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -234,7 +234,7 @@
     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);
 
@@ -245,7 +245,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->order < 3 || params->order > 32)
         return "Order must be between 3 and 32";
@@ -288,7 +288,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = blank_game(state->order, state->adjacent);
     int o2 = state->order*state->order, o3 = o2*state->order;
@@ -446,12 +446,12 @@
     return -1;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int x, y, len, n;
     char *ret, *p;
@@ -829,7 +829,8 @@
     return 1;
 }
 
-static game_state *solver_hint(game_state *state, int *diff_r, int mindiff, int maxdiff)
+static game_state *solver_hint(const game_state *state, int *diff_r,
+                               int mindiff, int maxdiff)
 {
     game_state *ret = dup_game(state);
     int diff, r = 0;
@@ -1190,11 +1191,11 @@
     return ret;
 }
 
-static game_state *load_game(const game_params *params, char *desc,
+static game_state *load_game(const game_params *params, const char *desc,
                              char **why_r)
 {
     game_state *state = blank_game(params->order, params->adjacent);
-    char *p = desc;
+    const char *p = desc;
     int i = 0, n, o = params->order, x, y;
     char *why = NULL;
 
@@ -1276,7 +1277,8 @@
     return NULL;
 }
 
-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)
 {
     game_state *state = load_game(params, desc, NULL);
     if (!state) {
@@ -1286,7 +1288,7 @@
     return state;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     char *why = NULL;
     game_state *dummy = load_game(params, desc, &why);
@@ -1298,8 +1300,8 @@
     return why;
 }
 
-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)
 {
     game_state *solved;
     int r;
@@ -1327,7 +1329,7 @@
     int hshow, hpencil, hcursor;        /* show state, type, and ?cursor. */
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1342,17 +1344,17 @@
     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)
 {
     /* See solo.c; if we were pencil-mode highlighting and
      * somehow a square has just been properly filled, cancel
@@ -1373,8 +1375,9 @@
     int hflash;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const game_drawstate *ds,
-			    int ox, int oy, int button)
+static char *interpret_move(const game_state *state, game_ui *ui,
+                            const game_drawstate *ds,
+                            int ox, int oy, int button)
 {
     int x = FROMCOORD(ox), y = FROMCOORD(oy), n;
     char buf[80];
@@ -1458,7 +1461,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     game_state *ret = NULL;
     int x, y, n, i, rc;
@@ -1483,7 +1486,7 @@
         }
         return ret;
     } else if (move[0] == 'S') {
-        char *p;
+        const char *p;
 
         ret = dup_game(state);
         ret->completed = ret->cheated = TRUE;
@@ -1525,8 +1528,8 @@
 
 #define DRAW_SIZE (TILE_SIZE*ds->order + GAP_SIZE*(ds->order-1) + BORDER*2)
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize, order; } ads, *ds = &ads;
@@ -1537,7 +1540,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1571,7 +1574,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int o2 = state->order*state->order, o3 = o2*state->order;
@@ -1691,8 +1694,9 @@
     draw_update(dr, ox, oy+TILE_SIZE, TILE_SIZE, g);
 }
 
-static void draw_furniture(drawing *dr, game_drawstate *ds, game_state *state,
-                           game_ui *ui, int x, int y, int hflash)
+static void draw_furniture(drawing *dr, game_drawstate *ds,
+                           const game_state *state, const game_ui *ui,
+                           int x, int y, int hflash)
 {
     int ox = COORD(x), oy = COORD(y), bg, hon;
     unsigned int f = GRID(state, flags, x, y);
@@ -1782,9 +1786,10 @@
     }
 }
 
-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 x, y, i, hchanged = 0, stale, hflash = 0;
 
@@ -1852,14 +1857,14 @@
     ds->hflash = hflash;
 }
 
-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 && newstate->completed &&
         !oldstate->cheated && !newstate->cheated)
@@ -1867,17 +1872,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -1887,7 +1892,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int ink = print_mono_colour(dr, 0);
     int x, y, o = state->order, ox, oy, n;
--- a/unfinished/group.c
+++ b/unfinished/group.c
@@ -150,7 +150,7 @@
     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 */
@@ -188,7 +188,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char ret[80];
 
@@ -201,7 +201,7 @@
     return dupstr(ret);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -232,7 +232,7 @@
     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);
 
@@ -243,7 +243,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 3 || params->w > 26)
         return "Grid size must be between 3 and 26";
@@ -810,7 +810,7 @@
     return NULL;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->w, a = w*w;
     const char *p = desc;
@@ -818,7 +818,7 @@
     return validate_grid_desc(&p, w, a);
 }
 
-static char *spec_to_grid(char *desc, digit *grid, int area)
+static const char *spec_to_grid(const char *desc, digit *grid, int area)
 {
     int i = 0;
     while (*desc && *desc != ',') {
@@ -843,7 +843,8 @@
     return desc;
 }
 
-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, a = w*w;
     game_state *state = snew(game_state);
@@ -875,7 +876,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->par.w, a = w*w;
     game_state *ret = snew(game_state);
@@ -908,8 +909,8 @@
     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 w = state->par.w, a = w*w;
     int i, ret;
@@ -942,12 +943,12 @@
     return out;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w = state->par.w;
     int x, y;
@@ -1015,7 +1016,7 @@
     int edgepos;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
 
@@ -1031,17 +1032,17 @@
     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)
 {
     int w = newstate->par.w;
     /*
@@ -1093,7 +1094,7 @@
     digit *sequence;
 };
 
-static int check_errors(game_state *state, long *errors)
+static int check_errors(const game_state *state, long *errors)
 {
     int w = state->par.w, a = w*w;
     digit *grid = state->grid;
@@ -1213,8 +1214,9 @@
     return -1;
 }
 
-static char *interpret_move(game_state *state, game_ui *ui,
-                            const 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->par.w;
     int tx, ty;
@@ -1353,7 +1355,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *from, char *move)
+static game_state *execute_move(const game_state *from, const char *move)
 {
     int w = from->par.w, a = w*w;
     game_state *ret;
@@ -1451,8 +1453,8 @@
 
 #define SIZE(w) ((w) * TILESIZE + 2*BORDER + LEGEND)
 
-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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1462,7 +1464,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1497,7 +1499,7 @@
     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->par.w, a = w*w;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1703,9 +1705,10 @@
     draw_update(dr, cx, cy, cw, ch);
 }
 
-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->par.w /*, a = w*w */;
     int x, y, i, j;
@@ -1814,14 +1817,14 @@
     }
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -1829,12 +1832,12 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+static int game_timing_state(const game_state *state, game_ui *ui)
 {
     if (state->completed)
 	return FALSE;
@@ -1841,7 +1844,7 @@
     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)
 {
     int pw, ph;
 
@@ -1853,7 +1856,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w = state->par.w;
     int ink = print_mono_colour(dr, 0);
--- a/unfinished/separate.c
+++ b/unfinished/separate.c
@@ -130,7 +130,7 @@
     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 */
@@ -153,7 +153,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[256];
     sprintf(buf, "%dx%dn%d", params->w, params->h, params->k);
@@ -160,17 +160,17 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     return NULL;
 }
 
-static game_params *custom_params(config_item *cfg)
+static game_params *custom_params(const config_item *cfg)
 {
     return NULL;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     return NULL;
 }
@@ -646,12 +646,13 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     return NULL;
 }
 
-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)
 {
     game_state *state = snew(game_state);
 
@@ -660,7 +661,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     game_state *ret = snew(game_state);
 
@@ -674,23 +675,23 @@
     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)
 {
     return NULL;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     return NULL;
 }
@@ -699,17 +700,17 @@
 {
 }
 
-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)
 {
 }
 
@@ -718,13 +719,14 @@
     int FIXME;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui,
-                            const 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)
 {
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     return NULL;
 }
@@ -733,14 +735,14 @@
  * 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)
 {
     *x = *y = 10 * tilesize;	       /* FIXME */
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -755,7 +757,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -770,9 +772,10 @@
     sfree(ds);
 }
 
-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)
 {
     /*
      * The initial contents of the window are not guaranteed and
@@ -783,33 +786,33 @@
     draw_rect(dr, 0, 0, 10*ds->tilesize, 10*ds->tilesize, COL_BACKGROUND);
 }
 
-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)
 {
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/unfinished/slide.c
+++ b/unfinished/slide.c
@@ -195,7 +195,7 @@
     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 */
@@ -221,7 +221,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -234,7 +234,7 @@
     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];
@@ -267,7 +267,7 @@
     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);
 
@@ -278,7 +278,7 @@
     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);
@@ -891,7 +891,7 @@
     return ret;
 }
 
-static char *validate_desc(const 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;
@@ -1001,7 +1001,8 @@
     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;
@@ -1083,7 +1084,7 @@
     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);
@@ -1124,8 +1125,8 @@
     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;
@@ -1168,12 +1169,12 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return board_text_format(state->w, state->h, state->board,
 			     state->imm->forcefield);
@@ -1188,7 +1189,7 @@
     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);
@@ -1210,17 +1211,17 @@
     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)
 {
 }
 
@@ -1242,8 +1243,9 @@
     int started;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui,
-                            const 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;
@@ -1458,7 +1460,7 @@
     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;
@@ -1595,8 +1597,8 @@
  * 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, *ds = &dummy;
@@ -1607,7 +1609,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1667,7 +1669,7 @@
     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);
@@ -2115,9 +2117,10 @@
     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;
@@ -2277,14 +2280,14 @@
     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;
@@ -2292,21 +2295,21 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/unfinished/sokoban.c
+++ b/unfinished/sokoban.c
@@ -149,7 +149,7 @@
     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 */
@@ -191,7 +191,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char data[256];
 
@@ -200,7 +200,7 @@
     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];
@@ -227,7 +227,7 @@
     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);
 
@@ -237,7 +237,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->w < 4 || params->h < 4)
 	return "Width and height must both be at least 4";
@@ -806,7 +806,7 @@
     return desc;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w = params->w, h = params->h;
     int area = 0;
@@ -843,7 +843,8 @@
     return NULL;
 }
 
-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;
     game_state *state = snew(game_state);
@@ -880,7 +881,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w = state->p.w, h = state->p.h;
     game_state *ret = snew(game_state);
@@ -901,23 +902,23 @@
     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)
 {
     return NULL;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     return NULL;
 }
@@ -926,17 +927,17 @@
 {
 }
 
-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)
 {
 }
 
@@ -1041,8 +1042,9 @@
     }
 }
 
-static char *interpret_move(game_state *state, game_ui *ui,
-                            const 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 dx=0, dy=0;
     char *move;
@@ -1097,7 +1099,7 @@
     return move;
 }
 
-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->p.w, h = state->p.h;
     int px = state->px, py = state->py;
@@ -1183,8 +1185,8 @@
  * 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)
 {
     /* Ick: fake up `ds->tilesize' for macro expansion purposes */
     struct { int tilesize; } ads, *ds = &ads;
@@ -1195,7 +1197,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1252,7 +1254,7 @@
     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->p.w, h = state->p.h;
     struct game_drawstate *ds = snew(struct game_drawstate);
@@ -1335,9 +1337,10 @@
     draw_update(dr, tx, ty, TILESIZE, TILESIZE);
 }
 
-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->p.w, h = state->p.h /*, wh = w*h */;
     int x, y;
@@ -1400,14 +1403,14 @@
 
 }
 
-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 && newstate->completed)
         return FLASH_LENGTH;
@@ -1415,21 +1418,21 @@
         return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }
 
--- a/unruly.c
+++ b/unruly.c
@@ -168,7 +168,7 @@
     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 */
@@ -203,7 +203,7 @@
     }
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[80];
 
@@ -214,7 +214,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -246,7 +246,7 @@
     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);
 
@@ -257,7 +257,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if ((params->w2 & 1) || (params->h2 & 1))
         return "Width and height must both be even";
@@ -269,12 +269,12 @@
     return NULL;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int w2 = params->w2, h2 = params->h2;
     int s = w2 * h2;
 
-    char *p = desc;
+    const char *p = desc;
     int pos = 0;
 
     while (*p) {
@@ -316,7 +316,8 @@
     return state;
 }
 
-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 w2 = params->w2, h2 = params->h2;
     int s = w2 * h2;
@@ -323,7 +324,7 @@
 
     game_state *state = blank_state(w2, h2);
 
-    char *p = desc;
+    const char *p = desc;
     int pos = 0;
 
     while (*p) {
@@ -353,7 +354,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int w2 = state->w2, h2 = state->h2;
     int s = w2 * h2;
@@ -377,12 +378,12 @@
     sfree(state);
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     int w2 = state->w2, h2 = state->h2;
     int lr = w2*2 + 1;
@@ -418,7 +419,7 @@
     int *zeros_cols;
 };
 
-static void unruly_solver_update_remaining(game_state *state,
+static void unruly_solver_update_remaining(const game_state *state,
                                            struct unruly_scratch *scratch)
 {
     int w2 = state->w2, h2 = state->h2;
@@ -442,7 +443,7 @@
         }
 }
 
-static struct unruly_scratch *unruly_new_scratch(game_state *state)
+static struct unruly_scratch *unruly_new_scratch(const game_state *state)
 {
     int w2 = state->w2, h2 = state->h2;
 
@@ -817,7 +818,7 @@
     return ret;
 }
 
-static int unruly_validate_rows(game_state *state, int horizontal,
+static int unruly_validate_rows(const game_state *state, int horizontal,
                                 char check, int *errors)
 {
     int w2 = state->w2, h2 = state->h2;
@@ -857,7 +858,7 @@
     return ret;
 }
 
-static int unruly_validate_all_rows(game_state *state, int *errors)
+static int unruly_validate_all_rows(const game_state *state, int *errors)
 {
     int errcount = 0;
 
@@ -871,7 +872,7 @@
     return 0;
 }
 
-static int unruly_validate_counts(game_state *state,
+static int unruly_validate_counts(const game_state *state,
                                   struct unruly_scratch *scratch, int *errors)
 {
     int w2 = state->w2, h2 = state->h2;
@@ -982,8 +983,8 @@
     return maxdiff;
 }
 
-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)
 {
     game_state *solved = dup_game(state);
     struct unruly_scratch *scratch = unruly_new_scratch(solved);
@@ -1232,7 +1233,7 @@
     char cursor;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ret = snew(game_ui);
 
@@ -1247,17 +1248,17 @@
     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)
 {
 }
 
@@ -1272,7 +1273,7 @@
     int *grid;
 };
 
-static game_drawstate *game_new_drawstate(drawing *dr, game_state *state)
+static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
@@ -1306,9 +1307,9 @@
 #define COORD(x)     ( (x) * ds->tilesize + ds->tilesize/2 )
 #define FROMCOORD(x) ( ((x)-(ds->tilesize/2)) / ds->tilesize )
 
-static char *interpret_move(game_state *state, game_ui *ui,
-                            const game_drawstate *ds, int ox, int oy,
-                            int button)
+static char *interpret_move(const game_state *state, game_ui *ui,
+                            const game_drawstate *ds,
+                            int ox, int oy, int button)
 {
     int hx = ui->cx;
     int hy = ui->cy;
@@ -1378,7 +1379,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     int w2 = state->w2, h2 = state->h2;
     int s = w2 * h2;
@@ -1388,7 +1389,7 @@
     game_state *ret;
 
     if (move[0] == 'S') {
-        char *p;
+        const char *p;
 
         ret = dup_game(state);
         p = move + 1;
@@ -1434,7 +1435,7 @@
  * Drawing routines.
  */
 
-static void game_compute_size(game_params *params, int tilesize,
+static void game_compute_size(const game_params *params, int tilesize,
                               int *x, int *y)
 {
     *x = tilesize * (params->w2 + 1);
@@ -1442,7 +1443,7 @@
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-                          game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1566,8 +1567,9 @@
 #define FLASH_TIME (FLASH_FRAME * 3)
 
 static void game_redraw(drawing *dr, game_drawstate *ds,
-                        game_state *oldstate, game_state *state, int dir,
-                        game_ui *ui, float animtime, float flashtime)
+                        const game_state *oldstate, const game_state *state,
+                        int dir, const game_ui *ui,
+                        float animtime, float flashtime)
 {
     int w2 = state->w2, h2 = state->h2;
     int s = w2 * h2;
@@ -1632,15 +1634,14 @@
     }
 }
 
-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 && newstate->completed &&
         !oldstate->cheated && !newstate->cheated)
@@ -1648,17 +1649,17 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
     int pw, ph;
 
@@ -1668,7 +1669,7 @@
     *y = ph / 100.0F;
 }
 
-static void game_print(drawing *dr, game_state *state, int tilesize)
+static void game_print(drawing *dr, const game_state *state, int tilesize)
 {
     int w2 = state->w2, h2 = state->h2;
     int x, y;
--- a/untangle.c
+++ b/untangle.c
@@ -154,7 +154,7 @@
     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 */
@@ -166,7 +166,7 @@
     params->n = atoi(string);
 }
 
-static char *encode_params(game_params *params, int full)
+static char *encode_params(const game_params *params, int full)
 {
     char buf[80];
 
@@ -175,7 +175,7 @@
     return dupstr(buf);
 }
 
-static config_item *game_configure(game_params *params)
+static config_item *game_configure(const game_params *params)
 {
     config_item *ret;
     char buf[80];
@@ -196,7 +196,7 @@
     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);
 
@@ -205,7 +205,7 @@
     return ret;
 }
 
-static char *validate_params(game_params *params, int full)
+static char *validate_params(const game_params *params, int full)
 {
     if (params->n < 4)
         return "Number of points must be at least four";
@@ -734,7 +734,7 @@
     return ret;
 }
 
-static char *validate_desc(const game_params *params, char *desc)
+static char *validate_desc(const game_params *params, const char *desc)
 {
     int a, b;
 
@@ -803,7 +803,8 @@
 	state->completed = TRUE;
 }
 
-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 n = params->n;
     game_state *state = snew(game_state);
@@ -842,7 +843,7 @@
     return state;
 }
 
-static game_state *dup_game(game_state *state)
+static game_state *dup_game(const game_state *state)
 {
     int n = state->params.n;
     game_state *ret = snew(game_state);
@@ -879,8 +880,8 @@
     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 n = state->params.n;
     int matrix[4];
@@ -1025,12 +1026,12 @@
     return ret;
 }
 
-static int game_can_format_as_text_now(game_params *params)
+static int game_can_format_as_text_now(const game_params *params)
 {
     return TRUE;
 }
 
-static char *game_text_format(game_state *state)
+static char *game_text_format(const game_state *state)
 {
     return NULL;
 }
@@ -1043,7 +1044,7 @@
     float anim_length;
 };
 
-static game_ui *new_ui(game_state *state)
+static game_ui *new_ui(const game_state *state)
 {
     game_ui *ui = snew(game_ui);
     ui->dragpoint = -1;
@@ -1056,17 +1057,17 @@
     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)
 {
     ui->dragpoint = -1;
     ui->just_moved = ui->just_dragged;
@@ -1079,8 +1080,9 @@
     long *x, *y;
 };
 
-static char *interpret_move(game_state *state, game_ui *ui, const 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 n = state->params.n;
 
@@ -1152,7 +1154,7 @@
     return NULL;
 }
 
-static game_state *execute_move(game_state *state, char *move)
+static game_state *execute_move(const game_state *state, const char *move)
 {
     int n = state->params.n;
     int p, k;
@@ -1191,14 +1193,14 @@
  * 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)
 {
     *x = *y = COORDLIMIT(params->n) * tilesize;
 }
 
 static void game_set_size(drawing *dr, game_drawstate *ds,
-			  game_params *params, int tilesize)
+                          const game_params *params, int tilesize)
 {
     ds->tilesize = tilesize;
 }
@@ -1255,7 +1257,7 @@
     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)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
     int i;
@@ -1289,9 +1291,10 @@
     return ret;
 }
 
-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, h;
     edge *e;
@@ -1406,8 +1409,8 @@
     draw_update(dr, 0, 0, w, h);
 }
 
-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)
 {
     if (ui->just_moved)
 	return 0.0F;
@@ -1418,8 +1421,8 @@
     return ui->anim_length;
 }
 
-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 && newstate->completed &&
 	!oldstate->cheated && !newstate->cheated)
@@ -1427,21 +1430,21 @@
     return 0.0F;
 }
 
-static int game_status(game_state *state)
+static int game_status(const game_state *state)
 {
     return state->completed ? +1 : 0;
 }
 
-static int game_timing_state(game_state *state, game_ui *ui)
+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)
 {
 }