rust/landgen/src/wavefront_collapse/wavefront_collapse.rs
changeset 16079 65c017453e83
parent 16075 2c2b094e6bbe
equal deleted inserted replaced
16078:e12d9a4d0e04 16079:65c017453e83
    61 
    61 
    62         let mut backtracks = 0usize;
    62         let mut backtracks = 0usize;
    63         while let Some(b) = self.collapse_step(random_numbers) {
    63         while let Some(b) = self.collapse_step(random_numbers) {
    64             backtracks += b;
    64             backtracks += b;
    65 
    65 
    66             if backtracks >= 1000 {
    66             if backtracks >= 128 {
    67                 println!("[WFC] Too much backtracking, stopping generation!");
    67                 println!("[WFC] Too much backtracking, stopping generation!");
    68                 break;
    68                 break;
    69             }
    69             }
    70         }
    70         }
    71 
    71 
   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<_>>();
   191                         if entropy < tiles_to_collapse.0 {
   191                         if entropy < tiles_to_collapse.0 {
   192                             tiles_to_collapse = (entropy, entries);
   192                             tiles_to_collapse = (entropy, entries);
   193                         } else {
   193                         } else {
   194                             tiles_to_collapse.1.extend(entries);
   194                             tiles_to_collapse.1.extend(entries);
   195                         }
   195                         }
   196 
       
   197                         //todo!("no collapse possible - what to do?")
       
   198                     }
   196                     }
   199                 }
   197                 }
   200             }
   198             }
   201         }
   199         }
   202 
   200 
   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 }