X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=mines.c;h=57f778a168890a7532928614c8890e08ef253a3d;hb=a0a581c8b5422bf0c5ed3fde6aa25811e4eb89fc;hp=7801ab47d81f33fa97c4b4af9d2e519e60a8e3fd;hpb=6567260eb0af75a3c82f4a8a8292c6446d94fd98;p=sgt-puzzles.git diff --git a/mines.c b/mines.c index 7801ab4..57f778a 100644 --- a/mines.c +++ b/mines.c @@ -136,7 +136,7 @@ static void free_params(game_params *params) sfree(params); } -static game_params *dup_params(game_params *params) +static game_params *dup_params(const game_params *params) { game_params *ret = snew(game_params); *ret = *params; /* structure copy */ @@ -173,7 +173,7 @@ static void decode_params(game_params *params, char const *string) } } -static char *encode_params(game_params *params, int full) +static char *encode_params(const game_params *params, int full) { char ret[400]; int len; @@ -193,7 +193,7 @@ static char *encode_params(game_params *params, int full) return dupstr(ret); } -static config_item *game_configure(game_params *params) +static config_item *game_configure(const game_params *params) { config_item *ret; char buf[80]; @@ -231,7 +231,7 @@ static config_item *game_configure(game_params *params) return ret; } -static game_params *custom_params(config_item *cfg) +static game_params *custom_params(const config_item *cfg) { game_params *ret = snew(game_params); @@ -245,7 +245,7 @@ static game_params *custom_params(config_item *cfg) return ret; } -static char *validate_params(game_params *params, int full) +static char *validate_params(const game_params *params, int full) { /* * Lower limit on grid size: each dimension must be at least 3. @@ -1955,7 +1955,7 @@ static char *new_mine_layout(int w, int h, int n, int x, int y, int unique, return grid; } -static char *new_game_desc(game_params *params, random_state *rs, +static char *new_game_desc(const game_params *params, random_state *rs, char **aux, int interactive) { /* @@ -1994,7 +1994,7 @@ static char *new_game_desc(game_params *params, random_state *rs, } } -static char *validate_desc(game_params *params, char *desc) +static char *validate_desc(const game_params *params, const char *desc) { int wh = params->w * params->h; int x, y; @@ -2167,7 +2167,8 @@ static int open_square(game_state *state, int x, int y) return 0; } -static game_state *new_game(midend *me, game_params *params, char *desc) +static game_state *new_game(midend *me, const game_params *params, + const char *desc) { game_state *state = snew(game_state); int i, wh, x, y, masked; @@ -2272,7 +2273,7 @@ static game_state *new_game(midend *me, game_params *params, char *desc) return state; } -static game_state *dup_game(game_state *state) +static game_state *dup_game(const game_state *state) { game_state *ret = snew(game_state); @@ -2302,8 +2303,8 @@ static void free_game(game_state *state) sfree(state); } -static char *solve_game(game_state *state, game_state *currstate, - char *aux, char **error) +static char *solve_game(const game_state *state, const game_state *currstate, + const char *aux, char **error) { if (!state->layout->mines) { *error = "Game has not been started yet"; @@ -2313,12 +2314,12 @@ static char *solve_game(game_state *state, game_state *currstate, return dupstr("S"); } -static int game_can_format_as_text_now(game_params *params) +static int game_can_format_as_text_now(const game_params *params) { return TRUE; } -static char *game_text_format(game_state *state) +static char *game_text_format(const game_state *state) { char *ret; int x, y; @@ -2354,7 +2355,7 @@ struct game_ui { int cur_x, cur_y, cur_visible; }; -static game_ui *new_ui(game_state *state) +static game_ui *new_ui(const game_state *state) { game_ui *ui = snew(game_ui); ui->hx = ui->hy = -1; @@ -2371,7 +2372,7 @@ static void free_ui(game_ui *ui) sfree(ui); } -static char *encode_ui(game_ui *ui) +static char *encode_ui(const game_ui *ui) { char buf[80]; /* @@ -2384,7 +2385,7 @@ static char *encode_ui(game_ui *ui) return dupstr(buf); } -static void decode_ui(game_ui *ui, char *encoding) +static void decode_ui(game_ui *ui, const char *encoding) { int p= 0; sscanf(encoding, "D%d%n", &ui->deaths, &p); @@ -2392,8 +2393,8 @@ static void decode_ui(game_ui *ui, char *encoding) ui->completed = TRUE; } -static void game_changed_state(game_ui *ui, game_state *oldstate, - game_state *newstate) +static void game_changed_state(game_ui *ui, const game_state *oldstate, + const game_state *newstate) { if (newstate->won) ui->completed = TRUE; @@ -2415,8 +2416,9 @@ struct game_drawstate { int cur_x, cur_y; /* -1, -1 for no cursor displayed. */ }; -static char *interpret_move(game_state *from, game_ui *ui, game_drawstate *ds, - int x, int y, int button) +static char *interpret_move(const game_state *from, game_ui *ui, + const game_drawstate *ds, + int x, int y, int button) { int cx, cy; char buf[256]; @@ -2590,7 +2592,7 @@ uncover: } } -static game_state *execute_move(game_state *from, char *move) +static game_state *execute_move(const game_state *from, const char *move) { int cy, cx; game_state *ret; @@ -2691,8 +2693,8 @@ static game_state *execute_move(game_state *from, char *move) * Drawing routines. */ -static void game_compute_size(game_params *params, int tilesize, - int *x, int *y) +static void game_compute_size(const game_params *params, int tilesize, + int *x, int *y) { /* Ick: fake up `ds->tilesize' for macro expansion purposes */ struct { int tilesize; } ads, *ds = &ads; @@ -2703,7 +2705,7 @@ static void game_compute_size(game_params *params, int tilesize, } static void game_set_size(drawing *dr, game_drawstate *ds, - game_params *params, int tilesize) + const game_params *params, int tilesize) { ds->tilesize = tilesize; } @@ -2795,7 +2797,7 @@ static float *game_colours(frontend *fe, int *ncolours) return ret; } -static game_drawstate *game_new_drawstate(drawing *dr, game_state *state) +static game_drawstate *game_new_drawstate(drawing *dr, const game_state *state) { struct game_drawstate *ds = snew(struct game_drawstate); @@ -2953,12 +2955,13 @@ static void draw_tile(drawing *dr, game_drawstate *ds, draw_update(dr, x, y, TILE_SIZE, TILE_SIZE); } -static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, - game_state *state, int dir, game_ui *ui, - float animtime, float flashtime) +static void game_redraw(drawing *dr, game_drawstate *ds, + const game_state *oldstate, const game_state *state, + int dir, const game_ui *ui, + float animtime, float flashtime) { int x, y; - int mines, markers, bg; + int mines, markers, closed, bg; int cx = -1, cy = -1, cmoved; if (flashtime) { @@ -3008,13 +3011,15 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, /* * Now draw the tiles. Also in this loop, count up the number - * of mines and mine markers. + * of mines, mine markers, and closed squares. */ - mines = markers = 0; + mines = markers = closed = 0; for (y = 0; y < ds->h; y++) for (x = 0; x < ds->w; x++) { int v = state->grid[y*ds->w+x], cc = 0; + if (v < 0) + closed++; if (v == -1) markers++; if (state->layout->mines && state->layout->mines[y*ds->w+x]) @@ -3073,7 +3078,42 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, else sprintf(statusbar, "COMPLETED!"); } else { + int safe_closed = closed - mines; sprintf(statusbar, "Marked: %d / %d", markers, mines); + if (safe_closed > 0 && safe_closed <= 9) { + /* + * In the situation where there's a very small number + * of _non_-mine squares left unopened, it's helpful + * to mention that number in the status line, to save + * the player from having to count it up + * painstakingly. This is particularly important if + * the player has turned up the mine density to the + * point where game generation resorts to its weird + * pathological fallback of a very dense mine area + * with a clearing in the middle, because that often + * leads to a deduction you can only make by knowing + * that there is (say) exactly one non-mine square to + * find, and it's a real pain to have to count up two + * large numbers of squares and subtract them to get + * that value of 1. + * + * The threshold value of 8 for displaying this + * information is because that's the largest number of + * non-mine squares that might conceivably fit around + * a single central square, and the most likely way to + * _use_ this information is to observe that if all + * the remaining safe squares are adjacent to _this_ + * square then everything else can be immediately + * flagged as a mine. + */ + if (safe_closed == 1) { + sprintf(statusbar + strlen(statusbar), + " (1 safe square remains)"); + } else { + sprintf(statusbar + strlen(statusbar), + " (%d safe squares remain)", safe_closed); + } + } } if (ui->deaths) sprintf(statusbar + strlen(statusbar), @@ -3082,14 +3122,14 @@ static void game_redraw(drawing *dr, game_drawstate *ds, game_state *oldstate, } } -static float game_anim_length(game_state *oldstate, game_state *newstate, - int dir, game_ui *ui) +static float game_anim_length(const game_state *oldstate, + const game_state *newstate, int dir, game_ui *ui) { return 0.0F; } -static float game_flash_length(game_state *oldstate, game_state *newstate, - int dir, game_ui *ui) +static float game_flash_length(const game_state *oldstate, + const game_state *newstate, int dir, game_ui *ui) { if (oldstate->used_solve || newstate->used_solve) return 0.0F; @@ -3107,7 +3147,7 @@ static float game_flash_length(game_state *oldstate, game_state *newstate, return 0.0F; } -static int game_status(game_state *state) +static int game_status(const game_state *state) { /* * We report the game as lost only if the player has used the @@ -3117,18 +3157,18 @@ static int game_status(game_state *state) return state->won ? (state->used_solve ? -1 : +1) : 0; } -static int game_timing_state(game_state *state, game_ui *ui) +static int game_timing_state(const game_state *state, game_ui *ui) { if (state->dead || state->won || ui->completed || !state->layout->mines) return FALSE; return TRUE; } -static void game_print_size(game_params *params, float *x, float *y) +static void game_print_size(const game_params *params, float *x, float *y) { } -static void game_print(drawing *dr, game_state *state, int tilesize) +static void game_print(drawing *dr, const game_state *state, int tilesize) { } @@ -3139,7 +3179,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize) const struct game thegame = { "Mines", "games.mines", "mines", default_params, - game_fetch_preset, + game_fetch_preset, NULL, decode_params, encode_params, free_params,