mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
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]
This commit is contained in:
12
cube.c
12
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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
4
malloc.c
4
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);
|
||||
|
87
midend.c
87
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:
|
||||
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;
|
||||
|
35
mines.c
35
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,
|
||||
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;
|
||||
|
45
net.c
45
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.
|
||||
|
33
netslide.c
33
netslide.c
@ -161,11 +161,8 @@ static game_params *default_params(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
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[] = {
|
||||
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"},
|
||||
@ -175,20 +172,24 @@ static int game_fetch_preset(int i, char **name, game_params **params)
|
||||
{5, 5, FALSE, 1.0, " easy"},
|
||||
{5, 5, FALSE, 0.0, " medium"},
|
||||
{5, 5, TRUE, 0.0, " hard"},
|
||||
};
|
||||
};
|
||||
|
||||
if (i < 0 || i >= lenof(values))
|
||||
static int game_fetch_preset(int i, char **name, game_params **params)
|
||||
{
|
||||
game_params *ret;
|
||||
char str[80];
|
||||
|
||||
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)
|
||||
|
34
pattern.c
34
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;
|
||||
}
|
||||
|
30
puzzles.h
30
puzzles.h
@ -5,6 +5,8 @@
|
||||
#ifndef PUZZLES_PUZZLES_H
|
||||
#define PUZZLES_PUZZLES_H
|
||||
|
||||
#include <stdlib.h> /* 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) \
|
||||
|
2
random.c
2
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;
|
||||
|
||||
|
32
rect.c
32
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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
67
solo.c
67
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user