NeuralNetwork.Network CreateNewNetwork()
    {
        //Create a new
        NeuralNetwork.Network newNetwork = Instantiate(neuralNetworkPrefab, transform);
        newNetwork.inputLayer = input;
        newNetwork.onOutput.AddListener(output.SetFly);
        newNetwork.InitializeConnections();

        //Add the new network to the list of networks
        NetworkIndividual newIndividual = new NetworkIndividual();

        newIndividual.network = newNetwork;
        networkPopulation.Add(newIndividual);

        return(newNetwork);
    }
    public void ReplacePopulation(List <NeuralNetwork.Network> loadedNetworks)
    {
        //Clear the population
        while (networkPopulation.Count > 0)
        {
            Destroy(networkPopulation[0].network.gameObject);
            networkPopulation.RemoveAt(0);
        }

        //Load the new population
        population = loadedNetworks.Count;

        for (int i = 0; i < population; i++)
        {
            NetworkIndividual newIndividual = new NetworkIndividual();
            newIndividual.network        = loadedNetworks[i];
            loadedNetworks[i].inputLayer = input;
            loadedNetworks[i].onOutput.AddListener(output.SetFly);
            networkPopulation.Add(newIndividual);
        }
    }
    public IEnumerator RunSingleEvolutionRound()
    {
        generation++;

        //Run the simulation for each individual
        for (int i = 0; i < networkPopulation.Count; i++)
        {
            yield return(StartCoroutine(Simulation.Instance.RunSimulation(networkPopulation[i].network, 0)));

            networkPopulation[i].fitness = Simulation.Instance.step;
        }

        //Sort the list by fitness
        networkPopulation.Sort(
            delegate(NetworkIndividual p1, NetworkIndividual p2)
        {
            return(p2.fitness.CompareTo(p1.fitness));
        }
            );

        //Kill the weak individuals
        int numberToKill = (int)(population * deathRatio);
        Queue <NetworkIndividual> killedIndividual = new Queue <NetworkIndividual>();

        for (int i = 0; i < numberToKill; i++)
        {
            //Some survive by luck
            if (Random.Range(0.0f, 1.0f) > 0.05f)
            {
                killedIndividual.Enqueue(networkPopulation[networkPopulation.Count - 1]);
                networkPopulation.RemoveAt(networkPopulation.Count - 1);
            }
        }

        //Calculate the average fitness for ui
        float average = 0;

        foreach (NetworkIndividual i in networkPopulation)
        {
            average += i.fitness;
        }
        average /= networkPopulation.Count;


        int mutatedCount = 0;

        //Mutate some random individuals
        foreach (NetworkIndividual i in networkPopulation)
        {
            if (mutateChance > Random.Range(0.0f, 1.0f))
            {
                MutateGene(i.network);
                mutatedCount++;
            }
        }

        //Breed
        int survivorsCount    = networkPopulation.Count;
        int childrenToProduce = population - survivorsCount;

        for (int i = 0; i < childrenToProduce; i++)
        {
            //Produce a child with two random survivors
            NetworkIndividual child = killedIndividual.Dequeue();
            networkPopulation.Add(child);
            Breed(networkPopulation[Random.Range(0, survivorsCount)].network, networkPopulation[Random.Range(0, survivorsCount)].network, child.network);
        }

        //Display an information panel about this generation
        infoPanelManager.NewGeneration(generation, networkPopulation[0].fitness, (int)average, mutatedCount, childrenToProduce, networkPopulation.Count);

        //Update the curves
        averageCurve.AddPoint(average);
        bestCurve.AddPoint(networkPopulation[0].fitness);
    }