|
This
is the second installment in series surveying the landscape of game
AI middleware. As the name suggests, tools categorized as AI middleware
provide artificial intelligence services to game engines, and it's
a segment that is emerging as a serious alternative to custom AI
software systems developed for specific projects.
For
the most part, AI middleware finds itself located outside the game
engine and the process of producing the desired behavior of agents
or non-player characters (NPC) or decision-making objects found
in a game.
In
this installment, we'll look at DirectIA, developed by Mathematiques
Appliquees S.A. of Paris, France. This product can be characterized
as an a behavior-oriented SDK.
DirectIA
(Direct Intelligent Adaptation) is a generic game AI SDK. The SDK
allows a developer to construct agent behavior for her game, which
in turn relies on several DirectIA built-in engines for processing.
There is a motivation engine to model the emotions and needs of
the agents, a behavior engine to model the agent's decision processes,
a communication engine that supports agent intercommunication, a
perception engine to process input from the game world, an action
engine to enable the agent to interact with the game world, and
a knowledge engine to organize the agent's understanding of the
game world.
What does
this AI middleware product do for the game developer?
DirectIA
provides an agent-based behavior modeling system. With significant
considerations of how and why a character makes a decision, DirectIA
provides interesting options. Fundamentally, DirectIA processes
state variables that are influenced by emotions, which come from
stimuli. The emotions trigger motivations that are also influenced
by stimuli. Motivations can trigger behaviors. Behaviors can trigger
other behaviors, or trigger actions that best satisfy the needs
of the agent.
The
actions are what the game developer sees executed as behavior within
the game. This process can result in some rather complex decision-making
that leads to behavior by the character.
What are
the main features of this AI Middleware product?
DirectIA
offers real-time decision and action behavior modeling tools, in
the form of a high-level tool suite and a low-level tool suite.
Within the high-level tools is support for complex agents and reactive
agents (which will be discussed in detail in the next section),
while the low-level tools offer pathbuilding, hierarchical pathfinding
and steering tools (which are in beta at this time). The pathbuilding
tools were not available at the time this article was written.
Additionally,
there are facilities for communication between agents (and the player)
and inputs for perceptions of virtual world of the game. Agents
can coordinate their activities through this communication.
The
behavior engine is the main component DirectIA, and can be viewed
as a set of motivations that compete within the agent to determine
the actions of that agent. The behavior engine is accessed through
the various script files described later in this article.
For
testing purposes, a GUI testing environment is provided with DirectIA
that allows a developer to display and follow the decision process
of each agent while the game is playing. Also, various state variables
and agent data elements can be displayed.
How does
the game developer implement this AI Middleware product in a game?
DirectIA
is implemented in a game via script and parameter files that are
initialized and loaded into the DirectIA engines at run time. The
developer also needs to create C++ classes (derived from DirectIA
base classes) for declaring entities, agents, actions and behaviors.
Callback functions are used to perform services for the scripts.
Finally, a number of DLLs are included with DirectIA as well. As
you can tell, these processes mean that DirectIA is geared more
towards the programmer than the level designer.
Scripts and
Parameters
The
engines can be tuned by editing a number of different script files.
These scripts use a language similar to C++ with a DirectIA-specific
syntax. Each script must be loaded and parsed to be used, but this
is a fairly straightforward process - the game engine simply calls
DIA_ReadScript_Engine().
Here are some of the scripts:
globals
script
This script contains signatures (similar to a function prototype)
of the agent script. The functions are coded in C/C++ and can be
called from within scripts. Global variables are also defined by
this script file. Script-based functions are also declared and implemented
within this file, which can access and process data only within
the scope of the DirectIA script variable and object definitions.
In other words, these functions are not able to access data outside
DirectIA - data governing the game world - except through the use
of user-written C/C++ callback functions.
stimulus
script
This script defines the effect (in terms of a value) that perceived
objects may have on the agent. The script contains a calculation
that computes the value of a particular stimuli and then calls
DIA_SetStimulusValue() to make it available for use. Listing
1 shows a sample stimulus script.
|
|
//------------------------------------------------------------
// Stimulus for greed. Activated by the perception of valuable
objects.
//------------------------------------------------------------
//
declare the stimulus with a unique name to identify it
stimulus SeeTreasure
{
float rStimulusValue=0.0;
// a c callback function is called
that will return the list of all
objects
// in the game. There is also some
built-in functions that could have
been
// called to get a list of all entities
from world which then would have
been
// filtered to retrieve the 'object'
entities.
selection selObjects=c_GetObjects();
// The loop instruction in the DirectIA
script language
with ( y in selObjects)
{
// DirectIA
is a strongly typed language, but allows dynamic
conversion
// within
a structure hierarchy to get the correct type
of an object.
// A 'selection'
is a collection of 'thing's and in this
case 'y' is a thing
RealObject
obj=y;
float rBoost;
// 'myself'
is the reserved word for the ID of the agent.
Here other
// script
functions are called to see if the current object
is of interest to
// the agent.
The 'InSameRoom' is called due to game rules.
The agent
// is only
stimulated by object that are in the same room
as him.
if( InSameRoom(
myself, obj ) && CareAboutObject( obj, rBoost
) )
// If the
object is of some value for the agent, boost the
stimulus
rStimulusValue
= rStimulusValue + c_Love( obj );
}
// Here the final value of the stimulus
is set to the value just computed.
DIA_SetStimulusValue( SeeTreasure,
rStimulusValue );
}
Code
Fragment Copyright © MASA (Mathematiques Appliquees
SA) 2002
|
 |
 |
 |
