/// <summary> /// Determines the best delivery task for the given bot, and allocates the required resources. /// </summary> /// <param name="bot">The bot to consider.</param> /// <param name="bestPod">The pod to use for the best delivery task.</param> /// <param name="bestItemDescription">The type of the item to use for the best delivery task.</param> /// <param name="bestRequest">The request to use for the best delivery task.</param> /// <param name="bestStation">The station to use for the best delivery task.</param> /// <param name="bestStorageLocationOldPod">The storage location for the current pod to use for the best delivery task.</param> public void GetBestDeliveryTask(Bot bot, out ExtractRequest bestRequest, out Pod bestPod, out ItemDescription bestItemDescription, out OutputStation bestStation, out Waypoint bestStorageLocationOldPod) { // Find an item to retrieve double bestTaskDistance = double.PositiveInfinity; bestPod = null; bestStorageLocationOldPod = null; // Try with the current pod ExtractRequest bestExtractTask; double bestExtractDistance; GetBestTaskForPod(bot, bot.Pod, bot.CurrentWaypoint, out bestExtractTask, out bestExtractDistance); bestRequest = bestExtractTask; if (bestRequest != null) { bestTaskDistance = bestExtractDistance; bestPod = bot.Pod; } // Distance to pick up the pod // double baseTime = bot.PodTransferTime; // Time to set down the current pod if it has one // if (bot.Pod != null) // baseTime += bot.PodTransferTime; foreach (var pod in Instance.ResourceManager.UnusedPods) { double distance = 0; Waypoint bestStorageLocationForThisPod = null; // If need to set down current pod if (bot.Pod != null) { // Grab this once to pull it out of the loop Waypoint targetPodWaypoint = pod.Waypoint; double minStorageDistance = double.PositiveInfinity; foreach (var storageLocation in Instance.ResourceManager.UnusedPodStorageLocations) { // Need time to set down current pod and also pick up new pod double storeDistance = 0; // Find Distance to get to storage location storeDistance += Estimators.EstimateTravelDistanceEuclid(bot, storageLocation); // Find time to get from storage location to new pod storeDistance += Estimators.EstimateTravelDistanceEuclid(bot, storageLocation, targetPodWaypoint); if (storeDistance < minStorageDistance) { minStorageDistance = storeDistance; bestStorageLocationForThisPod = storageLocation; } } // Use the best waypoint distance += minStorageDistance; } else { // No pod, just go pick it up distance += Estimators.EstimateTravelDistanceEuclid(bot, pod.Waypoint); } // Get place to take the pod GetBestTaskForPod(bot, pod, pod.Waypoint, out bestExtractTask, out bestExtractDistance); if (bestExtractTask != null) { // If the time is still better, then count it if (distance + bestExtractDistance < bestTaskDistance) { bestRequest = bestExtractTask; bestTaskDistance = distance + bestExtractDistance; bestPod = pod; bestStorageLocationOldPod = bestStorageLocationForThisPod; } } } // If found no task, take the oldest if (bestRequest == null) { bestRequest = Instance.ResourceManager.AvailableAndAssignedExtractRequests.First(); } bestItemDescription = bestRequest.Item; bestStation = bestRequest.Station; }