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;
	}
	/// <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;
	}
	/// <summary>
	/// Proceeds the along path.
	/// </summary>
	/// <returns><c>true</c>, if progress along the path was made, <c>false</c> otherwise.</returns>
	protected bool ProceedAlongPath(GoapPlan _currentPlan)
	{
		//find the next GO on the currentPath
		GameObject targetTroct = _currentPlan.plannedPath.Value[0];

		Vector3 towardsTarget = (targetTroct.transform.position - core.actor.currentTrOct.transform.position).normalized;

		//is this actor facing the troct?
		if (towardsTarget == core.actor.transform.forward)
		{
			//if so, try move forwards
			if (core.actor.TryMoveForwards())
			{
				_currentPlan.plannedPath.Value.RemoveAt(0);

				//see if the target node has been reached
				if (_currentPlan.plannedPath.Value.Count == 0)
				{
					KeyValuePair<string, List<GameObject>> tempPath = new KeyValuePair<string, List<GameObject>>(_currentPlan.plannedPath.Key, null);
					_currentPlan.plannedPath = tempPath;
				}

				return true; //return a successful progression along the path
			}
			else
			{
				return false; // return an unsuccessful progression along the path
			}
		}
		else //turn to face the next TrOct
		{
			return core.actor.TryRotate(targetTroct.transform); //return the result of attempting to look at the next troct.
		}
	}
	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;
	}
	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);
	}
	/// <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;
	}
	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;
	}
	calls; 						//the base function that is used to change the worldstate

	public abstract bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState);
	public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState)
	{
		return false;
	}
Beispiel #11
0
 private void Init()
 {
     goapPlan = new GoapPlan();
 }
	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;
	}
	/// <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;
	}
	/// <summary>
	/// Compares to see if plans are equal from their planning data (as the reference to the core will always flag them as different otherwise).
	/// </summary>
	/// <returns><c>true</c>, if plans are the same <c>false</c> otherwise.</returns>
	/// <param name="_planA">Plan a.</param>
	/// <param name="_planB">Plan b.</param>
	private bool ComparePlans(GoapPlan _planA, GoapPlan _planB)
	{
		//if the goals differ
		if (_planA.goalBeingFulfilled != _planB.goalBeingFulfilled)
		{
			//return stating this difference
			return false;
		}

		GoapAction[] tempA = _planA.actionOrder.ToArray(),
		tempB = _planB.actionOrder.ToArray();

		for (int i = 0; i < tempA.Length; i++)
		{
			if (tempA[i] != tempB[i])
			{
				return false;
			}
		}

		//else they must be the same
		return true;
	}
	/// <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;
	}
	/// <summary>
	/// Carry out the GOAP action, in this case, move to a safer area.
	/// </summary>
	/// <param name="_currentPlan">Current plan.</param>
	/// <param name="_worldState">World state.</param>
	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;

			List<TruncOct> inLineTrocts = new List<TruncOct>();

			//compile a list of trocts from all visible enemies
			for (int i = 0; i < _worldState.enemyData.Count; i++)
			{
				TruncOct enemyTroct = _worldState.enemyData[i].enemyLocation;

				//List all trocts leading from enemy location
				//loop through all faces of the troct
				for (int j = 0; j < enemyTroct.Faces.Count; j++)
				{
					//if the current face has no connection, continue to the next face.
					if (enemyTroct.connections[j] != 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[j]].GetComponent<TruncOct>();

						List<TruncOct> direction = new List<TruncOct>();
						direction.Add(newTroct);

						inLineTrocts.AddRange (TroctsInDirection(direction, j, newTroct, _worldState));
					}
				}
			}

			//find the closest troct in line that is not in line with the enemy
			List<TruncOct> inLineSelf = new List<TruncOct>();

			TruncOct thisTroct = core.actor.currentTrOct.GetComponent<TruncOct>();

			//loop through all faces of the troct
			for (int i = 0; i < thisTroct.Faces.Count; i++)
			{
				//if the current face has no connection, continue to the next face.
				if (thisTroct.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[thisTroct.connectionObjects[i]].GetComponent<TruncOct>();

					List<TruncOct> direction = new List<TruncOct>();
					direction.Add(newTroct);

					inLineSelf.AddRange (TroctsInDirection(direction, i, newTroct, _worldState));
				}
			}

			TruncOct targetTroct = null;

			//compare to find a troct that is not inline with an enemy
			for (int i = 0; i < inLineSelf.Count; i++)
			{
				if (!inLineTrocts.Contains(inLineSelf[i]))
				{
					targetTroct = inLineSelf[i];
					break;
				}			
			}

			//if a new location still needs to be found
			if (targetTroct == null)
			{
				//else find a close troct that is not in line
				List<TruncOct> closeTrocts = new List<TruncOct>();

				foreach(GameObject _tObject in GameManager.instance.allTrocts)
				{
					if (Vector3.Distance(core.actor.transform.position, _tObject.transform.position) <= (core.actor.viewDistance / 1.5f))
					{
						if (!inLineTrocts.Contains(_tObject.GetComponent<TruncOct>()))
						{
							targetTroct = _tObject.GetComponent<TruncOct>();
						}
					}
				}

				//if a close one cant be found, just generate a random one by force, we must move!
				while ((!inLineTrocts.Contains(targetTroct) && targetTroct == null) || targetTroct == null)
				{
					TruncOct rand = GameManager.instance.allTrocts[Random.Range(0, GameManager.instance.allTrocts.Count)].GetComponent<TruncOct>();

					if (!inLineTrocts.Contains(rand))
					{
						targetTroct = rand;
						break;
					}
				}
			}

			goalNode = targetTroct.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 abstract bool Sense(GoapPlan _currentPlan, GoapWorldstate _worldState);
	public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState)
	{
		//try to rotate towards the target enemy
		return core.actor.TryRotate(core.actor.targetEnemy.transform);
	}
	public override bool Action(GoapPlan _currentPlan, GoapWorldstate _worldState)
	{
		//SHOOT FORWARDS
		return core.actor.Shootforwards();
	}
Beispiel #20
0
 private void Init()
 {
     goapPlan             = new GoapPlan();
     usableGoapActionList = goapGoal.GetActions();
 }