745 lines
23 KiB
Rust
745 lines
23 KiB
Rust
use std::fmt::Display;
|
|
|
|
use colored::Colorize;
|
|
|
|
use crate::misc::Map;
|
|
|
|
use super::{
|
|
common::{Dimension, Direction, PathField},
|
|
Position, COLORS,
|
|
};
|
|
|
|
#[derive(Default, Clone)]
|
|
pub struct BruteforceField {
|
|
pub blocked: bool,
|
|
underground_vertical: bool,
|
|
underground_horizontal: bool,
|
|
}
|
|
|
|
static MAX_UNDERGROUND_LENGTH: u8 = 6;
|
|
|
|
#[derive(Clone)]
|
|
pub struct BruteforceBuilder {
|
|
map: Map<BruteforceField>,
|
|
path: Vec<[(Position, Direction); 2]>,
|
|
}
|
|
|
|
impl BruteforceBuilder {
|
|
pub fn new(width: usize, height: usize) -> Self {
|
|
Self {
|
|
map: Map::new(width, height),
|
|
path: Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn add_path(&mut self, start: (Position, Direction), end: (Position, Direction)) {
|
|
self.path.push([start, end]);
|
|
}
|
|
|
|
pub fn set_blocked(&mut self, x: usize, y: usize, blocked: bool) {
|
|
self.map.get_mut(x, y).blocked = blocked;
|
|
}
|
|
|
|
pub fn set_blocked_range(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, blocked: bool) {
|
|
for x in x1..=x2 {
|
|
for y in y1..=y2 {
|
|
self.set_blocked(x, y, blocked);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn build(self) -> Bruteforce {
|
|
let dimension = Dimension {
|
|
width: self.map.width,
|
|
height: self.map.height,
|
|
};
|
|
|
|
let mut b = Bruteforce {
|
|
map: self.map,
|
|
problems: Vec::new(),
|
|
pointer_stack: vec![0],
|
|
solution_count: 0,
|
|
count: 0,
|
|
dimension,
|
|
};
|
|
|
|
for [start, end] in self.path {
|
|
b.map.get_mut(start.0.x, start.0.y).blocked = true;
|
|
b.map.get_mut(end.0.x, end.0.y).blocked = true;
|
|
b.problems.push(Problem {
|
|
path: vec![PathField::Belt {
|
|
pos: start.0,
|
|
dir: start.1,
|
|
}],
|
|
end_pos: end.0,
|
|
end_dir: end.1,
|
|
finished: false,
|
|
})
|
|
}
|
|
|
|
b
|
|
}
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
struct Problem {
|
|
path: Vec<PathField>,
|
|
end_pos: Position,
|
|
end_dir: Direction,
|
|
finished: bool,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Bruteforce {
|
|
map: Map<BruteforceField>,
|
|
dimension: Dimension,
|
|
problems: Vec<Problem>,
|
|
pointer_stack: Vec<usize>,
|
|
solution_count: u128,
|
|
count: u128,
|
|
}
|
|
|
|
impl Bruteforce {
|
|
pub fn modify_pointer(&self) -> usize {
|
|
self.pointer_stack
|
|
.get(self.pointer_stack.len().saturating_sub(2))
|
|
.copied()
|
|
.unwrap_or(0)
|
|
}
|
|
|
|
fn add_pointer(&self) -> usize {
|
|
self.pointer_stack.last().copied().unwrap_or(0)
|
|
}
|
|
|
|
fn internal_apply_path_field(&mut self, i: usize, path_field: PathField) {
|
|
match &path_field {
|
|
PathField::Belt { pos, dir: _ } => self.map.get_mut(pos.x, pos.y).blocked = true,
|
|
PathField::Underground { pos, dir, len } => {
|
|
self.map.get_mut(pos.x, pos.y).blocked = true;
|
|
|
|
for i in 0..=*len {
|
|
let mid_pos = pos.in_direction(dir, i.into(), &self.dimension).unwrap();
|
|
if dir.vertical() {
|
|
self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = true;
|
|
} else {
|
|
self.map
|
|
.get_mut(mid_pos.x, mid_pos.y)
|
|
.underground_horizontal = true;
|
|
}
|
|
}
|
|
|
|
let end_pos = { pos.in_direction(dir, *len as usize, &self.dimension) }.unwrap();
|
|
self.map.get_mut(end_pos.x, end_pos.y).blocked = true;
|
|
}
|
|
}
|
|
self.problems[i].path.push(path_field);
|
|
}
|
|
|
|
fn internal_remove_path_field(&mut self, i: usize) {
|
|
match self.problems[i].path.pop().unwrap() {
|
|
PathField::Belt { pos, dir: _ } => self.map.get_mut(pos.x, pos.y).blocked = false,
|
|
PathField::Underground { pos, dir, len } => {
|
|
self.map.get_mut(pos.x, pos.y).blocked = false;
|
|
|
|
for i in 0..=len {
|
|
let mid_pos = pos.in_direction(&dir, i.into(), &self.dimension).unwrap();
|
|
if dir.vertical() {
|
|
self.map.get_mut(mid_pos.x, mid_pos.y).underground_vertical = false;
|
|
} else {
|
|
self.map
|
|
.get_mut(mid_pos.x, mid_pos.y)
|
|
.underground_horizontal = false;
|
|
}
|
|
}
|
|
|
|
let end_pos = pos.in_direction(&dir, len.into(), &self.dimension).unwrap();
|
|
self.map.get_mut(end_pos.x, end_pos.y).blocked = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn apply_path_field(&mut self, path_field: PathField) {
|
|
self.internal_apply_path_field(self.add_pointer(), path_field);
|
|
|
|
// set finished
|
|
let i = self.add_pointer();
|
|
// dbg!(i, self.check_finish(i));
|
|
self.problems[i].finished = self.check_finish(i);
|
|
|
|
// advance pointer
|
|
|
|
let current_pointer = self.add_pointer();
|
|
let mut pointer = current_pointer;
|
|
|
|
for i in 1..self.problems.len() {
|
|
if !self.problems[(current_pointer + i) % self.problems.len()].finished {
|
|
pointer = (current_pointer + i) % self.problems.len();
|
|
break;
|
|
}
|
|
}
|
|
|
|
self.pointer_stack.push(pointer);
|
|
}
|
|
|
|
fn remove_path_field(&mut self) {
|
|
self.internal_remove_path_field(self.modify_pointer());
|
|
|
|
// remove finish
|
|
let i = self.modify_pointer();
|
|
self.problems[i].finished = false;
|
|
|
|
// restore pointer
|
|
self.pointer_stack.pop();
|
|
}
|
|
|
|
fn modify_path_field(&mut self, path_field: PathField) {
|
|
let i = self.modify_pointer();
|
|
let last = *self.problems[i].path.last().unwrap();
|
|
|
|
match (last, &path_field) {
|
|
(PathField::Belt { pos: _, dir: _ }, PathField::Belt { pos: _, dir: _ }) => {}
|
|
(PathField::Belt { pos: _, dir: _ }, PathField::Underground { pos, dir, len }) => {
|
|
let end_pos = pos
|
|
.in_direction(dir, *len as usize, &self.dimension)
|
|
.unwrap();
|
|
|
|
self.map.get_mut(end_pos.x, end_pos.y).blocked = true;
|
|
|
|
for l in 0..=*len {
|
|
let p = pos.in_direction(dir, l as usize, &self.dimension).unwrap();
|
|
match dir.vertical() {
|
|
true => self.map.get_mut(p.x, p.y).underground_vertical = true,
|
|
false => self.map.get_mut(p.x, p.y).underground_horizontal = true,
|
|
}
|
|
}
|
|
}
|
|
(
|
|
PathField::Underground {
|
|
pos: _,
|
|
dir: _,
|
|
len: _,
|
|
},
|
|
PathField::Belt { pos: _, dir: _ },
|
|
) => {
|
|
unreachable!()
|
|
}
|
|
(
|
|
PathField::Underground {
|
|
pos,
|
|
dir,
|
|
len: last_len,
|
|
},
|
|
PathField::Underground {
|
|
pos: _,
|
|
dir: _,
|
|
len: new_len,
|
|
},
|
|
) => {
|
|
let last_end_pos = pos
|
|
.in_direction(&dir, last_len as usize, &self.dimension)
|
|
.unwrap();
|
|
let new_end_pos = pos
|
|
.in_direction(&dir, *new_len as usize, &self.dimension)
|
|
.unwrap();
|
|
|
|
self.map.get_mut(last_end_pos.x, last_end_pos.y).blocked = false;
|
|
self.map.get_mut(new_end_pos.x, new_end_pos.y).blocked = true;
|
|
|
|
match last_len < *new_len {
|
|
true => {
|
|
for l in last_len + 1..=*new_len {
|
|
let p = pos.in_direction(&dir, l as usize, &self.dimension).unwrap();
|
|
match dir.vertical() {
|
|
true => self.map.get_mut(p.x, p.y).underground_vertical = true,
|
|
false => self.map.get_mut(p.x, p.y).underground_horizontal = true,
|
|
}
|
|
}
|
|
}
|
|
false => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
|
|
*self.problems[i].path.last_mut().unwrap() = path_field;
|
|
|
|
// set finished
|
|
self.problems[i].finished = self.check_finish(i);
|
|
}
|
|
|
|
fn check_finish(&self, i: usize) -> bool {
|
|
match self.problems[i].path.last().unwrap() {
|
|
PathField::Belt { pos, dir } => pos
|
|
.in_direction(dir, 1, &self.dimension)
|
|
.filter(|p| {
|
|
p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse()
|
|
})
|
|
.is_some(),
|
|
PathField::Underground { pos, dir, len } => pos
|
|
.in_direction(dir, *len as usize + 1, &self.dimension)
|
|
.filter(|p| {
|
|
p == &self.problems[i].end_pos && dir != &self.problems[i].end_dir.reverse()
|
|
})
|
|
.is_some(),
|
|
}
|
|
}
|
|
|
|
fn modify_underground(&mut self, pos: &Position, dir: &Direction, len: u8) -> bool {
|
|
if len >= MAX_UNDERGROUND_LENGTH {
|
|
return false;
|
|
}
|
|
|
|
if len == 2
|
|
&& match dir.vertical() {
|
|
true => self.map.get(pos.x, pos.y).underground_vertical,
|
|
false => self.map.get(pos.x, pos.y).underground_horizontal,
|
|
}
|
|
{
|
|
return false;
|
|
}
|
|
|
|
let end_pos = match pos.in_direction(dir, len as usize, &self.dimension) {
|
|
Some(s) => s,
|
|
None => {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
if match dir.vertical() {
|
|
true => self.map.get(end_pos.x, end_pos.y).underground_vertical,
|
|
false => self.map.get(end_pos.x, end_pos.y).underground_horizontal,
|
|
} {
|
|
return false;
|
|
}
|
|
|
|
if !self.map.get(end_pos.x, end_pos.y).blocked {
|
|
self.modify_path_field(PathField::Underground {
|
|
pos: *pos,
|
|
dir: *dir,
|
|
len,
|
|
});
|
|
return true;
|
|
}
|
|
|
|
self.modify_underground(pos, dir, len + 1)
|
|
}
|
|
|
|
// fn modify_underground(&mut self, pos: &Position, dir: &Direction, len: u8) -> bool {
|
|
// dbg!(pos, dir, len);
|
|
|
|
// if match dir.vertical() {
|
|
// true => self.map.get(pos.x, pos.y).underground_vertical,
|
|
// false => self.map.get(pos.x, pos.y).underground_horizontal,
|
|
// } {
|
|
// return false;
|
|
// }
|
|
// for l in len..MAX_UNDERGROUND_LENGTH {
|
|
// if let Some(p) = self.pos_in_direction(pos, dir, l as usize) {
|
|
// dbg!(l, &p);
|
|
// if !self.map.get(p.x, p.y).blocked {
|
|
// if !(1..l)
|
|
// .filter_map(|i| self.pos_in_direction(pos, dir, i as usize))
|
|
// .any(|local_pos| !match dir.vertical() {
|
|
// true => self.map.get(local_pos.x, local_pos.y).underground_vertical,
|
|
// false => {
|
|
// self.map
|
|
// .get(local_pos.x, local_pos.y)
|
|
// .underground_horizontal
|
|
// }
|
|
// })
|
|
// {
|
|
// dbg!(true);
|
|
// self.modify_path_field(PathField::Underground {
|
|
// pos: *pos,
|
|
// dir: *dir,
|
|
// len: l,
|
|
// });
|
|
// return true;
|
|
// } else {
|
|
// return false;
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// false
|
|
// }
|
|
|
|
fn modify_remove(&mut self) -> bool {
|
|
if let Some([second_last, last]) = self.modify_path().last_chunk().copied() {
|
|
match last {
|
|
PathField::Belt { pos, dir } => {
|
|
if second_last.dir() == &dir {
|
|
self.modify_path_field(PathField::Belt {
|
|
pos,
|
|
dir: second_last.dir().clockwise(),
|
|
});
|
|
if self.is_next_free(&pos, &second_last.dir().clockwise()) {
|
|
return true;
|
|
} else {
|
|
return self.modify_remove();
|
|
}
|
|
}
|
|
|
|
if second_last.dir().clockwise() == dir {
|
|
self.modify_path_field(PathField::Belt {
|
|
pos,
|
|
dir: second_last.dir().counter_clockwise(),
|
|
});
|
|
if self.is_next_free(&pos, &second_last.dir().counter_clockwise()) {
|
|
return true;
|
|
} else {
|
|
return self.modify_remove();
|
|
}
|
|
}
|
|
|
|
if second_last.dir().counter_clockwise() == dir
|
|
&& self.modify_underground(&pos, second_last.dir(), 2)
|
|
{
|
|
let (p, d) = self
|
|
.modify_path()
|
|
.last()
|
|
.unwrap()
|
|
.end_pos(&self.dimension)
|
|
.unwrap();
|
|
|
|
if self.is_next_free(&p, &d) {
|
|
return true;
|
|
} else {
|
|
return self.modify_remove();
|
|
}
|
|
}
|
|
}
|
|
PathField::Underground { pos, dir, len } => {
|
|
if self.modify_underground(&pos, &dir, len + 1) {
|
|
let (p, d) = self
|
|
.modify_path()
|
|
.last()
|
|
.unwrap()
|
|
.end_pos(&self.dimension)
|
|
.unwrap();
|
|
|
|
if self.is_next_free(&p, &d) {
|
|
return true;
|
|
} else {
|
|
return self.modify_remove();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self.remove_path_field();
|
|
self.modify_remove()
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
|
|
fn modify_path(&self) -> &Vec<PathField> {
|
|
&self.problems[self.modify_pointer()].path
|
|
}
|
|
|
|
fn add_path(&self) -> &Vec<PathField> {
|
|
&self.problems[self.add_pointer()].path
|
|
}
|
|
|
|
// fn modify_path_mut(&mut self) -> &mut Vec<PathField> {
|
|
// let i = self.modify_pointer();
|
|
// &mut self.problems[i].path
|
|
// }
|
|
|
|
fn is_next_free(&self, pos: &Position, dir: &Direction) -> bool {
|
|
let i = self.modify_pointer();
|
|
{ pos.in_direction(dir, 1, &self.dimension) }
|
|
.filter(|p| !self.map.get(p.x, p.y).blocked || self.problems[i].end_pos == *p)
|
|
.is_some()
|
|
}
|
|
|
|
// Add an Path elemeent
|
|
fn add(&mut self) -> bool {
|
|
let (pos, dir) = self
|
|
.add_path()
|
|
.last()
|
|
.unwrap()
|
|
.end_pos(&self.dimension)
|
|
.unwrap();
|
|
|
|
if let Some(p) = pos.in_direction(&dir, 1, &self.dimension) {
|
|
if !self.map.get(p.x, p.y).blocked {
|
|
self.apply_path_field(PathField::Belt { pos: p, dir });
|
|
return self.is_next_free(&p, &dir);
|
|
}
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
pub fn next_state(&mut self) -> bool {
|
|
self.count += 1;
|
|
|
|
if self.add() {
|
|
return true;
|
|
}
|
|
|
|
self.modify_remove()
|
|
}
|
|
|
|
pub fn next_finish_state(&mut self) -> bool {
|
|
while self.next_state() {
|
|
// if self.count % 1000000 == 0 {
|
|
// println!("{}\n{}", self.count, self);
|
|
// }
|
|
if self.problems.iter().all(|p| p.finished) {
|
|
self.solution_count += 1;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
false
|
|
}
|
|
|
|
pub fn get_paths(&self) -> Vec<Vec<PathField>> {
|
|
self.problems.iter().map(|p| p.path.clone()).collect()
|
|
}
|
|
|
|
pub fn cost(&self) -> f64 {
|
|
self.problems
|
|
.iter()
|
|
.flat_map(|p| {
|
|
p.path.iter().map(|f| match f {
|
|
PathField::Belt { pos: _, dir: _ } => 1.5,
|
|
PathField::Underground {
|
|
pos: _,
|
|
dir: _,
|
|
len: _,
|
|
} => 17.5,
|
|
})
|
|
})
|
|
.sum()
|
|
}
|
|
|
|
pub fn count(&self) -> u128 {
|
|
self.count
|
|
}
|
|
|
|
pub fn solution_count(&self) -> u128 {
|
|
self.solution_count
|
|
}
|
|
}
|
|
|
|
impl Display for Bruteforce {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let width_digits = self.map.width.ilog10() + 1;
|
|
let height_digits = self.map.height.ilog10() + 1;
|
|
|
|
// print header
|
|
for i in 0..width_digits {
|
|
let d = width_digits - i - 1;
|
|
// padding
|
|
for _ in 0..height_digits {
|
|
write!(f, " ")?;
|
|
}
|
|
|
|
for x in 0..self.map.width {
|
|
let digits = x / (usize::pow(10, d));
|
|
if digits == 0 && d > 0 {
|
|
write!(f, " ")?;
|
|
} else {
|
|
write!(f, "{}", char::from_u32((digits % 10) as u32 + 48).unwrap())?;
|
|
}
|
|
}
|
|
|
|
writeln!(f)?;
|
|
}
|
|
|
|
let mut m: Map<Option<(usize, &str)>> = Map::new(self.map.width, self.map.height);
|
|
|
|
for (i, problem) in self.problems.iter().enumerate() {
|
|
if problem.finished {
|
|
m.set(problem.end_pos.x, problem.end_pos.y, Some((i, "T")));
|
|
} else {
|
|
m.set(problem.end_pos.x, problem.end_pos.y, Some((i, "t")));
|
|
}
|
|
for p in &problem.path {
|
|
match p {
|
|
PathField::Belt { pos, dir } => match dir {
|
|
Direction::Up => m.set(pos.x, pos.y, Some((i, "↑"))),
|
|
Direction::Right => m.set(pos.x, pos.y, Some((i, "→"))),
|
|
Direction::Down => m.set(pos.x, pos.y, Some((i, "↓"))),
|
|
Direction::Left => m.set(pos.x, pos.y, Some((i, "←"))),
|
|
},
|
|
PathField::Underground { pos, dir, len } => {
|
|
match dir {
|
|
Direction::Up => m.set(pos.x, pos.y, Some((i, "↟"))),
|
|
Direction::Right => m.set(pos.x, pos.y, Some((i, "↠"))),
|
|
Direction::Down => m.set(pos.x, pos.y, Some((i, "↡"))),
|
|
Direction::Left => m.set(pos.x, pos.y, Some((i, "↞"))),
|
|
};
|
|
let end_pos = pos
|
|
.in_direction(dir, *len as usize, &self.dimension)
|
|
.unwrap();
|
|
match dir {
|
|
Direction::Up => m.set(end_pos.x, end_pos.y, Some((i, "↥"))),
|
|
Direction::Right => m.set(end_pos.x, end_pos.y, Some((i, "↦"))),
|
|
Direction::Down => m.set(end_pos.x, end_pos.y, Some((i, "↧"))),
|
|
Direction::Left => m.set(end_pos.x, end_pos.y, Some((i, "↤"))),
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Print body
|
|
|
|
for y in 0..self.map.height {
|
|
write!(f, "{:1$}", y, height_digits as usize)?;
|
|
|
|
for x in 0..self.map.width {
|
|
if let Some((i, c)) = m.get(x, y) {
|
|
write!(f, "{}", c.color(COLORS[*i]))?;
|
|
} else if self.map.get(x, y).blocked {
|
|
write!(f, "#")?;
|
|
} else if self.map.get(x, y).underground_horizontal {
|
|
write!(f, "_")?;
|
|
} else if self.map.get(x, y).underground_vertical {
|
|
write!(f, "|")?;
|
|
} else if x % 8 == 0 || y % 8 == 0 {
|
|
write!(f, "∙")?;
|
|
} else {
|
|
write!(f, " ")?;
|
|
}
|
|
}
|
|
|
|
writeln!(f)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
use super::problems;
|
|
|
|
macro_rules! test_bruteforce {
|
|
($i:ident $x:expr) => {
|
|
#[test]
|
|
fn $i() {
|
|
let mut b = problems::$i();
|
|
|
|
while b.next_finish_state() {}
|
|
|
|
assert_eq!(b.solution_count(), $x);
|
|
}
|
|
};
|
|
($i:ident $x:expr; $($is:ident $xs:expr);+) => {
|
|
test_bruteforce!($i $x);
|
|
test_bruteforce!($($is $xs);+);
|
|
};
|
|
}
|
|
|
|
test_bruteforce!(simple 9; mid 238240; snake 5);
|
|
}
|
|
|
|
pub mod problems {
|
|
use super::*;
|
|
|
|
pub fn simple() -> Bruteforce {
|
|
let mut b = BruteforceBuilder::new(6, 8);
|
|
|
|
b.add_path(
|
|
(Position::new(1, 0), Direction::Down),
|
|
(Position::new(0, 0), Direction::Up),
|
|
);
|
|
|
|
b.add_path(
|
|
(Position::new(4, 0), Direction::Down),
|
|
(Position::new(1, 7), Direction::Up),
|
|
);
|
|
|
|
b.set_blocked_range(0, 2, 5, 5, true);
|
|
|
|
b.build()
|
|
}
|
|
|
|
pub fn mid() -> Bruteforce {
|
|
let mut b = BruteforceBuilder::new(6, 6);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 0), Direction::Down),
|
|
(Position::new(5, 5), Direction::Down),
|
|
);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 5), Direction::Up),
|
|
(Position::new(5, 0), Direction::Up),
|
|
);
|
|
|
|
b.build()
|
|
}
|
|
|
|
pub fn snake() -> Bruteforce {
|
|
let mut p = BruteforceBuilder::new(14, 3);
|
|
|
|
p.add_path(
|
|
(Position::new(0, 0), Direction::Right),
|
|
(Position::new(13, 0), Direction::Right),
|
|
);
|
|
p.add_path(
|
|
(Position::new(0, 1), Direction::Right),
|
|
(Position::new(13, 1), Direction::Right),
|
|
);
|
|
p.add_path(
|
|
(Position::new(0, 2), Direction::Right),
|
|
(Position::new(13, 2), Direction::Right),
|
|
);
|
|
|
|
p.set_blocked_range(3, 2, 10, 2, true);
|
|
|
|
p.build()
|
|
}
|
|
|
|
pub fn weaving() -> Bruteforce {
|
|
let mut b = BruteforceBuilder::new(14, 6);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 0), Direction::Right),
|
|
(Position::new(13, 0), Direction::Right),
|
|
);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 1), Direction::Right),
|
|
(Position::new(13, 1), Direction::Right),
|
|
);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 2), Direction::Right),
|
|
(Position::new(13, 2), Direction::Right),
|
|
);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 3), Direction::Right),
|
|
(Position::new(13, 3), Direction::Right),
|
|
);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 4), Direction::Right),
|
|
(Position::new(13, 4), Direction::Right),
|
|
);
|
|
|
|
b.add_path(
|
|
(Position::new(0, 5), Direction::Right),
|
|
(Position::new(13, 5), Direction::Right),
|
|
);
|
|
|
|
// b.set_blocked_range(7, 2, 10, 2, true);
|
|
// b.set_blocked_range(7, 3, 10, 4, true);
|
|
|
|
b.set_blocked_range(3, 2, 10, 3, true);
|
|
b.set_blocked(2, 0, true);
|
|
b.set_blocked(11, 0, true);
|
|
b.set_blocked(2, 5, true);
|
|
b.set_blocked(11, 5, true);
|
|
|
|
b.build()
|
|
}
|
|
}
|