public MeteoritesGenome(MeteoritesGenome templateGenome)
 {
     /*numObstacles = templateGenome.numObstacles;
      * minObstacleSize = templateGenome.minObstacleSize;
      * maxObstacleSize = templateGenome.maxObstacleSize;
      *
      * obstaclePositions = new Vector2[numObstacles];
      * obstacleScales = new float[numObstacles];
      * for (int i = 0; i < obstaclePositions.Length; i++) {
      *  if (i < templateGenome.obstaclePositions.Length) {  // when changing numOctaves, doesn't immediately change parentgenome terrainWaves array
      *      //terrainWaves[i] = new Vector3(templateGenome.terrainWaves[i].x, templateGenome.terrainWaves[i].y, templateGenome.terrainWaves[i].z);
      *      //Debug.Log("Copy Terrain Genome: " + terrainWaves[i].ToString());
      *      obstaclePositions[i] = new Vector2(templateGenome.obstaclePositions[i].x, templateGenome.obstaclePositions[i].y);
      *      obstacleScales[i] = templateGenome.obstacleScales[i];
      *      // = size;
      *  }
      *  else {
      *      obstaclePositions[i] = new Vector2(UnityEngine.Random.Range(0f, 1f), UnityEngine.Random.Range(0f, 1f));
      *      // Revisit this for prepping agentStartPositions!!!!
      *      if ((obstaclePositions[i] - new Vector2(0.5f, 0.5f)).magnitude < 0.15f) {
      *          obstaclePositions[i] = new Vector2(0.5f, 0.5f) + (obstaclePositions[i] - new Vector2(0.5f, 0.5f)) * 0.15f / (obstaclePositions[i] - new Vector2(0.5f, 0.5f)).magnitude;
      *      }
      *      obstacleScales[i] = UnityEngine.Random.Range(1f, 1f);
      *  }
      * }*/
 }
    public void CopyGenomeFromTemplate(EnvironmentGenome templateGenome)
    {
        //Debug.Log("CopyGenomeFromTemplate BEFORE startPosCount: " + templateGenome.agentStartPositionsList.Count.ToString());
        // This method creates a clone of the provided ScriptableObject Genome - should have no shared references!!!
        this.challengeType = templateGenome.challengeType;
        arenaBounds        = new Vector3(templateGenome.arenaBounds.x, templateGenome.arenaBounds.y, templateGenome.arenaBounds.z);

        agentStartPositionsList = new List <StartPositionGenome>();
        for (int i = 0; i < templateGenome.agentStartPositionsList.Count; i++)
        {
            //Debug.Log("CopyGenomeFromTemplate DURING i: " + i.ToString());
            StartPositionGenome genomeCopy = new StartPositionGenome(templateGenome.agentStartPositionsList[i]);
            agentStartPositionsList.Add(genomeCopy);
        }
        //Debug.Log("CopyGenomeFromTemplate AFTER startPosCount: " + agentStartPositionsList.Count.ToString());

        useTerrain = templateGenome.useTerrain;
        if (useTerrain)
        {
            terrainGenome = new TerrainGenome(templateGenome.terrainGenome);
            //terrainGenome.InitializeRandomGenome();
        }
        useBasicObstacles = templateGenome.useBasicObstacles;
        if (useBasicObstacles)
        {
            basicObstaclesGenome = new BasicObstaclesGenome(templateGenome.basicObstaclesGenome, this);
            //basicObstaclesGenome.InitializeRandomGenome();
        }
        useTargetColumn = templateGenome.useTargetColumn;
        if (useTargetColumn)
        {
            targetColumnGenome = new TargetColumnGenome();
            //targetColumnGenome.InitializeRandomGenome();
        }
        useAtmosphere = templateGenome.useAtmosphere;
        if (useAtmosphere)
        {
            atmosphereGenome = new AtmosphereGenome(templateGenome.atmosphereGenome);
            //basicObstaclesGenome.InitializeRandomGenome();
        }
        useMeteorites = templateGenome.useMeteorites;
        if (useMeteorites)
        {
            meteoritesGenome = new MeteoritesGenome(templateGenome.meteoritesGenome);
            //basicObstaclesGenome.InitializeRandomGenome();
        }

        // For now this is fine -- but eventually might want to copy brainGenome from saved asset!
        //brainGenome = new BrainGenome();  // creates neuron and axonLists
        //InitializeRandomBrainGenome();
    }
    public EnvironmentGenome BirthNewGenome(EnvironmentGenome parentGenome, int index, Challenge.Type challengeType, float mutationRate, float mutationDriftAmount)
    {
        EnvironmentGenome newGenome = new EnvironmentGenome(index);

        newGenome.challengeType = parentGenome.challengeType;
        newGenome.arenaBounds   = new Vector3(parentGenome.arenaBounds.x, parentGenome.arenaBounds.y, parentGenome.arenaBounds.z);

        newGenome.useTerrain = parentGenome.useTerrain;
        if (parentGenome.useTerrain)
        {
            newGenome.terrainGenome = TerrainGenome.BirthNewGenome(parentGenome.terrainGenome, mutationRate, mutationDriftAmount);
        }
        newGenome.useBasicObstacles = parentGenome.useBasicObstacles;
        if (parentGenome.useBasicObstacles)
        {
            newGenome.basicObstaclesGenome = BasicObstaclesGenome.BirthNewGenome(parentGenome.basicObstaclesGenome, mutationRate, mutationDriftAmount, this);
        }
        newGenome.useTargetColumn = parentGenome.useTargetColumn;
        if (parentGenome.useTargetColumn)
        {
            newGenome.targetColumnGenome = TargetColumnGenome.BirthNewGenome(parentGenome.targetColumnGenome, mutationRate, mutationDriftAmount);
        }
        newGenome.useAtmosphere = parentGenome.useAtmosphere;
        if (parentGenome.useAtmosphere)
        {
            newGenome.atmosphereGenome = AtmosphereGenome.BirthNewGenome(parentGenome.atmosphereGenome, mutationRate, mutationDriftAmount);
        }
        newGenome.useMeteorites = parentGenome.useMeteorites;
        if (parentGenome.useMeteorites)
        {
            newGenome.meteoritesGenome = MeteoritesGenome.BirthNewGenome(parentGenome.meteoritesGenome, mutationRate, mutationDriftAmount);
        }

        // StartPositions:
        // HACKY! DOES NOT SUPPORT EVOLVING START POSITIONS! ALL THE SAME!!!!
        newGenome.agentStartPositionsList = parentGenome.agentStartPositionsList;

        /*newGenome.agentStartPositionsList = new List<Vector3>();
         * //Debug.Log("(parentGenome.agentStartPositionsList.Count" + parentGenome.agentStartPositionsList.Count.ToString());
         * for (int i = 0; i < parentGenome.agentStartPositionsList.Count; i++) {
         *  newGenome.agentStartPositionsList.Add(new Vector3(parentGenome.agentStartPositionsList[i].x, parentGenome.agentStartPositionsList[i].y, parentGenome.agentStartPositionsList[i].z));
         * }
         * newGenome.agentStartRotationsList = new List<Quaternion>();
         * for (int i = 0; i < parentGenome.agentStartRotationsList.Count; i++) {
         *  newGenome.agentStartRotationsList.Add(new Quaternion(parentGenome.agentStartRotationsList[i].x, parentGenome.agentStartRotationsList[i].y, parentGenome.agentStartRotationsList[i].z, parentGenome.agentStartRotationsList[i].w));
         * }*/

        return(newGenome);
    }
    public static MeteoritesGenome BirthNewGenome(MeteoritesGenome parentGenome, float mutationRate, float mutationDriftAmount)
    {
        // OBSTACLES:
        // NEED TO COPY ALL ATTRIBUTES HERE unless I switch mutation process to go: full-copy, then re-traverse and mutate on a second sweep...
        MeteoritesGenome newGenome = new MeteoritesGenome();

        /*
         * newGenome.numObstacles = parentGenome.numObstacles;
         * newGenome.minObstacleSize = parentGenome.minObstacleSize;
         * newGenome.maxObstacleSize = parentGenome.maxObstacleSize;
         *
         *
         * newGenome.obstaclePositions = new Vector2[newGenome.numObstacles];
         * newGenome.obstacleScales = new float[newGenome.numObstacles];
         * for (int i = 0; i < parentGenome.obstaclePositions.Length; i++) {
         *  newGenome.obstaclePositions[i] = new Vector2(parentGenome.obstaclePositions[i].x, parentGenome.obstaclePositions[i].y);
         *  newGenome.obstacleScales[i] = parentGenome.obstacleScales[i];
         *  float rand = UnityEngine.Random.Range(0f, 1f);
         *  if (rand < mutationRate) {
         *      float newPosX = UnityEngine.Random.Range(0f, 1f);
         *      newGenome.obstaclePositions[i].x = Mathf.Lerp(newGenome.obstaclePositions[i].x, newPosX, mutationDriftAmount);
         *  }
         *  if (rand < mutationRate) {
         *      float newPosZ = UnityEngine.Random.Range(0f, 1f);
         *      newGenome.obstaclePositions[i].y = Mathf.Lerp(newGenome.obstaclePositions[i].y, newPosZ, mutationDriftAmount);
         *  }
         *  if ((newGenome.obstaclePositions[i] - new Vector2(0.5f, 0.5f)).magnitude < 0.15f) {
         *      newGenome.obstaclePositions[i] = new Vector2(0.5f, 0.5f) + (newGenome.obstaclePositions[i] - new Vector2(0.5f, 0.5f)) * 0.15f / (newGenome.obstaclePositions[i] - new Vector2(0.5f, 0.5f)).magnitude;
         *  }
         *  if (rand < mutationRate) {
         *      float newScale = UnityEngine.Random.Range(newGenome.minObstacleSize, newGenome.maxObstacleSize);
         *      newGenome.obstacleScales[i] = Mathf.Lerp(newGenome.obstacleScales[i], newScale, mutationDriftAmount);
         *  }
         * }
         */
        return(newGenome);
    }