// deep copy of the nodes public Node[] CopyNodes() { Node[] copy = new Node[nodes.Length]; for (int i = 0; i < nodes.Length; i++) { copy[i] = nodes[i].copySelf(); } return copy; }
public Agent(Node[] Nodes, int X, int Y, int StartDirection, int food, int ID, int MutateTableChance, int MutateAddNodeConnectionChance, int MutateRemoveNodeConnectionChance, int MutateSwitchNodeChance, double Red, double Green, double Blue, Random random, int carnivorePercentage, bool strictK, bool carnivorPercentageEnabled) { this.MutateSwitchNodeChance = MutateSwitchNodeChance; this.StrictK = strictK; this.CarnivorePercentage = carnivorePercentage; this.random = random; this.ID = ID; this.Red = Red; this.Blue = Blue; this.Green = Green; Food = food; Direction = StartDirection; this.nodes = Nodes; this.X = X; this.Y = Y; this.MutateTableChance = MutateTableChance; this.MutateAddNodeConnectionChance = MutateAddNodeConnectionChance; this.MutateRemoveNodeConnectionChance = MutateRemoveNodeConnectionChance; this.CarnivorPercentageEnabled = carnivorPercentageEnabled; }
// the actual execution / updating of the agents public void ExecuteAgents() { List<Agent> toBeRemoved = new List<Agent>(); // agents that need to be removed after all agents are updated at the end of the run if (RestartAtTurn == stepCounter) // if the simulation has reach the turn where it is to be restarted then remove all current agents { foreach(Agent agent in agents) { world.removeAgent(agent); } agents.Clear(); } if (agents.Count == 0) // if there are no agents alive then fill the world with agents according to the parameters specified by the user { if(KValues.Count == 0) { return; } stepCounter = 0; foreach(int k in KValues) // for each of the selected K values { for (int a = 0; a < AgentsPerKValue; a++) // add the specified ammount of agents { Node[] nodes = new Node[N]; for (int i = 0; i < N; i++) { // fill the new agents network with K random connections nodes[i] = new Node(i, null, random.Next(0, 2), new List<int>(), random); for (int j = 0; j < k; j++) { nodes[i].AddRandomConnection(N); } } if( AddAgent(new Agent(nodes, random.Next(0, world.worldWidth), random.Next(0, world.worldHeight), random.Next(1, 9), ReproductionCost / 2, IDCounter, 50, 50, 50, 50, (double)random.Next(1, 11) / 10, (double)random.Next(1, 11) / 10, (double)random.Next(1, 11) / 10, random, 0, StrictK, CarnivorPercentageEnabled), -1, -1) ) { IDCounter++; } } } resetCounter++; } agents = agents.OrderBy(i => random.Next()).ToList(); // create a randomly ordered list of agents to ensure a random order of execution int avarageFood = 0; for (int i = agents.Count - 1; i >= 0; i--) // execute / update each agent { if (agents[i].Alive) // if the agent is still alive { avarageFood += agents[i].Food; int[] surrounding = CalculateSurrounding(agents[i]); // the values for the agents input nodes int[] location; int[] output = agents[i].Execute(surrounding); // the values of the agents output nodes if (output[2] == 1 && agents[i].Food >= ReproductionCost + 50) // if the agents wants to reproduce and has enough food { location = directionToAbsolute(agents[i], agents[i].ValidateDirection(agents[i].Direction - 4)); if (!world.occupied(location[0], location[1])) { // create new agent (child) Agent newAgent = agents[i].CreateMutantCopy(); newAgent.ID = IDCounter; newAgent.X = location[0]; newAgent.Y = location[1]; // give the new agent a random color (currently not used) newAgent.Red = (double)random.Next(1, 11) / 10; newAgent.Blue = (double)random.Next(1, 11) / 10; newAgent.Green = (double)random.Next(1, 11) / 10; newAgent.Food = ReproductionCost / 6;// initial food for the child if (AddAgent(newAgent, agents[i].ID, agents[i].Age)) // try to add the new agent to the world { agents[i].Food -= ReproductionCost; IDCounter++; } } } if (output[1] == 1) // if the agents output signals that it wants to move { location = directionToAbsolute(agents[i], agents[i].Direction); if (world.occupied(location[0], location[1])) // if the new location is occupied then an attack will happen { Agent DefendingAgent = world.getAgent(location[0], location[1]); // get the defending agent // if the defending agent has a larger carnivor percentage or wins by chance if (DefendingAgent.CarnivorePercentage > agents[i].CarnivorePercentage | (DefendingAgent.CarnivorePercentage == agents[i].CarnivorePercentage & random.Next(0, 2) == 1)) { int FoodOfAge = agents[i].Age; if (FoodOfAge > 100) FoodOfAge = 100; DefendingAgent.Food += (int)(agents[i].Food * ((float)DefendingAgent.CarnivorePercentage) / 100);// +FoodOfAge; toBeRemoved.Add(agents[i]); world.removeAgent(agents[i]); agents[i].Alive = false; } else { int FoodOfAge = DefendingAgent.Age; if (FoodOfAge > 100) FoodOfAge = 100; agents[i].Food += (int)(DefendingAgent.Food * ((float)agents[i].CarnivorePercentage) / 100);// +agents[i].Age; world.removeAgent(DefendingAgent); toBeRemoved.Add(DefendingAgent); DefendingAgent.Alive = false; world.moveAgent(agents[i], location[0], location[1]); } } else if (world.moveAgent(agents[i].X, agents[i].Y, location[0], location[1])) // if the new location is free { agents[i].X = location[0]; agents[i].Y = location[1]; } } agents[i].Food -= 10; // remove the food that each turn costs agents[i].Age++; // if an agents reaches its maximum age or has no more food then remove the agent if (agents[i].Food <= 0 | agents[i].Age > MaxAge) { world.removeAgent(agents[i].X, agents[i].Y); toBeRemoved.Add(agents[i]); agents[i].Alive = false; } } } avarageFood = avarageFood / agents.Count; // remove all of the agents that have died in this run foreach (Agent agent in toBeRemoved) { agents.Remove(agent); } toBeRemoved.Clear(); // write test date to .csv file every 20 turns if (stepCounter % 20 == 0) { addToCSV(); } stepCounter++; }