Skip to content

Instantly share code, notes, and snippets.

@pacmancoder
Last active November 18, 2017 22:15
Show Gist options
  • Save pacmancoder/8f3eac766e487e5d9089 to your computer and use it in GitHub Desktop.
Save pacmancoder/8f3eac766e487e5d9089 to your computer and use it in GitHub Desktop.
Shitty labyrinth generation using eller algorithm written in Rust
#![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