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§

Generates an empty map, consisting entirely of solid walls

Examples found in repository?
examples/bsp_interior.rs (line 8)
5
6
7
8
9
10
fn main() {
    let mut rng = StdRng::seed_from_u64(907647352);
    let gen = BspInterior::new();
    let map = gen.modify_map(&mut rng, &MapBuffer::new(20, 10));
    println!("{:}", &map);
}
More examples
Hide additional examples
examples/bsp_rooms.rs (line 10)
6
7
8
9
10
11
12
fn main() {
    let system_time = SystemTime::now().duration_since(UNIX_EPOCH).expect("Can't access system time");
    let mut rng = StdRng::seed_from_u64(system_time.as_millis() as u64);
    let gen = BspRooms::new();
    let map = gen.modify_map(&mut rng, &MapBuffer::new(80, 50));
    println!("{:}", &map);
}
src/lib.rs (line 83)
82
83
84
85
86
87
88
89
90
91
    pub fn build_with_rng(&mut self, rng: &mut StdRng) -> MapBuffer {
        let mut map = MapBuffer::new(self.width, self.height);
        
        // Build additional layers in turn
        for modifier in self.modifiers.iter() {
            map = modifier.modify_map(rng, &map);
        }

        map
    }
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
    }

Create map from given string

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
Hide additional 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
    }
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
Hide additional 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(())
    }

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));
            }
        }
    }

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
Hide additional 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
    }

Modify tile at the given location

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
Hide additional 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
    }

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
Hide additional 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 
    }
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
Hide additional 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 
    }
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
    }

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Returns the “default value” for a type. Read more
Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
Converts the given value to a String. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.