wfc/
wfc.rs

1use crate::{
2    retry,
3    wrap::{Wrap, WrapXY},
4};
5use coord_2d::{Coord, Size};
6use direction::{CardinalDirection, CardinalDirectionTable, CardinalDirections};
7use grid_2d::Grid;
8use hashbrown::HashMap;
9use rand::Rng;
10use std::cmp::Ordering;
11use std::collections::BinaryHeap;
12use std::iter;
13use std::marker::PhantomData;
14use std::num::NonZeroU32;
15use std::ops::{Index, IndexMut};
16use std::slice;
17
18pub type PatternId = u32;
19
20#[derive(Default, Clone, Debug)]
21pub struct PatternTable<T> {
22    table: Vec<T>,
23}
24
25impl<T> PatternTable<T> {
26    pub fn from_vec(table: Vec<T>) -> Self {
27        Self { table }
28    }
29    pub fn len(&self) -> usize {
30        self.table.len()
31    }
32    pub fn drain(&mut self) -> ::std::vec::Drain<T> {
33        self.table.drain(..)
34    }
35    pub fn iter(&self) -> slice::Iter<T> {
36        self.table.iter()
37    }
38    pub fn iter_mut(&mut self) -> slice::IterMut<T> {
39        self.table.iter_mut()
40    }
41    pub fn enumerate(&self) -> impl Iterator<Item = (PatternId, &T)> {
42        self.iter()
43            .enumerate()
44            .map(|(index, item)| (index as PatternId, item))
45    }
46    pub fn enumerate_mut(&mut self) -> impl Iterator<Item = (PatternId, &mut T)> {
47        self.iter_mut()
48            .enumerate()
49            .map(|(index, item)| (index as PatternId, item))
50    }
51}
52impl<T: Clone> PatternTable<T> {
53    fn resize(&mut self, size: usize, value: T) {
54        self.table.resize(size, value);
55    }
56}
57
58impl<T> iter::FromIterator<T> for PatternTable<T> {
59    fn from_iter<I>(iter: I) -> Self
60    where
61        I: IntoIterator<Item = T>,
62    {
63        Self {
64            table: Vec::from_iter(iter),
65        }
66    }
67}
68
69impl<T> Index<PatternId> for PatternTable<T> {
70    type Output = T;
71    fn index(&self, index: PatternId) -> &Self::Output {
72        self.table.index(index as usize)
73    }
74}
75
76impl<T> IndexMut<PatternId> for PatternTable<T> {
77    fn index_mut(&mut self, index: PatternId) -> &mut Self::Output {
78        self.table.index_mut(index as usize)
79    }
80}
81
82#[derive(Clone)]
83pub struct PatternWeight {
84    weight: NonZeroU32,
85    weight_log_weight: f32,
86}
87
88impl PatternWeight {
89    pub fn new(weight: NonZeroU32) -> Self {
90        Self {
91            weight,
92            weight_log_weight: (weight.get() as f32) * (weight.get() as f32).log2(),
93        }
94    }
95    pub fn weight(&self) -> u32 {
96        self.weight.get()
97    }
98    pub fn weight_log_weight(&self) -> f32 {
99        self.weight_log_weight
100    }
101}
102
103#[derive(Clone)]
104pub struct GlobalStats {
105    pattern_weights: PatternTable<Option<PatternWeight>>,
106    compatibility_per_pattern: PatternTable<CardinalDirectionTable<Vec<PatternId>>>,
107    num_weighted_patterns: u32,
108    sum_pattern_weight: u32,
109    sum_pattern_weight_log_weight: f32,
110}
111
112struct NumWaysToBecomeEachPatternByDirection<'a> {
113    iter: slice::Iter<'a, CardinalDirectionTable<Vec<PatternId>>>,
114}
115
116impl<'a> Iterator for NumWaysToBecomeEachPatternByDirection<'a> {
117    type Item = CardinalDirectionTable<u32>;
118    fn next(&mut self) -> Option<Self::Item> {
119        self.iter.next().map(|compatible_patterns_by_direction| {
120            let mut num_ways_to_become_pattern_from_direction =
121                CardinalDirectionTable::default();
122            for direction in CardinalDirections {
123                num_ways_to_become_pattern_from_direction[direction] =
124                    compatible_patterns_by_direction
125                        .get(direction.opposite())
126                        .len() as u32;
127            }
128
129            num_ways_to_become_pattern_from_direction
130        })
131    }
132}
133
134pub struct PatternDescription {
135    pub weight: Option<NonZeroU32>,
136    pub allowed_neighbours: CardinalDirectionTable<Vec<PatternId>>,
137}
138
139impl PatternDescription {
140    pub fn new(
141        weight: Option<NonZeroU32>,
142        allowed_neighbours: CardinalDirectionTable<Vec<PatternId>>,
143    ) -> Self {
144        Self {
145            weight,
146            allowed_neighbours,
147        }
148    }
149}
150
151struct OptionSliceIter<'a, T> {
152    iter: slice::Iter<'a, Option<T>>,
153}
154
155impl<'a, T> Iterator for OptionSliceIter<'a, T> {
156    type Item = Option<&'a T>;
157    fn next(&mut self) -> Option<Self::Item> {
158        self.iter.next().map(|o| o.as_ref())
159    }
160}
161
162impl GlobalStats {
163    pub fn new(mut pattern_descriptions: PatternTable<PatternDescription>) -> Self {
164        let pattern_weights = pattern_descriptions
165            .iter()
166            .map(|desc| desc.weight.map(PatternWeight::new))
167            .collect::<PatternTable<_>>();
168        let compatibility_per_pattern = pattern_descriptions
169            .drain()
170            .map(|desc| desc.allowed_neighbours)
171            .collect::<PatternTable<_>>();
172        let num_weighted_patterns =
173            pattern_weights.iter().filter(|p| p.is_some()).count() as u32;
174        let sum_pattern_weight = pattern_weights
175            .iter()
176            .filter_map(|p| p.as_ref().map(|p| p.weight()))
177            .sum();
178        let sum_pattern_weight_log_weight = pattern_weights
179            .iter()
180            .filter_map(|p| p.as_ref().map(|p| p.weight_log_weight()))
181            .sum();
182        Self {
183            pattern_weights,
184            compatibility_per_pattern,
185            num_weighted_patterns,
186            sum_pattern_weight,
187            sum_pattern_weight_log_weight,
188        }
189    }
190    fn num_weighted_patterns(&self) -> u32 {
191        self.num_weighted_patterns
192    }
193    fn sum_pattern_weight(&self) -> u32 {
194        self.sum_pattern_weight
195    }
196    fn sum_pattern_weight_log_weight(&self) -> f32 {
197        self.sum_pattern_weight_log_weight
198    }
199    fn num_patterns(&self) -> usize {
200        self.pattern_weights.len()
201    }
202    fn pattern_stats(&self, pattern_id: PatternId) -> Option<&PatternWeight> {
203        self.pattern_weights[pattern_id].as_ref()
204    }
205    fn pattern_stats_option_iter(&self) -> OptionSliceIter<PatternWeight> {
206        OptionSliceIter {
207            iter: self.pattern_weights.iter(),
208        }
209    }
210    fn compatible_patterns_in_direction(
211        &self,
212        pattern_id: PatternId,
213        direction: CardinalDirection,
214    ) -> impl Iterator<Item = &PatternId> {
215        self.compatibility_per_pattern[pattern_id]
216            .get(direction)
217            .iter()
218    }
219    fn compatible_patterns_by_direction(
220        &self,
221    ) -> slice::Iter<CardinalDirectionTable<Vec<PatternId>>> {
222        self.compatibility_per_pattern.iter()
223    }
224    fn num_ways_to_become_each_pattern_by_direction(
225        &self,
226    ) -> NumWaysToBecomeEachPatternByDirection {
227        NumWaysToBecomeEachPatternByDirection {
228            iter: self.compatible_patterns_by_direction(),
229        }
230    }
231}
232
233#[derive(Default, Debug, Clone)]
234struct WaveCellStats {
235    num_weighted_compatible_patterns: u32,
236    // n0 + n1 + n2 + ...
237    sum_compatible_pattern_weight: u32,
238    // n0*log(n0) + n1*log(n1) + n2*log(n2) + ...
239    sum_compatible_pattern_weight_log_weight: f32,
240}
241
242impl WaveCellStats {
243    fn remove_compatible_pattern(&mut self, pattern_stats: &PatternWeight) {
244        assert!(self.num_weighted_compatible_patterns >= 1);
245        assert!(self.sum_compatible_pattern_weight >= pattern_stats.weight());
246
247        self.num_weighted_compatible_patterns -= 1;
248        self.sum_compatible_pattern_weight -= pattern_stats.weight();
249        self.sum_compatible_pattern_weight_log_weight -=
250            pattern_stats.weight_log_weight();
251    }
252    fn entropy(&self) -> f32 {
253        assert!(self.sum_compatible_pattern_weight > 0);
254
255        // log(n0+n1+n2+...) - (n0*log(n0) + n1*log(n1) + n2*log(n2) + ...) / (n0+n1+n2+...)
256        let sum_compatible_pattern_weight = self.sum_compatible_pattern_weight as f32;
257        sum_compatible_pattern_weight.log2()
258            - (self.sum_compatible_pattern_weight_log_weight
259                / sum_compatible_pattern_weight)
260    }
261}
262
263#[derive(Default, Clone, Debug)]
264struct NumWaysToBecomePattern {
265    direction_table: CardinalDirectionTable<u32>,
266}
267
268struct DecrementedToZero;
269
270impl NumWaysToBecomePattern {
271    const ZERO_CARDINAL_DIRECTION_TABLE: CardinalDirectionTable<u32> =
272        CardinalDirectionTable::new_array([0, 0, 0, 0]);
273    fn new(direction_table: CardinalDirectionTable<u32>) -> Self {
274        if direction_table.iter().any(|&count| count == 0) {
275            Self {
276                direction_table: Self::ZERO_CARDINAL_DIRECTION_TABLE,
277            }
278        } else {
279            Self { direction_table }
280        }
281    }
282    fn is_zero(&self) -> bool {
283        // if any element is 0, all elements must be 0, so it's sufficient to
284        // test a single element
285        assert!(
286            *self.direction_table.get(CardinalDirection::North) != 0
287                || self.direction_table == Self::ZERO_CARDINAL_DIRECTION_TABLE
288        );
289        *self.direction_table.get(CardinalDirection::North) == 0
290    }
291    fn clear_all_directions(&mut self) {
292        self.direction_table = Self::ZERO_CARDINAL_DIRECTION_TABLE;
293    }
294    fn try_decrement(
295        &mut self,
296        direction: CardinalDirection,
297    ) -> Option<DecrementedToZero> {
298        {
299            let count = self.direction_table.get_mut(direction);
300            if *count == 0 {
301                return None;
302            }
303            if *count != 1 {
304                *count -= 1;
305                return None;
306            }
307        }
308        self.clear_all_directions();
309        Some(DecrementedToZero)
310    }
311}
312
313#[derive(Default, Debug, Clone)]
314pub struct WaveCell {
315    // random value to break entropy ties
316    noise: u32,
317    num_compatible_patterns: u32,
318    stats: WaveCellStats,
319    // Keep track of the number of ways each neighbour could be assigned a pattern to allow this
320    // cell to be each pattern. This doubles as a way of keeping track of which patterns are
321    // compatible with this cell.
322    num_ways_to_become_each_pattern: PatternTable<NumWaysToBecomePattern>,
323}
324
325enum DecrementNumWaysToBecomePattern {
326    NoPatternRemoved,
327    RemovedNonWeightedPattern,
328    RemovedFinalCompatiblePattern,
329    RemovedFinalWeightedCompatiblePattern,
330    Finalized,
331    RemovedWeightedPatternMultipleCandidatesRemain,
332}
333
334#[derive(PartialEq, Debug, Clone, Copy)]
335struct EntropyWithNoise {
336    entropy: f32,
337    noise: u32,
338    // Record this field of WaveCellStats at the time of creating this entry.  This value will be
339    // different from the cell's value when retrieved from the heap if and only if the cell's
340    // entropy has changed. Storing this saves us from having to re-compute the cell's entropy to
341    // compare it to the stored entropy.
342    num_weighted_compatible_patterns: u32,
343}
344
345impl Eq for EntropyWithNoise {}
346
347impl PartialOrd for EntropyWithNoise {
348    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
349        match self.entropy.partial_cmp(&other.entropy) {
350            Some(Ordering::Equal) => self.noise.partial_cmp(&other.noise),
351            other_ordering => other_ordering,
352        }
353    }
354}
355
356#[derive(Debug)]
357pub enum ChosenPatternIdError {
358    NoCompatiblePatterns,
359    MultipleCompatiblePatterns,
360}
361
362impl WaveCell {
363    pub fn chosen_pattern_id(&self) -> Result<PatternId, ChosenPatternIdError> {
364        if self.num_compatible_patterns == 1 {
365            let pattern_id = self
366                .num_ways_to_become_each_pattern
367                .enumerate()
368                .filter_map(|(pattern_id, num_ways_to_become_pattern)| {
369                    if num_ways_to_become_pattern.is_zero() {
370                        None
371                    } else {
372                        Some(pattern_id)
373                    }
374                })
375                .next()
376                .expect("Missing pattern");
377            Ok(pattern_id)
378        } else if self.num_compatible_patterns == 0 {
379            Err(ChosenPatternIdError::NoCompatiblePatterns)
380        } else {
381            Err(ChosenPatternIdError::MultipleCompatiblePatterns)
382        }
383    }
384    fn weighted_compatible_stats_enumerate<'a>(
385        &'a self,
386        global_stats: &'a GlobalStats,
387    ) -> impl Iterator<Item = (PatternId, &'a PatternWeight)> {
388        self.num_ways_to_become_each_pattern
389            .iter()
390            .zip(global_stats.pattern_stats_option_iter())
391            .enumerate()
392            .filter_map(
393                |(pattern_id_usize, (num_ways_to_become_pattern, pattern_stats))| {
394                    if num_ways_to_become_pattern.is_zero() {
395                        None
396                    } else {
397                        pattern_stats.map(|pattern_stats| {
398                            (pattern_id_usize as PatternId, pattern_stats)
399                        })
400                    }
401                },
402            )
403    }
404    fn sum_compatible_pattern_weight(&self, global_stats: &GlobalStats) -> u32 {
405        self.num_ways_to_become_each_pattern
406            .iter()
407            .zip(global_stats.pattern_stats_option_iter())
408            .filter_map(|(num_ways_to_become_pattern, pattern_stats)| {
409                if num_ways_to_become_pattern.is_zero() {
410                    None
411                } else {
412                    pattern_stats.map(|pattern_stats| pattern_stats.weight())
413                }
414            })
415            .sum()
416    }
417    fn decrement_num_ways_to_become_pattern(
418        &mut self,
419        pattern_id: PatternId,
420        direction: CardinalDirection,
421        global_stats: &GlobalStats,
422    ) -> DecrementNumWaysToBecomePattern {
423        use self::DecrementNumWaysToBecomePattern as D;
424        match self.num_ways_to_become_each_pattern[pattern_id].try_decrement(direction) {
425            Some(DecrementedToZero) => {
426                assert!(self.num_compatible_patterns >= 1);
427                self.num_compatible_patterns -= 1;
428                if let Some(pattern_stats) = global_stats.pattern_stats(pattern_id) {
429                    self.stats.remove_compatible_pattern(pattern_stats);
430                    match self.stats.num_weighted_compatible_patterns {
431                        0 => {
432                            if self.num_compatible_patterns == 0 {
433                                D::RemovedFinalCompatiblePattern
434                            } else {
435                                D::RemovedFinalWeightedCompatiblePattern
436                            }
437                        }
438                        _ => {
439                            assert!(self.num_compatible_patterns != 0);
440                            if self.num_compatible_patterns == 1 {
441                                assert!(self.stats.num_weighted_compatible_patterns == 1);
442                                D::Finalized
443                            } else {
444                                D::RemovedWeightedPatternMultipleCandidatesRemain
445                            }
446                        }
447                    }
448                } else {
449                    D::RemovedNonWeightedPattern
450                }
451            }
452            None => D::NoPatternRemoved,
453        }
454    }
455    fn entropy_with_noise(&self) -> EntropyWithNoise {
456        let entropy = self.stats.entropy();
457        let noise = self.noise;
458        let num_weighted_compatible_patterns =
459            self.stats.num_weighted_compatible_patterns;
460        EntropyWithNoise {
461            entropy,
462            noise,
463            num_weighted_compatible_patterns,
464        }
465    }
466    fn choose_pattern_id<R: Rng>(
467        &self,
468        global_stats: &GlobalStats,
469        rng: &mut R,
470    ) -> PatternId {
471        assert!(self.stats.num_weighted_compatible_patterns >= 1);
472        assert!(self.stats.sum_compatible_pattern_weight >= 1);
473        assert_eq!(
474            self.sum_compatible_pattern_weight(global_stats),
475            self.stats.sum_compatible_pattern_weight
476        );
477
478        let mut remaining = rng.gen_range(0..self.stats.sum_compatible_pattern_weight);
479        for (pattern_id, pattern_stats) in
480            self.weighted_compatible_stats_enumerate(global_stats)
481        {
482            if remaining >= pattern_stats.weight() {
483                remaining -= pattern_stats.weight();
484            } else {
485                assert!(global_stats.pattern_stats(pattern_id).is_some());
486                return pattern_id;
487            }
488        }
489        unreachable!("The weight is positive and based on global_stats");
490    }
491    fn init<R: Rng>(&mut self, global_stats: &GlobalStats, rng: &mut R) {
492        self.noise = rng.gen();
493        self.num_compatible_patterns = global_stats.num_patterns() as u32;
494        self.stats.num_weighted_compatible_patterns =
495            global_stats.num_weighted_patterns();
496        self.stats.sum_compatible_pattern_weight = global_stats.sum_pattern_weight();
497        self.stats.sum_compatible_pattern_weight_log_weight =
498            global_stats.sum_pattern_weight_log_weight();
499        self.num_ways_to_become_each_pattern
500            .resize(global_stats.num_patterns(), Default::default());
501        self.num_ways_to_become_each_pattern
502            .iter_mut()
503            .zip(global_stats.num_ways_to_become_each_pattern_by_direction())
504            .for_each(|(dst, src)| *dst = NumWaysToBecomePattern::new(src));
505    }
506}
507
508#[derive(Clone)]
509pub struct Wave {
510    grid: Grid<WaveCell>,
511}
512
513impl Wave {
514    pub fn new(size: Size) -> Self {
515        Self {
516            grid: Grid::new_default(size),
517        }
518    }
519    fn init<R: Rng>(&mut self, global_stats: &GlobalStats, rng: &mut R) {
520        self.grid
521            .iter_mut()
522            .for_each(|cell| cell.init(global_stats, rng));
523    }
524    pub fn grid(&self) -> &Grid<WaveCell> {
525        &self.grid
526    }
527}
528
529#[derive(Debug, Clone)]
530struct RemovedPattern {
531    coord: Coord,
532    pattern_id: PatternId,
533}
534
535#[derive(Default, Clone)]
536struct Propagator {
537    removed_patterns_to_propagate: Vec<RemovedPattern>,
538}
539
540struct Contradiction;
541
542impl Propagator {
543    fn clear(&mut self) {
544        self.removed_patterns_to_propagate.clear();
545    }
546    fn propagate<W: Wrap>(
547        &mut self,
548        wave: &mut Wave,
549        global_stats: &GlobalStats,
550        entropy_changes_by_coord: &mut HashMap<Coord, EntropyWithNoise>,
551        num_cells_with_more_than_one_weighted_compatible_pattern: &mut u32,
552    ) -> Result<(), Contradiction> {
553        entropy_changes_by_coord.clear();
554        let wave_size = wave.grid.size();
555        while let Some(removed_pattern) = self.removed_patterns_to_propagate.pop() {
556            for direction in CardinalDirections {
557                let coord_to_update = if let Some(coord_to_update) = W::normalize_coord(
558                    removed_pattern.coord + direction.coord(),
559                    wave_size,
560                ) {
561                    coord_to_update
562                } else {
563                    continue;
564                };
565                let cell = wave.grid.get_checked_mut(coord_to_update);
566                for &pattern_id in global_stats.compatible_patterns_in_direction(
567                    removed_pattern.pattern_id,
568                    direction,
569                ) {
570                    use self::DecrementNumWaysToBecomePattern as D;
571                    match cell.decrement_num_ways_to_become_pattern(
572                        pattern_id,
573                        direction,
574                        global_stats,
575                    ) {
576                        D::NoPatternRemoved => continue,
577                        D::RemovedNonWeightedPattern => (),
578                        D::RemovedWeightedPatternMultipleCandidatesRemain => {
579                            let entropy = cell.entropy_with_noise();
580                            entropy_changes_by_coord
581                                .entry(coord_to_update)
582                                .and_modify(|existing_entropy| {
583                                    if entropy < *existing_entropy {
584                                        *existing_entropy = entropy;
585                                    }
586                                })
587                                .or_insert(entropy);
588                        }
589                        D::Finalized => {
590                            *num_cells_with_more_than_one_weighted_compatible_pattern -=
591                                1;
592                            entropy_changes_by_coord.remove(&coord_to_update);
593                        }
594                        D::RemovedFinalCompatiblePattern => {
595                            return Err(Contradiction);
596                        }
597                        D::RemovedFinalWeightedCompatiblePattern => {
598                            entropy_changes_by_coord.remove(&coord_to_update);
599                        }
600                    }
601                    self.removed_patterns_to_propagate.push(RemovedPattern {
602                        coord: coord_to_update,
603                        pattern_id,
604                    });
605                }
606            }
607        }
608        Ok(())
609    }
610}
611
612#[derive(PartialEq, Eq, Debug, Clone)]
613struct CoordEntropy {
614    coord: Coord,
615    entropy_with_noise: EntropyWithNoise,
616}
617
618impl PartialOrd for CoordEntropy {
619    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
620        other
621            .entropy_with_noise
622            .partial_cmp(&self.entropy_with_noise)
623    }
624}
625
626impl Ord for CoordEntropy {
627    fn cmp(&self, other: &Self) -> Ordering {
628        if self < other {
629            return Ordering::Less;
630        }
631        if self == other {
632            return Ordering::Equal;
633        }
634        return Ordering::Greater;
635    }
636}
637
638#[derive(Default, Clone)]
639struct Observer {
640    entropy_priority_queue: BinaryHeap<CoordEntropy>,
641}
642
643#[derive(Debug)]
644struct CellAtCoordMut<'a> {
645    wave_cell: &'a mut WaveCell,
646    coord: Coord,
647}
648
649impl<'a> CellAtCoordMut<'a> {
650    fn remove_all_patterns_except_one(
651        &mut self,
652        pattern_id_to_keep: PatternId,
653        global_stats: &GlobalStats,
654        propagator: &mut Propagator,
655    ) {
656        for (pattern_id, num_ways_to_become_pattern) in self
657            .wave_cell
658            .num_ways_to_become_each_pattern
659            .enumerate_mut()
660        {
661            if pattern_id != pattern_id_to_keep {
662                if !num_ways_to_become_pattern.is_zero() {
663                    num_ways_to_become_pattern.clear_all_directions();
664                    assert!(self.wave_cell.num_compatible_patterns >= 1);
665                    self.wave_cell.num_compatible_patterns -= 1;
666                    if let Some(pattern_stats) = global_stats.pattern_stats(pattern_id) {
667                        self.wave_cell
668                            .stats
669                            .remove_compatible_pattern(pattern_stats);
670                    }
671                    propagator
672                        .removed_patterns_to_propagate
673                        .push(RemovedPattern {
674                            coord: self.coord,
675                            pattern_id,
676                        });
677                }
678            }
679        }
680    }
681}
682
683#[derive(Debug)]
684enum ChooseNextCell<'a> {
685    MinEntropyCell(CellAtCoordMut<'a>),
686    NoCellsWithMultipleWeightedPatterns,
687}
688
689impl Observer {
690    fn clear(&mut self) {
691        self.entropy_priority_queue.clear();
692    }
693    fn choose_next_cell<'a>(&mut self, wave: &'a mut Wave) -> ChooseNextCell<'a> {
694        while let Some(coord_entropy) = self.entropy_priority_queue.pop() {
695            let index = wave
696                .grid
697                .index_of_coord(coord_entropy.coord)
698                .expect("Coord out of bounds");
699            let wave_cell = wave.grid.get_index_checked(index);
700            if wave_cell.stats.num_weighted_compatible_patterns
701                == coord_entropy
702                    .entropy_with_noise
703                    .num_weighted_compatible_patterns
704                && wave_cell.num_compatible_patterns > 1
705            {
706                return ChooseNextCell::MinEntropyCell(CellAtCoordMut {
707                    wave_cell: wave.grid.get_index_checked_mut(index),
708                    coord: coord_entropy.coord,
709                });
710            }
711        }
712        ChooseNextCell::NoCellsWithMultipleWeightedPatterns
713    }
714}
715
716#[derive(Default, Clone)]
717pub struct Context {
718    propagator: Propagator,
719    entropy_changes_by_coord: HashMap<Coord, EntropyWithNoise>,
720    observer: Observer,
721    num_cells_with_more_than_one_weighted_compatible_pattern: u32,
722}
723
724#[derive(Debug)]
725pub enum Observe {
726    Incomplete,
727    Complete,
728}
729
730#[derive(Debug)]
731pub enum PropagateError {
732    Contradiction,
733}
734
735struct WaveCellHandle<'a> {
736    cell_at_coord_mut: CellAtCoordMut<'a>,
737    propagator: &'a mut Propagator,
738    global_stats: &'a GlobalStats,
739}
740
741impl<'a> WaveCellHandle<'a> {
742    fn new(
743        wave: &'a mut Wave,
744        coord: Coord,
745        propagator: &'a mut Propagator,
746        global_stats: &'a GlobalStats,
747    ) -> Self {
748        let cell_at_coord_mut = CellAtCoordMut {
749            wave_cell: wave.grid.get_checked_mut(coord),
750            coord,
751        };
752        Self {
753            cell_at_coord_mut,
754            propagator,
755            global_stats,
756        }
757    }
758    fn forbid_all_patterns_except(&mut self, pattern_id: PatternId) {
759        self.cell_at_coord_mut.remove_all_patterns_except_one(
760            pattern_id,
761            self.global_stats,
762            &mut self.propagator,
763        );
764    }
765    fn forbid_pattern(&mut self, pattern_id: PatternId) {
766        if self
767            .cell_at_coord_mut
768            .wave_cell
769            .num_ways_to_become_each_pattern[pattern_id]
770            .is_zero()
771        {
772            return;
773        }
774        self.cell_at_coord_mut
775            .wave_cell
776            .num_ways_to_become_each_pattern[pattern_id]
777            .clear_all_directions();
778        self.cell_at_coord_mut.wave_cell.num_compatible_patterns -= 1;
779        if let Some(pattern_stats) = self.global_stats.pattern_stats(pattern_id) {
780            self.cell_at_coord_mut
781                .wave_cell
782                .stats
783                .remove_compatible_pattern(pattern_stats);
784        }
785        self.propagator
786            .removed_patterns_to_propagate
787            .push(RemovedPattern {
788                coord: self.cell_at_coord_mut.coord,
789                pattern_id,
790            });
791    }
792}
793
794impl Context {
795    pub fn new() -> Self {
796        Default::default()
797    }
798    fn init(&mut self, wave: &Wave, global_stats: &GlobalStats) {
799        self.propagator.clear();
800        self.observer.clear();
801        self.entropy_changes_by_coord.clear();
802        if global_stats.num_weighted_patterns() > 1 {
803            self.num_cells_with_more_than_one_weighted_compatible_pattern =
804                wave.grid.size().count() as u32;
805            wave.grid.enumerate().for_each(|(coord, cell)| {
806                self.observer.entropy_priority_queue.push(CoordEntropy {
807                    coord,
808                    entropy_with_noise: cell.entropy_with_noise(),
809                });
810            });
811        } else {
812            self.num_cells_with_more_than_one_weighted_compatible_pattern = 0;
813        }
814    }
815    fn propagate<W: Wrap>(
816        &mut self,
817        wave: &mut Wave,
818        global_stats: &GlobalStats,
819    ) -> Result<(), PropagateError> {
820        self.propagator
821            .propagate::<W>(
822                wave,
823                global_stats,
824                &mut self.entropy_changes_by_coord,
825                &mut self.num_cells_with_more_than_one_weighted_compatible_pattern,
826            )
827            .map_err(|_: Contradiction| PropagateError::Contradiction)?;
828        for (coord, entropy_with_noise) in self.entropy_changes_by_coord.drain() {
829            self.observer.entropy_priority_queue.push(CoordEntropy {
830                coord,
831                entropy_with_noise,
832            });
833        }
834        Ok(())
835    }
836    fn observe<R: Rng>(
837        &mut self,
838        wave: &mut Wave,
839        global_stats: &GlobalStats,
840        rng: &mut R,
841    ) -> Observe {
842        if self.num_cells_with_more_than_one_weighted_compatible_pattern == 0 {
843            return Observe::Complete;
844        }
845        let mut cell_at_coord = match self.observer.choose_next_cell(wave) {
846            ChooseNextCell::NoCellsWithMultipleWeightedPatterns => {
847                return Observe::Complete;
848            }
849            ChooseNextCell::MinEntropyCell(cell_at_coord) => cell_at_coord,
850        };
851        let pattern_id = cell_at_coord.wave_cell.choose_pattern_id(global_stats, rng);
852        cell_at_coord.remove_all_patterns_except_one(
853            pattern_id,
854            &global_stats,
855            &mut self.propagator,
856        );
857        self.num_cells_with_more_than_one_weighted_compatible_pattern -= 1;
858        Observe::Incomplete
859    }
860}
861
862pub trait ForbidPattern {
863    fn forbid<W: Wrap, R: Rng>(&mut self, fi: &mut ForbidInterface<W>, rng: &mut R);
864}
865
866#[derive(Clone)]
867pub struct ForbidNothing;
868impl ForbidPattern for ForbidNothing {
869    fn forbid<W: Wrap, R: Rng>(&mut self, _fi: &mut ForbidInterface<W>, _rng: &mut R) {}
870}
871
872pub struct ForbidRef<'a, F: ForbidPattern>(&'a mut F);
873impl<'a, F: ForbidPattern> ForbidPattern for ForbidRef<'a, F> {
874    fn forbid<W: Wrap, R: Rng>(&mut self, fi: &mut ForbidInterface<W>, rng: &mut R) {
875        self.0.forbid(fi, rng);
876    }
877}
878
879/// Represents a running instance of wfc which borrows its resources, making it
880/// possible to re-use memory across multiple runs.
881pub struct RunBorrow<'a, W: Wrap = WrapXY, F: ForbidPattern = ForbidNothing> {
882    core: RunBorrowCore<'a, W>,
883    forbid: F,
884}
885
886impl<'a> RunBorrow<'a> {
887    pub fn new<R: Rng>(
888        context: &'a mut Context,
889        wave: &'a mut Wave,
890        global_stats: &'a GlobalStats,
891        rng: &mut R,
892    ) -> Self {
893        Self::new_wrap_forbid(context, wave, global_stats, WrapXY, ForbidNothing, rng)
894    }
895}
896
897impl<'a, W: Wrap> RunBorrow<'a, W> {
898    pub fn new_wrap<R: Rng>(
899        context: &'a mut Context,
900        wave: &'a mut Wave,
901        global_stats: &'a GlobalStats,
902        wrap: W,
903        rng: &mut R,
904    ) -> Self {
905        Self::new_wrap_forbid(context, wave, global_stats, wrap, ForbidNothing, rng)
906    }
907}
908
909impl<'a, F: ForbidPattern> RunBorrow<'a, WrapXY, F> {
910    pub fn new_forbid<R: Rng>(
911        context: &'a mut Context,
912        wave: &'a mut Wave,
913        global_stats: &'a GlobalStats,
914        forbid: F,
915        rng: &mut R,
916    ) -> Self {
917        Self::new_wrap_forbid(context, wave, global_stats, WrapXY, forbid, rng)
918    }
919}
920
921impl<'a, W: Wrap, F: ForbidPattern> RunBorrow<'a, W, F> {
922    pub fn new_wrap_forbid<R: Rng>(
923        context: &'a mut Context,
924        wave: &'a mut Wave,
925        global_stats: &'a GlobalStats,
926        wrap: W,
927        mut forbid: F,
928        rng: &mut R,
929    ) -> Self {
930        let mut core = RunBorrowCore::new(context, wave, global_stats, wrap, rng);
931        forbid.forbid(&mut ForbidInterface(&mut core), rng);
932        Self { core, forbid }
933    }
934}
935
936struct RunBorrowCore<'a, W: Wrap = WrapXY> {
937    context: &'a mut Context,
938    wave: &'a mut Wave,
939    global_stats: &'a GlobalStats,
940    output_wrap: PhantomData<W>,
941}
942
943pub struct WaveCellRef<'a> {
944    wave_cell: &'a WaveCell,
945    global_stats: &'a GlobalStats,
946}
947
948pub enum WaveCellRefWeight {
949    Weight(u32),
950    SingleNonWeightedPattern,
951}
952
953pub struct MultipleWeightedPatternsEnumerateWeights<'a> {
954    iter: iter::Enumerate<
955        iter::Zip<
956            slice::Iter<'a, NumWaysToBecomePattern>,
957            OptionSliceIter<'a, PatternWeight>,
958        >,
959    >,
960}
961
962impl<'a> Iterator for MultipleWeightedPatternsEnumerateWeights<'a> {
963    type Item = (PatternId, u32);
964    fn next(&mut self) -> Option<Self::Item> {
965        while let Some((pattern_id_usize, (num_ways_to_become_pattern, pattern_stats))) =
966            self.iter.next()
967        {
968            if num_ways_to_become_pattern.is_zero() {
969                continue;
970            } else {
971                let pattern_id = pattern_id_usize as PatternId;
972                let weight =
973                    match pattern_stats.map(|pattern_stats| pattern_stats.weight()) {
974                        Some(weight) => weight,
975                        None => 0,
976                    };
977                return Some((pattern_id, weight));
978            }
979        }
980        None
981    }
982}
983
984pub enum NoPatternsWithWeights {
985    SingleCompatiblePattern(PatternId),
986}
987
988pub enum EnumerateCompatiblePatternWeights<'a> {
989    CompatiblePatternsWithWeights(MultipleWeightedPatternsEnumerateWeights<'a>),
990    SingleCompatiblePatternWithoutWeight(PatternId),
991    NoCompatiblePattern,
992    MultipleCompatiblePatternsWithoutWeights,
993}
994
995impl<'a> WaveCellRef<'a> {
996    pub fn sum_compatible_pattern_weight(&self) -> u32 {
997        self.wave_cell.stats.sum_compatible_pattern_weight
998    }
999    pub fn enumerate_compatible_pattern_weights(
1000        &self,
1001    ) -> EnumerateCompatiblePatternWeights {
1002        if self.wave_cell.num_compatible_patterns == 0 {
1003            return EnumerateCompatiblePatternWeights::NoCompatiblePattern;
1004        }
1005        if self.wave_cell.stats.num_weighted_compatible_patterns == 0 {
1006            if self.wave_cell.num_compatible_patterns == 1 {
1007                return EnumerateCompatiblePatternWeights::SingleCompatiblePatternWithoutWeight(
1008                    self.wave_cell.chosen_pattern_id().unwrap());
1009            } else {
1010                return EnumerateCompatiblePatternWeights::MultipleCompatiblePatternsWithoutWeights;
1011            }
1012        }
1013        let iter = self
1014            .wave_cell
1015            .num_ways_to_become_each_pattern
1016            .iter()
1017            .zip(self.global_stats.pattern_stats_option_iter())
1018            .enumerate();
1019        EnumerateCompatiblePatternWeights::CompatiblePatternsWithWeights(
1020            MultipleWeightedPatternsEnumerateWeights { iter },
1021        )
1022    }
1023}
1024
1025impl<'a, W: Wrap, F: ForbidPattern> RunBorrow<'a, W, F> {
1026    pub fn reset<R: Rng>(&mut self, rng: &mut R) {
1027        self.core.reset(rng);
1028        self.forbid
1029            .forbid(&mut ForbidInterface(&mut self.core), rng);
1030    }
1031
1032    pub fn step<R: Rng>(&mut self, rng: &mut R) -> Result<Observe, PropagateError> {
1033        let result = self.core.step(rng);
1034        if result.is_err() {
1035            self.reset(rng);
1036        }
1037        result
1038    }
1039
1040    pub fn collapse<R: Rng>(&mut self, rng: &mut R) -> Result<(), PropagateError> {
1041        let result = self.core.collapse(rng);
1042        if result.is_err() {
1043            self.reset(rng);
1044        }
1045        result
1046    }
1047
1048    pub fn wave_cell_ref(&self, coord: Coord) -> WaveCellRef {
1049        self.core.wave_cell_ref(coord)
1050    }
1051
1052    pub fn wave_cell_ref_iter(&self) -> impl Iterator<Item = WaveCellRef> {
1053        self.core.wave_cell_ref_iter()
1054    }
1055
1056    pub fn wave_cell_ref_enumerate(&self) -> impl Iterator<Item = (Coord, WaveCellRef)> {
1057        self.core.wave_cell_ref_enumerate()
1058    }
1059
1060    pub fn collapse_retrying<R, RB>(&mut self, mut retry: RB, rng: &mut R) -> RB::Return
1061    where
1062        R: Rng,
1063        RB: retry::RetryBorrow,
1064    {
1065        retry.retry(self, rng)
1066    }
1067}
1068
1069impl<'a, W: Wrap> RunBorrowCore<'a, W> {
1070    fn new<R: Rng>(
1071        context: &'a mut Context,
1072        wave: &'a mut Wave,
1073        global_stats: &'a GlobalStats,
1074        output_wrap: W,
1075        rng: &mut R,
1076    ) -> Self {
1077        let _ = output_wrap;
1078        wave.init(global_stats, rng);
1079        context.init(wave, global_stats);
1080        Self {
1081            context,
1082            wave,
1083            global_stats,
1084            output_wrap: PhantomData,
1085        }
1086    }
1087
1088    fn reset<R: Rng>(&mut self, rng: &mut R) {
1089        self.wave.init(self.global_stats, rng);
1090        self.context.init(&self.wave, self.global_stats);
1091    }
1092
1093    fn propagate(&mut self) -> Result<(), PropagateError> {
1094        self.context.propagate::<W>(self.wave, self.global_stats)
1095    }
1096
1097    fn observe<R: Rng>(&mut self, rng: &mut R) -> Observe {
1098        self.context.observe(self.wave, self.global_stats, rng)
1099    }
1100
1101    fn step<R: Rng>(&mut self, rng: &mut R) -> Result<Observe, PropagateError> {
1102        match self.observe(rng) {
1103            Observe::Complete => Ok(Observe::Complete),
1104            Observe::Incomplete => {
1105                self.propagate()?;
1106                Ok(Observe::Incomplete)
1107            }
1108        }
1109    }
1110
1111    fn wave_cell_handle(&mut self, coord: Coord) -> WaveCellHandle {
1112        WaveCellHandle::new(
1113            self.wave,
1114            coord,
1115            &mut self.context.propagator,
1116            self.global_stats,
1117        )
1118    }
1119
1120    fn forbid_all_patterns_except(
1121        &mut self,
1122        coord: Coord,
1123        pattern_id: PatternId,
1124    ) -> Result<(), PropagateError> {
1125        self.wave_cell_handle(coord)
1126            .forbid_all_patterns_except(pattern_id);
1127        self.propagate()
1128    }
1129
1130    fn forbid_pattern(
1131        &mut self,
1132        coord: Coord,
1133        pattern_id: PatternId,
1134    ) -> Result<(), PropagateError> {
1135        self.wave_cell_handle(coord).forbid_pattern(pattern_id);
1136        self.propagate()
1137    }
1138
1139    fn collapse<R: Rng>(&mut self, rng: &mut R) -> Result<(), PropagateError> {
1140        loop {
1141            match self.observe(rng) {
1142                Observe::Complete => return Ok(()),
1143                Observe::Incomplete => {
1144                    self.propagate()?;
1145                }
1146            }
1147        }
1148    }
1149
1150    fn wave_cell_ref(&self, coord: Coord) -> WaveCellRef {
1151        let wave_cell = self.wave.grid.get_checked(coord);
1152        WaveCellRef {
1153            wave_cell,
1154            global_stats: self.global_stats,
1155        }
1156    }
1157
1158    fn wave_cell_ref_iter(&self) -> impl Iterator<Item = WaveCellRef> {
1159        self.wave.grid.iter().map(move |wave_cell| WaveCellRef {
1160            wave_cell,
1161            global_stats: self.global_stats,
1162        })
1163    }
1164
1165    fn wave_cell_ref_enumerate(&self) -> impl Iterator<Item = (Coord, WaveCellRef)> {
1166        self.wave.grid.enumerate().map(move |(coord, wave_cell)| {
1167            let wave_cell_ref = WaveCellRef {
1168                wave_cell,
1169                global_stats: self.global_stats,
1170            };
1171            (coord, wave_cell_ref)
1172        })
1173    }
1174}
1175
1176pub struct ForbidInterface<'a, 'b, W: Wrap>(&'a mut RunBorrowCore<'b, W>);
1177
1178impl<'a, 'b, W: Wrap> ForbidInterface<'a, 'b, W> {
1179    pub fn wave_size(&self) -> Size {
1180        self.0.wave.grid.size()
1181    }
1182
1183    pub fn forbid_all_patterns_except<R: Rng>(
1184        &mut self,
1185        coord: Coord,
1186        pattern_id: PatternId,
1187        rng: &mut R,
1188    ) -> Result<(), PropagateError> {
1189        let result = self.0.forbid_all_patterns_except(coord, pattern_id);
1190        if result.is_err() {
1191            self.0.reset(rng);
1192        }
1193        result
1194    }
1195
1196    pub fn forbid_pattern<R: Rng>(
1197        &mut self,
1198        coord: Coord,
1199        pattern_id: PatternId,
1200        rng: &mut R,
1201    ) -> Result<(), PropagateError> {
1202        let result = self.0.forbid_pattern(coord, pattern_id);
1203        if result.is_err() {
1204            self.0.reset(rng);
1205        }
1206        result
1207    }
1208}
1209
1210#[derive(Clone)]
1211/// Represents a running instance of wfc which allocates and owns its resources
1212pub struct RunOwn<'a, W: Wrap = WrapXY, F: ForbidPattern = ForbidNothing> {
1213    context: Context,
1214    wave: Wave,
1215    global_stats: &'a GlobalStats,
1216    output_wrap: PhantomData<W>,
1217    forbid: F,
1218}
1219
1220pub enum OwnedObserve<'a, W: Wrap> {
1221    Complete(Wave),
1222    Incomplete(RunOwn<'a, W>),
1223}
1224
1225pub enum OwnedPropagateError<'a, W: Wrap> {
1226    Contradiction(RunOwn<'a, W>),
1227}
1228
1229impl<'a> RunOwn<'a> {
1230    pub fn new<R: Rng>(
1231        output_size: Size,
1232        global_stats: &'a GlobalStats,
1233        rng: &mut R,
1234    ) -> Self {
1235        Self::new_wrap_forbid(output_size, global_stats, WrapXY, ForbidNothing, rng)
1236    }
1237}
1238
1239impl<'a, W: Wrap> RunOwn<'a, W> {
1240    pub fn new_wrap<R: Rng>(
1241        output_size: Size,
1242        global_stats: &'a GlobalStats,
1243        wrap: W,
1244        rng: &mut R,
1245    ) -> Self {
1246        Self::new_wrap_forbid(output_size, global_stats, wrap, ForbidNothing, rng)
1247    }
1248}
1249
1250impl<'a, F: ForbidPattern> RunOwn<'a, WrapXY, F>
1251where
1252    F: Clone + Sync + Send,
1253{
1254    pub fn new_forbid<R: Rng>(
1255        output_size: Size,
1256        global_stats: &'a GlobalStats,
1257        forbid: F,
1258        rng: &mut R,
1259    ) -> Self {
1260        Self::new_wrap_forbid(output_size, global_stats, WrapXY, forbid, rng)
1261    }
1262}
1263
1264impl<'a, W: Wrap, F: ForbidPattern> RunOwn<'a, W, F>
1265where
1266    F: Clone + Sync + Send,
1267{
1268    pub fn new_wrap_forbid<R: Rng>(
1269        output_size: Size,
1270        global_stats: &'a GlobalStats,
1271        wrap: W,
1272        forbid: F,
1273        rng: &mut R,
1274    ) -> Self {
1275        let _ = wrap;
1276        let wave = Wave::new(output_size);
1277        let context = Context::new();
1278        let mut s = Self {
1279            context,
1280            wave,
1281            global_stats,
1282            output_wrap: PhantomData,
1283            forbid,
1284        };
1285        s.borrow_mut().reset(rng);
1286        s
1287    }
1288}
1289
1290impl<'a, W: Wrap, F: ForbidPattern> RunOwn<'a, W, F>
1291where
1292    F: Clone + Sync + Send,
1293{
1294    pub fn borrow_mut(&mut self) -> RunBorrow<W, ForbidRef<F>> {
1295        let core = RunBorrowCore {
1296            context: &mut self.context,
1297            wave: &mut self.wave,
1298            global_stats: self.global_stats,
1299            output_wrap: self.output_wrap,
1300        };
1301        RunBorrow {
1302            core,
1303            forbid: ForbidRef(&mut self.forbid),
1304        }
1305    }
1306
1307    pub fn step<R: Rng>(&mut self, rng: &mut R) -> Result<Observe, PropagateError> {
1308        self.borrow_mut().step(rng)
1309    }
1310
1311    pub fn collapse<R: Rng>(&mut self, rng: &mut R) -> Result<(), PropagateError> {
1312        self.borrow_mut().collapse(rng)
1313    }
1314
1315    pub fn wave_cell_ref(&self, coord: Coord) -> WaveCellRef {
1316        let wave_cell = self.wave.grid.get_checked(coord);
1317        WaveCellRef {
1318            wave_cell,
1319            global_stats: self.global_stats,
1320        }
1321    }
1322
1323    pub fn wave_cell_ref_iter(&self) -> impl Iterator<Item = WaveCellRef> {
1324        self.wave.grid.iter().map(move |wave_cell| WaveCellRef {
1325            wave_cell,
1326            global_stats: self.global_stats,
1327        })
1328    }
1329
1330    pub fn wave_cell_ref_enumerate(&self) -> impl Iterator<Item = (Coord, WaveCellRef)> {
1331        self.wave.grid.enumerate().map(move |(coord, wave_cell)| {
1332            let wave_cell_ref = WaveCellRef {
1333                wave_cell,
1334                global_stats: self.global_stats,
1335            };
1336            (coord, wave_cell_ref)
1337        })
1338    }
1339
1340    pub fn into_wave(self) -> Wave {
1341        self.wave
1342    }
1343
1344    pub fn collapse_retrying<R, RO>(self, mut retry: RO, rng: &mut R) -> RO::Return
1345    where
1346        R: Rng,
1347        RO: retry::RetryOwn,
1348    {
1349        retry.retry(self, rng)
1350    }
1351}
1352
1353#[derive(Clone)]
1354/// Represents a running instance of wfc which allocates and owns its resources including a copy
1355/// of the GlobalStats
1356pub struct RunOwnAll<W: Wrap = WrapXY, F: ForbidPattern = ForbidNothing> {
1357    context: Context,
1358    wave: Wave,
1359    global_stats: GlobalStats,
1360    output_wrap: PhantomData<W>,
1361    forbid: F,
1362}
1363
1364impl RunOwnAll {
1365    pub fn new<R: Rng>(
1366        output_size: Size,
1367        global_stats: GlobalStats,
1368        rng: &mut R,
1369    ) -> Self {
1370        Self::new_wrap_forbid(output_size, global_stats, WrapXY, ForbidNothing, rng)
1371    }
1372}
1373
1374impl<W: Wrap> RunOwnAll<W> {
1375    pub fn new_wrap<R: Rng>(
1376        output_size: Size,
1377        global_stats: GlobalStats,
1378        wrap: W,
1379        rng: &mut R,
1380    ) -> Self {
1381        Self::new_wrap_forbid(output_size, global_stats, wrap, ForbidNothing, rng)
1382    }
1383}
1384
1385impl<F: ForbidPattern> RunOwnAll<WrapXY, F>
1386where
1387    F: Clone + Sync + Send,
1388{
1389    pub fn new_forbid<R: Rng>(
1390        output_size: Size,
1391        global_stats: GlobalStats,
1392        forbid: F,
1393        rng: &mut R,
1394    ) -> Self {
1395        Self::new_wrap_forbid(output_size, global_stats, WrapXY, forbid, rng)
1396    }
1397}
1398
1399impl<W: Wrap, F: ForbidPattern> RunOwnAll<W, F>
1400where
1401    F: Clone + Sync + Send,
1402{
1403    pub fn new_wrap_forbid<R: Rng>(
1404        output_size: Size,
1405        global_stats: GlobalStats,
1406        wrap: W,
1407        forbid: F,
1408        rng: &mut R,
1409    ) -> Self {
1410        let _ = wrap;
1411        let wave = Wave::new(output_size);
1412        let context = Context::new();
1413        let mut s = Self {
1414            context,
1415            wave,
1416            global_stats,
1417            output_wrap: PhantomData,
1418            forbid,
1419        };
1420        s.borrow_mut().reset(rng);
1421        s
1422    }
1423}
1424
1425impl<W: Wrap, F: ForbidPattern> RunOwnAll<W, F>
1426where
1427    F: Clone + Sync + Send,
1428{
1429    pub fn borrow_mut(&mut self) -> RunBorrow<W, ForbidRef<F>> {
1430        let core = RunBorrowCore {
1431            context: &mut self.context,
1432            wave: &mut self.wave,
1433            global_stats: &self.global_stats,
1434            output_wrap: self.output_wrap,
1435        };
1436        RunBorrow {
1437            core,
1438            forbid: ForbidRef(&mut self.forbid),
1439        }
1440    }
1441
1442    pub fn step<R: Rng>(&mut self, rng: &mut R) -> Result<Observe, PropagateError> {
1443        self.borrow_mut().step(rng)
1444    }
1445
1446    pub fn collapse<R: Rng>(&mut self, rng: &mut R) -> Result<(), PropagateError> {
1447        self.borrow_mut().collapse(rng)
1448    }
1449
1450    pub fn wave_cell_ref(&self, coord: Coord) -> WaveCellRef {
1451        let wave_cell = self.wave.grid.get_checked(coord);
1452        WaveCellRef {
1453            wave_cell,
1454            global_stats: &self.global_stats,
1455        }
1456    }
1457
1458    pub fn wave_cell_ref_iter(&self) -> impl Iterator<Item = WaveCellRef> {
1459        self.wave.grid.iter().map(move |wave_cell| WaveCellRef {
1460            wave_cell,
1461            global_stats: &self.global_stats,
1462        })
1463    }
1464
1465    pub fn wave_cell_ref_enumerate(&self) -> impl Iterator<Item = (Coord, WaveCellRef)> {
1466        self.wave.grid.enumerate().map(move |(coord, wave_cell)| {
1467            let wave_cell_ref = WaveCellRef {
1468                wave_cell,
1469                global_stats: &self.global_stats,
1470            };
1471            (coord, wave_cell_ref)
1472        })
1473    }
1474
1475    pub fn into_wave(self) -> Wave {
1476        self.wave
1477    }
1478
1479    pub fn collapse_retrying<R, RO>(self, mut retry: RO, rng: &mut R) -> RO::Return
1480    where
1481        R: Rng,
1482        RO: retry::RetryOwnAll,
1483    {
1484        retry.retry(self, rng)
1485    }
1486}