using System; using System.Collections.Generic; using UnityEngine; using Unity.Mathematics; using static Unity.Mathematics.math; [Serializable] public abstract class Nucleus { public string name; //[Obsolete] public ClusterPrefab cluster { get; set; } public Cluster parent { get; set; } protected float3 _outputValue; public virtual Vector3 outputValue { get { return _outputValue; } set { //this.stale = 0; _outputValue = value; if (this.isFiring) WhenFiring?.Invoke(); } } public bool isFiring => length(_outputValue) > 0.5f; public Action WhenFiring; public virtual bool isSleeping => lengthsq(this.outputValue) == 0; [NonSerialized] public int stale = 1000; public readonly int staleValueForSleep = 20; public bool trace = false; public abstract Nucleus ShallowCloneTo(Cluster parent); public abstract Nucleus Clone(ClusterPrefab prefab); public enum Type { None, Neuron, MemoryCell, Selector, Cluster, Pulsar } #region Synapses public Vector3 bias = Vector3.zero; [SerializeField] private List _synapses = new(); public List synapses => _synapses; public Synapse AddSynapse(Nucleus sendingNucleus, float weight = 1.0f) { Synapse synapse = new(sendingNucleus, weight); this.synapses.Add(synapse); return synapse; } public Synapse GetSynapse(Nucleus sender) { foreach (Synapse synapse in this.synapses) if (synapse.nucleus == sender) return synapse; return null; } #endregion Synapses #region Receivers [SerializeReference] private List _receivers = new(); public List receivers { get { return _receivers; } set { _receivers = value; } } public virtual void AddReceiver(Nucleus receivingNucleus, float weight = 1) { this._receivers.Add(receivingNucleus); receivingNucleus.AddSynapse(this, weight); } public void RemoveReceiver(Nucleus receiverNucleus) { this._receivers.RemoveAll(receiver => receiver == receiverNucleus); receiverNucleus.synapses.RemoveAll(synapse => synapse.nucleus == this); } #endregion Receivers [SerializeReference] private NucleusArray _array; public NucleusArray array { get { return _array; } set { _array = value; } } #region Update public abstract void UpdateStateIsolated(); public virtual void UpdateNuclei() { if (this.array == null || this.array.nuclei == null || this.array.nuclei.Length <= 1) return; this.stale++; if (this.stale > staleValueForSleep) { //Debug.Log($"{this.name} goes to sleep, stale = {this.stale}"); _outputValue = Vector3.zero; } } public void ProcessStimulus(int thingId, Vector3 inputValue, string thingName = null) { this.array.ProcessStimulus(thingId, inputValue, thingName); } #endregion Update }