예제 #1
0
    // Update is called once per frame
    void Update()
    {
        //Used to track the best performing spawn
        double bestFitness = 0;
        int    bestSpawn   = 0;


        //TimeScale
        if (Input.GetKeyDown(KeyCode.Comma))
        {
            Time.timeScale *= .5f;
        }
        if (Input.GetKeyDown(KeyCode.Period))
        {
            Time.timeScale *= 2;
        }
        int species = 0;
        int genome  = 0;

        //Update each spawn in the population, used to increase their fitness as needed and have them respond to the inputs
        for (int i = 0; i < population; i++)
        {
            GameObject     closestFood = foods[0];
            float          distance    = Vector3.Distance(closestFood.transform.position, spawns[i].transform.position); //distance to closest food
            SpriteRenderer sprite      = spawns[i].GetComponent <SpriteRenderer>();                                      //get spawn sprite
            sprite.color = genAlg.species[species].color;

            for (int j = 0; j < numFood; j++) //Finds the closest food item
            {
                float newDistance = Vector3.Distance(spawns[i].transform.position, foods[j].transform.position);
                if (newDistance < distance)
                {
                    distance    = newDistance;
                    closestFood = foods[j];
                }
            }

            //relative position of spawn to closest food
            Vector2 relPos = spawns[i].transform.position - closestFood.transform.position;
            relPos.Normalize();

            Vector2 relRotation = spawns[i].transform.up;
            relRotation.Normalize();

            //---------------Create the input list--------------------------------------------\\
            List <double> input = new List <double> {
                relPos.x, relPos.y, relRotation.x, relRotation.y, 1
            };


            //---------------Get the ouput list by inputing the input list--------------------\\
            List <double> output = genAlg.species[species].population[genome].Run(input);



            //----------------Applying the output to te spawn---------------------------------\\
            spawns[i].transform.Rotate(new Vector3(0, 0, (float)(output[0] - output[1]) * Time.deltaTime * 100));
            spawns[i].transform.Translate(Vector2.up * speedAdj * Time.deltaTime);

            //---------------Increasing Fitness-------------------------------------------------\\
            if (distance < 1f)
            {
                genAlg.species[species].population[genome].fitness += genAlg.species[species].population[genome].fitness * .1F + 1;

                //move food particle
                closestFood.transform.position = new Vector3(Random.Range(0, gameArea.x), Random.Range(0, gameArea.y));
            }


            //Some informational text, and allowing for the search of the most fit spawn
            if (i == 0)
            {
                infoText.text = "Generation: " + genAlg.generation + "\nInputs: relPosX, relPosY, relRotaionX, relRotationY\nOutputs: rightRotation, leftRotation"
                                + "\nTime: " + Time.time.ToString("0")
                                + "\nTime Scale: " + Time.timeScale
                                + "\nSpecies Count: " + genAlg.species.Count;
                bestFitness = genAlg.species[species].population[genome].fitness;
                bestSpawn   = i;


                //----------------Use the first spawn as the selected object in visual representation--------------//
                if (updateGraph)
                {
                    graph.NodeUpdate(genAlg.species[randomWatchSpecies].population[randomWatchGenome]);
                }
            }
            else
            {
                if (bestFitness < genAlg.species[species].population[genome].fitness)
                {
                    bestFitness  = genAlg.species[species].population[genome].fitness;
                    sprite       = spawns[bestSpawn].GetComponent <SpriteRenderer>();
                    sprite.color = genAlg.species[species].color;
                    bestSpawn    = i;
                    sprite       = spawns[i].GetComponent <SpriteRenderer>();
                    sprite.color = Color.yellow;
                }
            }

            if (species == randomWatchSpecies && genome == randomWatchGenome)
            {
                randomWatchSpawn = i;
            }

            genome++;
            if (genome >= genAlg.species[species].population.Count)
            {
                species++;
                genome = 0;
            }

            //Border control
            if (spawns[i].transform.position.y < 0)
            {
                spawns[i].transform.position = new Vector3(spawns[i].transform.position.x, gameArea.y);
            }
            else if (spawns[i].transform.position.y > gameArea.y)
            {
                spawns[i].transform.position = new Vector3(spawns[i].transform.position.x, 0);
            }

            if (spawns[i].transform.position.x < 0)
            {
                spawns[i].transform.position = new Vector3(gameArea.x, spawns[i].transform.position.y);
            }
            else if (spawns[i].transform.position.x > gameArea.x)
            {
                spawns[i].transform.position = new Vector3(0, spawns[i].transform.position.y);
            }
        }

        //More Stats
        genAlg.CalculateBestWorstAvTot();
        infoText.text += "\nBest Fitness: " + genAlg.bestFitness + "\nAverage Fitness: " + genAlg.averageFitness + "\nLowest Fitness: " + genAlg.worstFitness;
        fitnessGraph.UpdateFitnessGraph(genAlg.generation, genAlg.bestFitness, genAlg.averageFitness);

        //Change first spawn's color so it is recognizable
        spawns[randomWatchSpawn].GetComponent <SpriteRenderer>().color = Color.cyan;


        //----------------Creates the New Population using the fitness levels of the old one----------------//
        if (Time.time > updateTime)
        {
            updateTime += populationResetTime;

            //--------------The main function that creates the new population into the genAlg class--------//

            genAlg.Epoch();


            for (int i = 0; i < population; i++)
            {
                //change all of the spawns positions
                spawns[i].transform.position = new Vector3(Random.Range(0, gameArea.x), Random.Range(0, gameArea.y));

                //Update the spawns neural networks with the new weights
                //nNetwork[i].PutWeights(genAlg.population[i].weights);
            }

            //change the location of all the food
            for (int i = 0; i < numFood; i++)
            {
                foods[i].transform.position = new Vector3(Random.Range(0, gameArea.x), Random.Range(0, gameArea.y));
            }
            randomWatchSpecies = Random.Range(0, genAlg.species.Count);
            randomWatchGenome  = Random.Range(0, genAlg.species[randomWatchSpecies].population.Count);
            graph.CreateGraph(genAlg.species[randomWatchSpecies].population[randomWatchGenome]);
            fitnessGraph.UpdateSpeciesPopulationGraph(genAlg.species, genAlg.generation);
        }
    }