BEHAVIOR_STATUS SequentialNode::execute(void* agent)
{
	if (currentPosition == -1) //starting out
	{
		init(agent);
		currentPosition = 0;
	}

	if (children.size() == 0)
		return BT_SUCCESS;

	BehaviorTreeNode* currentTask = children.at(currentPosition);
	BEHAVIOR_STATUS result = currentTask->execute(agent);

	while(result == BT_SUCCESS)
	{
		if (currentPosition == children.size()-1) //finished last task
		{
			currentPosition = -1; //indicate we are not running anything
			return BT_SUCCESS;
		}
		else
		{
			currentPosition++;
			currentTask = children.at(currentPosition);
			result = currentTask->execute(agent);
		}
	}
	if (result == BT_FAILURE)
		currentPosition = -1;
	return result;
}
	BEHAVIOR_STATUS CNodePriorityInterrupt::execute(void* agent)
	{
		if (children.size() == 0)
			return BT_SUCCESS;

		if (currentPosition == -1)
			init(agent);

		// Nodo que vamos a comprobar a continuación
		int checkedNode = 0;
		BEHAVIOR_STATUS status;
		BehaviorTreeNode* currentlyRunningNode;
		while (checkedNode < children.size()) //keep trying children until one doesn't fail
		{
			currentlyRunningNode = children.at(checkedNode);
			status = currentlyRunningNode->execute(agent);
			if (status == BT_FAILURE) {
				// Si el nodo falla al ejecutarse lo reiniciamos y pasamos al siguiente
				currentlyRunningNode->init(agent);
				checkedNode++;
			} else {
				// Si el nodo actual se ejecuta tenemos que comprobar si se ha interrumpido 
				// la ejecución de otro nodo menos prioritario, para poder reinicializarlo.
				// El último nodo no ejecutado se almacena en currentPosition. 
				// Tendremos que comprobar si tiene menos prioridad, es decir, si su índice
				// es mayor que el que ocupa el que acabamos de ejecutar con éxito.
				if (checkedNode < currentPosition)
					children.at(currentPosition)->init(agent);
				// Si el nodo ha terminado con éxito, el selector también termina con éxito
				if (status == BT_SUCCESS) {
					// Además, dejamos inicializado el nodo que acaba de terminar para la próxima vuelta
					currentlyRunningNode->init(agent);
					currentPosition = 0;
					return BT_SUCCESS;
				} else {
					// Sólo queda que el status sea BT_RUNNING
					// En este caso actualizamos el nodo actual por si ha cambiado
					currentPosition = checkedNode;
					return BT_RUNNING;
				}
				//assert(!"BT in an unsupported state");
			}
		}
		// Si ha llegado al final de la lista de nodos y todos han fallado el selector
		// tendrá también que fallar
		currentPosition = 0;
		return BT_FAILURE;
	}
예제 #3
0
BEHAVIOR_STATUS ParallelNode::execute(void* agent)
{
	if (childrenStatus == NULL)
		init(agent);
	// go through all children and update the childrenStatus
	for (unsigned int i = 0 ; i<children.size(); i++)
	{
		BehaviorTreeNode* node = children[i];
		if ((*childrenStatus)[node] == BT_RUNNING)
		{
			BEHAVIOR_STATUS status = node->execute(agent);
			if (status == BT_FAILURE)
			{
				if (failPolicy == FAIL_ON_ONE)
				{
					init(agent);
					return BT_FAILURE;
				}
				else
				{
					(*childrenStatus)[node] = BT_FAILURE;
				}
			}
			if (status == BT_SUCCESS)
				(*childrenStatus)[node] = BT_SUCCESS;
		}
		if ((*childrenStatus)[node] == BT_FAILURE && failPolicy == FAIL_ON_ALL) //theoretically the failPolicy check is not needed
		{
			BEHAVIOR_STATUS status = node->execute(agent);
			(*childrenStatus)[node] = status;
		}
	}

	//look through the childrenStatus and see if we have met any of our end conditions
	ChildrenStatusMap::iterator iter;
	bool sawSuccess = false;
	bool sawAllFails = true;
	bool sawAllSuccess = true;
	for (iter = childrenStatus->begin(); iter != childrenStatus->end() ; iter++)
	{
		switch((*iter).second)
		{
		case BT_SUCCESS:
			//can't instantly return success for succeedOnOne policy if failOnOne is also true, because failOnOne overrides succeedOnOne
			if (succeedPolicy == SUCCEED_ON_ONE && failPolicy != FAIL_ON_ONE)
			{
				init(agent);
				return BT_SUCCESS;
			}
			sawSuccess = true;
			sawAllFails = false;
			break;
		case BT_FAILURE:
			if (failPolicy == FAIL_ON_ONE)
			{
				init(agent);
				return BT_FAILURE;
			}
			sawAllSuccess = false;
			break;
		case BT_RUNNING:
			sawAllFails = false;
			sawAllSuccess = false;
			//optimization for early exit
			if (failPolicy == FAIL_ON_ALL && succeedPolicy == SUCCEED_ON_ALL)
			{
				return BT_RUNNING;
			}
			break;
		}
	}
	if (failPolicy == FAIL_ON_ALL && sawAllFails)
	{
		init(agent);
		return BT_FAILURE;
	}
	else if ((succeedPolicy == SUCCEED_ON_ALL && sawAllSuccess) ||
             (succeedPolicy == SUCCEED_ON_ONE && sawSuccess))
	{
		init(agent);
		return BT_SUCCESS;
	}
	else
	{
		return BT_RUNNING;
	}
}