示例#1
0
 public void InitShaderTexture(BrainNEAT brain)
 {
     if (neuronPositionsTexture == null)
     {
         neuronPositionsTexture = new Texture2D(brain.neuronList.Count, 1, TextureFormat.RGBAHalf, false);
     }
     else
     {
         neuronPositionsTexture.Resize(brain.neuronList.Count, 1);
     }
 }
示例#2
0
 public void UpdateVertexColors(BrainNEAT brain)
 {
     //Debug.Log("UpdateVertexColors(BrainNEAT brain) " + GetColorFromValue(brain.neuronList[0].currentValue[0]).ToString());
     for (int i = 0; i < brain.neuronList.Count; i++)
     {
         ChangeNodeColor(i, GetColorFromNeuron(brain.neuronList[i]));
     }
     for (int j = 0; j < brain.connectionList.Count; j++)
     {
         //ChangeConnectionColor(j, GetColorFromConnection(brain.connectionList[j], brain));
     }
     meshBuilder.UpdateMeshColors();
 }
示例#3
0
 public void UpdateNodeVertexPositions(BrainNEAT brain)
 {
     for (int i = 0; i < nodeVertexList.Count; i++)
     {
         // for all neurons:
         //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString());
         //float size = neuronRadius + Mathf.Abs(brain.neuronList[i].previousValue) * neuronRadius * 0.12f;
         float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);
         meshBuilder.Vertices[nodeVertexList[i][0]] = nodePositionsList[i];
         meshBuilder.Vertices[nodeVertexList[i][1]] = nodePositionsList[i] + new Vector3(0f, size, 0f);
         meshBuilder.Vertices[nodeVertexList[i][2]] = nodePositionsList[i] + new Vector3(size, 0f, 0f) + new Vector3(0f, size, 0f);
         meshBuilder.Vertices[nodeVertexList[i][3]] = nodePositionsList[i] + new Vector3(size, 0f, 0f);
     }
     meshBuilder.UpdateMeshVertices();
 }
示例#4
0
    private Color GetColorFromConnection(ConnectionNEAT connection, BrainNEAT brain)
    {
        //black = -1, white = 1
        //float val01 = connection.weight[0] * 0.5f + 0.5f;
        float val01    = brain.neuronList[connection.fromNodeID].currentValue[0] * connection.weight[0] * 0.2f + 0.5f;
        Color newColor = new Color(val01, val01, val01);

        newColor = Color.Lerp(newColor, new Color(0f, 0f, 1f), 0f);
        //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.In) {
        //    newColor = Color.Lerp(newColor, new Color(0f, 1f, 0f), 0.75f);
        //}
        //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.Out) {
        //    newColor = Color.Lerp(newColor, new Color(1f, 0f, 0f), 0.75f);
        //}
        //Debug.Log(val01.ToString());
        return(newColor);
    }
示例#5
0
        //TODO: In more complete evaluators, take in an arena manager that lets you check out a room.  That will return the bot/brain that was
        //created for that room (request a room each time StartNewEvaluation is called, or if no rooms available at that moment, each tick until
        //a room is free - then start evaluating from that moment)
        public Evaluator1_FAIL(Bot bot, BrainNEAT brainPart, SensorHoming[] homingParts, Point3D homePoint, ExperimentInitArgs_Activation activation, HyperNEAT_Args hyperneatArgs = null)
        {
            _bot         = bot;
            _brainPart   = brainPart;
            _homingParts = homingParts;

            _homePoint = homePoint;

            _activation    = activation;
            _hyperneatArgs = hyperneatArgs;

            foreach (SensorHoming homingPart in homingParts)
            {
                homingPart.HomePoint  = homePoint;
                homingPart.HomeRadius = _maxDistance * 1.25;
            }
        }
示例#6
0
    public void UpdateConnectionVertexPositions(BrainNEAT brain)
    {
        //for (int c = 0; c < brain.connectionList.Count; c++) {

        //BuildLink(meshBuilder, nodePositionsList[brain.connectionList[c].fromNodeID] + offset, nodePositionsList[brain.connectionList[c].toNodeID] + offset, connectionWidth, GetColorFromValue(brain.connectionList[c].weight[0]));
        //Debug.Log("BuildNew BrainMesh: from: " + nodePositionsList[brain.connectionList[c].fromNodeID].ToString() + ", to: " + nodePositionsList[brain.connectionList[c].toNodeID].ToString());
        //}
        for (int i = 0; i < connectionVertexList.Count; i++)
        {
            // for all connections:

            Vector3 linkVector  = new Vector3(nodePositionsList[brain.connectionList[i].toNodeID].x - nodePositionsList[brain.connectionList[i].fromNodeID].x, nodePositionsList[brain.connectionList[i].toNodeID].y - nodePositionsList[brain.connectionList[i].fromNodeID].y, nodePositionsList[brain.connectionList[i].toNodeID].z - nodePositionsList[brain.connectionList[i].fromNodeID].z);
            Vector3 widthVector = new Vector3(new Vector2(linkVector.y, -linkVector.x).normalized.x, new Vector2(linkVector.y, -linkVector.x).normalized.y, 0f) * (connectionWidthMin + Mathf.Abs(brain.connectionList[i].weight[0]) * connectionWidthMin * 0.62f);
            Vector3 cornerPos   = new Vector3(nodePositionsList[brain.connectionList[i].fromNodeID].x - widthVector.x * 0.5f + neuronRadiusMin * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].y - widthVector.y * 0.5f + neuronRadiusMin * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].z);
            //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString());
            meshBuilder.Vertices[connectionVertexList[i][0]] = cornerPos;
            meshBuilder.Vertices[connectionVertexList[i][1]] = cornerPos + linkVector;
            meshBuilder.Vertices[connectionVertexList[i][2]] = cornerPos + linkVector + widthVector;
            meshBuilder.Vertices[connectionVertexList[i][3]] = cornerPos + widthVector;
        }
        meshBuilder.UpdateMeshVertices();
    }
 public void InitShaderTexture(BrainNEAT brain) {
     if (neuronPositionsTexture == null) {
         neuronPositionsTexture = new Texture2D(brain.neuronList.Count, 1, TextureFormat.RGBAHalf, false);
     }
     else {
         neuronPositionsTexture.Resize(brain.neuronList.Count, 1);
     }
 }
    public Mesh BuildNewMesh(BrainNEAT brain) {
        if(sourceCritter == null) {
            Debug.Log("BuildNewMesh(BrainNEAT brain) SOURCE CRITTER NULL!!!");
        }
        else {
            SetNeuronSegmentPositions(brain);
        }

        if (nodeVertexList == null) {
            nodeVertexList = new List<List<int>>();
        }
        else {
            nodeVertexList.Clear();
        }
        if (connectionVertexList == null) {
            connectionVertexList = new List<List<int>>();
        }
        else {
            connectionVertexList.Clear();
        }
        
        if(nodePositionsList == null) {
            nodePositionsList = new List<Vector3>();
        }
        else {
            nodePositionsList.Clear();
        }
        if(bezierCurveList == null) {
            bezierCurveList = new List<BezierCurve>();
        }
        else {
            bezierCurveList.Clear();
        }
        if(hiddenNodeIndicesList == null) {
            hiddenNodeIndicesList = new List<int>();  // keep track of hidden nodes for later use
        }
        else {
            hiddenNodeIndicesList.Clear();
        }
        
        meshBuilder = new MeshBuilder();
        //Debug.Log("PRE ERROR: brain: " + brain.ToString());
        //neuronRadius = 1.4f / Mathf.Max((float)brain.inputNeuronList.Count, (float)brain.outputNeuronList.Count);
        //Vector3 offset = new Vector3(neuronRadius * 0.5f, neuronRadius * 0.5f, 0f);

        int currentInputIndex = 0;
        int currentOutputIndex = 0; 

        for(int i = 0; i < brain.neuronList.Count; i++) {
            // go through all nodes and place them in proper spot
            float xpos = 0f;
            float ypos = 0f;
            float zpos = 0f;

            //float size = Mathf.Min((neuronRadius * brain.neuronList[i].currentValue[0] * 0.2f + 0.02f), 2.0f);
            float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);

            if (brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.In) {
                xpos = (float)(currentInputIndex + 1) / (float)(brain.inputNeuronList.Count + 1) - 0.5f;
                ypos = 0f;
                zpos = UnityEngine.Random.Range(-0.5f, 0.5f);
                currentInputIndex++;
                BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i]));
            }
            else if(brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.Hid) {
                xpos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f;
                ypos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f;
                zpos = UnityEngine.Random.Range(-0.5f, 0.5f);
                hiddenNodeIndicesList.Add(i);
                //BuildNode(meshBuilder, new Vector3(xpos, ypos, 0f), new Vector3(radius, 0f, 0f), new Vector3(0f, radius, 0f), GetColorFromValue(brain.neuronList[i].currentValue[0]));
            }
            else {  // output
                xpos = (float)(currentOutputIndex + 1) / (float)(brain.outputNeuronList.Count + 1) - 0.5f;
                ypos = 1f - neuronRadiusMax;
                zpos = UnityEngine.Random.Range(-0.5f, 0.5f);
                currentOutputIndex++;
                BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i]));
            }
            nodePositionsList.Add(new Vector3(xpos, ypos, zpos));
        }

        // position HiddenNodes!!
        
        // BUILD hidden nodes:
        for (int h = 0; h < hiddenNodeIndicesList.Count; h++) {
            float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[hiddenNodeIndicesList[h]].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);
            BuildNodeSphere(meshBuilder, new Vector3(nodePositionsList[hiddenNodeIndicesList[h]].x, nodePositionsList[hiddenNodeIndicesList[h]].y, nodePositionsList[hiddenNodeIndicesList[h]].z), size, GetColorFromNeuron(brain.neuronList[hiddenNodeIndicesList[h]]));
        }

        // CONNECTIONS!
        //connectionWidth = Mathf.Max(neuronRadius * 0.1f, 0.01f);
        //Debug.Log("BuildNew BrainMesh: numConnections: " + brain.connectionList.Count);
        for(int c = 0; c < brain.connectionList.Count; c++) {
            BezierCurve connectionBezier = new BezierCurve();
            connectionBezier.points[0] = nodePositionsList[brain.connectionList[c].fromNodeID];
            connectionBezier.points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f);
            connectionBezier.points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f);
            connectionBezier.points[3] = nodePositionsList[brain.connectionList[c].toNodeID];
            bezierCurveList.Add(connectionBezier);
            float startWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0]) * connectionWidthMax * 0.4f), connectionWidthMax), connectionWidthMin);
            float endWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * connectionWidthMax * 0.4f, connectionWidthMax), connectionWidthMin);
            BuildLinkBezier(meshBuilder, connectionBezier, startWidth, endWidth, GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]), GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID]));
            //Debug.Log("BuildNew BrainMesh: from: " + nodePositionsList[brain.connectionList[c].fromNodeID].ToString() + ", to: " + nodePositionsList[brain.connectionList[c].toNodeID].ToString());
        }
        
        //MoveHiddenNodes(brain, 1);
        return meshBuilder.CreateMesh();
    }
