equal
deleted
inserted
replaced
1 use integral_geometry::Size; |
1 use integral_geometry::Size; |
2 use std::collections::{HashMap, HashSet}; |
2 use std::collections::HashSet; |
3 use vec2d::Vec2D; |
3 use vec2d::Vec2D; |
4 |
4 |
5 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] |
5 #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] |
6 pub enum Tile { |
6 pub enum Tile { |
7 Empty, |
7 Empty, |
8 Outside, |
8 Outside, |
9 Numbered(u32), |
9 Numbered(usize), |
10 } |
10 } |
11 |
11 |
12 impl Tile { |
12 impl Tile { |
13 fn is(&self, i: u32) -> bool { |
13 fn is(&self, i: usize) -> bool { |
14 *self == Tile::Numbered(i) |
14 *self == Tile::Numbered(i) |
15 } |
15 } |
16 |
16 |
17 fn is_empty(&self) -> bool { |
17 fn is_empty(&self) -> bool { |
18 match self { |
18 match self { |
20 Tile::Outside => true, |
20 Tile::Outside => true, |
21 _ => false, |
21 _ => false, |
22 } |
22 } |
23 } |
23 } |
24 |
24 |
25 fn is_empty_or(&self, i: u32) -> bool { |
25 fn is_empty_or(&self, i: usize) -> bool { |
26 match self { |
26 match self { |
27 Tile::Numbered(n) => *n == i, |
27 Tile::Numbered(n) => *n == i, |
28 Tile::Empty => true, |
28 Tile::Empty => true, |
29 _ => false, |
29 _ => false, |
30 } |
30 } |
31 } |
31 } |
32 |
32 |
33 fn is_void_or(&self, i: u32) -> bool { |
33 fn is_void_or(&self, i: usize) -> bool { |
34 match self { |
34 match self { |
35 Tile::Numbered(n) => *n == i, |
35 Tile::Numbered(n) => *n == i, |
36 _ => true, |
36 _ => true, |
37 } |
37 } |
38 } |
38 } |
42 fn default() -> Self { |
42 fn default() -> Self { |
43 Tile::Outside |
43 Tile::Outside |
44 } |
44 } |
45 } |
45 } |
46 |
46 |
|
47 #[derive(Debug)] |
47 pub struct CollapseRule { |
48 pub struct CollapseRule { |
48 tile: Tile, |
49 pub tile: Tile, |
49 right: HashSet<Tile>, |
50 pub right: HashSet<Tile>, |
50 bottom: HashSet<Tile>, |
51 pub bottom: HashSet<Tile>, |
51 left: HashSet<Tile>, |
52 pub left: HashSet<Tile>, |
52 top: HashSet<Tile>, |
53 pub top: HashSet<Tile>, |
53 } |
54 } |
54 |
55 |
55 pub struct WavefrontCollapse { |
56 pub struct WavefrontCollapse { |
56 rules: Vec<CollapseRule>, |
57 rules: Vec<CollapseRule>, |
57 grid: Vec2D<Tile>, |
58 grid: Vec2D<Tile>, |
78 seed_fn(&mut self.grid); |
79 seed_fn(&mut self.grid); |
79 |
80 |
80 while self.collapse_step(random_numbers) {} |
81 while self.collapse_step(random_numbers) {} |
81 } |
82 } |
82 |
83 |
83 fn add_rule(&mut self, rule: CollapseRule) { |
84 pub fn set_rules(&mut self, rules: Vec<CollapseRule>) { |
|
85 self.rules = rules; |
|
86 } |
|
87 |
|
88 pub fn add_rule(&mut self, rule: CollapseRule) { |
84 self.rules.push(rule); |
89 self.rules.push(rule); |
85 } |
90 } |
86 |
91 |
87 fn get_tile(&self, y: usize, x: usize) -> Tile { |
92 fn get_tile(&self, y: usize, x: usize) -> Tile { |
88 self.grid.get(y, x).map(|p| *p).unwrap_or_default() |
93 self.grid.get(y, x).map(|p| *p).unwrap_or_default() |
118 } |
123 } |
119 }) |
124 }) |
120 .collect(); |
125 .collect(); |
121 |
126 |
122 let entropy = possibilities.len(); |
127 let entropy = possibilities.len(); |
123 if entropy > 0 && entropy <= tiles_to_collapse.0 { |
128 if entropy > 0 { |
124 let entry = ( |
129 if entropy <= tiles_to_collapse.0 { |
125 y, |
130 let entry = ( |
126 x, |
131 y, |
127 possibilities |
132 x, |
128 [random_numbers.next().unwrap_or_default() as usize % entropy], |
133 possibilities |
129 ); |
134 [random_numbers.next().unwrap_or_default() as usize % entropy], |
|
135 ); |
130 |
136 |
131 if entropy < tiles_to_collapse.0 { |
137 if entropy < tiles_to_collapse.0 { |
132 tiles_to_collapse = (entropy, vec![entry]) |
138 tiles_to_collapse = (entropy, vec![entry]) |
133 } else { |
139 } else { |
134 tiles_to_collapse.1.push(entry) |
140 tiles_to_collapse.1.push(entry) |
|
141 } |
135 } |
142 } |
136 } else { |
143 } else { |
137 todo!("no collapse possible") |
144 println!("We're here: {}, {}", x, y); |
|
145 println!( |
|
146 "Neighbour tiles are: {:?} {:?} {:?} {:?}", |
|
147 right_tile, bottom_tile, left_tile, top_tile |
|
148 ); |
|
149 println!("Rules are: {:?}", self.rules); |
|
150 |
|
151 todo!("no collapse possible - what to do?") |
138 } |
152 } |
139 } |
153 } |
140 } |
154 } |
141 } |
155 } |
142 |
156 |
155 true |
169 true |
156 } else { |
170 } else { |
157 false |
171 false |
158 } |
172 } |
159 } |
173 } |
|
174 |
|
175 pub fn grid(&self) -> &Vec2D<Tile> { |
|
176 &self.grid |
|
177 } |
160 } |
178 } |
161 |
179 |
162 #[cfg(test)] |
180 #[cfg(test)] |
163 mod tests { |
181 mod tests { |
164 use super::{Tile, WavefrontCollapse}; |
182 use super::{Tile, WavefrontCollapse}; |
166 use vec2d::Vec2D; |
184 use vec2d::Vec2D; |
167 |
185 |
168 #[test] |
186 #[test] |
169 fn test_wavefront_collapse() { |
187 fn test_wavefront_collapse() { |
170 let size = Size::new(4, 4); |
188 let size = Size::new(4, 4); |
171 let mut rnd = [0u32; 64].into_iter(); |
189 let mut rnd = [0u32; 64].into_iter().cycle(); |
172 let mut wfc = WavefrontCollapse::default(); |
190 let mut wfc = WavefrontCollapse::default(); |
|
191 |
|
192 wfc.generate_map(&size, |_| {}, &mut rnd); |
173 |
193 |
174 let empty_land = Vec2D::new(&size, Tile::Empty); |
194 let empty_land = Vec2D::new(&size, Tile::Empty); |
175 |
195 |
176 assert_eq!(empty_land.as_slice(), wfc.grid.as_slice()); |
196 assert_eq!(empty_land.as_slice(), wfc.grid().as_slice()); |
177 } |
197 } |
178 } |
198 } |