/// <summary> /// Conduct the events a normal ant AntAgent object. /// The action will be determined based on it's current status (e.g. if it is moving to a food source, /// if it is depositing food at a nest). /// </summary> /// <param name="ant">The AntAgent for which to conduct the appropriate action for (based on it's current status).</param> private void AntAction(AntAgent ant) { // Based on if the ant is at or moving to food or nest. // The ant can be forgetful, so we need to make sure it knows where food is as it moves. if (ant.IsMovingToFood && ant.IsFoodKnown) { ant.Approach(ant.FoodLocation); // See if the ant is at the nest or food source currently. if (ant.AgentPosition.Distance(ant.FoodLocation) < 1) { FoodAntAction(ant); } } else if (ant.IsMovingToNest && ant.IsNestKnown) { ant.Approach(ant.NestLocation); // If the ant is currently at the nest. if (ant.AgentPosition.Distance(ant.NestLocation) < 1) { NestAntAction(ant); } } else { GenericAntAction(ant); } }
/// <summary> /// Detect the nearest robber ant nest given a robber AntAgent object stored in the robber ant colony. /// </summary> /// <param name="ant">The AntAgent object to find the closest robber ant nest object within it's proximity.</param> private void DetectNearestRobberNest(AntAgent ant) { Nest robberNest; double distanceToNest; double shortestNestDance; shortestNestDance = 0.0; // Loop through the robber ant nest to get the closest robber AntAgent to the given object. for (int robberNestIndex = 0; robberNestIndex < colonyRobberNests.Count(); robberNestIndex++) { robberNest = colonyRobberNests.ElementAt(robberNestIndex); distanceToNest = ant.AgentPosition.Distance(robberNest.NestPosition); if (shortestNestDance == 0) { shortestNestDance = distanceToNest; } if (distanceToNest <= objectDetectionRadius && distanceToNest <= shortestNestDance) { shortestNestDance = distanceToNest; ant.ClosestNestIndex = robberNestIndex; ant.NestLocation = robberNest.NestPosition; ant.IsNestKnown = true; } } }
/// <summary> /// Conduct the events that a robber AntAgent object undertakes in the ant world. /// </summary> /// <param name="robberAnt">The robber AntAgent object to undertake the appropriate action in the current condition.</param> private void RobberAntAction(AntAgent robberAnt) { if (robberAnt.IsMovingToFood) { // Approach location of the target ant with possible food. robberAnt.Approach(robberAnt.FoodLocation); if (robberAnt.AgentPosition.Distance(robberAnt.FoodLocation) < 5) { RobberFoodAntAction(robberAnt); } } else if (robberAnt.IsMovingToNest) { robberAnt.Approach(robberAnt.NestLocation); // If the robber ant is currently at the nest. if (robberAnt.AgentPosition.Distance(robberAnt.NestLocation) < 1) { RobberNestAntAction(robberAnt); } } else { GenericAntAction(robberAnt); } }
/// <summary> /// Simulate the generic actions that both normal and robber ants undertake when /// they are either wandering around or about to move to food source or nest. /// </summary> /// <param name="ant">The AntAgent to simulate it's generic actions.</param> private void GenericAntAction(AntAgent ant) { // Based on if the ant is currently carrying food or not. if (!ant.IsCarryingFood) { // If the ant knows where the location of the food is, then go there. if (ant.IsFoodKnown) { ant.IsMovingToFood = true; } else { ant.Wander(); } } // If it is carrying food.. else { // ..and if the location of the nest is known, then go there. if (ant.IsNestKnown) { ant.IsMovingToNest = true; } else { ant.Wander(); } } }
private void CreateAnts() { Rectangle worldLimits; // create a radnom object to pass to the ants randomGenerator = new Random(); // define some world size for the ants to move around on // assume the size of the world is the same size as the panel // on which they are displayed worldLimits = new Rectangle(0, 0, drawingPanel.Width, drawingPanel.Height); // create a couple of agents at some postions agent1 = new AntAgent(new SOFT152Vector(100, 150), randomGenerator, worldLimits); agent2 = new AntAgent(new SOFT152Vector(200, 150), randomGenerator, worldLimits); agent3 = new AntAgent(new SOFT152Vector(300, 150), randomGenerator, worldLimits); // create an object at a arbitary position someObject = new SOFT152Vector(250, 250); //create a 2nd object at an arbitrary position foodObject = new SOFT152Vector(50, 50); //create a nest object at an arbitrary position nest1 = new NestObject(new SOFT152Vector(50, 100)); //create a food object at an arbitrary position food1 = new FoodObject(new SOFT152Vector(100, 50), 100); }
/// <summary> /// Simulate a conversation between AntAgent object, using their ClosestAntIndex, /// to share information of the location of food and/or nest if either has it. /// </summary> /// <param name="sharingAnt">The AntAgent object which is to communicate with the closest ant to it.</param> private void ShareInformation(AntAgent sharingAnt) { Food sharingAntFoodSource; Food receivingAntFoodSource; // If there is a new closest ant assigned. if (sharingAnt.IsNewClosestAnt) { AntAgent receivingAnt; receivingAnt = antColony.ElementAt(sharingAnt.ClosestAntIndex); // Share nest location information: if (sharingAnt.IsNestKnown && !receivingAnt.IsNestKnown) { receivingAnt.NestLocation = sharingAnt.NestLocation; receivingAnt.IsNestKnown = true; } else if (!sharingAnt.IsNestKnown && receivingAnt.IsNestKnown) { sharingAnt.NestLocation = receivingAnt.NestLocation; sharingAnt.IsNestKnown = true; } // Share food location information if the food source an ant knows is not yet depleted. if (sharingAnt.IsFoodKnown && !receivingAnt.IsFoodKnown) { sharingAntFoodSource = colonyFoodSources.ElementAt(sharingAnt.ClosestFoodIndex); // Check to see if the food source is depleted before sharing the information. if (!sharingAntFoodSource.isFoodDepleted) { receivingAnt.FoodLocation = sharingAnt.FoodLocation; receivingAnt.IsFoodKnown = true; } } else if (!sharingAnt.IsFoodKnown && receivingAnt.IsFoodKnown) { receivingAntFoodSource = colonyFoodSources.ElementAt(receivingAnt.ClosestFoodIndex); if (!receivingAntFoodSource.isFoodDepleted) { sharingAnt.FoodLocation = receivingAnt.FoodLocation; sharingAnt.IsFoodKnown = true; } } // Set the new closest ant boolean value to false. sharingAnt.IsNewClosestAnt = false; } }
/// <summary> /// Detect the closest AntAgent object to another given AntAgent object. /// This method is for the use of both normal ants and robber ants, /// however, the search will always be from the normal ant colony. /// </summary> /// <param name="ant">The AntAgent object to detect the closest AntAgent within it's detection radius.</param> /// <param name="antIndex">The index of the AntAgent within it's own colony (List AntAgent object).</param> private void DetectClosestAnt(AntAgent ant, int antIndex) { AntAgent otherAnt; double otherAntDistance; double shortestAntDistance; shortestAntDistance = 0.0; // Allow ants to be detected if they come in close distance of other ants. for (int otherAntIndex = 0; otherAntIndex < antColonySize; otherAntIndex++) { otherAnt = antColony.ElementAt(otherAntIndex); // NOTE: Issue when robber ant compared to normal ant colony - avoid choosing the current ant. if (antIndex != otherAntIndex) { // Debug.WriteLine("Found other ant {0}.", otherAntIndex); // Get the distance from the current ant to the other ant. otherAntDistance = ant.AgentPosition.Distance(otherAnt.AgentPosition); // Set initial distance to work with. if (shortestAntDistance == 0.0) { shortestAntDistance = otherAntDistance; } // Debug.WriteLine("Other ants distance: {0}", otherAntDistance); // Make sure the other ant is within our radius. Allow ant which equals the shortest distance to enter, // this means the last ant in the radius can communicate. if (otherAntDistance <= antDetectionRadius && otherAntDistance <= shortestAntDistance) { // The current shortest distance will change if the other ant's distance // is smaller than the current shortest distance. shortestAntDistance = otherAntDistance; // Set the closest ant index for the current ant to the index of the other ant. // This allows us to identify which ants should communicate together. // Do not assign the same ant which was approached before. if (ant.ClosestAntIndex != otherAntIndex) { ant.ClosestAntIndex = otherAntIndex; ant.IsNewClosestAnt = true; } } } } }
/// <summary> /// Simulate memory loss within ants. The loss of memory for /// the ant can also occur at any random time it is wandering /// (if it has knowledge of food or the nest). /// </summary> /// <param name="antWithMemory">The AntAgent for which to simulate memory loss.</param> private void AntMemoryLoss(AntAgent antWithMemory) { int randomNum; if (antWithMemory.IsNestKnown) { randomNum = randomGenerator.Next(0, 11); // 20% chance of forgetting nest. if (randomNum >= 8) { antWithMemory.IsNestKnown = false; } if (antWithMemory.IsFoodKnown) { randomNum = randomGenerator.Next(0, 11); // 40% chance of forgetting food. if (randomNum <= 4) { antWithMemory.IsFoodKnown = false; } } } // Vice versa: if (antWithMemory.IsFoodKnown) { randomNum = randomGenerator.Next(0, 11); // 20% chance of forgetting food source. if (randomNum >= 8) { antWithMemory.IsFoodKnown = false; } if (antWithMemory.IsNestKnown) { randomNum = randomGenerator.Next(0, 11); // 40% chance of forgetting nest. if (randomNum <= 4) { antWithMemory.IsNestKnown = false; } } } }
/// <summary> /// Simulate actions when a robber ant arrives at it's nest. /// </summary> /// <param name="robberAnt">The robber AntAgent to simulate events when it arrives at it's nest.</param> private void RobberNestAntAction(AntAgent robberAnt) { Nest robberNestAtLocation; robberNestAtLocation = colonyRobberNests.ElementAt(robberAnt.ClosestNestIndex); robberAnt.IsMovingToNest = false; // Allow the ant to deposit the food it stole. robberNestAtLocation.DepositFood(); Debug.WriteLine("A robber ant deposited a piece of food in the nest. Total food deposited at robber nest = {0}", robberNestAtLocation.FoodDeposited); // The ant is no longer carrying the food. robberAnt.IsCarryingFood = false; }
/// <summary> /// Simulate actions when a normal ant arrives at it's nest. /// </summary> /// <param name="ant">The AntAgent to simulate events when it arrives at it's nest.</param> private void NestAntAction(AntAgent ant) { Nest nestAtLocation; nestAtLocation = colonyNests.ElementAt(ant.ClosestNestIndex); ant.IsMovingToNest = false; // Allow the ant to deposit the food. nestAtLocation.DepositFood(); Debug.WriteLine("An ant deposited a piece of food in the nest. Total food deposited at nest = {0}", nestAtLocation.FoodDeposited); // The ant is no longer carrying the food. ant.IsCarryingFood = false; }
/// <summary> /// Recognise the closest normal ant to a robber AntAgent object /// as being a potential food source; robber ant recognises /// normal ant's position as it's food location. /// /// The robber ant will only recognise a new food location if it /// is not already carrying a piece of food it has not yet deposited. /// </summary> /// <param name="robberAnt">The robber AntAgent object for which to set its next food location.</param> private void RecogniseClosestAnt(AntAgent robberAnt) { if (robberAnt.IsNewClosestAnt && !robberAnt.IsCarryingFood) { AntAgent foodAnt; foodAnt = antColony.ElementAt(robberAnt.ClosestAntIndex); robberAnt.FoodLocation = foodAnt.AgentPosition; // Set food is known, to allow the robber ant to move to the food ants location. robberAnt.IsFoodKnown = true; // Allow for the ant to not keep on approaching the same ant. robberAnt.IsNewClosestAnt = false; } }
/// <summary> /// An ant will be able to detect the closest food source to it. /// This is used by normal ants. /// </summary> /// <param name="ant">The AntAgent object to detect the food source from.</param> private void DetectNearestFoodSource(AntAgent ant) { Food foodSource; double distanceToFood; double shortestFoodDistance; shortestFoodDistance = 0.0; for (int foodIndex = 0; foodIndex < colonyFoodSources.Count(); foodIndex++) { foodSource = colonyFoodSources.ElementAt(foodIndex); // Since we are not removing the food source completely, // only check those sources which still have food. if (!foodSource.isFoodDepleted) { // Get distance from the ant to the food source: distanceToFood = ant.AgentPosition.Distance(foodSource.FoodPosition); if (shortestFoodDistance == 0) { shortestFoodDistance = distanceToFood; } // Assign the new shortest distance if it is in range and if it is smaller than // or equal to the previous distance: if (distanceToFood <= objectDetectionRadius && distanceToFood <= shortestFoodDistance) { shortestFoodDistance = distanceToFood; // Set the closest food index and location. ant.ClosestFoodIndex = foodIndex; ant.FoodLocation = foodSource.FoodPosition; // The food source is now known to the ant. ant.IsFoodKnown = true; } } } }
/// <summary> /// this method creates the ants and put them into their lists. Thanks to the for-loops inside /// we can set the amount of ants that will wander on the graphic panel. /// </summary> private void CreateAnts() { Rectangle worldLimits; AntAgent tempAnt; antList = new List <AntAgent>(); robberAntList = new List <AntAgent>(); worldLimits = new Rectangle(0, 0, drawingPanel.Width, drawingPanel.Height); randomGenerator = new Random(); //Inside the for-loop below, two coordinates get created randomly. They are then used to create //the vector object of a single ant. The vector object is used inside the AntAgent constructor method //to give the AntAgent a position on the graphic panel. The AntAgent object is assigned to the variable //"tempAnt". After it is added to the list the loop goes back to create another AntAgent. //The loop below is used to create the 'civilian' ants. for (int i = 0; i < 700; i++) { int X = Convert.ToInt32(randomGenerator.Next(0, drawingPanel.Width - 1)); int Y = Convert.ToInt32(randomGenerator.Next(0, drawingPanel.Height - 1)); tempAnt = new AntAgent(new SOFT152Vector(X, Y), randomGenerator, worldLimits); antList.Add(tempAnt); } //The loop below creates the 'robber' ants. for (int i = 0; i < 0; i++) { int X = Convert.ToInt32(randomGenerator.Next(0, drawingPanel.Width - 1)); int Y = Convert.ToInt32(randomGenerator.Next(0, drawingPanel.Height - 1)); tempAnt = new AntAgent(new SOFT152Vector(X, Y), randomGenerator, worldLimits); robberAntList.Add(tempAnt); } }
private void CreateAnts() { Rectangle worldLimits; // create a radnom object to pass to the ants randomGenerator = new Random(); // define some world size for the ants to move around on // assume the size of the world is the same size as the panel // on which they are displayed worldLimits = new Rectangle(0, 0, drawingPanel.Width, drawingPanel.Height); for (int i = 0; i < noOfAnts; i++) { antGroup[i] = new AntAgent(new SOFT152Vector(randomGenerator.NextDouble() * drawingPanel.Width, randomGenerator.NextDouble() * drawingPanel.Height), randomGenerator, worldLimits); antGroup[i].HasFood = false; antGroup[i].KnowsFood = false; antGroup[i].KnowsNest = false; //set moving values for all the ants in the antGroup antGroup[i].AgentSpeed = 1.0; antGroup[i].WanderLimits = 0.25; //keep all the antAgents in the antGroup in the world antGroup[i].ShouldStayInWorldBounds = true; } // create an object at a arbitary position someObject = new SOFT152Vector(250, 250); anotherObject = new SOFT152Vector(50, 50); }
/// <summary> /// Simulate actions when a robber ant arrives at a food source. /// </summary> /// <param name="robberAnt">The robber AntAgent to simulate events when it arrives at the food source.</param> private void RobberFoodAntAction(AntAgent robberAnt) { AntAgent foodAnt; foodAnt = antColony.ElementAt(robberAnt.ClosestAntIndex); robberAnt.IsMovingToFood = false; // Allow us to interrogate the ant to determine if it has food to steal. if (foodAnt.IsCarryingFood) { // The robber ant steals the food off the normal ant. foodAnt.IsCarryingFood = false; robberAnt.IsCarryingFood = true; Debug.WriteLine("Robber ant stole a piece of food from a normal ant."); } else { // If not, we have not found a possible food source. robberAnt.IsFoodKnown = false; } }
/// <summary> /// An ant will be able to detect the closest nest to it; dedicated for normal ants. /// </summary> /// <param name="ant">The AntAgent object to find the closest normal nest within it's proximity.</param> private void DetectNearestNest(AntAgent ant) { Nest nest; double distanceToNest; double shortestNestDistance; shortestNestDistance = 0.0; for (int nestIndex = 0; nestIndex < colonyNests.Count(); nestIndex++) { nest = colonyNests.ElementAt(nestIndex); // Get the distance from the ant to the next. distanceToNest = ant.AgentPosition.Distance(nest.NestPosition); if (shortestNestDistance == 0) { shortestNestDistance = distanceToNest; } // Assign the new shortest distance if it is within detection distance and // it is shorter than any previous distances. if (distanceToNest <= objectDetectionRadius && distanceToNest <= shortestNestDistance) { shortestNestDistance = distanceToNest; // Assign this nest as the closest and record it's position. ant.ClosestNestIndex = nestIndex; ant.NestLocation = nest.NestPosition; // Make sure the nest is now known to the ant. ant.IsNestKnown = true; } } }
/// <summary> /// Simulate actions when a normal ant arrives at a food source. /// </summary> /// <param name="ant">The AntAgent to simulate events at the food source.</param> private void FoodAntAction(AntAgent ant) { Food foodAtLocation; foodAtLocation = colonyFoodSources.ElementAt(ant.ClosestFoodIndex); ant.IsMovingToFood = false; // Make sure food is available at the source before attempting to get food. if (!foodAtLocation.isFoodDepleted) { // Allow the ant to pick up one piece of the food. foodAtLocation.TakeFood(); // Allow the ant to now carry the food to the nest. ant.IsCarryingFood = true; Debug.WriteLine("An ant took a piece from the food source, remaining pieces = {0}.", foodAtLocation.FoodAvailable); } else { // As the food source has been depleted, make sure the ant forgets about this location. ant.IsFoodKnown = false; } }
/// <summary> /// Create ants (normal ants and robber ants) based on the /// colony sizes that is specified in the form. /// </summary> private void CreateAnts() { Rectangle worldLimits; AntAgent nextAntAgent; int vectorX; int vectorY; bool inputSizeValid; // Define some world size for the ants to move around on assume the // size of the world is the same size as the panel on which they are displayed. worldLimits = new Rectangle(0, 0, drawingPanel.Width, drawingPanel.Height); antColony = new List <AntAgent>(); robberAntColony = new List <AntAgent>(); // Create a random object to pass to created ants. randomGenerator = new Random(); // Ensure the colony sizes entered are converted from text // to integer sucessfully. inputSizeValid = false; try { // Get the ant/robber ant colony size. antColonySize = Convert.ToInt32(colonySizeTextBox.Text); robberAntColonySize = Convert.ToInt32(robberColonySizeTextBox.Text); inputSizeValid = true; } catch (FormatException) { MessageBox.Show("Please enter an integer as the number of normal/robber ants you want to create.", "Ant Colony Simulation - Input Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } if (inputSizeValid) { Debug.WriteLine("Creating {0} ants for the colony.", antColonySize); // Loop through the number of ants we need to create. for (int antIndex = 0; antIndex < antColonySize; antIndex++) { // Set the vector X and vector Y to be randomly generated. // Use next to get a new random number. vectorX = randomGenerator.Next(0, drawingPanel.Width); vectorY = randomGenerator.Next(0, drawingPanel.Height); // Create the AntAgent object for this vector. nextAntAgent = new AntAgent(new SOFT152Vector(vectorX, vectorY), randomGenerator, worldLimits); // Set the properties for the new ant. nextAntAgent.AgentSpeed = 1.5; nextAntAgent.ApproachRadius = 10; antColony.Add(nextAntAgent); Debug.WriteLine("Created new AntAgent (index {0}) at Vector({1}, {2})", antIndex, nextAntAgent.AgentPosition.X, nextAntAgent.AgentPosition.Y); } Debug.WriteLine("Creating {0} robber ants for the colony.", robberAntColonySize); // Loop through the size we want to create and create each ant. for (int robberAntIndex = 0; robberAntIndex < robberAntColonySize; robberAntIndex++) { vectorX = randomGenerator.Next(0, drawingPanel.Width); vectorY = randomGenerator.Next(0, drawingPanel.Height); // Create the robber ant using the co-ordinates, random object and the bounds of the world. nextAntAgent = new AntAgent(new SOFT152Vector(vectorX, vectorY), randomGenerator, worldLimits); // The speed and approach radius of the robber ant differ from normal ants; // they are to appear more quicker than that of normal ants. nextAntAgent.AgentSpeed = 1.75; nextAntAgent.ApproachRadius = 5; robberAntColony.Add(nextAntAgent); Debug.WriteLine("Created new Robber AntAgent (index {0} at Vector({1}, {2})", robberAntIndex, nextAntAgent.AgentPosition.X, nextAntAgent.AgentPosition.Y); } } }