Struct mapgen::map_buffer::MapBuffer
source · pub struct MapBuffer {
pub walkables: Vec<bool>,
pub tile_types: Vec<usize>,
pub width: usize,
pub height: usize,
pub starting_point: Option<Point>,
pub exit_point: Option<Point>,
pub rooms: Vec<Rect>,
pub corridors: Vec<Vec<Point>>,
}
Expand description
Map data
Fields§
§walkables: Vec<bool>
§tile_types: Vec<usize>
§width: usize
§height: usize
§starting_point: Option<Point>
§exit_point: Option<Point>
§rooms: Vec<Rect>
§corridors: Vec<Vec<Point>>
Implementations§
source§impl MapBuffer
impl MapBuffer
sourcepub fn new(width: usize, height: usize) -> MapBuffer
pub fn new(width: usize, height: usize) -> MapBuffer
Generates an empty map, consisting entirely of solid walls
Examples found in repository?
More examples
src/map_buffer.rs (line 60)
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
pub fn from_string(map_string: &str) -> MapBuffer {
let lines: Vec<&str> = map_string.split('\n')
.map(|l| l.trim())
.filter(|l| !l.is_empty())
.collect();
let cols = lines.iter().map(|l| l.len()).max().get_or_insert(1).to_owned();
let rows = lines.len();
let mut map = MapBuffer::new(cols, rows);
for i in 0..rows {
let line = lines[i].as_bytes();
for j in 0..line.len() {
if line[j] as char == ' ' {
map.set_walkable(j, i, true);
}
}
}
map
}
sourcepub fn from_string(map_string: &str) -> MapBuffer
pub fn from_string(map_string: &str) -> MapBuffer
Create map from given string
sourcepub fn is_walkable(&self, x: usize, y: usize) -> bool
pub fn is_walkable(&self, x: usize, y: usize) -> bool
Get TileType at the given location
Examples found in repository?
src/map_buffer.rs (line 84)
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
pub fn is_blocked(&self, x: usize, y: usize) -> bool {
!self.is_walkable(x, y)
}
/// Get available exists from the given tile
pub fn get_available_exits(&self, x: usize, y: usize) -> Vec<(usize, usize, f32)> {
let mut exits = Vec::new();
// Cardinal directions
if x > 0 && self.is_walkable(x-1, y) { exits.push((x-1, y, 1.0)) };
if self.is_walkable(x+1, y) { exits.push((x+1, y, 1.0)) };
if y > 0 && self.is_walkable(x, y-1) { exits.push((x, y-1, 1.0)) };
if self.is_walkable(x, y+1) { exits.push((x, y+1, 1.0)) };
// Diagonals
if x > 0 && y > 0 && self.is_walkable(x-1, y-1) { exits.push((x-1, y-1, 1.45)); }
if y > 0 && self.is_walkable(x+1, y-1) { exits.push((x+1, y-1, 1.45)); }
if x > 0 && self.is_walkable(x-1, y+1) { exits.push((x-1, y+1, 1.45)); }
if self.is_walkable(x+1, y+1) { exits.push((x+1, y+1, 1.45)); }
exits
}
More examples
src/filter/bsp_rooms.rs (line 123)
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
fn is_possible(&self, rect: Rect, map: &MapBuffer) -> bool {
let mut expanded = rect;
expanded.x1 -= 2;
expanded.x2 += 2;
expanded.y1 -= 2;
expanded.y2 += 2;
let mut can_build = true;
for r in map.rooms.iter() {
if r.intersect(&rect) { can_build = false; }
}
for y in expanded.y1 ..= expanded.y2 {
for x in expanded.x1 ..= expanded.x2 {
if x > map.width - 2 { can_build = false; }
if y > map.height - 2 { can_build = false; }
if x < 1 { can_build = false; }
if y < 1 { can_build = false; }
if can_build && map.is_walkable(x as usize, y as usize) {
can_build = false;
}
}
}
can_build
}
sourcepub fn is_blocked(&self, x: usize, y: usize) -> bool
pub fn is_blocked(&self, x: usize, y: usize) -> bool
Examples found in repository?
src/filter/cellular_automata.rs (line 68)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
fn apply_iteration(map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
for y in 1..map.height-1 {
for x in 1..map.width-1 {
let idxs = [
(x-1, y-1), (x, y-1), (x+1, y-1),
(x-1, y), (x+1, y),
(x-1, y+1), (x, y+1), (x+1, y+1)];
let neighbors = idxs.iter()
.filter(|(x, y)| map.is_blocked(*x, *y))
.count();
let walkable = neighbors < 5 && neighbors > 0;
new_map.set_walkable(x, y, walkable);
}
}
new_map
}
More examples
src/map_buffer.rs (line 168)
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
pub fn add_corridor(&mut self, from: Point, to:Point) {
let mut corridor = Vec::new();
let mut x = from.x;
let mut y = from.y;
while x != to.x || y != to.y {
if x < to.x {
x += 1;
} else if x > to.x {
x -= 1;
} else if y < to.y {
y += 1;
} else if y > to.y {
y -= 1;
}
if self.is_blocked(x, y) {
corridor.push(Point::new(x, y));
self.set_walkable(x, y, true);
}
}
}
pub fn paint(&mut self, mode: Symmetry, brush_size: usize, x: usize, y: usize) {
match mode {
Symmetry::None => self.apply_paint(brush_size, x, y),
Symmetry::Horizontal => {
let center_x = self.width / 2;
if x == center_x {
self.apply_paint(brush_size, x, y);
} else {
let dist_x = usize_abs(center_x, x);
self.apply_paint(brush_size, center_x + dist_x, y);
self.apply_paint(brush_size, center_x - dist_x, y);
}
}
Symmetry::Vertical => {
let center_y = self.height / 2;
if y == center_y {
self.apply_paint(brush_size, x, y);
} else {
let dist_y = usize_abs(center_y, y);
self.apply_paint(brush_size, x, center_y + dist_y);
self.apply_paint(brush_size, x, center_y - dist_y);
}
}
Symmetry::Both => {
let center_x = self.width / 2;
let center_y = self.height / 2;
if x == center_x && y == center_y {
self.apply_paint(brush_size, x, y);
} else {
let dist_x = usize_abs(center_x, x);
self.apply_paint(brush_size, center_x + dist_x, y);
self.apply_paint(brush_size, center_x - dist_x, y);
let dist_y = usize_abs(center_y, y);
self.apply_paint(brush_size, x, center_y + dist_y);
self.apply_paint(brush_size, x, center_y - dist_y);
}
}
}
}
fn apply_paint(&mut self, brush_size: usize, x: usize, y: usize) {
match brush_size {
1 => {
self.set_walkable(x, y, true);
}
_ => {
let half_brush_size = brush_size / 2;
for brush_y in y-half_brush_size .. y+half_brush_size {
for brush_x in x-half_brush_size .. x+half_brush_size {
if brush_x > 1 && brush_x < self.width-1 && brush_y > 1 && brush_y < self.height-1 {
self.set_walkable(brush_x, brush_y, true);
}
}
}
}
}
}
}
impl fmt::Display for MapBuffer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for y in 0..self.height {
let bytes: Vec<u8> = (0..self.width)
.map(|x| if self.is_blocked(x, y) {'#'} else {' '} as u8)
.collect();
let line = String::from_utf8(bytes).expect("Can't convert map to string");
let _ = writeln!(f, "{}", line);
}
Ok(())
}
sourcepub fn get_available_exits(&self, x: usize, y: usize) -> Vec<(usize, usize, f32)>
pub fn get_available_exits(&self, x: usize, y: usize) -> Vec<(usize, usize, f32)>
Get available exists from the given tile
Examples found in repository?
src/dijkstra.rs (line 75)
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
fn build(&mut self, map: &MapBuffer) {
let mapsize: usize = (self.size_x * self.size_y) as usize;
let mut open_list: VecDeque<((usize, usize), f32)> = VecDeque::with_capacity(mapsize);
if let Some(pos) = map.starting_point {
open_list.push_back(((pos.x, pos.y), 0.0));
let idx = self.xy_idx(pos.x, pos.y);
self.tiles[idx] = 0.0;
}
while let Some(((x, y), depth)) = open_list.pop_front() {
let exits = map.get_available_exits(x, y);
for (x, y, add_depth) in exits {
let idx = self.xy_idx(x, y);
let new_depth = depth + add_depth;
let prev_depth = self.tiles[idx];
if new_depth >= prev_depth { continue; }
if new_depth >= self.max_depth { continue; }
self.tiles[idx] = new_depth;
open_list.push_back(((x, y), new_depth));
}
}
}
sourcepub fn set_walkable(&mut self, x: usize, y: usize, set: bool)
pub fn set_walkable(&mut self, x: usize, y: usize, set: bool)
Modify tile at the given location
Examples found in repository?
src/filter/noise_generator.rs (line 57)
51 52 53 54 55 56 57 58 59 60 61 62 63
fn build(&self, map: &MapBuffer, rng: &mut StdRng) -> MapBuffer {
let mut new_map = map.clone();
let p = (self.prob * 100.0) as u32;
for y in 1..new_map.height-1 {
for x in 1..new_map.width-1 {
let roll = rng.next_u32() % 100;
if roll > p { new_map.set_walkable(x, y, true) }
else { new_map.set_walkable(x, y, false) }
}
}
new_map
}
More examples
src/filter/cellular_automata.rs (line 72)
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
fn apply_iteration(map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
for y in 1..map.height-1 {
for x in 1..map.width-1 {
let idxs = [
(x-1, y-1), (x, y-1), (x+1, y-1),
(x-1, y), (x+1, y),
(x-1, y+1), (x, y+1), (x+1, y+1)];
let neighbors = idxs.iter()
.filter(|(x, y)| map.is_blocked(*x, *y))
.count();
let walkable = neighbors < 5 && neighbors > 0;
new_map.set_walkable(x, y, walkable);
}
}
new_map
}
src/filter/maze.rs (line 210)
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
fn copy_to_map(&self, map: &mut MapBuffer) {
// Clear the map
for i in map.walkables.iter_mut() { *i = false; }
for cell in self.cells.iter() {
let x = (cell.column as usize + 1) * 2;
let y = (cell.row as usize + 1) * 2;
map.set_walkable(x, y, true);
if !cell.walls[TOP] { map.set_walkable(x, y-1, true) }
if !cell.walls[RIGHT] { map.set_walkable(x+1, y, true) }
if !cell.walls[BOTTOM] { map.set_walkable(x, y+1, true) }
if !cell.walls[LEFT] { map.set_walkable(x-1, y, true) }
}
}
src/map_buffer.rs (line 66)
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
pub fn from_string(map_string: &str) -> MapBuffer {
let lines: Vec<&str> = map_string.split('\n')
.map(|l| l.trim())
.filter(|l| !l.is_empty())
.collect();
let cols = lines.iter().map(|l| l.len()).max().get_or_insert(1).to_owned();
let rows = lines.len();
let mut map = MapBuffer::new(cols, rows);
for i in 0..rows {
let line = lines[i].as_bytes();
for j in 0..line.len() {
if line[j] as char == ' ' {
map.set_walkable(j, i, true);
}
}
}
map
}
/// Get TileType at the given location
pub fn is_walkable(&self, x: usize, y: usize) -> bool {
if x >= self.width || y >= self.height {
false
} else {
let idx = (y as usize) * self.width + (x as usize);
self.walkables[idx]
}
}
pub fn is_blocked(&self, x: usize, y: usize) -> bool {
!self.is_walkable(x, y)
}
/// Get available exists from the given tile
pub fn get_available_exits(&self, x: usize, y: usize) -> Vec<(usize, usize, f32)> {
let mut exits = Vec::new();
// Cardinal directions
if x > 0 && self.is_walkable(x-1, y) { exits.push((x-1, y, 1.0)) };
if self.is_walkable(x+1, y) { exits.push((x+1, y, 1.0)) };
if y > 0 && self.is_walkable(x, y-1) { exits.push((x, y-1, 1.0)) };
if self.is_walkable(x, y+1) { exits.push((x, y+1, 1.0)) };
// Diagonals
if x > 0 && y > 0 && self.is_walkable(x-1, y-1) { exits.push((x-1, y-1, 1.45)); }
if y > 0 && self.is_walkable(x+1, y-1) { exits.push((x+1, y-1, 1.45)); }
if x > 0 && self.is_walkable(x-1, y+1) { exits.push((x-1, y+1, 1.45)); }
if self.is_walkable(x+1, y+1) { exits.push((x+1, y+1, 1.45)); }
exits
}
// Check if given tile can be accessed
// fn is_exit_valid(&self, x:usize, y:usize) -> bool {
// !self.at(x, y).is_blocked
// }
/// Modify tile at the given location
pub fn set_walkable(&mut self, x: usize, y: usize, set: bool) {
if x < self.width && y < self.height {
let idx = self.xy_idx(x as usize, y as usize);
self.walkables[idx] = set;
}
}
// Get type type
pub fn tile_type(&self, x: usize, y: usize) -> usize {
if x >= self.width || y >= self.height {
0
} else {
let idx = (y as usize) * self.width + (x as usize);
self.tile_types[idx]
}
}
/// Modify tile at the given location
pub fn set_tile(&mut self, x: usize, y: usize, id: usize) {
if x < self.width && y < self.height {
let idx = self.xy_idx(x as usize, y as usize);
self.tile_types[idx] = id;
}
}
pub fn xy_idx(&self, x: usize, y: usize) -> usize {
y * self.width + x
}
/// Create room on the map at given location
/// Room is created by setting all tiles in the room to the Floor
pub fn add_room(&mut self, rect: Rect) {
for x in rect.x1..rect.x2 {
for y in rect.y1..rect.y2 {
self.set_walkable(x as usize, y as usize, true);
}
}
self.rooms.push(rect);
}
pub fn add_corridor(&mut self, from: Point, to:Point) {
let mut corridor = Vec::new();
let mut x = from.x;
let mut y = from.y;
while x != to.x || y != to.y {
if x < to.x {
x += 1;
} else if x > to.x {
x -= 1;
} else if y < to.y {
y += 1;
} else if y > to.y {
y -= 1;
}
if self.is_blocked(x, y) {
corridor.push(Point::new(x, y));
self.set_walkable(x, y, true);
}
}
}
pub fn paint(&mut self, mode: Symmetry, brush_size: usize, x: usize, y: usize) {
match mode {
Symmetry::None => self.apply_paint(brush_size, x, y),
Symmetry::Horizontal => {
let center_x = self.width / 2;
if x == center_x {
self.apply_paint(brush_size, x, y);
} else {
let dist_x = usize_abs(center_x, x);
self.apply_paint(brush_size, center_x + dist_x, y);
self.apply_paint(brush_size, center_x - dist_x, y);
}
}
Symmetry::Vertical => {
let center_y = self.height / 2;
if y == center_y {
self.apply_paint(brush_size, x, y);
} else {
let dist_y = usize_abs(center_y, y);
self.apply_paint(brush_size, x, center_y + dist_y);
self.apply_paint(brush_size, x, center_y - dist_y);
}
}
Symmetry::Both => {
let center_x = self.width / 2;
let center_y = self.height / 2;
if x == center_x && y == center_y {
self.apply_paint(brush_size, x, y);
} else {
let dist_x = usize_abs(center_x, x);
self.apply_paint(brush_size, center_x + dist_x, y);
self.apply_paint(brush_size, center_x - dist_x, y);
let dist_y = usize_abs(center_y, y);
self.apply_paint(brush_size, x, center_y + dist_y);
self.apply_paint(brush_size, x, center_y - dist_y);
}
}
}
}
fn apply_paint(&mut self, brush_size: usize, x: usize, y: usize) {
match brush_size {
1 => {
self.set_walkable(x, y, true);
}
_ => {
let half_brush_size = brush_size / 2;
for brush_y in y-half_brush_size .. y+half_brush_size {
for brush_x in x-half_brush_size .. x+half_brush_size {
if brush_x > 1 && brush_x < self.width-1 && brush_y > 1 && brush_y < self.height-1 {
self.set_walkable(brush_x, brush_y, true);
}
}
}
}
}
}
src/filter/voronoi.rs (line 74)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
fn build(&self, rng: &mut StdRng, map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
let seeds = self.generate_seeds(rng, map.width, map.height);
let mut voronoi_distance = vec![(0, 0.0f32) ; self.n_seeds];
let mut voronoi_membership : Vec<i32> = vec![0 ; map.width as usize * map.height as usize];
for (i, vid) in voronoi_membership.iter_mut().enumerate() {
let x = i % map.width;
let y = i / map.width;
for (seed, pos) in seeds.iter().enumerate() {
let distance = pos.distance_to(&Point::new(x, y));
voronoi_distance[seed] = (seed, distance);
}
voronoi_distance.sort_by(|a,b| a.1.partial_cmp(&b.1).unwrap());
*vid = voronoi_distance[0].0 as i32;
}
for y in 1..new_map.height-1 {
for x in 1..new_map.width-1 {
let mut neighbors = 0;
let my_idx = new_map.xy_idx(x, y);
let my_seed = voronoi_membership[my_idx];
if voronoi_membership[new_map.xy_idx(x-1, y)] != my_seed { neighbors += 1; }
if voronoi_membership[new_map.xy_idx(x+1, y)] != my_seed { neighbors += 1; }
if voronoi_membership[new_map.xy_idx(x, y-1)] != my_seed { neighbors += 1; }
if voronoi_membership[new_map.xy_idx(x, y+1)] != my_seed { neighbors += 1; }
if neighbors < 2 {
new_map.set_walkable(x, y, true);
}
}
}
new_map
}
src/filter/drunkard.rs (line 82)
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
fn build(&self, rng: &mut StdRng, map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
// Set a central starting point
let starting_position = Point::new( new_map.width / 2, new_map.height / 2 );
new_map.set_walkable(starting_position.x, starting_position.y, true);
let total_tiles = new_map.width * new_map.height;
let desired_floor_tiles = (self.floor_percent * total_tiles as f32) as usize;
let mut floor_tile_count = new_map.walkables.iter().filter(|&&a| a).count();
let mut digger_count = 0;
while floor_tile_count < desired_floor_tiles {
let mut drunk_x;
let mut drunk_y;
match self.spawn_mode {
DrunkSpawnMode::StartingPoint => {
drunk_x = starting_position.x;
drunk_y = starting_position.y;
}
DrunkSpawnMode::Random => {
if digger_count == 0 {
drunk_x = starting_position.x;
drunk_y = starting_position.y;
} else {
drunk_x = rng.roll_dice(1, new_map.width - 3) + 1;
drunk_y = rng.roll_dice(1, new_map.height - 3) + 1;
}
}
}
let mut drunk_life = self.drunken_lifetime;
while drunk_life > 0 {
new_map.set_walkable(drunk_x, drunk_y, false);
new_map.paint(self.symmetry, self.brush_size, drunk_x, drunk_y);
let stagger_direction = rng.roll_dice(1, 4);
match stagger_direction {
1 => { if drunk_x > 1 { drunk_x -= 1; } }
2 => { if drunk_x < new_map.width-2 { drunk_x += 1; } }
3 => { if drunk_y > 1 { drunk_y -=1; } }
_ => { if drunk_y < new_map.height-2 { drunk_y += 1; } }
}
drunk_life -= 1;
}
digger_count += 1;
floor_tile_count = new_map.walkables.iter().filter(|&&a| a).count();
}
new_map
}
pub fn tile_type(&self, x: usize, y: usize) -> usize
sourcepub fn xy_idx(&self, x: usize, y: usize) -> usize
pub fn xy_idx(&self, x: usize, y: usize) -> usize
Examples found in repository?
src/map_buffer.rs (line 114)
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
pub fn set_walkable(&mut self, x: usize, y: usize, set: bool) {
if x < self.width && y < self.height {
let idx = self.xy_idx(x as usize, y as usize);
self.walkables[idx] = set;
}
}
// Get type type
pub fn tile_type(&self, x: usize, y: usize) -> usize {
if x >= self.width || y >= self.height {
0
} else {
let idx = (y as usize) * self.width + (x as usize);
self.tile_types[idx]
}
}
/// Modify tile at the given location
pub fn set_tile(&mut self, x: usize, y: usize, id: usize) {
if x < self.width && y < self.height {
let idx = self.xy_idx(x as usize, y as usize);
self.tile_types[idx] = id;
}
}
More examples
src/metric.rs (line 34)
25 26 27 28 29 30 31 32 33 34 35 36 37
pub fn path_length(map: &MapBuffer) -> f32 {
if map.starting_point.is_none() {
return 0.0
}
match map.exit_point {
None => 0.0,
Some(exit) => {
let dijkstra = DijkstraMap::new(map);
dijkstra.tiles[map.xy_idx(exit.x, exit.y)]
},
}
}
src/filter/voronoi.rs (line 66)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
fn build(&self, rng: &mut StdRng, map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
let seeds = self.generate_seeds(rng, map.width, map.height);
let mut voronoi_distance = vec![(0, 0.0f32) ; self.n_seeds];
let mut voronoi_membership : Vec<i32> = vec![0 ; map.width as usize * map.height as usize];
for (i, vid) in voronoi_membership.iter_mut().enumerate() {
let x = i % map.width;
let y = i / map.width;
for (seed, pos) in seeds.iter().enumerate() {
let distance = pos.distance_to(&Point::new(x, y));
voronoi_distance[seed] = (seed, distance);
}
voronoi_distance.sort_by(|a,b| a.1.partial_cmp(&b.1).unwrap());
*vid = voronoi_distance[0].0 as i32;
}
for y in 1..new_map.height-1 {
for x in 1..new_map.width-1 {
let mut neighbors = 0;
let my_idx = new_map.xy_idx(x, y);
let my_seed = voronoi_membership[my_idx];
if voronoi_membership[new_map.xy_idx(x-1, y)] != my_seed { neighbors += 1; }
if voronoi_membership[new_map.xy_idx(x+1, y)] != my_seed { neighbors += 1; }
if voronoi_membership[new_map.xy_idx(x, y-1)] != my_seed { neighbors += 1; }
if voronoi_membership[new_map.xy_idx(x, y+1)] != my_seed { neighbors += 1; }
if neighbors < 2 {
new_map.set_walkable(x, y, true);
}
}
}
new_map
}
sourcepub fn add_room(&mut self, rect: Rect)
pub fn add_room(&mut self, rect: Rect)
Create room on the map at given location Room is created by setting all tiles in the room to the Floor
Examples found in repository?
src/filter/simple_rooms.rs (line 62)
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
fn build_rooms(&self, map: &MapBuffer, rng : &mut StdRng) -> MapBuffer {
let mut new_map = map.clone();
// Create room dimensions
for _ in 0..self.max_rooms {
let w = rng.random_range(self.min_room_size, self.max_room_size);
let h = rng.random_range(self.min_room_size, self.max_room_size);
let x = rng.random_range(1, new_map.width - w);
let y = rng.random_range(1, new_map.height - h);
let new_room = Rect::new(x, y, w, h);
let intersects = new_map.rooms.iter().any(|r| new_room.intersect(r));
if !intersects {
new_map.add_room(new_room);
}
}
new_map
}
More examples
src/filter/bsp_rooms.rs (line 59)
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
fn build_rooms(&self, map: &MapBuffer, rng : &mut StdRng) -> MapBuffer {
let mut new_map = map.clone();
// Start with a single map-sized rectangle
let mut rects = vec![Rect::new(2, 2, new_map.width-5, new_map.height-5)];
let first_room = rects[0];
rects.append(&mut self.split_into_subrects(first_room)); // Divide the first room
// Up to max_split times, we get a random rectangle and divide it. If its possible to squeeze a
// room in there, we place it and add it to the rooms list.
for _ in 0..self.max_split {
let rect = self.get_random_rect(rng, &rects);
let candidate = self.get_random_sub_rect(rect, rng);
if self.is_possible(candidate, &new_map) {
new_map.add_room(candidate);
rects.append(&mut self.split_into_subrects(rect));
}
}
new_map
}
src/filter/bsp_interior.rs (line 58)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn build(&self, rng: &mut StdRng, map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
let mut rects = vec![Rect::new(1, 1, new_map.width-2, new_map.height-2)];
let first_room = rects[0];
// Divide the first room
self.add_subrects(first_room, rng, &mut rects);
let rooms_copy = rects.clone();
for r in rooms_copy.iter() {
let room = *r;
new_map.add_room(room);
}
// Now we want corridors
for i in 0..new_map.rooms.len()-1 {
let room = new_map.rooms[i];
let next_room = new_map.rooms[i+1];
let start_x = rng.random_range(room.x1, room.x2);
let start_y = rng.random_range(room.y1, room.y2);
let end_x = rng.random_range(next_room.x1, next_room.x2);
let end_y = rng.random_range(next_room.y1, next_room.y2);
new_map.add_corridor(Point::new(start_x, start_y), Point::new(end_x, end_y));
}
new_map
}
sourcepub fn add_corridor(&mut self, from: Point, to: Point)
pub fn add_corridor(&mut self, from: Point, to: Point)
Examples found in repository?
src/filter/rooms_corridors_nearest.rs (line 41)
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
fn corridors(&self, map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
let mut connected : HashSet<usize> = HashSet::new();
for (i,room) in map.rooms.iter().enumerate() {
let mut room_distance : Vec<(usize, f32)> = Vec::new();
let room_center = room.center();
for (j,other_room) in new_map.rooms.iter().enumerate() {
if i != j && !connected.contains(&j) {
let other_center = other_room.center();
let distance = room_center.distance_to(&other_center);
room_distance.push((j, distance));
}
}
if !room_distance.is_empty() {
room_distance.sort_by(|a,b| a.1.partial_cmp(&b.1).unwrap() );
let dest_center = new_map.rooms[room_distance[0].0].center();
new_map.add_corridor(room_center, dest_center);
connected.insert(i);
}
}
new_map
}
More examples
src/filter/bsp_interior.rs (line 69)
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
fn build(&self, rng: &mut StdRng, map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
let mut rects = vec![Rect::new(1, 1, new_map.width-2, new_map.height-2)];
let first_room = rects[0];
// Divide the first room
self.add_subrects(first_room, rng, &mut rects);
let rooms_copy = rects.clone();
for r in rooms_copy.iter() {
let room = *r;
new_map.add_room(room);
}
// Now we want corridors
for i in 0..new_map.rooms.len()-1 {
let room = new_map.rooms[i];
let next_room = new_map.rooms[i+1];
let start_x = rng.random_range(room.x1, room.x2);
let start_y = rng.random_range(room.y1, room.y2);
let end_x = rng.random_range(next_room.x1, next_room.x2);
let end_y = rng.random_range(next_room.y1, next_room.y2);
new_map.add_corridor(Point::new(start_x, start_y), Point::new(end_x, end_y));
}
new_map
}
sourcepub fn paint(&mut self, mode: Symmetry, brush_size: usize, x: usize, y: usize)
pub fn paint(&mut self, mode: Symmetry, brush_size: usize, x: usize, y: usize)
Examples found in repository?
src/filter/drunkard.rs (line 110)
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
fn build(&self, rng: &mut StdRng, map: &MapBuffer) -> MapBuffer {
let mut new_map = map.clone();
// Set a central starting point
let starting_position = Point::new( new_map.width / 2, new_map.height / 2 );
new_map.set_walkable(starting_position.x, starting_position.y, true);
let total_tiles = new_map.width * new_map.height;
let desired_floor_tiles = (self.floor_percent * total_tiles as f32) as usize;
let mut floor_tile_count = new_map.walkables.iter().filter(|&&a| a).count();
let mut digger_count = 0;
while floor_tile_count < desired_floor_tiles {
let mut drunk_x;
let mut drunk_y;
match self.spawn_mode {
DrunkSpawnMode::StartingPoint => {
drunk_x = starting_position.x;
drunk_y = starting_position.y;
}
DrunkSpawnMode::Random => {
if digger_count == 0 {
drunk_x = starting_position.x;
drunk_y = starting_position.y;
} else {
drunk_x = rng.roll_dice(1, new_map.width - 3) + 1;
drunk_y = rng.roll_dice(1, new_map.height - 3) + 1;
}
}
}
let mut drunk_life = self.drunken_lifetime;
while drunk_life > 0 {
new_map.set_walkable(drunk_x, drunk_y, false);
new_map.paint(self.symmetry, self.brush_size, drunk_x, drunk_y);
let stagger_direction = rng.roll_dice(1, 4);
match stagger_direction {
1 => { if drunk_x > 1 { drunk_x -= 1; } }
2 => { if drunk_x < new_map.width-2 { drunk_x += 1; } }
3 => { if drunk_y > 1 { drunk_y -=1; } }
_ => { if drunk_y < new_map.height-2 { drunk_y += 1; } }
}
drunk_life -= 1;
}
digger_count += 1;
floor_tile_count = new_map.walkables.iter().filter(|&&a| a).count();
}
new_map
}