/// <summary> /// compare the fed worldstate to a newly generated one, if they have different enemy data, replan. /// </summary> /// <param name="_worldState">World state.</param> public override bool Sense(GoapPlan _currentPlan, GoapWorldstate _worldState) { bool changeSensed = false; GoapWorldstate oldState = _worldState, newState = new GoapWorldstate(); //generate a new worldstate newState.generateWorldState(core.actor); //if the enemy data is different, the enemies have changed and a new plan should be forged if (CompareEnemyData(oldState.enemyData, newState.enemyData)) { //drop the current target enemy core.actor.targetEnemy = null; changeSensed = true; } //push the new worldstate into the core core.setWorldState(newState); //return the verdict return changeSensed; }
public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState) { //target a visible enemy //if there is only one enemy visible, target it if (_worldState.enemyData.Count == 1) { core.actor.targetEnemy = _worldState.enemyData[0].enemy; } else //if there are more, choose the closest { ActorBase closest = null; float closestDistance = float.PositiveInfinity; foreach (EnemyPosition _enemyData in _worldState.enemyData) { float testDistance = Vector3.Distance(core.actor.transform.position, _enemyData.enemy.transform.position); if (testDistance < closestDistance) { closest = _enemyData.enemy; closestDistance = testDistance; } } core.actor.targetEnemy = closest; } return true; }
public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState) { GameObject goalNode = null; //if the path has not already been made if (_currentPlan.plannedPath.Value == null || _currentPlan.plannedPath.Key != actionName) { KeyValuePair<string, List<GameObject>> tempPath = new KeyValuePair<string, List<GameObject>>(actionName, _currentPlan.plannedPath.Value); _currentPlan.plannedPath = tempPath; TruncOct enemyTroct= core.actor.targetEnemy.currentTrOct.GetComponent<TruncOct>(); List<TruncOct> inLineTrocts = new List<TruncOct>(); //List all trocts leading from enemy location //loop through all faces of the troct for (int i = 0; i < enemyTroct.Faces.Count; i++) { //if the current face has no connection, continue to the next face. if (enemyTroct.connections[i] != TruncOct.connectionState.Connected) { continue; } else //else it it connected and should be pushed as far as it can go outwards { //get the next troct TruncOct newTroct = _worldState.topology[enemyTroct.connectionObjects[i]].GetComponent<TruncOct>(); List<TruncOct> direction = new List<TruncOct>(); direction.Add(newTroct); inLineTrocts.AddRange (TroctsInDirection(direction, i, newTroct, _worldState)); } } //find the closest one that is avaliable float closestDistance = float.MaxValue; TruncOct closestTroct; for (int i = 0; i < inLineTrocts.Count; i++) { float tempDist = Vector3.Distance(core.actor.currentTrOct.transform.position, inLineTrocts[i].transform.position); if (tempDist < closestDistance) { closestDistance = tempDist; closestTroct = inLineTrocts[i]; goalNode = closestTroct.gameObject; } } //now plot a route to A* pathfind to _currentPlan.plotRoute(core.actor, core.actor.currentTrOct, goalNode); } //try to follow the A* path return ProceedAlongPath(_currentPlan); }
public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState) { //if we have 2 action points left, heal otherwise remove last action points and continue if (!core.actor.TryToRepair()) { core.actor.actionPoints = 0; return false; } return true; }
//does this action need to be done. public override bool Test(GoapWorldstate _worldState) { //if there is not a target enemy if (core.actor.targetEnemy == null) { //the we need to target one return true; } //there is already a target return false; }
public override float calcWeight (GoapWorldstate _actorWorldState) { float totalWeight = 1 - (core.actor.health / 100f); //if not at full health and there are no visible enemies, it may as well heal if (core.actor.health != core.actor.maxHealth && _actorWorldState.enemyData.Count == 0) { baseWeight = 1f; } return totalWeight; }
//does this action need to be done. public override bool Test(GoapWorldstate _worldState) { GoapWorldstate worldState = core.getworldState (); //if enemies are in this actor's worldstate, they dont need to find enemies. if (worldState.enemyData.Count != 0) { return false; } else //else this does need to be done and enemies need to be found. { return true; } }
public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState) { GameObject goalNode = null; //if there is not currently a path, plot a course towards a random undiscovered area if (_currentPlan.plannedPath.Value == null) { //compile a list of all trocts concealed by the fow List<GameObject> undiscoveredTrocts = new List<GameObject>(); foreach (GameObject _trOctObj in _worldState.topology) { if (_trOctObj.GetComponent<TruncOct>().inFow) { undiscoveredTrocts.Add(_trOctObj); } } //find the one with the largest combined distance from all allies float biggestDistance = 0f; GameObject furthestTroct; for (int i = 0; i < undiscoveredTrocts.Count; i++) { float totalDistance = 0f; for (int j = 0; j < _worldState.allies.Count; j++) { totalDistance += Vector3.Distance(undiscoveredTrocts[i].transform.position, _worldState.allies[j].currentTrOct.transform.position); } if (totalDistance > biggestDistance) { furthestTroct = undiscoveredTrocts[i]; biggestDistance = totalDistance; //this will be the goal TrOct goalNode = furthestTroct; } } //plot a route using the central A* plotter through the current plan _currentPlan.plotRoute(core.actor, core.actor.currentTrOct, goalNode); } // attempt to follow the path that was either preexisting or was just generated return ProceedAlongPath(_currentPlan); }
private List<TruncOct> TroctsInDirection(List<TruncOct> _troctsInLine, int _facing, TruncOct _rootTroct, GoapWorldstate _worldState) { //see if the facing is connected if (_rootTroct.connections[_facing] != TruncOct.connectionState.Connected) { return _troctsInLine; } else //there is a connection { TruncOct newTroct = _worldState.topology[_rootTroct.connectionObjects[_facing]].GetComponent<TruncOct>(); _troctsInLine.Add(newTroct); _troctsInLine = (TroctsInDirection(_troctsInLine, _facing, newTroct, _worldState)); } return _troctsInLine; }
//does this action need to be done? public override bool Test(GoapWorldstate _worldState) { //are we currently facing the enemy already? if (!core.actor.targetEnemy) { return true; } //get the enemy's troct TruncOct enemyTroct = core.actor.targetEnemy.currentTrOct.GetComponent<TruncOct>(); //if the direction towards an enemy is the same as the direction of facing if ((enemyTroct.transform.position - core.actor.currentTrOct.transform.position).normalized == core.actor.transform.forward) { float distance = Vector3.Distance(enemyTroct.transform.position , core.actor.currentTrOct.transform.position); for (int j = 0; j < _worldState.allies.Count; j++) { TruncOct allyTroct = _worldState.allies[j].currentTrOct.GetComponent<TruncOct>(); //check there are no allies in the way. //is the ally in the same direction as the enemy but closer? if (((allyTroct.transform.position - core.actor.currentTrOct.transform.position).normalized == core.actor.transform.forward) && Vector3.Distance(allyTroct.transform.position , core.actor.currentTrOct.transform.position) < distance) { //an ally is in the way, move to a different position return true; } else { //no allies in the way and enemy a head return false; } } } //if here is reached there are no enemies within current sight. return true; }
/// <summary> /// If the actor is facing the next troct on the path and the path is obstructed and the current actor has action points left, replan /// </summary> /// <param name="_worldState">World state.</param> public override bool Sense(GoapPlan _currentPlan, GoapWorldstate _worldState) { //make a copy of the current path List<GameObject> path = _currentPlan.plannedPath.Value; //if the path is empty or we are at the end of the path, return false as no replanning has to be done as a result of the sensed state if (_currentPlan.plannedPath.Value == null) { return false; } else { if (_currentPlan.plannedPath.Value [0] == core.actor.currentTrOct) { _currentPlan.plannedPath.Value.RemoveAt (0); } } //find the next GO on the currentPath GameObject targetTroct = path[0]; Vector3 towardsTarget = (targetTroct.transform.position - core.actor.currentTrOct.transform.position).normalized; //is this actor facing the troct? if (towardsTarget == core.actor.transform.forward) { //is the target troct occupied? if (targetTroct.GetComponent<TruncOct>().containedActor != null) { //if so, replan return true; } } return false; }
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 override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState) { //SHOOT FORWARDS return core.actor.Shootforwards(); }
public void setWorldState(GoapWorldstate _worldState) { worldState = _worldState; }
/// <summary> /// Updates the worldstate. /// </summary> /// <returns>The new worldstate.</returns> private GoapWorldstate UpdateWorldstate () { GoapWorldstate newWorldState = new GoapWorldstate(); newWorldState.generateWorldState (actor); return newWorldState; }
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 override float calcWeight (GoapWorldstate _actorWorldState) { float totalWeight = baseWeight; return totalWeight; }
/// <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 override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState) { return false; }
calls; //the base function that is used to change the worldstate public abstract bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState);
//does this action need to be done. public override bool Test(GoapWorldstate _worldState) { TruncOct currentTroct = core.actor.currentTrOct.GetComponent<TruncOct>(); //are we already in line with the target? if (!core.actor.targetEnemy) { return true; } //do any enemy directions line up with the current troct faces? TruncOct enemyTroct = core.actor.targetEnemy.currentTrOct.GetComponent<TruncOct>(); foreach (Vector3 _facing in currentTroct.Faces) { if ((enemyTroct.transform.position - currentTroct.transform.position).normalized == _facing.normalized) { //they line up and so we do not need to line up a shot return false; } } return true; }
public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState) { //try to rotate towards the target enemy return core.actor.TryRotate(core.actor.targetEnemy.transform); }
//does this action need to be done. public override bool Test(GoapWorldstate _worldState) { return false; }
private List<GoapAction> FulfillPrereqs (List<GoapAction> _currentActionList, List<string> _currentPrerequisites, GoapWorldstate _worldstate) { foreach (string _prereq in _currentPrerequisites) { //find the item to fulfill the current prereq foreach (GoapAction _action in actionPool) { if (_action.fulfillment == _prereq) { //if the action does not need to be done, no more need to be added, so just return the actionlist as is if (!_action.Test (_worldstate)) { return _currentActionList; } else { _currentActionList.Insert (0, _action); List<string> prereqs = _action.prerequisites; _currentActionList = FulfillPrereqs (_currentActionList, prereqs, _worldstate); } } } } return _currentActionList; }
public abstract bool Sense(GoapPlan _currentPlan, GoapWorldstate _worldState);
//does this action need to be done. public override bool Test(GoapWorldstate _worldState) { //this is the end action so it always need to be attempted. return true; }
/// <summary> /// Calculates the total weight of this goal. /// </summary> /// <returns>The weight.</returns> /// <param name="_actorWorldState">Actor world state.</param> public virtual float calcWeight (GoapWorldstate _actorWorldState) {return 0f;}
private GoapPlan ExecutePlan(GoapPlan _currentPlan, GoapWorldstate _worldState) { bool actionSuccess = true; int currentPlanAction = 0; //try to carry out the plan until an action attempt fails (or sensors interrupt) while (actor.actionPoints > 0) { //test all actions up to the current int value for retroactive analysis for (int i = 0; i < currentPlanAction; i++) { if (_currentPlan.actionOrder[i].Test(_worldState)) { currentPlanAction = i; break; } } //if the action on the top of the stack needs to be done if (_currentPlan.actionOrder[currentPlanAction].Test (_worldState)) { //run sensors GoapPlan tempPlan = CheckSensors(_currentPlan, _worldState); //if the plans differ if (!ComparePlans(_currentPlan, tempPlan)) { return tempPlan; } //try to carry it out and have it set the result of actionSuccess depending on a success or failure actionSuccess = _currentPlan.actionOrder[currentPlanAction].Action(_currentPlan, _worldState); if (actionSuccess) //if an action was successfully done,check if it will need to be continued (with a new worldstate) { _worldState.generateWorldState (actor); //if the action no longer needs to be done, pop it from the stack if (!_currentPlan.actionOrder[currentPlanAction].Test (_worldState)) { currentPlanAction ++; } tempPlan = CheckSensors (_currentPlan, getworldState ()); //call sensors as a precaution if (!ComparePlans(_currentPlan, tempPlan)) { return tempPlan; } } } else//move to the next operation in the plan the plan, as it doesnt need to be carried out { currentPlanAction++; } } //return the plan now that it has been processed and attempted return _currentPlan; }
public abstract bool Test(GoapWorldstate _worldState);
/// <summary> /// Calls the sensors one at a time in order to see if the plan needs changing in accordance to worldstate changes /// </summary> /// <returns>The altered goal if the sensors call for a replan</returns> /// <param name="">.</param> private GoapPlan CheckSensors (GoapPlan _currentPlan, GoapWorldstate _worldState) { foreach (GoapSensor _sensor in sensors) { //if a replan is needed according to the current sensor if (_sensor.Sense(_currentPlan, _worldState)) { //resort goals, and from this formulate a new plan return FormulatePlan(SortGoals(_worldState), _worldState); } } //if all is fine, return the plan back as it was, it is fine. return _currentPlan; }