diff --git a/assets/digits/digit_1.png b/assets/digits/digit_1.png index cc37886..fb46b47 100644 Binary files a/assets/digits/digit_1.png and b/assets/digits/digit_1.png differ diff --git a/src/editor.rs b/src/editor.rs index 25da17a..dbbadd8 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -14,7 +14,7 @@ use crate::{ marble_engine::{ board::Board, pos::{Pos, PosInt}, - tile::{Claim, Direction, GateType, MathOp, MirrorType, OpenTile, PTile, Tile, WireType}, + tile::{Direction, GateType, MarbleTarget, MathOp, MirrorType, OpenTile, PTile, Tile, WireType}, Machine, }, simple_button, simple_option_button, slider, @@ -179,7 +179,7 @@ impl Editor { match self.sim_state { SimState::Editing => { self.start_sim(); - // self.step(); + self.step(); } SimState::Running => (), SimState::Stepping => self.step(), @@ -722,7 +722,7 @@ impl Editor { let max = selection.0.max(selection.1); for x in min.x..=max.x { for y in min.y..=max.y { - self.source_board.set(Pos { x, y }, Tile::BLANK); + self.source_board.set(Pos { x, y }, Tile::default()); } } } @@ -773,7 +773,7 @@ impl Editor { tool_button((1, 0), "marble", Tool::SetTile(Tile::from_char('o'))); match tool_button( (1, 1), - &Tile::Wire(self.tool_wire, false).texture(), + &Tile::Powerable(PTile::Wire(self.tool_wire), false).texture(), Tool::Wire, ) { Some(Scroll::Down) => self.tool_wire.next(), @@ -935,7 +935,7 @@ impl Editor { let pos = *pos; for n in 0..10 { if d.is_key_pressed(unsafe { transmute::(b'0' as u32 + n) }) { - self.set_tile(pos, Tile::Open(OpenTile::Digit(n as u8), Claim::Free)); + self.set_tile(pos, Tile::Open(OpenTile::Digit(n as u8), MarbleTarget::Free)); } } } @@ -986,14 +986,16 @@ impl Editor { Tool::Gate => { self.set_tile(pos, Tile::Powerable(PTile::Gate(self.tool_gate), false)) } - Tool::Wire => self.set_tile(pos, Tile::Wire(self.tool_wire, false)), + Tool::Wire => { + self.set_tile(pos, Tile::Powerable(PTile::Wire(self.tool_wire), false)) + } Tool::Arrow => self.set_tile(pos, Tile::Arrow(self.tool_arrow)), Tool::Mirror => self.set_tile(pos, Tile::Mirror(self.tool_mirror)), Tool::Digits(_pos) => { self.active_tool = Tool::Digits(Some(pos)); if let Some(tile) = self.source_board.get_mut(pos) { - if !matches!(tile, Tile::Open(OpenTile::Digit(_), _)) { - *tile = Tile::Open(OpenTile::Digit(0), Claim::Free); + if ! matches!(tile, Tile::Open(OpenTile::Digit(_), _)) { + *tile = Tile::Open(OpenTile::Digit(0), MarbleTarget::Free); } } } @@ -1016,7 +1018,7 @@ impl Editor { if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) && self.active_tool == Tool::Erase { - self.set_tile(tile_pos.into(), Tile::BLANK) + self.set_tile(tile_pos.into(), Tile::default()) } if let Tool::SelectArea(selection) = &mut self.active_tool { if d.is_mouse_button_down(MouseButton::MOUSE_BUTTON_LEFT) { diff --git a/src/marble_engine.rs b/src/marble_engine.rs index 502af92..7ae33e7 100644 --- a/src/marble_engine.rs +++ b/src/marble_engine.rs @@ -14,6 +14,8 @@ pub struct Machine { board: Board, marbles: Vec, powered: Vec, + flipper_events: Vec, + input: Vec, input_index: usize, output: Vec, @@ -26,6 +28,7 @@ impl Machine { board: Board::new_empty(width, width), marbles: Vec::new(), powered: Vec::new(), + flipper_events: Vec::new(), input, input_index: 0, output: Vec::new(), @@ -99,114 +102,12 @@ impl Machine { pub fn step(&mut self) { self.steps += 1; - - let old_marbles = self.marbles.len(); - - let mut new_marbles = Vec::new(); - // activate all powered machines - for &pos in &self.powered { - match self.board.get_mut(pos) { - Some(Tile::Powerable(machine, state)) => { - *state = false; - let machine = *machine; - for dir in Direction::ALL { - let front_pos = dir.step(pos); - let source_pos = dir.opposite().step(pos); - match self.board.get(source_pos) { - Some(Tile::Wire(wiretype, true)) => { - if !wiretype.has_output(dir) { - continue; - } - } - Some(Tile::Trigger(true)) => (), - _ => continue, - } - let Some(front_tile) = self.board.get_mut(front_pos) else { - continue; - }; - // `machine`` is being powered, in direction `dir`` - match machine { - PTile::Gate(_) => (), // handled at the power propagation stage (end of step) - PTile::Math(op) => { - if front_tile.is_blank() { - let pos_a = dir.left().step(pos); - let pos_b = dir.right().step(pos); - let val_a = self.board.get_or_blank(pos_a).read_value(); - let val_b = self.board.get_or_blank(pos_b).read_value(); - - let value = match op { - MathOp::Add => val_a.wrapping_add(val_b), - MathOp::Sub => val_a.wrapping_sub(val_b), - MathOp::Mul => val_a.wrapping_mul(val_b), - MathOp::Div => val_a.checked_div(val_b).unwrap_or_default(), - MathOp::Rem => val_a.checked_rem(val_b).unwrap_or_default(), - }; - new_marbles.push((front_pos, value, dir)); - } - } - PTile::IO => { - if front_tile == &Tile::BLANK && self.input_index < self.input.len() - { - let value = self.input[self.input_index] as MarbleValue; - self.input_index += 1; - new_marbles.push((front_pos, value, dir)); - } - } - PTile::Bag => { - if front_tile == &Tile::BLANK { - new_marbles.push((front_pos, 0, dir)); - } - } - PTile::Flipper => { - match front_tile { - Tile::Wire(wire_type, _) => { - *wire_type = match *wire_type { - WireType::Vertical => WireType::Horizontal, - WireType::Horizontal => WireType::Vertical, - WireType::Cross => WireType::Cross, - } - } - Tile::Mirror(mirror) => mirror.flip(), - Tile::Arrow(dir) => *dir = dir.opposite(), - _ => (), - }; - } - } - } - } - Some(Tile::Trigger(_state)) => (), - Some(Tile::Wire(_, _state)) => (), - _ => unreachable!(), - }; - } - - for &(pos, _val, _dir) in &new_marbles { - let Some(Tile::Open(OpenTile::Blank, claim)) = self.board.get_mut(pos) else { + // reset wires + for &p in &self.powered { + let Some(Tile::Powerable(_, state)) = self.board.get_mut(p) else { unreachable!() }; - *claim = match claim { - Claim::Free => Claim::Claimed, - Claim::Claimed | Claim::Blocked => Claim::Blocked, - _ => unreachable!(), - } - } - // new marbles are past old_marbles index, so will not move this step - for (pos, value, dir) in new_marbles { - let Some(Tile::Open(OpenTile::Blank, Claim::Claimed)) = self.board.get_mut(pos) else { - continue; - }; - self.board.set(pos, Tile::Marble { value, dir }); - self.marbles.push(pos); - } - - // old wires have to be reset after machine processing, - // so they can figure out which directions they are powered from - for &p in &self.powered { - match self.board.get_mut(p) { - Some(Tile::Trigger(state)) => *state = false, - Some(Tile::Wire(_, state)) => *state = false, - _ => (), - } + *state = false; } self.powered.clear(); @@ -269,14 +170,16 @@ impl Machine { }; if will_reverse_direction[i] { *dir = dir.opposite(); - } else if let DirInfluence::One(new_dir) = influenced_direction[i] { - *dir = new_dir; + } else { + if let DirInfluence::One(new_dir) = influenced_direction[i] { + *dir = new_dir; + } } } let mut claim_positions = Vec::new(); // mark claims to figure out what spaces can be moved to - for &pos in &self.marbles[..old_marbles] { + for &pos in &self.marbles { let Some(Tile::Marble { value: _, dir }) = self.board.get(pos) else { unreachable!() }; @@ -286,44 +189,51 @@ impl Machine { }; if let Tile::Open(_type, claim) = front_tile { *claim = match claim { - Claim::Free => { + MarbleTarget::Free => { claim_positions.push(front_pos); - Claim::Claimed + MarbleTarget::Claimed } - Claim::ClaimedIndirect => Claim::Claimed, - Claim::BlockedIndirect => Claim::Claimed, - Claim::Claimed => Claim::Blocked, - Claim::Blocked => Claim::Blocked, + MarbleTarget::ClaimedIndirect => MarbleTarget::Claimed, + MarbleTarget::BlockedIndirect => MarbleTarget::Claimed, + MarbleTarget::Claimed => MarbleTarget::Blocked, + MarbleTarget::Blocked => MarbleTarget::Blocked, }; } else { - let target_pos = match front_tile { - Tile::Arrow(d) => d.step(front_pos), - Tile::Mirror(m) => m.new_dir(dir).step(front_pos), - Tile::Trigger(_) => dir.step(front_pos), + let target_pos; + match front_tile { + Tile::Arrow(d) => { + target_pos = d.step(front_pos); + } + Tile::Mirror(m) => { + target_pos = m.new_dir(dir).step(front_pos); + } + Tile::Powerable(PTile::Trigger, _) => { + target_pos = dir.step(front_pos); + } _ => continue, - }; + } let Some(target_tile) = self.board.get_mut(target_pos) else { continue; }; if let Tile::Open(_type, claim) = target_tile { *claim = match claim { - Claim::Free => { + MarbleTarget::Free => { claim_positions.push(front_pos); - Claim::ClaimedIndirect + MarbleTarget::ClaimedIndirect } - Claim::ClaimedIndirect => Claim::BlockedIndirect, - Claim::BlockedIndirect => Claim::BlockedIndirect, - Claim::Claimed => Claim::Claimed, - Claim::Blocked => Claim::Blocked, + MarbleTarget::ClaimedIndirect => MarbleTarget::BlockedIndirect, + MarbleTarget::BlockedIndirect => MarbleTarget::BlockedIndirect, + MarbleTarget::Claimed => MarbleTarget::Claimed, + MarbleTarget::Blocked => MarbleTarget::Blocked, }; } } } - // let mut triggers_activated = Vec::new(); + let mut triggers_activated = Vec::new(); let mut removed_marbles = Vec::new(); // move marbles - for (i, pos) in self.marbles[..old_marbles].iter_mut().enumerate() { + for (i, pos) in self.marbles.iter_mut().enumerate() { let Some(Tile::Marble { value, dir }) = self.board.get(*pos) else { unreachable!() }; @@ -337,15 +247,15 @@ impl Machine { OpenTile::Blank => value, OpenTile::Digit(n) => value.wrapping_mul(10).wrapping_add(n as MarbleValue), }; - board.set(*pos, Tile::BLANK); + board.set(*pos, Tile::default()); board.set(target_pos, Tile::Marble { value, dir }); *pos = target_pos; }; if let Tile::Open(space_type, claim_state) = front_tile { - if *claim_state == Claim::Claimed { + if *claim_state == MarbleTarget::Claimed { move_to(*space_type, front_pos, dir, &mut self.board); - } else if *claim_state != Claim::Free { + } else if *claim_state != MarbleTarget::Free { // (Free means a marble was just here but moved earlier this tick) // bounce on failed direct movement self.board.set( @@ -369,7 +279,7 @@ impl Machine { new_dir = m.new_dir(dir); target_pos = new_dir.step(front_pos); } - Tile::Trigger(_) => { + Tile::Powerable(PTile::Trigger, _) => { is_trigger = true; target_pos = dir.step(front_pos); } @@ -387,10 +297,10 @@ impl Machine { let Some(target_tile) = self.board.get_mut(target_pos) else { continue; }; - if let Tile::Open(space_type, Claim::ClaimedIndirect) = target_tile { + if let Tile::Open(space_type, MarbleTarget::ClaimedIndirect) = target_tile { move_to(*space_type, target_pos, new_dir, &mut self.board); if is_trigger { - self.powered.push(front_pos); + triggers_activated.push(front_pos); } } } @@ -398,112 +308,132 @@ impl Machine { for pos in claim_positions { if let Some(Tile::Open(_, claim_state)) = self.board.get_mut(pos) { - *claim_state = Claim::Free; + *claim_state = MarbleTarget::Free; } } // remove marbles for &i in removed_marbles.iter().rev() { - self.board.set(self.marbles[i], Tile::BLANK); + self.board.set(self.marbles[i], Tile::default()); self.marbles.swap_remove(i); } - // propagate power - let mut i = 0; - while i < self.powered.len() { - let pos = self.powered[i]; - let Some(tile) = self.board.get_mut(pos) else { + // process triggers + self.flipper_events.clear(); + for pos in triggers_activated { + let Some(Tile::Powerable(PTile::Trigger, state)) = self.board.get_mut(pos) else { unreachable!() }; - match tile { - Tile::Trigger(state) => { - *state = true; - for dir in Direction::ALL { - let target_pos = dir.step(pos); - match self.board.get_mut(target_pos) { - Some(Tile::Powerable(_, state)) => { - if !*state { - *state = true; - self.powered.push(target_pos); - } - } - Some(Tile::Wire(_, state)) => { - // only push it if it hasnt already been pushed - if !*state { - *state = true; - self.powered.push(target_pos); - } - } - _ => (), - } - } - } - Tile::Wire(wiretype, state) => { - *state = true; - for dir in wiretype.directions() { - let target_pos = dir.step(pos); - match self.board.get_mut(target_pos) { - Some(Tile::Powerable(_, state)) => { - if !*state { - *state = true; - self.powered.push(target_pos); - } - } - Some(Tile::Wire(_, state)) => { - // only push it if it hasnt already been pushed - if !*state { - *state = true; - self.powered.push(target_pos); - } - } - _ => (), - } - } - } - Tile::Powerable(PTile::Gate(gate), state) => { - *state = true; - let gate = *gate; - for dir in Direction::ALL { - let front_pos = dir.step(pos); - let source_pos = dir.opposite().step(pos); - match self.board.get(source_pos) { - Some(Tile::Wire(wiretype, true)) => { - if !wiretype.has_output(dir) { - continue; - } - } - Some(Tile::Trigger(true)) => (), - _ => continue, - } - let Some(front_tile) = self.board.get_mut(front_pos) else { - continue; - }; - if matches!(front_tile, Tile::Wire(_, _) | Tile::Powerable(_, _)) { - let pos_a = dir.left().step(pos); - let pos_b = dir.right().step(pos); - let val_a = self.board.get_or_blank(pos_a).read_value(); - let val_b = self.board.get_or_blank(pos_b).read_value(); - - let result = match gate { - GateType::LessThan => val_a < val_b, - GateType::GreaterThan => val_a > val_b, - GateType::Equal => val_a == val_b, - GateType::NotEqual => val_a != val_b, - }; - if result { - self.powered.push(front_pos); - } - } - } - } - // state may be false if it was powered by a machine in earlier step - Tile::Powerable(_, state) => *state = true, - _ => { - dbg!(tile); - unreachable!() - } + self.powered.push(pos); + *state = true; + for dir in Direction::ALL { + self.propagate_power(dir, dir.step(pos)); + } + } + + // process flipped tiles + for &p in &self.flipper_events { + let Some(target) = self.board.get_mut(p) else { + continue; + }; + match target { + Tile::Powerable(PTile::Wire(wire_type), _) => { + *wire_type = match *wire_type { + WireType::Vertical => WireType::Horizontal, + WireType::Horizontal => WireType::Vertical, + WireType::Cross => WireType::Cross, + } + } + Tile::Mirror(mirror) => mirror.flip(), + Tile::Arrow(dir) => *dir = dir.opposite(), + _ => (), + }; + } + } + + fn propagate_power(&mut self, dir: Direction, pos: Pos) { + let Some(tile) = self.board.get_mut(pos) else { + return; + }; + let front_pos = dir.step(pos); + if let Tile::Powerable(tile, state) = tile { + if let PTile::Trigger = tile { + return; + } + let was_powered = *state; + *state = true; + self.powered.push(pos); + match tile { + PTile::Wire(wiretype) => { + if was_powered { + return; + } + let dirs = wiretype.directions(); + for d in dirs { + self.propagate_power(*d, d.step(pos)); + } + } + PTile::Bag => { + if let Some(front) = self.board.get_blank_mut(front_pos) { + *front = Tile::Marble { value: 0, dir }; + self.marbles.push(front_pos); + } + } + PTile::IO => { + if let Some(front) = self.board.get_blank_mut(front_pos) { + if self.input_index < self.input.len() { + let value = self.input[self.input_index] as MarbleValue; + self.input_index += 1; + *front = Tile::Marble { value, dir }; + self.marbles.push(front_pos); + } + } + } + PTile::Math(op) => { + let op = *op; + let pos_a = dir.left().step(pos); + let pos_b = dir.right().step(pos); + let val_a = self.board.get_or_blank(pos_a).read_value(); + let val_b = self.board.get_or_blank(pos_b).read_value(); + if !self.board.get_or_blank(pos_a).is_blank() + || !self.board.get_or_blank(pos_b).is_blank() + { + let value = match op { + MathOp::Add => val_a.wrapping_add(val_b), + MathOp::Sub => val_a.wrapping_sub(val_b), + MathOp::Mul => val_a.wrapping_mul(val_b), + MathOp::Div => val_a.checked_div(val_b).unwrap_or_default(), + MathOp::Rem => val_a.checked_rem(val_b).unwrap_or_default(), + }; + // println!("{op:?} a:{val_a} b:{val_b}"); + if let Some(front) = self.board.get_blank_mut(front_pos) { + *front = Tile::Marble { value, dir }; + self.marbles.push(front_pos); + } + } + } + PTile::Flipper => { + self.flipper_events.push(front_pos); + } + PTile::Gate(gate) => { + let gate = *gate; + let pos_a = dir.left().step(pos); + let pos_b = dir.right().step(pos); + let val_a = self.board.get_or_blank(pos_a).read_value(); + let val_b = self.board.get_or_blank(pos_b).read_value(); + + let result = match gate { + GateType::LessThan => val_a < val_b, + GateType::GreaterThan => val_a > val_b, + GateType::Equal => val_a == val_b, + GateType::NotEqual => val_a != val_b, + }; + if result { + self.propagate_power(dir, dir.step(pos)); + } + } + PTile::Trigger => (), } - i += 1; } } } diff --git a/src/marble_engine/board.rs b/src/marble_engine/board.rs index af8664d..6052ff5 100644 --- a/src/marble_engine/board.rs +++ b/src/marble_engine/board.rs @@ -26,7 +26,7 @@ impl Board { rows.push(tiles); } for line in &mut rows { - line.resize(width, Tile::BLANK); + line.resize(width, Tile::default()); } Board::new(rows) @@ -44,7 +44,7 @@ impl Board { } pub fn new_empty(width: usize, height: usize) -> Self { - let rows = vec![vec![Tile::BLANK; width]; height]; + let rows = vec![vec![Tile::default(); width]; height]; Self { rows, width, @@ -89,7 +89,7 @@ impl Board { if self.in_bounds(p) { self.rows[p.y as usize][p.x as usize] } else { - Tile::BLANK + Tile::default() } } @@ -101,6 +101,16 @@ impl Board { } } + pub fn get_blank_mut(&mut self, p: Pos) -> Option<&mut Tile> { + if self.in_bounds(p) { + let tile = &mut self.rows[p.y as usize][p.x as usize]; + if let Tile::Open(OpenTile::Blank, _) = tile{ + return Some(tile); + } + } + None + } + pub fn set(&mut self, p: Pos, tile: Tile) { if self.in_bounds(p) { self.rows[p.y as usize][p.x as usize] = tile; @@ -137,7 +147,7 @@ impl Board { if p.x < 0 { let len = p.x.unsigned_abs() as usize; for row in &mut self.rows { - let mut new_row = vec![Tile::BLANK; len]; + let mut new_row = vec![Tile::default(); len]; new_row.append(row); *row = new_row; } @@ -146,21 +156,21 @@ impl Board { } else if p.x as usize >= self.width { let new_width = p.x as usize + 1; for row in &mut self.rows { - row.resize(new_width, Tile::BLANK); + row.resize(new_width, Tile::default()); } self.width = new_width; } if p.y < 0 { let len = p.y.unsigned_abs() as usize; - let mut new_rows = vec![vec![Tile::BLANK; self.width]; len]; + let mut new_rows = vec![vec![Tile::default(); self.width]; len]; new_rows.append(&mut self.rows); self.rows = new_rows; offset_y = len; self.height += len; } else if p.y as usize >= self.height { let new_height = p.y as usize + 1; - self.rows.resize(new_height, vec![Tile::BLANK; self.width]); + self.rows.resize(new_height, vec![Tile::default(); self.width]); self.height = new_height; } (offset_x as PosInt, offset_y as PosInt) diff --git a/src/marble_engine/tile.rs b/src/marble_engine/tile.rs index 8393793..c18a8a9 100644 --- a/src/marble_engine/tile.rs +++ b/src/marble_engine/tile.rs @@ -4,18 +4,16 @@ pub type MarbleValue = u32; #[derive(Debug, Clone, Copy, PartialEq)] pub enum Tile { - Open(OpenTile, Claim), + Open(OpenTile, MarbleTarget), Block, Marble { value: MarbleValue, dir: Direction }, Mirror(MirrorType), Arrow(Direction), - Trigger(bool), - Wire(WireType, bool), Powerable(PTile, bool), } #[derive(Debug, Clone, Copy, PartialEq)] -pub enum Claim { +pub enum MarbleTarget { Free, ClaimedIndirect, BlockedIndirect, @@ -31,6 +29,8 @@ pub enum OpenTile { #[derive(Debug, Clone, Copy, PartialEq)] pub enum PTile { + Trigger, + Wire(WireType), Gate(GateType), Math(MathOp), Bag, @@ -76,18 +76,23 @@ pub enum Direction { Right, } +impl Default for Tile { + fn default() -> Self { + Tile::Open(OpenTile::Blank, MarbleTarget::Free) + } +} + impl Tile { - pub const BLANK: Self = Tile::Open(OpenTile::Blank, Claim::Free); pub const fn from_char(c: char) -> Tile { match c { 'o' => Tile::Marble { value: 0, dir: Direction::Down, }, - '*' => Tile::Trigger(false), - '-' => Tile::Wire(WireType::Horizontal, false), - '|' => Tile::Wire(WireType::Vertical, false), - '+' => Tile::Wire(WireType::Cross, false), + '*' => Tile::Powerable(PTile::Trigger, false), + '-' => Tile::Powerable(PTile::Wire(WireType::Horizontal), false), + '|' => Tile::Powerable(PTile::Wire(WireType::Vertical), false), + '+' => Tile::Powerable(PTile::Wire(WireType::Cross), false), '/' => Tile::Mirror(MirrorType::Forward), '\\' => Tile::Mirror(MirrorType::Back), '^' => Tile::Arrow(Direction::Up), @@ -106,9 +111,9 @@ impl Tile { 'D' => Tile::Powerable(PTile::Math(MathOp::Div), false), 'R' => Tile::Powerable(PTile::Math(MathOp::Rem), false), 'B' => Tile::Powerable(PTile::Bag, false), - d @ '0'..='9' => Tile::Open(OpenTile::Digit(d as u8 - b'0'), Claim::Free), + d @ '0'..='9' => Tile::Open(OpenTile::Digit(d as u8 - b'0'), MarbleTarget::Free), '#' => Tile::Block, - _ => Tile::Open(OpenTile::Blank, Claim::Free), + _ => Tile::Open(OpenTile::Blank, MarbleTarget::Free), } } @@ -128,13 +133,13 @@ impl Tile { Direction::Left => '<', Direction::Right => '>', }, - Tile::Trigger(_) => '*', - Tile::Wire(wire, _) => match wire { - WireType::Vertical => '|', - WireType::Horizontal => '-', - WireType::Cross => '+', - }, Tile::Powerable(tile, _) => match tile { + PTile::Trigger => '*', + PTile::Wire(wire) => match wire { + WireType::Vertical => '|', + WireType::Horizontal => '-', + WireType::Cross => '+', + }, PTile::Gate(gate) => match gate { GateType::LessThan => 'L', GateType::GreaterThan => 'G', @@ -175,22 +180,10 @@ impl Tile { Tile::Open(OpenTile::Digit(n), _) => return format!("tile_digit_{n}"), Tile::Mirror(mirror) => mirror.texture_name(), Tile::Arrow(dir) => dir.arrow_tile_texture_name(), - Tile::Trigger(state) => { - if *state { - "trigger_on" - } else { - "trigger_off" - } - } - Tile::Wire(wire, state) => { - return format!( - "{}_{}", - wire.texture_name(), - if *state { "on" } else { "off" } - ) - } Tile::Powerable(tile, state) => { let root = match tile { + PTile::Trigger => "trigger", + PTile::Wire(wire) => wire.texture_name(), PTile::Gate(gate) => gate.texture_name(), PTile::Math(math_op) => math_op.texture_name(), PTile::Bag => "bag", @@ -264,14 +257,6 @@ impl Direction { } impl WireType { - pub fn has_output(self, dir: Direction) -> bool { - match self { - WireType::Vertical => matches!(dir, Direction::Up | Direction::Down), - WireType::Horizontal => matches!(dir, Direction::Right | Direction::Left), - WireType::Cross => true, - } - } - pub fn directions(self) -> &'static [Direction] { match self { WireType::Vertical => &[Direction::Up, Direction::Down],