main/
main.rs

1use std::{thread, time::Duration};
2
3use microwfc::*;
4
5use rand::thread_rng;
6
7#[derive(Clone, PartialEq, Eq, Debug)]
8enum Tile {
9    Water,
10    Dirt,
11    Grass,
12}
13
14impl From<Tile> for String {
15    fn from(val: Tile) -> Self {
16        // See ANSI escape codes for 8-bit colors:
17        // https://en.wikipedia.org/wiki/ANSI_escape_sequence#8-bit
18        match val {
19            Tile::Water => "\x1b[38;5;21m██\x1b[0m".to_string(),
20            Tile::Dirt => "\x1b[38;5;94m██\x1b[0m".to_string(),
21            Tile::Grass => "\x1b[38;5;28m██\x1b[0m".to_string(),
22        }
23    }
24}
25
26impl PossibleValues for Tile {
27    fn get_possible_values() -> Vec<(Self, f32)> {
28        vec![(Self::Grass, 4f32), (Self::Dirt, 1f32), (Self::Water, 3f32)]
29    }
30}
31
32fn main() {
33    let mut rng = thread_rng();
34    // Make a new 30-by-30 grid.
35    let mut grid: Grid<Tile, 2> = Grid::new([30, 30]).unwrap();
36    loop {
37        let r = grid.wfc(
38            |g, loc, me, probability| {
39                // We use !any(|x| ...) to get none(|x| ...) functionality
40                match *me {
41                    // Disallow water next to grass
42                    Tile::Water => (
43                        !g.unidirectional_neighbors(loc).iter().any(|x| {
44                            x.1.determined_value
45                                .as_ref()
46                                .map(|x| *x == Tile::Grass)
47                                .unwrap_or(false) // Allow unsolved pixels
48                        }),
49                        probability,
50                    ),
51                    // Dirt is always allowed
52                    Tile::Dirt => (true, probability),
53                    // Disallow grass next to water
54                    Tile::Grass => (
55                        !g.unidirectional_neighbors(loc).iter().any(|x| {
56                            x.1.determined_value
57                                .as_ref()
58                                .map(|x| *x == Tile::Water)
59                                .unwrap_or(false)
60                        }),
61                        probability,
62                    ),
63                }
64            },
65            1,
66            &mut rng,
67            0.05,
68            |grid| {
69                // Clear the screen
70                println!("\x1b[H\x1b[2J\x1b[3J");
71
72                let mut s = String::new();
73                for y in 0..grid.size()[0] {
74                    s += "\n";
75                    for x in 0..grid.size()[1] {
76                        if let Some(x) = grid.get_item([x, y]).determined_value {
77                            s += &String::from(x);
78                        } else {
79                            s += "  ";
80                        }
81                    }
82                }
83
84                println!("{}", s);
85                thread::sleep(Duration::from_millis(10));
86            },
87        );
88        if r.is_ok() {
89            break;
90        } else {
91            println!("fuck");
92        }
93    }
94}