Compare commits
10 commits
a7ce6ffb56
...
86bd6fc789
Author | SHA1 | Date | |
---|---|---|---|
86bd6fc789 | |||
e8102f0e72 | |||
c260404065 | |||
618c6d57e8 | |||
cf133e462f | |||
33f808f0ad | |||
82912dbc44 | |||
31f2e25cdc | |||
b21dc88b68 | |||
d0c44cdcbe |
19 changed files with 633 additions and 156 deletions
236
Cargo.lock
generated
236
Cargo.lock
generated
|
@ -2,6 +2,23 @@
|
||||||
# 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"
|
||||||
|
@ -14,6 +31,45 @@ 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"
|
||||||
|
@ -25,14 +81,69 @@ 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.1.1"
|
version = "0.3.0"
|
||||||
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"
|
||||||
|
@ -45,12 +156,60 @@ 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"
|
||||||
|
@ -99,6 +258,32 @@ 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"
|
||||||
|
@ -111,8 +296,57 @@ 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"
|
||||||
|
|
14
Cargo.toml
14
Cargo.toml
|
@ -1,12 +1,2 @@
|
||||||
[package]
|
[workspace]
|
||||||
name = "labirust"
|
members = ["labirust", "labirust-cli"]
|
||||||
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"
|
|
||||||
|
|
12
labirust-cli/Cargo.toml
Normal file
12
labirust-cli/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[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"] }
|
12
labirust-cli/README.md
Normal file
12
labirust-cli/README.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# labirust-cli
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
A cli to run labirust algorithms.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# through cargo
|
||||||
|
cargo install labirust-cli
|
||||||
|
```
|
58
labirust-cli/src/main.rs
Normal file
58
labirust-cli/src/main.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
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();
|
||||||
|
}
|
12
labirust/Cargo.toml
Normal file
12
labirust/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[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"
|
|
@ -14,14 +14,19 @@ 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 clone this repo and run the tests to see mazes solving themselves on the terminal.
|
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.
|
||||||
|
|
||||||
for you to see anything during the execution of tests, don't forget to add these arguments:
|
|
||||||
```sh
|
```sh
|
||||||
-- --nocapture
|
# installation
|
||||||
|
cargo install labirust-cli
|
||||||
|
|
||||||
# example:
|
# usage
|
||||||
cargo test -- implementations::breath_first --nocapture
|
labirust-cli --help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
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"
|
||||||
|
```
|
|
@ -1,3 +1,8 @@
|
||||||
|
//! ## 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,
|
||||||
|
@ -6,7 +11,10 @@ use std::{
|
||||||
|
|
||||||
use crate::{Algorithm, Maze, Pos};
|
use crate::{Algorithm, Maze, Pos};
|
||||||
|
|
||||||
use self::builder::{new_builder, BuildableMazeState, ExecutorBuilder, Unprovided};
|
use self::builder::{
|
||||||
|
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>);
|
||||||
|
@ -84,21 +92,15 @@ 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<Algo>
|
pub struct Executor {
|
||||||
where
|
|
||||||
Algo: Algorithm,
|
|
||||||
{
|
|
||||||
delay: Duration,
|
delay: Duration,
|
||||||
maze: Maze,
|
maze: Maze,
|
||||||
algorithm: Algo,
|
algorithm: Box<dyn Algorithm>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A> Executor<A>
|
impl Executor {
|
||||||
where
|
|
||||||
A: Algorithm,
|
|
||||||
{
|
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
fn new(maze: Maze, algorithm: A, delay: Duration) -> Self {
|
fn new(maze: Maze, algorithm: Box<dyn Algorithm>, delay: Duration) -> Self {
|
||||||
Self {
|
Self {
|
||||||
maze,
|
maze,
|
||||||
algorithm,
|
algorithm,
|
||||||
|
@ -106,13 +108,25 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build<'f, F, MS>(algorithm: A, builder: F) -> Self
|
pub fn build<'f, A, 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 mut builder = (operation)(new_builder());
|
let 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)
|
||||||
}
|
}
|
||||||
|
@ -155,25 +169,26 @@ where
|
||||||
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 {
|
for position in path {
|
||||||
overlay.insert(*position, 'P');
|
overlay.insert(*position, '█');
|
||||||
}
|
}
|
||||||
|
overlay.insert(maze.start(), 'S');
|
||||||
|
overlay.insert(maze.end(), 'E');
|
||||||
|
overlay.insert(*path.last().unwrap(), 'G');
|
||||||
|
|
||||||
overlay.insert(*path.last().unwrap(), 'x');
|
let grid = maze.display(Some(overlay));
|
||||||
|
let text = format!("tick {tick}:\n{grid}\n");
|
||||||
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() + 1;
|
let count = text.lines().count();
|
||||||
let up = termion::cursor::Up(count as u16);
|
let up = termion::cursor::Up(count as u16);
|
||||||
print!("{up}")
|
print!("{up}")
|
||||||
}
|
}
|
||||||
|
|
||||||
print!("tick {tick}:\n{text}\n");
|
print!("{text}");
|
||||||
}
|
}
|
||||||
}
|
}
|
179
labirust/src/executor/builder.rs
Normal file
179
labirust/src/executor/builder.rs
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,18 +12,16 @@ pub use depth_first::DepthFirst;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn depth_first() {
|
fn depth_first() {
|
||||||
use crate::{generate, Executor};
|
use crate::{Executor, SimpleGenerator};
|
||||||
let algorithm = DepthFirst::new();
|
let algorithm = DepthFirst::new();
|
||||||
let maze = generate(20, 20);
|
let mut executor = Executor::build(algorithm, |b| b.generated(SimpleGenerator::new(40, 20)));
|
||||||
// let mut executor = Executor::new(maze, algorithm);
|
executor.run();
|
||||||
// executor.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn breath_first() {
|
fn breath_first() {
|
||||||
use crate::{generate, Executor};
|
use crate::{Executor, SimpleGenerator};
|
||||||
let algorithm = BreathFirst::new();
|
let algorithm = BreathFirst::new();
|
||||||
let maze = generate(20, 20);
|
let mut executor = Executor::build(algorithm, |b| b.generated(SimpleGenerator::new(40, 20)));
|
||||||
// let mut executor = Executor::new(maze, algorithm);
|
executor.run();
|
||||||
// executor.run();
|
|
||||||
}
|
}
|
66
labirust/src/labyrinth/generator.rs
Normal file
66
labirust/src/labyrinth/generator.rs
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
//! ## 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}");
|
||||||
|
}
|
|
@ -14,5 +14,8 @@ 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::{generator::generate, Maze};
|
pub use labyrinth::{
|
||||||
|
generator::{MazeGenerator, SimpleGenerator},
|
||||||
|
Maze,
|
||||||
|
};
|
||||||
pub use position::Pos;
|
pub use position::Pos;
|
|
@ -1,57 +0,0 @@
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
//! ## 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;
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue