Compare commits

..

No commits in common. "86bd6fc78971380a776e8f80bb2ae3b4936fc7e2" and "a7ce6ffb56201f22f345188936bba4f37918b447" have entirely different histories.

19 changed files with 158 additions and 635 deletions

236
Cargo.lock generated
View file

@ -2,23 +2,6 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
@ -31,45 +14,6 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "3.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b"
dependencies = [
"atty",
"bitflags",
"clap_derive",
"clap_lex",
"indexmap",
"lazy_static",
"strsim",
"termcolor",
"textwrap",
]
[[package]]
name = "clap_derive"
version = "3.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "clap_lex"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213"
dependencies = [
"os_str_bytes",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.6" version = "0.2.6"
@ -81,69 +25,14 @@ dependencies = [
"wasi", "wasi",
] ]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "indexmap"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]] [[package]]
name = "labirust" name = "labirust"
version = "0.3.0" version = "0.1.1"
dependencies = [ dependencies = [
"rand", "rand",
"termion", "termion",
] ]
[[package]]
name = "labirust"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be89e6ef8c189ed1fa5acb4475a3b43c2aa835c0788fb38b11df3ddb58359f8c"
dependencies = [
"rand",
"termion",
]
[[package]]
name = "labirust-cli"
version = "0.1.0"
dependencies = [
"clap",
"labirust 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.126" version = "0.2.126"
@ -156,60 +45,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "os_str_bytes"
version = "6.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.16" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
dependencies = [
"proc-macro2",
]
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.8.5" version = "0.8.5"
@ -258,32 +99,6 @@ dependencies = [
"redox_syscall", "redox_syscall",
] ]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "termion" name = "termion"
version = "1.5.6" version = "1.5.6"
@ -296,57 +111,8 @@ dependencies = [
"redox_termios", "redox_termios",
] ]
[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
[[package]]
name = "unicode-ident"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.10.2+wasi-snapshot-preview1" version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -1,2 +1,12 @@
[workspace] [package]
members = ["labirust", "labirust-cli"] name = "labirust"
version = "0.1.1"
edition = "2021"
license = "MIT"
authors = ["JOLIMAITRE Matthieu <matthieu@imagevo.fr>"]
description = "Naive rust crate for implementing and testing maze solving Algorithms."
repository = "https://github.com/MajorBarnulf/labirust/"
[dependencies]
rand = "0.8"
termion = "1.5"

View file

@ -14,19 +14,14 @@ Hi, I am a junior rust dev (yes, how original, I know) and this is one of the sm
## Usage ## Usage
If you want to see what the library is capable of, you can try the CLI, either by clonning this repo and building it with cargo or by installing it through the crates.io depot. If you want to see what the library is capable of, you can clone this repo and run the tests to see mazes solving themselves on the terminal.
for you to see anything during the execution of tests, don't forget to add these arguments:
```sh ```sh
# installation -- --nocapture
cargo install labirust-cli
# usage # example:
labirust-cli --help cargo test -- implementations::breath_first --nocapture
``` ```
If you want to implement more resolution algorithm yourself and for some reason you think this is the right crate to provide frameworks, you can explore the crate documentation and add this crate to your project dependencies. If you want to implement more resolution algorithm yourself and for some reason you think this is the right crate to provide frameworks, you can explore the crate documentation and add this crate to your project dependencies.
```toml
# in Cargo.toml
[dependencies]
labirust = "0.3"
```

View file

@ -1,12 +0,0 @@
[package]
name = "labirust-cli"
version = "0.1.0"
edition = "2021"
license = "MIT"
authors = ["JOLIMAITRE Matthieu <matthieu@imagevo.fr>"]
description = "A cli to run labirust algorithms."
repository = "https://github.com/MajorBarnulf/labirust/"
[dependencies]
labirust = "0.3"
clap = { version = "3.1", features = ["derive"] }

View file

@ -1,12 +0,0 @@
# labirust-cli
## Description
A cli to run labirust algorithms.
## Installation
```sh
# through cargo
cargo install labirust-cli
```

View file

@ -1,58 +0,0 @@
use std::str::FromStr;
use clap::Parser;
use labirust::{implementations::*, Algorithm, Executor, SimpleGenerator};
enum Algorithms {
DepthFirst,
BreathFirst,
}
impl FromStr for Algorithms {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"depth-first" => Ok(Self::DepthFirst),
"breath-first" => Ok(Self::BreathFirst),
_ => Err("No right pattern".into()),
}
}
}
#[derive(Parser)]
struct Parameters {
/// Algorithm to use in the simulation.
/// One of: "depth-first", "breath-first"
algorithm: Algorithms,
/// Width of the maze to solve.
#[clap(short, default_value_t = 40)]
width: usize,
/// Height of the maze to solve.
#[clap(short, default_value_t = 20)]
height: usize,
/// Delay between two simulation ticks.
#[clap(short, default_value_t = 100)]
delay: usize,
}
fn main() {
let params = Parameters::parse();
let algorithm: Box<dyn Algorithm> = match params.algorithm {
Algorithms::DepthFirst => Box::new(DepthFirst::new()),
Algorithms::BreathFirst => Box::new(BreathFirst::new()),
};
let mut executor = Executor::build_dyn(algorithm, |b| {
b.generated(Box::new(SimpleGenerator::new(
params.width as isize,
params.height as isize,
)))
});
executor.run();
}

View file

@ -1,12 +0,0 @@
[package]
name = "labirust"
version = "0.3.0"
edition = "2021"
license = "MIT"
authors = ["JOLIMAITRE Matthieu <matthieu@imagevo.fr>"]
description = "Naive rust crate for implementing and testing maze solving Algorithms."
repository = "https://github.com/MajorBarnulf/labirust/"
[dependencies]
rand = "0.8"
termion = "1.5"

View file

@ -1,179 +0,0 @@
use std::time::Duration;
use crate::{labyrinth::generator::MazeGenerator, Maze};
use self::maze_state::{BuildableMazeState, Generated, MazeState, Provided, Unprovided};
pub mod maze_state {
use crate::{labyrinth::generator::MazeGenerator, Maze};
/// Describe the state of the [`Maze`] parameter in the builder of an [`crate::Executor`]. Not ment to be implemented.
pub trait MazeState {}
pub trait BuildableMazeState: MazeState {
fn get(&self) -> Maze;
}
pub struct Unprovided;
impl MazeState for Unprovided {}
pub struct Provided {
maze: Maze,
}
impl Provided {
pub fn new(maze: Maze) -> Self {
Self { maze }
}
}
impl MazeState for Provided {}
impl BuildableMazeState for Provided {
fn get(&self) -> Maze {
self.maze.clone()
}
}
pub struct Generated {
generator: Box<dyn MazeGenerator>,
}
impl Generated {
pub fn new<G>(generator: G) -> Self
where
G: MazeGenerator + 'static,
{
let generator = Box::new(generator);
Self { generator }
}
pub fn new_dyn(generator: Box<dyn MazeGenerator + 'static>) -> Self {
Self { generator }
}
}
impl MazeState for Generated {}
impl BuildableMazeState for Generated {
fn get(&self) -> Maze {
self.generator.generate()
}
}
}
/// Builder for an [`crate::Executor`], needs at least a [`Maze`].
pub struct ExecutorBuilder<MS>
where
MS: MazeState,
{
maze_state: MS,
delay: Duration,
}
pub(crate) fn new_builder() -> ExecutorBuilder<Unprovided> {
ExecutorBuilder {
maze_state: Unprovided,
delay: Duration::from_millis(100),
}
}
impl<MS: MazeState> ExecutorBuilder<MS> {
/// Provide a specific [`Maze`] for the execution.
pub fn maze(self, maze: Maze) -> ExecutorBuilder<Provided> {
let Self {
delay,
maze_state: _,
} = self;
ExecutorBuilder {
delay,
maze_state: Provided::new(maze),
}
}
/// Provide a generator to generate a [`Maze`] for the execution.
pub fn generated<G>(self, generator: G) -> ExecutorBuilder<Generated>
where
G: MazeGenerator + 'static,
{
let Self {
delay,
maze_state: _,
} = self;
ExecutorBuilder {
delay,
maze_state: Generated::new(generator),
}
}
/// Sets the delay between terminal redraws, default is 100ms.
pub fn delay_ms(self, delay: u64) -> Self {
let delay = Duration::from_millis(delay);
let Self {
maze_state,
delay: _,
} = self;
Self { maze_state, delay }
}
}
impl<MS: BuildableMazeState> ExecutorBuilder<MS> {
pub(crate) fn build(self) -> (Maze, Duration) {
let maze = self.maze_state.get();
let delay = self.delay;
(maze, delay)
}
}
pub enum DynMazeState {
None,
Provided(Provided),
Generated(Generated),
}
impl DynMazeState {
pub fn get(self) -> Option<Maze> {
match self {
DynMazeState::None => None,
DynMazeState::Provided(provided) => Some(provided.get()),
DynMazeState::Generated(generated) => Some(generated.get()),
}
}
}
pub struct DynExecutorBuilder {
maze: DynMazeState,
delay: Duration,
}
impl DynExecutorBuilder {
pub(crate) fn new() -> Self {
Self {
maze: DynMazeState::None,
delay: Duration::from_millis(100),
}
}
pub fn maze(self, maze: Maze) -> Self {
let maze = DynMazeState::Provided(Provided::new(maze));
let Self { maze: _, delay } = self;
Self { maze, delay }
}
pub fn generated(self, generator: Box<dyn MazeGenerator>) -> Self {
let maze = DynMazeState::Generated(Generated::new_dyn(generator));
let Self { maze: _, delay } = self;
Self { delay, maze }
}
pub fn delay_ms(self, delay: u64) -> Self {
let delay = Duration::from_millis(delay);
let Self { maze, delay: _ } = self;
Self { maze, delay }
}
pub(crate) fn build(self) -> (Maze, Duration) {
let maze = self.maze.get().expect("no buildable maze provided");
let delay = self.delay;
(maze, delay)
}
}