Listing 1. Sample stimulus script
|
emotion
script
This script defines buffers that act between stimuli and state variables.
The definitions in the emotion script help simulate surprise and
habit. These state variables are input to the motivation engine
mentioned earlier. Listing 2 shows a sample emotion script.
|
|
//
The emotion is declared with a unique name to identify it.
// This emotion will be used somewhere else in the engine
to
// modify the strength of a behavior activation. The value
of
// this emotion can be retrieved in the script by calling
DIA_GetEmotion( greed ).
emotion
greed
{
// Factor applied to the input stimulus
// (In this case, the input value
is equal to the stimulus)
stim_factor = 1;
// The surprise factor is used to
simulate a boost when the emotion increase.
// here there is no surprise
surprise_factor = 0;
// define the max increase and decrease
rate of the value per time unit.
// Here the emotion can vary a lot
quickly.
max_decrease_rate = 300;
max_increase_rate = 300;
// Used to simulate the adaptation
of an agent to a stimulus
// (for example, an agent facing
a treasure long enough will get
// used to seeing it, and will no
longer feel any greed).
// Here there is no persistence
habit_factor = 0;
// The name of the input stimulus
used with this emotion
used_stimulus = SeeTreasure;
// The state variable that is modified
by the output of this emotion.
// Here we only use the output of
the emotion as a direct value in
// another part of the script by
calling DIA_GetEmotion( greed ).
// No state variable is influenced.
modified_sv = {};
}
Code
Fragment Copyright © MASA (Mathematiques Appliquees
SA) 2002
|
 |
 |
 |
Listing
2. Sample emotion script
|
state
variable script
This script sets the values for physiological or psychological states
of the agent. These state values are used by other scripts to help
make agent decisions. Think of these values as control attributes
used by the agents.
motivation
script
This script sets variables for a particular motivation by using
state variables that were set by stimuli and emotions. The variables
are then used by the motivation engine. This script also defines
the behavior code (found in behavior scripts) that is executed to
respond to this particular motivation.
behavior
script
This script sets parameters for the behavior engine, mentioned earlier.
An agent's actuators (which limit the actions an agent can simultaneously
perform) are listed in the behavior script. The behaviors and actions
that can be performed by an agent are also defined and implemented
in this script file.
Initializing
and using DirectIA
Initializing
and using DirectIA is performed with your game code. Initialization
is best performed before the main loop of the game begins to run.
Parse the "types" file by calling DIA_ReadScript_Types()
with the name of the file. Optionally, you may parse the "workspace"
file by calling DIA_ReadScript_Workspace()
with the name of the file. However, if the game does not need any
global script variables or C/C++ callback functions, then this step
can be skipped.
The
objects controlled by DirectIA should be game object classes derived
from the DIA_Engine
class. Game objects that do not use the DirectIA engine, but are
still manipulated by DirectIA would be derived from the DIA_Thing
class. An agent would be derived from the
DIA_Engine and an object that the agent uses (like a magic
wand) would be derived from the DIA_Thing
class. In either case, the developer must include a const
char *GetName() function implementation in those derived
classes.
You
create and register models or a defined type of agent using the
DIA_Model class.
This way you don't have to parsing the script files for each agent-the
script files are read once for each type of model, and the models
are copied to the agents as necessary. Once the models have been
read (a copy step similar to that just mentioned), the engines initialize.
Updating
agents involves an iteration of the DirectIA engine, and is performed
within your game loop. DIA_Workspace::GetTime()
is called to calculate the elapsed time since the last iteration.
Then DIA_Engine::ComputeActions()
is called to update the engine and have the agents select the best
actions for satisfying motivations and reacting to the environment.
This evaluation function is not called as often as DIA_Engine::ExecuteAllActions(),
which executes the selected actions that were not completed.
Of
course, any C/C++ functions that are called from the scripts need
to be written and must conform to a specific prototype as defined
by DirectIA. Additionally, these functions must be registered before
use.
Wrap Up
DirectIA
is a very agent-centric tool. Its sophisticated behavior engine
relies on its own built-in functionality tuned via script files
to meet an agent's decision-making needs. The DirectIA decision-making
process is very "state" oriented, at least from an external
point-of-view. Since using this tool involves extensive coding (creating
and updating scripts, developing C/C++ callback functions, deriving
game world objects and agents from DirectIA base classes, embedding
DirectIA API calls within the game code, and so on), it's not as
accessible to level designers as the tool surveyed yesterday, AI.implant.
Instead, I believe the proper use of DirectIA would require a programmer/designer
team working together to access the powerful behavior engine of
DirectIA.
|