summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--Cargo.toml2
-rw-r--r--src/minesweeper.rs65
3 files changed, 51 insertions, 18 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c7c9ab0..6da7778 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1423,7 +1423,7 @@ dependencies = [
[[package]]
name = "websweeper"
-version = "1.2.0"
+version = "1.4.0"
dependencies = [
"ammonia",
"flate2",
diff --git a/Cargo.toml b/Cargo.toml
index 1693248..6bc5f57 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "websweeper"
-version = "1.3.0"
+version = "1.4.0"
authors = ["stale <stale@masba.net>"]
edition = "2021"
diff --git a/src/minesweeper.rs b/src/minesweeper.rs
index 616a6a0..9b6ac0c 100644
--- a/src/minesweeper.rs
+++ b/src/minesweeper.rs
@@ -203,30 +203,59 @@ impl Board {
(x < self.width.get() && y < self.height.get()).then(|| (x,y))
} else { None }
}
- pub fn flood_reveal(&mut self, pos: (usize,usize)) {
+ pub fn flood_reveal(&mut self, pos: (usize,usize)) -> bool {
let mut queue = vec![pos];
while let Some(pos) = queue.pop() {
- if let Some(off) = self.pos_to_off(pos) {
- let c = &mut self.data[off];
- if *c & HIDDEN_BIT > 0 {
- *c &= !(HIDDEN_BIT | FLAGGED_BIT);
- self.hidden_tiles -= 1;
- if *c > 0 { continue; }
- if let Some(mut adj) = self.neighs(pos) {
- queue.append(&mut adj);
- }
+ let off = self.pos_to_off_unchecked(pos);
+ let mut c = self.data[off];
+ if c & HIDDEN_BIT > 0 {
+ c = self.unhide_offset(off);
+ if is_mine(c) { return true; }
+ if c > 0 { continue; }
+ if let Some(mut adj) = self.neighs(pos) {
+ queue.append(&mut adj);
}
}
}
+ false
}
- pub fn reveal(mut self, pos: (usize,usize)) -> MoveResult {
+ pub fn reveal_numtile(&mut self, pos: (usize,usize)) -> bool {
if let Some(off) = self.pos_to_off(pos) {
- self.flood_reveal(pos);
- let c = self.data[off];
- MoveResult(self, (c & !(FLAGGED_BIT | CORRECT_BIT)) == TILE_NUMBITS)
- } else {
- MoveResult(self, false)
+ let count = self.data[off] as usize;
+ if 1 <= count && count <= 8 {
+ if let Some(mut neighs) = self.neighs(pos) {
+ let total_neighs = neighs.len();
+ neighs.retain(|x| self.data[self.pos_to_off_unchecked(*x)] & FLAGGED_BIT == 0);
+ if (total_neighs - neighs.len()) == count {
+ for pos in neighs.iter() {
+ if self.flood_reveal(*pos) {
+ return true;
+ }
+ }
+ }
+ }
+ }
}
+ false
+ }
+ pub fn reveal_in_place(&mut self, pos: (usize,usize)) -> bool {
+ if let Some(off) = self.pos_to_off(pos) {
+ let v = self.data[off];
+ if 1 <= v && v <= 8 {
+ self.reveal_numtile(pos)
+ } else {
+ self.flood_reveal(pos)
+ }
+ } else { false }
+ }
+ pub fn unhide_offset(&mut self, off: usize) -> u8 {
+ self.data[off] &= !(HIDDEN_BIT | FLAGGED_BIT);
+ self.hidden_tiles -= 1;
+ self.data[off]
+ }
+ pub fn reveal(mut self, pos: (usize,usize)) -> MoveResult {
+ let lost = self.reveal_in_place(pos);
+ MoveResult(self, lost)
}
pub fn grade(mut self) -> Board {
for i in &mut self.data {
@@ -300,4 +329,8 @@ fn pos_u2i(pos: (usize, usize)) -> Option<(isize, isize)> {
if let (Ok(x),Ok(y)) = (pos.0.try_into(), pos.1.try_into())
{ Some((x,y)) } else { None }
}
+pub fn is_mine(v: u8) -> bool {
+ (v & !(FLAGGED_BIT | CORRECT_BIT)) == TILE_NUMBITS
+}
+