Agent Definitions: Difference between revisions

From Off Grid Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 43: Line 43:
| ''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.
| ''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.
<syntaxhighlight source lang="lua" line start=5>
{ data = { "HipHop", "Pop"}, tags = { "music", "likes" } },
{ data = { "Rock"}, tags = { "music", "dislikes" } },
{ data = { "Classical", "HipHop"}, tags = { "music", "relaxes" } },
{ data = { "LiverpoolReds" }, tags = { "sport", "likes", "celebrates" } },
</syntaxhighlight>
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 [[AI Lua API#Change Subject|API call ChangeSubject]]. Let's write a requirement that will pass using only the subject.
<syntaxhighlight source lang="lua" line start=5>
personalityRequirement = { subject = "music" },
</syntaxhighlight>
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.
<syntaxhighlight source lang="lua" line start=5>
personalityRequirement = { subject = "music", other = "likes" },
</syntaxhighlight>
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.
<syntaxhighlight source lang="lua" line start=5>
personalityRequirement = { value = "Rock", subject = "music", other = "likes" },
</syntaxhighlight>
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
<syntaxhighlight source lang="lua" line start=5>
personalityRequirement = { value = "ManchesterBlues", subject = "celebrates", inverse = true },
</syntaxhighlight>
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.


== File Format ==
== File Format ==

Revision as of 17:37, 5 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.

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.

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.

Stats

A stat 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.

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.

canFix

This will eventually be a fixing Action. (TODO!)