From c80ba7f72596437b28540f463b952e6dcbce6295 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tomas=20Wenstr=C3=B6m?= Date: Sun, 24 Jan 2021 18:57:13 +0100 Subject: [PATCH] Delete smaller wall regions and leave only one room --- src/core/game.rs | 3 +++ src/core/level.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/src/core/game.rs b/src/core/game.rs index 1bdaa8d..3e017b1 100644 --- a/src/core/game.rs +++ b/src/core/game.rs @@ -57,6 +57,9 @@ impl AppState for GameState { Event::KeyDown { keycode: Some(Keycode::KpMinus), .. } => { self.world.level.decrease_iteration(); } + Event::KeyDown { keycode: Some(Keycode::KpEnter), .. } => { + self.world.level.filter_regions(); + } _ => {} } } diff --git a/src/core/level.rs b/src/core/level.rs index bab89e0..65e74ff 100644 --- a/src/core/level.rs +++ b/src/core/level.rs @@ -34,6 +34,10 @@ impl Level { println!("iterate {} time(s)", self.iterations); } + pub fn filter_regions(&mut self) { + self.grid.filter_regions(); + } + pub fn render(&mut self, renderer: &mut Renderer, _sprites: &SpriteManager) { let w = renderer.viewport().0 as i32; @@ -189,4 +193,77 @@ impl Grid { cells } } + + fn find_regions(&self) -> Vec { + let mut regions = vec!(); + let mut marked = vec!(vec!(false; self.height); self.width); + for x in 0..self.width { + for y in 0..self.height { + if !marked[x][y] { + regions.push(self.get_region_at_point(x, y, &mut marked)); + } + } + } + regions + } + + fn get_region_at_point(&self, x: usize, y: usize, marked: &mut Vec>) -> Region { + let value = self.cells[x][y]; + let mut cells = vec!(); + let mut queue = vec!((x, y)); + marked[x][y] = true; + + while let Some(p) = queue.pop() { + cells.push(p); + for i in &[(-1, 0), (1, 0), (0, -1), (0, 1)] { + let ip = (p.0 as isize + i.0, p.1 as isize + i.1); + if ip.0 >= 0 && ip.0 < self.width as isize && ip.1 >= 0 && ip.1 < self.height as isize { + let up = (ip.0 as usize, ip.1 as usize); + if self.cells[up.0][up.1] == value && !marked[up.0][up.1] { + marked[up.0][up.1] = true; + queue.push(up); + } + } + } + } + + Region { value, cells } + } + + fn delete_region(&mut self, region: &Region) { + for c in ®ion.cells { + self.cells[c.0][c.1] = !region.value; + } + } + + pub fn filter_regions(&mut self) { + let min_wall_size = 0.0015; + println!("grid size: ({}, {}) = {} cells", self.width, self.height, self.width * self.height); + println!("min wall size: {}", (self.width * self.height) as f64 * min_wall_size); + + // delete all smaller wall regions + for r in self.find_regions().iter().filter(|r| r.value) { + let percent = r.cells.len() as f64 / (self.width * self.height) as f64; + if percent < min_wall_size { + println!("delete wall region of size {}", r.cells.len()); + self.delete_region(r); + } + } + + // delete all rooms but the largest + let regions = self.find_regions(); // check again, because if a removed room contains a removed wall, the removed wall will become a room + let mut rooms: Vec<&Region> = regions.iter().filter(|r| !r.value).collect(); + rooms.sort_by_key(|r| r.cells.len()); + rooms.reverse(); + while rooms.len() > 1 { + self.delete_region(rooms.pop().unwrap()); + } + } +} + +////////// REGION ////////////////////////////////////////////////////////////// + +struct Region { + value: bool, + cells: Vec<(usize, usize)>, } -- 2.11.0