示例#9
0
    public Mesh BuildNewMesh(BrainNEAT brain)
    {
        if (sourceCritter == null)
        {
            Debug.Log("BuildNewMesh(BrainNEAT brain) SOURCE CRITTER NULL!!!");
        }
        else
        {
            SetNeuronSegmentPositions(brain);
        }

        if (nodeVertexList == null)
        {
            nodeVertexList = new List <List <int> >();
        }
        else
        {
            nodeVertexList.Clear();
        }
        if (connectionVertexList == null)
        {
            connectionVertexList = new List <List <int> >();
        }
        else
        {
            connectionVertexList.Clear();
        }

        if (nodePositionsList == null)
        {
            nodePositionsList = new List <Vector3>();
        }
        else
        {
            nodePositionsList.Clear();
        }
        if (bezierCurveList == null)
        {
            bezierCurveList = new List <BezierCurve>();
        }
        else
        {
            bezierCurveList.Clear();
        }
        if (hiddenNodeIndicesList == null)
        {
            hiddenNodeIndicesList = new List <int>();  // keep track of hidden nodes for later use
        }
        else
        {
            hiddenNodeIndicesList.Clear();
        }

        meshBuilder = new MeshBuilder();
        //Debug.Log("PRE ERROR: brain: " + brain.ToString());
        //neuronRadius = 1.4f / Mathf.Max((float)brain.inputNeuronList.Count, (float)brain.outputNeuronList.Count);
        //Vector3 offset = new Vector3(neuronRadius * 0.5f, neuronRadius * 0.5f, 0f);

        int currentInputIndex  = 0;
        int currentOutputIndex = 0;

        for (int i = 0; i < brain.neuronList.Count; i++)
        {
            // go through all nodes and place them in proper spot
            float xpos = 0f;
            float ypos = 0f;
            float zpos = 0f;

            //float size = Mathf.Min((neuronRadius * brain.neuronList[i].currentValue[0] * 0.2f + 0.02f), 2.0f);
            float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);

            if (brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.In)
            {
                xpos = (float)(currentInputIndex + 1) / (float)(brain.inputNeuronList.Count + 1) - 0.5f;
                ypos = 0f;
                zpos = UnityEngine.Random.Range(-0.5f, 0.5f);
                currentInputIndex++;
                BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i]));
            }
            else if (brain.neuronList[i].nodeType == GeneNodeNEAT.GeneNodeType.Hid)
            {
                xpos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f;
                ypos = 0.0f; // UnityEngine.Random.Range(neuronRadius, 1f - neuronRadius); //0.5f;
                zpos = UnityEngine.Random.Range(-0.5f, 0.5f);
                hiddenNodeIndicesList.Add(i);
                //BuildNode(meshBuilder, new Vector3(xpos, ypos, 0f), new Vector3(radius, 0f, 0f), new Vector3(0f, radius, 0f), GetColorFromValue(brain.neuronList[i].currentValue[0]));
            }
            else    // output
            {
                xpos = (float)(currentOutputIndex + 1) / (float)(brain.outputNeuronList.Count + 1) - 0.5f;
                ypos = 1f - neuronRadiusMax;
                zpos = UnityEngine.Random.Range(-0.5f, 0.5f);
                currentOutputIndex++;
                BuildNodeSphere(meshBuilder, new Vector3(xpos, ypos, zpos), size, GetColorFromNeuron(brain.neuronList[i]));
            }
            nodePositionsList.Add(new Vector3(xpos, ypos, zpos));
        }

        // position HiddenNodes!!

        // BUILD hidden nodes:
        for (int h = 0; h < hiddenNodeIndicesList.Count; h++)
        {
            float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[hiddenNodeIndicesList[h]].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);
            BuildNodeSphere(meshBuilder, new Vector3(nodePositionsList[hiddenNodeIndicesList[h]].x, nodePositionsList[hiddenNodeIndicesList[h]].y, nodePositionsList[hiddenNodeIndicesList[h]].z), size, GetColorFromNeuron(brain.neuronList[hiddenNodeIndicesList[h]]));
        }

        // CONNECTIONS!
        //connectionWidth = Mathf.Max(neuronRadius * 0.1f, 0.01f);
        //Debug.Log("BuildNew BrainMesh: numConnections: " + brain.connectionList.Count);
        for (int c = 0; c < brain.connectionList.Count; c++)
        {
            BezierCurve connectionBezier = new BezierCurve();
            connectionBezier.points[0] = nodePositionsList[brain.connectionList[c].fromNodeID];
            connectionBezier.points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f);
            connectionBezier.points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f);
            connectionBezier.points[3] = nodePositionsList[brain.connectionList[c].toNodeID];
            bezierCurveList.Add(connectionBezier);
            float startWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0]) * connectionWidthMax * 0.4f), connectionWidthMax), connectionWidthMin);
            float endWidth   = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * connectionWidthMax * 0.4f, connectionWidthMax), connectionWidthMin);
            BuildLinkBezier(meshBuilder, connectionBezier, startWidth, endWidth, GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]), GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID]));
            //Debug.Log("BuildNew BrainMesh: from: " + nodePositionsList[brain.connectionList[c].fromNodeID].ToString() + ", to: " + nodePositionsList[brain.connectionList[c].toNodeID].ToString());
        }

        //MoveHiddenNodes(brain, 1);
        return(meshBuilder.CreateMesh());
    }
示例#10
0
        /// <summary>
        /// Once the world is created on the worker thread, maps and bots need to be created for each room
        /// NOTE: This is called from the worker thread
        /// </summary>
        private void Arena_WorldCreated(object sender, EventArgs e)
        {
            World world = Arena.WorldAccessor.World;

            #region materials

            MaterialManager = new MaterialManager(world);
            MaterialIDs     = new MaterialIDs();

            // Wall
            Game.Newt.v2.NewtonDynamics.Material material = new Game.Newt.v2.NewtonDynamics.Material();
            material.Elasticity = ItemOptionsArco.ELASTICITY_WALL;
            MaterialIDs.Wall    = MaterialManager.AddMaterial(material);

            // Bot
            material        = new Game.Newt.v2.NewtonDynamics.Material();
            MaterialIDs.Bot = MaterialManager.AddMaterial(material);

            // Bot Ram
            material            = new Game.Newt.v2.NewtonDynamics.Material();
            material.Elasticity = ItemOptionsArco.ELASTICITY_BOTRAM;
            MaterialIDs.BotRam  = MaterialManager.AddMaterial(material);

            // Exploding Bot
            material = new Game.Newt.v2.NewtonDynamics.Material();
            material.IsCollidable    = false;
            MaterialIDs.ExplodingBot = MaterialManager.AddMaterial(material);

            // Weapon
            material           = new Game.Newt.v2.NewtonDynamics.Material();
            MaterialIDs.Weapon = MaterialManager.AddMaterial(material);

            // Treasure Box
            material = new Game.Newt.v2.NewtonDynamics.Material();
            MaterialIDs.TreasureBox = MaterialManager.AddMaterial(material);

            //TODO: Uncomment these
            // Collisions
            //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Bot, Collision_BotBot);
            //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Weapon, Collision_BotWeapon);
            //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.Weapon, Collision_WeaponWeapon);
            ////_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.Wall, Collision_BotWall);
            //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.Wall, Collision_WeaponWall);
            //_materialManager.RegisterCollisionEvent(_materialIDs.Weapon, _materialIDs.TreasureBox, Collision_WeaponTreasureBox);
            //_materialManager.RegisterCollisionEvent(_materialIDs.Bot, _materialIDs.TreasureBox, Collision_BotTreasureBox);

            #endregion

            List <KeepItems2D> keep2Ds = new List <KeepItems2D>();

            foreach (var(room, _) in Arena.AllRooms)
            {
                #region keep 2D

                //TODO: drag plane should either be a plane or a large cylinder, based on the current (level|scene|stage|area|arena|map|place|region|zone)

                // This game is 3D emulating 2D, so always have the mouse go to the XY plane
                DragHitShape dragPlane = new DragHitShape();
                dragPlane.SetShape_Plane(new Triangle(new Point3D(-1, -1, room.Center.Z), new Point3D(1, -1, room.Center.Z), new Point3D(0, 1, room.Center.Z)));

                // This will keep objects onto that plane using forces (not velocities)
                KeepItems2D keep2D = new KeepItems2D
                {
                    SnapShape = dragPlane,
                };

                //keep2D.Add(room.Bot, false);
                keep2Ds.Add(keep2D);

                #endregion

                #region bot

                ShipCoreArgs core = new ShipCoreArgs()
                {
                    World         = world,
                    Material_Ship = MaterialIDs.Bot,
                    Map           = room.Map,
                };

                //BotConstructor_Events events = new BotConstructor_Events();
                //events.

                // Create the bot
                Bot bot = null;
                if (RequestCustomBot != null)
                {
                    bot = RequestCustomBot(core, keep2D, dragPlane, MaterialIDs);
                }
                else
                {
                    BotConstruction_Result construction = BotConstructor.ConstructBot(DNA, core, ShipExtraArgs);
                    bot = new Bot(construction);
                }

                // Find some parts
                BrainNEAT brainPart = bot.Parts.FirstOrDefault(o => o is BrainNEAT) as BrainNEAT;
                if (brainPart == null)
                {
                    throw new ApplicationException("Didn't find BrainNEAT part");
                }

                SensorHoming[] homingParts = bot.Parts.
                                             Where(o => o is SensorHoming).
                                             Select(o => (SensorHoming)o).
                                             ToArray();

                if (homingParts.Length == 0)
                {
                    throw new ApplicationException("Didn't find SensorHoming part");
                }

                #endregion

                room.Bot         = bot;
                room.BrainPart   = brainPart;
                room.HomingParts = homingParts;

                foreach (SensorHoming homing in homingParts)
                {
                    homing.HomePoint  = room.Center;
                    homing.HomeRadius = (ROOMSIZE / 2d) * Evaluator3.MULT_HOMINGSIZE;
                }

                room.Map.AddItem(bot);

                keep2D.Add(room.Bot, false);
            }

            Keep2D = keep2Ds.ToArray();

            world.Updated += World_Updated;
        }
    public void UpdateConnectionVertexPositions(BrainNEAT brain) {
        //for (int c = 0; c < brain.connectionList.Count; c++) {

            //BuildLink(meshBuilder, nodePositionsList[brain.connectionList[c].fromNodeID] + offset, nodePositionsList[brain.connectionList[c].toNodeID] + offset, connectionWidth, GetColorFromValue(brain.connectionList[c].weight[0]));
            //Debug.Log("BuildNew BrainMesh: from: " + nodePositionsList[brain.connectionList[c].fromNodeID].ToString() + ", to: " + nodePositionsList[brain.connectionList[c].toNodeID].ToString());
        //}
        for (int i = 0; i < connectionVertexList.Count; i++) {
            // for all connections:
            
            Vector3 linkVector = new Vector3(nodePositionsList[brain.connectionList[i].toNodeID].x - nodePositionsList[brain.connectionList[i].fromNodeID].x, nodePositionsList[brain.connectionList[i].toNodeID].y - nodePositionsList[brain.connectionList[i].fromNodeID].y, nodePositionsList[brain.connectionList[i].toNodeID].z - nodePositionsList[brain.connectionList[i].fromNodeID].z);
            Vector3 widthVector = new Vector3(new Vector2(linkVector.y, -linkVector.x).normalized.x, new Vector2(linkVector.y, -linkVector.x).normalized.y, 0f) * (connectionWidthMin + Mathf.Abs(brain.connectionList[i].weight[0]) * connectionWidthMin * 0.62f);
            Vector3 cornerPos = new Vector3(nodePositionsList[brain.connectionList[i].fromNodeID].x - widthVector.x * 0.5f + neuronRadiusMin * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].y - widthVector.y * 0.5f + neuronRadiusMin * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].z);
            //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString());
            meshBuilder.Vertices[connectionVertexList[i][0]] = cornerPos;
            meshBuilder.Vertices[connectionVertexList[i][1]] = cornerPos + linkVector;
            meshBuilder.Vertices[connectionVertexList[i][2]] = cornerPos + linkVector + widthVector;
            meshBuilder.Vertices[connectionVertexList[i][3]] = cornerPos + widthVector;
        }
        meshBuilder.UpdateMeshVertices();
    }
示例#12
0
 public void BuildBrainMesh(BrainNEAT brain) {
     MiniGameManager currentGameManager = PlayerList[playingCurPlayer].masterTrialsList[playingCurTrialIndex].miniGameManager;
     if (brainNetworkGO == null) {
         brainNetworkGO = new GameObject("brainNetworkGO");
         brainNetworkGO.AddComponent<MeshFilter>();
         
         //Material brainNetworkMat = new Material(Shader.Find("Custom/SimpleBrainNetworkShader"));
         brainNetworkGO.AddComponent<MeshRenderer>().material = brainNetworkMat;
         
         networkVisualizer = brainNetworkGO.AddComponent<BrainNetworkVisualizer>();
         
         if (currentGameManager.miniGameInstance.critterBeingTested != null) {
             networkVisualizer.sourceCritter = currentGameManager.miniGameInstance.critterBeingTested;
         }
         
         //currentGameManager.miniGameInstance.critterBeingTested.critterSegmentMaterial.SetTexture("_NeuronPosTex", networkVisualizer.neuronPositionsTexture);
     }
     MiniGameCritterWalkBasic minigame = (MiniGameCritterWalkBasic)currentGameManager.miniGameInstance as MiniGameCritterWalkBasic;
     networkVisualizer.InitShaderTexture(brain);
     minigame.SetShaderTextures(networkVisualizer);
     brainNetworkGO.GetComponent<MeshFilter>().sharedMesh = networkVisualizer.BuildNewMesh(brain);
 }
 public void UpdateNodeVertexPositions(BrainNEAT brain) {
     for(int i = 0; i < nodeVertexList.Count; i++) {
         // for all neurons:
         //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString());
         //float size = neuronRadius + Mathf.Abs(brain.neuronList[i].previousValue) * neuronRadius * 0.12f;
         float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[i].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);
         meshBuilder.Vertices[nodeVertexList[i][0]] = nodePositionsList[i];
         meshBuilder.Vertices[nodeVertexList[i][1]] = nodePositionsList[i] + new Vector3(0f, size, 0f);
         meshBuilder.Vertices[nodeVertexList[i][2]] = nodePositionsList[i] + new Vector3(size, 0f, 0f) + new Vector3(0f, size, 0f);
         meshBuilder.Vertices[nodeVertexList[i][3]] = nodePositionsList[i] + new Vector3(size, 0f, 0f);
     }
     meshBuilder.UpdateMeshVertices();
 }
 private Color GetColorFromConnection(ConnectionNEAT connection, BrainNEAT brain) {
     //black = -1, white = 1
     //float val01 = connection.weight[0] * 0.5f + 0.5f;
     float val01 = brain.neuronList[connection.fromNodeID].currentValue[0] * connection.weight[0] * 0.2f + 0.5f;
     Color newColor = new Color(val01, val01, val01);
     newColor = Color.Lerp(newColor, new Color(0f, 0f, 1f), 0f);
     //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.In) {
     //    newColor = Color.Lerp(newColor, new Color(0f, 1f, 0f), 0.75f);
     //}
     //if (connection.nodeType == GeneNodeNEAT.GeneNodeType.Out) {
     //    newColor = Color.Lerp(newColor, new Color(1f, 0f, 0f), 0.75f);
     //}
     //Debug.Log(val01.ToString());
     return newColor;
 }
    public void MoveNeurons(BrainNEAT brain, int numIter) {

        // position HiddenNodes!!
        int numIterations = numIter;
        List<Vector3> newNodePositionsList = new List<Vector3>();
        for(int i = 0; i < nodePositionsList.Count; i++) {  // Initialize new positions list
            Vector3 newPositionVector = new Vector3();
            newPositionVector = nodePositionsList[i];
            newNodePositionsList.Add(newPositionVector);
        }
        
        //float attract = 0.007f;
        //float repel = 0.0025f;
        for (int phase = 0; phase < numIterations; phase++) {
            // Attract NEURONS:
            for (int c = 0; c < brain.connectionList.Count; c++) {
                // go trhough all connections and treat them as springs
                int fromNode = brain.connectionList[c].fromNodeID;
                int toNode = brain.connectionList[c].toNodeID;
                
                Vector3 linkVector = nodePositionsList[toNode] - nodePositionsList[fromNode];
                if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.In) {
                    //linkVector += new Vector2(0f, -attract * 2.7f);
                }
                else if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.Out) {
                    //linkVector += new Vector2(0f, attract * 2.7f);
                }
                float dist = Mathf.Max(linkVector.sqrMagnitude, 0.02f);
                newNodePositionsList[fromNode] += linkVector * attractByConnections * dist;  // move fromNode towards toNode proportionally based on its distance
                newNodePositionsList[toNode] -= linkVector * attractByConnections * dist;  // move fromNode towards toNode proportionally based on its distance  
                
            }
            // REPEL NEURONS:
            for (int j = 0; j < nodePositionsList.Count; j++) {  // for all nodes
                for (int k = 0; k < nodePositionsList.Count; k++) {   // go through all nodes
                    if (j != k) {  // if not comparing to itself
                        Vector3 vectorToNode = (nodePositionsList[k] - nodePositionsList[j]);
                        float dist = Mathf.Max(vectorToNode.magnitude, 0.01f);
                        // repel from each node:
                        if (dist < neuronRepelMaxDistance) {
                            newNodePositionsList[j] -= vectorToNode * neuronRepelForce / dist;
                            newNodePositionsList[k] += vectorToNode * neuronRepelForce / dist;
                        }                        
                    }
                }
                // For each node, if not hidden, move towards its worldPos:
                if (brain.neuronList[j].nodeType != GeneNodeNEAT.GeneNodeType.Hid) {
                    Vector3 vectorToSegmentPos = (brain.neuronList[j].worldPos - nodePositionsList[j]);
                    float dist = Mathf.Max(vectorToSegmentPos.sqrMagnitude, 0.01f);
                    newNodePositionsList[j] += vectorToSegmentPos * attractToCritterPos;
                    //Debug.Log("brain.neuronList[" + j.ToString() + "] worldPos: " + brain.neuronList[j].worldPos.ToString() + ", nodePos: " + nodePositionsList[j].ToString());
                }
                // build texture to pass to shader:
                Vector3 position = nodePositionsList[j];
                neuronPositionsTexture.SetPixel(j, 1, new Color(position.x, position.y, position.z, brain.neuronList[j].currentValue[0]));
            }

            // Apply new Neuron positions to master list:
            for (int p = 0; p < nodePositionsList.Count; p++) {  // Initialize new positions list
                //Vector3 newPositionVector = new Vector3();
                nodePositionsList[p] = newNodePositionsList[p];
            }

            // BEZIER CURVES:
            for (int c = 0; c < brain.connectionList.Count; c++) {
                bezierCurveList[c].points[0] = nodePositionsList[brain.connectionList[c].fromNodeID];
                //bezierCurveList[c].points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f);
                //bezierCurveList[c].points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f);
                bezierCurveList[c].points[3] = nodePositionsList[brain.connectionList[c].toNodeID];
                

                for (int b = 0; b < bezierCurveList.Count; b++) {
                    // Go through all other bezierCurves and repel from others  
                    if (b != c) {  // if not comparing to itself:
                        for (int control = 0; control < 4; control++) {  // go through each of the 4 points in the other bezierCurve connection:
                            Vector3 vectorToControlPoint1 = bezierCurveList[b].points[control] - bezierCurveList[c].points[1];
                            float distance = Mathf.Max(vectorToControlPoint1.sqrMagnitude, 0.02f);
                            // The middle control points in the current Beziercurve are repelled from ALL OTHER bezier curve control points!
                            if (distance < neuronRepelMaxDistance) {
                                bezierCurveList[c].points[1] -= vectorToControlPoint1 * bezierRepelForce * distance;
                                bezierCurveList[c].points[2] -= vectorToControlPoint1 * bezierRepelForce * distance;
                            }
                        }
                    }
                }
                // ATTRACT to rest position!
                Vector3 vectorControl1ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.333f) - bezierCurveList[c].points[1];
                float dist1 = Mathf.Max(vectorControl1ToRest.sqrMagnitude, 0.02f);
                Vector3 vectorControl2ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.667f) - bezierCurveList[c].points[2];
                float dist2 = Mathf.Max(vectorControl2ToRest.sqrMagnitude, 0.02f);
                bezierCurveList[c].points[1] += vectorControl1ToRest * attractToControlPoints * dist1;
                bezierCurveList[c].points[2] += vectorControl2ToRest * attractToControlPoints * dist2;
            }   
            

            neuronPositionsTexture.Apply();
        }
        //meshBuilder.UpdateMeshVertices();
    }  
示例#16
0
    public void MoveNeurons(BrainNEAT brain, int numIter)
    {
        // position HiddenNodes!!
        int            numIterations        = numIter;
        List <Vector3> newNodePositionsList = new List <Vector3>();

        for (int i = 0; i < nodePositionsList.Count; i++)    // Initialize new positions list
        {
            Vector3 newPositionVector = new Vector3();
            newPositionVector = nodePositionsList[i];
            newNodePositionsList.Add(newPositionVector);
        }

        //float attract = 0.007f;
        //float repel = 0.0025f;
        for (int phase = 0; phase < numIterations; phase++)
        {
            // Attract NEURONS:
            for (int c = 0; c < brain.connectionList.Count; c++)
            {
                // go trhough all connections and treat them as springs
                int fromNode = brain.connectionList[c].fromNodeID;
                int toNode   = brain.connectionList[c].toNodeID;

                Vector3 linkVector = nodePositionsList[toNode] - nodePositionsList[fromNode];
                if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.In)
                {
                    //linkVector += new Vector2(0f, -attract * 2.7f);
                }
                else if (brain.neuronList[fromNode].nodeType == GeneNodeNEAT.GeneNodeType.Out)
                {
                    //linkVector += new Vector2(0f, attract * 2.7f);
                }
                float dist = Mathf.Max(linkVector.sqrMagnitude, 0.02f);
                newNodePositionsList[fromNode] += linkVector * attractByConnections * dist; // move fromNode towards toNode proportionally based on its distance
                newNodePositionsList[toNode]   -= linkVector * attractByConnections * dist; // move fromNode towards toNode proportionally based on its distance
            }
            // REPEL NEURONS:
            for (int j = 0; j < nodePositionsList.Count; j++)     // for all nodes
            {
                for (int k = 0; k < nodePositionsList.Count; k++) // go through all nodes
                {
                    if (j != k)                                   // if not comparing to itself
                    {
                        Vector3 vectorToNode = (nodePositionsList[k] - nodePositionsList[j]);
                        float   dist         = Mathf.Max(vectorToNode.magnitude, 0.01f);
                        // repel from each node:
                        if (dist < neuronRepelMaxDistance)
                        {
                            newNodePositionsList[j] -= vectorToNode * neuronRepelForce / dist;
                            newNodePositionsList[k] += vectorToNode * neuronRepelForce / dist;
                        }
                    }
                }
                // For each node, if not hidden, move towards its worldPos:
                if (brain.neuronList[j].nodeType != GeneNodeNEAT.GeneNodeType.Hid)
                {
                    Vector3 vectorToSegmentPos = (brain.neuronList[j].worldPos - nodePositionsList[j]);
                    float   dist = Mathf.Max(vectorToSegmentPos.sqrMagnitude, 0.01f);
                    newNodePositionsList[j] += vectorToSegmentPos * attractToCritterPos;
                    //Debug.Log("brain.neuronList[" + j.ToString() + "] worldPos: " + brain.neuronList[j].worldPos.ToString() + ", nodePos: " + nodePositionsList[j].ToString());
                }
                // build texture to pass to shader:
                Vector3 position = nodePositionsList[j];
                neuronPositionsTexture.SetPixel(j, 1, new Color(position.x, position.y, position.z, brain.neuronList[j].currentValue[0]));
            }

            // Apply new Neuron positions to master list:
            for (int p = 0; p < nodePositionsList.Count; p++)    // Initialize new positions list
            //Vector3 newPositionVector = new Vector3();
            {
                nodePositionsList[p] = newNodePositionsList[p];
            }

            // BEZIER CURVES:
            for (int c = 0; c < brain.connectionList.Count; c++)
            {
                bezierCurveList[c].points[0] = nodePositionsList[brain.connectionList[c].fromNodeID];
                //bezierCurveList[c].points[1] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.333f);
                //bezierCurveList[c].points[2] = Vector3.Lerp(nodePositionsList[brain.connectionList[c].fromNodeID], nodePositionsList[brain.connectionList[c].toNodeID], 0.667f);
                bezierCurveList[c].points[3] = nodePositionsList[brain.connectionList[c].toNodeID];


                for (int b = 0; b < bezierCurveList.Count; b++)
                {
                    // Go through all other bezierCurves and repel from others
                    if (b != c)                                       // if not comparing to itself:
                    {
                        for (int control = 0; control < 4; control++) // go through each of the 4 points in the other bezierCurve connection:
                        {
                            Vector3 vectorToControlPoint1 = bezierCurveList[b].points[control] - bezierCurveList[c].points[1];
                            float   distance = Mathf.Max(vectorToControlPoint1.sqrMagnitude, 0.02f);
                            // The middle control points in the current Beziercurve are repelled from ALL OTHER bezier curve control points!
                            if (distance < neuronRepelMaxDistance)
                            {
                                bezierCurveList[c].points[1] -= vectorToControlPoint1 * bezierRepelForce * distance;
                                bezierCurveList[c].points[2] -= vectorToControlPoint1 * bezierRepelForce * distance;
                            }
                        }
                    }
                }
                // ATTRACT to rest position!
                Vector3 vectorControl1ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.333f) - bezierCurveList[c].points[1];
                float   dist1 = Mathf.Max(vectorControl1ToRest.sqrMagnitude, 0.02f);
                Vector3 vectorControl2ToRest = Vector3.Lerp(bezierCurveList[c].points[0], bezierCurveList[c].points[3], 0.667f) - bezierCurveList[c].points[2];
                float   dist2 = Mathf.Max(vectorControl2ToRest.sqrMagnitude, 0.02f);
                bezierCurveList[c].points[1] += vectorControl1ToRest * attractToControlPoints * dist1;
                bezierCurveList[c].points[2] += vectorControl2ToRest * attractToControlPoints * dist2;
            }


            neuronPositionsTexture.Apply();
        }
        //meshBuilder.UpdateMeshVertices();
    }
