1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use std::{thread, time::Duration};

use microwfc::*;

use rand::thread_rng;

#[derive(Clone, PartialEq, Eq, Debug)]
enum Test {
    Stone,
    Dirt,
    Grass,
}

impl PossibleValues for Test {
    fn get_possible_values() -> Vec<(Self, f32)> {
        vec![(Self::Grass, 4f32), (Self::Dirt, 1f32), (Self::Stone, 3f32)]
    }
}

fn main() {
    let mut rng = thread_rng();
    // Make a new 30-by-30 grid.
    let mut grid: Grid<Test, 2> = Grid::new([30, 30]).unwrap();
    loop {
        let r = grid.wfc(
            |g, loc, me, probability| {
                // We use !any(|x| ...) to get none(|x| ...) functionality
                match *me {
                    // Disallow stone next to grass
                    Test::Stone => (
                        !g.unidirectional_neighbors(loc).iter().any(|x| {
                            x.1.determined_value
                                .as_ref()
                                .map(|x| *x == Test::Grass)
                                .unwrap_or(false) // Allow unsolved pixels
                        }),
                        probability,
                    ),
                    // Dirt is always allowed
                    Test::Dirt => (true, probability),
                    // Disallow grass next to stone
                    Test::Grass => (
                        !g.unidirectional_neighbors(loc).iter().any(|x| {
                            x.1.determined_value
                                .as_ref()
                                .map(|x| *x == Test::Stone)
                                .unwrap_or(false)
                        }),
                        probability,
                    ),
                }
            },
            1,
            &mut rng,
            0.05,
            |grid| {
                let mut s = String::new();
                for y in 0..grid.size()[0] {
                    s += "\n";
                    for x in 0..grid.size()[1] {
                        if let Some(x) = grid.get_item([x, y]).determined_value {
                            s += match x {
                                Test::Stone => "##",
                                Test::Dirt => "YY",
                                Test::Grass => "//",
                            };
                        } else {
                            s += "  ";
                        }
                    }
                }
                println!("{}", s);
                thread::sleep(Duration::from_millis(10));
            },
        );
        if r.is_ok() {
            break;
        } else {
            println!("fuck");
        }
    }
}