void OnlinePlanExpansionExecution::OnGoalNodeSucceeded(_In_ IOlcbpPlan::NodeID nodeId) { GoalEx* pGoal = (GoalEx*)m_pOlcbpPlan->GetNode(nodeId); _ASSERTE(pGoal->State() == ESTATE_Succeeded); if (GetNodeData(nodeId).BelongingCase != nullptr) { LogInfo("Goal=%s succeeded, revising its case and retaining it", pGoal->ToString().c_str()); CaseEx* currentCase = GetLastCaseForGoalNode(nodeId); m_pCbReasoner->Reviser()->Revise(currentCase, true); //UpdateHistory(currentCase); } else { LogInfo("Goal=%s succeeded without expansion, no case to revise", pGoal->ToString().c_str()); } UpdateBelongingSubplanChildrenWithParentReadiness(nodeId); OnNodeDone(nodeId); if (m_planRootNodeId == nodeId) { g_MessagePump->Send(new Message(0, MSG_PlanComplete)); } }
void OnlinePlanExpansionExecution::OnGoalNodeFailed(_In_ IOlcbpPlan::NodeID nodeId) { GoalEx* pGoal = (GoalEx*)m_pOlcbpPlan->GetNode(nodeId); _ASSERTE(pGoal->State() == ESTATE_Failed); if (GetNodeData(nodeId).BelongingCase != nullptr) { LogInfo("Goal=%s failed, revising and retaining it", pGoal->ToString().c_str()); CaseEx* currentCase = GetLastCaseForGoalNode(nodeId); m_pCbReasoner->Reviser()->Revise(currentCase, false); //UpdateHistory(currentCase); } OnNodeDone(nodeId); }
bool OnlinePlanExpansionExecution::UpdateGoalNode(_In_ IOlcbpPlan::NodeID currentNode, _In_ const WorldClock& clock) { bool expanded = false; GoalEx* pCurrentGoalNode = (GoalEx*)m_pOlcbpPlan->GetNode(currentNode); // fast return if node state reached a final state (i.e succeeded or failed) _ASSERTE(!IsNodeDone(currentNode)); #pragma region Node Open if (IsNodeOpen(currentNode)) { _ASSERTE(pCurrentGoalNode->GetState() == ESTATE_NotPrepared); _ASSERTE(IsNodeDone(currentNode) == false); bool hasPreviousPlan = DestroyGoalSnippetIfExist(currentNode); // The goal was previously expanded with a plan, but it somehow failed // Thats why it is now open // Revise the node belonging case as failed case if (hasPreviousPlan) { LogInfo("Node with plan-step '%s' is open and has children nodes, case is sent for revision and children have been destroyed", pCurrentGoalNode->ToString().c_str()); CaseEx* currentCase = GetLastCaseForGoalNode(currentNode); m_pCbReasoner->Reviser()->Revise(currentCase, false); UpdateHistory(currentCase); } if (pCurrentGoalNode->SuccessConditionsSatisfied(*g_Game)) { LogInfo("Goal %s already satisfied, no need to expand it, closing the node", pCurrentGoalNode->ToString().c_str()); pCurrentGoalNode->SetState(ESTATE_Succeeded, *g_Game, clock); CloseNode(currentNode); OnGoalNodeSucceeded(currentNode); } else { IOlcbpPlan::NodeID satisfyingGoalNode = GetNodeData(currentNode).SatisfyingGoal; AbstractRetriever::RetrieveOptions options; options.ExcludedCases = GetNodeData(currentNode).TriedCases; if (satisfyingGoalNode != IOlcbpPlan::NullNodeID) { LogInfo("Excluding satisfying goal node %s to avoid recursive plan expansion", m_pOlcbpPlan->GetNode(satisfyingGoalNode)->ToString().c_str()); // Add belonging case to exclusion to avoid recursive expansion of plans _ASSERTE(GetNodeData(satisfyingGoalNode).BelongingCase != nullptr); options.ExcludedGoalHashes.insert(GetNodeData(satisfyingGoalNode).BelongingCase->Goal()->Hash()); } //pCurrentGoalNode->AdaptParameters(*g_Game); options.GoalTypeId = (GoalType)pCurrentGoalNode->StepTypeId(); options.pGameState = g_Game; options.Parameters = pCurrentGoalNode->Parameters(); CaseEx* pCandidateCase = m_pCbReasoner->Retriever()->Retrieve(options); // We found a matching case and it was not tried for that goal before if (pCandidateCase != nullptr) { // Retriever should always retrieve a non tried case for that specific node // _ASSERTE(!IsCaseTried(currentNode, pCandidateCase)); LogInfo("Retrieved case '%s' has not been tried before, and its goal is being sent for expansion", pCandidateCase->Goal()->ToString().c_str()); MarkCaseAsTried(currentNode, pCandidateCase); ExpandGoal(currentNode, pCandidateCase); expanded = true; } else { // The current failed goal node is the root goal and the planner exhausted all possible // plans form the case-base for that goal node and nothing succeeded so far // // WE SURRENDER!! // if (m_planRootNodeId == currentNode) { LogWarning("Planner has exhausted all possible cases, WE SURRENDER!!"); m_planRootNodeId = IOlcbpPlan::NullNodeID; } else { LogInfo("Goal=%s exhausted all possible cases, failing it", pCurrentGoalNode->ToString().c_str()); pCurrentGoalNode->SetState(ESTATE_Failed, *g_Game, clock); CloseNode(currentNode); OnGoalNodeFailed(currentNode); } } } } #pragma endregion #pragma region Node Closed else { _ASSERTE(pCurrentGoalNode->GetState() == ESTATE_NotPrepared); if (pCurrentGoalNode->SuccessConditionsSatisfied(*g_Game) && !HasActiveAction(currentNode)) { pCurrentGoalNode->SetState(ESTATE_Succeeded, *g_Game, clock); OnGoalNodeSucceeded(currentNode); } else { // The goal is not done yet, and all of its children are done and // finished execution. It does not make sense for the goal to continue // this goal should fail, it has no future if (GetNodeData(currentNode).WaitOnChildrenCount == 0) { if (!pCurrentGoalNode->IsSleeping(clock)) { if (pCurrentGoalNode->SleepsCount() < GoalMaxSleepsCount) { LogInfo("%s is still not done and all of its children are done execution, slept %d time(s) before, will send it to sleep", pCurrentGoalNode->ToString().c_str(), pCurrentGoalNode->SleepsCount()); pCurrentGoalNode->Sleep(clock, GoalSleepTime); } else { LogInfo("%s is still not done and all of its children are done execution, already tried to sleep it %d time(s) before, failing it", pCurrentGoalNode->ToString().c_str(), GoalMaxSleepsCount); OpenNode(currentNode); } } } } } #pragma endregion return expanded; }