|
|
|
//! Logical operations: if, etc.
|
|
|
|
|
|
|
|
use crate::prelude::*;
|
|
|
|
use crate::tile::prelude::*;
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
|
|
|
|
pub struct If {
|
|
|
|
invert: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl If {
|
|
|
|
pub fn new(invert: bool) -> Self {
|
|
|
|
Self {
|
|
|
|
invert
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Tile for If {
|
|
|
|
fn update<'b>(&'b mut self, mut context: UpdateContext<'b>) {
|
|
|
|
if let Some(mut signal) = context.take_signal() {
|
|
|
|
let truthy = match signal.pop() {
|
|
|
|
Some(Value::Number(x)) => x != 0.0,
|
|
|
|
Some(Value::String(s)) => !s.is_empty(),
|
|
|
|
_ => false
|
|
|
|
};
|
|
|
|
|
|
|
|
let reorient = if self.invert {
|
|
|
|
truthy
|
|
|
|
} else {
|
|
|
|
!truthy
|
|
|
|
};
|
|
|
|
|
|
|
|
if reorient {
|
|
|
|
if matches!(signal.direction(), Direction::Left | Direction::Right) {
|
|
|
|
if let Some(up) = context.offset((0, -1)) {
|
|
|
|
let _ = context.send(up, Direction::Up, signal.clone());
|
|
|
|
}
|
|
|
|
if let Some(down) = context.offset((0, 1)) {
|
|
|
|
let _ = context.send(down, Direction::Down, signal);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if let Some(left) = context.offset((-1, 0)) {
|
|
|
|
let _ = context.send(left, Direction::Left, signal.clone());
|
|
|
|
}
|
|
|
|
if let Some(right) = context.offset((1, 0)) {
|
|
|
|
let _ = context.send(right, Direction::Right, signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if let Some(target_position) = context.offset(signal.direction().into_offset()) {
|
|
|
|
let _ = context.send(target_position, signal.direction(), signal);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if context.state() != State::Idle {
|
|
|
|
context.next_state();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn draw_simple(&self, ctx: DrawContext) -> TextChar {
|
|
|
|
if self.invert {
|
|
|
|
TextChar::from_state('¿', ctx.state)
|
|
|
|
} else {
|
|
|
|
TextChar::from_state('?', ctx.state)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn schema(&self) -> TileSchema {
|
|
|
|
// TODO: add Vec<Signal>?
|
|
|
|
TileSchema::map()
|
|
|
|
.add(
|
|
|
|
"invert",
|
|
|
|
TileSchema::value("Invert", "Bool")
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|