示例#17
0
    public void SetNeuronSegmentPositions(BrainNEAT brain)
    {
        int currentInputIndex  = 0;
        int currentOutputIndex = 0;

        // Check for ANGLE SENSORS:
        for (int i = 0; i < sourceCritter.segaddonJointAngleSensorList.Count; i++)
        {
            if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].GetComponent <CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY)
            {
                // Add an extra one if it's a dual Joint
                brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position;
                currentInputIndex++;
            }
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonContactSensorList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonContactSensorList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonRaycastSensorList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRaycastSensorList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonCompassSensor1DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonCompassSensor3DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonPositionSensor1DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonPositionSensor3DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonRotationSensor1DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonRotationSensor3DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonVelocitySensor1DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonVelocitySensor3DList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonAltimeterList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonAltimeterList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        // Outputs:
        for (int i = 0; i < sourceCritter.segaddonJointMotorList.Count; i++)
        {
            if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].GetComponent <CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY)
            {
                // Add an extra one if it's a dual Joint
                brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f;

                currentOutputIndex++;
            }
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonThrusterEffector1DList.Count; i++)
        {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector1DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonThrusterEffector3DList.Count; i++)
        {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector3DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonTorqueEffector1DList.Count; i++)
        {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector1DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonTorqueEffector3DList.Count; i++)
        {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector3DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }

        // More Inputs:
        for (int i = 0; i < sourceCritter.segaddonOscillatorInputList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonOscillatorInputList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonValueInputList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonValueInputList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonTimerInputList.Count; i++)
        {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTimerInputList[i].segmentID].transform.position;
            currentInputIndex++;
        }
    }
 public void UpdateVertexColors(BrainNEAT brain) {
     //Debug.Log("UpdateVertexColors(BrainNEAT brain) " + GetColorFromValue(brain.neuronList[0].currentValue[0]).ToString());
     for (int i = 0; i < brain.neuronList.Count; i++) {
         ChangeNodeColor(i, GetColorFromNeuron(brain.neuronList[i]));
     }
     for (int j = 0; j < brain.connectionList.Count; j++) {
         //ChangeConnectionColor(j, GetColorFromConnection(brain.connectionList[j], brain));
     }
     meshBuilder.UpdateMeshColors();
 }
示例#19
0
    public void UpdateNodeVertexPositionsSphere(BrainNEAT brain)
    {
        for (int n = 0; n < nodeVertexList.Count; n++)
        {
            // for all neurons:
            //float size = Mathf.Min((neuronRadius * brain.neuronList[n].currentValue[0] * 0.2f + 0.02f), 2.0f);
            float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[n].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);
            int   currentVertexIndex = 0;
            if (nodePositionsList == null)
            {
                //Debug.Log("if(nodePositionsList == null) {");
            }
            else
            {
                //Debug.Log("if(nodePositionsList != null) {" + nodePositionsList.Count.ToString() + ", n: " + n.ToString() + ", fromNode: " + brain.connectionList[n].fromNodeID.ToString());
            }
            Vector3    offset = nodePositionsList[n] - new Vector3(0f, size, 0f);
            int        m_HeightSegmentCount = 4;
            int        m_RadialSegmentCount = 4;
            float      m_VerticalScale      = 1f;
            Quaternion rotation             = Quaternion.identity;
            //the angle increment per height segment:
            float angleInc = Mathf.PI / m_HeightSegmentCount;
            //the vertical (scaled) radius of the sphere:
            float verticalRadius = size * m_VerticalScale;
            //build the rings:
            for (int i = 0; i <= m_HeightSegmentCount; i++)
            {
                Vector3 centrePos = Vector3.zero;
                //calculate a height offset and radius based on a vertical circle calculation:
                centrePos.y = -Mathf.Cos(angleInc * i);
                float radius = Mathf.Sin(angleInc * i);
                //calculate the slope of the shpere at this ring based on the height and radius:
                Vector2 slope = new Vector3(-centrePos.y / m_VerticalScale, radius);
                slope.Normalize();
                //multiply the unit height by the vertical radius, and then add the radius to the height to make this sphere originate from its base rather than its centre:
                centrePos.y = centrePos.y * verticalRadius + verticalRadius;
                //scale the radius by the one stored in the partData:
                radius *= size;
                //calculate the final position of the ring centre:
                Vector3 finalRingCentre = rotation * centrePos + offset;
                //V coordinate:
                float v = (float)i / m_HeightSegmentCount;
                //build the ring:
                //BuildRing(meshBuilder, m_RadialSegmentCount, finalRingCentre, radius, v, i > 0, rotation, slope);
                float angleIncrement = (Mathf.PI * 2.0f) / m_RadialSegmentCount;

                for (int j = 0; j <= m_RadialSegmentCount; j++)
                {
                    float   angle        = angleIncrement * j;
                    Vector3 unitPosition = Vector3.zero;
                    unitPosition.x = Mathf.Cos(angle);
                    unitPosition.z = Mathf.Sin(angle);
                    float   normalVertical   = -slope.x;
                    float   normalHorizontal = slope.y;
                    Vector3 normal           = unitPosition * normalHorizontal;
                    normal.y     = normalVertical;
                    normal       = rotation * normal;
                    unitPosition = rotation * unitPosition;

                    meshBuilder.Vertices[nodeVertexList[n][currentVertexIndex]] = finalRingCentre + unitPosition * radius;
                    currentVertexIndex++;
                }
            }
        }
        meshBuilder.UpdateMeshVertices();
    }
    public void SetNeuronSegmentPositions(BrainNEAT brain) {
        
        int currentInputIndex = 0;
        int currentOutputIndex = 0;
        // Check for ANGLE SENSORS:
        for(int i = 0; i < sourceCritter.segaddonJointAngleSensorList.Count; i++) {            
            if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].GetComponent<CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY) {
                // Add an extra one if it's a dual Joint
                brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position;
                currentInputIndex++;
            }
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointAngleSensorList[i].segmentID].transform.position;
            currentInputIndex++;            
        }
        for(int i = 0; i < sourceCritter.segaddonContactSensorList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonContactSensorList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonRaycastSensorList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRaycastSensorList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonCompassSensor1DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonCompassSensor3DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonCompassSensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonPositionSensor1DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonPositionSensor3DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonPositionSensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonRotationSensor1DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonRotationSensor3DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonRotationSensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonVelocitySensor1DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor1DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonVelocitySensor3DList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonVelocitySensor3DList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonAltimeterList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonAltimeterList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        // Outputs:
        for (int i = 0; i < sourceCritter.segaddonJointMotorList.Count; i++) {
            if (sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].GetComponent<CritterSegment>().sourceNode.jointLink.jointType == CritterJointLink.JointType.DualXY) {
                // Add an extra one if it's a dual Joint
                brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f;

                currentOutputIndex++;
            }
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.position - sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.forward * sourceCritter.critterSegmentList[sourceCritter.segaddonJointMotorList[i].segmentID].transform.localScale.z * 0.5f;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonThrusterEffector1DList.Count; i++) {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector1DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonThrusterEffector3DList.Count; i++) {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonThrusterEffector3DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonTorqueEffector1DList.Count; i++) {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector1DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonTorqueEffector3DList.Count; i++) {
            brain.outputNeuronList[currentOutputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTorqueEffector3DList[i].segmentID].transform.position;
            currentOutputIndex++;
        }

        // More Inputs:
        for (int i = 0; i < sourceCritter.segaddonOscillatorInputList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonOscillatorInputList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonValueInputList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonValueInputList[i].segmentID].transform.position;
            currentInputIndex++;
        }
        for (int i = 0; i < sourceCritter.segaddonTimerInputList.Count; i++) {
            brain.inputNeuronList[currentInputIndex].worldPos = sourceCritter.critterSegmentList[sourceCritter.segaddonTimerInputList[i].segmentID].transform.position;
            currentInputIndex++;
        }        
    }
