Skip to content

Instantly share code, notes, and snippets.

@Aceeri
Created July 3, 2020 08:49
Show Gist options
  • Save Aceeri/e6bc8a5cd1a04332cdd60693bc1acf09 to your computer and use it in GitHub Desktop.
Save Aceeri/e6bc8a5cd1a04332cdd60693bc1acf09 to your computer and use it in GitHub Desktop.
Rust Shape maker script
#[derive(Debug, Copy, Clone)]
enum Direction {
Top = 0,
Right = 1,
Bottom = 2,
Left = 3,
}
#[derive(Debug, Copy, Clone)]
enum ConnectionError {
#[allow(dead_code)]
OriginOutOfBounds,
#[allow(dead_code)]
ConnectionOutOfBounds,
#[allow(dead_code)]
OriginDoesntExist,
#[allow(dead_code)]
ConnectionDoesntExist,
}
impl Direction {
#[allow(dead_code)]
pub fn invert(&self) -> Direction {
match self {
Direction::Top => Direction::Bottom,
Direction::Bottom => Direction::Top,
Direction::Right => Direction::Left,
Direction::Left => Direction::Right,
}
}
#[allow(dead_code)]
pub fn dimensional(&self) -> (i8, i8) {
match self {
Direction::Top => (-1, 0),
Direction::Bottom => (1, 0),
Direction::Right => (0, 1),
Direction::Left => (0, -1),
}
}
#[allow(dead_code)]
pub fn index(&self) -> usize {
*self as usize
}
}
#[derive(Debug, Clone)]
struct Cell {
instance_id: u64,
// We can pack these into a single u8 in the future.
exists: bool,
connections: [bool; 4],
}
impl Cell {
pub fn new(exists: bool, connections: [bool; 4], instance_id: u64) -> Self {
Cell {
instance_id: instance_id,
exists: exists,
connections: connections,
}
}
#[allow(dead_code)]
pub fn exists(&self) -> bool {
self.exists
}
#[allow(dead_code)]
pub fn connected(&self, direction: Direction) -> bool {
self.connections[direction as usize]
}
#[allow(dead_code)]
pub fn set_exists(&mut self, exists: bool) {
self.exists = exists;
}
#[allow(dead_code)]
pub fn set_connection(&mut self, connection: Direction, connected: bool) {
self.connections[connection.index()] = connected;
}
}
impl Default for Cell {
fn default() -> Self {
Cell::new(false, [false; 4], 0)
}
}
#[derive(Debug, Clone)]
struct ItemSpace {
data: Vec<Vec<Cell>>,
}
impl ItemSpace {
pub fn new() -> Self {
ItemSpace {
data: Vec::new(),
}
}
pub fn expand(&mut self, width: usize, height: usize) -> bool {
//println!("expanding from {}, {} to {}, {}", self.width(), self.height(), width, height);
if height > self.data.len() {
self.data.resize(height, Vec::new());
}
for row in self.data.iter_mut() {
if width > row.len() {
row.resize(width, Cell::new(
false,
[false; 4],
0,
));
}
}
//println!("expanded from {}, {} to {}, {}", self.width(), self.height(), width, height);
true
}
pub fn set_exists(&mut self, x: usize, y: usize, exists: bool) -> bool {
//println!("setting {}, {} to {}", x, y, exists);
if y >= self.data.len() && x >= self.data[y].len() {
return false
}
self.data[y][x].exists = true;
if !exists {
self.data[y][x].connections = [false; 4];
}
true
}
#[allow(dead_code)]
pub fn bounds_check(&self, x: usize, y: usize) -> bool {
y < self.height() && x < self.width()
}
#[allow(dead_code)]
pub fn height(&self) -> usize {
self.data.len()
}
#[allow(dead_code)]
pub fn width(&self) -> usize {
if self.height() > 0 {
return self.data[0].len()
}
0
}
#[allow(dead_code)]
pub fn connect(&mut self, origin_x: usize, origin_y: usize, direction: Direction) -> Result<(), ConnectionError> {
//println!("connecting {}, {} to {:?}", origin_x, origin_y, direction);
if !self.bounds_check(origin_x, origin_y) {
return Err(ConnectionError::OriginOutOfBounds);
}
if !self.data[origin_y][origin_x].exists() {
return Err(ConnectionError::OriginDoesntExist);
}
let (direction_y, direction_x) = direction.dimensional();
let (connect_y, connect_x) = (
((origin_y as isize + direction_y as isize) as usize),
((origin_x as isize + direction_x as isize) as usize),
);
if !self.bounds_check(connect_x, connect_y) {
return Err(ConnectionError::ConnectionOutOfBounds);
}
if !self.data[connect_y][connect_x].exists() {
return Err(ConnectionError::ConnectionDoesntExist);
}
self.data[origin_y][origin_x].set_connection(direction, true);
self.data[connect_y][connect_x].set_connection(direction.invert(), true);
Ok(())
}
pub fn display(&self) -> String {
let mut result = "".to_owned();
for row in &self.data {
let mut above = "".to_owned();
let mut center = "".to_owned();
let mut below = "".to_owned();
for cell in row {
if cell.connections[Direction::Top.index()] {
above = above + " ^ ";
} else {
above = above + " ";
}
if cell.connections[Direction::Bottom.index()] {
below = below + " v ";
} else {
below = below + " ";
}
if cell.connections[Direction::Left.index()] {
center = center + "<";
} else {
center = center + " ";
}
if cell.exists() {
center = center + "O";
} else {
center = center + "X";
}
if cell.connections[Direction::Right.index()] {
center = center + ">";
} else {
center = center + " ";
}
}
result = format!("{}\n{}\n{}\n{}", result, above, center, below);
}
result
}
pub fn from_str(string: &str) -> ItemSpace {
let mut item_space = ItemSpace::new();
let mut column_index = 0;
let mut row = true;
let mut column = true;
for line in string.lines() {
if line.len() == 0 {
continue;
}
let mut row_index = 0;
for char in line.trim().chars() {
//println!("{}, {} = {}", row_index, column_index, char);
item_space.expand(row_index + 1, column_index + 1);
match char {
'X' => { // exists
item_space.set_exists(row_index, column_index, true);
},
'O' => { // doesn't exist
item_space.set_exists(row_index, column_index, false);
},
'-' => { // connection right
item_space.expand(row_index + 2, column_index + 1);
item_space.set_exists(row_index + 1, column_index, true);
display_err(item_space.connect(row_index, column_index, Direction::Right));
}
'|' => {
item_space.expand(row_index + 1, column_index + 2);
item_space.set_exists(row_index, column_index + 1, true);
display_err(item_space.connect(row_index, column_index, Direction::Bottom));
}
_ => {
}
}
if !column {
row_index += 1;
}
column = !column;
}
if !row {
column_index += 1;
}
row = !row;
}
item_space
}
pub fn to_ue4(&self) -> String {
let mut cell_collection = Vec::new();
for row in &self.data {
let mut row_collection = Vec::new();
for element in row {
let element_string = format!(
"(Exists={},ConnectedTop={},ConnectedRight={},ConnectedBottom={},ConnectedLeft={})",
truth_string(element.exists),
truth_string(element.connections[Direction::Top as usize]),
truth_string(element.connections[Direction::Right as usize]),
truth_string(element.connections[Direction::Bottom as usize]),
truth_string(element.connections[Direction::Left as usize]),
);
row_collection.push(element_string);
}
let row_string = format!("(Row=({}))", row_collection.join(","));
cell_collection.push(row_string);
}
let shape_format = format!("(Cells=({}))", cell_collection.join(","));
shape_format
}
}
fn display_err(result: Result<(), ConnectionError>) {
match result {
Ok(()) => {},
Err(err) => println!("{:?}", err),
}
}
fn truth_string(b: bool) -> &'static str {
if b {
"True"
} else {
"False"
}
}
#[allow(dead_code)]
fn connect(space: &mut ItemSpace, x: usize, y: usize, direction: Direction) {
match space.connect(x, y, direction) {
Ok(()) => { /* println!("{}, {} connected {:?}", x, y, direction) */ },
Err(err) => println!("{}, {}, {:?}, failed to connect: {:?}", x, y, direction, err),
}
}
fn main() {
let data = "\
X-X-X\n\
| |\n\
X-X-X\n\
";
for line in data.lines() {
println!("{}", line);
}
let item_space = ItemSpace::from_str(data);
println!("{}", item_space.display());
println!("{}", item_space.to_ue4());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment