1use std::{
7 collections::{HashMap, HashSet},
8 thread,
9 time::Duration,
10};
11
12use crate::{Algorithm, Maze, Pos};
13
14use self::builder::{
15 maze_state::{BuildableMazeState, Unprovided},
16 new_builder, DynExecutorBuilder, ExecutorBuilder,
17};
18
19pub struct Guess(Vec<Pos>);
21
22pub struct Insight<'p> {
25 position: Pos,
26 paths: &'p [Pos],
27}
28
29impl<'p> Insight<'p> {
30 fn new(position: Pos, paths: &'p [Pos]) -> Self {
31 Self { paths, position }
32 }
33
34 fn from_position(position: Pos, maze: &'p Maze) -> Self {
35 let paths = maze.paths_from(position);
36 Self::new(position, paths)
37 }
38
39 pub fn position(&self) -> Pos {
41 self.position
42 }
43
44 pub fn paths(&self) -> &[Pos] {
46 self.paths
47 }
48}
49
50pub struct Context<'m> {
52 maze: &'m Maze,
53}
54
55impl<'m> Context<'m> {
56 fn new(maze: &'m Maze) -> Self {
57 Self { maze }
58 }
59
60 pub fn guess(&self, pos: Vec<Pos>) -> Guess {
63 Guess(pos)
64 }
65
66 pub fn start(&self) -> Pos {
68 self.maze.start()
69 }
70
71 pub fn end(&self) -> Pos {
73 self.maze.end()
74 }
75
76 pub fn width(&self) -> isize {
78 self.maze.width()
79 }
80
81 pub fn height(&self) -> isize {
83 self.maze.width()
84 }
85
86 pub fn size(&self) -> (isize, isize) {
88 self.maze.size()
89 }
90}
91
92mod builder;
93
94pub struct Executor {
96 delay: Duration,
97 maze: Maze,
98 algorithm: Box<dyn Algorithm>,
99}
100
101impl Executor {
102 fn new(maze: Maze, algorithm: Box<dyn Algorithm>, delay: Duration) -> Self {
104 Self {
105 maze,
106 algorithm,
107 delay,
108 }
109 }
110
111 pub fn build<'f, A, F, MS>(algorithm: A, builder: F) -> Self
112 where
113 A: Algorithm + 'static,
114 MS: BuildableMazeState,
115 F: Fn(ExecutorBuilder<Unprovided>) -> ExecutorBuilder<MS>,
116 {
117 let operation = builder;
118 let builder = (operation)(new_builder());
119 let (maze, delay) = builder.build();
120 let algorithm = Box::new(algorithm);
121 Self::new(maze, algorithm, delay)
122 }
123
124 pub fn build_dyn<F>(algorithm: Box<dyn Algorithm>, builder: F) -> Self
125 where
126 F: Fn(DynExecutorBuilder) -> DynExecutorBuilder,
127 {
128 let operation = builder;
129 let builder = (operation)(DynExecutorBuilder::new());
130 let (maze, delay) = builder.build();
131 Self::new(maze, algorithm, delay)
132 }
133
134 pub fn run(&mut self) {
136 let Self {
137 maze,
138 algorithm,
139 delay,
140 } = self;
141 let mut insight = Insight::from_position(maze.start(), &maze);
142 let mut tick = 0;
143 let mut tried = HashSet::new();
144 loop {
145 let mut context = Context::new(maze);
146 let Guess(guess) = algorithm.progress(&insight, &mut context);
147 guess.iter().for_each(|&p| {
151 tried.insert(p);
152 });
153 let tail = *guess.last().expect("returned an empty path");
154
155 Self::draw(maze, &tried, tick, &guess);
157 thread::sleep(*delay);
158 tick += 1;
159
160 if maze.is_end(tail) {
162 break;
163 } else {
164 insight = Insight::from_position(tail, maze)
165 }
166 }
167 }
168
169 fn draw(maze: &Maze, tried: &HashSet<Pos>, tick: usize, path: &Vec<Pos>) {
170 let mut overlay = HashMap::new();
171 for position in tried {
172 overlay.insert(*position, '░');
173 }
174 for position in path {
175 overlay.insert(*position, '█');
176 }
177 overlay.insert(maze.start(), 'S');
178 overlay.insert(maze.end(), 'E');
179 overlay.insert(*path.last().unwrap(), 'G');
180
181 let grid = maze.display(Some(overlay));
182 let text = format!("tick {tick}:\n{grid}\n");
183
184 if tick > 0 {
187 let count = text.lines().count();
188 let up = termion::cursor::Up(count as u16);
189 print!("{up}")
190 }
191
192 print!("{text}");
193 }
194}