Atualmente, estou desenvolvendo um sistema GOAP em Java. Uma explicação do GOAP pode ser encontrada em http://web.media.mit.edu/~jorkin/goap.html . Essencialmente, ele está usando A * para plotar entre ações que modificam o estado mundial.
Para fornecer uma chance justa de todas as ações e objetivos serem executados, estou usando uma função heurística para estimar o custo de fazer alguma coisa. Qual é a melhor maneira de estimar esse custo para que seja comparável a todos os outros custos?
Como exemplo, estimando o custo de fugir de um inimigo contra atacá-lo - como o custo deve ser calculado para ser comparável?
java
ai
path-finding
fullwall
fonte
fonte
Respostas:
Para tornar todos os custos comparáveis, você só precisa usar a mesma heurística para todas as ações. Por exemplo, todas as ações têm uma lista de possíveis resultados e todos os resultados têm um certo valor para a entidade.
Por exemplo, há uma piscina profunda com água e a entidade está com sede. Portanto, analisamos uma ação que o pool tem disponível para satisfazer essa necessidade:
Primeiro, as prioridades da entidade associadas a esses locais, você pode chamar de modificadores. Algumas delas mudam com o tempo e dependem da entidade. Por exemplo, uma formiga pode se preocupar menos em permanecer viva e mais em preocupações com colônias. Ou se uma entidade ficou um tempo sem beber, a prioridade de satisfazer a sede pode substituir outras.
Prioridades da entidade :
Satisfazer a sede: 40
Permanecer seco: 10
Permanecer vivo: 100
Então, o que o local representa:
Local : Piscina
Ação : Coletar água
* Resultados potenciais: * :
Satisfazer a sede - (-95)
Se molhar - 10 Se
afogar - 1
Portanto, podemos calcular esse custo de ação em: (40 * -95) + (10 * 10) + (100 * 1) = -3600
Onde a coleta de água de um rio furioso pode parecer:
Local : rio em fúria
Ação : Coletar água
* Resultados potenciais: * :
Satisfazer a sede - (-95)
Se molhar - 90
Afogar - 60
(40 * -95) + (10 * 90) + (100 * 60) = 3100
Portanto, é claramente uma melhor escolha coletar água da piscina. Talvez se o rio violento fosse a única opção, a entidade esperaria até que sua prioridade de satisfação da sede fosse muito alta antes de tentar o rio.
Você pode manter as coisas muito mais simples começando. Apenas tenha algumas variáveis que podem ser aplicadas de maneira mais global. Como permanecer vivo, satisfazer as necessidades. No seu exemplo de luta ou fuga, você precisa atribuir uma classificação a cada entidade para que elas possam se classificar efetivamente contra a outra entidade para fins de pontuação.
fonte
Eu sei, eu sei, já faz um bom tempo.
De fato, no GOAP implementado em 2005 por Jeff Orkin no FEAR (e reutilizado nas sequências, extensão e ... Shadow Of Mordor), as ações têm custos fixos, variando de 0,5 a 8. Em geral, o custo do ataque é muito alto. mais caro que o custo da defesa. Esses custos podem ser acessados no banco de dados de jogos do Free FEAR SDK (2008); aqui estão eles:
{{Animate, 1}, {Attack, 6}, {AttackBurstLimited, 5}, {AttackCrouch, 5}, {AttackFromAmbush, 4}, {AttackFromArmored, 4}, {AttackFromArmoredBounded, 4}, {AttackFromCover, 4}, { AttackFromVehicle, 1}, {AttackFromView, 4.5}, {AttackGrenadeFromCover, 2}, {AttackLunge3D, 1}, {AttackLungeMelee, 1}, {AttackLungeSuicide, 1}, {AttackLungeUncloaked, 1}, {AttackMelee, 3}, {AttackLigado, 3}, 1}, {AttackMeleeUncloaked, 3}, {AttackReady, 7}, {AttackTurret, 6}, {AttackTurretCeiling, 6}, {BlindFireFromCover, 2}, {Charge, 1}, {DeathOnVehicle, 1}, {DismountNodeUncloaked, 1} , {DismountVehicle, 1}, {DodgeCovered, 1}, {DodgeOnVehicle, 1}, {DodgeRoll, 2}, {DodgeRollParanoid, 2}, {DodgeShuffle, 3}, {DrawWeapon, 1}, {EscapeDanger, 0,5}, { FaceNode, 1}, {FlushOutWithGrenade, 3}, {Follow, 3}, {FollowHeavyArmor, 2}, {FollowPlayer, 2}, {FollowPlayerFidget, 1,8},{FollowWaitAtNode, 4}, {GetOutOfTheWay, 1}, {GotoNode, 1}, {GotoNode3D, 1}, {GotoNodeDirect, 1}, {GotoNodeOfType, 1}, {GotoTarget, 4}, {GotoTarget3D, 4}, {GotoTargetLost , 8}, {GotoValidPosition, 1}, {HolsterWeapon, 1}, {Idle, 2}, {IdleFidget, 1}, {IdleOnVehicle, 1}, {IdleTurret, 2}, {InspectDisturbance, 2}, {InstantDeath, 1 } {InstantDeathKnockDown, 1}, {KnockDownBullet, 2}, {KnockDownExplosive, 2}, {KnockDownMelee, 2}, {LongRecoilBullet, 3}, {LongRecoilExplosive, 3}, {LongRecoilHelmetPiercing, 3}, {LongRecoilMelee {LookAtDisturbance, 1.5}, {LookAtDisturbanceFromView, 3}, {LopeToTargetUncloaked, 1}, {MountNodeUncloaked, 1}, {MountVehicle, 1}, {ReactToDanger, 1}, {Reload, 5}, {ReloadCovered, 1}, {ReloadCrouch , 5}, {ShortRecoilMelee, 4}, {Atordoado, 1}, {SuppressionFire, 2}, {SuppressionFireFromCover, 1}, {SurveyArea, 1},{TraverseBlockedDoor, 1}, {TraverseLink, 2}, {TraverseLinkUncloaked, 1}, {Descobrir, 1}, {UseSmartObjectNode, 3}, {UseSmartObjectNodeMounted, 1}}
Mas não é o caso em todas as implementações GOAP e, por exemplo, os Tomb Raiders têm custos variáveis (por exemplo, a distância para uma ação Goto).
As ações também têm condições prévias e algumas ações devem ser executadas apesar da arquitetura do GOAP (por exemplo, reproduzir uma animação "atordoada" em reação que diminui rapidamente a saúde - apesar do objetivo "Kill Enemy" e do plano que o GOAP retorna para satisfazer esse objetivo). No seu exemplo, ou seja, fugir vs atacar, o nível de saúde pode ser uma condição prévia (e não é necessário ter custos variáveis).
Ou uma função de membro Check_Costs () é executada antes de qualquer outra coisa, com base nas prioridades de Michael, e retorna o custo dinâmico.
Agora, observe que em Shadow Of Mordor, os desenvolvedores de jogos tentaram brincar com os custos das ações para influenciar o que seria executado na tela. Acontece que não é tão fácil e nem mesmo uma ação barata aparece com tanta frequência: a IA em um jogo suporta o jogador; se o jogador não fizer o que é esperado, a IA apenas suportará isso e ... o que aparecerá na tela não será o design do jogo esperado.
fonte