Example #1
0
        /// <summary>
        /// Gets the readable neurons from the containers of the type requested (and skips the current container)
        /// </summary>
        private static List<Tuple<ContainerInput, List<INeuron>, double>> BuildExternalLinksRandom_Continue_Eligible(BotConstruction_PartMap partMap, NeuronContainerType containerType, int currentIndex, ContainerInput[] containers, List<INeuron>[] readable)
        {
            var retVal = new List<Tuple<ContainerInput, List<INeuron>, double>>();

            for (int cntr = 0; cntr < containers.Length; cntr++)
            {
                if (cntr == currentIndex)
                {
                    continue;
                }

                if (containers[cntr].ContainerType != containerType)
                {
                    continue;
                }

                double? weight = null;
                foreach (var mapped in partMap.Actual)
                {
                    if ((mapped.Item1.Token == containers[currentIndex].Token && mapped.Item2.Token == containers[cntr].Token) ||
                        (mapped.Item2.Token == containers[currentIndex].Token && mapped.Item1.Token == containers[cntr].Token))
                    {
                        weight = mapped.Item3;
                        break;
                    }
                }

                if (weight == null)
                {
                    // The map doesn't hold a link between these two containers
                    continue;
                }

                retVal.Add(Tuple.Create(containers[cntr], readable[cntr], weight.Value));
            }

            return retVal;
        }
Example #2
0
        private static NeuralLink[][] BuildExternalLinksRandom(BotConstruction_PartMap partMap, ContainerInput[] containers, double maxWeight)
        {
            NeuralLink[][] retVal = new NeuralLink[containers.Length][];

            // Pull out the readable nodes from each container
            List<INeuron>[] readable = BuildExternalLinksRandom_FindReadable(containers);

            // Shoot through each container, and create links that feed it
            for (int cntr = 0; cntr < containers.Length; cntr++)
            {
                ContainerInput container = containers[cntr];

                if (container.ExternalRatios == null || container.ExternalRatios.Length == 0)
                {
                    // This container shouldn't be fed by other containers (it's probably a sensor)
                    retVal[cntr] = null;
                    continue;
                }

                // Find writable nodes
                List<INeuron> writeable = new List<INeuron>();
                writeable.AddRange(container.Container.Neruons_ReadWrite);
                writeable.AddRange(container.Container.Neruons_Writeonly);

                if (writeable.Count == 0)
                {
                    // There are no nodes that can be written
                    retVal[cntr] = null;
                    continue;
                }

                List<NeuralLink> links = new List<NeuralLink>();

                foreach (var ratio in container.ExternalRatios)
                {
                    // Link to this container type
                    links.AddRange(BuildExternalLinksRandom_Continue(partMap, containers, cntr, ratio, readable, writeable, maxWeight));
                }

                // Add links to the return jagged array
                if (links.Count == 0)
                {
                    retVal[cntr] = null;
                }
                else
                {
                    retVal[cntr] = links.ToArray();
                }
            }

            // Exit Function
            return retVal;
        }
Example #3
0
        private static List<NeuralLink> BuildExternalLinksRandom_Continue(BotConstruction_PartMap partMap, ContainerInput[] containers, int currentIndex, Tuple<NeuronContainerType, ExternalLinkRatioCalcType, double> ratio, List<INeuron>[] readable, List<INeuron> writeable, double maxWeight)
        {
            List<NeuralLink> retVal = new List<NeuralLink>();

            // Find eligible containers
            var matchingInputs = BuildExternalLinksRandom_Continue_Eligible(partMap, ratio.Item1, currentIndex, containers, readable);
            if (matchingInputs.Count == 0)
            {
                return retVal;
            }

            // Add up all the eligible neurons
            int sourceNeuronCount = matchingInputs.Sum(o => o.Item2.Count);

            double multiplier = matchingInputs.Average(o => o.Item3);
            multiplier *= ratio.Item3;

            // Figure out how many to create (this is the total count.  Each feeder container will get a percent of these based on its ratio of
            // neurons compared to the other feeders)
            int count = BuildExternalLinks_Count(ratio.Item2, sourceNeuronCount, writeable.Count, multiplier);
            if (count == 0)
            {
                return retVal;
            }

            // I don't want to draw so evenly from all the containers.  Draw from all containers at once.  This will have more clumping, and some containers
            // could be completely skipped.
            //
            // My reasoning for this is manipulators like thrusters don't really make sense to be fed evenly from every single sensor.  Also, thruster's count is by
            // destination neuron, which is very small.  So fewer total links will be created by doing just one pass
            List<Tuple<int, int>> inputLookup = new List<Tuple<int, int>>();
            for (int outer = 0; outer < matchingInputs.Count; outer++)
            {
                for (int inner = 0; inner < matchingInputs[outer].Item2.Count; inner++)
                {
                    //Item1 = index into matchingInputs
                    //Item2 = index into neuron
                    inputLookup.Add(new Tuple<int, int>(outer, inner));
                }
            }

            // For now, just build completely random links
            //NOTE: This is ignoring the relative weights in the map passed in.  Those weights were used to calculate how many total links there should be
            Tuple<int, int, double>[] links = GetRandomLinks(inputLookup.Count, writeable.Count, count, Enumerable.Range(0, inputLookup.Count).ToArray(), Enumerable.Range(0, writeable.Count).ToArray(), new SortedList<int, int>(), maxWeight);

            foreach (var link in links)
            {
                // link.Item1 is the from neuron.  But all the inputs were put into a single list, so use the inputLookup to figure out which container/neuron
                // is being referenced
                var input = matchingInputs[inputLookup[link.Item1].Item1];
                int neuronIndex = inputLookup[link.Item1].Item2;

                double[] brainChemicals = GetBrainChemicalModifiers(input.Item1, maxWeight);		// the brain chemicals are always based on the from container (same in NeuralOperation.Tick)

                retVal.Add(new NeuralLink(input.Item1.Container, containers[currentIndex].Container, input.Item2[neuronIndex], writeable[link.Item2], link.Item3, brainChemicals));
            }

            // Exit Function
            return retVal;
        }
Example #4
0
        /// <summary>
        /// This overload takes a map that tells which parts can link to which
        /// </summary>
        public static ContainerOutput[] LinkNeurons(BotConstruction_PartMap partMap, ContainerInput[] containers, double maxWeight)
        {
            //TODO: Take these as params (these are used when hooking up existing links)
            const int MAXINTERMEDIATELINKS = 3;
            const int MAXFINALLINKS = 3;

            NeuralLink[][] internalLinks, externalLinks;
            if (containers.Any(o => o.ExternalLinks != null || o.InternalLinks != null))
            {
                internalLinks = BuildInternalLinksExisting(containers, MAXINTERMEDIATELINKS, MAXFINALLINKS);
                externalLinks = BuildExternalLinksExisting(containers, MAXINTERMEDIATELINKS, MAXFINALLINKS);        //NOTE: The partMap isn't needed for existing links.  It is just to help figure out new random links

                internalLinks = CapWeights(internalLinks, maxWeight);
                externalLinks = CapWeights(externalLinks, maxWeight);
            }
            else
            {
                internalLinks = BuildInternalLinksRandom(containers, maxWeight);
                externalLinks = BuildExternalLinksRandom(partMap, containers, maxWeight);
            }

            // Build the return
            ContainerOutput[] retVal = new ContainerOutput[containers.Length];
            for (int cntr = 0; cntr < containers.Length; cntr++)
            {
                retVal[cntr] = new ContainerOutput(containers[cntr].Container, internalLinks[cntr], externalLinks[cntr]);
            }

            // Exit Function
            return retVal;
        }