public void MoveAnt(AntInfo ant, HexInfo hex) { var oldHex = ant.Hex; oldHex.HasAnt = false; hex.HasAnt = true; ant.Hex = hex; ant.LastLocation = oldHex.Coordinates; // move ant ant.Ant.transform.DOMove(Master.MasterHex.CalculatePosition(hex.Coordinates.x, hex.Coordinates.y), Master.CoreGameLoopFrequency).SetEase(Ease.Linear); // move food if ant is carrying if (ant.Food != null) { ant.Food.transform.DOMove(Master.MasterHex.CalculatePosition(hex.Coordinates.x, hex.Coordinates.y), Master.CoreGameLoopFrequency).SetEase(Ease.Linear); } // uncomment this if you want to see where the ants have been //Master.MasterHex.HighlightHex(hex.Coordinates, Color.green); ant.Energy--; // spend energy ant.LastTurn = Master.GameTurn; hex.LastTouched = Master.GameTurn; }
private void Solve() { _antThread = Thread.CurrentThread; InitializeMatrixes(); List <AntInfo> allAnts = new List <AntInfo>(); while (true) { allAnts.Clear(); for (int i = 0; i < _ants; i++) { bool findingRoute = true; AntInfo ant = new AntInfo(_data.Vertexes.Count); while (findingRoute) { bool isTruckFull = CheckCurrentCapacity(ant); ant.NextVertex = isTruckFull == false?FindNewVertex(ant) : 0; ActualizeCurrentRoute(ant); if (ant.DepotVisiting == _data.TrucksNumber || CheckEndOfRoute(ant)) { findingRoute = false; } } allAnts.Add(ant); } AverageRouteInfo(allAnts); ActualizePheromones(allAnts); } }
private bool CheckCurrentCapacity(AntInfo ant) { for (int i = 1; i < ant.Visited.Length; i++) { if (ant.Visited[i] == false && _data.TruckCapacity >= ant.CurrentCapacity + _data.Vertexes[i].Demand) { return(false); } } return(true); }
private bool CheckEndOfRoute(AntInfo ant) { for (int i = 1; i < ant.Visited.Length; i++) { if (ant.Visited[i] == false) { return(false); } } return(ant.CurrentVertex == 0); }
public GameObject RespawnAntAt(AntInfo ant, Vector2Int coords) { ant.Ant.transform.DOMove(Master.MasterHex.CalculatePosition(coords.x, coords.y), 0F); HexInfo hex = Master.MasterHex.GetHexInfoAt(coords); ant.InitializeAnt(ant.Ant, hex, Master.GameTurn, MaxAntEnergy); CurrentAnts.Add(ant); var antHex = Master.MasterHex.GetHexInfoAt(coords); MoveAnt(ant, antHex); return(ant.Ant); }
private void ActualizeCurrentRoute(AntInfo ant) { if (ant.NextVertex == 0) { ant.CurrentCapacity = 0; ant.DepotVisiting += 1; } else { ant.Visited[ant.NextVertex] = true; } ant.CurrentRoute.Add(ant.NextVertex); ant.CurrentDistance += _distances[ant.CurrentVertex, ant.NextVertex]; ant.CurrentCapacity += _data.Vertexes[ant.NextVertex].Demand; ant.CurrentVertex = ant.NextVertex; }
private bool MoveToTarget(AntInfo ant, HexInfo target) { if (target == null) { return(false); } if (!target.IsEmpty || ant.Hex == target || Vector2Int.Distance(ant.Hex.Coordinates, target.Coordinates) >= 2) { return(false); } MoveAnt(ant, target); return(true); }
private double[] CalculateProbabilities(AntInfo ant) { double sum = 0.0; int count = _data.Vertexes.Count; double[] probabilities = new double[count]; bool[] available = new bool[count]; int currentVertex = ant.CurrentVertex; for (int i = 0; i < count; i++) { if (i == 0 || i == currentVertex || ant.Visited[i] || _data.TruckCapacity < ant.CurrentCapacity + _data.Vertexes[i].Demand) { available[i] = false; } else { available[i] = true; sum += Math.Pow(_pheromones[currentVertex, i], alfa) * Math.Pow(_heuristics[currentVertex, i], beta); } } for (int i = 0; i < count; i++) { if (available[i]) { probabilities[i] = (Math.Pow(_pheromones[currentVertex, i], alfa) * Math.Pow(_heuristics[currentVertex, i], beta)) / sum; } else { probabilities[i] = 0; } } return(probabilities); }
private int FindNewVertex(AntInfo ant) { bool notFound = true; int nextVertex = ant.CurrentVertex; double[] probabilities = CalculateProbabilities(ant); int tries = 1; int maxTries = 10; int count = ant.Visited.Length; int i = _rand.Next(0, count - 1); while (notFound) { i++; if (i >= count) { i = 1; tries++; } if (ant.CurrentVertex == i || ant.Visited[i]) { continue; } if (MyRandom(probabilities[i]) || tries > maxTries) { nextVertex = i; notFound = false; break; } } return(nextVertex); }
private bool MoveToFarTarget(AntInfo ant, HexInfo target) { if (target == null) { return(false); } var farTargets = target.AdjacentSpaces.NonAdjacentTo(target.Coordinates); foreach (var space in farTargets) { var hex = Master.MasterHex.GetHexInfoAt(space); if (hex == null) { continue; } if (MoveToTarget(ant, hex)) { return(true); } } return(false); }
private bool MoveToAnyTarget(AntInfo ant, List <HexInfo> area) { var hex = area.Where(x => x.IsEmpty).RandomElement(); return(MoveToTarget(ant, hex)); }
private void AntAct(AntInfo ant) { var myHex = ant.Hex; var myLocation = myHex.Coordinates; var adjacentHexes = Master.MasterHex.GetNeighboringHexInfo(myLocation.x, myLocation.y, false); var preferHexes = adjacentHexes.Where(x => x.IsPathable).ToList(); HexInfo moveTarget = null; // GENERAL // are we standing next to food? var foodHex = adjacentHexes.FirstOrDefault(x => x.HasPellet); if (foodHex != null) { myHex.FoodInfo.Distance = 1; myHex.FoodInfo.Coordinates = foodHex.Coordinates; myHex.FoodInfo.LastUpdated = Master.GameTurn; } else { var bestFoodHex = adjacentHexes.Where(x => x.FoodInfo.Distance > 0 && x.FoodInfo.Coordinates != myHex.Coordinates && x.FoodInfo.Coordinates != ant.LastLocation && (myHex.FoodInfo.Distance == 0 || myHex.FoodInfo.Distance > x.FoodInfo.Distance)) .OrderBy(x => x.FoodInfo.Distance) .FirstOrDefault(); myHex.FoodInfo.Distance = bestFoodHex == null ? 0 : bestFoodHex.FoodInfo.Distance + 1; myHex.FoodInfo.Coordinates = bestFoodHex == null ? myHex.Coordinates : bestFoodHex.Coordinates; myHex.FoodInfo.LastUpdated = Master.GameTurn; } // can we drop off food? if (ant.HasFood && adjacentHexes.Any(x => x.IsColony)) { // made it home! store the food Destroy(ant.Food); ant.Food = null; ant.HasFood = false; FoodStored++; } // are we standing next to the colony? var homeHex = adjacentHexes.FirstOrDefault(x => x.IsColony); if (homeHex != null) { myHex.HomeInfo.Distance = 1; myHex.HomeInfo.Coordinates = homeHex.Coordinates; myHex.HomeInfo.LastUpdated = Master.GameTurn; } else { var bestHomeHex = adjacentHexes.Where(x => x.HomeInfo.Distance > 0 && x.HomeInfo.Coordinates != myHex.Coordinates && x.HomeInfo.Coordinates != ant.LastLocation && (myHex.HomeInfo.Distance == 0 || myHex.HomeInfo.Distance > x.HomeInfo.Distance)) .OrderBy(x => x.HomeInfo.Distance) .FirstOrDefault(); myHex.HomeInfo.Distance = bestHomeHex == null ? 0 : bestHomeHex.HomeInfo.Distance + 1; myHex.HomeInfo.Coordinates = bestHomeHex == null ? myHex.Coordinates : bestHomeHex.Coordinates; myHex.HomeInfo.LastUpdated = Master.GameTurn; } // EAT if (ant.AllowedEat && ant.IsHungry && FoodStored > 0) { if (adjacentHexes.Any(x => x.IsColony)) { // made it home! de-spawn DespawnAnts.Add(ant); RestingOccupany++; return; // this ant is done } moveTarget = FindHomeTarget(preferHexes); } // GATHER if (ant.AllowedGather && moveTarget == null) { // can we pickup food? if (!ant.HasFood && foodHex != null) { // Pickup the food var food = Master.MasterFood.CurrentFood[foodHex.Coordinates]; Master.MasterFood.CurrentFood.Remove(foodHex.Coordinates); ant.Food = food; ant.HasFood = true; foodHex.HasPellet = false; ant.Food.transform.DOMove(Master.MasterHex.CalculatePosition(ant.Hex.Coordinates.x, ant.Hex.Coordinates.y), 0F) .SetEase(Ease.Linear); } // are we carrying food? if (ant.HasFood) { moveTarget = FindHomeTarget(preferHexes); } // are we looking for food? if (!ant.HasFood) { moveTarget = FindFoodTarget(preferHexes); if (moveTarget != null && myHex.FoodInfo.Distance > 0 && moveTarget.FoodInfo.Distance > 0 && moveTarget.FoodInfo.Distance > myHex.FoodInfo.Distance) { moveTarget = null; // prefer exploration instead of backtracking for food } } } // EXPLORE if (ant.AllowedExplore && moveTarget == null) { moveTarget = FindSearchTarget(preferHexes); } // ANARCHY if (moveTarget == null) { moveTarget = preferHexes.RandomElement(); } // attempt to move to target if (!MoveToTarget(ant, moveTarget)) { // attempt to move near target if (!MoveToNearTarget(ant, moveTarget)) { // move far from target if (!MoveToFarTarget(ant, moveTarget)) { // move anywhere! MoveToAnyTarget(ant, adjacentHexes); } } } }