+
+ /*
+ * 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 "";
+ }
+}
+
+static game_state *execute_move(const game_state *from, const char *move)
+{
+ int cy, cx;
+ game_state *ret;
+
+ if (!strcmp(move, "S")) {
+ int yy, xx;
+
+ ret = dup_game(from);
+ 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 {
+ ret = dup_game(from);
+
+ 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;
+