View file

@ -1,66 +0,0 @@
//! ## Generator
//!
//! This module contains raw functions generating mazes.
use std::collections::HashSet;
use rand::{prelude::SliceRandom, thread_rng};
use crate::{Maze, Pos};
/// Trait encapsulating the behavior of a type capable to create mazes.
pub trait MazeGenerator {
fn generate(&self) -> Maze;
}
/// Most common maze generation technique, recursively creating paths to unvisited cells, each time choosing next direction at random.
pub struct SimpleGenerator {
width: isize,
height: isize,
}
impl SimpleGenerator {
pub fn new(width: isize, height: isize) -> Self {
Self { height, width }
}
}
impl MazeGenerator for SimpleGenerator {
fn generate(&self) -> Maze {
let Self { width, height } = *self;
let mut result = Maze::new(
width,
height,
Pos::zero(),
(width - 1, height - 1).into(),
Vec::new(),
);
fn recursive(current: Pos, result: &mut Maze, visited: &mut HashSet<Pos>) {
visited.insert(current);
let mut adjascent_positions = result.adjascent(current);
adjascent_positions.shuffle(&mut thread_rng());
for neighbor in adjascent_positions {
if visited.contains(&neighbor) {
continue;
}
result.create_path(current, neighbor);
recursive(neighbor, result, visited);
}
}
let mut visited = HashSet::new();
let current = Pos::zero();
recursive(current, &mut result, &mut visited);
result
}
}
#[test]
fn generation() {
let generator = SimpleGenerator::new(10, 10);
let maze = generator.generate();
let text = maze.display(None);
println!("{text}");
}

View file

