chiark / gitweb /
Refactored the game_size() interface, which was getting really
authorSimon Tatham <anakin@pobox.com>
Tue, 5 Jul 2005 18:13:31 +0000 (18:13 +0000)
committerSimon Tatham <anakin@pobox.com>
Tue, 5 Jul 2005 18:13:31 +0000 (18:13 +0000)
unpleasant and requiring lots of special cases to be taken care of
by every single game. The new interface exposes an integer `tile
size' or `scale' parameter to the midend and provides two much
simpler routines: one which computes the pixel window size given a
game_params and a tile size, and one which is given a tile size and
must set up a drawstate appropriately. All the rest of the
complexity is handled in the midend, mostly by binary search, so
grubby special cases only have to be dealt with once.

[originally from svn r6059]

17 files changed:
cube.c
fifteen.c
flip.c
guess.c
midend.c
mines.c
net.c
netslide.c
nullgame.c
pattern.c
pegs.c
puzzles.h
rect.c
samegame.c
sixteen.c
solo.c
twiddle.c

diff --git a/cube.c b/cube.c
index 6a867a47c8c387971a9967f2247a40689d73011a..768f53f69c28d5fe86a3e075f48e61eab3847973 100644 (file)
--- a/cube.c
+++ b/cube.c
@@ -157,7 +157,7 @@ enum {
 
 enum { LEFT, RIGHT, UP, DOWN, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT };
 
-#define PREFERRED_GRID_SCALE 48.0F
+#define PREFERRED_GRID_SCALE 48
 #define GRID_SCALE (ds->gridscale)
 #define ROLLTIME 0.13F
 
@@ -1452,31 +1452,28 @@ static struct bbox find_bbox(game_params *params)
     return bb;
 }
 
-#define XSIZE(bb, solid) \
-    ((int)(((bb).r - (bb).l + 2*(solid)->border) * GRID_SCALE))
-#define YSIZE(bb, solid) \
-    ((int)(((bb).d - (bb).u + 2*(solid)->border) * GRID_SCALE))
+#define XSIZE(gs, bb, solid) \
+    ((int)(((bb).r - (bb).l + 2*(solid)->border) * gs))
+#define YSIZE(gs, bb, solid) \
+    ((int)(((bb).d - (bb).u + 2*(solid)->border) * gs))
 
-static void game_size(game_params *params, game_drawstate *ds, int *x, int *y,
-                      int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
     struct bbox bb = find_bbox(params);
-    float gsx, gsy, gs;
 
-    gsx = *x / (bb.r - bb.l + 2*solids[params->solid]->border);
-    gsy = *y / (bb.d - bb.u + 2*solids[params->solid]->border);
-    gs = min(gsx, gsy);
-
-    if (expand)
-        ds->gridscale = gs;
-    else
-        ds->gridscale = min(gs, PREFERRED_GRID_SCALE);
+    *x = XSIZE(tilesize, bb, solids[params->solid]);
+    *y = YSIZE(tilesize, bb, solids[params->solid]);
+}
 
-    ds->ox = (int)(-(bb.l - solids[params->solid]->border) * GRID_SCALE);
-    ds->oy = (int)(-(bb.u - solids[params->solid]->border) * GRID_SCALE);
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    struct bbox bb = find_bbox(params);
 
-    *x = XSIZE(bb, solids[params->solid]);
-    *y = YSIZE(bb, solids[params->solid]);
+    ds->gridscale = tilesize;
+    ds->ox = (int)(-(bb.l - solids[params->solid]->border) * ds->gridscale);
+    ds->oy = (int)(-(bb.u - solids[params->solid]->border) * ds->gridscale);
 }
 
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
@@ -1524,8 +1521,8 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     game_state *newstate;
     int square;
 
