1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use crate::brain::BrainID;
use crate::id::ID;
use crate::Scalar;
use serde::{Deserialize, Serialize};

pub type NeuronID = ID<Neuron>;

#[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[repr(C)]
pub struct Impulse {
    pub potential: Scalar,
    pub timeout: Scalar,
}

#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
pub(crate) struct Synapse {
    pub source: NeuronID,
    pub target: NeuronID,
    pub distance: Scalar,
    pub receptors: Scalar,
    pub impulses: Vec<Impulse>,
    pub inactivity: Scalar,
}

#[derive(Debug, Default, Copy, Clone, PartialEq, Serialize, Deserialize)]
#[repr(C)]
pub struct Position {
    pub x: Scalar,
    pub y: Scalar,
    pub z: Scalar,
}

impl Position {
    #[inline]
    pub fn magnitude_sqr(&self) -> Scalar {
        self.x * self.x + self.y * self.y + self.z * self.z
    }

    #[inline]
    pub fn magnitude(&self) -> Scalar {
        self.magnitude_sqr().sqrt()
    }

    pub fn distance_sqr(&self, other: Self) -> Scalar {
        let dx = self.x - other.x;
        let dy = self.y - other.y;
        let dz = self.z - other.z;
        dx * dx + dy * dy + dz * dz
    }

    #[inline]
    pub fn distance(&self, other: Self) -> Scalar {
        self.distance_sqr(other).sqrt()
    }
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[repr(C)]
pub struct Neuron {
    id: NeuronID,
    owner_id: BrainID,
    position: Position,
    potential: Scalar,
}

impl Neuron {
    pub(crate) fn new(owner_id: BrainID, position: Position) -> Self {
        Self {
            id: Default::default(),
            owner_id,
            position,
            potential: 0.0,
        }
    }

    pub(crate) fn with_id(id: NeuronID, owner_id: BrainID, position: Position) -> Self {
        Self {
            id,
            owner_id,
            position,
            potential: 0.0,
        }
    }

    #[inline]
    pub fn id(&self) -> NeuronID {
        self.id
    }

    #[inline]
    pub fn owner_id(&self) -> BrainID {
        self.owner_id
    }

    #[inline]
    pub fn position(&self) -> Position {
        self.position
    }

    #[inline]
    pub fn potential(&self) -> Scalar {
        self.potential
    }

    #[inline]
    pub(crate) fn push_potential(&mut self, value: Scalar) {
        self.potential += value;
    }

    #[inline]
    pub(crate) fn process_potential(&mut self, delta_time_times_decay: Scalar) {
        if self.potential < -delta_time_times_decay {
            self.potential = (self.potential + delta_time_times_decay).min(0.0);
        } else if self.potential > delta_time_times_decay {
            self.potential = (self.potential - delta_time_times_decay).max(0.0);
        } else {
            self.potential = 0.0;
        }
    }

    #[inline]
    pub(crate) fn fire(&mut self) {
        self.potential = 0.0;
    }
}