1use {
2 rand::{thread_rng, Rng},
3 std::{
4 hash::Hash,
5 collections::{HashMap, VecDeque},
6 sync::mpsc::{channel, Sender}
7 },
8 bitsetium::{BitSearch, BitEmpty, BitSet, BitIntersection, BitUnion, BitTestNone},
9 crate::{
10 grid_drawing::{get_brush_ranges, DRAW_LOOKUP},
11 get_bits_set_count,
12 make_one_bit_entry,
13 make_initial_probabilities,
14 errors::WfcError,
15 BitsIterator
16 }
17};
18
19struct NeighbourQueryResult {
20 north: Option<usize>,
21 south: Option<usize>,
22 east: Option<usize>,
23 west: Option<usize>,
24}
25
26pub trait WfcEntropyHeuristic<TBitSet>
28 where TBitSet:
29 BitSearch + BitEmpty + BitSet + BitIntersection +
30 BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
31 BitUnion<Output = TBitSet>
32{
33 fn choose_next_collapsed_slot(
35 &self,
36 width: usize,
37 height: usize,
38 modules: &[WfcModule<TBitSet>],
39 available_indices: &[usize]
40 ) -> usize;
41}
42
43#[derive(Default)]
47pub struct DefaultEntropyHeuristic;
48impl<TBitSet> WfcEntropyHeuristic<TBitSet> for DefaultEntropyHeuristic
49 where TBitSet:
50 BitSearch + BitEmpty + BitSet + BitIntersection +
51 BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
52 BitUnion<Output = TBitSet> {
53 fn choose_next_collapsed_slot(
54 &self,
55 _width: usize,
56 _height: usize,
57 _modules: &[WfcModule<TBitSet>],
58 available_indices: &[usize]
59 ) -> usize {
60 let mut rng = thread_rng();
61 rng.gen_range(0, available_indices.len())
62 }
63}
64
65pub trait WfcEntropyChoiceHeuristic<TBitSet>
68 where TBitSet:
69 BitSearch + BitEmpty + BitSet + BitIntersection +
70 BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
71 BitUnion<Output = TBitSet>
72{
73 fn choose_least_entropy_bit(
76 &self,
77 width: usize,
78 height: usize,
79 row: usize,
80 column: usize,
81 modules: &[WfcModule<TBitSet>],
82 slot_bits: &TBitSet,
83 ) -> Option<usize>;
84}
85
86#[derive(Default)]
90pub struct DefaultEntropyChoiceHeuristic;
91impl<TBitSet> WfcEntropyChoiceHeuristic<TBitSet> for DefaultEntropyChoiceHeuristic
92 where TBitSet:
93 BitSearch + BitEmpty + BitSet + BitIntersection +
94 BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
95 BitUnion<Output = TBitSet> {
96 fn choose_least_entropy_bit(
97 &self,
98 _width: usize,
99 _height: usize,
100 _row: usize,
101 _column: usize,
102 _modules: &[WfcModule<TBitSet>],
103 slot_bits: &TBitSet
104 ) -> Option<usize>
105 {
106 let mut rng = thread_rng();
107 let random_bit_id = rng.gen_range(0, get_bits_set_count(slot_bits));
108 let mut iterator = BitsIterator::new(slot_bits);
109 Some(iterator.nth(random_bit_id).unwrap())
110 }
111}
112
113#[derive(Copy, Clone)]
118pub struct WfcModule<TBitSet>
119 where TBitSet:
120 BitSearch + BitEmpty + BitSet + BitIntersection +
121 BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
122 BitUnion<Output = TBitSet>
123{
124 pub north_neighbours: TBitSet,
126
127 pub south_neighbours: TBitSet,
129
130 pub east_neighbours: TBitSet,
132
133 pub west_neighbours: TBitSet,
135}
136
137impl<TBitSet> WfcModule<TBitSet>
138 where TBitSet:
139 BitSearch + BitEmpty + BitSet + BitIntersection +
140 BitUnion + BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
141 BitUnion<Output = TBitSet>
142{
143 pub fn new() -> Self {
145 Self {
146 north_neighbours: TBitSet::empty(),
147 south_neighbours: TBitSet::empty(),
148 east_neighbours: TBitSet::empty(),
149 west_neighbours: TBitSet::empty(),
150 }
151 }
152
153 pub fn add_north_neighbour(&mut self, idx: usize) {
155 self.north_neighbours.set(idx)
156 }
157
158 pub fn add_south_neighbour(&mut self, idx: usize) {
160 self.south_neighbours.set(idx)
161 }
162
163 pub fn add_east_neighbour(&mut self, idx: usize) {
165 self.east_neighbours.set(idx)
166 }
167
168 pub fn add_west_neighbour(&mut self, idx: usize) {
170 self.west_neighbours.set(idx)
171 }
172}
173
174enum WfcContextBuilderExtra<'a, TBitSet>
175 where TBitSet:
176 BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion +
177 BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
178 BitUnion<Output = TBitSet>
179{
180 General,
181 UsingCustomInitializer { initializer: Box<dyn Fn(usize, usize) -> TBitSet>},
182 FromExisting { collapse: &'a [usize] }
183}
184
185pub struct WfcContextBuilder<'a, TBitSet>
187 where TBitSet:
188 BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion +
189 BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
190 BitUnion<Output = TBitSet>
191{
192 extra: WfcContextBuilderExtra<'a, TBitSet>,
193 modules: &'a [WfcModule<TBitSet>],
194 width: usize,
195 height: usize,
196 entropy_heuristic: Box<dyn WfcEntropyHeuristic<TBitSet>>,
197 entropy_choice_heuristic: Box<dyn WfcEntropyChoiceHeuristic<TBitSet>>,
198 history_transmitter: Option<Sender<(usize, TBitSet)>>
199}
200
201impl<'a, TBitSet> WfcContextBuilder<'a, TBitSet>
202 where TBitSet:
203 BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion +
204 BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
205 BitUnion<Output = TBitSet>
206{
207 pub fn new(modules: &'a [WfcModule<TBitSet>], width: usize, height: usize) -> Self {
209 Self {
210 extra: WfcContextBuilderExtra::General,
211 modules,
212 width,
213 height,
214 entropy_heuristic: Box::new(DefaultEntropyHeuristic::default()),
215 entropy_choice_heuristic: Box::new(DefaultEntropyChoiceHeuristic::default()),
216 history_transmitter: None
217 }
218 }
219
220 pub fn use_existing_collapse(self, collapse: &'a [usize]) -> Self {
224 Self {
225 extra: WfcContextBuilderExtra::FromExisting { collapse },
226 ..self
227 }
228 }
229
230 pub fn use_custom_initializer(self, initializer: Box<dyn Fn(usize, usize) -> TBitSet>) -> Self {
234 Self {
235 extra: WfcContextBuilderExtra::UsingCustomInitializer { initializer },
236 ..self
237 }
238 }
239
240 pub fn with_entropy_heuristic(
242 self,
243 heuristic: Box<dyn WfcEntropyHeuristic<TBitSet>>
244 ) -> Self {
245 Self {
246 entropy_heuristic: heuristic,
247 ..self
248 }
249 }
250
251 pub fn with_entropy_choice_heuristic(
253 self,
254 heuristic: Box<dyn WfcEntropyChoiceHeuristic<TBitSet>>
255 ) -> Self {
256 Self {
257 entropy_choice_heuristic: heuristic,
258 ..self
259 }
260 }
261
262 pub fn with_history_transmitter(
265 self,
266 history_transmitter: Sender<(usize, TBitSet)>
267 ) -> Self {
268 Self {
269 history_transmitter: Some(history_transmitter),
270 ..self
271 }
272 }
273
274 pub fn build(self) -> WfcContext<'a, TBitSet> {
276 match self.extra {
277 WfcContextBuilderExtra::General => {
278 WfcContext::new(
279 self.modules,
280 self.width,
281 self.height,
282 self.entropy_heuristic,
283 self.entropy_choice_heuristic,
284 None,
285 self.history_transmitter
286 )
287 }
288 WfcContextBuilderExtra::FromExisting { collapse } => {
289 WfcContext::from_existing_collapse(
290 self.modules,
291 self.width,
292 self.height,
293 self.entropy_heuristic,
294 self.entropy_choice_heuristic,
295 collapse,
296 self.history_transmitter
297 )
298 }
299 WfcContextBuilderExtra::UsingCustomInitializer { initializer } => {
300 WfcContext::new(
301 self.modules,
302 self.width,
303 self.height,
304 self.entropy_heuristic,
305 self.entropy_choice_heuristic,
306 Some(initializer),
307 self.history_transmitter
308 )
309 }
310 }
311 }
312}
313
314pub struct WfcContext<'a, TBitSet>
316 where TBitSet:
317 BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion +
318 BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
319 BitUnion<Output = TBitSet>
320{
321 modules: &'a [WfcModule<TBitSet>],
322 width: usize,
323 height: usize,
324 grid: Vec<TBitSet>,
325 north_memoizer: HashMap<TBitSet, TBitSet>,
326 south_memoizer: HashMap<TBitSet, TBitSet>,
327 east_memoizer: HashMap<TBitSet, TBitSet>,
328 west_memoizer: HashMap<TBitSet, TBitSet>,
329 entropy_heuristic: Box<dyn WfcEntropyHeuristic<TBitSet>>,
330 entropy_choice_heuristic: Box<dyn WfcEntropyChoiceHeuristic<TBitSet>>,
331 buckets: Vec<Vec<usize>>,
332 history_transmitter: Option<Sender<(usize, TBitSet)>>
333}
334
335macro_rules! neighbour_func_impl {
336 ($func_name:ident of $memo_name:ident and $neighbours_member:ident) => {
337 fn $func_name(&mut self, module_variants: &TBitSet) -> TBitSet {
338 self.$memo_name
339 .get(module_variants)
340 .map(|it| *it)
341 .unwrap_or_else(|| {
342 let mut set = TBitSet::empty();
343 for module_id in BitsIterator::new(module_variants) {
344 set = set.union(self.modules[module_id].$neighbours_member);
345 }
346 self.$memo_name.insert(module_variants.clone(), set);
347 set
348 })
349 }
350 }
351}
352
353impl<'a, TBitSet> WfcContext<'a, TBitSet>
354 where TBitSet:
355 BitSearch + BitEmpty + BitSet + BitIntersection + BitUnion +
356 BitTestNone + Hash + Eq + Copy + BitIntersection<Output = TBitSet> +
357 BitUnion<Output = TBitSet>
358{
359 fn new(
360 modules: &'a [WfcModule<TBitSet>],
361 width: usize,
362 height: usize,
363 entropy_heuristic: Box<dyn WfcEntropyHeuristic<TBitSet>>,
364 entropy_choice_heuristic: Box<dyn WfcEntropyChoiceHeuristic<TBitSet>>,
365 initializer: Option<Box<dyn Fn(usize, usize) -> TBitSet>>,
366 history_transmitter: Option<Sender<(usize, TBitSet)>>
367 ) -> Self {
368 let mut grid: Vec<TBitSet> = Vec::new();
369 let mut buckets: Vec<Vec<usize>> = vec![Vec::new(); modules.len()+1];
370 let initial_probabilities = make_initial_probabilities(modules.len());
371 for idx in 0..(width * height) {
372 if let Some(sender) = &history_transmitter {
373 sender.send((idx, initial_probabilities)).unwrap();
374 }
375 if let Some(init) = &initializer {
376 let row = idx / width;
377 let col = idx % width;
378 let value = init(row, col);
379 buckets[get_bits_set_count(&value)].push(idx);
380 grid.push(value);
381 } else {
382 grid.push(initial_probabilities);
383 buckets[modules.len()].push(idx);
384 }
385 }
386 Self {
387 modules,
388 width,
389 height,
390 grid,
391 north_memoizer: HashMap::new(),
392 south_memoizer: HashMap::new(),
393 east_memoizer: HashMap::new(),
394 west_memoizer: HashMap::new(),
395 entropy_heuristic,
396 entropy_choice_heuristic,
397 buckets,
398 history_transmitter
399 }
400 }
401
402 fn from_existing_collapse(
403 modules: &'a [WfcModule<TBitSet>],
404 width: usize,
405 height: usize,
406 entropy_heuristic: Box<dyn WfcEntropyHeuristic<TBitSet>>,
407 entropy_choice_heuristic: Box<dyn WfcEntropyChoiceHeuristic<TBitSet>>,
408 collapse: &[usize],
409 history_transmitter: Option<Sender<(usize, TBitSet)>>
410 ) -> Self {
411 assert_eq!(collapse.len(), width * height);
412
413 let mut grid: Vec<TBitSet> = Vec::new();
414 let mut buckets: Vec<Vec<usize>> = vec![Vec::new(); modules.len()+1];
415 for idx in 0..(width * height) {
416 buckets[1].push(idx);
417 grid.push(make_one_bit_entry(collapse[idx]));
418 }
419 Self {
420 modules,
421 width,
422 height,
423 grid,
424 north_memoizer: HashMap::new(),
425 south_memoizer: HashMap::new(),
426 east_memoizer: HashMap::new(),
427 west_memoizer: HashMap::new(),
428 entropy_heuristic,
429 entropy_choice_heuristic,
430 buckets,
431 history_transmitter
432 }
433 }
434
435 pub fn local_collapse(
443 &mut self,
444 row: usize,
445 column: usize,
446 module: usize,
447 result_transmitter: Sender<Result<Vec<usize>, WfcError>>
448 ) {
449 let old_grid = self.grid.clone();
450 let old_buckets = self.buckets.clone();
451
452 let initial_probabilities: TBitSet = make_initial_probabilities(self.modules.len());
453
454 for brush_id in 0..6 {
455 let (hor_range_dest, vert_range_dest, hor_range_source, vert_range_source) =
457 get_brush_ranges(
458 row,
459 column,
460 brush_id,
461 self.width,
462 self.height
463 );
464
465 if brush_id > 0 {
466 self.buckets = old_buckets.clone();
468 for j in vert_range_dest.clone() {
469 for i in hor_range_dest.clone() {
470 self.grid[j * self.width + i] = old_grid[j * self.width + i];
471 }
472 }
473 }
474
475 let (v_zip, h_zip) = (
476 vert_range_dest.clone().zip(vert_range_source),
477 hor_range_dest.clone().zip(hor_range_source)
478 );
479
480 let lookup = &(DRAW_LOOKUP[brush_id]);
481 for (j_dest, j_source) in v_zip.clone() {
482 for (i_dest, i_source) in h_zip.clone() {
483 if lookup[j_source * 15 + i_source] == 1 {
484 continue;
485 }
486
487 let mut probability_set = initial_probabilities;
488 let idx = j_dest * self.width + i_dest;
489
490 let neighbours = self.get_neighbours(idx);
491
492 if neighbours.north.is_some() && lookup[(j_source - 1) * 15 + i_source] == 1 {
493 let north_neighbour_slot = self.grid[neighbours.north.unwrap()];
494 probability_set = probability_set.intersection(
495 self.south_neighbours(&north_neighbour_slot)
496 );
497 }
498 if neighbours.south.is_some() && lookup[(j_source + 1) * 15 + i_source] == 1 {
499 let south_neighbour_slot = self.grid[neighbours.south.unwrap()];
500 probability_set = probability_set.intersection(
501 self.north_neighbours(&south_neighbour_slot)
502 );
503 }
504 if neighbours.east.is_some() && lookup[j_source * 15 + i_source + 1] == 1 {
505 let east_neighbour_slot = self.grid[neighbours.east.unwrap()];
506 probability_set = probability_set.intersection(
507 self.west_neighbours(&east_neighbour_slot)
508 );
509 }
510 if neighbours.west.is_some() && lookup[j_source * 15 + i_source - 1] == 1 {
511 let west_neighbour_slot = self.grid[neighbours.west.unwrap()];
512 probability_set = probability_set.intersection(
513 self.east_neighbours(&west_neighbour_slot)
514 );
515 }
516 self.set(idx, probability_set);
517 }
518 }
519 self.set_module(row, column, module);
520
521 let (tx, rc) = channel();
522
523 self.collapse(10, tx.clone());
524
525 match rc.recv() {
526 Ok(res) => {
527 if res.is_ok() {
528 result_transmitter.send(res).unwrap();
529 return;
530 }
531 }
532 Err(_) => {
533 result_transmitter.send(Err(WfcError::SomeCreepyShit)).unwrap();
534 return;
535 }
536 }
537 }
538 result_transmitter.send(Err(WfcError::TooManyContradictions)).unwrap();
539 }
540
541 fn set(&mut self, idx: usize, value: TBitSet) {
542 let old_v = self.grid[idx];
543 let old_bits_set = get_bits_set_count(&old_v);
544 let new_bits_set = get_bits_set_count(&value);
545
546 let len = self.buckets[old_bits_set].len();
547
548 for i in (0..len).rev() {
549 if self.buckets[old_bits_set][i].eq(&idx) {
550 self.buckets[old_bits_set][i] = self.buckets[old_bits_set][len-1];
551 self.buckets[old_bits_set].remove(len-1);
552 break;
553 }
554 }
555
556 self.buckets[new_bits_set].push(idx);
557 self.grid[idx] = value;
558 if let Some(sender) = &self.history_transmitter {
559 sender.send((idx, value)).unwrap();
560 }
561 }
562
563 pub fn set_module(&mut self, row: usize, column: usize, module: usize) {
565 let idx = row * self.width + column;
566 self.set(idx, make_one_bit_entry(module));
567 let mut propagation_queue: VecDeque<usize> = VecDeque::new();
568 propagation_queue.push_back(idx);
569 self.propagate(&mut propagation_queue);
570 }
571
572 pub fn collapse(
580 &mut self,
581 max_contradictions: i32,
582 result_transmitter: Sender<Result<Vec<usize>, WfcError>>
583 ) {
584 let mut contradictions_allowed = max_contradictions;
585 let old_grid = self.grid.clone();
586 let old_buckets = self.buckets.clone();
587 let mut propagation_queue: VecDeque<usize> = VecDeque::new();
588 'outer: loop {
589 'backtrack: loop {
590 if !self.buckets[0].is_empty() {
592 break 'backtrack; }
594 let mut min_bucket_id = 1;
595 'bucket_search: for i in 2_..self.buckets.len() {
596 if !self.buckets[i].is_empty() {
597 min_bucket_id = i;
598 break 'bucket_search;
599 }
600 }
601 if min_bucket_id == 1 {
602 result_transmitter.send(Ok(self.grid
603 .iter()
604 .map(|it| it.find_first_set(0).unwrap())
605 .collect()
606 )).unwrap();
607 return; }
609
610 if self.collapse_next_slot(&mut propagation_queue, min_bucket_id).is_none() {
613 break 'backtrack; }
615
616 self.propagate(&mut propagation_queue);
619 }
620
621 for i in 0..self.grid.len() {
624 self.grid[i] = old_grid[i];
625 if let Some(sender) = &self.history_transmitter {
626 sender.send((i, old_grid[i])).unwrap();
627 }
628 }
629 self.buckets = old_buckets.clone();
630 propagation_queue.clear();
631
632 if contradictions_allowed == 0 {
633 break 'outer;
634 }
635
636 contradictions_allowed -= 1;
637 }
638 result_transmitter.send(Err(WfcError::TooManyContradictions)).unwrap();
639 }
640
641 fn get_neighbours(&self, idx: usize) -> NeighbourQueryResult {
642 let row = idx / self.width;
643 let column = idx % self.width;
644 NeighbourQueryResult {
645 north: if row == 0 { None } else {Some(idx-self.width)},
646 south: if row >= self.height-1 { None } else {Some(idx+self.width)},
647 east: if column >= self.width-1 { None } else {Some(idx+1)},
648 west: if column == 0 { None } else {Some(idx-1)}
649 }
650 }
651
652 fn propagate(&mut self, mut propagation_queue: &mut VecDeque<usize>) {
653 'propagation: while !propagation_queue.is_empty() {
654 let next_id = propagation_queue.pop_front().unwrap();
655 let nbr_ids = self.get_neighbours(next_id);
656 for neighbour in &[nbr_ids.north, nbr_ids.south, nbr_ids.east, nbr_ids.west] {
657 if let &Some(neighbour_slot_id) = neighbour {
658 if get_bits_set_count(&self.grid[neighbour_slot_id]) != 1 {
659 self.propagate_slot(&mut propagation_queue, neighbour_slot_id);
660 if self.grid[neighbour_slot_id].test_none() {
661 break 'propagation;
663 }
664 }
665 }
666 }
667 }
668 }
669
670 fn propagate_slot(&mut self, propagation_queue: &mut VecDeque<usize>, neighbour_id: usize) {
671 let mut probability_set: TBitSet = make_initial_probabilities(self.modules.len());
672 let nbr_ids = self.get_neighbours(neighbour_id);
673 if let Some(west_neighbour) = nbr_ids.west {
674 let west_neighbour = self.grid[west_neighbour];
675 probability_set = probability_set.intersection(self.east_neighbours(&west_neighbour));
676 }
677 if let Some(east_neighbour) = nbr_ids.east {
678 let east_neighbour = self.grid[east_neighbour];
679 probability_set = probability_set.intersection(self.west_neighbours(&east_neighbour));
680 }
681 if let Some(north_neighbour) = nbr_ids.north {
682 let north_neighbour = self.grid[north_neighbour];
683 probability_set = probability_set.intersection(self.south_neighbours(&north_neighbour));
684 }
685 if let Some(south_neighbour) = nbr_ids.south {
686 let south_neighbour = self.grid[south_neighbour];
687 probability_set = probability_set.intersection(self.north_neighbours(&south_neighbour));
688 }
689
690 if self.grid[neighbour_id].eq(&probability_set) { return; }
691
692 self.set(neighbour_id, probability_set);
693
694 if probability_set.test_none() { return; }
695 propagation_queue.push_back(neighbour_id);
696 }
697
698 fn collapse_next_slot(
699 &mut self,
700 propagation_queue: &mut VecDeque<usize>,
701 min_bucket_id: usize
702 ) -> Option<TBitSet> {
703 let next_slot_id_in_bucket = self.entropy_heuristic.choose_next_collapsed_slot(
704 self.width,
705 self.height,
706 self.modules,
707 &self.buckets[min_bucket_id]
708 );
709 let slot_id = self.buckets[min_bucket_id][next_slot_id_in_bucket];
710 let next_bit = self.entropy_choice_heuristic.choose_least_entropy_bit(
711 self.width,
712 self.height,
713 slot_id / self.width,
714 slot_id % self.width,
715 self.modules,
716 &self.grid[slot_id]
717 )?;
718 let new_slot = make_one_bit_entry(next_bit);
719 self.grid[slot_id] = new_slot;
720 if let Some(sender) = &self.history_transmitter {
721 sender.send((slot_id, new_slot)).unwrap();
722 }
723 self.buckets[min_bucket_id].remove(next_slot_id_in_bucket);
724 self.buckets[1].push(slot_id);
725 propagation_queue.push_back(slot_id);
726 Some(new_slot)
727 }
728
729 neighbour_func_impl!{ east_neighbours of east_memoizer and east_neighbours }
730 neighbour_func_impl!{ west_neighbours of west_memoizer and west_neighbours }
731 neighbour_func_impl!{ north_neighbours of north_memoizer and north_neighbours }
732 neighbour_func_impl!{ south_neighbours of south_memoizer and south_neighbours }
733}