using UnityEngine; namespace NanoBrain { /// /// A Receptor is a Nucleus which can receive input (called Stimulus) from outside the the cluster/brain /// /// It has the ability to distinguish stimuli from different things using an array of Nuclei public interface IReceptor { /// /// Get the name of the receptor /// /// The name of the receptor public string GetName(); /// /// The array of nuclei used to track multiple things sending stimuli /// /// The size of the array determines the maximum number of things which can be distinguished public Nucleus[] nucleiArray { get; set; } /// /// Extends the nucleiArray with an additional element /// /// A prefab of the nucleus to add? public void AddReceptorElement(ClusterPrefab prefab); /// /// Removes the last element from the nucleiArray /// public void RemoveReceptorElement(); /// /// Add a receiver for this receptor array /// /// The receiving Nucleus /// The initial weight to use for the synapses /// This function will add a synapse to the receiver for each element in the nucleiArray. public void AddArrayReceiver(Nucleus receiverToAdd, float weight = 1); /// /// Process an external stimulus /// /// The value of the stimulus /// The id of the thing causing the stimulus /// The name of the thing causing the stimulus public void ProcessStimulus(Vector3 inputValue, int thingId = 0, string thingName = null); } public static class IReceptorHelpers { /// /// Implementation for the NanoBrain::IReceptor::AddReceptorElement which can be used for all implementations of IReceptor /// /// The IReceptor which needs to extend its nucleiArray /// A prefab of the nucleus to add? public static void AddReceptorElement(IReceptor receptor, ClusterPrefab prefab) { if (receptor.nucleiArray.Length == 0) { Debug.LogError("Empty perceptoid array, cannot add"); } int newLength = receptor.nucleiArray.Length + 1; Nucleus[] newArray = new Nucleus[newLength]; string baseName = receptor.GetName(); int colonPos = baseName.IndexOf(":"); if (colonPos > 0) baseName = baseName[..colonPos]; for (int i = 0; i < receptor.nucleiArray.Length; i++) newArray[i] = receptor.nucleiArray[i]; if (receptor.nucleiArray[0] is Nucleus nucleus) { newArray[newLength - 1] = nucleus.Clone(prefab); newArray[newLength - 1].name = $"{baseName}: {newLength - 1}"; } foreach (Nucleus element in receptor.nucleiArray) { if (element is IReceptor receptorElement) { receptorElement.nucleiArray = newArray; } } } /// /// Implementation for the NanoBrain::IReceptor::RemoteReceptorElement which can be used for all implementations of IReceptor /// /// The IReceptor which needs to shorten its nucleiArray public static void RemoveReceptorElement(IReceptor receptor) { int newLength = receptor.nucleiArray.Length - 1; if (newLength == 0) { Debug.LogWarning("Perceptoid array cannot be empty"); } Nucleus[] newArray = new Nucleus[newLength]; for (int i = 0; i < newLength; i++) newArray[i] = receptor.nucleiArray[i]; // Delete the last perception if (receptor.nucleiArray[newLength] is Nucleus nucleus) Neuron.Delete(nucleus); foreach (Nucleus element in receptor.nucleiArray) { if (element is IReceptor receptorElement) { receptorElement.nucleiArray = newArray; } } } /// /// Implementation for the NanoBreain::IRceptor::AddArrayReceiver which can be used for all implementations of IReceptor /// /// The IReceptor for which a receiving nuclues needs to be added /// The nucleus to receive input from the receptor /// The initial weight for the synapses public static void AddArrayReceiver(IReceptor receptor, Nucleus receiverToAdd, float weight = 1) { foreach (Nucleus element in receptor.nucleiArray) { if (element is Cluster cluster) cluster.defaultOutput.AddReceiver(receiverToAdd, weight); if (element is Neuron neuron) neuron.AddReceiver(receiverToAdd, weight); } } } }