public GoapGoal GetGoalByID(int id) { IDataReader goalReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT goap_goals.* " + "FROM goap_goals " + "WHERE goap_goals.id = '" + id + "'"); while(goalReader.Read()) { string goalName = goalReader.GetString(1); GoapGoal goal = new GoapGoal(); goal.Name = goalName; //query for conditions for each goal IDataReader condReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT world_states.*, goal_conditions.* " + "FROM goal_conditions INNER JOIN world_states " + "ON goal_conditions.world_state_id = world_states.id AND goal_conditions.goal_id = '" + id + "'"); List<GoapWorldState> conditions = new List<GoapWorldState>(); while(condReader.Read()) { GoapWorldState state = ParseWorldState(condReader); conditions.Add(state); } condReader.Close(); condReader = null; goal.GoalStates = conditions; return goal; } return null; }
private void AddGoal(GoapGoal goal) { if (_goals.Count < 5) { _goals.Add(goal); } }
public GoapGoal GetGoalByID(int id) { IDataReader goalReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT goap_goals.* " + "FROM goap_goals " + "WHERE goap_goals.id = '" + id + "'"); while (goalReader.Read()) { string goalName = goalReader.GetString(1); GoapGoal goal = new GoapGoal(); goal.Name = goalName; //query for conditions for each goal IDataReader condReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT world_states.*, goal_conditions.* " + "FROM goal_conditions INNER JOIN world_states " + "ON goal_conditions.world_state_id = world_states.id AND goal_conditions.goal_id = '" + id + "'"); List <GoapWorldState> conditions = new List <GoapWorldState>(); while (condReader.Read()) { GoapWorldState state = ParseWorldState(condReader); conditions.Add(state); } condReader.Close(); condReader = null; goal.GoalStates = conditions; return(goal); } return(null); }
IEnumerator WaitAndCheckImportantEvent(float waitTime, float priority) { yield return(new WaitForSeconds(waitTime)); if (ControlType == AIControlType.Player) { yield return(0); } //when an important event happens, stop current action and reevaluate all the goals and pick the highest priority goal //Debug.Log("Triggering important event " + _parentCharacter.name); if (_currentAction != null) { if (_currentAction.AbortAction(priority)) { _currentAction = null; _currentGoal = null; FindAndExecuteAction(); } } else { _currentGoal = null; FindAndExecuteAction(); } }
public void OnGUI() { if (goalSet == null) { return; } GoapGoal newPickedGoal = null; foreach (GoapGoal goal in goalSet) { GUILayout.BeginHorizontal(); GUILayout.Label(goal.Name, GUI.skin.label); if (GUILayout.Button("Activate")) { newPickedGoal = goal; } GUILayout.EndHorizontal(); } if (newPickedGoal != null) { foreach (GoapGoal goal in goalSet) { goal.enabled = (goal == newPickedGoal); } GameObject.FindObjectOfType <GoapAgent>().WarnGoalEnd(newPickedGoal); } }
public void ForceStopCurrentAction() { if (_currentAction != null) { _currentAction.StopAction(); } _currentAction = null; _currentGoal = null; }
public override bool CheckActionCompletion() { if (!_readyForCompletion) { return(false); } if (ParentCharacter.MyAI.BlackBoard.GuardLevel == 0) { return(true); } if (ParentCharacter.MyAI.BlackBoard.TargetEnemy == null) { return(true); } Weapon currentWeapon = ParentCharacter.MyAI.WeaponSystem.GetCurrentWeapon(); //CsDebug.Inst.CharLog(ParentCharacter, "current weapon " + currentWeapon); if (currentWeapon == null) { return(true); } //if top priority goal is follow, check if i'm too far from follow target or guard target GoapGoal top = ParentCharacter.MyAI.GetDynamicGoal(0); if (top != null && top.Name == "Follow target" && ParentCharacter.MyAI.BlackBoard.GuardLevel <= 0) { if (Vector3.Distance(ParentCharacter.transform.position, ParentCharacter.MyAI.BlackBoard.FollowTarget.transform.position) > 6) { return(true); } } foreach (GoapWorldState state in Effects) { object result = ParentCharacter.MyAI.EvaluateWorldState(state); CsDebug.Inst.CharLog(ParentCharacter, "Checking if state " + state.Name + " value is " + state.Value + " result: " + result); if (!result.Equals(state.Value)) { //CsDebug.Inst.CharLog(ParentCharacter, "result is not equal to effect"); return(false); } } return(true); }
public void Initialize() { _allCharacters = new List<Character>(); _humansInScene = new List<HumanCharacter>(); _mutantsInScene = new List<MutantCharacter>(); DynamicGoalGuard = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(6); DynamicGoalGuard.Priority = 5; DynamicGoalFollow = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(8); DynamicGoalFollow.Priority = 5; DynamicGoalPatrol = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(2); DynamicGoalPatrol.Priority = 5; }
/** * Create a subset of the actions excluding the removeMe one. Creates a new set. */ private static HashSet <GoapGoal> ActionSubset(HashSet <GoapGoal> actions, GoapGoal removeMe) { HashSet <GoapGoal> subset = new HashSet <GoapGoal>(); foreach (GoapGoal a in actions) { if (!a.Equals(removeMe)) { subset.Add(a); } } return(subset); }
public void Initialize(Character character) { _parentCharacter = character; WorkingMemory = new WorkingMemory(); WorkingMemory.Initialize(_parentCharacter); BlackBoard = new BlackBoard(); Sensor = new AISensor(); Sensor.Initialize(_parentCharacter); TargetingSystem = new AITargeting(); TargetingSystem.Initialize(_parentCharacter); WeaponSystem = new AIWeapon(); WeaponSystem.Initialize(_parentCharacter); Planner = new GoapPlanner(this); _goals = GameManager.Inst.DBManager.DBHandlerAI.GetCharacterGoalSet(_parentCharacter.GoapID); _actions = GameManager.Inst.DBManager.DBHandlerAI.GetCharacterActionSet(_parentCharacter.GoapID); _currentWorldStates = new List <GoapWorldState>(); _parentCharacter.MyEventHandler.OnCurrentActionComplete -= OnCurrentActionComplete; _parentCharacter.MyEventHandler.OnCurrentActionComplete += OnCurrentActionComplete; _parentCharacter.MyEventHandler.OnPerFrameTimer -= PerFrameUpdate; _parentCharacter.MyEventHandler.OnPerFrameTimer += PerFrameUpdate; //update parent character for each action foreach (GoapAction action in _actions) { action.ParentCharacter = _parentCharacter; } //BlackBoard.PatrolLoc = new Vector3(63.9f, 0.3f, -13.3f); //BlackBoard.PatrolRange = new Vector3(30, 10, 15); if (ControlType != AIControlType.Player) { BlackBoard.GuardLevel = 1; _parentCharacter.SendCommand(CharacterCommands.SetAlert); } _currentGoal = null; _currentAction = null; _parentCharacter.MyEventHandler.OnOneSecondTimer += OnOneSecondTimer; }
public void ClearDynamicGoal(int priority) { //CsDebug.Inst.CharLog(_parentCharacter, "Clearing top priority goal for " + _parentCharacter.name); List <GoapGoal> goalsCopy = new List <GoapGoal>(_goals); foreach (GoapGoal goal in goalsCopy) { if (goal.Priority == priority) { if (_currentGoal == goal) { _currentAction.StopAction(); } _goals.Remove(goal); _currentAction = null; _currentGoal = null; FindAndExecuteAction(); } } }
public List <GoapGoal> GetCharacterGoalSet(int characterID) { IDataReader goalReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT goap_goals.*, character_goals.priority " + "FROM goap_goals INNER JOIN character_goals " + "ON goap_goals.id = character_goals.goal_id AND character_goals.character_id = '" + characterID + "'"); List <GoapGoal> goals = new List <GoapGoal>(); while (goalReader.Read()) { int goalID = goalReader.GetInt32(0); string goalName = goalReader.GetString(1); int priority = goalReader.GetInt32(2); GoapGoal goal = new GoapGoal(); goal.Name = goalName; goal.Priority = priority; //query for conditions for each goal IDataReader condReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT world_states.*, goal_conditions.* " + "FROM goal_conditions INNER JOIN world_states " + "ON goal_conditions.world_state_id = world_states.id AND goal_conditions.goal_id = '" + goalID + "'"); List <GoapWorldState> conditions = new List <GoapWorldState>(); while (condReader.Read()) { GoapWorldState state = ParseWorldState(condReader); conditions.Add(state); } condReader.Close(); condReader = null; goal.GoalStates = conditions; goals.Add(goal); } goalReader.Close(); goalReader = null; return(goals); }
private bool EvaluateGoal(GoapGoal goal) { //check which goal's conditions are met bool isGoalMet = true; foreach (GoapWorldState state in goal.GoalStates) { object value = EvaluateWorldState(state); CsDebug.Inst.CharLog(_parentCharacter, "Evaluating Goal; current value " + value + " target value " + state.Value); if (!UnityEngine.Object.Equals(value, state.Value)) { CsDebug.Inst.CharLog(_parentCharacter, "Evaluating goal result: values don't match"); //this goal isn't met! isGoalMet = false; return(isGoalMet); } } return(isGoalMet); }
private GoapGoal GetNextGoal() { GoapGoal result = null; if (_currentGoal == null) { //get the highest priority goal GoapGoal goal = _goals.OrderBy(p => p.Priority).FirstOrDefault(); result = goal; } else { //get the goal that's next highest than current goal var intermediate = (from g in _goals where g.Priority >= _currentGoal.Priority && g != _currentGoal orderby g.Priority select g); GoapGoal goal = intermediate.FirstOrDefault(); result = goal; } return(result); }
public List<GoapGoal> GetCharacterGoalSet(int characterID) { IDataReader goalReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT goap_goals.*, character_goals.priority " + "FROM goap_goals INNER JOIN character_goals " + "ON goap_goals.id = character_goals.goal_id AND character_goals.character_id = '" + characterID + "'"); List<GoapGoal> goals = new List<GoapGoal>(); while(goalReader.Read()) { int goalID = goalReader.GetInt32(0); string goalName = goalReader.GetString(1); int priority = goalReader.GetInt32(2); GoapGoal goal = new GoapGoal(); goal.Name = goalName; goal.Priority = priority; //query for conditions for each goal IDataReader condReader = GameManager.Inst.DBManager.RunAIQuery( "SELECT world_states.*, goal_conditions.* " + "FROM goal_conditions INNER JOIN world_states " + "ON goal_conditions.world_state_id = world_states.id AND goal_conditions.goal_id = '" + goalID + "'"); List<GoapWorldState> conditions = new List<GoapWorldState>(); while(condReader.Read()) { GoapWorldState state = ParseWorldState(condReader); conditions.Add(state); } condReader.Close(); condReader = null; goal.GoalStates = conditions; goals.Add(goal); } goalReader.Close(); goalReader = null; return goals; }
public void GetNewPlan() { ClearPlan(); foreach (GoapAction action in AvailableActions) { action.ResetAction(); } List <GoapGoal> orderedGoals = myUtilityEngine.RunUtilityEngine(); UpdateWorldState(); if (orderedGoals.Count > 0) { bool FoundGoalPath = false; int i = 0; while (FoundGoalPath == false) { CurrentGoal = orderedGoals[i]; ActionPlan = myPlanner.GoapPlan(this); if (ActionPlan == null) { // no plan found. ++i; if (i >= orderedGoals.Count) { // end the loop if no path can be found to any goal. FoundGoalPath = true; } } else { // plan found GetNextAction(); FoundGoalPath = true; } } } }
public void Initialize() { GameObject playerObj = GameManager.Instantiate(Resources.Load("PlayerCharacter")) as GameObject; SelectedMember = playerObj.GetComponent <HumanCharacter>(); //SelectedMember = GameObject.Find("PlayerCharacter").GetComponent<HumanCharacter>(); SelectedMember.Initialize(); //SelectedMember.MyNavAgent.enabled = true; RefreshMarkerForMember(SelectedMember); /* * HumanCharacter member2 = GameObject.Find("HumanCharacter3").GetComponent<HumanCharacter>(); * member2.Initialize(); * RefreshMarkerForMember(member2); * * * //for testing * member2.MyAI.BlackBoard.FollowTarget = SelectedMember; */ Members.Add(SelectedMember); //Members.Add(member2); MemberGuardGoal = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(6); MemberGuardGoal.Priority = 0; MemberFollowGoal = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(8); MemberFollowGoal.Priority = 0; //initialize inventory and then load weapons to prefab GameManager.Inst.ItemManager.LoadPartyInventory(); RefreshAllMemberWeight(); RefreshAllMemberArmors(); RefreshAllMemberWeapons(); }
public void OnDeath() { if (_currentAction != null) { _currentAction.AbortAction(1); _currentAction = null; } _currentGoal = null; _parentCharacter.MyEventHandler.OnOneSecondTimer -= OnOneSecondTimer; _parentCharacter.MyEventHandler.OnCurrentActionComplete -= OnCurrentActionComplete; _parentCharacter.MyEventHandler.OnPerFrameTimer -= PerFrameUpdate; TargetingSystem.OnDeath(); Sensor.OnDeath(); WorkingMemory.OnDeath(); if (Squad != null) { Squad.RemoveMember(_parentCharacter); } }
public void SetDynamicyGoal(GoapGoal newGoal, int priority) { //CsDebug.Inst.CharLog(_parentCharacter, "Setting top priority goal " + newGoal.Name + " for " + _parentCharacter.name); List <GoapGoal> goalsCopy = new List <GoapGoal>(_goals); foreach (GoapGoal goal in goalsCopy) { if (goal.Priority == priority) { _goals.Remove(goal); } } _goals.Add(newGoal); if (_currentAction != null) { _currentAction.StopAction(); } _currentAction = null; _currentGoal = newGoal; FindAndExecuteAction(); }
public void SetDynamicyGoal(GoapGoal newGoal, int priority) { //CsDebug.Inst.CharLog(_parentCharacter, "Setting top priority goal " + newGoal.Name + " for " + _parentCharacter.name); List<GoapGoal> goalsCopy = new List<GoapGoal>(_goals); foreach(GoapGoal goal in goalsCopy) { if(goal.Priority == priority) { _goals.Remove(goal); } } _goals.Add(newGoal); if(_currentAction != null) { _currentAction.StopAction(); } _currentAction = null; _currentGoal = newGoal; FindAndExecuteAction(); }
public GoalNode(GoapGoal goal, int depth, Node neighbour, FactSet dataSet, GUIStyle nodeStyle, GUIStyle activeStyle, GUIStyle blockedStyle) : base(null, depth, neighbour, dataSet, nodeStyle, activeStyle, blockedStyle) { this.goal = goal; AddChilds(goal.childs); }
private void RefreshCharactersTab() { IDataReader reader = RunQuery("SELECT characters.* FROM characters"); Dictionary<int, CharacterData> characters = new Dictionary<int, CharacterData>(); int i = 1; while(reader.Read()) { int c_id = reader.GetInt32(0); string c_title = reader.GetString(1); string c_first = reader.GetString(2); string c_last = reader.GetString(3); CharacterData data = new CharacterData(); data.ID = c_id; data.Title = c_title; data.FirstName = c_first; data.LastName = c_last; characters.Add(i, data); i++; } string [] dropDownOptions = new string[characters.Count + 1]; dropDownOptions[0] = "None"; if(characters.Count > 0) { for(int index=1; index <= characters.Count; index++) { dropDownOptions[index] = characters[index].Title + ", " + characters[index].FirstName + " " + characters[index].LastName; } } GUI.Label(new Rect(10, 40, 200, 20), "Characters:"); _tab3Char = EditorGUI.Popup(new Rect(10, 60, 250, 20), _tab3Char, dropDownOptions); if(_tab3Char > 0) { //now we have the character ID, we make a list of character goals IDataReader goalReader = RunQuery( "SELECT goap_goals.*, character_goals.priority " + "FROM goap_goals INNER JOIN character_goals " + "ON goap_goals.id = character_goals.goal_id AND character_goals.character_id = '" + characters[_tab3Char].ID + "'"); List<GoapGoal> goals = new List<GoapGoal>(); while(goalReader.Read()) { int goalID = goalReader.GetInt32(0); string goalName = goalReader.GetString(1); int priority = goalReader.GetInt32(2); GoapGoal goal = new GoapGoal(); goal.Name = goalName; goal.Priority = priority; goals.Add(goal); } IDataReader allGoalsReader = RunQuery("SELECT goap_goals.* FROM goap_goals"); Dictionary<int, GoalData> allGoals = new Dictionary<int, GoalData>(); int goalIndex = 0; while(allGoalsReader.Read()) { int c_id = allGoalsReader.GetInt32(0); string c_desc = allGoalsReader.GetString(1); GoalData data = new GoalData(); data.ID = c_id; data.Description = c_desc; allGoals.Add(goalIndex, data); goalIndex++; } GUI.Label(new Rect(10, 90, 150, 20), "Goals:"); int rectHeight = 110; int heightStep = 20; int gIndex = 0; foreach(GoapGoal goal in goals) { int selectedName = 0; int selectedPriority = 0; string [] options = new string[allGoals.Count]; for(int index=0; index < allGoals.Count; index++) { options[index] = allGoals[index].Description; if(goal.Name == allGoals[index].Description) { selectedName = index; selectedPriority = goal.Priority; } } int height = rectHeight + gIndex * heightStep; int newSelectedName = EditorGUI.Popup(new Rect(10, height, 150, 20), selectedName, options); GUI.Label(new Rect(170, height, 40, 20), "Priority"); int newSelectedPriority = EditorGUI.Popup(new Rect(220, height, 60, 20), selectedPriority, new string[]{"0", "1", "2", "3", "4", "5"}); bool toBeUpdated = false; if(newSelectedName != selectedName || newSelectedPriority != selectedPriority) { toBeUpdated = true; } bool toBeDeleted = false; if(GUI.Button(new Rect(290, height, 15, 15), "-")) { toBeDeleted = true; } if(toBeUpdated) { RunQuery("UPDATE character_goals SET goal_id = " + allGoals[newSelectedName].ID + ", priority = " + newSelectedPriority + " WHERE character_id = " + characters[_tab3Char].ID + " AND goal_id = " + allGoals[selectedName].ID); } if(toBeDeleted) { RunQuery("DELETE FROM character_goals WHERE goal_id = " + allGoals[newSelectedName].ID + " AND character_id = " + characters[_tab3Char].ID); } gIndex ++; } rectHeight = rectHeight + heightStep * goals.Count; //a button to add new condition if(GUI.Button(new Rect(290, rectHeight, 20, 20), "+")) { RunQuery("INSERT INTO character_goals (character_id, goal_id, priority) VALUES (" + characters[_tab3Char].ID + ", " + allGoals[0].ID + ", 0)"); } //now we have the character ID, we make a list of character actions IDataReader actionReader = RunQuery( "SELECT goap_actions.* " + "FROM goap_actions INNER JOIN character_actions " + "ON goap_actions.id = character_actions.action_id AND character_actions.character_id = '" + characters[_tab3Char].ID + "'"); List<ActionData> actions = new List<ActionData>(); while(actionReader.Read()) { int id = actionReader.GetInt32(0); string className = actionReader.GetString(1); string description = actionReader.GetString(2); float cost = actionReader.GetFloat(3); ActionData action = new ActionData(); action.ID = id; action.ClassName = className; action.Description = description; action.DefaultCost = cost; actions.Add(action); } IDataReader allActionsReader = RunQuery("SELECT goap_actions.* FROM goap_actions"); Dictionary<int, ActionData> allActions = new Dictionary<int, ActionData>(); int actionIndex = 0; while(allActionsReader.Read()) { int c_id = allActionsReader.GetInt32(0); string c_desc = allActionsReader.GetString(2); ActionData data = new ActionData(); data.ID = c_id; data.Description = c_desc; allActions.Add(actionIndex, data); actionIndex++; } rectHeight = rectHeight + 30; GUI.Label(new Rect(10, rectHeight, 150, 20), "Actions:"); rectHeight += 20; int aIndex = 0; foreach(ActionData action in actions) { int selectedName = 0; string [] options = new string[allActions.Count]; for(int index=0; index < allActions.Count; index++) { options[index] = allActions[index].Description; if(action.Description == allActions[index].Description) { selectedName = index; } } int height = rectHeight + aIndex * heightStep; int newSelectedName = EditorGUI.Popup(new Rect(10, height, 150, 20), selectedName, options); bool toBeUpdated = false; if(newSelectedName != selectedName) { toBeUpdated = true; } bool toBeDeleted = false; if(GUI.Button(new Rect(290, height, 15, 15), "-")) { toBeDeleted = true; } if(toBeUpdated) { RunQuery("UPDATE character_actions SET action_id = " + allActions[newSelectedName].ID + " WHERE character_id = " + characters[_tab3Char].ID + " AND action_id = " + allActions[selectedName].ID); } if(toBeDeleted) { RunQuery("DELETE FROM character_actions WHERE action_id = " + allActions[newSelectedName].ID + " AND character_id = " + characters[_tab3Char].ID); } aIndex ++; } rectHeight = rectHeight + heightStep * actions.Count; //a button to add new condition if(GUI.Button(new Rect(290, rectHeight, 20, 20), "+")) { RunQuery("INSERT INTO character_actions (character_id, action_id) VALUES (" + characters[_tab3Char].ID + ", " + allActions[0].ID + ")"); } } }
public void SetGoapGoal(GoapGoal goapGoal) { this.goapGoal = goapGoal; }
public void Initialize(Character character) { _parentCharacter = character; WorkingMemory = new WorkingMemory(); WorkingMemory.Initialize(_parentCharacter); BlackBoard = new BlackBoard(); Sensor = new AISensor(); Sensor.Initialize(_parentCharacter); TargetingSystem = new AITargeting(); TargetingSystem.Initialize(_parentCharacter); WeaponSystem = new AIWeapon(); WeaponSystem.Initialize(_parentCharacter); Planner = new GoapPlanner(this); _goals = GameManager.Inst.DBManager.DBHandlerAI.GetCharacterGoalSet(_parentCharacter.GoapID); _actions = GameManager.Inst.DBManager.DBHandlerAI.GetCharacterActionSet(_parentCharacter.GoapID); _currentWorldStates = new List<GoapWorldState>(); _parentCharacter.MyEventHandler.OnCurrentActionComplete += OnCurrentActionComplete; _parentCharacter.MyEventHandler.OnPerFrameTimer += PerFrameUpdate; //update parent character for each action foreach(GoapAction action in _actions) { action.ParentCharacter = _parentCharacter; } //BlackBoard.PatrolLoc = new Vector3(63.9f, 0.3f, -13.3f); //BlackBoard.PatrolRange = new Vector3(30, 10, 15); if(ControlType != AIControlType.Player) { BlackBoard.GuardLevel = 1; _parentCharacter.SendCommand(CharacterCommands.SetAlert); } _currentGoal = null; _currentAction = null; _parentCharacter.MyEventHandler.OnOneSecondTimer += OnOneSecondTimer; }
public Queue<GoapAction> GetActionQueue(GoapGoal myGoal, List<GoapAction> availableActions) { GoapStateGraphNode goal = new GoapStateGraphNode(myGoal.GoalStates, new List<GoapWorldState>()); goal.CostSinceStart = 0; goal.HeuristicCost = GetHeuristic(goal); goal.UnsatisfiedStates = myGoal.GoalStates; List<GoapStateGraphNode> openNodes = new List<GoapStateGraphNode>(); openNodes.Add(goal); List<GoapStateGraphNode> closedNodes = new List<GoapStateGraphNode>(); GoapStateGraphNode resultFirstNode = null; _evaluatedStates = new List<GoapWorldState>(); //evaluate world states in goal conditions foreach(GoapWorldState state in myGoal.GoalStates) { CheckWorldState(state); } while(openNodes.Count() > 0) { //starting from the graph goal node, for each world state look for a action that will satisfy it. //when an action is found, create a new graph node, add action effect to satified states, and add action preconditions to unsatisfied states //then sort all neighbors into a list ordered by cost+heuristic //for each neighbor in the list, starting from the one with lowest cost+heuristic, //find the lowest f_score node in open nodes GoapStateGraphNode bestOpenNode = openNodes[0]; foreach(GoapStateGraphNode node in openNodes) { if(node.HeuristicCost < bestOpenNode.HeuristicCost) { bestOpenNode = node; } } CsDebug.Inst.Log("======Evaluating best open node with cost " + bestOpenNode.CostSinceStart, CsDLevel.Debug, CsDComponent.AI); if(bestOpenNode.CameFromAction != null) { CsDebug.Inst.Log("Came from Action " + bestOpenNode.CameFromAction.Name, CsDLevel.Debug, CsDComponent.AI); } //evaluate the current world state for states in current node foreach(GoapWorldState s in bestOpenNode.UnsatisfiedStates) { CheckWorldState(s); CsDebug.Inst.Log("Current Unsatisfied State: " + s.Name + s.Operator + s.Value, CsDLevel.Debug, CsDComponent.AI); } foreach(GoapWorldState s in bestOpenNode.SatisfiedStates) { CheckWorldState(s); //CsDebug.Inst.Log("Current Satisfied State: " + s.Name + s.Operator + s.Value, CsDLevel.Debug, CsDComponent.AI); } //if all unsatisfied states can be solved by current world state then we have found a path if(CompareWorldStatesContain(_parentAI.GetCurrentWorldState(), bestOpenNode.UnsatisfiedStates)) { //search complete, found a path! CsDebug.Inst.Log("Found best path!", CsDLevel.Info, CsDComponent.AI); resultFirstNode = bestOpenNode; break; } openNodes.Remove(bestOpenNode); closedNodes.Add(bestOpenNode); //find all neighbors foreach(GoapAction action in availableActions) { CsDebug.Inst.Log("------Starting to evaluate action " + action.Name, CsDLevel.Debug, CsDComponent.AI); List<GoapWorldState> usefulEffects = CompareWorldStatesContainAny(bestOpenNode.UnsatisfiedStates, action.Effects); if(usefulEffects == null) { CsDebug.Inst.Log("Action has no useful effects!", CsDLevel.Debug, CsDComponent.AI); //found conflict, or action is marked as not viable from previous attempts continue; } if(!_parentAI.CheckActionViable(action)) { CsDebug.Inst.Log("Action has been failed before!", CsDLevel.Debug, CsDComponent.AI); //found conflict, or action is marked as not viable from previous attempts continue; } if(!action.CheckContextPrecondition()) { CsDebug.Inst.Log("Action is not viable!", CsDLevel.Debug, CsDComponent.AI); //found conflict, or action is marked as not viable from previous attempts continue; } else if(usefulEffects.Count > 0) { CsDebug.Inst.Log("Found action " + action.Name + " that satisfies preconditions set containing " + bestOpenNode.UnsatisfiedStates.Count(), CsDLevel.Debug, CsDComponent.AI); CsDebug.Inst.Log("Current best open node unsatisfied states contains " + bestOpenNode.UnsatisfiedStates[0].Name + "=" + bestOpenNode.UnsatisfiedStates[0].Value, CsDLevel.Trace, CsDComponent.AI); //neighbor's effect is removed from neighbor unsatisfied list and added to the satisfied list //any precondition that hasn't been resolved or listed is added to the neighbor's unsatisfied list //this way we don't have any dupilicate states List<GoapWorldState> neighborUnsatisfied = new List<GoapWorldState>(bestOpenNode.UnsatisfiedStates); List<GoapWorldState> neighborSatisfied = new List<GoapWorldState>(bestOpenNode.SatisfiedStates); bool isNoConflict = true; foreach(GoapWorldState effect in usefulEffects) { RemoveStateFromSet(neighborUnsatisfied, effect); isNoConflict = AddStateToSet(neighborSatisfied, effect); if(!isNoConflict) { //CsDebug.Inst.Log("Found conflict when adding effect " + effect.Name + effect.Value + "to neighbor satisfied set", CsDLevel.Trace, CsDComponent.AI); continue; } } isNoConflict = true; foreach(GoapWorldState condition in action.Preconditions) { //is this condition already in the neighborSatisfied list? //is this condition already in the neighborUnsatisfied list? //if both answer is no, add the new condition to neighborUnsatisfied list bool isInSatisfied = CompareWorldStatesContain(neighborSatisfied, new List<GoapWorldState>{condition}); bool isInUnsatisfied = CompareWorldStatesContain(neighborUnsatisfied, new List<GoapWorldState>{condition}); if(!isInSatisfied && !isInUnsatisfied) { isNoConflict = AddStateToSet(neighborUnsatisfied, condition); if(!isNoConflict) { //CsDebug.Inst.Log("Found conflict when adding condition " + condition.Name + condition.Value + "to neighbor UNsatisfied set", CsDLevel.Trace, CsDComponent.AI); continue; } } } //CsDebug.Inst.Log("Successfully added preconditions for action " + action.Name, CsDLevel.Debug, CsDComponent.AI); //now we check if the above neighbor unsatisfied+satisfied combination exists in any open or closed nodes //if in closed nodes, we skip this neighbor. if in open nodes, we will calculate its heuristic cost //if not in any set, create a new node bool isInClosed = false; foreach(GoapStateGraphNode node in closedNodes) { if(CompareWorldStatesEqual(node.UnsatisfiedStates, neighborUnsatisfied) && CompareWorldStatesEqual(node.SatisfiedStates, neighborSatisfied)) { isInClosed = true; } } if(isInClosed) { continue; } //CsDebug.Inst.Log("checking if node already exists in openNodes", CsDLevel.Debug, CsDComponent.AI); GoapStateGraphNode openNode = null; foreach(GoapStateGraphNode node in openNodes) { if(CompareWorldStatesEqual(node.UnsatisfiedStates, neighborUnsatisfied) && CompareWorldStatesEqual(node.SatisfiedStates, neighborSatisfied)) { //CsDebug.Inst.Log("Node already exists", CsDLevel.Debug, CsDComponent.AI); openNode = node; } } float tentativeCost = bestOpenNode.CostSinceStart + action.Cost; if(openNode != null) { //CsDebug.Inst.Log("Node exists, check its cost", CsDLevel.Debug, CsDComponent.AI); if(tentativeCost >= openNode.CostSinceStart) { //CsDebug.Inst.Log("Invalid path!", CsDLevel.Debug, CsDComponent.AI); //this is NOT a good path continue; } } else { //add a new node into openNodes openNode = new GoapStateGraphNode(neighborUnsatisfied, neighborSatisfied); CsDebug.Inst.Log("Adding a new neighbor node with " + neighborUnsatisfied.Count() + " unsatisfied conditions", CsDLevel.Debug, CsDComponent.AI); openNodes.Add(openNode); } CsDebug.Inst.Log("~~~~~~~~~Found a valid path, assigning neighbor parameters" + action.Name, CsDLevel.Info, CsDComponent.AI); openNode.CameFrom = bestOpenNode; openNode.CameFromAction = action; openNode.CostSinceStart = tentativeCost; openNode.HeuristicCost = openNode.CostSinceStart + GetHeuristic(openNode); } } } if(resultFirstNode == null) { //CsDebug.Inst.Log("No path found! Exiting planner.", CsDLevel.Info, CsDComponent.AI); return null; } Queue<GoapAction> actions = new Queue<GoapAction>(); GoapStateGraphNode currentNode = resultFirstNode; //CsDebug.Inst.Log("Start enqueueing actions", CsDLevel.Debug, CsDComponent.AI); while(currentNode.CameFrom != null) { //CsDebug.Inst.Log("Enqueueing action " + currentNode.CameFromAction.Name, CsDLevel.Info, CsDComponent.AI); actions.Enqueue(currentNode.CameFromAction); currentNode = currentNode.CameFrom; } return actions; }
public GoapPlanManager(GoapGoal goapGoal) { this.goapGoal = goapGoal; Init(); }
public void Initialize() { SelectedMember = GameObject.Find("HumanCharacter").GetComponent<HumanCharacter>(); SelectedMember.Initialize(); RefreshMarkerForMember(SelectedMember); /* HumanCharacter member2 = GameObject.Find("HumanCharacter3").GetComponent<HumanCharacter>(); member2.Initialize(); RefreshMarkerForMember(member2); //for testing member2.MyAI.BlackBoard.FollowTarget = SelectedMember; */ Members.Add(SelectedMember); //Members.Add(member2); MemberGuardGoal = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(6); MemberGuardGoal.Priority = 0; MemberFollowGoal = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(8); MemberFollowGoal.Priority = 0; //initialize inventory and then load weapons to prefab GameManager.Inst.ItemManager.LoadPartyInventory(); RefreshAllMemberArmors(); RefreshAllMemberWeapons(); }
private void RefreshCharactersTab() { IDataReader reader = RunQuery("SELECT characters.* FROM characters"); Dictionary <int, CharacterData> characters = new Dictionary <int, CharacterData>(); int i = 1; while (reader.Read()) { int c_id = reader.GetInt32(0); string c_title = reader.GetString(1); string c_first = reader.GetString(2); string c_last = reader.GetString(3); CharacterData data = new CharacterData(); data.ID = c_id; data.Title = c_title; data.FirstName = c_first; data.LastName = c_last; characters.Add(i, data); i++; } string [] dropDownOptions = new string[characters.Count + 1]; dropDownOptions[0] = "None"; if (characters.Count > 0) { for (int index = 1; index <= characters.Count; index++) { dropDownOptions[index] = characters[index].Title + ", " + characters[index].FirstName + " " + characters[index].LastName; } } GUI.Label(new Rect(10, 40, 200, 20), "Characters:"); _tab3Char = EditorGUI.Popup(new Rect(10, 60, 250, 20), _tab3Char, dropDownOptions); if (_tab3Char > 0) { //now we have the character ID, we make a list of character goals IDataReader goalReader = RunQuery( "SELECT goap_goals.*, character_goals.priority " + "FROM goap_goals INNER JOIN character_goals " + "ON goap_goals.id = character_goals.goal_id AND character_goals.character_id = '" + characters[_tab3Char].ID + "'"); List <GoapGoal> goals = new List <GoapGoal>(); while (goalReader.Read()) { int goalID = goalReader.GetInt32(0); string goalName = goalReader.GetString(1); int priority = goalReader.GetInt32(2); GoapGoal goal = new GoapGoal(); goal.Name = goalName; goal.Priority = priority; goals.Add(goal); } IDataReader allGoalsReader = RunQuery("SELECT goap_goals.* FROM goap_goals"); Dictionary <int, GoalData> allGoals = new Dictionary <int, GoalData>(); int goalIndex = 0; while (allGoalsReader.Read()) { int c_id = allGoalsReader.GetInt32(0); string c_desc = allGoalsReader.GetString(1); GoalData data = new GoalData(); data.ID = c_id; data.Description = c_desc; allGoals.Add(goalIndex, data); goalIndex++; } GUI.Label(new Rect(10, 90, 150, 20), "Goals:"); int rectHeight = 110; int heightStep = 20; int gIndex = 0; foreach (GoapGoal goal in goals) { int selectedName = 0; int selectedPriority = 0; string [] options = new string[allGoals.Count]; for (int index = 0; index < allGoals.Count; index++) { options[index] = allGoals[index].Description; if (goal.Name == allGoals[index].Description) { selectedName = index; selectedPriority = goal.Priority; } } int height = rectHeight + gIndex * heightStep; int newSelectedName = EditorGUI.Popup(new Rect(10, height, 150, 20), selectedName, options); GUI.Label(new Rect(170, height, 40, 20), "Priority"); int newSelectedPriority = EditorGUI.Popup(new Rect(220, height, 60, 20), selectedPriority, new string[] { "0", "1", "2", "3", "4", "5" }); bool toBeUpdated = false; if (newSelectedName != selectedName || newSelectedPriority != selectedPriority) { toBeUpdated = true; } bool toBeDeleted = false; if (GUI.Button(new Rect(290, height, 15, 15), "-")) { toBeDeleted = true; } if (toBeUpdated) { RunQuery("UPDATE character_goals SET goal_id = " + allGoals[newSelectedName].ID + ", priority = " + newSelectedPriority + " WHERE character_id = " + characters[_tab3Char].ID + " AND goal_id = " + allGoals[selectedName].ID); } if (toBeDeleted) { RunQuery("DELETE FROM character_goals WHERE goal_id = " + allGoals[newSelectedName].ID + " AND character_id = " + characters[_tab3Char].ID); } gIndex++; } rectHeight = rectHeight + heightStep * goals.Count; //a button to add new condition if (GUI.Button(new Rect(290, rectHeight, 20, 20), "+")) { RunQuery("INSERT INTO character_goals (character_id, goal_id, priority) VALUES (" + characters[_tab3Char].ID + ", " + allGoals[0].ID + ", 0)"); } //now we have the character ID, we make a list of character actions IDataReader actionReader = RunQuery( "SELECT goap_actions.* " + "FROM goap_actions INNER JOIN character_actions " + "ON goap_actions.id = character_actions.action_id AND character_actions.character_id = '" + characters[_tab3Char].ID + "'"); List <ActionData> actions = new List <ActionData>(); while (actionReader.Read()) { int id = actionReader.GetInt32(0); string className = actionReader.GetString(1); string description = actionReader.GetString(2); float cost = actionReader.GetFloat(3); ActionData action = new ActionData(); action.ID = id; action.ClassName = className; action.Description = description; action.DefaultCost = cost; actions.Add(action); } IDataReader allActionsReader = RunQuery("SELECT goap_actions.* FROM goap_actions"); Dictionary <int, ActionData> allActions = new Dictionary <int, ActionData>(); int actionIndex = 0; while (allActionsReader.Read()) { int c_id = allActionsReader.GetInt32(0); string c_desc = allActionsReader.GetString(2); ActionData data = new ActionData(); data.ID = c_id; data.Description = c_desc; allActions.Add(actionIndex, data); actionIndex++; } rectHeight = rectHeight + 30; GUI.Label(new Rect(10, rectHeight, 150, 20), "Actions:"); rectHeight += 20; int aIndex = 0; foreach (ActionData action in actions) { int selectedName = 0; string [] options = new string[allActions.Count]; for (int index = 0; index < allActions.Count; index++) { options[index] = allActions[index].Description; if (action.Description == allActions[index].Description) { selectedName = index; } } int height = rectHeight + aIndex * heightStep; int newSelectedName = EditorGUI.Popup(new Rect(10, height, 150, 20), selectedName, options); bool toBeUpdated = false; if (newSelectedName != selectedName) { toBeUpdated = true; } bool toBeDeleted = false; if (GUI.Button(new Rect(290, height, 15, 15), "-")) { toBeDeleted = true; } if (toBeUpdated) { RunQuery("UPDATE character_actions SET action_id = " + allActions[newSelectedName].ID + " WHERE character_id = " + characters[_tab3Char].ID + " AND action_id = " + allActions[selectedName].ID); } if (toBeDeleted) { RunQuery("DELETE FROM character_actions WHERE action_id = " + allActions[newSelectedName].ID + " AND character_id = " + characters[_tab3Char].ID); } aIndex++; } rectHeight = rectHeight + heightStep * actions.Count; //a button to add new condition if (GUI.Button(new Rect(290, rectHeight, 20, 20), "+")) { RunQuery("INSERT INTO character_actions (character_id, action_id) VALUES (" + characters[_tab3Char].ID + ", " + allActions[0].ID + ")"); } } }
private bool EvaluateGoal(GoapGoal goal) { //check which goal's conditions are met bool isGoalMet = true; foreach(GoapWorldState state in goal.GoalStates) { object value = EvaluateWorldState(state); //CsDebug.Inst.CharLog(_parentCharacter, "Evaluating Goal; current value " + value + " target value " + state.Value); if(!Object.Equals(value, state.Value)) { //CsDebug.Inst.CharLog(_parentCharacter, "Evaluating goal result: values don't match"); //this goal isn't met! isGoalMet = false; return isGoalMet; } } return isGoalMet; }
public void OnDeath() { if(_currentAction != null) { _currentAction.AbortAction(1); _currentAction = null; } _currentGoal = null; _parentCharacter.MyEventHandler.OnOneSecondTimer -= OnOneSecondTimer; TargetingSystem.OnDeath(); Sensor.OnDeath(); WorkingMemory.OnDeath(); }
IEnumerator WaitAndCheckImportantEvent(float waitTime, float priority) { yield return new WaitForSeconds(waitTime); if(ControlType == AIControlType.Player) { return true; } //when an important event happens, stop current action and reevaluate all the goals and pick the highest priority goal Debug.Log("Triggering important event " + _parentCharacter.name); if(_currentAction != null) { if(_currentAction.AbortAction(priority)) { _currentAction = null; _currentGoal = null; FindAndExecuteAction(); } } else { _currentGoal = null; FindAndExecuteAction(); } }
private void FindAndExecuteAction() { //check if there is current goal and if the current goal is met //if met, find next goal //if not met, check if there's current action. if there is action leave it alone. if no action then calculate planner and execute first action //if no current goal, get next goal //Debug.Log("Start finding and executing action"); if(_currentGoal == null) { Debug.Log("no current goal, getting a new one"); _currentGoal = GetNextGoal(); Debug.Log("found new goal " + _currentGoal.Name); _currentAction = null; } int counter = _goals.Count; while(counter > 0 && _currentGoal != null) { //Debug.Log("Find&Execute: checking goal " + _currentGoal.Name); bool needNextGoal = false; if(_currentAction == null && _currentGoal != null) { if(!EvaluateGoal(_currentGoal)) { //CsDebug.Inst.Log("current goal " + _currentGoal.Name + " is not met, running planner", CsDLevel.Info, CsDComponent.AI); _actionQueue = Planner.GetActionQueue(_currentGoal, _actions); if(_actionQueue != null && _actionQueue.Count > 0) { _currentAction = _actionQueue.Dequeue(); //Debug.Log("Found current action " + _currentAction.Name + " for goal " + _currentGoal.Name); if(_currentAction.ExecuteAction()) { //action executed successfully return; } } //failed to find action for current goal, get next goal needNextGoal = true; } else { needNextGoal = true; } } else { //there's action; leave it alone return; } if(needNextGoal) { _currentGoal = GetNextGoal(); //Debug.Log("getting next goal; result: " + _currentGoal.Name); _currentAction = null; } counter --; } }
private void FindAndExecuteAction() { //check if there is current goal and if the current goal is met //if met, find next goal //if not met, check if there's current action. if there is action leave it alone. if no action then calculate planner and execute first action //if no current goal, get next goal CsDebug.Inst.CharLog(_parentCharacter, "Start finding and executing action"); if (_currentGoal == null) { CsDebug.Inst.CharLog(_parentCharacter, "no current goal, getting a new one"); _currentGoal = GetNextGoal(); CsDebug.Inst.CharLog(_parentCharacter, "found new goal " + _currentGoal.Name); _currentAction = null; } int counter = _goals.Count; while (counter > 0 && _currentGoal != null) { CsDebug.Inst.CharLog(_parentCharacter, "Find&Execute: checking goal " + _currentGoal.Name); bool needNextGoal = false; if (_currentAction == null && _currentGoal != null) { if (!EvaluateGoal(_currentGoal)) { CsDebug.Inst.CharLog(_parentCharacter, "current goal " + _currentGoal.Name + " is not met, running planner, character " + _parentCharacter.name); _actionQueue = Planner.GetActionQueue(_currentGoal, _actions); if (_actionQueue != null && _actionQueue.Count > 0) { _currentAction = _actionQueue.Dequeue(); CsDebug.Inst.CharLog(_parentCharacter, "Found current action " + _currentAction.Name + " for goal " + _currentGoal.Name); if (_currentAction.ExecuteAction()) { //action executed successfully return; } } //failed to find action for current goal, get next goal CsDebug.Inst.CharLog(_parentCharacter, "Failed to find action for goal " + _currentGoal.Name); needNextGoal = true; } else { CsDebug.Inst.CharLog(_parentCharacter, "Goal is already met: " + _currentGoal.Name); needNextGoal = true; } } else { //there's action; leave it alone return; } if (needNextGoal) { _currentGoal = GetNextGoal(); _currentAction = null; if (_currentGoal != null) { CsDebug.Inst.CharLog(_parentCharacter, "getting next goal; result: " + _currentGoal.Name); } else { CsDebug.Inst.CharLog(_parentCharacter, "getting next goal; result: null"); } } counter--; } }
public void ClearDynamicGoal(int priority) { //CsDebug.Inst.CharLog(_parentCharacter, "Clearing top priority goal for " + _parentCharacter.name); List<GoapGoal> goalsCopy = new List<GoapGoal>(_goals); foreach(GoapGoal goal in goalsCopy) { if(goal.Priority == priority) { if(_currentGoal == goal) { _currentAction.StopAction(); } _goals.Remove(goal); _currentAction = null; _currentGoal = null; FindAndExecuteAction(); } } }
/// <summary> /// Formulates a plan from the given goal and current actor state. /// </summary> /// <returns>The plan.</returns> /// <param name="_goal">Goal.</param> /// <param name="_worldstate">Worldstate.</param> private GoapPlan FormulatePlan (GoapGoal _goal, GoapWorldstate _worldstate) { GoapPlan newPlan = new GoapPlan(); newPlan.actionOrder = new List<GoapAction> (); //according to the goal form an initial prerequisite of what we want to do newPlan.goalBeingFulfilled = _goal; string initPrereq = _goal.initPrerequisite; //add the initial action onto the stack to start constructing the plan foreach (GoapAction _action in actionPool) { if (_action.fulfillment == initPrereq) { newPlan.actionOrder.Insert (0, _action); break; } } List<string> prerequisites = newPlan.actionOrder[0].prerequisites; newPlan.actionOrder = FulfillPrereqs (newPlan.actionOrder, prerequisites, _worldstate); return newPlan; }
public GoapActionHomeWork(GoapGoal goapGoal) : base(goapGoal) { cost = 40; }
public void TakeTurn () { worldState = UpdateWorldstate(); //sort the goal priorities for this turn. GoapGoal tempGoal = SortGoals (worldState); //if the goal has changed, or the sensors demand it, a new plan must be formulated if (tempGoal != currentGoal || currentPlan == null) { currentGoal = tempGoal; currentPlan = FormulatePlan(currentGoal, worldState); } //loop the plan execution until all while (actor.actionPoints > 0) { //process and execute the plan, setting it to be the new plan currentPlan = ExecutePlan (currentPlan, worldState); } return; }
public void Initialize() { _allCharacters = new List <Character>(); _humansInScene = new List <HumanCharacter>(); _mutantsInScene = new List <MutantCharacter>(); _deadBodies = new Dictionary <Character, int>(); _fadeTimers = new Dictionary <Character, float>(); _allNavNodes = new List <NavNode>(); _navNodeBases = new List <NavNode>(); _navNodeMutants = new List <NavNode>(); DynamicGoalGuard = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(6); DynamicGoalGuard.Priority = 5; DynamicGoalFollow = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(8); DynamicGoalFollow.Priority = 5; DynamicGoalPatrol = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(2); DynamicGoalPatrol.Priority = 5; DynamicGoalExplore = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(12); DynamicGoalExplore.Priority = 5; DynamicGoalChill = GameManager.Inst.DBManager.DBHandlerAI.GetGoalByID(10); DynamicGoalChill.Priority = 5; GameObject [] navNodes = GameObject.FindGameObjectsWithTag("NavNode"); foreach (GameObject o in navNodes) { NavNode node = o.GetComponent <NavNode>(); _allNavNodes.Add(node); if (node.Type == NavNodeType.Base) { _navNodeBases.Add(node); } else if (node.Type == NavNodeType.MutantHunt) { _navNodeMutants.Add(node); } } if (_allFactions == null) { _allFactions = GameManager.Inst.DBManager.DBHandlerCharacter.LoadFactionData(); } /* * FactionData newFaction1 = new FactionData(); * newFaction1.Name = "Player"; * newFaction1.MemberModelIDs = new string[]{"Bandit"}; * newFaction1.FactionID = Faction.Player; * * FactionData newFaction2 = new FactionData(); * newFaction2.Name = "The Legionnaires"; * newFaction2.MemberModelIDs = new string[]{"Legionnaire1", "Legionnaire2", "Legionnaire3"}; * newFaction2.FactionID = Faction.Legionnaires; * * FactionData newFaction3 = new FactionData(); * newFaction3.Name = "Millitary"; * newFaction3.MemberModelIDs = new string[]{"Bandit"}; * newFaction3.FactionID = Faction.Military; * * FactionData newFaction4 = new FactionData(); * newFaction4.Name = "Mutants"; * newFaction4.MemberModelIDs = new string[]{"Mutant3", "Mutant4"}; * newFaction4.FactionID = Faction.Mutants; * * FactionData newFaction5 = new FactionData(); * newFaction5.Name = "Civilian"; * newFaction5.MemberModelIDs = new string[]{"Bandit"}; * newFaction5.FactionID = Faction.Civilian; * * FactionData newFaction6 = new FactionData(); * newFaction6.Name = "Bootleggers"; * newFaction6.MemberModelIDs = new string[]{"Bootlegger1", "Bootlegger2", "Bootlegger3", "Bootlegger4"}; * newFaction6.FactionID = Faction.Bootleggers; * * newFaction2.AddRelationshipEntry(Faction.Player, 0); * newFaction2.AddRelationshipEntry(Faction.Mutants, 0); * * newFaction3.AddRelationshipEntry(Faction.Player, 0); * newFaction3.AddRelationshipEntry(Faction.Mutants, 0); * * newFaction4.AddRelationshipEntry(Faction.Player, 0); * newFaction4.AddRelationshipEntry(Faction.Legionnaires, 0); * newFaction4.AddRelationshipEntry(Faction.Military, 0); * * newFaction5.AddRelationshipEntry(Faction.Player, 0.5f); * * newFaction6.AddRelationshipEntry(Faction.Player, 0.5f); * * _allFactions.Add(newFaction1.FactionID, newFaction1); * _allFactions.Add(newFaction2.FactionID, newFaction2); * _allFactions.Add(newFaction3.FactionID, newFaction3); * _allFactions.Add(newFaction4.FactionID, newFaction4); * _allFactions.Add(newFaction5.FactionID, newFaction5); * _allFactions.Add(newFaction6.FactionID, newFaction6); */ _allHouseHolds = new Dictionary <string, Household>(); Household [] households = GameObject.FindObjectsOfType <Household>(); foreach (Household h in households) { _allHouseHolds.Add(h.name, h); } if (_allSquads == null) { _allSquads = new Dictionary <string, AISquad>(); LoadAISquads(); } //initialize preset characters GameObject [] characters = GameObject.FindGameObjectsWithTag("NPC"); //Debug.LogError("Number of NPC in scene " + characters.Length + " number of squads " + _allSquads.Count); foreach (GameObject o in characters) { Character c = o.GetComponent <Character>(); if (c != null) { c.Initialize(); if (!string.IsNullOrEmpty(c.SquadID)) { _allSquads[c.SquadID].AddMember(c); //Debug.Log(c.SquadID + " now has members " + _allSquads[c.SquadID].Members.Count); } } //load preset inventory if (c.PresetInventory != null && c.PresetInventory.IsEnabled) { GameManager.Inst.ItemManager.LoadNPCInventory(c.Inventory, c.PresetInventory); } c.MyAI.WeaponSystem.LoadWeaponsFromInventory(false); } foreach (Household h in _allHouseHolds.Values) { //Debug.LogError("initializing household " + h.name); h.Initialize(); } //Debug.LogError("Number of NPC in NPC Manager " + _allCharacters.Count); }
public void ForceStopCurrentAction() { if(_currentAction != null) { _currentAction.StopAction(); } _currentAction = null; _currentGoal = null; }
private GoapGoal SortGoals (GoapWorldstate _worldState) { GoapGoal newGoal = new GoapGoal(); float highestWeight = float.MinValue, testWeight; for (int i = 0; i < goals.Count; i++) { testWeight = goals[i].calcWeight(worldState); if (testWeight > highestWeight) { highestWeight = testWeight; newGoal = goals[i]; } } return newGoal; }
public Queue <GoapAction> GetActionQueue(GoapGoal myGoal, List <GoapAction> availableActions) { GoapStateGraphNode goal = new GoapStateGraphNode(myGoal.GoalStates, new List <GoapWorldState>()); goal.CostSinceStart = 0; goal.HeuristicCost = GetHeuristic(goal); goal.UnsatisfiedStates = myGoal.GoalStates; List <GoapStateGraphNode> openNodes = new List <GoapStateGraphNode>(); openNodes.Add(goal); List <GoapStateGraphNode> closedNodes = new List <GoapStateGraphNode>(); GoapStateGraphNode resultFirstNode = null; _evaluatedStates = new List <GoapWorldState>(); //evaluate world states in goal conditions foreach (GoapWorldState state in myGoal.GoalStates) { CheckWorldState(state); } //Debug.Log("starting goap planner while loop " + _parentAI.name); while (openNodes.Count() > 0) { //starting from the graph goal node, for each world state look for a action that will satisfy it. //when an action is found, create a new graph node, add action effect to satified states, and add action preconditions to unsatisfied states //then sort all neighbors into a list ordered by cost+heuristic //for each neighbor in the list, starting from the one with lowest cost+heuristic, //find the lowest f_score node in open nodes GoapStateGraphNode bestOpenNode = openNodes[0]; foreach (GoapStateGraphNode node in openNodes) { if (node.HeuristicCost < bestOpenNode.HeuristicCost) { bestOpenNode = node; } } CsDebug.Inst.Log("======Evaluating best open node with cost " + bestOpenNode.CostSinceStart, CsDLevel.Debug, CsDComponent.AI); if (bestOpenNode.CameFromAction != null) { CsDebug.Inst.Log("Came from Action " + bestOpenNode.CameFromAction.Name, CsDLevel.Debug, CsDComponent.AI); } //evaluate the current world state for states in current node foreach (GoapWorldState s in bestOpenNode.UnsatisfiedStates) { CheckWorldState(s); CsDebug.Inst.Log("Current Unsatisfied State: " + s.Name + s.Operator + s.Value, CsDLevel.Debug, CsDComponent.AI); } foreach (GoapWorldState s in bestOpenNode.SatisfiedStates) { CheckWorldState(s); //CsDebug.Inst.Log("Current Satisfied State: " + s.Name + s.Operator + s.Value, CsDLevel.Debug, CsDComponent.AI); } //if all unsatisfied states can be solved by current world state then we have found a path if (CompareWorldStatesContain(_parentAI.GetCurrentWorldState(), bestOpenNode.UnsatisfiedStates)) { //search complete, found a path! CsDebug.Inst.Log("Found best path!", CsDLevel.Info, CsDComponent.AI); resultFirstNode = bestOpenNode; break; } openNodes.Remove(bestOpenNode); closedNodes.Add(bestOpenNode); //find all neighbors foreach (GoapAction action in availableActions) { CsDebug.Inst.Log("------Starting to evaluate action " + action.Name, CsDLevel.Debug, CsDComponent.AI); List <GoapWorldState> usefulEffects = CompareWorldStatesContainAny(bestOpenNode.UnsatisfiedStates, action.Effects); if (usefulEffects == null) { CsDebug.Inst.Log("Action has no useful effects!", CsDLevel.Debug, CsDComponent.AI); //found conflict, or action is marked as not viable from previous attempts continue; } if (!_parentAI.CheckActionViable(action)) { CsDebug.Inst.Log("Action has been failed before!", CsDLevel.Debug, CsDComponent.AI); //found conflict, or action is marked as not viable from previous attempts continue; } if (!action.CheckContextPrecondition()) { CsDebug.Inst.Log("Action is not viable!", CsDLevel.Debug, CsDComponent.AI); //found conflict, or action is marked as not viable from previous attempts continue; } else if (usefulEffects.Count > 0) { CsDebug.Inst.Log("Found action " + action.Name + " that satisfies preconditions set containing " + bestOpenNode.UnsatisfiedStates.Count(), CsDLevel.Debug, CsDComponent.AI); CsDebug.Inst.Log("Current best open node unsatisfied states contains " + bestOpenNode.UnsatisfiedStates[0].Name + "=" + bestOpenNode.UnsatisfiedStates[0].Value, CsDLevel.Trace, CsDComponent.AI); //neighbor's effect is removed from neighbor unsatisfied list and added to the satisfied list //any precondition that hasn't been resolved or listed is added to the neighbor's unsatisfied list //this way we don't have any dupilicate states List <GoapWorldState> neighborUnsatisfied = new List <GoapWorldState>(bestOpenNode.UnsatisfiedStates); List <GoapWorldState> neighborSatisfied = new List <GoapWorldState>(bestOpenNode.SatisfiedStates); bool isNoConflict = true; foreach (GoapWorldState effect in usefulEffects) { RemoveStateFromSet(neighborUnsatisfied, effect); isNoConflict = AddStateToSet(neighborSatisfied, effect); if (!isNoConflict) { //CsDebug.Inst.Log("Found conflict when adding effect " + effect.Name + effect.Value + "to neighbor satisfied set", CsDLevel.Trace, CsDComponent.AI); continue; } } isNoConflict = true; foreach (GoapWorldState condition in action.Preconditions) { //is this condition already in the neighborSatisfied list? //is this condition already in the neighborUnsatisfied list? //if both answer is no, add the new condition to neighborUnsatisfied list bool isInSatisfied = CompareWorldStatesContain(neighborSatisfied, new List <GoapWorldState> { condition }); bool isInUnsatisfied = CompareWorldStatesContain(neighborUnsatisfied, new List <GoapWorldState> { condition }); if (!isInSatisfied && !isInUnsatisfied) { isNoConflict = AddStateToSet(neighborUnsatisfied, condition); if (!isNoConflict) { //CsDebug.Inst.Log("Found conflict when adding condition " + condition.Name + condition.Value + "to neighbor UNsatisfied set", CsDLevel.Trace, CsDComponent.AI); continue; } } } //CsDebug.Inst.Log("Successfully added preconditions for action " + action.Name, CsDLevel.Debug, CsDComponent.AI); //now we check if the above neighbor unsatisfied+satisfied combination exists in any open or closed nodes //if in closed nodes, we skip this neighbor. if in open nodes, we will calculate its heuristic cost //if not in any set, create a new node bool isInClosed = false; foreach (GoapStateGraphNode node in closedNodes) { if (CompareWorldStatesEqual(node.UnsatisfiedStates, neighborUnsatisfied) && CompareWorldStatesEqual(node.SatisfiedStates, neighborSatisfied)) { isInClosed = true; } } if (isInClosed) { continue; } //CsDebug.Inst.Log("checking if node already exists in openNodes", CsDLevel.Debug, CsDComponent.AI); GoapStateGraphNode openNode = null; foreach (GoapStateGraphNode node in openNodes) { if (CompareWorldStatesEqual(node.UnsatisfiedStates, neighborUnsatisfied) && CompareWorldStatesEqual(node.SatisfiedStates, neighborSatisfied)) { //CsDebug.Inst.Log("Node already exists", CsDLevel.Debug, CsDComponent.AI); openNode = node; } } float tentativeCost = bestOpenNode.CostSinceStart + action.GetActionCost(); if (openNode != null) { //CsDebug.Inst.Log("Node exists, check its cost", CsDLevel.Debug, CsDComponent.AI); if (tentativeCost >= openNode.CostSinceStart) { //CsDebug.Inst.Log("Invalid path!", CsDLevel.Debug, CsDComponent.AI); //this is NOT a good path continue; } } else { //add a new node into openNodes openNode = new GoapStateGraphNode(neighborUnsatisfied, neighborSatisfied); CsDebug.Inst.Log("Adding a new neighbor node with " + neighborUnsatisfied.Count() + " unsatisfied conditions", CsDLevel.Debug, CsDComponent.AI); openNodes.Add(openNode); } CsDebug.Inst.Log("~~~~~~~~~Found a valid path, assigning neighbor parameters" + action.Name, CsDLevel.Info, CsDComponent.AI); openNode.CameFrom = bestOpenNode; openNode.CameFromAction = action; openNode.CostSinceStart = tentativeCost; openNode.HeuristicCost = openNode.CostSinceStart + GetHeuristic(openNode); } } } if (resultFirstNode == null) { //CsDebug.Inst.Log("No path found! Exiting planner.", CsDLevel.Info, CsDComponent.AI); return(null); } Queue <GoapAction> actions = new Queue <GoapAction>(); GoapStateGraphNode currentNode = resultFirstNode; //CsDebug.Inst.Log("Start enqueueing actions", CsDLevel.Debug, CsDComponent.AI); while (currentNode.CameFrom != null) { //CsDebug.Inst.Log("Enqueueing action " + currentNode.CameFromAction.Name, CsDLevel.Info, CsDComponent.AI); //Debug.Log("Enqueueing action " + currentNode.CameFromAction.Name); actions.Enqueue(currentNode.CameFromAction); currentNode = currentNode.CameFrom; } return(actions); }
public GoapActionEat(GoapGoal goapGoal) : base(goapGoal) { cost = 20; }
public void Initialize(Character character) { _parentCharacter = character; WorkingMemory = new WorkingMemory(); WorkingMemory.Initialize(_parentCharacter); BlackBoard = new BlackBoard(); Sensor = new AISensor(); Sensor.Initialize(_parentCharacter); TargetingSystem = new AITargeting(); TargetingSystem.Initialize(_parentCharacter); WeaponSystem = new AIWeapon(); WeaponSystem.Initialize(_parentCharacter); Planner = new GoapPlanner(this); _goals = GameManager.Inst.DBManager.DBHandlerAI.GetCharacterGoalSet(_parentCharacter.ID); _actions = GameManager.Inst.DBManager.DBHandlerAI.GetCharacterActionSet(_parentCharacter.ID); _currentWorldStates = new List<GoapWorldState>(); _parentCharacter.MyEventHandler.OnNewEnemyTargetFound += OnImportantEvent; _parentCharacter.MyEventHandler.OnCurrentActionComplete += OnCurrentActionComplete; //update parent character for each action foreach(GoapAction action in _actions) { action.ParentCharacter = _parentCharacter; } BlackBoard.PatrolLoc = new Vector3(-15, 0, -15); BlackBoard.PatrolRange = new Vector3(20, 10, 20); BlackBoard.HasPatrolInfo = true; if(ControlType != AIControlType.Player) { _currentGoal = null; _currentAction = null; FindAndExecuteAction(); } }
public GoapActionReset(GoapGoal goapGoal) : base(goapGoal) { cost = 30; }
//AI Events public void OnImportantEvent() { //when an important event happens, stop current action and reevaluate all the goals and pick the highest priority goal if(_currentAction != null) { _currentAction.StopAction(); _currentAction = null; } _currentGoal = null; FindAndExecuteAction(); }
public GoapActionCook(GoapGoal goapGoal) : base(goapGoal) { cost = 10; }
private void AddGoal(GoapGoal goal) { if(_goals.Count < 5) { _goals.Add(goal); } }
public GoapActionPlayBall(GoapGoal goapGoal) : base(goapGoal) { cost = 50; }
private bool EvaluateGoal(GoapGoal goal) { //check which goal's conditions are met bool isGoalMet = true; foreach(GoapWorldState state in goal.GoalStates) { object value = EvaluateWorldState(state); if(value != state.Value) { //this goal isn't met! isGoalMet = false; return isGoalMet; } } return isGoalMet; }