#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Interface {
pub kind: u8,
pub target: u16,
pub modality: u8,
pub gates: EnergyGates,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct EnergyGates {
pub low_ceiling: i16,
pub high_floor: i16,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum InterfaceAction {
Low,
Neutral,
High,
}
impl EnergyGates {
pub const fn default() -> Self {
Self {
low_ceiling: -1000,
high_floor: 1000,
}
}
pub const fn sensory_default() -> Self {
Self {
low_ceiling: -500,
high_floor: 2000,
}
}
pub const fn motor_default() -> Self {
Self {
low_ceiling: -2000,
high_floor: 500,
}
}
pub const fn memory_default() -> Self {
Self {
low_ceiling: -5000,
high_floor: 5000,
}
}
#[inline]
pub const fn action(&self, energy: i16) -> InterfaceAction {
if energy < self.low_ceiling {
InterfaceAction::Low
} else if energy > self.high_floor {
InterfaceAction::High
} else {
InterfaceAction::Neutral
}
}
}
impl Default for EnergyGates {
fn default() -> Self {
Self::default()
}
}
impl Interface {
pub const KIND_NONE: u8 = 0;
pub const KIND_SENSORY_BASE: u8 = 1;
pub const KIND_MOTOR_BASE: u8 = 50;
pub const KIND_MEMORY_BASE: u8 = 100;
pub const KIND_CHEMICAL_BASE: u8 = 150;
pub const KIND_USER_BASE: u8 = 200;
pub const MODALITY_NONE: u8 = 0;
pub const MODALITY_AUDITORY: u8 = 1;
pub const MODALITY_VISUAL: u8 = 2;
pub const MODALITY_TACTILE: u8 = 3;
pub const MODALITY_CHEMICAL: u8 = 4;
#[inline]
pub const fn none() -> Self {
Self {
kind: Self::KIND_NONE,
target: 0,
modality: Self::MODALITY_NONE,
gates: EnergyGates::default(),
}
}
#[inline]
pub const fn sensory(channel: u16, modality: u8) -> Self {
Self {
kind: Self::KIND_SENSORY_BASE,
target: channel,
modality,
gates: EnergyGates::sensory_default(),
}
}
#[inline]
pub const fn auditory(channel: u16) -> Self {
Self::sensory(channel, Self::MODALITY_AUDITORY)
}
#[inline]
pub const fn visual(channel: u16) -> Self {
Self::sensory(channel, Self::MODALITY_VISUAL)
}
#[inline]
pub const fn motor(channel: u16, modality: u8) -> Self {
Self {
kind: Self::KIND_MOTOR_BASE,
target: channel,
modality,
gates: EnergyGates::motor_default(),
}
}
#[inline]
pub const fn memory(bank_id: u16) -> Self {
Self {
kind: Self::KIND_MEMORY_BASE,
target: bank_id,
modality: Self::MODALITY_NONE,
gates: EnergyGates::memory_default(),
}
}
#[inline]
pub const fn chemical(chemical_id: u8) -> Self {
Self {
kind: Self::KIND_CHEMICAL_BASE,
target: chemical_id as u16,
modality: Self::MODALITY_NONE,
gates: EnergyGates::default(),
}
}
#[inline]
pub const fn user(kind_offset: u8, target: u16) -> Self {
Self {
kind: Self::KIND_USER_BASE.saturating_add(kind_offset),
target,
modality: Self::MODALITY_NONE,
gates: EnergyGates::default(),
}
}
#[inline]
pub const fn is_external(&self) -> bool {
self.kind != Self::KIND_NONE
}
#[inline]
pub const fn is_sensory(&self) -> bool {
self.kind >= Self::KIND_SENSORY_BASE && self.kind < Self::KIND_MOTOR_BASE
}
#[inline]
pub const fn is_motor(&self) -> bool {
self.kind >= Self::KIND_MOTOR_BASE && self.kind < Self::KIND_MEMORY_BASE
}
#[inline]
pub const fn is_memory(&self) -> bool {
self.kind >= Self::KIND_MEMORY_BASE && self.kind < Self::KIND_CHEMICAL_BASE
}
#[inline]
pub const fn is_chemical(&self) -> bool {
self.kind >= Self::KIND_CHEMICAL_BASE && self.kind < Self::KIND_USER_BASE
}
#[inline]
pub const fn action(&self, energy: i16) -> InterfaceAction {
self.gates.action(energy)
}
}
impl Default for Interface {
fn default() -> Self {
Self::none()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_interface_categories() {
assert!(!Interface::none().is_external());
assert!(Interface::sensory(0, 1).is_sensory());
assert!(Interface::motor(0, 1).is_motor());
assert!(Interface::memory(0).is_memory());
assert!(Interface::chemical(0).is_chemical());
}
#[test]
fn test_energy_gates() {
let gates = EnergyGates::memory_default();
assert_eq!(gates.action(-6000), InterfaceAction::Low);
assert_eq!(gates.action(0), InterfaceAction::Neutral);
assert_eq!(gates.action(6000), InterfaceAction::High);
}
#[test]
fn test_interface_action() {
let mem = Interface::memory(0);
assert_eq!(mem.action(-6000), InterfaceAction::Low); assert_eq!(mem.action(0), InterfaceAction::Neutral); assert_eq!(mem.action(6000), InterfaceAction::High); }
}