/// <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); }
/// <summary> /// Выбирает новое состояние на основе текущего состояния мира. /// </summary> public string SelectNewState(AntAICondition aWorldState) { string newState = ""; if (currentGoal != null) { planner.MakePlan(ref currentPlan, aWorldState, currentGoal); if (currentPlan.isSuccess) { string actionName = planner.GetAction(currentPlan[0]).name; newState = planner.GetState(actionName); /* Отладочный вывод плана в консоль. * AntAICondition condition = aConditions.Clone(); * string p = string.Format("Conditions: {0}\n", _planner.NameIt(condition.Description())); * for (int i = 0; i < _currentPlan.Count; i++) * { * AntAIAction action = _planner.GetAction(_currentPlan[i]); * condition.Act(action.post); * p += string.Format("<color=orange>{0}</color> => {1}\n", action.name, _planner.NameIt(condition.Description())); * } * AntLog.Trace(p); * //*/ } } else { AntLog.Report("AntAIAgent", "Goal not defined!"); } return(newState); }
public AntAICondition post; // Current world state. #endregion #region Public Methods public AntAIAction(string aName, int aCost = 1) { cost = aCost; name = aName; state = null; pre = new AntAICondition(); post = new AntAICondition(); }
private void BuildPlanHandler() { // Create planner. var planner = new AntAIPlanner(); // planner.DebugMode = true; planner.LoadScenario(_scenario); // Create current world state and set current conditions. var current = new AntAICondition(); current.BeginUpdate(planner); for (int i = 0, n = _worldState.list.Length; i < n; i++) { current.Set(_scenario.conditions.GetName(_worldState.list[i].id), _worldState.list[i].value); } current.EndUpdate(); // Create our goal world state. AntAIScenarioGoal defaultGoal = null; for (int i = 0, n = _scenario.goals.Length; i < n; i++) { if (_scenario.goals[i].isDefault) { defaultGoal = _scenario.goals[i]; break; } } A.Assert(defaultGoal == null, "Default goal not found!"); if (defaultGoal == null) { return; } // Copy conditions from the scenario goal to the goal conditions. var goal = new AntAICondition(); goal.BeginUpdate(planner); for (int i = 0, n = defaultGoal.conditions.Length; i < n; i++) { goal.Set(_scenario.conditions.GetName(defaultGoal.conditions[i].id), defaultGoal.conditions[i].value); } goal.EndUpdate(); // Create and build the plan. var plan = new AntAIPlan(); planner.MakePlan(ref plan, current, goal); // Call event when plan is ready. if (EventBuildPlan != null) { EventBuildPlan(this, plan, planner); } }
public bool IsFinished(AntAIAgent aAgent, AntAICondition aWorldState) { if (_isFinished || OverlapInterrupts(aAgent.planner, aWorldState)) { Reset(); return(true); } return(false); }
/// <summary> /// Устанавливает указанную цель как текущую. /// </summary> public void SetGoal(string aGoalName) { currentGoal = FindGoal(aGoalName); if (currentGoal == null) { AntLog.Report("AIControl", "Can't find \"{0}\" goal.", aGoalName); SetDefaultGoal(); } }
public AntAICondition defaultGoal; // Цель по умолчанию. public AntAIAgent() { sense = null; currentState = null; defaultState = null; worldState = new AntAICondition(); planner = new AntAIPlanner(); currentPlan = new AntAIPlan(); currentGoal = null; }
/// <summary> /// Устанавливает цель по умолчанию как текущее. /// </summary> public void SetDefaultGoal() { if (defaultGoal != null) { currentGoal = defaultGoal; } else { AntLog.Report("AIControl", "Default Goal not defined!"); } }
private int FindEqual(List <AntAINode> aList, AntAICondition aCondition) { for (int i = 0, n = aList.Count; i < n; i++) { if (aList[i].world.Equals(aCondition)) { return(i); } } return(-1); }
/// <summary> /// Устанавливает цель по умолчанию как текущее. /// </summary> public void SetDefaultGoal() { if (defaultGoal != null) { currentGoal = defaultGoal; } else { AntLog.Report("AntAIAgent", "Default <b>Goal</b> is not defined!"); } }
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> /// Gets goal by goal name. /// </summary> /// <param name="aGoalName">Goal name.</param> /// <returns>Returns goal by name. If goal not found, will be created new one.</returns> public AntAICondition GetGoal(string aGoalName) { var goal = FindGoal(aGoalName); if (goal == null) { goal = new AntAICondition { name = aGoalName }; goals.Add(goal); } return(goal); }
private List <AntAIAction> GetPossibleTransitions(AntAICondition aCurrent) { var possible = new List <AntAIAction>(); for (int i = 0, n = actions.Count; i < n; i++) { if (actions[i].pre.Match(aCurrent)) { possible.Add(actions[i]); } } return(possible); }
public bool OverlapInterrupts(AntAIPlanner aPlanner, AntAICondition aConditions) { int index = -1; for (int i = 0, n = _interruptions.Count; i < n; i++) { index = aPlanner.GetAtomIndex(_interruptions[i]); if (aConditions.GetValue(index)) { return(true); } } return(false); }
/// <summary> /// Checking if current world state is equal interruption settings. /// </summary> /// <param name="aAgent">Ref to the AntAIAgent.</param> /// <param name="aWorldState">Current world state.</param> /// <returns></returns> public bool OverlapInterrupts(AntAIAgent aAgent, AntAICondition aWorldState) { int index = -1; for (int i = 0, n = _interruptions.Count; i < n; i++) { index = aAgent.planner.GetAtomIndex(_interruptions[i]); if (aWorldState.GetValue(index)) { return(true); } } return(false); }
/// <summary> /// Описывает состояние. /// </summary> private void DescribeCondition(AntAICondition aCondition, ref List <string> aResult) { bool value; for (int i = 0; i < AntAIPlanner.MAX_ATOMS; i++) { if (aCondition.GetMask(i)) { value = aCondition.GetValue(i); aResult.Add(string.Format(" '<color={2}>{0}</color>' = <color={2}>{1}</color>", _agent.planner.atoms[i], value, (value) ? _trueColor : _falseColor)); } } }
/// <summary> /// Обновляет информацию уже существующей ноды описывающей состояние мира (условий ИИ). /// </summary> private void UpdateWorldStateNode(AntAICondition aCondition, AntAIDebuggerNode aNode) { List <string> desc = new List <string>(); desc.Add(string.Format("<b><color={0}>WORLD STATE</color></b>", _titleColor)); desc.Add(" <b>Current Conditions</b>"); DescribeCondition(aCondition, ref desc); StringBuilder text = new StringBuilder(); for (int i = 0, n = desc.Count; i < n; i++) { text.AppendLine(desc[i]); } aNode.title = text.ToString(); aNode.rect.height = CalcHeight(desc.Count); }
/// <summary> /// Создает новую ноду описывающую поставленную задачу (состояния к которым стримится ИИ). /// </summary> private AntAIDebuggerNode CreateGoalNode(AntAICondition aGoal, ref Vector2 aNodePosition) { List <string> desc = new List <string>(); desc.Add(string.Format("<b><color={1}>GOAL</color> '<color={2}>{0}</color>'</b>", aGoal.name, _titleColor, _nameColor)); desc.Add(" <b>Tends to conditions</b>"); DescribeCondition(aGoal, ref desc); StringBuilder text = new StringBuilder(); for (int i = 0, n = desc.Count; i < n; i++) { text.AppendLine(desc[i]); } return(AddNode(text.ToString(), 220.0f, CalcHeight(desc.Count), _goalStyle, _activeGoalStyle, ref aNodePosition)); }
public void BindData(string aTitle, AntAIPlanner aPlanner, AntAICondition aCur, AntAICondition aPre) { title = string.Concat("▶ ", aTitle); _items = new List <Item>(); bool v; for (int i = 0, n = AntAIPlanner.MAX_ATOMS; i < n; i++) { if (aCur.GetMask(i)) { v = aCur.GetValue(i); _items.Add(new Item { name = aPlanner.atoms[i], value = v, isChanged = (v != aPre.GetValue(i)) }); } } }
/// <summary> /// Создает новую ноду описывающуюу текущее состояние мира (условия ИИ). /// </summary> private AntAIDebuggerNode CreateWorldStateNode(AntAICondition aCondition, ref Vector2 aNodePosition) { List <string> desc = new List <string>(); desc.Add(string.Format("<b><color={0}>WORLD STATE</color></b>", _titleColor)); desc.Add(" <b>Current Conditions</b>"); DescribeCondition(aCondition, ref desc); StringBuilder text = new StringBuilder(); for (int i = 0, n = desc.Count; i < n; i++) { text.AppendLine(desc[i]); } var node = AddNode(text.ToString(), 220.0f, CalcHeight(desc.Count), _nodeStyle, _nodeStyle, ref aNodePosition, false); node.SetOutput(node.rect.width - 10.0f, node.rect.height * 0.5f); node.SetInput(10.0f, node.rect.height * 0.5f); _genericNodes.Add(node); return(node); }
/// <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> /// Описывает конкретное действие из плана ИИ. /// </summary> private string DescribePlanAction(AntAICondition aCur, AntAICondition aPre, out int aNumLines) { var lines = new List <string>(); lines.Add(string.Format("<b><color={1}>ACTION</color> '<color={2}>{0}</color>'</b>", aCur.name, _titleColor, _nameColor)); lines.Add(" <b>Post Conditions</b>"); bool value; for (int j = 0; j < AntAIPlanner.MAX_ATOMS; j++) { if (aCur.GetMask(j)) { value = aCur.GetValue(j); if (value != aPre.GetValue(j)) { lines.Add(string.Format(" <color=#a873dd><b>></b></color> <i>'<color={2}>{0}</color>' = <color={2}>{1}</color></i>", _agent.planner.atoms[j], value, (value) ? _trueColor : _falseColor)); } else { lines.Add(string.Format(" '<color={2}>{0}</color>' = <color={2}>{1}</color>", _agent.planner.atoms[j], value, (value) ? _trueColor : _falseColor)); } } } StringBuilder text = new StringBuilder(); for (int i = 0, n = lines.Count; i < n; i++) { text.AppendLine(lines[i]); } aNumLines = lines.Count; return(text.ToString()); }
public bool IsFinished(AntAIAgent aAgent, AntAICondition aWorldState) { return(_isFinished || OverlapInterrupts(aAgent.planner, aWorldState)); }
/// <summary> /// Определяет какая цель будет целью по умолчанию. /// </summary> public void DefaultGoalIs(string aGoalName) { defaultGoal = FindGoal(aGoalName); }
/// <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); } }