/// <summary> /// Создает новую ноду описывающую конкретное действие из плана ИИ. /// </summary> private AntAIDebuggerNode CreatePlanNode(AntAIAction aAction, AntAICondition aConditions, AntAICondition aPrevConditions, ref Vector2 aNodePosition) { AntAICondition condCopy = aConditions.Clone(); condCopy.name = aAction.name; int numLines; string desc = DescribePlanAction(condCopy, aPrevConditions, out numLines); GUIStyle style; if (_currentPlan.isSuccess) { style = (aAction.name.Equals(_agent.currentPlan[0])) ? _activePlanStyle : _planStyle; } else { style = (aAction.name.Equals(_agent.currentPlan[0])) ? _activeFailedPlanStyle : _failedPlanStyle; } var node = AddNode(desc, 220.0f, CalcHeight(numLines), style, style, ref aNodePosition, false); node.value = aAction.state; node.SetOutput(node.rect.width - 10.0f, node.rect.height * 0.5f); node.SetInput(10.0f, node.rect.height * 0.5f); if (_genericNodes.Count > 0) { _genericNodes[_genericNodes.Count - 1].LinkTo(node, new Color(0.3f, 0.7f, 0.4f)); } _genericNodes.Add(node); return(node); }
private void UpdatePlan(Vector2 aNodePosition, out float aMaxHeight) { for (int i = 0, n = _genericNodes.Count; i < n; i++) { _genericNodes[i].isActive = false; } aMaxHeight = 0.0f; int curIndex = 0; AntAIDebuggerNode node; if (_genericNodes.Count > 0) { node = _genericNodes[curIndex]; UpdateWorldStateNode(_agent.planner.debugConditions, node); node.isActive = true; node.rect.x = aNodePosition.x; aNodePosition.x += node.rect.width; } else { node = CreateWorldStateNode(_agent.planner.debugConditions, ref aNodePosition); } curIndex++; AntAIAction action; AntAICondition conditions = _agent.planner.debugConditions; AntAICondition prevConditions; for (int i = 0, n = _currentPlan.Count; i < n; i++) { action = _agent.planner.GetAction(_currentPlan[i]); prevConditions = conditions.Clone(); conditions.Act(action.post); if (curIndex < _genericNodes.Count) { node = _genericNodes[curIndex]; UpdatePlanNode(action, conditions, prevConditions, node); node.isActive = true; node.rect.x = aNodePosition.x; aNodePosition.x += node.rect.width; } else { node = CreatePlanNode(action, conditions, prevConditions, ref aNodePosition); } aMaxHeight = (node.rect.height > aMaxHeight) ? node.rect.height : aMaxHeight; curIndex++; } }
/// <summary> /// Обновляет ноду описывающую конкретное действие из плана ИИ. /// </summary> private void UpdatePlanNode(AntAIAction aAction, AntAICondition aConditions, AntAICondition aPrevConditions, AntAIDebuggerNode aNode) { AntAICondition condCopy = aConditions.Clone(); condCopy.name = aAction.name; aNode.value = aAction.state; int numLines; aNode.title = DescribePlanAction(condCopy, aPrevConditions, out numLines); aNode.rect.height = CalcHeight(numLines); if (_currentPlan.isSuccess) { aNode.defaultNodeStyle = (aAction.name.Equals(_agent.currentPlan[0])) ? _activePlanStyle : _planStyle; } else { aNode.defaultNodeStyle = (aAction.name.Equals(_agent.currentPlan[0])) ? _activeFailedPlanStyle : _failedPlanStyle; } }
/// <summary> /// Builds the plan. /// </summary> /// <param name="aPlan">Reference to the result Plan.</param> /// <param name="aCurrent">Current World State.</param> /// <param name="aGoal">Goal World State that we want reach.</param> public void MakePlan(ref AntAIPlan aPlan, AntAICondition aCurrent, AntAICondition aGoal) { #if UNITY_EDITOR DebugConditions = aCurrent.Clone(); #endif var opened = new List <AntAINode>(); var closed = new List <AntAINode>(); opened.Add(new AntAINode { world = aCurrent, parent = null, cost = 0, heuristic = aCurrent.Heuristic(aGoal), sum = aCurrent.Heuristic(aGoal), action = string.Empty }); AntAINode current = opened[0]; while (opened.Count > 0) { // Find lowest rank. current = opened[0]; for (int i = 1, n = opened.Count; i < n; i++) { if (opened[i].sum < current.sum) { current = opened[i]; } } opened.Remove(current); if (current.world.Match(aGoal)) { // Plan is found! ReconstructPlan(ref aPlan, closed, current); aPlan.isSuccess = true; if (EventPlanUpdated != null) { EventPlanUpdated(aPlan); } return; } closed.Add(current); // Get neighbors. List <AntAIAction> neighbors = GetPossibleTransitions(current.world); AntAICondition neighbor; int openedIndex = -1; int closedIndex = -1; int cost = -1; for (int i = 0, n = neighbors.Count; i < n; i++) { cost = current.cost + neighbors[i].cost; neighbor = current.world.Clone(); neighbor.Act(neighbors[i].post); openedIndex = FindEqual(opened, neighbor); closedIndex = FindEqual(closed, neighbor); if (openedIndex > -1 && cost < opened[openedIndex].cost) { opened.RemoveAt(openedIndex); openedIndex = -1; } if (closedIndex > -1 && cost < closed[closedIndex].cost) { closed.RemoveAt(closedIndex); closedIndex = -1; } if (openedIndex == -1 && closedIndex == -1) { opened.Add(new AntAINode { world = neighbor, cost = cost, heuristic = neighbor.Heuristic(aGoal), sum = cost + neighbor.Heuristic(aGoal), action = neighbors[i].name, parent = current.world }); } } } // Failed plan. ReconstructPlan(ref aPlan, closed, current); aPlan.isSuccess = false; if (EventPlanUpdated != null) { EventPlanUpdated(aPlan); } }