aboutsummaryrefslogtreecommitdiff
path: root/mines.c
diff options
context:
space:
mode:
Diffstat (limited to 'mines.c')
-rw-r--r--mines.c185
1 files changed, 123 insertions, 62 deletions
diff --git a/mines.c b/mines.c
index 6895b2e..4fd0e21 100644
--- a/mines.c
+++ b/mines.c
@@ -2279,46 +2279,15 @@ static void free_game(game_state *state)
sfree(state);
}
-static game_state *solve_game(game_state *state, game_state *currstate,
- game_aux_info *aux, char **error)
+static char *solve_game(game_state *state, game_state *currstate,
+ game_aux_info *aux, char **error)
{
- /*
- * Simply expose the entire grid as if it were a completed
- * solution.
- */
- game_state *ret;
- int yy, xx;
-
if (!state->layout->mines) {
- *error = "Game has not been started yet";
- return NULL;
+ *error = "Game has not been started yet";
+ return NULL;
}
- ret = dup_game(state);
- 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 = ret->just_used_solve = TRUE;
- ret->won = TRUE;
-
- return ret;
+ return dupstr("S");
}
static char *game_text_format(game_state *state)
@@ -2390,11 +2359,11 @@ struct game_drawstate {
*/
};
-static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
- int x, int y, int button)
+static char *interpret_move(game_state *from, game_ui *ui, game_drawstate *ds,
+ int x, int y, int button)
{
- game_state *ret;
int cx, cy;
+ char buf[256];
if (from->dead || from->won)
return NULL; /* no further moves permitted */
@@ -2418,7 +2387,7 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
ui->hx = cx;
ui->hy = cy;
ui->hradius = (from->grid[cy*from->w+cx] >= 0 ? 1 : 0);
- return from;
+ return "";
}
if (button == RIGHT_BUTTON) {
@@ -2436,11 +2405,8 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
from->grid[cy * from->w + cx] != -1)
return NULL;
- ret = dup_game(from);
- ret->just_used_solve = FALSE;
- ret->grid[cy * from->w + cx] ^= (-2 ^ -1);
-
- return ret;
+ sprintf(buf, "F%d,%d", cx, cy);
+ return dupstr(buf);
}
if (button == LEFT_RELEASE || button == MIDDLE_RELEASE) {
@@ -2449,10 +2415,10 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
/*
* At this stage we must never return NULL: we have adjusted
- * the ui, so at worst we return `from'.
+ * the ui, so at worst we return "".
*/
if (cx < 0 || cx >= from->w || cy < 0 || cy >= from->h)
- return from;
+ return "";
/*
* Left-clicking on a covered square opens a tile. Not
@@ -2462,12 +2428,12 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
if (button == LEFT_RELEASE &&
(from->grid[cy * from->w + cx] == -2 ||
from->grid[cy * from->w + cx] == -3)) {
- ret = dup_game(from);
- ret->just_used_solve = FALSE;
- open_square(ret, cx, cy);
- if (ret->dead)
- ui->deaths++;
- return ret;
+ /* Check if you've killed yourself. */
+ if (from->layout->mines && from->layout->mines[cy * from->w + cx])
+ ui->deaths++;
+
+ sprintf(buf, "O%d,%d", cx, cy);
+ return dupstr(buf);
}
/*
@@ -2490,8 +2456,101 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
}
if (n == from->grid[cy * from->w + cx]) {
- ret = dup_game(from);
- ret->just_used_solve = FALSE;
+
+ /*
+ * Now see if any of the squares we're clearing
+ * contains a mine (which will happen iff you've
+ * incorrectly marked the mines around the clicked
+ * square). If so, we open _just_ those squares, to
+ * reveal as little additional information as we
+ * can.
+ */
+ char *p = buf;
+ char *sep = "";
+
+ for (dy = -1; dy <= +1; dy++)
+ for (dx = -1; dx <= +1; dx++)
+ if (cx+dx >= 0 && cx+dx < from->w &&
+ cy+dy >= 0 && cy+dy < from->h) {
+ if (from->grid[(cy+dy)*from->w+(cx+dx)] != -1 &&
+ from->layout->mines &&
+ from->layout->mines[(cy+dy)*from->w+(cx+dx)]) {
+ p += sprintf(p, "%sO%d,%d", sep, cx+dx, cy+dy);
+ sep = ";";
+ }
+ }
+
+ if (p > buf) {
+ ui->deaths++;
+ } else {
+ sprintf(buf, "C%d,%d", cx, cy);
+ }
+
+ return dupstr(buf);
+ }
+ }
+
+ return "";
+ }
+
+ return NULL;
+}
+
+static game_state *execute_move(game_state *from, char *move)
+{
+ int cy, cx;
+ 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 = ret->just_used_solve = TRUE;
+ ret->won = TRUE;
+
+ return ret;
+ } else {
+ ret = dup_game(from);
+ ret->just_used_solve = FALSE;
+
+ while (*move) {
+ if (move[0] == 'F' &&
+ sscanf(move+1, "%d,%d", &cx, &cy) == 2 &&
+ cx >= 0 && cx < from->w && cy >= 0 && cy < from->h) {
+ ret->grid[cy * from->w + cx] ^= (-2 ^ -1);
+ } else if (move[0] == 'O' &&
+ sscanf(move+1, "%d,%d", &cx, &cy) == 2 &&
+ cx >= 0 && cx < from->w && cy >= 0 && cy < from->h) {
+ open_square(ret, cx, cy);
+ } else if (move[0] == 'C' &&
+ sscanf(move+1, "%d,%d", &cx, &cy) == 2 &&
+ cx >= 0 && cx < from->w && cy >= 0 && cy < from->h) {
+ int dx, dy;
+
for (dy = -1; dy <= +1; dy++)
for (dx = -1; dx <= +1; dx++)
if (cx+dx >= 0 && cx+dx < ret->w &&
@@ -2499,16 +2558,17 @@ static game_state *make_move(game_state *from, game_ui *ui, game_drawstate *ds,
(ret->grid[(cy+dy)*ret->w+(cx+dx)] == -2 ||
ret->grid[(cy+dy)*ret->w+(cx+dx)] == -3))
open_square(ret, cx+dx, cy+dy);
- if (ret->dead)
- ui->deaths++;
- return ret;
+ } else {
+ free_game(ret);
+ return NULL;
}
+
+ while (*move && *move != ';') move++;
+ if (*move) move++;
}
- return from;
+ return ret;
}
-
- return NULL;
}
/* ----------------------------------------------------------------------
@@ -2962,7 +3022,8 @@ const struct game thegame = {
new_ui,
free_ui,
game_changed_state,
- make_move,
+ interpret_move,
+ execute_move,
game_size,
game_colours,
game_new_drawstate,