示例#21
0
    public void UpdateConnectionVertexPositionsBezier(BrainNEAT brain)
    {
        for (int c = 0; c < connectionVertexList.Count; c++)
        {
            // for all connections:

            /*Vector3 linkVector = new Vector3(nodePositionsList[brain.connectionList[i].toNodeID].x - nodePositionsList[brain.connectionList[i].fromNodeID].x, nodePositionsList[brain.connectionList[i].toNodeID].y - nodePositionsList[brain.connectionList[i].fromNodeID].y, nodePositionsList[brain.connectionList[i].toNodeID].z - nodePositionsList[brain.connectionList[i].fromNodeID].z);
             * Vector3 widthVector = new Vector3(new Vector2(linkVector.y, -linkVector.x).normalized.x, new Vector2(linkVector.y, -linkVector.x).normalized.y, 0f) * (connectionWidth + Mathf.Abs(brain.connectionList[i].weight[0]) * connectionWidth * 0.62f);
             * Vector3 cornerPos = new Vector3(nodePositionsList[brain.connectionList[i].fromNodeID].x - widthVector.x * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].y - widthVector.y * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].z);
             * //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString());
             * meshBuilder.Vertices[connectionVertexList[i][0]] = cornerPos;
             * meshBuilder.Vertices[connectionVertexList[i][1]] = cornerPos + linkVector;
             * meshBuilder.Vertices[connectionVertexList[i][2]] = cornerPos + linkVector + widthVector;
             * meshBuilder.Vertices[connectionVertexList[i][3]] = cornerPos + widthVector;
             */
            int currentVertexIndex = 0;
            //float width = connectionWidth; // brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0];
            Color colorStart                 = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]);
            Color colorEnd                   = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID]);
            float startWidth                 = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin);
            float endWidth                   = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin);
            float m_splineStartRadius        = startWidth;
            float m_splineEndRadius          = endWidth;
            int   m_splineHeightSegmentCount = 8;
            int   m_splineRadialSegmentCount = 4;

            float tInc = 1f / m_splineHeightSegmentCount; // How many subdivisions along the length of the spline

            for (int i = 0; i <= m_splineHeightSegmentCount; i++)
            {
                float   t          = tInc * (float)i;
                Vector3 ringCenter = bezierCurveList[c].GetPoint(t);

                Vector3    dir = bezierCurveList[c].GetDirection(t);
                Quaternion rot = Quaternion.identity;
                if (dir != Vector3.zero)
                {
                    rot.SetLookRotation(dir);
                }
                float radius = ((1f - t) * m_splineStartRadius) + (t * m_splineEndRadius);
                // Construct the mesh Ring!
                //BuildBezierCurveRing(meshBuilder, m_splineRadialSegmentCount, ringCenter, radius, t, i > 0, rot);
                //protected void BuildBezierCurveRing(MeshBuilder meshBuilder, int segmentCount, Vector3 center, float radius, float v, bool buildTriangles, Quaternion rotation) {
                float angleInc = (Mathf.PI * 2.0f) / m_splineRadialSegmentCount;

                for (int j = 0; j <= m_splineRadialSegmentCount; j++)
                {
                    float angle = angleInc * j;

                    Vector3 unitPosition = Vector3.zero;
                    unitPosition.x = Mathf.Cos(angle);
                    unitPosition.y = Mathf.Sin(angle);

                    unitPosition = rot * unitPosition;
                    Vector3 normal = unitPosition;

                    //meshBuilder.Vertices[] = ringCenter + unitPosition * radius;
                    meshBuilder.Vertices[connectionVertexList[c][currentVertexIndex]] = ringCenter + unitPosition * radius;
                    meshBuilder.Colors[connectionVertexList[c][currentVertexIndex]]   = Color.Lerp(colorStart, colorEnd, t);
                    currentVertexIndex++;
                    //meshBuilder.Vertices.Add(ringCenter + unitPosition * radius);
                    //meshBuilder.Normals.Add(normal);
                    //meshBuilder.UVs.Add(new Vector2((float)i / segmentCount, v));
                    //meshBuilder.UVs.Add(new Vector2((float)j / m_splineRadialSegmentCount, t));
                    //verticesList.Add(meshBuilder.Vertices.Count - 1);
                    //meshBuilder.Colors.Add(color);

                    /*if (j > 0 && i > 0) {
                     *  //Debug.Log ("buildTriangles!");
                     *  int baseIndex = meshBuilder.Vertices.Count - 1;
                     *
                     *  int vertsPerRow = m_splineRadialSegmentCount + 1;
                     *
                     *  int index0 = baseIndex;
                     *  int index1 = baseIndex - 1;
                     *  int index2 = baseIndex - vertsPerRow;
                     *  int index3 = baseIndex - vertsPerRow - 1;
                     *
                     *  meshBuilder.AddTriangle(index1, index2, index0);
                     *  meshBuilder.AddTriangle(index1, index3, index2);
                     * }*/
                }
            }
        }

        meshBuilder.UpdateMeshVertices();
    }
    public void UpdateNodeVertexPositionsSphere(BrainNEAT brain) {
        for (int n = 0; n < nodeVertexList.Count; n++) {
            // for all neurons:
            //float size = Mathf.Min((neuronRadius * brain.neuronList[n].currentValue[0] * 0.2f + 0.02f), 2.0f);
            float size = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[n].currentValue[0])) * neuronRadiusMaxValue, neuronRadiusMax), neuronRadiusMin);
            int currentVertexIndex = 0;
            if(nodePositionsList == null) {
                //Debug.Log("if(nodePositionsList == null) {");
            }
            else {
                //Debug.Log("if(nodePositionsList != null) {" + nodePositionsList.Count.ToString() + ", n: " + n.ToString() + ", fromNode: " + brain.connectionList[n].fromNodeID.ToString());
            }
            Vector3 offset = nodePositionsList[n] - new Vector3(0f, size, 0f);
            int m_HeightSegmentCount = 4;
            int m_RadialSegmentCount = 4;
            float m_VerticalScale = 1f;
            Quaternion rotation = Quaternion.identity;
            //the angle increment per height segment:
            float angleInc = Mathf.PI / m_HeightSegmentCount;
            //the vertical (scaled) radius of the sphere:
            float verticalRadius = size * m_VerticalScale;
            //build the rings:
            for (int i = 0; i <= m_HeightSegmentCount; i++) {
                Vector3 centrePos = Vector3.zero;
                //calculate a height offset and radius based on a vertical circle calculation:
                centrePos.y = -Mathf.Cos(angleInc * i);
                float radius = Mathf.Sin(angleInc * i);
                //calculate the slope of the shpere at this ring based on the height and radius:
                Vector2 slope = new Vector3(-centrePos.y / m_VerticalScale, radius);
                slope.Normalize();
                //multiply the unit height by the vertical radius, and then add the radius to the height to make this sphere originate from its base rather than its centre:
                centrePos.y = centrePos.y * verticalRadius + verticalRadius;
                //scale the radius by the one stored in the partData:
                radius *= size;
                //calculate the final position of the ring centre:
                Vector3 finalRingCentre = rotation * centrePos + offset;
                //V coordinate:
                float v = (float)i / m_HeightSegmentCount;
                //build the ring:
                //BuildRing(meshBuilder, m_RadialSegmentCount, finalRingCentre, radius, v, i > 0, rotation, slope);
                float angleIncrement = (Mathf.PI * 2.0f) / m_RadialSegmentCount;

                for (int j = 0; j <= m_RadialSegmentCount; j++) {
                    float angle = angleIncrement * j;
                    Vector3 unitPosition = Vector3.zero;
                    unitPosition.x = Mathf.Cos(angle);
                    unitPosition.z = Mathf.Sin(angle);
                    float normalVertical = -slope.x;
                    float normalHorizontal = slope.y;
                    Vector3 normal = unitPosition * normalHorizontal;
                    normal.y = normalVertical;
                    normal = rotation * normal;
                    unitPosition = rotation * unitPosition;

                    meshBuilder.Vertices[nodeVertexList[n][currentVertexIndex]] = finalRingCentre + unitPosition * radius;
                    currentVertexIndex++;
                }
            }

        }
        meshBuilder.UpdateMeshVertices();
    }
    public Population BreedPopulation(ref Population sourcePopulation, int currentGeneration) {

        #region Pre-Crossover, Figuring out how many agents to breed etc.
        int LifetimeGeneration = currentGeneration + sourcePopulation.trainingGenerations;
        int totalNumWeightMutations = 0;
        //float totalWeightChangeValue = 0f;
        // go through species list and adjust fitness
        List<SpeciesBreedingPool> childSpeciesPoolsList = new List<SpeciesBreedingPool>(); // will hold agents in an internal list to facilitate crossover
        
        for (int s = 0; s < sourcePopulation.speciesBreedingPoolList.Count; s++) {            
            SpeciesBreedingPool newChildSpeciesPool = new SpeciesBreedingPool(sourcePopulation.speciesBreedingPoolList[s].templateGenome, sourcePopulation.speciesBreedingPoolList[s].speciesID);  // create Breeding Pools
            // copies the existing breeding pools but leaves their agentLists empty for future children
            childSpeciesPoolsList.Add(newChildSpeciesPool);            // Add to list of pools          
        }

        sourcePopulation.RankAgentArray(); // based on modified species fitness score, so compensated for species sizes
        
        Agent[] newAgentArray = new Agent[sourcePopulation.masterAgentArray.Length];

        // Calculate total fitness score:
        float totalScore = 0f;
        if (survivalByRaffle) {
            for (int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents
                totalScore += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies;
            }
        }

        // Figure out How many Agents survive
        int numSurvivors = Mathf.RoundToInt(survivalRate * (float)sourcePopulation.populationMaxSize);
        //Depending on method, one at a time, select an Agent to survive until the max Number is reached
        int newChildIndex = 0;
        // For ( num Agents ) {
        for (int i = 0; i < numSurvivors; i++) {
            // If survival is by fitness score ranking:
            if (survivalByRank) {
                // Pop should already be ranked, so just traverse from top (best) to bottom (worst)
                newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[newChildIndex];
                SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID);
                survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]);
                //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species'
                newChildIndex++;
            }
            // if survival is completely random, as a control:
            if (survivalStochastic) {
                int randomAgent = UnityEngine.Random.Range(0, numSurvivors - 1);
                // Set next newChild slot to a randomly-chosen agent within the survivor faction -- change to full random?
                newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[randomAgent];
                SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID);
                survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]);
                //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species'
                newChildIndex++;
            }
            // if survival is based on a fitness lottery:
            if (survivalByRaffle) {  // Try when Fitness is normalized from 0-1
                float randomSlicePosition = UnityEngine.Random.Range(0f, totalScore);
                float accumulatedFitness = 0f;
                for (int a = 0; a < sourcePopulation.populationMaxSize; a++) { // iterate through all agents
                    accumulatedFitness += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies;
                    // if accum fitness is on slicePosition, copy this Agent
                    //Debug.Log("NumSurvivors: " + numSurvivors.ToString() + ", Surviving Agent " + a.ToString() + ": AccumFitness: " + accumulatedFitness.ToString() + ", RafflePos: " + randomSlicePosition.ToString() + ", TotalScore: " + totalScore.ToString() + ", newChildIndex: " + newChildIndex.ToString());
                    if (accumulatedFitness >= randomSlicePosition) {
                        newAgentArray[newChildIndex] = sourcePopulation.masterAgentArray[a]; // add to next gen's list of agents
                        SpeciesBreedingPool survivingAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, newAgentArray[newChildIndex].speciesID);
                        survivingAgentBreedingPool.AddNewAgent(newAgentArray[newChildIndex]);
                        //SortNewAgentIntoSpecies(newAgentArray[newChildIndex], childSpeciesList); // sorts this surviving agent into next generation's species'
                        newChildIndex++;
                        break;
                    }
                }
            }
        }

        // Figure out how many new agents must be created to fill up the new population:
        int numNewChildAgents = sourcePopulation.populationMaxSize - numSurvivors;
        int numEligibleBreederAgents = Mathf.RoundToInt(breedingRate * (float)sourcePopulation.populationMaxSize);
        int currentRankIndex = 0;

        // Once the agents are ranked, trim the BreedingPools of agents that didn't make the cut for mating:
        if(useSpeciation) {
            for (int s = 0; s < sourcePopulation.speciesBreedingPoolList.Count; s++) {
                int index = 0;
                int failsafe = 0;
                int numAgents = sourcePopulation.speciesBreedingPoolList[s].agentList.Count;
                while (index < numAgents) {
                    if (index < sourcePopulation.speciesBreedingPoolList[s].agentList.Count) {
                        if (sourcePopulation.speciesBreedingPoolList[s].agentList[index].fitnessRank >= numEligibleBreederAgents) {
                            sourcePopulation.speciesBreedingPoolList[s].agentList.RemoveAt(index);
                        }
                        else {
                            index++;
                        }
                    }
                    else {
                        break;
                    }
                    failsafe++;
                    if (failsafe > 500) {
                        Debug.Log("INFINITE LOOP! hit failsafe 500 iters -- Trimming BreedingPools!");
                        break;
                    }
                }
                //Debug.Log("BreedPopulation -- TRIMSpeciesPool# " + s.ToString() + ", id: " + sourcePopulation.speciesBreedingPoolList[s].speciesID.ToString() + ", Count: " + sourcePopulation.speciesBreedingPoolList[s].agentList.Count.ToString());
                //
            }
        }        

        float totalScoreBreeders = 0f;
        if (breedingByRaffle) {  // calculate total fitness scores to determine lottery weights
            for (int a = 0; a < numEligibleBreederAgents; a++) { // iterate through all agents
                totalScoreBreeders += sourcePopulation.masterAgentArray[a].fitnessScoreSpecies;
            }
        }
        #endregion

        // Iterate over numAgentsToCreate :
        int newChildrenCreated = 0;
        while (newChildrenCreated < numNewChildAgents) {
            //		Find how many parents random number btw min/max:
            int numParentAgents = 2; // UnityEngine.Random.Range(minNumParents, maxNumParents);
            int numChildAgents = 1; // defaults to one child, but:
            if (numNewChildAgents - newChildrenCreated >= 2) {  // room for two more!
                numChildAgents = 2;                
            }

            Agent[] parentAgentsArray = new Agent[numParentAgents]; // assume 2 for now? yes, so far....
            
            List<GeneNodeNEAT>[] parentNodeListArray = new List<GeneNodeNEAT>[numParentAgents];
            List<GeneLinkNEAT>[] parentLinkListArray = new List<GeneLinkNEAT>[numParentAgents];

            Agent firstParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex);
            parentAgentsArray[0] = firstParentAgent;
            List<GeneNodeNEAT> firstParentNodeList = firstParentAgent.brainGenome.nodeNEATList;
            List<GeneLinkNEAT> firstParentLinkList = firstParentAgent.brainGenome.linkNEATList;
            //List<GeneNodeNEAT> firstParentNodeList = new List<GeneNodeNEAT>();
            //List<GeneLinkNEAT> firstParentLinkList = new List<GeneLinkNEAT>();
            //firstParentNodeList = firstParentAgent.brainGenome.nodeNEATList;
            //firstParentLinkList = firstParentAgent.brainGenome.linkNEATList;
            parentNodeListArray[0] = firstParentNodeList;
            parentLinkListArray[0] = firstParentLinkList;

            Agent secondParentAgent;
            SpeciesBreedingPool parentAgentBreedingPool = sourcePopulation.GetBreedingPoolByID(sourcePopulation.speciesBreedingPoolList, firstParentAgent.speciesID);
            if (useSpeciation) {
                //parentAgentBreedingPool
                float randBreedOutsideSpecies = UnityEngine.Random.Range(0f, 1f);
                if (randBreedOutsideSpecies < interspeciesBreedingRate) { // Attempts to Found a new species
                                                                          // allowed to breed outside its own species:
                    secondParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex);
                }
                else {
                    // Selects mate only from within its own species:
                    secondParentAgent = SelectAgentFromPoolForBreeding(parentAgentBreedingPool);
                }
            }
            else {
                secondParentAgent = SelectAgentFromPopForBreeding(sourcePopulation, numEligibleBreederAgents, ref currentRankIndex);
            }           
            
            parentAgentsArray[1] = secondParentAgent;
            List<GeneNodeNEAT> secondParentNodeList = secondParentAgent.brainGenome.nodeNEATList;
            List<GeneLinkNEAT> secondParentLinkList = secondParentAgent.brainGenome.linkNEATList;
            //List<GeneNodeNEAT> secondParentNodeList = new List<GeneNodeNEAT>();
            //List<GeneLinkNEAT> secondParentLinkList = new List<GeneLinkNEAT>();
            //secondParentNodeList = secondParentAgent.brainGenome.nodeNEATList;
            //secondParentLinkList = secondParentAgent.brainGenome.linkNEATList;
            parentNodeListArray[1] = secondParentNodeList;
            parentLinkListArray[1] = secondParentLinkList;
           
            //		Iterate over ChildArray.Length :  // how many newAgents created
            for (int c = 0; c < numChildAgents; c++) { // for number of child Agents in floatArray[][]:
                Agent newChildAgent = new Agent();
                
                List<GeneNodeNEAT> childNodeList = new List<GeneNodeNEAT>();
                List<GeneLinkNEAT> childLinkList = new List<GeneLinkNEAT>();
                
                GenomeNEAT childBrainGenome = new GenomeNEAT();
                childBrainGenome.nodeNEATList = childNodeList;
                childBrainGenome.linkNEATList = childLinkList;

                int numEnabledLinkGenes = 0;

                if (useCrossover) {                    
                    int nextLinkInnoA = 0;
                    int nextLinkInnoB = 0;
                    //int nextBodyNodeInno = 0;
                    //int nextBodyAddonInno = 0;

                    int failsafeMax = 500;
                    int failsafe = 0;
                    int parentListIndexA = 0;
                    int parentListIndexB = 0;
                    //int parentBodyNodeIndex = 0;
                    bool parentDoneA = false;
                    bool parentDoneB = false;
                    bool endReached = false;

                    int moreFitParent = 0;  // which parent is more Fit
                    if (parentAgentsArray[0].fitnessScoreSpecies < parentAgentsArray[1].fitnessScoreSpecies) {
                        moreFitParent = 1;
                    }
                    else if (parentAgentsArray[0].fitnessScoreSpecies == parentAgentsArray[1].fitnessScoreSpecies) {
                        moreFitParent = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 1f));
                    }

                    //  MATCH UP Links between both agents, if they have a gene with matching Inno#, then mixing can occur                    
                    while (!endReached) {
                        failsafe++;
                        if(failsafe > failsafeMax) {
                            Debug.Log("failsafe reached!");
                            break;
                        }
                        // inno# of next links:
                        if(parentLinkListArray[0].Count > parentListIndexA) {
                            nextLinkInnoA = parentLinkListArray[0][parentListIndexA].innov;
                        }
                        else {
                            parentDoneA = true;
                        }
                        if (parentLinkListArray[1].Count > parentListIndexB) {
                            nextLinkInnoB = parentLinkListArray[1][parentListIndexB].innov;
                        }
                        else {
                            parentDoneB = true;
                        }

                        int innoDelta = nextLinkInnoA - nextLinkInnoB;  // 0=match, neg= Aextra, pos= Bextra
                        if (parentDoneA && !parentDoneB) {
                            innoDelta = 1;
                        }
                        if (parentDoneB && !parentDoneA) {
                            innoDelta = -1;
                        }
                        if (parentDoneA && parentDoneB) {  // reached end of both parent's linkLists
                            endReached = true;
                            break;
                        }

                        if (innoDelta < 0) {  // Parent A has an earlier link mutation
                            //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta < 0 (" + innoDelta.ToString() + ") --  moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString());
                            if (moreFitParent == 0) {  // Parent A is more fit:
                                GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, parentLinkListArray[0][parentListIndexA].weight, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen);
                                childLinkList.Add(newChildLink);
                                if (parentLinkListArray[0][parentListIndexA].enabled)
                                    numEnabledLinkGenes++;
                            }
                            else {
                                if(CheckForMutation(crossoverRandomLinkChance)) {  // was less fit parent, but still passed on a gene!:
                                    GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, parentLinkListArray[0][parentListIndexA].weight, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen);
                                    childLinkList.Add(newChildLink);
                                }
                            }
                            parentListIndexA++;
                        }
                        if (innoDelta > 0) {  // Parent B has an earlier link mutation
                            //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta > 0 (" + innoDelta.ToString() + ") --  moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString());
                            if (moreFitParent == 1) {  // Parent B is more fit:
                                GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[1][parentListIndexB].fromNodeID, parentLinkListArray[1][parentListIndexB].toNodeID, parentLinkListArray[1][parentListIndexB].weight, parentLinkListArray[1][parentListIndexB].enabled, parentLinkListArray[1][parentListIndexB].innov, parentLinkListArray[1][parentListIndexB].birthGen);
                                childLinkList.Add(newChildLink);
                                if (parentLinkListArray[1][parentListIndexB].enabled)
                                    numEnabledLinkGenes++;
                            }
                            else {
                                if (CheckForMutation(crossoverRandomLinkChance)) {  // was less fit parent, but still passed on a gene!:
                                    GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[1][parentListIndexB].fromNodeID, parentLinkListArray[1][parentListIndexB].toNodeID, parentLinkListArray[1][parentListIndexB].weight, parentLinkListArray[1][parentListIndexB].enabled, parentLinkListArray[1][parentListIndexB].innov, parentLinkListArray[1][parentListIndexB].birthGen);
                                    childLinkList.Add(newChildLink);
                                }
                            }
                            parentListIndexB++;
                        }
                        if (innoDelta == 0) {  // Match!
                            float randParentIndex = UnityEngine.Random.Range(0f, 1f);
                            float newWeightValue;
                            if (randParentIndex < 0.5) {
                                // ParentA wins:
                                newWeightValue = parentLinkListArray[0][parentListIndexA].weight;
                            }
                            else {  // ParentB wins:
                                newWeightValue = parentLinkListArray[1][parentListIndexB].weight;
                            }
                            //Debug.Log("newChildIndex: " + newChildIndex.ToString() + ", IndexA: " + parentListIndexA.ToString() + ", IndexB: " + parentListIndexB.ToString() + ", innoDelta == 0 (" + innoDelta.ToString() + ") --  moreFitP: " + moreFitParent.ToString() + ", nextLinkInnoA: " + nextLinkInnoA.ToString() + ", nextLinkInnoB: " + nextLinkInnoB.ToString() + ", randParent: " + randParentIndex.ToString() + ", weight: " + newWeightValue.ToString());
                            GeneLinkNEAT newChildLink = new GeneLinkNEAT(parentLinkListArray[0][parentListIndexA].fromNodeID, parentLinkListArray[0][parentListIndexA].toNodeID, newWeightValue, parentLinkListArray[0][parentListIndexA].enabled, parentLinkListArray[0][parentListIndexA].innov, parentLinkListArray[0][parentListIndexA].birthGen);
                            childLinkList.Add(newChildLink);
                            if (parentLinkListArray[0][parentListIndexA].enabled)
                                numEnabledLinkGenes++;

                            parentListIndexA++;
                            parentListIndexB++;
                        }

                    }
                    // once childLinkList is built -- use nodes of the moreFit parent:
                    for (int i = 0; i < parentNodeListArray[moreFitParent].Count; i++) { 
                        // iterate through all nodes in the parent List and copy them into fresh new geneNodes:
                        GeneNodeNEAT clonedNode = new GeneNodeNEAT(parentNodeListArray[moreFitParent][i].id, parentNodeListArray[moreFitParent][i].nodeType, parentNodeListArray[moreFitParent][i].activationFunction, parentNodeListArray[moreFitParent][i].sourceAddonInno, parentNodeListArray[moreFitParent][i].sourceAddonRecursionNum, false, parentNodeListArray[moreFitParent][i].sourceAddonChannelNum);
                        childNodeList.Add(clonedNode);
                    }

                    if (useMutation) {
                        // BODY MUTATION:
                        //PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);
                        // NEED TO ADJUST BRAINS IF MUTATION CHANGES #NODES!!!!

                        // BRAIN MUTATION:
                        if (numEnabledLinkGenes < 1)
                            numEnabledLinkGenes = 1;
                        for (int k = 0; k < childLinkList.Count; k++) {
                            float mutateChance = mutationBlastModifier * masterMutationRate / (1f + (float)numEnabledLinkGenes * 0.15f);
                            if (LifetimeGeneration - childLinkList[k].birthGen < newLinkBonusDuration) {
                                float t = 1 - ((LifetimeGeneration - childLinkList[k].birthGen) / (float)newLinkBonusDuration);
                                // t=0 means age of gene is same as bonusDuration, t=1 means it is brand new
                                mutateChance = Mathf.Lerp(mutateChance, mutateChance * newLinkMutateBonus, t);
                            }
                            if (CheckForMutation(mutateChance)) {  // Weight Mutation!
                                //Debug.Log("Weight Mutation Link[" + k.ToString() + "] weight: " + childLinkList[k].weight.ToString() + ", mutate: " + MutateFloat(childLinkList[k].weight).ToString());
                                childLinkList[k].weight = MutateFloat(childLinkList[k].weight);
                                totalNumWeightMutations++;
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationRemoveLinkChance)) {
                            //Debug.Log("Remove Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.RemoveRandomLink();
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddNodeChance)) {   // Adds a new node
                            //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.AddNewRandomNode(LifetimeGeneration, GetNextAddonInnov());
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationRemoveNodeChance)) {   // Adds a new node
                            //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.RemoveRandomNode();
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddLinkChance)) { // Adds new connection
                            //Debug.Log("Add Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            if (CheckForMutation(existingNetworkBias)) {
                                childBrainGenome.AddNewExtraLink(existingFromNodeBias, LifetimeGeneration);
                            }
                            else {
                                childBrainGenome.AddNewRandomLink(LifetimeGeneration);
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationActivationFunctionChance)) {
                            TransferFunctions.TransferFunction newFunction;
                            int randIndex = Mathf.RoundToInt(UnityEngine.Random.Range(0f, childNodeList.Count - 1));
                            int randomTF = (int)UnityEngine.Random.Range(0f, 12f);

                            switch (randomTF) {
                                case 0:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 1:
                                    newFunction = TransferFunctions.TransferFunction.Linear;
                                    break;
                                case 2:
                                    newFunction = TransferFunctions.TransferFunction.Gaussian;
                                    break;
                                case 3:
                                    newFunction = TransferFunctions.TransferFunction.Abs;
                                    break;
                                case 4:
                                    newFunction = TransferFunctions.TransferFunction.Cos;
                                    break;
                                case 5:
                                    newFunction = TransferFunctions.TransferFunction.Sin;
                                    break;
                                case 6:
                                    newFunction = TransferFunctions.TransferFunction.Tan;
                                    break;
                                case 7:
                                    newFunction = TransferFunctions.TransferFunction.Square;
                                    break;
                                case 8:
                                    newFunction = TransferFunctions.TransferFunction.Threshold01;
                                    break;
                                case 9:
                                    newFunction = TransferFunctions.TransferFunction.ThresholdNegPos;
                                    break;
                                case 10:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 11:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 12:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                default:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                            }
                            if (childNodeList[randIndex].nodeType != GeneNodeNEAT.GeneNodeType.Out) {  // keep outputs -1 to 1 range
                                Debug.Log("ActivationFunction Mutation Node[" + randIndex.ToString() + "] prev: " + childNodeList[randIndex].activationFunction.ToString() + ", new: " + newFunction.ToString());
                                childNodeList[randIndex].activationFunction = newFunction;
                            }
                        }
                    }
                    else {
                        Debug.Log("Mutation Disabled!");
                    }

                    // THE BODY   ==========!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!======================================================================================
                    CritterGenome childBodyGenome = new CritterGenome();  // create new body genome for Child
                    // This creates the ROOT NODE!!!!
                    // Clone Nodes & Addons from more fit parent to create new child body genome
                    // crossover is on, so check for matching Nodes and Add-ons (based on Inno#'s) to determine when to mix Settings/Attributes:                    
                    // Iterate over the nodes of the more fit parent:
                    for (int i = 0; i < parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList.Count; i++) {
                        int currentNodeInno = parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[i].innov;
                        if (i == 0) {  // if this is the ROOT NODE:
                            childBodyGenome.CritterNodeList[0].CopySettingsFromNode(parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[0]);
                            // The root node was already created during the Constructor method of the CritterGenome,
                            // ... so instead of creating a new one, just copy the settings
                        }
                        else {  // NOT the root node, proceed normally:
                                // Create new cloned node defaulted to the settings of the source( more-fit parent's) Node:
                            CritterNode clonedCritterNode = parentAgentsArray[moreFitParent].bodyGenome.CritterNodeList[i].CloneThisCritterNode();
                            
                            // Check other parent for same node:
                            for (int j = 0; j < parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList.Count; j++) {
                                if (parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList[j].innov == currentNodeInno) {
                                    // CROSSOVER NODE SETTINGS HERE!!!  ---- If random dice roll > 0.5, use less fit parent's settings, otherwise leave as default
                                    BodyCrossover(ref clonedCritterNode, parentAgentsArray[1 - moreFitParent].bodyGenome.CritterNodeList[j]);                                    
                                }
                            }
                            childBodyGenome.CritterNodeList.Add(clonedCritterNode);
                        }                        
                    }
                    // ADD-ONS!!!!!!!!!!!!!!!!!!!!!!
                    BreedCritterAddons(ref childBodyGenome, ref parentAgentsArray[moreFitParent].bodyGenome, ref parentAgentsArray[1 - moreFitParent].bodyGenome);
                    newChildAgent.bodyGenome = childBodyGenome;  // ?????
                    if (useMutation) {
                        // BODY MUTATION:
                        PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);
                    }
                }
                else { // no crossover:                    
                    
                    //===============================================================================================
                    for (int i = 0; i < parentNodeListArray[0].Count; i++) {
                        // iterate through all nodes in the parent List and copy them into fresh new geneNodes:
                        GeneNodeNEAT clonedNode = new GeneNodeNEAT(parentNodeListArray[0][i].id, parentNodeListArray[0][i].nodeType, parentNodeListArray[0][i].activationFunction, parentNodeListArray[0][i].sourceAddonInno, parentNodeListArray[0][i].sourceAddonRecursionNum, false, parentNodeListArray[0][i].sourceAddonChannelNum);
                        childNodeList.Add(clonedNode);
                    }
                    for (int j = 0; j < parentLinkListArray[0].Count; j++) {
                        //same thing with connections
                        GeneLinkNEAT clonedLink = new GeneLinkNEAT(parentLinkListArray[0][j].fromNodeID, parentLinkListArray[0][j].toNodeID, parentLinkListArray[0][j].weight, parentLinkListArray[0][j].enabled, parentLinkListArray[0][j].innov, parentLinkListArray[0][j].birthGen);
                        childLinkList.Add(clonedLink);
                        if (parentLinkListArray[0][j].enabled)
                            numEnabledLinkGenes++;
                    }
                    // MUTATION:
                    if (useMutation) {
                        // BODY MUTATION:
                        //childBrainGenome.nodeNEATList = childNodeList
                        //PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);

                        // BRAIN MUTATION:
                        if (numEnabledLinkGenes < 1)
                            numEnabledLinkGenes = 1;
                        for (int k = 0; k < childLinkList.Count; k++) {
                            float mutateChance = mutationBlastModifier * masterMutationRate / (1f + (float)numEnabledLinkGenes * 0.15f);
                            if (LifetimeGeneration - childLinkList[k].birthGen < newLinkBonusDuration) {
                                float t = 1 - ((LifetimeGeneration - childLinkList[k].birthGen) / (float)newLinkBonusDuration);
                                // t=0 means age of gene is same as bonusDuration, t=1 means it is brand new
                                mutateChance = Mathf.Lerp(mutateChance, mutateChance * newLinkMutateBonus, t);
                            }
                            if (CheckForMutation(mutateChance)) {  // Weight Mutation!
                                //Debug.Log("Weight Mutation Link[" + k.ToString() + "] weight: " + childLinkList[k].weight.ToString() + ", mutate: " + MutateFloat(childLinkList[k].weight).ToString());
                                childLinkList[k].weight = MutateFloat(childLinkList[k].weight);
                                totalNumWeightMutations++;
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationRemoveLinkChance)) {
                            //Debug.Log("Remove Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.RemoveRandomLink();
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddNodeChance)) {   // Adds a new node
                            //Debug.Log("Add Node Mutation Agent[" + newChildIndex.ToString() + "]");
                            childBrainGenome.AddNewRandomNode(LifetimeGeneration, GetNextAddonInnov());
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationAddLinkChance)) { // Adds new connection
                            //Debug.Log("Add Link Mutation Agent[" + newChildIndex.ToString() + "]");
                            if(CheckForMutation(existingNetworkBias)) {
                                childBrainGenome.AddNewExtraLink(existingFromNodeBias, LifetimeGeneration);
                            }
                            else {
                                childBrainGenome.AddNewRandomLink(LifetimeGeneration);
                            }
                        }
                        if (CheckForMutation(mutationBlastModifier * mutationActivationFunctionChance)) {
                            TransferFunctions.TransferFunction newFunction;
                            int randIndex = Mathf.RoundToInt(UnityEngine.Random.Range(0f, childNodeList.Count - 1));
                            int randomTF = (int)UnityEngine.Random.Range(0f, 12f);

                            switch (randomTF) {
                                case 0:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 1:
                                    newFunction = TransferFunctions.TransferFunction.Linear;
                                    break;
                                case 2:
                                    newFunction = TransferFunctions.TransferFunction.Gaussian;
                                    break;
                                case 3:
                                    newFunction = TransferFunctions.TransferFunction.Abs;
                                    break;
                                case 4:
                                    newFunction = TransferFunctions.TransferFunction.Cos;
                                    break;
                                case 5:
                                    newFunction = TransferFunctions.TransferFunction.Sin;
                                    break;
                                case 6:
                                    newFunction = TransferFunctions.TransferFunction.Tan;
                                    break;
                                case 7:
                                    newFunction = TransferFunctions.TransferFunction.Square;
                                    break;
                                case 8:
                                    newFunction = TransferFunctions.TransferFunction.Threshold01;
                                    break;
                                case 9:
                                    newFunction = TransferFunctions.TransferFunction.ThresholdNegPos;
                                    break;
                                case 10:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 11:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                case 12:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                                default:
                                    newFunction = TransferFunctions.TransferFunction.RationalSigmoid;
                                    break;
                            }
                            if (childNodeList[randIndex].nodeType != GeneNodeNEAT.GeneNodeType.Out) {  // keep outputs -1 to 1 range
                                Debug.Log("ActivationFunction Mutation Node[" + randIndex.ToString() + "] prev: " + childNodeList[randIndex].activationFunction.ToString() + ", new: " + newFunction.ToString());
                                childNodeList[randIndex].activationFunction = newFunction;
                            }
                        }
                        //for (int t = 0; t < childNodeList.Count; t++) {
                            
                        //}
                    }
                    else {
                        Debug.Log("Mutation Disabled!");
                    }

                    //   THE BODY!!!!! ++++++++++++++++++++++================+++++++++++++++++++===============+++++++++++++++++++===================+++++++++++++++++==============
                    CritterGenome childBodyGenome = new CritterGenome();  // create new body genome for Child                 
                    // Iterate over the nodes of the more fit parent:
                    for (int i = 0; i < parentAgentsArray[0].bodyGenome.CritterNodeList.Count; i++) {
                        int currentNodeInno = parentAgentsArray[0].bodyGenome.CritterNodeList[i].innov;
                        if (i == 0) {  // if this is the ROOT NODE:
                            childBodyGenome.CritterNodeList[0].CopySettingsFromNode(parentAgentsArray[0].bodyGenome.CritterNodeList[0]);
                            // The root node was already created during the Constructor method of the CritterGenome,
                            // ... so instead of creating a new one, just copy the settings
                        }
                        else {  // NOT the root node, proceed normally:
                                // Create new cloned node defaulted to the settings of the source( more-fit parent's) Node:
                            CritterNode clonedCritterNode = parentAgentsArray[0].bodyGenome.CritterNodeList[i].CloneThisCritterNode();
                            childBodyGenome.CritterNodeList.Add(clonedCritterNode);
                        }
                    }
                    // ADD-ONS!!!!!!!!!!!!!!!!!!!!!!
                    BreedCritterAddons(ref childBodyGenome, ref parentAgentsArray[0].bodyGenome, ref parentAgentsArray[0].bodyGenome);
                    newChildAgent.bodyGenome = childBodyGenome;
                    if (useMutation) {
                        // BODY MUTATION:
                        PerformBodyMutation(ref childBodyGenome, ref childBrainGenome);
                    }
                }
                
                newChildAgent.brainGenome = childBrainGenome;
                //newChildAgent.brainGenome.nodeNEATList = childNodeList;
                //newChildAgent.brainGenome.linkNEATList = childLinkList;
                BrainNEAT childBrain = new BrainNEAT(newChildAgent.brainGenome);
                childBrain.BuildBrainNetwork();
                newChildAgent.brain = childBrain;
                //Debug.Log("NEW CHILD numNodes: " + newChildAgent.brainGenome.nodeNEATList.Count.ToString() + ", #Neurons: " + newChildAgent.brain.neuronList.Count.ToString());
                //newChildAgent.bodyGenome.PreBuildCritter(0.8f);
                // Species:
                if (useSpeciation) {
                    float randAdoption = UnityEngine.Random.Range(0f, 1f);
                    if (randAdoption < adoptionRate) { // Attempts to Found a new species
                        bool speciesGenomeMatch = false;
                        for (int s = 0; s < childSpeciesPoolsList.Count; s++) {
                            float geneticDistance = GenomeNEAT.MeasureGeneticDistance(newChildAgent.brainGenome, childSpeciesPoolsList[s].templateGenome, neuronWeight, linkWeight, weightWeight, normalizeExcess, normalizeDisjoint, normalizeLinkWeight);

                            if (geneticDistance < speciesSimilarityThreshold) {
                                speciesGenomeMatch = true;
                                //agent.speciesID = speciesBreedingPoolList[s].speciesID; // this is done inside the AddNewAgent method below v v v 
                                childSpeciesPoolsList[s].AddNewAgent(newChildAgent);
                                //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") SortAgentIntoBreedingPool dist: " + geneticDistance.ToString() + ", speciesIDs: " + newChildAgent.speciesID.ToString() + ", " + childSpeciesPoolsList[s].speciesID.ToString() + ", speciesCount: " + childSpeciesPoolsList[s].agentList.Count.ToString());
                                break;
                            }
                        }
                        if (!speciesGenomeMatch) {

                            SpeciesBreedingPool newSpeciesBreedingPool = new SpeciesBreedingPool(newChildAgent.brainGenome, sourcePopulation.GetNextSpeciesID()); // creates new speciesPool modeled on this agent's genome

                            newSpeciesBreedingPool.AddNewAgent(newChildAgent);  // add this agent to breeding pool
                            childSpeciesPoolsList.Add(newSpeciesBreedingPool);  // add new speciesPool to the population's list of all active species

                            //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") SortAgentIntoBreedingPool NO MATCH!!! -- creating new BreedingPool " + newSpeciesBreedingPool.speciesID.ToString() + ", newChildAgentSpeciesID: " + newChildAgent.speciesID.ToString());
                        }
                    }
                    else {  // joins parent species automatically:
                        SpeciesBreedingPool newSpeciesBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, parentAgentBreedingPool.speciesID);
                        newSpeciesBreedingPool.AddNewAgent(newChildAgent);  // add this agent to breeding pool
                                                                            //Debug.Log(" NEW CHILD (" + newChildIndex.ToString() + ") NO ADOPTION SortAgentIntoBreedingPool speciesIDs: " + newChildAgent.speciesID.ToString() + ", " + newSpeciesBreedingPool.speciesID.ToString() + ", speciesCount: " + newSpeciesBreedingPool.agentList.Count.ToString());
                    }
                }
                else {  // joins parent species automatically:
                    SpeciesBreedingPool newSpeciesBreedingPool = sourcePopulation.GetBreedingPoolByID(childSpeciesPoolsList, parentAgentBreedingPool.speciesID);
                    newSpeciesBreedingPool.AddNewAgent(newChildAgent);  // add this agent to breeding pool                                                                        
                }

                newChildAgent.parentFitnessScoreA = sourcePopulation.masterAgentArray[newChildIndex].fitnessScore;
                newAgentArray[newChildIndex] = newChildAgent;

                newChildIndex++;  // new child created!
                newChildrenCreated++;
            }
        }

        /*Debug.Log("Finished Crossover! childSpeciesPoolsList:");
        for (int i = 0; i < sourcePopulation.speciesBreedingPoolList.Count; i++) {
            string poolString = " Child Species ID: " + sourcePopulation.speciesBreedingPoolList[i].speciesID.ToString();
            for (int j = 0; j < sourcePopulation.speciesBreedingPoolList[i].agentList.Count; j++) {
                poolString += ", member# " + j.ToString() + ", species: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].speciesID.ToString() + ", fitRank: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].fitnessRank.ToString();
            }
            Debug.Log(poolString);
        }*/

        // Clear out extinct species:
        int listIndex = 0;
        for (int s = 0; s < childSpeciesPoolsList.Count; s++) {
            if (listIndex >= childSpeciesPoolsList.Count) {
                Debug.Log("end childSpeciesPoolsList " + childSpeciesPoolsList.Count.ToString() + ", index= " + listIndex.ToString());
                break;
            }
            else {
                if (childSpeciesPoolsList[listIndex].agentList.Count == 0) {  // if empty:
                    //Debug.Log("Species " + childSpeciesPoolsList[listIndex].speciesID.ToString() + " WENT EXTINCT!!! --- childSpeciesPoolsList[" + listIndex.ToString() + "] old Count: " + childSpeciesPoolsList.Count.ToString() + ", s: " + s.ToString());
                    childSpeciesPoolsList.RemoveAt(listIndex);
                    //s--;  // see if this works                    
                }
                else {
                    listIndex++;
                }
            }
        }
        
        Debug.Log("Finished Crossover! totalNumWeightMutations: " + totalNumWeightMutations.ToString() + ", mutationBlastModifier: " + mutationBlastModifier.ToString() + ", bodyMutationBlastModifier: " + bodyMutationBlastModifier.ToString() + ", LifetimeGeneration: " + LifetimeGeneration.ToString() + ", currentGeneration: " + currentGeneration.ToString() + ", sourcePopulation.trainingGenerations: " + sourcePopulation.trainingGenerations.ToString());
        sourcePopulation.masterAgentArray = newAgentArray;
        sourcePopulation.speciesBreedingPoolList = childSpeciesPoolsList;

        /*Debug.Log("Finished Crossover! sourcePopulation.speciesBreedingPoolList:");
        for (int i = 0; i < sourcePopulation.speciesBreedingPoolList.Count; i++) {
            string poolString = "New Species ID: " + sourcePopulation.speciesBreedingPoolList[i].speciesID.ToString();
            for (int j = 0; j < sourcePopulation.speciesBreedingPoolList[i].agentList.Count; j++) {
                poolString += ", member# " + j.ToString() + ", species: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].speciesID.ToString() + ", fitRank: " + sourcePopulation.speciesBreedingPoolList[i].agentList[j].fitnessRank.ToString();
            }
            Debug.Log(poolString);
        }*/

        return sourcePopulation;
    }
    public void UpdateConnectionVertexPositionsBezier(BrainNEAT brain) {

        for (int c = 0; c < connectionVertexList.Count; c++) {
            // for all connections:

            /*Vector3 linkVector = new Vector3(nodePositionsList[brain.connectionList[i].toNodeID].x - nodePositionsList[brain.connectionList[i].fromNodeID].x, nodePositionsList[brain.connectionList[i].toNodeID].y - nodePositionsList[brain.connectionList[i].fromNodeID].y, nodePositionsList[brain.connectionList[i].toNodeID].z - nodePositionsList[brain.connectionList[i].fromNodeID].z);
            Vector3 widthVector = new Vector3(new Vector2(linkVector.y, -linkVector.x).normalized.x, new Vector2(linkVector.y, -linkVector.x).normalized.y, 0f) * (connectionWidth + Mathf.Abs(brain.connectionList[i].weight[0]) * connectionWidth * 0.62f);
            Vector3 cornerPos = new Vector3(nodePositionsList[brain.connectionList[i].fromNodeID].x - widthVector.x * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].y - widthVector.y * 0.5f + neuronRadius * 0.5f, nodePositionsList[brain.connectionList[i].fromNodeID].z);
            //Debug.Log("index0: " + nodePositionsList[i].x.ToString() + ", " + nodePositionsList[i].y.ToString() + " index1: " + nodePositionsList[i].x.ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index2: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + (nodePositionsList[i].y + neuronRadius).ToString() + " index3: " + (nodePositionsList[i].x + neuronRadius).ToString() + ", " + nodePositionsList[i].y.ToString());
            meshBuilder.Vertices[connectionVertexList[i][0]] = cornerPos;
            meshBuilder.Vertices[connectionVertexList[i][1]] = cornerPos + linkVector;
            meshBuilder.Vertices[connectionVertexList[i][2]] = cornerPos + linkVector + widthVector;
            meshBuilder.Vertices[connectionVertexList[i][3]] = cornerPos + widthVector;
            */
            int currentVertexIndex = 0;
            //float width = connectionWidth; // brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0];
            Color colorStart = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].fromNodeID]);
            Color colorEnd = GetColorFromNeuron(brain.neuronList[brain.connectionList[c].toNodeID]);
            float startWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].fromNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin);
            float endWidth = Mathf.Max(Mathf.Min((Mathf.Abs(brain.neuronList[brain.connectionList[c].toNodeID].currentValue[0])) * neuronRadiusMaxValue, connectionWidthMax), connectionWidthMin);
            float m_splineStartRadius = startWidth;
            float m_splineEndRadius = endWidth;
            int m_splineHeightSegmentCount = 8;
            int m_splineRadialSegmentCount = 4;

            float tInc = 1f / m_splineHeightSegmentCount; // How many subdivisions along the length of the spline

            for (int i = 0; i <= m_splineHeightSegmentCount; i++) {
                float t = tInc * (float)i;
                Vector3 ringCenter = bezierCurveList[c].GetPoint(t);
                
                Vector3 dir = bezierCurveList[c].GetDirection(t);
                Quaternion rot = Quaternion.identity;
                if(dir != Vector3.zero) {
                    rot.SetLookRotation(dir);
                }                
                float radius = ((1f - t) * m_splineStartRadius) + (t * m_splineEndRadius);
                // Construct the mesh Ring!
                //BuildBezierCurveRing(meshBuilder, m_splineRadialSegmentCount, ringCenter, radius, t, i > 0, rot); 
                //protected void BuildBezierCurveRing(MeshBuilder meshBuilder, int segmentCount, Vector3 center, float radius, float v, bool buildTriangles, Quaternion rotation) {
                float angleInc = (Mathf.PI * 2.0f) / m_splineRadialSegmentCount;

                for (int j = 0; j <= m_splineRadialSegmentCount; j++) {
                    float angle = angleInc * j;

                    Vector3 unitPosition = Vector3.zero;
                    unitPosition.x = Mathf.Cos(angle);
                    unitPosition.y = Mathf.Sin(angle);

                    unitPosition = rot * unitPosition;
                    Vector3 normal = unitPosition;

                    //meshBuilder.Vertices[] = ringCenter + unitPosition * radius;
                    meshBuilder.Vertices[connectionVertexList[c][currentVertexIndex]] = ringCenter + unitPosition * radius;
                    meshBuilder.Colors[connectionVertexList[c][currentVertexIndex]] = Color.Lerp(colorStart, colorEnd, t);
                    currentVertexIndex++;
                    //meshBuilder.Vertices.Add(ringCenter + unitPosition * radius);
                    //meshBuilder.Normals.Add(normal);
                    //meshBuilder.UVs.Add(new Vector2((float)i / segmentCount, v));
                    //meshBuilder.UVs.Add(new Vector2((float)j / m_splineRadialSegmentCount, t));
                    //verticesList.Add(meshBuilder.Vertices.Count - 1);
                    //meshBuilder.Colors.Add(color);

                    /*if (j > 0 && i > 0) {
                        //Debug.Log ("buildTriangles!");
                        int baseIndex = meshBuilder.Vertices.Count - 1;

                        int vertsPerRow = m_splineRadialSegmentCount + 1;

                        int index0 = baseIndex;
                        int index1 = baseIndex - 1;
                        int index2 = baseIndex - vertsPerRow;
                        int index3 = baseIndex - vertsPerRow - 1;

                        meshBuilder.AddTriangle(index1, index2, index0);
                        meshBuilder.AddTriangle(index1, index3, index2);
                    }*/
                }
            }
        }

        meshBuilder.UpdateMeshVertices();
    }
