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 sum_compatible_pattern_weight: u32,
238 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 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 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 noise: u32,
317 num_compatible_patterns: u32,
318 stats: WaveCellStats,
319 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 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
879pub 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)]
1211pub 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)]
1354pub 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}