--- minefield.c.2.20.1 2008-10-20 16:18:01.000000000 -0700 +++ minefield.c.mine 2008-10-20 16:22:35.000000000 -0700 @@ -126,6 +126,77 @@ guint y, guint c); /* end prototypes */ + +/* if the number of remaining neighbouring mines is exactly equal + to the number of neighbouring unmarked (unflagged and uncleared) + spaces, flag each neighbouring unmarked space as a mine. + + returns number of mines flagged +*/ +static guint pwanson_all_remaining_bombs(GtkMineField *mfield, gint x, gint y) +{ + guint i; + gint nx, ny, c2, c; + guint nunknown = 0; + guint nmines = 0; + guint nchanged = 0; + + c = cell_idx(mfield, x, y); + if (!mfield->mines[c].shown) return 0; + + for (i=0; i<8; i++) { + nx = x+neighbour_map[i].x; + ny = y+neighbour_map[i].y; + if ((c2 = cell_idx(mfield, nx, ny)) == -1) + continue; + + if (mfield->mines[c2].marked) + nmines++; + + if (!mfield->mines[c2].shown) + nunknown++; + } + + if (nmines == mfield->mines[c].neighbours) + return 0; + + if (mfield->mines[c].neighbours == nunknown) { + for (i=0; i<8; i++) { + nx = x+neighbour_map[i].x; + ny = y+neighbour_map[i].y; + if ((c2 = cell_idx(mfield, nx, ny)) == -1) + continue; + + if (!mfield->mines[c2].shown && !mfield->mines[c2].marked) { + gtk_minefield_toggle_mark(mfield, nx, ny); + gtk_mine_draw(mfield, nx, ny); + nchanged++; + } + } + } + + return nchanged; +} + +static guint pwanson_get_num_flagged(GtkMineField *mfield, gint x, gint y) +{ + guint i; + gint nx, ny, c2; + guint nflagged = 0; + + for (i=0; i<8; i++) { + nx = x+neighbour_map[i].x; + ny = y+neighbour_map[i].y; + if ((c2 = cell_idx(mfield, nx, ny)) == -1) + continue; + + if (mfield->mines[c2].marked) + nflagged++; + } + + return nflagged; +} + /* The abstraction of the coordinate system. Note that this is inline code that does no checking, use it sparsely. If in doubt, use cell_idx instead. */ @@ -650,9 +721,14 @@ for (x = x1; x <= x2; x++) { for (y = y1; y <= y2; y++) { c = cell_idx_no_checks (mfield, x, y); - if (mfield->mines[c].neighbours == 0 && mfield->mines[c].shown == 1) { - changed |= gtk_minefield_check_cell (mfield, x, y); - if (changed) { + if (mfield->mines[c].neighbours == pwanson_get_num_flagged(mfield, x, y) + && mfield->mines[c].shown == 1) { + changed += gtk_minefield_check_cell (mfield, x, y); + } + else { + changed += pwanson_all_remaining_bombs(mfield, x, y); + } + if (changed == 1) { if (x < cx1) cx1 = x; if (x > cx2) @@ -662,9 +738,12 @@ if (y > cy2) cy2 = y; } + if (changed > 1) { + cx1 = 0; cx2 = mfield->xsize; + cy1 = 0; cy2 = mfield->ysize; + } } } - } } while (changed); if (mfield->shown == mfield->xsize * mfield->ysize - mfield->mcount) {