-    draw_rect(fe, 0, 0, XSIZE(bb, state->solid), YSIZE(bb, state->solid),
-              COL_BACKGROUND);
+    draw_rect(fe, 0, 0, XSIZE(GRID_SCALE, bb, state->solid),
+             YSIZE(GRID_SCALE, bb, state->solid), COL_BACKGROUND);
 
     if (dir < 0) {
         game_state *t;
@@ -1656,7 +1653,8 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
     }
     sfree(poly);
 
-    draw_update(fe, 0, 0, XSIZE(bb, state->solid), YSIZE(bb, state->solid));
+    draw_update(fe, 0, 0, XSIZE(GRID_SCALE, bb, state->solid),
+               YSIZE(GRID_SCALE, bb, state->solid));
 
     /*
      * Update the status bar.
@@ -1722,7 +1720,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_GRID_SCALE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index 6f75514f069c74efc054f184ccce644c2ccba631..319a585ebe21326641e80c5aa29692a9542603bf 100644 (file)
--- a/fifteen.c
+++ b/fifteen.c
@@ -563,27 +563,23 @@ static game_state *execute_move(game_state *from, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times one more
-     * than the grid dimension (the border is half the width of the
-     * tiles).
-     */
-    tsx = (double)*x / ((double)params->w + 1.0);
-    tsy = (double)*y / ((double)params->h + 1.0);
-    ts = min(tsx, tsy);
-    if (expand)
-        ds->tilesize = (int)(ts + 0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = TILE_SIZE * params->w + 2 * BORDER;
     *y = TILE_SIZE * params->h + 2 * BORDER;
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
@@ -886,7 +882,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
diff --git a/flip.c b/flip.c
index 503681e887e015c84adebe35a37d36e8fd9a4300..b38aff1a62ff865f9c27beaca0fb6bed9a2076f5 100644 (file)
--- a/flip.c
+++ b/flip.c
@@ -988,27 +988,23 @@ static game_state *execute_move(game_state *from, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times one more
-     * than the grid dimension (the border is half the width of the
-     * tiles).
-     */
-    tsx = (double)*x / ((double)params->w + 1.0);
-    tsy = (double)*y / ((double)params->h + 1);
-    ts = min(tsx, tsy);
-    if (expand)
-        ds->tilesize = (int)(ts + 0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = TILE_SIZE * params->w + 2 * BORDER;
     *y = TILE_SIZE * params->h + 2 * BORDER;
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
@@ -1276,7 +1272,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
diff --git a/guess.c b/guess.c
index 9b94123bbbe59eb82bf14979c21b537a81bd8b9d..39241b04d2bafc854e78ed3d8ffbf10e3245d851 100644 (file)
--- a/guess.c
+++ b/guess.c
@@ -805,18 +805,18 @@ static game_state *execute_move(game_state *from, char *move)
 
 #define BORDER    0.5
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double hmul, vmul_c, vmul_g, vmul, szx, szy;
-    int sz, colh, guessh;
+    double hmul, vmul_c, vmul_g, vmul;
+    int hintw = (params->npegs+1)/2;
 
     hmul = BORDER   * 2.0 +               /* border */
            1.0      * 2.0 +               /* vertical colour bar */
            1.0      * params->npegs +     /* guess pegs */
            PEG_GAP  * params->npegs +     /* guess gaps */
-           PEG_HINT * ds->hintw +         /* hint pegs */
-           PEG_GAP  * (ds->hintw - 1);    /* hint gaps */
+           PEG_HINT * hintw +             /* hint pegs */
+           PEG_GAP  * (hintw - 1);        /* hint gaps */
 
     vmul_c = BORDER  * 2.0 +                    /* border */
              1.0     * params->ncolours +       /* colour pegs */
@@ -828,13 +828,16 @@ static void game_size(game_params *params, game_drawstate *ds,
 
     vmul = max(vmul_c, vmul_g);
 
-    szx = *x / hmul;
-    szy = *y / vmul;
-    sz = max(min((int)szx, (int)szy), 1);
-    if (expand)
-        ds->pegsz = sz;
-    else
-        ds->pegsz = min(sz, PEG_PREFER_SZ);
+    *x = (int)ceil((double)tilesize * hmul);
+    *y = (int)ceil((double)tilesize * vmul);
+}
+
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    int colh, guessh, x, y;
+
+    ds->pegsz = tilesize;
 
     ds->hintsz = (int)((double)ds->pegsz * PEG_HINT);
     ds->gapsz  = (int)((double)ds->pegsz * PEG_GAP);
@@ -843,25 +846,21 @@ static void game_size(game_params *params, game_drawstate *ds,
     ds->pegrad  = (ds->pegsz -1)/2; /* radius of peg to fit in pegsz (which is 2r+1) */
     ds->hintrad = (ds->hintsz-1)/2;
 
-    *x = (int)ceil((double)ds->pegsz * hmul);
-    *y = (int)ceil((double)ds->pegsz * vmul);
-    ds->w = *x; ds->h = *y;
-
     colh = ((ds->pegsz + ds->gapsz) * params->ncolours) - ds->gapsz;
     guessh = ((ds->pegsz + ds->gapsz) * params->nguesses);      /* guesses */
     guessh += ds->gapsz + ds->pegsz;                            /* solution */
 
+    game_compute_size(params, tilesize, &x, &y);
     ds->colx = ds->border;
-    ds->coly = (*y - colh) / 2;
+    ds->coly = (y - colh) / 2;
 
     ds->guessx = ds->solnx = ds->border + ds->pegsz * 2;     /* border + colours */
-    ds->guessy = (*y - guessh) / 2;
+    ds->guessy = (y - guessh) / 2;
     ds->solny = ds->guessy + ((ds->pegsz + ds->gapsz) * params->nguesses) + ds->gapsz;
 
-    if (ds->pegsz > 0) {
-        if (ds->blit_peg) blitter_free(ds->blit_peg);
-        ds->blit_peg = blitter_new(ds->pegsz, ds->pegsz);
-    }
+    assert(ds->pegsz > 0);
+    if (ds->blit_peg) blitter_free(ds->blit_peg);
+    ds->blit_peg = blitter_new(ds->pegsz, ds->pegsz);
 }
 
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
@@ -1296,7 +1295,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PEG_PREFER_SZ, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index df661b52026901dd00f59ba1bddb22a46c7985da..b5efda64369e358eb059dcb54c345f4e55392678 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -78,7 +78,7 @@ struct midend_data {
 
     int pressed_mouse_button;
 
-    int winwidth, winheight;
+    int tilesize, winwidth, winheight;
 };
 
 #define ensure(me) do { \
@@ -121,7 +121,7 @@ midend_data *midend_new(frontend *fe, const game *ourgame)
     me->laststatus = NULL;
     me->timing = FALSE;
     me->elapsed = 0.0F;
-    me->winwidth = me->winheight = 0;
+    me->tilesize = me->winwidth = me->winheight = 0;
 
     sfree(randseed);
 
@@ -169,11 +169,63 @@ void midend_free(midend_data *me)
     sfree(me);
 }
 
+static void midend_size_new_drawstate(midend_data *me)
+{
+    /*
+     * Don't even bother, if we haven't worked out our tile size
+     * anyway yet.
+     */
+    if (me->tilesize > 0) {
+       me->ourgame->compute_size(me->params, me->tilesize,
+                                 &me->winwidth, &me->winheight);
+       me->ourgame->set_size(me->drawstate, me->params, me->tilesize);
+    }
+}
+
 void midend_size(midend_data *me, int *x, int *y, int expand)
 {
-    me->ourgame->size(me->params, me->drawstate, x, y, expand);
-    me->winwidth = *x;
-    me->winheight = *y;
+    int min, max;
+    int rx, ry;
+
+    /*
+     * Find the tile size that best fits within the given space. If
+     * `expand' is TRUE, we must actually find the _largest_ such
+     * tile size; otherwise, we bound above at the game's preferred
+     * tile size.
+     */
+    if (expand) {
+       max = 1;
+       do {
+           max *= 2;
+           me->ourgame->compute_size(me->params, max, &rx, &ry);
+       } while (rx <= *x && ry <= *y);
+    } else
+       max = me->ourgame->preferred_tilesize + 1;
+    min = 1;
+
+    /*
+     * Now binary-search between min and max. We're looking for a
+     * boundary rather than a value: the point at which tile sizes
+     * stop fitting within the given dimensions. Thus, we stop when
+     * max and min differ by exactly 1.
+     */
+    while (max - min > 1) {
+       int mid = (max + min) / 2;
+       me->ourgame->compute_size(me->params, mid, &rx, &ry);
+       if (rx <= *x && ry <= *y)
+           min = mid;
+       else
+           max = mid;
+    }
+
+    /*
+     * Now `min' is a valid size, and `max' isn't. So use `min'.
+     */
+
+    me->tilesize = min;
+    midend_size_new_drawstate(me);
+    *x = me->winwidth;
+    *y = me->winheight;
 }
 
 void midend_set_params(midend_data *me, game_params *params)
@@ -192,12 +244,6 @@ static void midend_set_timer(midend_data *me)
        deactivate_timer(me->frontend);
 }
 
-static void midend_size_new_drawstate(midend_data *me)
-{
-    me->ourgame->size(me->params, me->drawstate, &me->winwidth, &me->winheight,
-                      TRUE);
-}
-
 void midend_force_redraw(midend_data *me)
 {
     if (me->drawstate)
diff --git a/mines.c b/mines.c
index 7597d072c194287d32f90fb02dbda85071ae8fea..e8882248cf289bccb9a91f4ac731fd63913e86c1 100644 (file)
--- a/mines.c
+++ b/mines.c
@@ -2604,27 +2604,23 @@ static game_state *execute_move(game_state *from, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times 3 more than
-     * the grid dimension (the border is 3/2 the width of the
-     * tiles).
-     */
-    tsx = (double)*x / ((double)params->w + 3.0);
-    tsy = (double)*y / ((double)params->h + 3.0);
-    ts = min(tsx, tsy);
-    if (expand)
-        ds->tilesize = (int)(ts + 0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = BORDER * 2 + TILE_SIZE * params->w;
     *y = BORDER * 2 + TILE_SIZE * params->h;
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
@@ -3048,7 +3044,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
diff --git a/net.c b/net.c
index 2e867007f9c3ecc6e4d426ba4ca1f90a9c289d77..cb8e613b056bbc09dc2cc7e4441c9effe8550b08 100644 (file)
--- a/net.c
+++ b/net.c
@@ -2146,25 +2146,17 @@ static void game_free_drawstate(game_drawstate *ds)
     sfree(ds);
 }
 
-static void game_size(game_params *params, game_drawstate *ds, int *x, int *y,
-                      int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    int tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times the grid
-     * dimension, plus TILE_BORDER, plus twice WINDOW_OFFSET.
-     */
-    tsx = (*x - 2*WINDOW_OFFSET - TILE_BORDER) / params->width;
-    tsy = (*y - 2*WINDOW_OFFSET - TILE_BORDER) / params->height;
-    ts = min(tsx, tsy);
-
-    if (expand)
-        ds->tilesize = ts;
-    else
-        ds->tilesize = min(ts, PREFERRED_TILE_SIZE);
+    *x = WINDOW_OFFSET * 2 + tilesize * params->width + TILE_BORDER;
+    *y = WINDOW_OFFSET * 2 + tilesize * params->height + TILE_BORDER;
+}
 
-    *x = WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER;
-    *y = WINDOW_OFFSET * 2 + TILE_SIZE * params->height + TILE_BORDER;
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
 }
 
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
@@ -2757,7 +2749,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index fe77794d4e23638a00cf184585bfd54a63e11544..b16cb0bf222aaa1484251c6a5ef5648e65357c5a 100644 (file)
@@ -1194,29 +1194,23 @@ static void game_free_drawstate(game_drawstate *ds)
     sfree(ds);
 }
 
-static void game_size(game_params *params, game_drawstate *ds, int *x, int *y,
-                      int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    int tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times two more
-     * than the grid dimension (the border containing the arrows is
-     * the same width as the tiles), plus TILE_BORDER, plus twice
-     * WINDOW_OFFSET.
-     */
-    tsx = (*x - 2*WINDOW_OFFSET - TILE_BORDER) / (params->width + 2);
-    tsy = (*y - 2*WINDOW_OFFSET - TILE_BORDER) / (params->height + 2);
-    ts = min(tsx, tsy);
-
-    if (expand)
-        ds->tilesize = ts;
-    else
-        ds->tilesize = min(ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->width + TILE_BORDER;
     *y = BORDER * 2 + WINDOW_OFFSET * 2 + TILE_SIZE * params->height + TILE_BORDER;
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret;
@@ -1815,7 +1809,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index 204f6336fb56c41d2acf8c4b8b5ea62354191d1e..bdf0e07153726b4bebaff36ab9572cec3929c7e6 100644 (file)
@@ -152,6 +152,7 @@ static void game_changed_state(game_ui *ui, game_state *oldstate,
 }
 
 struct game_drawstate {
+    int tilesize;
     int FIXME;
 };
 
@@ -170,10 +171,16 @@ static game_state *execute_move(game_state *state, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    *x = *y = 200;                     /* FIXME */
+    *x = *y = 10 * tilesize;          /* FIXME */
+}
+
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
 }
 
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
@@ -190,6 +197,7 @@ static game_drawstate *game_new_drawstate(game_state *state)
 {
     struct game_drawstate *ds = snew(struct game_drawstate);
 
+    ds->tilesize = 0;
     ds->FIXME = 0;
 
     return ds;
@@ -210,7 +218,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate,
      * should start by drawing a big background-colour rectangle
      * covering the whole window.
      */
-    draw_rect(fe, 0, 0, 200, 200, COL_BACKGROUND);
+    draw_rect(fe, 0, 0, 10*ds->tilesize, 10*ds->tilesize, COL_BACKGROUND);
 }
 
 static float game_anim_length(game_state *oldstate, game_state *newstate,
@@ -263,7 +271,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    20 /* FIXME */, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index 7713ffd2062f427e606d7aec22b7979f262b26fe..5ef032f78e4d6347e239bf7ee87f86288f263196 100644 (file)
--- a/pattern.c
+++ b/pattern.c
@@ -945,21 +945,23 @@ static game_state *execute_move(game_state *from, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double ts;
-
-    ts = min(GETTILESIZE(params->w, *x), GETTILESIZE(params->h, *y));
-    if (expand)
-        ds->tilesize = (int)(ts + 0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = SIZE(params->w);
     *y = SIZE(params->h);
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
@@ -1190,7 +1192,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
diff --git a/pegs.c b/pegs.c
index 4cfd4a0776839e9343221d79a410873a4bff2176..0cd740fcb159383c663b4cddc2644327bde3492d 100644 (file)
--- a/pegs.c
+++ b/pegs.c
@@ -798,25 +798,23 @@ static game_state *execute_move(game_state *state, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times one more
-     * than the grid dimension (the border is half the width of the
-     * tiles).
-     */
-    tsx = (double)*x / ((double)params->w + 1.0);
-    tsy = (double)*y / ((double)params->h + 1.0);
-    ts = min(tsx, tsy);
-    if (expand)
-        ds->tilesize = (int)(ts + 0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = TILESIZE * params->w + 2 * BORDER;
     *y = TILESIZE * params->h + 2 * BORDER;
+}
+
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+
+    assert(TILESIZE > 0);
 
     if (ds->drag_background)
        blitter_free(ds->drag_background);
@@ -1094,7 +1092,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index 57445ab4b02d3044a101aae55521dc2ffbe639f5..d41d9646b6ba3aadff838fcf64e00a7fc876c5ab 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -286,8 +286,9 @@ struct game {
     char *(*interpret_move)(game_state *state, game_ui *ui, game_drawstate *ds,
                            int x, int y, int button);
     game_state *(*execute_move)(game_state *state, char *move);
-    void (*size)(game_params *params, game_drawstate *ds, int *x, int *y,
-                 int expand);
+    int preferred_tilesize;
+    void (*compute_size)(game_params *params, int tilesize, int *x, int *y);
+    void (*set_size)(game_drawstate *ds, game_params *params, int tilesize);
     float *(*colours)(frontend *fe, game_state *state, int *ncolours);
     game_drawstate *(*new_drawstate)(game_state *state);
     void (*free_drawstate)(game_drawstate *ds);
diff --git a/rect.c b/rect.c
index ec7bd4aaa4cbfbf3d61b909318226b81800c24f1..952f133246f0603bba30d5d7ae5fd090d3af895d 100644 (file)
--- a/rect.c
+++ b/rect.c
@@ -2499,30 +2499,23 @@ static game_state *execute_move(game_state *from, char *move)
 #define COLOUR(k) ( (k)==1 ? COL_LINE : COL_DRAG )
 #define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) )
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times 1.5 more
-     * than the grid dimension (the border is 3/4 the width of the
-     * tiles).
-     * 
-     * We must cast to unsigned before multiplying by two, because
-     * *x might be INT_MAX.
-     */
-    tsx = 2.0 * (double)*x / (2.0 * (double)params->w + 3.0);
-    tsy = 2.0 * (double)*y / (2.0 * (double)params->h + 3.0);
-    ts = min(tsx, tsy);
-    if (expand)
-        ds->tilesize = (int)(ts + 0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = params->w * TILE_SIZE + 2*BORDER + 1;
     *y = params->h * TILE_SIZE + 2*BORDER + 1;
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
@@ -2798,7 +2791,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index a384c0b54e1b40254b9b5ad33520f5c2e00e6bad..35f2ae2105259f200501fb56c90243ae1c524f36 100644 (file)
@@ -686,36 +686,19 @@ static game_state *execute_move(game_state *from, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds, int *x, int *y,
-                      int expand)
-{
-    double tsx, tsy, ts;
-
-    /*
-     * We could choose the tile gap dynamically as well if we
-     * wanted to; for example, at low tile sizes it might be
-     * sensible to leave it out completely. However, for the moment
-     * and for the sake of simplicity I'm just going to fix it at
-     * 2.
-     */
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
     ds->tilegap = 2;
+    ds->tileinner = tilesize - ds->tilegap;
+}
 
-    /*
-     * Each window dimension equals the tile size (inner plus gap)
-     * times the grid dimension, plus another tile size (border is
-     * half the width of a tile), minus one tile gap.
-     * 
-     * We must cast to unsigned before adding to *x and *y, since
-     * they might be INT_MAX!
-     */
-    tsx = ((double)*x + (double)ds->tilegap) / ((double)params->w + 1.0);
-    tsy = ((double)*y + (double)ds->tilegap) / ((double)params->h + 1.0);
-
-    ts = min(tsx, tsy);
-    if (expand)
-        ds->tileinner = (int)(ts+0.5) - ds->tilegap;
-    else
-        ds->tileinner = min((int)ts, PREFERRED_TILE_SIZE) - ds->tilegap;
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
+{
+    /* Ick: fake up tile size variables for macro expansion purposes */
+    game_drawstate ads, *ds = &ads;
+    game_set_size(ds, params, tilesize);
 
     *x = TILE_SIZE * params->w + 2 * BORDER - TILE_GAP;
     *y = TILE_SIZE * params->h + 2 * BORDER - TILE_GAP;
@@ -1005,7 +988,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index 72585c17fe99f89c213bead00e625ec7df924126..f293fab67c126ff3209741c227e96b81a7a21440 100644 (file)
--- a/sixteen.c
+++ b/sixteen.c
@@ -685,28 +685,23 @@ static game_state *execute_move(game_state *from, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    int tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times two more
-     * than the grid dimension (the border is the same size as the
-     * tiles).
-     */
-    tsx = *x / (params->w + 2);
-    tsy = *y / (params->h + 2);
-    ts = min(tsx, tsy);
-
-    if (expand)
-        ds->tilesize = ts;
-    else
-        ds->tilesize = min(ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = TILE_SIZE * params->w + 2 * BORDER;
     *y = TILE_SIZE * params->h + 2 * BORDER;
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
@@ -1063,7 +1058,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
diff --git a/solo.c b/solo.c
index cfbb869ac3e457dc1c6943dc9695c3126e3a05e7..9c6a1f96e1fa5682c8e0ac9c9a9e3f1b27ecba76 100644 (file)
--- a/solo.c
+++ b/solo.c
@@ -2092,20 +2092,21 @@ static game_state *execute_move(game_state *from, char *move)
 #define SIZE(cr) ((cr) * TILE_SIZE + 2*BORDER + 1)
 #define GETTILESIZE(cr, w) ( (double)(w-1) / (double)(cr+1) )
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    int c = params->c, r = params->r, cr = c*r;
-    double ts;
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
-    ts = min(GETTILESIZE(cr, *x), GETTILESIZE(cr, *y));
-    if (expand)
-        ds->tilesize = (int)(ts+0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    *x = SIZE(params->c * params->r);
+    *y = SIZE(params->c * params->r);
+}
 
-    *x = SIZE(cr);
-    *y = SIZE(cr);
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
 }
 
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
@@ -2414,7 +2415,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,
index 92f5db3806638f9231652e069e3b3e054134e8ea..ce3d0ece979abbccd35dad00de6ff479eb11e3f2 100644 (file)
--- a/twiddle.c
+++ b/twiddle.c
@@ -744,27 +744,23 @@ static game_state *execute_move(game_state *from, char *move)
  * Drawing routines.
  */
 
-static void game_size(game_params *params, game_drawstate *ds,
-                      int *x, int *y, int expand)
+static void game_compute_size(game_params *params, int tilesize,
+                             int *x, int *y)
 {
-    double tsx, tsy, ts;
-    /*
-     * Each window dimension equals the tile size times one more
-     * than the grid dimension (the border is half the width of the
-     * tiles).
-     */
-    tsx = (double)*x / ((double)params->w + 1.0);
-    tsy = (double)*y / ((double)params->h + 1.0);
-    ts = min(tsx, tsy);
-    if (expand)
-        ds->tilesize = (int)(ts + 0.5);
-    else
-        ds->tilesize = min((int)ts, PREFERRED_TILE_SIZE);
+    /* Ick: fake up `ds->tilesize' for macro expansion purposes */
+    struct { int tilesize; } ads, *ds = &ads;
+    ads.tilesize = tilesize;
 
     *x = TILE_SIZE * params->w + 2 * BORDER;
     *y = TILE_SIZE * params->h + 2 * BORDER;
 }
 
+static void game_set_size(game_drawstate *ds, game_params *params,
+                         int tilesize)
+{
+    ds->tilesize = tilesize;
+}
+
 static float *game_colours(frontend *fe, game_state *state, int *ncolours)
 {
     float *ret = snewn(3 * NCOLOURS, float);
@@ -1228,7 +1224,7 @@ const struct game thegame = {
     game_changed_state,
     interpret_move,
     execute_move,
-    game_size,
+    PREFERRED_TILE_SIZE, game_compute_size, game_set_size,
     game_colours,
     game_new_drawstate,
     game_free_drawstate,