159 |
159 |
160 let entropy = possibilities.len(); |
160 let entropy = possibilities.len(); |
161 if entropy > 0 { |
161 if entropy > 0 { |
162 if entropy <= tiles_to_collapse.0 { |
162 if entropy <= tiles_to_collapse.0 { |
163 let weights = possibilities.iter().map(|(weight, _)| weight.pow(2)); |
163 let weights = possibilities.iter().map(|(weight, _)| weight.pow(2)); |
164 let distribution = WeightedIndex::new(weights).unwrap(); |
164 |
165 |
165 let tile = if weights.clone().sum::<u32>() == 0 { |
166 let entry = |
166 possibilities |
167 (y, x, possibilities[distribution.sample(random_numbers)].1); |
167 .as_slice() |
|
168 .choose(random_numbers) |
|
169 .expect("non-empty slice") |
|
170 .1 |
|
171 } else { |
|
172 let distribution = WeightedIndex::new(weights).unwrap(); |
|
173 possibilities[distribution.sample(random_numbers)].1 |
|
174 }; |
|
175 |
|
176 let entry = (y, x, tile); |
168 |
177 |
169 if entropy < tiles_to_collapse.0 { |
178 if entropy < tiles_to_collapse.0 { |
170 tiles_to_collapse = (entropy, vec![entry]) |
179 tiles_to_collapse = (entropy, vec![entry]) |
171 } else { |
180 } else { |
172 tiles_to_collapse.1.push(entry) |
181 tiles_to_collapse.1.push(entry) |
173 } |
182 } |
174 } |
183 } |
175 } else { |
184 } else { |
176 /* |
|
177 println!("We're here: {}, {}", x, y); |
|
178 println!( |
|
179 "Neighbour tiles are: {:?} {:?} {:?} {:?}", |
|
180 right_tile, bottom_tile, left_tile, top_tile |
|
181 ); |
|
182 println!("Rules are: {:?}", self.rules); |
|
183 */ |
|
184 |
|
185 let entries = neighbors |
185 let entries = neighbors |
186 .iter() |
186 .iter() |
187 .filter(|(y, x)| self.grid.get(*y, *x).is_some()) |
187 .filter(|(y, x)| self.grid.get(*y, *x).is_some()) |
188 .map(|(y, x)| (*y, *x, Tile::Empty)) |
188 .map(|(y, x)| (*y, *x, Tile::Empty)) |
189 .collect::<Vec<_>>(); |
189 .collect::<Vec<_>>(); |
218 .get_mut(y, x) |
216 .get_mut(y, x) |
219 .expect("correct iteration over grid") = tile; |
217 .expect("correct iteration over grid") = tile; |
220 |
218 |
221 Some(0) |
219 Some(0) |
222 } else { |
220 } else { |
|
221 // all tiles are filled according to the rules |
223 None |
222 None |
224 } |
223 } |
225 } |
224 } |
226 } |
225 } |
227 |
226 |
228 pub fn grid(&self) -> &Vec2D<Tile> { |
227 pub fn grid(&self) -> &Vec2D<Tile> { |
229 &self.grid |
228 &self.grid |
230 } |
229 } |
231 } |
230 } |
232 |
|
233 #[cfg(test)] |
|
234 mod tests { |
|
235 use super::{Tile, WavefrontCollapse}; |
|
236 use integral_geometry::Size; |
|
237 use vec2d::Vec2D; |
|
238 |
|
239 #[test] |
|
240 fn test_wavefront_collapse() { |
|
241 let size = Size::new(4, 4); |
|
242 let mut rnd = [0u32; 64].into_iter().cycle(); |
|
243 let mut wfc = WavefrontCollapse::default(); |
|
244 |
|
245 wfc.generate_map(&size, |_| {}, &mut rnd); |
|
246 |
|
247 let empty_land = Vec2D::new(&size, Tile::Empty); |
|
248 |
|
249 assert_eq!(empty_land.as_slice(), wfc.grid().as_slice()); |
|
250 } |
|
251 } |
|