Created
July 3, 2020 08:49
-
-
Save Aceeri/e6bc8a5cd1a04332cdd60693bc1acf09 to your computer and use it in GitHub Desktop.
Rust Shape maker script
This file contains hidden or 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
#[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