2025-12-05 16:41:11 +01:00

169 lines
4.6 KiB
C#

using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Nucleus {
public int id; // hash code
[SerializeField]
protected string _name;
public virtual string name {
get => _name;
set => _name = value;
}
//public readonly Dictionary<Nucleus, float> synapses = new();
[SerializeField]
public List<Synapse> synapses = new();
//public HashSet<Nucleus> receivers = new();
[SerializeField]
public List<Receiver> receivers = new();
#region Serialization
public void Rebuild(NanoBrainObj brain) {
if (this.synapses != null) {
foreach (Synapse synapse in synapses)
synapse.Rebuild(brain);
}
if (this.receivers == null)
this.receivers = new();
else
foreach (Receiver receiver in receivers)
receiver.Rebuild(brain);
}
#endregion
#region Runtime state (not serialized)
// public NanoBrain brain { get; protected set; }
public NanoBrainObj newBrain { get; protected set; }
public virtual Vector3 outputValue { get; set; }
[System.NonSerialized]
public int stale = 0;
[System.NonSerialized]
public int layerIx;
#endregion Runtime state
public Nucleus(NanoBrainObj brain, string name) {
this.newBrain = brain;
if (this.newBrain != null)
this.newBrain.nuclei.Add(this);
else
Debug.LogError("No neuroid network");
this._name = name;
this.id = this.GetHashCode();
}
public virtual void AddReceiver(Nucleus receiver) {
this.receivers.Add(new Receiver(receiver));
//receiver.synapses[this] = 1.0f; // new(this);
receiver.SetWeight(this, 1.0f);
//Debug.Log($"receiver # {this.receivers.Count} synapse count {receiver.synapses.Count}");
}
public static void Delete(Nucleus nucleus) {
foreach (Synapse synapse in nucleus.synapses) {
if (synapse.nucleus.receivers.Count > 1) {
// there is another nucleus feeding into this input nucleus
synapse.nucleus.receivers.RemoveAll(r => r.nucleus == nucleus);
} else {
// No other links, delete it.
Nucleus.Delete(synapse.nucleus);
}
}
foreach (Receiver receiver in nucleus.receivers)
receiver.nucleus.synapses.RemoveAll(s => s.nucleus == nucleus);
nucleus.newBrain.nuclei.RemoveAll(n => n == nucleus);
}
public void GetInputFrom(Nucleus input, float weight = 1.0f) {
input.AddReceiver(this);
this.SetWeight(input, weight);
}
public bool isSleeping {
get {
return this.stale > 2;
}
}
public bool SynapseExists(Nucleus nucleus) {
foreach (Synapse synapse in synapses) {
if (synapse.nucleus == nucleus)
return true;
}
return false;
}
public void SetWeight(Nucleus nucleus, float weight) {
foreach (Synapse synapse in synapses) {
if (synapse.nucleus == nucleus) {
synapse.weight = weight;
return;
}
}
Synapse newSynapse = new(nucleus, weight);
synapses.Add(newSynapse);
}
}
[System.Serializable]
public class Synapse {
[System.NonSerialized]
public Nucleus nucleus;
public int nucleusId;
public float weight;
public Synapse(Nucleus nucleus, float weight) {
this.nucleus = nucleus;
this.nucleusId = nucleus.id;
this.weight = weight;
}
public void Rebuild(NanoBrainObj brain) {
if (brain == null) {
return;
}
foreach (Nucleus nucleus in brain.nuclei) {
if (nucleus.id == this.nucleusId) {
this.nucleus = nucleus;
return;
}
}
Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}");
}
}
[System.Serializable]
public class Receiver {
[System.NonSerialized]
public Nucleus nucleus;
public int nucleusId;
public Receiver(Nucleus nucleus) {
this.nucleus = nucleus;
this.nucleusId = nucleus.id;
}
public void Rebuild(NanoBrainObj brain) {
if (brain == null)
return;
foreach (Nucleus nucleus in brain.nuclei) {
if (nucleus.id == this.nucleusId) {
this.nucleus = nucleus;
return;
}
}
Debug.LogError($"Synapse deserialization error: could not find nucleus with id {this.nucleusId}");
}
}