static game_state *new_game(midend *me, game_params *params, char *desc)
{
game_state *state = snew(game_state);
- int i, wh, x, y, ret, masked;
+ int i, wh, x, y, masked;
unsigned char *bmp;
state->w = params->w;
}
if (x >= 0 && y >= 0)
- ret = open_square(state, x, y);
+ open_square(state, x, y);
sfree(bmp);
}
int cur_x, cur_y; /* -1, -1 for no cursor displayed. */
};
-static char *interpret_move(game_state *from, game_ui *ui, game_drawstate *ds,
+static char *interpret_move(game_state *from, game_ui *ui, const game_drawstate *ds,
int x, int y, int button)
{
int cx, cy;
game_state *ret;
if (!strcmp(move, "S")) {
- /*
- * Simply expose the entire grid as if it were a completed
- * solution.
- */
int yy, xx;
ret = dup_game(from);
- for (yy = 0; yy < ret->h; yy++)
- for (xx = 0; xx < ret->w; xx++) {
-
- if (ret->layout->mines[yy*ret->w+xx]) {
- ret->grid[yy*ret->w+xx] = -1;
- } else {
- int dx, dy, v;
-
- v = 0;
-
- for (dx = -1; dx <= +1; dx++)
- for (dy = -1; dy <= +1; dy++)
- if (xx+dx >= 0 && xx+dx < ret->w &&
- yy+dy >= 0 && yy+dy < ret->h &&
- ret->layout->mines[(yy+dy)*ret->w+(xx+dx)])
- v++;
-
- ret->grid[yy*ret->w+xx] = v;
- }
- }
- ret->used_solve = TRUE;
- ret->won = TRUE;
+ if (!ret->dead) {
+ /*
+ * If the player is still alive at the moment of pressing
+ * Solve, expose the entire grid as if it were a completed
+ * solution.
+ */
+ for (yy = 0; yy < ret->h; yy++)
+ for (xx = 0; xx < ret->w; xx++) {
+
+ if (ret->layout->mines[yy*ret->w+xx]) {
+ ret->grid[yy*ret->w+xx] = -1;
+ } else {
+ int dx, dy, v;
+
+ v = 0;
+
+ for (dx = -1; dx <= +1; dx++)
+ for (dy = -1; dy <= +1; dy++)
+ if (xx+dx >= 0 && xx+dx < ret->w &&
+ yy+dy >= 0 && yy+dy < ret->h &&
+ ret->layout->mines[(yy+dy)*ret->w+(xx+dx)])
+ v++;
+
+ ret->grid[yy*ret->w+xx] = v;
+ }
+ }
+ } else {
+ /*
+ * If the player pressed Solve _after dying_, show a full
+ * corrections grid in the style of standard Minesweeper.
+ * Players who don't like Mines's behaviour on death of
+ * only showing the mine that killed you (so that in case
+ * of a typo you can undo and carry on without the rest of
+ * the grid being spoiled) can use this to get the display
+ * that ordinary Minesweeper would have given them.
+ */
+ for (yy = 0; yy < ret->h; yy++)
+ for (xx = 0; xx < ret->w; xx++) {
+ int pos = yy*ret->w+xx;
+ if ((ret->grid[pos] == -2 || ret->grid[pos] == -3) &&
+ ret->layout->mines[pos]) {
+ ret->grid[pos] = 64;
+ } else if (ret->grid[pos] == -1 &&
+ !ret->layout->mines[pos]) {
+ ret->grid[pos] = 66;
+ }
+ }
+ }
+ ret->used_solve = TRUE;
return ret;
} else {
} else if (v >= 64) {
/*
* Mark a mine.
- *
- * FIXME: this could be done better!
*/
-#if 0
- draw_text(dr, x + TILE_SIZE / 2, y + TILE_SIZE / 2,
- FONT_VARIABLE, TILE_SIZE * 7 / 8,
- ALIGN_VCENTRE | ALIGN_HCENTRE,
- COL_MINE, "*");
-#else
{
int cx = x + TILE_SIZE / 2;
int cy = y + TILE_SIZE / 2;
int r = TILE_SIZE / 2 - 3;
- int coords[4*5*2];
- int xdx = 1, xdy = 0, ydx = 0, ydy = 1;
- int tdx, tdy, i;
-
- for (i = 0; i < 4*5*2; i += 5*2) {
- coords[i+2*0+0] = cx - r/6*xdx + r*4/5*ydx;
- coords[i+2*0+1] = cy - r/6*xdy + r*4/5*ydy;
- coords[i+2*1+0] = cx - r/6*xdx + r*ydx;
- coords[i+2*1+1] = cy - r/6*xdy + r*ydy;
- coords[i+2*2+0] = cx + r/6*xdx + r*ydx;
- coords[i+2*2+1] = cy + r/6*xdy + r*ydy;
- coords[i+2*3+0] = cx + r/6*xdx + r*4/5*ydx;
- coords[i+2*3+1] = cy + r/6*xdy + r*4/5*ydy;
- coords[i+2*4+0] = cx + r*3/5*xdx + r*3/5*ydx;
- coords[i+2*4+1] = cy + r*3/5*xdy + r*3/5*ydy;
-
- tdx = ydx;
- tdy = ydy;
- ydx = xdx;
- ydy = xdy;
- xdx = -tdx;
- xdy = -tdy;
- }
-
- draw_polygon(dr, coords, 5*4, COL_MINE, COL_MINE);
+ draw_circle(dr, cx, cy, 5*r/6, COL_MINE, COL_MINE);
+ draw_rect(dr, cx - r/6, cy - r, 2*(r/6)+1, 2*r+1, COL_MINE);
+ draw_rect(dr, cx - r, cy - r/6, 2*r+1, 2*(r/6)+1, COL_MINE);
draw_rect(dr, cx-r/3, cy-r/3, r/3, r/4, COL_HIGHLIGHT);
}
-#endif
if (v == 66) {
/*
return 0.0F;
}
+static int game_status(game_state *state)
+{
+ /*
+ * We report the game as lost only if the player has used the
+ * Solve function to reveal all the mines. Otherwise, we assume
+ * they'll undo and continue play.
+ */
+ return state->won ? (state->used_solve ? -1 : +1) : 0;
+}
+
static int game_timing_state(game_state *state, game_ui *ui)
{
if (state->dead || state->won || ui->completed || !state->layout->mines)
game_redraw,
game_anim_length,
game_flash_length,
+ game_status,
FALSE, FALSE, game_print_size, game_print,
TRUE, /* wants_statusbar */
TRUE, game_timing_state,