3 ms·
The idea of reusing A* was amazing, but what it really means is that all the actions are implemented as C++ classes. This is just a consequence (of reuse A*); b
by JustForFun 10y ago
The idea of reusing A* was amazing, but what it really means is that all the actions are implemented as C++ classes. This is just a consequence (of reuse A*); but in fact it's a breakthrough in terms of planning runtime. On current average machines, GOAP in F.E.A.R. builds plans in far less than 1 milli-second.
Whereas academic planners at the time were struggling with PDDL (a symbolic declarative language for describing planning domains -- i.e. problems and actions which can appear in plans), GOAP rewrites all the actions in C++. Then, no problem for procedural preconditions and postconditions, for instance: just call C++ code to check what you have to.
-- JustForFun.
- E6300 10y agoWhat I'm wondering is, how does it work out certain situations? For example: The ultimate goal of an enemy AI is to shoot at the player. To do this, it must have a line of sight to the player. Figuring out where to stand seems to me equivalent to solving a perspective projection using the level geometry as constraints. Does it actually try to do this, or does it just not bother moving into line of sight and just moves towards the player's position?
- JustForFun 10y agoFrom AIActionAttackFromNode.cpp: // ----------------------------------------------------------------------- // // // ROUTINE: CAIActionAttackFromNode::ValidateContextPreconditions // // PURPOSE: Return true if real-time preconditions are valid. // // ----------------------------------------------------------------------- // bool CAIActionAttackFromNode::ValidateContextPreconditions( CAI* pAI, CAIWorldState& wsWorldStateGoal, bool bIsPlanning ) { // Intentionally do not call super::ValidateContextPreconditions(). // Firing from a node ignores range. // AI does not have a weapon of the correct type if (!AIWeaponUtils::HasWeaponType(pAI, GetWeaponType(), bIsPlanning)) { return false; } // AI does not have any ammo required by this weapon type. if ( !AIWeaponUtils::HasAmmo(pAI, GetWeaponType(), bIsPlanning ) ) { return false; } // AI must already be at a node. SAIWORLDSTATE_PROP* pProp = pAI->GetAIWorldState()->GetWSProp( kWSK_AtNode, pAI->m_hObject ); if( !( pProp && pProp->hWSValue ) ) { return false; } HOBJECT hNode = pProp->hWSValue; // Node must be derived from SmartObject. HCLASS hTest = g_pLTServer->GetClass( "AINodeSmartObject" ); HCLASS hClass = g_pLTServer->GetObjectClass( hNode ); if( !g_pLTServer->IsKindOf( hClass, hTest ) ) { return false; } // Node must be correct type. AINode* pNode = (AINode*)g_pLTServer->HandleToObject( pProp->hWSValue ); if( !( pNode && ( pNode->GetType() == m_pActionRecord->eNodeType ) ) ) { return false; } // The node must be valid in terms of FOV. if( pAI->HasTarget( kTarget_Character | kTarget_Object | kTarget_CombatOpportunity ) && pNode->IsNodeValid( pAI, pAI->GetPosition(), pAI->GetAIBlackBoard()->GetBBTargetObject(), kThreatPos_TargetPos, m_dwNodeStatus ) ) { return true; } // Preconditions are not valid. return false; } // ----------------------------------------------------------------------- //