@ -1,8 +1,3 @@
//! ## Executor
//!
//! This module contains the definition of an [`Executor`], used to run an [`Algorithm`] and have a graphical output in the terminal.
//! This type is supposed to be created using the builder pattern (c.f. [`Executor`]`::build`).
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
thread, thread,
@ -11,10 +6,7 @@ use std::{
use crate::{Algorithm, Maze, Pos}; use crate::{Algorithm, Maze, Pos};
use self::builder::{ use self::builder::{new_builder, BuildableMazeState, ExecutorBuilder, Unprovided};
maze_state::{BuildableMazeState, Unprovided},
new_builder, DynExecutorBuilder, ExecutorBuilder,
};
/// A guess to pass to the current [`Executor`] at the end of every `progress` call. /// A guess to pass to the current [`Executor`] at the end of every `progress` call.
pub struct Guess(Vec<Pos>); pub struct Guess(Vec<Pos>);
@ -92,15 +84,21 @@ impl<'m> Context<'m> {
mod builder; mod builder;
/// A structure holding a [`Maze`] and iteratively solving it with a provided [`Algorithm`]. /// A structure holding a [`Maze`] and iteratively solving it with a provided [`Algorithm`].
pub struct Executor { pub struct Executor<Algo>
where
Algo: Algorithm,
{
delay: Duration, delay: Duration,
maze: Maze, maze: Maze,
algorithm: Box<dyn Algorithm>, algorithm: Algo,
} }
impl Executor { impl<A> Executor<A>
where
A: Algorithm,
{
/// Constructor. /// Constructor.
fn new(maze: Maze, algorithm: Box<dyn Algorithm>, delay: Duration) -> Self { fn new(maze: Maze, algorithm: A, delay: Duration) -> Self {
Self { Self {
maze, maze,
algorithm, algorithm,
@ -108,25 +106,13 @@ impl Executor {
} }
} }
pub fn build<'f, A, F, MS>(algorithm: A, builder: F) -> Self pub fn build<'f, F, MS>(algorithm: A, builder: F) -> Self
where where
A: Algorithm + 'static,
MS: BuildableMazeState, MS: BuildableMazeState,
F: Fn(ExecutorBuilder<Unprovided>) -> ExecutorBuilder<MS>, F: Fn(ExecutorBuilder<Unprovided>) -> ExecutorBuilder<MS>,
{ {
let operation = builder; let operation = builder;
let builder = (operation)(new_builder()); let mut builder = (operation)(new_builder());
let (maze, delay) = builder.build();
let algorithm = Box::new(algorithm);
Self::new(maze, algorithm, delay)
}
pub fn build_dyn<F>(algorithm: Box<dyn Algorithm>, builder: F) -> Self
where
F: Fn(DynExecutorBuilder) -> DynExecutorBuilder,
{
let operation = builder;
let builder = (operation)(DynExecutorBuilder::new());
let (maze, delay) = builder.build(); let (maze, delay) = builder.build();
Self::new(maze, algorithm, delay) Self::new(maze, algorithm, delay)
} }
@ -169,26 +155,25 @@ impl Executor {
fn draw(maze: &Maze, tried: &HashSet<Pos>, tick: usize, path: &Vec<Pos>) { fn draw(maze: &Maze, tried: &HashSet<Pos>, tick: usize, path: &Vec<Pos>) {
let mut overlay = HashMap::new(); let mut overlay = HashMap::new();
for position in tried { for position in tried {
overlay.insert(*position, ''); overlay.insert(*position, '#');
} }
for position in path {
overlay.insert(*position, '█');
}
overlay.insert(maze.start(), 'S');
overlay.insert(maze.end(), 'E');
overlay.insert(*path.last().unwrap(), 'G');
let grid = maze.display(Some(overlay)); for position in path {
let text = format!("tick {tick}:\n{grid}\n"); overlay.insert(*position, 'P');
}
overlay.insert(*path.last().unwrap(), 'x');
let text = maze.display(Some(overlay));
// DIRTY! // DIRTY!
// print the frame on top of the previous one // print the frame on top of the previous one
if tick > 0 { if tick > 0 {
let count = text.lines().count(); let count = text.lines().count() + 1;
let up = termion::cursor::Up(count as u16); let up = termion::cursor::Up(count as u16);
print!("{up}") print!("{up}")
} }
print!("{text}"); print!("tick {tick}:\n{text}\n");
} }
} }

57
src/executor/builder.rs Normal file
View file

@ -0,0 +1,57 @@
use std::time::Duration;
use crate::{labyrinth::generator::MazeGenerator, Maze};
pub trait MazeState {}
pub trait BuildableMazeState: MazeState {
fn get(self) -> Maze;
}
pub struct Unprovided;
impl MazeState for Unprovided {}
struct Provided {
maze: Maze,
}
impl MazeState for Provided {}
impl BuildableMazeState for Provided {
fn get(self) -> Maze {
self.maze
}
}
struct Generated {
generator: Box<dyn MazeGenerator>,
}
impl MazeState for Generated {}
impl BuildableMazeState for Generated {
fn get(mut self) -> Maze {
self.generator.generate()
}
}
pub struct ExecutorBuilder<MS>
where
MS: MazeState,
{
maze_state: MS,
delay: Duration,
}
pub fn new_builder() -> ExecutorBuilder<Unprovided> {
ExecutorBuilder {
maze_state: Unprovided,
delay: Duration::from_millis(100),
}
}
impl<MS: BuildableMazeState> ExecutorBuilder<MS> {
pub fn build(self) -> (Maze, Duration) {
let maze = self.maze_state.get();
let delay = self.delay;
(maze, delay)
}
}

View file

@ -12,16 +12,18 @@ pub use depth_first::DepthFirst;
#[test] #[test]
fn depth_first() { fn depth_first() {
use crate::{Executor, SimpleGenerator}; use crate::{generate, Executor};
let algorithm = DepthFirst::new(); let algorithm = DepthFirst::new();
let mut executor = Executor::build(algorithm, |b| b.generated(SimpleGenerator::new(40, 20))); let maze = generate(20, 20);
executor.run(); // let mut executor = Executor::new(maze, algorithm);
// executor.run();
} }
#[test] #[test]
fn breath_first() { fn breath_first() {
use crate::{Executor, SimpleGenerator}; use crate::{generate, Executor};
let algorithm = BreathFirst::new(); let algorithm = BreathFirst::new();
let mut executor = Executor::build(algorithm, |b| b.generated(SimpleGenerator::new(40, 20))); let maze = generate(20, 20);
executor.run(); // let mut executor = Executor::new(maze, algorithm);
// executor.run();
} }

View file

@ -0,0 +1,50 @@
//! ## Generator
//!
//! This module contains raw functions generating mazes.
use std::collections::HashSet;
use rand::{prelude::SliceRandom, thread_rng};
use crate::{Maze, Pos};
/// Most common maze generation technique, recursively creating paths to unvisited cells, each time choosing next direction at random.
pub fn generate(width: isize, height: isize) -> Maze {
let mut result = Maze::new(
width,
height,
Pos::zero(),
(width - 1, height - 1).into(),
Vec::new(),
);
fn recursive(current: Pos, result: &mut Maze, visited: &mut HashSet<Pos>) {
visited.insert(current);
let mut adjascent_positions = result.adjascent(current);
adjascent_positions.shuffle(&mut thread_rng());
for neighbor in adjascent_positions {
if visited.contains(&neighbor) {
continue;
}
result.create_path(current, neighbor);
recursive(neighbor, result, visited);
}
}
let mut visited = HashSet::new();
let current = Pos::zero();
recursive(current, &mut result, &mut visited);
result
}
#[test]
fn generation() {
let maze = generate(20, 20);
let text = maze.display(None);
println!("{text}");
}
pub trait MazeGenerator {
fn generate(&mut self) -> Maze;
}

View file

@ -14,8 +14,5 @@ mod position;
pub use algorithm::Algorithm; pub use algorithm::Algorithm;
pub use executor::{Context, Executor, Guess, Insight}; pub use executor::{Context, Executor, Guess, Insight};
pub use labyrinth::{ pub use labyrinth::{generator::generate, Maze};
generator::{MazeGenerator, SimpleGenerator},
Maze,
};
pub use position::Pos; pub use position::Pos;