148 lines
3.6 KiB
Rust
148 lines
3.6 KiB
Rust
use std::io::{self, Write};
|
|
|
|
use termcolor::{ColorSpec, StandardStream, WriteColor};
|
|
|
|
use crate::prelude::*;
|
|
|
|
#[derive(Clone, Debug, Copy)]
|
|
pub enum PathField {
|
|
Belt {
|
|
pos: Position,
|
|
dir: Direction,
|
|
},
|
|
Underground {
|
|
pos: Position,
|
|
dir: Direction,
|
|
len: u8,
|
|
},
|
|
}
|
|
|
|
impl PathField {
|
|
pub fn pos(&self) -> &Position {
|
|
match self {
|
|
PathField::Belt { pos, dir: _ } => pos,
|
|
PathField::Underground {
|
|
pos,
|
|
dir: _,
|
|
len: _,
|
|
} => pos,
|
|
}
|
|
}
|
|
|
|
pub fn dir(&self) -> &Direction {
|
|
match self {
|
|
PathField::Belt { pos: _, dir } => dir,
|
|
PathField::Underground {
|
|
pos: _,
|
|
dir,
|
|
len: _,
|
|
} => dir,
|
|
}
|
|
}
|
|
|
|
pub fn end_pos(&self) -> (Position, Direction) {
|
|
match self {
|
|
PathField::Belt { pos, dir } => (*pos, *dir),
|
|
PathField::Underground { pos, dir, len } => {
|
|
(pos.in_direction(dir, *len as PositionType), *dir)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn offset(&self, offset: &Position) -> Self {
|
|
match self {
|
|
PathField::Belt { pos, dir } => PathField::Belt {
|
|
pos: Position::new(pos.x + offset.x, pos.y + offset.y),
|
|
dir: *dir,
|
|
},
|
|
PathField::Underground { pos, dir, len } => PathField::Underground {
|
|
pos: Position::new(pos.x + offset.x, pos.y + offset.y),
|
|
dir: *dir,
|
|
len: *len,
|
|
},
|
|
}
|
|
}
|
|
|
|
pub fn cost(&self) -> usize {
|
|
match self {
|
|
PathField::Belt { pos: _, dir: _ } => 150,
|
|
PathField::Underground {
|
|
pos: _,
|
|
dir: _,
|
|
len: _,
|
|
} => 1750,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn print_map<F>(width: i32, height: i32, f: F) -> io::Result<()>
|
|
where
|
|
F: Fn(i32, i32) -> (ColorSpec, &'static str),
|
|
{
|
|
let stdout = &mut StandardStream::stdout(termcolor::ColorChoice::Always);
|
|
|
|
let width_digits = (width - 1).ilog10() + 1;
|
|
let height_digits = (height - 1).ilog10() + 1;
|
|
|
|
// print header
|
|
for i in 0..width_digits {
|
|
let d = width_digits - i - 1;
|
|
|
|
//padding
|
|
for _ in 0..height_digits {
|
|
write!(stdout, " ")?;
|
|
}
|
|
|
|
for x in 0..width {
|
|
let digits = x / (i32::pow(10, d));
|
|
if digits == 0 && d > 0 {
|
|
write!(stdout, " ")?;
|
|
} else {
|
|
write!(
|
|
stdout,
|
|
"{}",
|
|
char::from_u32((digits % 10) as u32 + 48).unwrap()
|
|
)?;
|
|
}
|
|
}
|
|
writeln!(stdout)?;
|
|
}
|
|
|
|
for y in 0..height {
|
|
write!(stdout, "{:1$}", y, height_digits as usize)?;
|
|
|
|
for x in 0..width {
|
|
let (c, s) = f(x, y);
|
|
stdout.set_color(&c)?;
|
|
write!(stdout, "{:1}", s)?;
|
|
stdout.reset()?;
|
|
}
|
|
|
|
writeln!(stdout, "{:1$}", y, height_digits as usize)?;
|
|
}
|
|
|
|
for i in 0..width_digits {
|
|
let d = width_digits - i - 1;
|
|
|
|
//padding
|
|
for _ in 0..height_digits {
|
|
write!(stdout, " ")?;
|
|
}
|
|
|
|
for x in 0..width {
|
|
let digits = x / (i32::pow(10, d));
|
|
if digits == 0 && d > 0 {
|
|
write!(stdout, " ")?;
|
|
} else {
|
|
write!(
|
|
stdout,
|
|
"{}",
|
|
char::from_u32((digits % 10) as u32 + 48).unwrap()
|
|
)?;
|
|
}
|
|
}
|
|
writeln!(stdout)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|