6 ms·
> What sets F.E.A.R. apart is the fact that [...] A* is used to plan actions as well as paths. [...] If the Player slams a door on a pursing enemy, the soldier
by E6300 10y ago
> What sets F.E.A.R. apart is the fact that [...] A* is used to plan actions as well as paths. [...] If the Player slams a door on a pursing enemy, the soldier can dynamically re-plan and decide to fire through the window, or flank through an alternate entrance.
Interesting idea. Clever use of a classic algorithm in a novel way.
- frik 10y agoA* was pretty new back then. Previous iteration of games just 2-3 years older used older algos, or invented new path finding algos due CPU constraints.
- omginternets 10y agoA* dates back to 1968 [0] It's an extension of Dijkstra's algorithm that adds a few heuristics. [0] http://ieeexplore.ieee.org/document/4082128/ http://ieeexplore.ieee.org/document/4082128/
- hjnilsson 10y agoA* is much older than that. Age of Empires and Warcraft for example used it 10 years before F.E.A.R.
- frik 10y agoI was speaking about RTS and in the sense of Age of Empires 1 and Empire Earth. The main dev of both this titles Rick Goodwell mentioned A* was used in Empire Earth the first time, older AoE1 used an older less CPU intensive algo. @omginternets: > dates back ... extension of ... adds a few heuristics. Blabla, BS. Fact is Empire Earth was one of the very first computer games to use A* algo. Age of Empires 1 used a worse faster different algo. Fact is in the age before Wikipedia and Google, decade old papers of obscure algos were more or less lost and forgotten. They were written on paper with no digital copy readly available. So game devs often reinvented things without not knowing of previous work, it took several years until the early 2000s that this old stuff got scanned and made public viewable.
- E6300 10y ago> The main dev of both this titles Rick Goodwell mentioned A* was used in Empire Earth the first time, older AoE1 used an older less CPU intensive algo. Citation? The only mention I can find about the pathfinding algorithm used by Age of Empires is this: http://artho.com/age/pathfinding.html http://artho.com/age/pathfinding.html A* is supposed to be an optimization of Dijkstra's. I don't know why you call it CPU intensive.
- deleted 10y ago[deleted]
- JustForFun 10y agoThe 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; } // ----------------------------------------------------------------------- //