diff --git a/game.cpp b/game.cpp index 9125c034..d0ecbe42 100644 --- a/game.cpp +++ b/game.cpp @@ -7352,6 +7352,28 @@ void knightFlavorMessage(cell *c2) { msgid++; } +int mine_adjacency_rule = 0; + +vector adj_minefield_cells(cell *c) { + vector res; + if(mine_adjacency_rule == 0 || (VALENCE == 3 && DIM == 2)) + forCellCM(c2, c) res.push_back(c2); + else if(DIM == 2) { + cellwalker cw(c, 0); + cw += wstep; + cw++; + cellwalker cw1 = cw; + do { + res.push_back(cw.at); + cw += wstep; + cw++; + if(cw.cpeek() == c) cw++; + } + while(cw != cw1); + } + return res; + } + bool uncoverMines(cell *c, int lev, int dist, bool just_checking) { bool b = false; if(c->wall == waMineMine && just_checking) return true; @@ -7367,21 +7389,23 @@ bool uncoverMines(cell *c, int lev, int dist, bool just_checking) { bool minesNearby = false; bool nominesNearby = false; bool mineopens = false; + + auto adj = adj_minefield_cells(c); - forCellEx(c2, c) { + for(cell *c2: adj) { if(c2->wall == waMineMine) minesNearby = true; if(c2->wall == waMineOpen) mineopens = true; if(c2->wall == waMineUnknown && !c2->item) nominesNearby = true; } - if(lev && (nominesNearby || mineopens) && !minesNearby) for(int i=0; itype; i++) - if(c->move(i) && (c->move(i)->wall == waMineUnknown || c->move(i)->wall == waMineOpen)) { - b |= uncoverMines(c->move(i), lev-1, dist+1, just_checking); + if(lev && (nominesNearby || mineopens) && !minesNearby) for(cell *c2: adj) + if(c2->wall == waMineUnknown || c2->wall == waMineOpen) { + b |= uncoverMines(c2, lev-1, dist+1, just_checking); if(b && just_checking) return true; } if(minesNearby && !nominesNearby && dist == 0) { - forCellEx(c2, c) + for(cell *c2: adj) if(c2->wall == waMineMine && c2->land == laMinefield) c2->landparam |= 1; } diff --git a/geom-exp.cpp b/geom-exp.cpp index 65480541..3990aa47 100644 --- a/geom-exp.cpp +++ b/geom-exp.cpp @@ -695,6 +695,15 @@ void showEuclideanMenu() { }; }); } + + if(specialland == laMinefield && (DIM == 3 || VALENCE != 3)) { + dialog::addSelItem(XLAT("mine adjacency rule"), XLAT(mine_adjacency_rule ? "vertex" : DIM == 3 ? "face" : "edge"), 'M'); + dialog::add_action([] { + stop_game(); + mine_adjacency_rule = !mine_adjacency_rule; + start_game(); + }); + } dialog::addBoolItem(XLAT("pattern"), specialland == laCanvas, 'p'); if(specialland == laCanvas) dialog::lastItem().value = patterns::whichCanvas; @@ -838,6 +847,9 @@ int read_geom_args() { currfp.findsubpath(); } #endif + else if(argis("-mineadj")) { + shift(); mine_adjacency_rule = argi(); + } else if(argis("-tpar")) { torusconfig::torus_mode = torusconfig::tmSingle; shift(); sscanf(argcs(), "%d,%d,%d", diff --git a/graph.cpp b/graph.cpp index 6d4bf202..f4d11be4 100644 --- a/graph.cpp +++ b/graph.cpp @@ -2741,8 +2741,8 @@ const char* minetexts[8] = { int countMinesAround(cell *c) { int mines = 0; - for(int i=0; itype; i++) - if(c->move(i) && c->move(i)->wall == waMineMine) + for(cell *c2: adj_minefield_cells(c)) + if(c2->wall == waMineMine) mines++; return mines; } @@ -6544,10 +6544,10 @@ void drawscreen() { mines[p] = 0; cell *c = playerpos(p); if(!c) continue; - for(int i=0; itype; i++) if(c->move(i)) { - if(c->move(i)->land == laMinefield) + for(cell *c2: adj_minefield_cells(c)) { + if(c2->land == laMinefield) minefieldNearby = true; - if(c->move(i)->wall == waMineMine) { + if(c2->wall == waMineMine) { bool ep = false; if(!ep) mines[p]++, tmines++; }