示例#25
0
        private void BrainNEAT_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (_experiment == null || _ea == null)
                {
                    //NOTE: Just doing this for laziness.  I don't want to write a bunch of logic to train a phenome up front
                    MessageBox.Show("Need to have a running experiment", this.Title, MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                // Get a genome
                NeatGenome genome = _ea.CurrentChampGenome;

                // Create a phenome
                IBlackBox phenome = ExperimentNEATBase.GetBlackBox(genome, _experimentArgs.Activation, _hyperneatArgs);

                // Instantiate a BrainNEAT
                EditorOptions options     = new EditorOptions();
                ItemOptions   itemOptions = new ItemOptions();

                Container energy = new Container()
                {
                    QuantityMax     = 1000,
                    QuantityCurrent = 1000,
                };

                BrainNEATDNA dnaBrain = new BrainNEATDNA()
                {
                    PartType = BrainNEAT.PARTTYPE, Position = new Point3D(0, 0, 0), Orientation = Quaternion.Identity, Scale = new Vector3D(1, 1, 1)
                };

                BrainNEAT brain = new BrainNEAT(options, itemOptions, dnaBrain, energy);


                brain.SetPhenome(phenome, genome, _experimentArgs.Activation, _hyperneatArgs);


                for (int cntr = 0; cntr < 100; cntr++)
                {
                    foreach (INeuron neuron in brain.Neruons_Writeonly)
                    {
                        neuron.SetValue(StaticRandom.NextDouble(-2.5, 2.5));
                    }

                    brain.Update_AnyThread(1);
                }



                #region save/load test2

                // let BrainNEAT do the save/load

                BrainNEATDNA dna2     = (BrainNEATDNA)brain.GetNewDNA();
                string       dna2Text = XamlServices.Save(dna2).Replace('"', '\'');
                BrainNEAT    brain2   = new BrainNEAT(options, itemOptions, dna2, energy);

                for (int cntr = 0; cntr < 100; cntr++)
                {
                    foreach (INeuron neuron in brain2.Neruons_Writeonly)
                    {
                        neuron.SetValue(StaticRandom.NextDouble(-2.5, 2.5));
                    }

                    brain2.Update_AnyThread(1);
                }

                BrainNEATDNA dna3   = (BrainNEATDNA)brain2.GetNewDNA();
                BrainNEAT    brain3 = new BrainNEAT(options, itemOptions, dna3, energy);

                for (int cntr = 0; cntr < 100; cntr++)
                {
                    foreach (INeuron neuron in brain3.Neruons_Writeonly)
                    {
                        neuron.SetValue(StaticRandom.NextDouble(-2.5, 2.5));
                    }

                    brain3.Update_AnyThread(1);
                }

                #endregion
                #region save/load test1

                // initial test, building minimum necessary dna

                BrainNEATDNA brainDNA = new BrainNEATDNA()
                {
                    Activation           = _experimentArgs.Activation,
                    Hyper                = _hyperneatArgs,
                    NEATPositions_Input  = brain.Neruons_Readonly.Select(o => o.Position).ToArray(),
                    NEATPositions_Output = brain.Neruons_Writeonly.Select(o => o.Position).ToArray(),
                    Genome               = ExperimentNEATBase.SavePopulation(new[] { genome }),
                };


                // Make sure this can be serialized/deserialized
                string testString = XamlServices.Save(brainDNA);
                brainDNA = UtilityCore.Clone(brainDNA);


                List <NeatGenome> genomeList = null;
                if (_hyperneatArgs == null)
                {
                    genomeList = ExperimentNEATBase.LoadPopulation(brainDNA.Genome, brainDNA.Activation, brainDNA.NEATPositions_Input.Length, brainDNA.NEATPositions_Output.Length);
                }
                else
                {
                    genomeList = ExperimentNEATBase.LoadPopulation(brainDNA.Genome, brainDNA.Activation, _hyperneatArgs);
                }

                #endregion
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), this.Title, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }