O'Reilly logo

Programming Game AI by Example by Mat Buckland

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

This process of decomposing and satisfying goals continues until the entire
hierarchy has been traversed and Eric is left with a gleaming new sword in
his hands.
Well, that’s the what; let’s now look at the how.
Implementation
Nested object hierarchies, such as those required to implement hierarchical
goal-based agents, are commonly found in software. For instance, word
processors like the one I’m using to write this book store documents as col
-
lections of atomic and composite components. The smallest components,
alphanumeric characters, are grouped together into increasingly complex
collections. For example, the word “philosophy” is a composite component
comprised of several atomic components, and the sentence “I think there
-
fore I am” is a composite component comprised of three composite and
two atomic objects. In turn, sentences can be grouped together into para
-
graph objects, which can be grouped into pages and so on. I’m sure you get
the idea. The important point to note is that the application is able to handle
composite and atomic objects uniformly, regardless of their size or com
-
plexity — it’s just as easy to cut and paste a word as it is several pages of
text. This is exactly the property required by hierarchical goals. But how do
we code it?
The composite design pattern provides a solution. It works by defining
an abstract base class that represents both composite and atomic objects.
This enables clients to manipulate all goals identically, no matter how sim
-
ple or complex they may be. See Figure 9.5.
382 | Chapter 9
Implementation
Figure 9.4. Expanding the Follow Path goal
The figure clearly shows how Composite objects aggregate instances of
Components, which in turn may be either Composite or Atomic. Notice how
Composite objects forward client requests to their children. In this arche
-
typal example requests are forwarded to all children. However, other
designs may require a slightly different implementation, as is the case with
goals.
Figure 9.6 shows the composite pattern applied to the design of hierar-
chical goals. Subgoals are added by pushing them onto the front of the
subgoal container and are processed in LIFO (last in, first out) order in the
same way as a stack-like data structure. Notice how client requests are only
forwarded to the frontmost subgoal, ensuring that subgoals are evaluated in
sequence.
Goal-Driven Agent Behavior | 383
Implementation
Figure 9.5 The archetypal composite design pattern
Figure 9.6. The composite pattern applied to goals
Goal objects share a lot of similarities with the State class. They have a
method for handling messages just like
State, and Activate, Process, and
Terminate methods, which share similarities with the Enter, Execute, and
Exit methods of State.
The
Activate method contains initialization logic and represents the
planning phase of the goal. Unlike the
State::Enter method though, which
is only called once when a state first becomes current, a
Goal is able to call
its
Activate method any number of times to replan if the situation
demands.
Process, which is executed each update step, returns an enumerated
value indicating the status of the goal. This can be one of four values:
n
inactive: The goal is waiting to be activated.
n
active: The goal has been activated and will be processed each
update step.
n
completed: The goal has completed and will be removed on the next
update.
n
failed: The goal has failed and will either replan or be removed on
the next update.
The
Terminate method undertakes any necessary tidying up before a goal is
exited and is called just before a goal is destroyed.
In practice, a chunk of the logic implemented by composite goals is
common to all composites and can be abstracted out into a
Goal_Composite
class, which all concrete composite goals can inherit from, resulting in the
final design fleshed out in Figure 9.7.
The UML diagrams do an adequate job of describing the
Goal class hier-
archy so I won’t waste paper listing their declarations, but I think it will be
helpful if I list the source for a couple of the
Goal_Composite methods.
384 | Chapter 9
Implementation

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required