Agent Definitions: Difference between revisions
No edit summary |
mNo edit summary |
||
Line 230: | Line 230: | ||
An Interest may be a Device, or may simply be a particular part of a level that an AI needs to get to in order to perform an Action. An Interest is created by adding an InterestPoint to a GameObject (or making a new GameObject with an InterestPoint added). Be sure to orient the GameObject such that the Z axis is pointing in the direction the AI should use the InterestPoint from. | An Interest may be a Device, or may simply be a particular part of a level that an AI needs to get to in order to perform an Action. An Interest is created by adding an InterestPoint to a GameObject (or making a new GameObject with an InterestPoint added). Be sure to orient the GameObject such that the Z axis is pointing in the direction the AI should use the InterestPoint from. | ||
==== canUse ==== | ==== canUse ==== | ||
This is a using Action. The Agent will attempt to reach the nearest Interest that they know to be working, and try to use it. If it's in an Amok state, this may fail. | This is a using Action. The Agent will attempt to reach the nearest Interest that they know to be working, and try to use it. If it's in an Amok state, this may fail. The table is pretty similar to a standard [[#Action|Action]]. | ||
{| class="wikitable" | |||
!colspan="2" | canUse Table | |||
|- | |||
! Name !! Description | |||
|- | |||
| ''interest'' || The name of the InterestPoint this Action will take place at. | |||
|- | |||
| ''effect'' || The effect [[#GOAP State|GOAP State]]. This will be applied to the World State when this Action is performed. | |||
|- | |||
| ''required'' || The required [[#GOAP State|GOAP State]]. The World State must include this state in order for the Action to be used. | |||
|- | |||
| ''personalityEffect'' || Optional. The [[#Statistics|effect]] on personality stats that performing this Action has. | |||
|- | |||
| ''personalityRequirement'' || Optional. For this Action to be performed, this [[#Personality|requirement]] must be satisfied. | |||
|} | |||
==== canFix ==== | ==== canFix ==== | ||
This will eventually be a fixing Action. (TODO!) | This will eventually be a fixing Action. (TODO!) | ||
[[Category:Modding]] | [[Category:Modding]] |
Revision as of 12:52, 6 December 2018
Agent Definitions
Each AI's behaviour is defined by its Agent definition.
Concepts
GOAP State
The World State and Goal states are made up of GOAP States. GOAP stands for "Goal-Oriented Action Planning". Each state comprises a unique string ID, and a boolean (true/false) value. The state as a whole is made up of multiple state items.
GOAP State Item | |
---|---|
Name | Description |
state | The unique name of the state. |
value | The true/false value. |
A state is made up of 1-n items. This can be represented either as
{ { state = "amused", value = false }, { state = "tired", value = false }, }
or, for a state with a single item in, as
{ state = "amused", value = false }
...which saves some slightly untidy extra braces. Note that in the former example, the items are just an anonymous list, the keys are implicit. GOAP State is a type that will appear throughout this guide and it is always parsed in the same way.
Personality
Each AI (TBC: Human AI?) should have a personality profile. This describes the AI's likes, loves, family, dog... anything you like. This is one of the main mechanisms for differentiating behaviour between agents - thus allowing a player's actions to affect multiple agents in multiple ways, and allows for complex behaviour. The mechanism for doing this is the Personality Requirement.
Personality Requirement | ||
---|---|---|
Name | Type | Description |
subject | string | The primary tag that this requirement is seeking. |
value | string | Optional. The value that has a tag matching subject. |
other | string | Optional. Another tag, or list of tags, that the value must match with for this requirement to be satisfied. |
inverse | boolean | Defaults to false. Setting to true swaps the result of the requirement - so a match means the requirement fails, and the lack of a match means the requirement passes. |
Here's a snippet of a Personality Profile.
{ data = { "HipHop", "Pop"}, tags = { "music", "likes" } }, { data = { "Rock"}, tags = { "music", "dislikes" } }, { data = { "Classical", "HipHop"}, tags = { "music", "relaxes" } }, { data = { "LiverpoolReds" }, tags = { "sport", "likes", "celebrates" } },
So, this AI considers that HipHop & Pop are both music, and they like it. They consider Rock to be music, but they dislike it. They consider Classical and HipHop to be music that relaxes them. They consider LiverpoolReds to be related to sport, they like it, and they celebrate it.
The only mandatory part of a requirement is the subject. The subject is merely a tag, but it's the tag we look for first, and it's the tag that can be specified by API call ChangeSubject. Let's write a requirement that will pass using only the subject.
personalityRequirement = { subject = "music" },
This requirement, wherever it's used, will pass if the subject of "music" is set to "HipHop", "Pop", "Rock", or "Classical". So for instance, we might trigger a Dance Action if music is set to any of these. But that might not make a huge amount of sense for this AI, because they're not so keen on Rock music. So let's add an extra tag that we need for this requirement to be satisfied.
personalityRequirement = { subject = "music", other = "likes" },
This means the requirement will no longer pass for "Classical" or "Rock", because they aren't tagged as "likes" in their profile. That makes more sense! But... do we want the AI to perform the same dance to "HipHop" and "Rock"? Possibly not. This is where the value attribute is useful.
personalityRequirement = { value = "Rock", subject = "music", other = "likes" },
This requirement only passes for agents who like Rock music.
Finally, what's inverse for? Essentially, it's for checking for the absence of something. Consider the requirement
personalityRequirement = { value = "ManchesterBlues", subject = "celebrates", inverse = true },
Well spotted - "ManchesterBlues" is not present in our profile snippet. This means that, without the inverse flag, this requirement would fail. But with it, it passes! So, supposing we had a radio which set the subject as "celebrates", and the value as "ManchesterBlues", we could get this AI to sob gently to himself, while the one stood next to him is overcome with joy.
Statistics
Each statistic is a tracked, saved, numerical value that represents a particular aspect of the AI. The value is clamped between 0 and 1. Each stat has two lists, above and below, of names and thresholds. These will become world states that become true when the value becomes greater or equal/lesser or equal (respectively) to the threshold value. Statistics can be adjusted by actions, responses, and reactions. In doing so the world state may change, and new goals become achievable.
Personality Effects will be referred to throughout this, so let's dig into them here.
Personality Effect | ||
---|---|---|
Name | Type | Description |
stat | string | The unique name of the stat. |
adjust | number | The value to be added to the current value of this stat. Use a negative number to reduce it! |
One of the simpler tables in the Agent Definition. Simply put, when this effect happens, the named stat will have adjust added to it. The stat will then be clamped in the range 0 - 1, and the world states that rely on it will be recalculated.
File Format
The definition is a single table, named Agent, containing several tables that define different aspects of an Agent.
World State
The World State is a description of everything an AI knows about, in the context of planning. It is simply a GOAP State.
Goals
A Goal is a state that an Agent desires to be in. The planner will seek to use the Actions at its disposal to come up with a plan (set of Actions) that it can run to adjust the current World State so that it includes the Goal state. At its heart is a GOAP State, but it has some extra wizardry too.
Personality Effect | ||
---|---|---|
Name | Type | Description |
goal | table | A GOAP State. |
interrupts | boolean | Defaults to false. When set to true, this Goal will interrupt any of lower priority if it becomes achievable. For instance, chasing the player is more important than eating a snack. |
priority | number | The higher the priority a goal is, the more important it is. As a result it will be attempted before lower priority goals. |
onCompletion | table | Optional. This is a GOAP State that will be applied to the World State when this goal is successful. Useful for cyclic tasks (e.g. patrolling). |
Stats
List of Statistics.
Statistic Table | ||
---|---|---|
Name | Type | Description |
name | string | Unique name for this statistic. |
default | number | Default value for this statistic. |
above | table | List of states that will become true when above or equal to the specified threshold (see next table). |
below | table | List of states that will become true when below or equal to the specified threshold (see next table). |
Statistic-State Table | ||
---|---|---|
Name | Type | Description |
id | string | The name of the world state to be created. |
threshold | number | Threshold for this statistic. Behaviour depends upon whether this state is in the above or below table. |
So, what might this look like?
{ name = "happiness", default = 0.5, above = { { id = "elated", threshold = 1.00 } { id = "cheerful", threshold = 0.8 } } },
This stat is called happiness. It starts at 0.5. It has two world states, "elated", which becomes true at maximum happiness (1.0), and "cheerful", which happens when it's merely 0.8.
{ name = "energy", default = 0.5, above = { id = "energized", threshold = 1.0 }, below = { id = "tired", threshold = 0.0 } },
Notice that this one has a single entry in both above and below, missing out the nested brackets.
Actions
An Actions is something that the AI does. In order to do it, it must have a particular world state. After having done it, it will change its world state.
Action Table | |
---|---|
Name | Description |
name | The name of the Action, which should be unique. |
gesture | Optional. The gesture to play when performing this Action. |
effect | The effect GOAP State. This will be applied to the World State when this Action is performed. See XXXX |
required | The required GOAP State. The World State must include this state in order for the Action to be used. |
personalityEffect | Optional. The effect on personality stats that performing this Action has. |
targetAgent | Default false. If true, the Agent requires that there be another agent nearby for this Action to be performed. |
targetPlayer | Default false. If true, the Agent requires that the player be nearby for this Action to be performed. |
targetRequirement | Optional. The required personality profile this AI needs for this Action to run. |
Responses
A response is a method of adjusting an AI's personality stats when another AI performs an Action on them.
Response Table | |
---|---|
Name | Description |
Action | The name of the Action, which should be unique. |
personalityEffect | The effect on personality stats that being the victim of this Action has. |
Reactions
A reaction is a method of adjusting an AI's personality stats when they do something, based on their personality profile. These effects will be performed when ReactTo is called, if the requirement is satisfied.
Reaction Table | |
---|---|
Name | Description |
personalityRequirement | The requirement, which, when reacted to, will bring about the effect. |
personalityEffect | The effect on personality stats that occurs. |
Let's look at a quick example of how to use this.
{ personalityEffect = { stat = "energy", adjust = -0.5 }, personalityRequirement = { subject = "music", other = "relaxes" }, }
Here we have an effect that requires a personality entry that is tagged both as "music", and "relaxes". How does this get used? Well, for the purpose of this example, let's assume this AI has stepped into earshot of a radio, which has its own script. As a result, the following is called
AI.ReactTo(theAI, "music", "Classical")
What does this do? This says that the AI (which will be referred to by the variable theAI, a string referencing the AI's ID) should "React To" some external influence of tag "music", with the value of "Classical". If this requirement holds, the effect applies.
So the AI with this personality will have the effect applied, in this situation...
{ data = { "Classical", "HipHop"}, tags = { "music", "relaxes" } },
...and this AI won't.
{ data = { "Dance"}, tags = { "music", "relaxes" } },
Interests
An Interest may be a Device, or may simply be a particular part of a level that an AI needs to get to in order to perform an Action. An Interest is created by adding an InterestPoint to a GameObject (or making a new GameObject with an InterestPoint added). Be sure to orient the GameObject such that the Z axis is pointing in the direction the AI should use the InterestPoint from.
canUse
This is a using Action. The Agent will attempt to reach the nearest Interest that they know to be working, and try to use it. If it's in an Amok state, this may fail. The table is pretty similar to a standard Action.
canUse Table | |
---|---|
Name | Description |
interest | The name of the InterestPoint this Action will take place at. |
effect | The effect GOAP State. This will be applied to the World State when this Action is performed. |
required | The required GOAP State. The World State must include this state in order for the Action to be used. |
personalityEffect | Optional. The effect on personality stats that performing this Action has. |
personalityRequirement | Optional. For this Action to be performed, this requirement must be satisfied. |
canFix
This will eventually be a fixing Action. (TODO!)