Advertisement
443eb9

Untitled

Jan 16th, 2024
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 7.71 KB | None | 0 0
  1.            
  2. let mut wfc_grid = WfcGrid::from_runner(&mut runner);
  3. while wfc_grid.remaining > 0 && wfc_grid.retraced_time < wfc_grid.max_retrace_time {
  4.      wfc_grid.collapse();
  5. }
  6. wfc_grid.generate_data()
  7. // -------------
  8. pub struct WfcGrid {
  9.     mode: WfcMode,
  10.     ty: TilemapType,
  11.     area: TileArea,
  12.     rng: StdRng,
  13.     conn_rules: Vec<Vec<u128>>,
  14.     uncollapsed: HashSet<(u8, UVec2)>,
  15.     elements: HashMap<UVec2, WfcElement>,
  16.     remaining: usize,
  17.     history: Vec<Option<WfcHistory>>,
  18.     cur_hist: usize,
  19.     retrace_strength: u32,
  20.     max_retrace_factor: u32,
  21.     max_retrace_time: u32,
  22.     retraced_time: u32,
  23.     sampler: Option<Box<dyn Fn(&WfcElement, &mut StdRng) -> u8 + Send + Sync>>,
  24. }
  25.  
  26. impl WfcGrid {
  27.     pub fn from_runner(runner: &mut WfcRunner) -> Self {
  28.         let mut uncollapsed = HashSet::new();
  29.         let mut elements = HashMap::new();
  30.         let max_psbs = runner.conn_rules.len() as u8;
  31.  
  32.         for y in 0..runner.area.extent.y {
  33.             for x in 0..runner.area.extent.x {
  34.                 elements.insert(
  35.                     UVec2 { x, y },
  36.                     WfcElement {
  37.                         index: UVec2 { x, y },
  38.                         element_index: None,
  39.                         collapsed: false,
  40.                         psbs: (!0) >> (128 - max_psbs),
  41.                     },
  42.                 );
  43.  
  44.                 uncollapsed.insert((max_psbs, UVec2 { x, y }));
  45.             }
  46.         }
  47.  
  48.         WfcGrid {
  49.             mode: runner.mode.clone(),
  50.             area: runner.area,
  51.             conn_rules: runner.conn_rules.clone(),
  52.             uncollapsed,
  53.             elements,
  54.             history: vec![None; runner.max_history],
  55.             cur_hist: 0,
  56.             ty: runner.ty,
  57.             rng: match runner.seed {
  58.                 Some(seed) => StdRng::seed_from_u64(seed),
  59.                 None => StdRng::from_entropy(),
  60.             },
  61.             remaining: runner.area.size(),
  62.             retrace_strength: 1,
  63.             max_retrace_factor: runner.max_retrace_factor,
  64.             max_retrace_time: runner.max_retrace_time,
  65.             retraced_time: 0,
  66.             sampler: runner.sampler.take(),
  67.         }
  68.     }
  69.  
  70.     pub fn collapse(&mut self) {
  71.         println!("{:?}+{}", self.rng, self.remaining);
  72.         self.history[self.cur_hist] = Some(WfcHistory {
  73.             uncollapsed: self.uncollapsed.clone(),
  74.             elements: self.elements.clone(),
  75.             remaining: self.remaining,
  76.         });
  77.         self.cur_hist = (self.cur_hist + 1) % self.history.len();
  78.  
  79.         let min = self.get_min();
  80.         let elem = self.elements.get_mut(&min).unwrap();
  81.         self.uncollapsed
  82.             .remove(&(elem.psbs.count_ones() as u8, elem.index));
  83.  
  84.         let psb = match &self.mode {
  85.             WfcMode::NonWeighted => {
  86.                 let psb_vec = elem.get_psbs_vec();
  87.                 let result = self.rng.sample(Uniform::new(0, psb_vec.len()));
  88.                 println!("{}", result);
  89.                 psb_vec[result]
  90.             }
  91.             WfcMode::Weighted(w) => {
  92.                 let psb_vec = elem.get_psbs_vec();
  93.                 let weights = psb_vec.iter().map(|p| w[*p as usize]).collect::<Vec<_>>();
  94.                 psb_vec[self.rng.sample(WeightedIndex::new(weights).unwrap())]
  95.             }
  96.             WfcMode::CustomSampler => {
  97.                 let mut rng = self.rng.clone();
  98.                 let res = self.sampler.as_ref().unwrap()(&elem, &mut rng) as u8;
  99.                 self.rng = rng;
  100.                 res
  101.             }
  102.         };
  103.  
  104.         elem.element_index = Some(psb);
  105.         elem.psbs = 1 << psb;
  106.         elem.collapsed = true;
  107.         self.remaining -= 1;
  108.  
  109.         self.retrace_strength *= self.max_retrace_factor;
  110.  
  111.         let index = elem.index;
  112.         self.constrain(index);
  113.     }
  114.  
  115.     pub fn constrain(&mut self, center: UVec2) {
  116.         let mut queue = VecDeque::from([center]);
  117.         let mut spreaded = HashSet::from([center]);
  118.  
  119.         while !queue.is_empty() {
  120.             let cur_center = queue.pop_front().unwrap();
  121.             spreaded.insert(cur_center);
  122.  
  123.             let cur_elem = self.elements.get(&cur_center).cloned().unwrap();
  124.             let neis = cur_center.neighbours(self.ty, false);
  125.             let nei_count = neis.len();
  126.  
  127.             for dir in 0..nei_count {
  128.                 let Some(nei_index) = neis[dir] else {
  129.                     continue;
  130.                 };
  131.                 let Some(nei_elem) = self.elements.get_mut(&nei_index) else {
  132.                     continue;
  133.                 };
  134.                 if nei_elem.collapsed || spreaded.contains(&nei_index) {
  135.                     continue;
  136.                 }
  137.  
  138.                 let mut psb = 0;
  139.                 let psb_rec = nei_elem.psbs;
  140.                 cur_elem.get_psbs_vec().into_iter().for_each(|p| {
  141.                     psb |= self.conn_rules[p as usize][dir];
  142.                 });
  143.                 nei_elem.psbs &= psb;
  144.  
  145.                 if nei_elem.psbs.count_ones() == 0 {
  146.                     self.retrace();
  147.                     return;
  148.                 }
  149.  
  150.                 if nei_elem.psbs != psb_rec {
  151.                     queue.push_back(nei_index);
  152.                     let new_psbs = nei_elem.psbs.count_ones() as u8;
  153.                     self.update_entropy(psb_rec.count_ones() as u8, new_psbs as u8, nei_index);
  154.                 }
  155.             }
  156.         }
  157.  
  158.         self.retrace_strength = 1;
  159.     }
  160.  
  161.     pub fn update_entropy(&mut self, old: u8, new: u8, target: UVec2) {
  162.         self.uncollapsed.remove(&(old, target));
  163.         self.uncollapsed.insert((new, target));
  164.     }
  165.  
  166.     pub fn retrace(&mut self) {
  167.         let hist = {
  168.             let hist_len = self.history.len();
  169.             let strength = self.retrace_strength as usize;
  170.  
  171.             if hist_len <= strength {
  172.                 // max retrace time exceeded
  173.                 self.retraced_time = self.max_retrace_time;
  174.             } else {
  175.                 if self.cur_hist >= strength {
  176.                     self.cur_hist -= strength;
  177.                 } else {
  178.                     // need to wrap around
  179.                     let hist_to_be = hist_len - (strength - self.cur_hist);
  180.                     if self.history[hist_to_be].is_none() {
  181.                         // retrace failed
  182.                         self.retraced_time = self.max_retrace_time;
  183.                     } else {
  184.                         self.cur_hist = hist_to_be;
  185.                     }
  186.                 }
  187.             }
  188.  
  189.             // in case the cur_hist is 0
  190.             self.history[(self.cur_hist + hist_len - 1) % hist_len]
  191.                 .clone()
  192.                 .unwrap()
  193.         };
  194.  
  195.         self.remaining = hist.remaining;
  196.         self.uncollapsed = hist.uncollapsed;
  197.         self.elements = hist.elements;
  198.         self.retraced_time += self.retrace_strength;
  199.     }
  200.  
  201.     pub fn get_min(&mut self) -> UVec2 {
  202.         let mut min_entropy = u8::MAX;
  203.         let mut candidates = Vec::with_capacity(self.remaining);
  204.         self.uncollapsed.iter().for_each(|(entropy, index)| {
  205.             if entropy < &min_entropy {
  206.                 min_entropy = *entropy;
  207.                 candidates.clear();
  208.                 candidates.push(*index);
  209.             } else if entropy == &min_entropy {
  210.                 candidates.push(*index);
  211.             }
  212.         });
  213.         candidates[self.rng.sample(Uniform::new(0, candidates.len()))]
  214.     }
  215.  
  216.     pub fn generate_data(&mut self) -> Option<WfcData> {
  217.         if self.retraced_time >= self.max_retrace_time {
  218.             return None;
  219.         }
  220.  
  221.         let mut data = WfcData::new(self.area);
  222.         self.elements.drain().for_each(|(i, e)| {
  223.             data.set(i, e.element_index.unwrap());
  224.         });
  225.         Some(data)
  226.     }
  227. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement