Last active
November 18, 2017 22:15
-
-
Save pacmancoder/8f3eac766e487e5d9089 to your computer and use it in GitHub Desktop.
Shitty labyrinth generation using eller algorithm written in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(dead_code)] | |
extern crate rand; | |
use rand::random; | |
/// Labyrinth Edge | |
#[derive(Clone,Copy)] | |
enum LabEdge { | |
Exist, | |
None, | |
} | |
#[derive(Clone,Copy)] | |
struct LabCell { | |
set: Option<usize>, | |
bottom_edge: LabEdge, | |
right_edge: LabEdge, | |
} | |
impl LabCell { | |
fn new() -> LabCell { | |
LabCell { | |
set: None, | |
bottom_edge: LabEdge::None, | |
right_edge: LabEdge::None, | |
} | |
} | |
fn change_set(&mut self, new_set: usize) -> &mut LabCell { | |
self.set = Some(new_set); | |
self | |
} | |
fn drop_set(&mut self) -> &mut LabCell { | |
self.set = None; | |
self | |
} | |
fn set_bottom_edge(&mut self, edge: LabEdge) -> &mut LabCell { | |
self.bottom_edge = edge; | |
self | |
} | |
fn set_right_edge(&mut self, edge: LabEdge) -> &mut LabCell { | |
self.right_edge = edge; | |
self | |
} | |
fn have_set(&self) -> bool { | |
match self.set { | |
Some(_) => true, | |
None => false, | |
} | |
} | |
fn sets_equal(&self, rhs: &LabCell) -> bool { | |
if self.have_set() && rhs.have_set() { | |
self.set.unwrap() == rhs.set.unwrap() | |
} else { | |
false | |
} | |
} | |
fn get_set(&self) -> Option<usize> { | |
self.set | |
} | |
fn have_right_edge(&self) -> bool { | |
match self.right_edge { | |
LabEdge::Exist => true, | |
_ => false, | |
} | |
} | |
fn have_bottom_edge(&self) -> bool { | |
match self.bottom_edge { | |
LabEdge::Exist => true, | |
_ => false, | |
} | |
} | |
} | |
#[derive(PartialEq, Eq)] | |
enum LineKind { | |
Top, | |
Middle, | |
Bottom, | |
} | |
struct LabLine { | |
cells: Vec<LabCell>, | |
kind: LineKind, | |
next_set: usize, | |
} | |
impl LabLine { | |
fn print(&self) { | |
let mut s = " ".to_owned(); | |
if self.kind == LineKind::Top { | |
for _ in 0..self.cells.len() { | |
s.push_str("__ "); | |
} | |
println!("{}", s); | |
} | |
s.clear(); | |
for cell in &self.cells { | |
if cell.have_bottom_edge() { | |
s.push_str("__"); | |
} else { | |
s.push_str(" "); | |
}; | |
if cell.have_right_edge() { | |
s.push_str("|"); | |
} else { | |
s.push_str(" "); | |
}; | |
}; | |
s.pop(); | |
println!("|{}|", s); | |
} | |
fn new(width: usize) -> LabLine { | |
assert!(width > 1); | |
let mut line = LabLine { | |
cells: vec![LabCell::new(); width], | |
kind: LineKind::Top, | |
next_set: 0, | |
}; | |
line.fill_empty(); | |
line.add_right_edges(); | |
line.add_bottom_edges(); | |
line | |
} | |
fn generate_next(&self) -> LabLine { | |
let mut line = LabLine { | |
cells: self.cells.clone(), | |
kind: LineKind::Middle, | |
next_set: self.next_set, | |
}; | |
line.prepare_new_line(); | |
line.fill_empty(); | |
line.add_right_edges(); | |
line.add_bottom_edges(); | |
line | |
} | |
fn make_last(&mut self) { | |
self.add_bottom_edges_all(); | |
let mut i = 0; | |
while i < self.cells.len() - 1 { | |
let current_set = self.cells[i].get_set().unwrap(); | |
let next_set = self.cells[i + 1].get_set().unwrap(); | |
if current_set != next_set { | |
let mut j = i + 1; | |
while self.cells[j].get_set().unwrap() == next_set { | |
self.cells[j].change_set(current_set); | |
j += 1; | |
if j == self.cells.len() { | |
break; | |
} | |
}; | |
self.cells[i].set_right_edge(LabEdge::None); | |
} | |
i += 1; | |
} | |
} | |
fn fill_empty(&mut self) { | |
for cell in &mut self.cells { | |
if let None = cell.get_set() { | |
cell.change_set(self.next_set); | |
self.next_set += 1; | |
} | |
} | |
} | |
fn add_right_edges(&mut self) { | |
for i in 0..self.cells.len() - 1 { | |
if random::<bool>() || | |
(self.cells[i].get_set().unwrap() == self.cells[i + 1].get_set().unwrap()) { | |
self.cells[i].set_right_edge(LabEdge::Exist); | |
// merge sets | |
} else { | |
let current_set = self.cells[i].get_set().unwrap(); | |
self.cells[i + 1].change_set(current_set); | |
} | |
} | |
} | |
fn add_bottom_edges(&mut self) { | |
let mut set_max = 0; | |
let mut set_used = 0; | |
let mut last_set = self.cells[0].get_set().unwrap(); | |
let mut current_set; | |
for i in 0..self.cells.len(){ | |
current_set = self.cells[i].get_set().unwrap(); | |
if last_set == current_set { | |
set_max += 1; | |
} else { | |
set_max = 1; | |
set_used = 0; | |
} | |
let next_set_equal = if i == self.cells.len() - 1 { | |
false | |
} else { | |
self.cells[i+1].get_set().unwrap() == current_set | |
}; | |
if set_used < set_max - 1 || next_set_equal { | |
if random::<bool>() { | |
set_used += 1; | |
self.cells[i].set_bottom_edge(LabEdge::Exist); | |
} | |
} | |
last_set = self.cells[i].get_set().unwrap(); | |
} | |
} | |
fn add_bottom_edges_all(&mut self) { | |
for cell in &mut self.cells { | |
cell.set_bottom_edge(LabEdge::Exist); | |
} | |
} | |
fn prepare_new_line(&mut self) { | |
for cell in &mut self.cells { | |
cell.set_right_edge(LabEdge::None); | |
if cell.have_bottom_edge() { | |
cell.drop_set(); | |
} | |
cell.set_bottom_edge(LabEdge::None); | |
}; | |
} | |
} | |
const LAB_WIDTH: usize = 63; | |
const LAB_HEIGHT: usize = 49; | |
fn main() { | |
let mut line = LabLine::new(LAB_WIDTH); | |
line.print(); | |
for _ in 0..LAB_HEIGHT - 1 { | |
line = line.generate_next(); | |
line.print(); | |
} | |
line = line.generate_next(); | |
line.make_last(); | |
line.print(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment