From: Simon Tatham Date: Wed, 1 Jun 2005 17:47:56 +0000 (+0000) Subject: Miscellaneous fixes from James Harvey's PalmOS porting work: X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=sgt-puzzles.git;a=commitdiff_plain;h=50edaa578b614eb74c57a38faa2d05ab628ff81b Miscellaneous fixes from James Harvey's PalmOS porting work: - fixed numerous memory leaks (not Palm-specific) - corrected a couple of 32-bit-int assumptions (vital for Palm but generally a good thing anyway) - lifted a few function pointer types into explicit typedefs (neutral for me but convenient for the source-munging Perl scripts he uses to deal with Palm code segment rules) - lifted a few function-level static arrays into global static arrays (neutral for me but apparently works round a Palm tools bug) - a couple more presets in Rectangles (so that Palm, or any other slow platform which can't handle the larger sizes easily, can still have some variety available) - in Solo, arranged a means of sharing scratch space between calls to nsolve to prevent a lot of redundant malloc/frees (gives a 10% speed increase even on existing platforms) [originally from svn r5897] --- diff --git a/cube.c b/cube.c index cb6a1f9..0ff952f 100644 --- a/cube.c +++ b/cube.c @@ -300,10 +300,9 @@ static char *encode_params(game_params *params, int full) return dupstr(data); } +typedef void (*egc_callback)(void *, struct grid_square *); -static void enum_grid_squares(game_params *params, - void (*callback)(void *, struct grid_square *), - void *ctx) +static void enum_grid_squares(game_params *params, egc_callback callback, void *ctx) { const struct solid *solid = solids[params->solid]; @@ -979,6 +978,8 @@ static game_state *dup_game(game_state *state) static void free_game(game_state *state) { + sfree(state->squares); + sfree(state->facecolours); sfree(state); } @@ -1233,6 +1234,7 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds, success = align_poly(poly, &from->squares[ret->current], all_pkey); if (!success) { + sfree(poly); angle = -angle; poly = transform_poly(from->solid, from->squares[from->current].flip, @@ -1572,8 +1574,8 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, } sfree(poly); - draw_update(fe, 0, 0, (int)((bb.r-bb.l+2.0F) * GRID_SCALE), - (int)((bb.d-bb.u+2.0F) * GRID_SCALE)); + game_size(&state->params, &i, &j); + draw_update(fe, 0, 0, i, j); /* * Update the status bar. diff --git a/fifteen.c b/fifteen.c index 4b37dd7..bf2cdf1 100644 --- a/fifteen.c +++ b/fifteen.c @@ -130,7 +130,7 @@ static game_params *custom_params(config_item *cfg) static char *validate_params(game_params *params) { - if (params->w < 2 && params->h < 2) + if (params->w < 2 || params->h < 2) return "Width and height must both be at least two"; return NULL; @@ -374,6 +374,7 @@ static game_state *dup_game(game_state *state) static void free_game(game_state *state) { + sfree(state->tiles); sfree(state); } diff --git a/malloc.c b/malloc.c index fd0ddf9..a7fa7c5 100644 --- a/malloc.c +++ b/malloc.c @@ -10,7 +10,7 @@ * smalloc should guarantee to return a useful pointer - Halibut * can do nothing except die when it's out of memory anyway. */ -void *smalloc(int size) { +void *smalloc(size_t size) { void *p; p = malloc(size); if (!p) @@ -30,7 +30,7 @@ void sfree(void *p) { /* * srealloc should guaranteeably be able to realloc NULL */ -void *srealloc(void *p, int size) { +void *srealloc(void *p, size_t size) { void *q; if (p) { q = realloc(p, size); diff --git a/midend.c b/midend.c index cde2729..b6b1720 100644 --- a/midend.c +++ b/midend.c @@ -96,15 +96,38 @@ midend_data *midend_new(frontend *fe, const game *ourgame) return me; } +static void midend_free_game(midend_data *me) +{ + while (me->nstates > 0) + me->ourgame->free_game(me->states[--me->nstates].state); + + if (me->drawstate) + me->ourgame->free_drawstate(me->drawstate); +} + void midend_free(midend_data *me) { + int i; + + midend_free_game(me); + + random_free(me->random); sfree(me->states); sfree(me->desc); sfree(me->seedstr); - random_free(me->random); if (me->aux_info) me->ourgame->free_aux_info(me->aux_info); me->ourgame->free_params(me->params); + if (me->npresets) { + for (i = 0; i < me->npresets; i++) { + sfree(me->presets[i]); + sfree(me->preset_names[i]); + } + sfree(me->presets); + sfree(me->preset_names); + } + if (me->ui) + me->ourgame->free_ui(me->ui); if (me->curparams) me->ourgame->free_params(me->curparams); sfree(me->laststatus); @@ -142,11 +165,7 @@ void midend_force_redraw(midend_data *me) void midend_new_game(midend_data *me) { - while (me->nstates > 0) - me->ourgame->free_game(me->states[--me->nstates].state); - - if (me->drawstate) - me->ourgame->free_drawstate(me->drawstate); + midend_free_game(me); assert(me->nstates == 0); @@ -259,7 +278,7 @@ static void midend_finish_move(midend_data *me) midend_set_timer(me); } -static void midend_stop_anim(midend_data *me) +void midend_stop_anim(midend_data *me) { if (me->oldstate || me->anim_time) { midend_finish_move(me); @@ -299,29 +318,29 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button) { game_state *oldstate = me->ourgame->dup_game(me->states[me->statepos - 1].state); - int special = FALSE, gotspecial = FALSE; + int special = FALSE, gotspecial = FALSE, ret = 1; float anim_time; if (button == 'n' || button == 'N' || button == '\x0E') { midend_stop_anim(me); midend_new_game(me); midend_redraw(me); - return 1; /* never animate */ + goto done; /* never animate */ } else if (button == 'u' || button == 'u' || button == '\x1A' || button == '\x1F') { midend_stop_anim(me); special = me->states[me->statepos-1].special; gotspecial = TRUE; if (!midend_undo(me)) - return 1; + goto done; } else if (button == 'r' || button == 'R' || button == '\x12' || button == '\x19') { midend_stop_anim(me); if (!midend_redo(me)) - return 1; + goto done; } else if (button == 'q' || button == 'Q' || button == '\x11') { - me->ourgame->free_game(oldstate); - return 0; + ret = 0; + goto done; } else { game_state *s = me->ourgame->make_move(me->states[me->statepos-1].state, @@ -334,7 +353,7 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button) * state has been updated and a redraw is called for. */ midend_redraw(me); - return 1; + goto done; } else if (s) { midend_stop_anim(me); while (me->nstates > me->statepos) @@ -345,8 +364,7 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button) me->statepos = ++me->nstates; me->dir = +1; } else { - me->ourgame->free_game(oldstate); - return 1; + goto done; } } @@ -364,7 +382,7 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button) me->dir, me->ui); } - me->oldstate = oldstate; + me->oldstate = oldstate; oldstate = NULL; if (anim_time > 0) { me->anim_time = anim_time; } else { @@ -377,7 +395,9 @@ static int midend_really_process_key(midend_data *me, int x, int y, int button) midend_set_timer(me); - return 1; + done: + if (oldstate) me->ourgame->free_game(oldstate); + return ret; } int midend_process_key(midend_data *me, int x, int y, int button) @@ -687,21 +707,27 @@ void midend_supersede_game_desc(midend_data *me, char *desc) config_item *midend_get_config(midend_data *me, int which, char **wintitle) { - char *titlebuf, *parstr; + char *titlebuf, *parstr, *rest; config_item *ret; + char sep; + assert(wintitle); titlebuf = snewn(40 + strlen(me->ourgame->name), char); switch (which) { case CFG_SETTINGS: sprintf(titlebuf, "%s configuration", me->ourgame->name); - *wintitle = dupstr(titlebuf); + *wintitle = titlebuf; return me->ourgame->configure(me->params); case CFG_SEED: case CFG_DESC: - sprintf(titlebuf, "%s %s selection", me->ourgame->name, + if (!me->curparams) { + sfree(titlebuf); + return NULL; + } + sprintf(titlebuf, "%s %s selection", me->ourgame->name, which == CFG_SEED ? "random" : "game"); - *wintitle = dupstr(titlebuf); + *wintitle = titlebuf; ret = snewn(2, config_item); @@ -721,21 +747,16 @@ config_item *midend_get_config(midend_data *me, int which, char **wintitle) * changes). */ parstr = me->ourgame->encode_params(me->curparams, which == CFG_SEED); + assert(parstr); if (which == CFG_DESC) { - ret[0].sval = snewn(strlen(parstr) + strlen(me->desc) + 2, char); - sprintf(ret[0].sval, "%s:%s", parstr, me->desc); - } else if (me->seedstr) { - ret[0].sval = snewn(strlen(parstr) + strlen(me->seedstr) + 2, char); - sprintf(ret[0].sval, "%s#%s", parstr, me->seedstr); + rest = me->desc ? me->desc : ""; + sep = ':'; } else { - /* - * If the current game was not randomly generated, the - * best we can do is to give a template for typing a - * new seed in. - */ - ret[0].sval = snewn(strlen(parstr) + 2, char); - sprintf(ret[0].sval, "%s#", parstr); + rest = me->seedstr ? me->seedstr : ""; + sep = '#'; } + ret[0].sval = snewn(strlen(parstr) + strlen(rest) + 2, char); + sprintf(ret[0].sval, "%s%c%s", parstr, sep, rest); sfree(parstr); ret[1].type = C_END; diff --git a/mines.c b/mines.c index 5afefe6..50ba8f0 100644 --- a/mines.c +++ b/mines.c @@ -95,24 +95,22 @@ static game_params *default_params(void) return ret; } +static const struct game_params mines_presets[] = { + {9, 9, 10, TRUE}, + {16, 16, 40, TRUE}, + {30, 16, 99, TRUE}, +}; + static int game_fetch_preset(int i, char **name, game_params **params) { game_params *ret; char str[80]; - static const struct { int w, h, n; } values[] = { - {9, 9, 10}, - {16, 16, 40}, - {30, 16, 99}, - }; - if (i < 0 || i >= lenof(values)) + if (i < 0 || i >= lenof(mines_presets)) return FALSE; ret = snew(game_params); - ret->w = values[i].w; - ret->h = values[i].h; - ret->n = values[i].n; - ret->unique = TRUE; + *ret = mines_presets[i]; sprintf(str, "%dx%d, %d mines", ret->w, ret->h, ret->n); @@ -558,9 +556,11 @@ static void std_add(struct squaretodo *std, int i) std->next[i] = -1; } +typedef int (*open_cb)(void *, int, int); + static void known_squares(int w, int h, struct squaretodo *std, - signed char *grid, - int (*open)(void *ctx, int x, int y), void *openctx, + signed char *grid, + open_cb open, void *openctx, int x, int y, int mask, int mine) { int xx, yy, bit; @@ -626,11 +626,12 @@ struct perturbations { * steps were required; the exact return value is the number of * perturb calls. */ + +typedef struct perturbations *(*perturb_cb) (void *, signed char *, int, int, int); + static int minesolve(int w, int h, int n, signed char *grid, - int (*open)(void *ctx, int x, int y), - struct perturbations *(*perturb)(void *ctx, - signed char *grid, - int x, int y, int mask), + open_cb open, + perturb_cb perturb, void *ctx, random_state *rs) { struct setstore *ss = ss_new(); @@ -2071,7 +2072,7 @@ static char *new_game_desc(game_params *params, random_state *rs, rsdesc = random_state_encode(rs); desc = snewn(strlen(rsdesc) + 100, char); - sprintf(desc, "r%d,%c,%s", params->n, params->unique ? 'u' : 'a', rsdesc); + sprintf(desc, "r%d,%c,%s", params->n, (char)(params->unique ? 'u' : 'a'), rsdesc); sfree(rsdesc); return desc; } @@ -2258,6 +2259,7 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc) wh = state->w * state->h; state->layout = snew(struct mine_layout); + memset(state->layout, 0, sizeof(struct mine_layout)); state->layout->refcount = 1; state->grid = snewn(wh, char); @@ -2334,6 +2336,7 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc) } ret = open_square(state, x, y); + sfree(bmp); } return state; diff --git a/net.c b/net.c index 5ef1ba7..38a025c 100644 --- a/net.c +++ b/net.c @@ -149,32 +149,29 @@ static game_params *default_params(void) return ret; } +static const struct game_params net_presets[] = { + {5, 5, FALSE, TRUE, 0.0}, + {7, 7, FALSE, TRUE, 0.0}, + {9, 9, FALSE, TRUE, 0.0}, + {11, 11, FALSE, TRUE, 0.0}, + {13, 11, FALSE, TRUE, 0.0}, + {5, 5, TRUE, TRUE, 0.0}, + {7, 7, TRUE, TRUE, 0.0}, + {9, 9, TRUE, TRUE, 0.0}, + {11, 11, TRUE, TRUE, 0.0}, + {13, 11, TRUE, TRUE, 0.0}, +}; + static int game_fetch_preset(int i, char **name, game_params **params) { game_params *ret; char str[80]; - static const struct { int x, y, wrap; } values[] = { - {5, 5, FALSE}, - {7, 7, FALSE}, - {9, 9, FALSE}, - {11, 11, FALSE}, - {13, 11, FALSE}, - {5, 5, TRUE}, - {7, 7, TRUE}, - {9, 9, TRUE}, - {11, 11, TRUE}, - {13, 11, TRUE}, - }; - - if (i < 0 || i >= lenof(values)) + + if (i < 0 || i >= lenof(net_presets)) return FALSE; ret = snew(game_params); - ret->width = values[i].x; - ret->height = values[i].y; - ret->wrapping = values[i].wrap; - ret->unique = TRUE; - ret->barrier_probability = 0.0; + *ret = net_presets[i]; sprintf(str, "%dx%d%s", ret->width, ret->height, ret->wrapping ? " wrapping" : ""); @@ -302,12 +299,8 @@ static game_params *custom_params(config_item *cfg) static char *validate_params(game_params *params) { - if (params->width <= 0 && params->height <= 0) + if (params->width <= 0 || params->height <= 0) return "Width and height must both be greater than zero"; - if (params->width <= 0) - return "Width must be greater than zero"; - if (params->height <= 0) - return "Height must be greater than zero"; if (params->width <= 1 && params->height <= 1) return "At least one of width and height must be greater than one"; if (params->barrier_probability < 0) @@ -968,6 +961,7 @@ static void perturb(int w, int h, unsigned char *tiles, int wrapping, break; } + sfree(perim2); if (i == nperim) return; /* nothing we can do! */ @@ -1944,7 +1938,10 @@ static game_state *make_move(game_state *state, game_ui *ui, ret->last_rotate_dir = 0; /* suppress animation */ ret->last_rotate_x = ret->last_rotate_y = 0; - } else assert(0); + } else { + ret = NULL; /* placate optimisers which don't understand assert(0) */ + assert(0); + } /* * Check whether the game has been completed. diff --git a/netslide.c b/netslide.c index 5697b2f..f6282eb 100644 --- a/netslide.c +++ b/netslide.c @@ -161,34 +161,35 @@ static game_params *default_params(void) return ret; } +static const struct { int x, y, wrap, bprob; const char* desc; } +netslide_presets[] = { + {3, 3, FALSE, 1.0, " easy"}, + {3, 3, FALSE, 0.0, " medium"}, + {3, 3, TRUE, 0.0, " hard"}, + {4, 4, FALSE, 1.0, " easy"}, + {4, 4, FALSE, 0.0, " medium"}, + {4, 4, TRUE, 0.0, " hard"}, + {5, 5, FALSE, 1.0, " easy"}, + {5, 5, FALSE, 0.0, " medium"}, + {5, 5, TRUE, 0.0, " hard"}, +}; + static int game_fetch_preset(int i, char **name, game_params **params) { game_params *ret; char str[80]; - static const struct { int x, y, wrap, bprob; const char* desc; } values[] = { - {3, 3, FALSE, 1.0, " easy"}, - {3, 3, FALSE, 0.0, " medium"}, - {3, 3, TRUE, 0.0, " hard"}, - {4, 4, FALSE, 1.0, " easy"}, - {4, 4, FALSE, 0.0, " medium"}, - {4, 4, TRUE, 0.0, " hard"}, - {5, 5, FALSE, 1.0, " easy"}, - {5, 5, FALSE, 0.0, " medium"}, - {5, 5, TRUE, 0.0, " hard"}, - }; - - if (i < 0 || i >= lenof(values)) + + if (i < 0 || i >= lenof(netslide_presets)) return FALSE; ret = snew(game_params); - ret->width = values[i].x; - ret->height = values[i].y; - ret->wrapping = values[i].wrap; - ret->barrier_probability = values[i].bprob; + ret->width = netslide_presets[i].x; + ret->height = netslide_presets[i].y; + ret->wrapping = netslide_presets[i].wrap; + ret->barrier_probability = netslide_presets[i].bprob; ret->movetarget = 0; - sprintf(str, "%dx%d%s", ret->width, ret->height, - values[i].desc); + sprintf(str, "%dx%d%s", ret->width, ret->height, netslide_presets[i].desc); *name = dupstr(str); *params = ret; @@ -314,12 +315,8 @@ static game_params *custom_params(config_item *cfg) static char *validate_params(game_params *params) { - if (params->width <= 1 && params->height <= 1) + if (params->width <= 1 || params->height <= 1) return "Width and height must both be greater than one"; - if (params->width <= 1) - return "Width must be greater than one"; - if (params->height <= 1) - return "Height must be greater than one"; if (params->barrier_probability < 0) return "Barrier probability may not be negative"; if (params->barrier_probability > 1) diff --git a/pattern.c b/pattern.c index 26201e8..f8e8fc5 100644 --- a/pattern.c +++ b/pattern.c @@ -11,9 +11,6 @@ #include "puzzles.h" -#define max(x,y) ( (x)>(y) ? (x):(y) ) -#define min(x,y) ( (x)<(y) ? (x):(y) ) - enum { COL_BACKGROUND, COL_EMPTY, @@ -62,24 +59,26 @@ static game_params *default_params(void) return ret; } +static const struct game_params pattern_presets[] = { + {10, 10}, + {15, 15}, + {20, 20}, +#ifndef SLOW_SYSTEM + {25, 25}, + {30, 30}, +#endif +}; + static int game_fetch_preset(int i, char **name, game_params **params) { game_params *ret; char str[80]; - static const struct { int x, y; } values[] = { - {10, 10}, - {15, 15}, - {20, 20}, - {25, 25}, - {30, 30}, - }; - - if (i < 0 || i >= lenof(values)) + + if (i < 0 || i >= lenof(pattern_presets)) return FALSE; ret = snew(game_params); - ret->w = values[i].x; - ret->h = values[i].y; + *ret = pattern_presets[i]; sprintf(str, "%dx%d", ret->w, ret->h); @@ -166,12 +165,8 @@ static game_params *custom_params(config_item *cfg) static char *validate_params(game_params *params) { - if (params->w <= 0 && params->h <= 0) + if (params->w <= 0 || params->h <= 0) return "Width and height must both be greater than zero"; - if (params->w <= 0) - return "Width must be greater than zero"; - if (params->h <= 0) - return "Height must be greater than zero"; return NULL; } @@ -494,8 +489,7 @@ static char *new_game_desc(game_params *params, random_state *rs, ai->w = params->w; ai->h = params->h; - ai->grid = snewn(ai->w * ai->h, unsigned char); - memcpy(ai->grid, grid, ai->w * ai->h); + ai->grid = grid; *aux = ai; } diff --git a/puzzles.h b/puzzles.h index b8317ee..8be9009 100644 --- a/puzzles.h +++ b/puzzles.h @@ -5,6 +5,8 @@ #ifndef PUZZLES_PUZZLES_H #define PUZZLES_PUZZLES_H +#include /* for size_t */ + #ifndef TRUE #define TRUE 1 #endif @@ -19,8 +21,12 @@ #define STR_INT(x) #x #define STR(x) STR_INT(x) +/* NB not perfect because they evaluate arguments multiple times. */ +#define max(x,y) ( (x)>(y) ? (x) : (y) ) +#define min(x,y) ( (x)<(y) ? (x) : (y) ) + enum { - LEFT_BUTTON = 0x1000, + LEFT_BUTTON = 0x0200, MIDDLE_BUTTON, RIGHT_BUTTON, LEFT_DRAG, @@ -34,10 +40,11 @@ enum { CURSOR_LEFT, CURSOR_RIGHT, - MOD_CTRL = 0x10000000, - MOD_SHFT = 0x20000000, - MOD_NUM_KEYPAD = 0x40000000, - MOD_MASK = 0x70000000 /* mask for all modifiers */ + /* made smaller because of 'limited range of datatype' errors. */ + MOD_CTRL = 0x1000, + MOD_SHFT = 0x2000, + MOD_NUM_KEYPAD = 0x4000, + MOD_MASK = 0x7000 /* mask for all modifiers */ }; #define IS_MOUSE_DOWN(m) ( (unsigned)((m) - LEFT_BUTTON) <= \ @@ -108,6 +115,14 @@ struct config_item { /* * Platform routines */ + +#ifdef DEBUG +#define debug(x) (debug_printf x) +void debug_printf(char *fmt, ...); +#else +#define debug(x) +#endif + void fatal(char *fmt, ...); void frontend_default_colour(frontend *fe, float *output); void draw_text(frontend *fe, int x, int y, int fonttype, int fontsize, @@ -135,6 +150,7 @@ void midend_set_params(midend_data *me, game_params *params); void midend_size(midend_data *me, int *x, int *y); void midend_new_game(midend_data *me); void midend_restart_game(midend_data *me); +void midend_stop_anim(midend_data *me); int midend_process_key(midend_data *me, int x, int y, int button); void midend_force_redraw(midend_data *me); void midend_redraw(midend_data *me); @@ -156,8 +172,8 @@ char *midend_rewrite_statusbar(midend_data *me, char *text); /* * malloc.c */ -void *smalloc(int size); -void *srealloc(void *p, int size); +void *smalloc(size_t size); +void *srealloc(void *p, size_t size); void sfree(void *p); char *dupstr(const char *s); #define snew(type) \ diff --git a/random.c b/random.c index 08bc608..107649c 100644 --- a/random.c +++ b/random.c @@ -264,7 +264,7 @@ unsigned long random_upto(random_state *state, unsigned long limit) bits += 3; assert(bits < 32); - max = 1 << bits; + max = 1L << bits; divisor = max / limit; max = limit * divisor; diff --git a/rect.c b/rect.c index 0eeb704..0448958 100644 --- a/rect.c +++ b/rect.c @@ -98,9 +98,14 @@ static int game_fetch_preset(int i, char **name, game_params **params) switch (i) { case 0: w = 7, h = 7; break; - case 1: w = 11, h = 11; break; - case 2: w = 15, h = 15; break; - case 3: w = 19, h = 19; break; + case 1: w = 9, h = 9; break; + case 2: w = 11, h = 11; break; + case 3: w = 13, h = 13; break; + case 4: w = 15, h = 15; break; +#ifndef SLOW_SYSTEM + case 5: w = 17, h = 17; break; + case 6: w = 19, h = 19; break; +#endif default: return FALSE; } @@ -212,9 +217,9 @@ static game_params *custom_params(config_item *cfg) static char *validate_params(game_params *params) { - if (params->w <= 0 && params->h <= 0) + if (params->w <= 0 || params->h <= 0) return "Width and height must both be greater than zero"; - if (params->w < 2 && params->h < 2) + if (params->w*params->h < 2) return "Grid area must be greater than one"; if (params->expandfactor < 0.0F) return "Expansion factor may not be negative"; @@ -2277,16 +2282,15 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds, * Drawing routines. */ -#define CORRECT 65536 +#define CORRECT (1L<<16) #define COLOUR(k) ( (k)==1 ? COL_LINE : COL_DRAG ) -#define MAX(x,y) ( (x)>(y) ? (x) : (y) ) -#define MAX4(x,y,z,w) ( MAX(MAX(x,y),MAX(z,w)) ) +#define MAX4(x,y,z,w) ( max(max(x,y),max(z,w)) ) struct game_drawstate { int started; int w, h; - unsigned int *visible; + unsigned long *visible; }; static void game_size(game_params *params, int *x, int *y) @@ -2333,7 +2337,7 @@ static game_drawstate *game_new_drawstate(game_state *state) ds->started = FALSE; ds->w = state->w; ds->h = state->h; - ds->visible = snewn(ds->w * ds->h, unsigned int); + ds->visible = snewn(ds->w * ds->h, unsigned long); for (i = 0; i < ds->w * ds->h; i++) ds->visible[i] = 0xFFFF; @@ -2459,7 +2463,7 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, for (x = 0; x < state->w; x++) for (y = 0; y < state->h; y++) { - unsigned int c = 0; + unsigned long c = 0; if (HRANGE(state,x,y)) c |= index(state,hedge,x,y); @@ -2475,12 +2479,14 @@ static void game_redraw(frontend *fe, game_drawstate *ds, game_state *oldstate, if (y+1 < state->h) c |= index(state,corners,x,y+1) << 12; if (x+1 < state->w && y+1 < state->h) - c |= index(state,corners,x+1,y+1) << 14; + /* cast to prevent 2<<14 sign-extending on promotion to long */ + c |= (unsigned long)index(state,corners,x+1,y+1) << 14; if (index(state, correct, x, y) && !flashtime) c |= CORRECT; if (index(ds,ds->visible,x,y) != c) { - draw_tile(fe, state, x, y, hedge, vedge, corners, c & CORRECT); + draw_tile(fe, state, x, y, hedge, vedge, corners, + (c & CORRECT) ? 1 : 0); index(ds,ds->visible,x,y) = c; } } diff --git a/sixteen.c b/sixteen.c index 744e01d..feab05d 100644 --- a/sixteen.c +++ b/sixteen.c @@ -173,7 +173,7 @@ static game_params *custom_params(config_item *cfg) static char *validate_params(game_params *params) { - if (params->w < 2 && params->h < 2) + if (params->w < 2 || params->h < 2) return "Width and height must both be at least two"; return NULL; @@ -505,6 +505,7 @@ static game_state *dup_game(game_state *state) static void free_game(game_state *state) { + sfree(state->tiles); sfree(state); } diff --git a/solo.c b/solo.c index 2cd406a..c8fac6e 100644 --- a/solo.c +++ b/solo.c @@ -96,8 +96,6 @@ int solver_show_working; #include "puzzles.h" -#define max(x,y) ((x)>(y)?(x):(y)) - /* * To save space, I store digits internally as unsigned char. This * imposes a hard limit of 255 on the order of the puzzle. Since @@ -177,8 +175,10 @@ static int game_fetch_preset(int i, char **name, game_params **params) { "3x3 Intermediate", { 3, 3, SYMM_ROT2, DIFF_INTERSECT } }, { "3x3 Advanced", { 3, 3, SYMM_ROT2, DIFF_SET } }, { "3x3 Unreasonable", { 3, 3, SYMM_ROT2, DIFF_RECURSIVE } }, +#ifndef SLOW_SYSTEM { "3x4 Basic", { 3, 4, SYMM_ROT2, DIFF_SIMPLE } }, { "4x4 Basic", { 4, 4, SYMM_ROT2, DIFF_SIMPLE } }, +#endif }; if (i < 0 || i >= lenof(presets)) @@ -844,7 +844,12 @@ static int nsolve_intersect(struct nsolve_usage *usage, return ret; } +struct nsolve_scratch { + unsigned char *grid, *rowidx, *colidx, *set; +}; + static int nsolve_set(struct nsolve_usage *usage, + struct nsolve_scratch *scratch, int start, int step1, int step2 #ifdef STANDALONE_SOLVER , char *fmt, ... @@ -853,10 +858,10 @@ static int nsolve_set(struct nsolve_usage *usage, { int c = usage->c, r = usage->r, cr = c*r; int i, j, n, count; - unsigned char *grid = snewn(cr*cr, unsigned char); - unsigned char *rowidx = snewn(cr, unsigned char); - unsigned char *colidx = snewn(cr, unsigned char); - unsigned char *set = snewn(cr, unsigned char); + unsigned char *grid = scratch->grid; + unsigned char *rowidx = scratch->rowidx; + unsigned char *colidx = scratch->colidx; + unsigned char *set = scratch->set; /* * We are passed a cr-by-cr matrix of booleans. Our first job @@ -999,10 +1004,6 @@ static int nsolve_set(struct nsolve_usage *usage, } if (progress) { - sfree(set); - sfree(colidx); - sfree(rowidx); - sfree(grid); return TRUE; } } @@ -1021,17 +1022,33 @@ static int nsolve_set(struct nsolve_usage *usage, break; /* done */ } - sfree(set); - sfree(colidx); - sfree(rowidx); - sfree(grid); - return FALSE; } +static struct nsolve_scratch *nsolve_new_scratch(struct nsolve_usage *usage) +{ + struct nsolve_scratch *scratch = snew(struct nsolve_scratch); + int cr = usage->cr; + scratch->grid = snewn(cr*cr, unsigned char); + scratch->rowidx = snewn(cr, unsigned char); + scratch->colidx = snewn(cr, unsigned char); + scratch->set = snewn(cr, unsigned char); + return scratch; +} + +static void nsolve_free_scratch(struct nsolve_scratch *scratch) +{ + sfree(scratch->set); + sfree(scratch->colidx); + sfree(scratch->rowidx); + sfree(scratch->grid); + sfree(scratch); +} + static int nsolve(int c, int r, digit *grid) { struct nsolve_usage *usage; + struct nsolve_scratch *scratch; int cr = c*r; int x, y, n; int diff = DIFF_BLOCK; @@ -1055,6 +1072,8 @@ static int nsolve(int c, int r, digit *grid) memset(usage->col, FALSE, cr * cr); memset(usage->blk, FALSE, cr * cr); + scratch = nsolve_new_scratch(usage); + /* * Place all the clue numbers we are given. */ @@ -1204,7 +1223,7 @@ static int nsolve(int c, int r, digit *grid) */ for (x = 0; x < cr; x += r) for (y = 0; y < r; y++) - if (nsolve_set(usage, cubepos(x,y,1), r*cr, 1 + if (nsolve_set(usage, scratch, cubepos(x,y,1), r*cr, 1 #ifdef STANDALONE_SOLVER , "set elimination, block (%d,%d)", 1+x/r, 1+y #endif @@ -1217,7 +1236,7 @@ static int nsolve(int c, int r, digit *grid) * Row-wise set elimination. */ for (y = 0; y < cr; y++) - if (nsolve_set(usage, cubepos(0,y,1), cr*cr, 1 + if (nsolve_set(usage, scratch, cubepos(0,y,1), cr*cr, 1 #ifdef STANDALONE_SOLVER , "set elimination, row %d", 1+YUNTRANS(y) #endif @@ -1230,7 +1249,7 @@ static int nsolve(int c, int r, digit *grid) * Column-wise set elimination. */ for (x = 0; x < cr; x++) - if (nsolve_set(usage, cubepos(x,0,1), cr, 1 + if (nsolve_set(usage, scratch, cubepos(x,0,1), cr, 1 #ifdef STANDALONE_SOLVER , "set elimination, column %d", 1+x #endif @@ -1246,6 +1265,8 @@ static int nsolve(int c, int r, digit *grid) break; } + nsolve_free_scratch(scratch); + sfree(usage->cube); sfree(usage->row); sfree(usage->col); @@ -1448,6 +1469,16 @@ static char *new_game_desc(game_params *params, random_state *rs, ai->r = r; ai->grid = snewn(cr * cr, digit); memcpy(ai->grid, grid, cr * cr * sizeof(digit)); + /* + * We might already have written *aux the last time we + * went round this loop, in which case we should free + * the old aux_info before overwriting it with the new + * one. + */ + if (*aux) { + sfree((*aux)->grid); + sfree(*aux); + } *aux = ai; } diff --git a/twiddle.c b/twiddle.c index e66bdb0..7beedc4 100644 --- a/twiddle.c +++ b/twiddle.c @@ -409,7 +409,7 @@ static char *new_game_desc(game_params *params, random_state *rs, int k; k = sprintf(buf, "%d%c", grid[i] / 4, - params->orientable ? "uldr"[grid[i] & 3] : ','); + (char)(params->orientable ? "uldr"[grid[i] & 3] : ',')); ret = sresize(ret, retlen + k + 1, char); strcpy(ret + retlen, buf); @@ -764,6 +764,7 @@ static game_drawstate *game_new_drawstate(game_state *state) static void game_free_drawstate(game_drawstate *ds) { + sfree(ds->grid); sfree(ds); } diff --git a/windows.c b/windows.c index 0a61f3c..430fff0 100644 --- a/windows.c +++ b/windows.c @@ -77,13 +77,6 @@ void debug_printf(char *fmt, ...) dputs(buf); va_end(ap); } - -#define debug(x) (debug_printf x) - -#else - -#define debug(x) - #endif struct font {