X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/48dcdd627698354063fa1b551cfa1917dea1b25e..171fbdaa70df511fabad11a55abf98b57a6b03cb:/mines.c diff --git a/mines.c b/mines.c index 881cad0..62af8cb 100644 --- a/mines.c +++ b/mines.c @@ -71,7 +71,7 @@ struct mine_layout { struct game_state { int w, h, n, dead, won; struct mine_layout *layout; /* real mine positions */ - char *grid; /* player knowledge */ + signed char *grid; /* player knowledge */ /* * Each item in the `grid' array is one of the following values: * @@ -255,6 +255,8 @@ static char *validate_params(game_params *params) return "Width must be greater than zero"; if (params->h <= 0) return "Height must be greater than zero"; + if (params->n > params->w * params->h - 9) + return "Too many mines for grid size"; /* * FIXME: Need more constraints here. Not sure what the @@ -558,7 +560,8 @@ static void std_add(struct squaretodo *std, int i) std->next[i] = -1; } -static void known_squares(int w, int h, struct squaretodo *std, char *grid, +static void known_squares(int w, int h, struct squaretodo *std, + signed char *grid, int (*open)(void *ctx, int x, int y), void *openctx, int x, int y, int mask, int mine) { @@ -625,9 +628,10 @@ struct perturbations { * steps were required; the exact return value is the number of * perturb calls. */ -static int minesolve(int w, int h, int n, char *grid, +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, char *grid, + struct perturbations *(*perturb)(void *ctx, + signed char *grid, int x, int y, int mask), void *ctx, random_state *rs) { @@ -1276,7 +1280,7 @@ static int minesolve(int w, int h, int n, char *grid, */ struct minectx { - char *grid; + signed char *grid; int w, h; int sx, sy; random_state *rs; @@ -1335,7 +1339,7 @@ static int squarecmp(const void *av, const void *bv) return 0; } -static struct perturbations *mineperturb(void *vctx, char *grid, +static struct perturbations *mineperturb(void *vctx, signed char *grid, int setx, int sety, int mask) { struct minectx *ctx = (struct minectx *)vctx; @@ -1655,7 +1659,7 @@ static char *minegen(int w, int h, int n, int x, int y, int unique, * We bypass this bit if we're not after a unique grid. */ if (unique) { - char *solvegrid = snewn(w*h, char); + signed char *solvegrid = snewn(w*h, char); struct minectx actx, *ctx = &actx; int solveret, prevret = -2; @@ -1801,7 +1805,7 @@ static void obfuscate_bitmap(unsigned char *bmp, int bits, int decode) static char *new_mine_layout(int w, int h, int n, int x, int y, int unique, random_state *rs, char **game_desc) { - char *grid, *ret, *p; + signed char *grid, *ret, *p; unsigned char *bmp; int i, area; @@ -1845,24 +1849,30 @@ static char *new_mine_layout(int w, int h, int n, int x, int y, int unique, } static char *new_game_desc(game_params *params, random_state *rs, - game_aux_info **aux) + game_aux_info **aux, int interactive) { -#ifdef PREOPENED - int x = random_upto(rs, params->w); - int y = random_upto(rs, params->h); - char *grid, *desc; + if (!interactive) { + /* + * For batch-generated grids, pre-open one square. + */ + int x = random_upto(rs, params->w); + int y = random_upto(rs, params->h); + signed char *grid; + char *desc; - grid = new_mine_layout(params->w, params->h, params->n, - x, y, params->unique, rs); -#else - char *rsdesc, *desc; + grid = new_mine_layout(params->w, params->h, params->n, + x, y, params->unique, rs, &desc); + sfree(grid); + return desc; + } else { + char *rsdesc, *desc; - rsdesc = random_state_encode(rs); - desc = snewn(strlen(rsdesc) + 100, char); - sprintf(desc, "r%d,%c,%s", params->n, params->unique ? 'u' : 'a', rsdesc); - sfree(rsdesc); - return desc; -#endif + rsdesc = random_state_encode(rs); + desc = snewn(strlen(rsdesc) + 100, char); + sprintf(desc, "r%d,%c,%s", params->n, params->unique ? 'u' : 'a', rsdesc); + sfree(rsdesc); + return desc; + } } static void game_free_aux_info(game_aux_info *aux) @@ -2079,6 +2089,8 @@ static game_state *new_game(midend_data *me, game_params *params, char *desc) state->layout->me = me; } else { + state->layout->rs = NULL; + state->layout->me = NULL; state->layout->mines = snewn(wh, char); x = atoi(desc); @@ -2172,7 +2184,30 @@ static game_state *solve_game(game_state *state, game_aux_info *aux, static char *game_text_format(game_state *state) { - return NULL; + char *ret; + int x, y; + + ret = snewn((state->w + 1) * state->h + 1, char); + for (y = 0; y < state->h; y++) { + for (x = 0; x < state->w; x++) { + int v = state->grid[y*state->w+x]; + if (v == 0) + v = '-'; + else if (v >= 1 && v <= 8) + v = '0' + v; + else if (v == -1) + v = '*'; + else if (v == -2 || v == -3) + v = '?'; + else if (v >= 64) + v = '!'; + ret[y * (state->w+1) + x] = v; + } + ret[y * (state->w+1) + state->w] = '\n'; + } + ret[(state->w + 1) * state->h] = '\0'; + + return ret; } struct game_ui { @@ -2306,7 +2341,7 @@ static game_state *make_move(game_state *from, game_ui *ui, int x, int y, struct game_drawstate { int w, h, started; - char *grid; + signed char *grid; /* * Items in this `grid' array have all the same values as in * the game_state grid, and in addition: @@ -2726,7 +2761,7 @@ const struct game thegame = { dup_game, free_game, FALSE, solve_game, - FALSE, game_text_format, + TRUE, game_text_format, new_ui, free_ui, make_move,