1 use super::tile_image::{Edge, TileImage}; |
1 use super::tile_image::{Edge, EdgeSet, MatchSide, TileImage}; |
2 use super::wavefront_collapse::{CollapseRule, Tile, WavefrontCollapse}; |
2 use super::wavefront_collapse::{CollapseRule, Tile, WavefrontCollapse}; |
3 use crate::{LandGenerationParameters, LandGenerator}; |
3 use crate::{LandGenerationParameters, LandGenerator}; |
4 use integral_geometry::Size; |
4 use integral_geometry::Size; |
5 use png::Decoder; |
5 use png::Decoder; |
6 use rand::Rng; |
6 use rand::Rng; |
27 #[derive(Debug, Clone)] |
27 #[derive(Debug, Clone)] |
28 pub struct TileDescription { |
28 pub struct TileDescription { |
29 pub name: String, |
29 pub name: String, |
30 pub weight: u8, |
30 pub weight: u8, |
31 pub edges: EdgesDescription, |
31 pub edges: EdgesDescription, |
|
32 pub anti_match: Option<[u64; 4]>, |
32 pub is_negative: Option<bool>, |
33 pub is_negative: Option<bool>, |
33 pub can_flip: Option<bool>, |
34 pub can_flip: Option<bool>, |
34 pub can_mirror: Option<bool>, |
35 pub can_mirror: Option<bool>, |
35 pub can_rotate90: Option<bool>, |
36 pub can_rotate90: Option<bool>, |
36 pub can_rotate180: Option<bool>, |
37 pub can_rotate180: Option<bool>, |
128 } |
129 } |
129 } |
130 } |
130 } |
131 } |
131 } |
132 } |
132 |
133 |
133 let [top_edge, right_edge, bottom_edge, left_edge]: [Edge<String>; 4] = [ |
134 let edge_set: EdgeSet<String> = EdgeSet::new([ |
134 (&tile_description.edges.top).into(), |
135 (&tile_description.edges.top).into(), |
135 (&tile_description.edges.right).into(), |
136 (&tile_description.edges.right).into(), |
136 (&tile_description.edges.bottom).into(), |
137 (&tile_description.edges.bottom).into(), |
137 (&tile_description.edges.left).into(), |
138 (&tile_description.edges.left).into(), |
138 ]; |
139 ]); |
139 |
140 |
140 let tile = |
141 let tile = TileImage::<T, String>::new( |
141 TileImage::<T, String>::new(tiles_image, tile_description.weight, top_edge, right_edge, bottom_edge, left_edge); |
142 tiles_image, |
|
143 tile_description.weight, |
|
144 edge_set, |
|
145 tile_description.anti_match.unwrap_or_default(), |
|
146 ); |
142 |
147 |
143 result.push(tile.clone()); |
148 result.push(tile.clone()); |
144 |
149 |
145 if tile_description.can_flip.unwrap_or_default() { |
150 if tile_description.can_flip.unwrap_or_default() { |
146 result.push(tile.flipped()); |
151 result.push(tile.flipped()); |
207 let mut bottom = default_connection.clone(); |
212 let mut bottom = default_connection.clone(); |
208 let mut left = default_connection.clone(); |
213 let mut left = default_connection.clone(); |
209 let mut top = default_connection.clone(); |
214 let mut top = default_connection.clone(); |
210 |
215 |
211 let iteration = [ |
216 let iteration = [ |
212 (&grid_top_edge, tile.top_edge(), &mut top), |
217 (&grid_top_edge, tile.edge_set().top(), &mut top), |
213 (&grid_right_edge, tile.right_edge(), &mut right), |
218 (&grid_right_edge, tile.edge_set().right(), &mut right), |
214 (&grid_bottom_edge, tile.bottom_edge(), &mut bottom), |
219 (&grid_bottom_edge, tile.edge_set().bottom(), &mut bottom), |
215 (&grid_left_edge, tile.left_edge(), &mut left), |
220 (&grid_left_edge, tile.edge_set().left(), &mut left), |
216 ]; |
221 ]; |
217 |
222 |
218 // compatibility with grid edges |
223 // compatibility with grid edges |
219 for (edge, tile_edge, set) in iteration { |
224 for (edge, tile_edge, set) in iteration { |
220 for (is_compatible, tile) in edge |
225 for (is_compatible, tile) in edge |
235 } |
240 } |
236 } |
241 } |
237 } |
242 } |
238 |
243 |
239 // compatibility with itself |
244 // compatibility with itself |
240 if tile.left_edge().is_compatible(tile.right_edge()) { |
245 if tile.is_compatible(&tile, MatchSide::OnLeft) { |
241 left.insert(Tile::Numbered(i)); |
246 left.insert(Tile::Numbered(i)); |
242 right.insert(Tile::Numbered(i)); |
247 right.insert(Tile::Numbered(i)); |
243 } |
248 } |
244 |
249 |
245 if tile.top_edge().is_compatible(tile.bottom_edge()) { |
250 if tile.is_compatible(&tile, MatchSide::OnTop) { |
246 top.insert(Tile::Numbered(i)); |
251 top.insert(Tile::Numbered(i)); |
247 bottom.insert(Tile::Numbered(i)); |
252 bottom.insert(Tile::Numbered(i)); |
248 } |
253 } |
249 |
254 |
250 // compatibility with previously defined tiles |
255 // compatibility with previously defined tiles |
251 for p in 0..i { |
256 for p in 0..i { |
252 // Check left edge |
257 // Check left edge |
253 if tiles[p].left_edge().is_compatible(tile.right_edge()) { |
258 if tiles[p].is_compatible(&tile, MatchSide::OnLeft) { |
254 rules[p].left.insert(Tile::Numbered(i)); |
259 rules[p].left.insert(Tile::Numbered(i)); |
255 right.insert(Tile::Numbered(p)); |
260 right.insert(Tile::Numbered(p)); |
256 } |
261 } |
257 |
262 |
258 // Check right edge |
263 // Check right edge |
259 if tiles[p].right_edge().is_compatible(tile.left_edge()) { |
264 if tiles[p].is_compatible(&tile, MatchSide::OnRight) { |
260 rules[p].right.insert(Tile::Numbered(i)); |
265 rules[p].right.insert(Tile::Numbered(i)); |
261 left.insert(Tile::Numbered(p)); |
266 left.insert(Tile::Numbered(p)); |
262 } |
267 } |
263 |
268 |
264 // Check top edge |
269 // Check top edge |
265 if tiles[p].top_edge().is_compatible(tile.bottom_edge()) { |
270 if tiles[p].is_compatible(&tile, MatchSide::OnTop) { |
266 rules[p].top.insert(Tile::Numbered(i)); |
271 rules[p].top.insert(Tile::Numbered(i)); |
267 bottom.insert(Tile::Numbered(p)); |
272 bottom.insert(Tile::Numbered(p)); |
268 } |
273 } |
269 |
274 |
270 // Check bottom edge |
275 // Check bottom edge |
271 if tiles[p].bottom_edge().is_compatible(tile.top_edge()) { |
276 if tiles[p].is_compatible(&tile, MatchSide::OnBottom) { |
272 rules[p].bottom.insert(Tile::Numbered(i)); |
277 rules[p].bottom.insert(Tile::Numbered(i)); |
273 top.insert(Tile::Numbered(p)); |
278 top.insert(Tile::Numbered(p)); |
274 } |
279 } |
275 } |
280 } |
276 |
281 |
277 let weight = (probability_distribution_factor * 2 * i as i32 / (tiles.len() - 1) as i32 |
282 let weight = (probability_distribution_factor * 2 * i as i32 / (tiles.len() - 1) as i32 |
278 + 100 |
283 + 100 |
279 - probability_distribution_factor) as u32; |
284 - probability_distribution_factor) as u32; |
280 |
285 |
281 rules.push(CollapseRule { |
286 rules.push(CollapseRule { |
282 weight: weight * tile.weight as u32 + 1, |
287 weight: weight * tile.weight as u32, |
283 tile: Tile::Numbered(i), |
288 tile: Tile::Numbered(i), |
284 top, |
289 top, |
285 right, |
290 right, |
286 bottom, |
291 bottom, |
287 left, |
292 left, |
342 *tile.get(tile_row, tile_column).unwrap_or(¶meters.zero) |
347 *tile.get(tile_row, tile_column).unwrap_or(¶meters.zero) |
343 }, |
348 }, |
344 ); |
349 ); |
345 } |
350 } |
346 } |
351 } |
|
352 } else { |
|
353 // couldn't find a tile to place here, dump some debug info for tile set maker |
|
354 let mut edges = ["-", "|", "-", "|"].map(|s| s.to_owned()); |
|
355 |
|
356 if row > 0 { |
|
357 let tile = wfc.grid().get(row - 1, column); |
|
358 edges[0] = if let Some(Tile::Numbered(tile_index)) = tile { |
|
359 tiles[*tile_index].edge_set().bottom().name() |
|
360 } else { |
|
361 format!("{:?}", tile.unwrap()) |
|
362 } |
|
363 } |
|
364 if column < wfc_size.width as usize - 1 { |
|
365 let tile = wfc.grid().get(row, column + 1); |
|
366 edges[1] = if let Some(Tile::Numbered(tile_index)) = tile { |
|
367 tiles[*tile_index].edge_set().left().name() |
|
368 } else { |
|
369 format!("{:?}", tile.unwrap()) |
|
370 } |
|
371 } |
|
372 if row < wfc_size.height as usize - 1 { |
|
373 let tile = wfc.grid().get(row + 1, column); |
|
374 edges[2] = if let Some(Tile::Numbered(tile_index)) = tile { |
|
375 tiles[*tile_index].edge_set().top().name() |
|
376 } else { |
|
377 format!("{:?}", tile.unwrap()) |
|
378 } |
|
379 } |
|
380 if column > 0 { |
|
381 let tile = wfc.grid().get(row, column - 1); |
|
382 edges[3] = if let Some(Tile::Numbered(tile_index)) = tile { |
|
383 tiles[*tile_index].edge_set().right().name() |
|
384 } else { |
|
385 format!("{:?}", tile.unwrap()) |
|
386 } |
|
387 } |
|
388 eprintln!( |
|
389 "Couldn't find a tile to place here (row, column): ({}, {}), edges are: [{}]", |
|
390 row, column, edges.join(", "), |
|
391 ); |
347 } |
392 } |
348 } |
393 } |
349 } |
394 } |
350 |
395 |
351 result |
396 result |