As humans, we like to implement solutions which are familiar to us

As humans, we like to implement solutions which are familiar to us. We get caught up doing
things the way we know how to do them, rather than the “best” way to do them. It’s easy to get
caught up in thinking like this and as a result we end up using outdated technologies and
implement features in ways that our modern contemporaries don’t understand, or are simply
less effective or efficient. My purpose with this and future papers will be to expose readers to a
broad spectrum of solutions that will hopefully help them in their own coding. Today I’ll be
covering Action Lists!
Action Lists are a simple yet powerful type of AI that all game developers should know about.
While ultimately not scalable for large AI networks, they allow for relatively complex emergent
behavior and are easy to implement. Whether you are just getting into AI programming or are
an experienced industry veteran looking to expand your toolkit, this presentation will introduce
you to Action Lists and provide concrete examples to help you implement your own solutions.
Let’s begin the story.
Once Upon A Time…
Several years ago I was starting the development of King Randall’s Party, a game in which the
player builds a castle and tries to defend it against the King who is trying to knock it down. I
needed to create a reasonably smart AI that could look at the player’s castle and figure out
how to circumvent or destroy it in order to reach its objective – the gold pile the player is
defending. This was a big challenge, almost too big to consider all at once. So like any good
programmer I broke it down into a more manageable problem set. The first challenges: I
needed to get the units to have a specific set of behaviors that they would act according to.
A quick internet search caused my mind to implode, of course. Searching for “Game AI”
brought up results on planners, finite state machines, steering behaviors, flocking, A*,
pathfinding, etc. I had no clue where to start, so I did what any reasonable, rational person
would do. I asked my dog. This isn’t anything new, of course. Whenever I have a tech problem,
I ask my dog. Now I know what you’re thinking “Jesse, that’s dumb, and you’re crazy… What
do dogs know about computers?” Well, let’s just gloss over that. It may or may not have
involved some illegal technology and or college class auditing.
Anyway, I said “Ok Frankie – there is so much going on with AI, I really don’t have a clue
where to start. How should I go about creating an AI framework for my game units?” Frankie
gave me this pretty withering look that basically informed me that I was an idiot and pretty
dumb, despite what my high school teacher Mr. Francis may have told me about there never
being any stupid questions. I’m pretty sure Frankie wouldn’t have had nice thoughts about Mr.
Francis either. “Jesse”, she asked, “how do you typically start your day?”
Well, I write everything that I need to do that day down in a list and then prioritize it according
to how important the task is and how soon it needs to be done. I explained this to Frankie and
she responded “And that, is an Action list.” She told me that an Action List is a list of tasks or
behaviors that your game units work their way through one at a time. It is a form of finite state
system, and could be described as a simple behavior tree with a single branch level. Here is
how they work. According to my dog.
How Action Lists Work
First you write down all the behaviors you want your AI to have.
Then you order them according to priority. Lowest to highest.
Now we iterate over the list checking each action to see if it can execute and if it can,
executing it. We then check the actions Blocking property, and if the item is Blocking further
actions we exit the list. We will get into why Blocking is important later.
In our example here, our first action Attack Player will only execute if the AI is close to the
player. Let’s say it is not, so it checks if it can build a ladder at this location (and should it), and
so on until it finds an action item it can execute such as Break Door. It then executes the Break
Door code.
Here is where Blocking comes into play. If Break Door occurs instantly, then it will not block
any further actions and the rest of the list can execute. This is typically not the case – actions
usually take up more than one frame. So in this case the Break Door Action Item
calls unit.Attack(door), which will change the
unit’s CurrentState from Waiting to BreakDoor and will return true until the door is
broken.
A Simple Finite State Machine
Well ok. That sounds workable. Frankie had made a good suggestion and Action Lists seem
like a great fit for my project. But I’d never heard of them before so I had my doubts – most of
what I hear floating around about AI has to do with transition-based finite state machines,
similar to what Unity3D uses for animations in Mechanim. You define a bunch of states, and
identify when and how they transition between each other. In exchange for some belly
scratches, Frankie explained to me when you make a transition based finite state machine,
you need to define all the states you want to have, and then also define all of the transitions to
and from each of those individual states. This can get complicated really, really fast. If you
have a Hurt state, you need to identify every other state that can transition to this state, and
when. Walking to hurt; jumping to hurt, crouching to hurt, attacking to hurt. This can be useful,
but can also get complicated really fast. If your AI requirements are fairly simple, that’s a lot of
potentially unnecessary overhead.
Another difficulty with transition-based state machines is that it is difficult to debug. If you set a
break point and look at what the AI’s current state is, it is impossible without additional debug
code to know how the AI got into its current state, what the previous states were and what
transition was used to get to the current state.
Drawbacks of Action Lists
As I dug into action lists some more, I realized that they were perfect for my implementation,
but I also realized they had some drawbacks. The biggest flaw is simply the result of its
greatest strength – its simplicity. Because it is a single ordered list, I couldn’t have any sort of
complex hierarchy of priorities. So if I wanted Attack Player to be a higher priority than Break
Door, but lower than Move To Objective, while also having Move To Objective being lower
priority than Break Door… that’s not a simple problem to solve with action lists, but trivial with
finite state machines.
In summary, action lists are really useful for reasonably simple AI systems, but the more
complex the AI you want to model, the more difficult it will be to implement action lists. That
being said, there are a few ways you can extend the concept of Action Lists to make them
more powerful.
Ways to Extend This Concept
So some of my AI units are multitaskers – they can move and attack at the same time. I could
create multiple action lists – one to handle movement and one to handle attacking, but that is
can be problematic – what if some types of movement preclude attacking, and some attacks
require the unit to stand still? This is where Action Lanes come in.
Action Lanes are an extension to the concept of Blocking. With Action Lanes, Action Items can
now identify specific types of Action Items that it blocks from executing while allowing others to
execute without problem. Let’s show this in action.
An Action Lane is just an additional way to determine what action. Each Action Item belongs to
one or more lanes, and when its Blocking property returns true, it will add the lanes it belongs
to Each action has a lane or multiple lanes they are identified with, and they will only block
other actions which belong to those lanes. As an example, Attack Player belongs in the Action
Lane, Move to Goal belongs in the Movement lane, and Build Ladder belongs in both since the
unit must stand still and cannot attack while building. Then we order these items, and if they
execute they will block subsequent actions appropriately.
Example Implementation
Now that we’ve gone over the theory, it is useful to step through a practical implementation.
First let’s setup our Action List and Action Items. For Action Items I like to decouple
implementation, so let’s make an interface.
Here is an example implementation of the IActionItem for the BreakDoor Action Item.
For the Action List itself we can use a simple List. Then we load it up with the IActionItems.
After that, we setup a method that iterates over the list every frame. Remember we also have
to handle blocking.
Things get a bit more complicated if you want to use action lanes. In that case we define Action
Lanes as a bitfield and then modify the IActionIteminterface.
Then we modify the iterator to take these lanes into account. Action Items will be skipped over
if their lane is blocked, but will otherwise check as normal. If all lanes are blocked then we
break out of the loop.
Conclusion
So that’s a lot to take in. While coding the other day Frankie asked me to summarize my
learnings. Thinking about it, there were a few key takeaways for me.

Action lists are easier to setup and maintain then small transition-based state systems.

They model a recognizable priority system.

There are a few ways they can be extended to handle expanded functionality.
As with anything in coding, there is often no best solution. It is important to keep a large variety
of coding tools in our toolbox so that we can pick the right one for the problem at hand. Action
Lists turned out to be perfect for King Randall’s Party. Perhaps they will be the right solution for
your project?
Originally posted on gorillatactics.com
About the Author(s)
Jesse is the founder of Gorilla Tactics, a contract game development company operating out
of a deserted, mountain-peak nuclear facility in Amherst MA accessible only via parachute,
rugged mountaineering, and dogsled team. Jesse got his start in game development when,
having swam two hundred miles down the Deerfield river into town to pick up some
lumberjacking paraphernalia, he passed a window with a few display PS2’s and decided to
abandon his beautiful life of solitude to bring joy to the masses through the media of video
games. He has worked with clients such as Warner Bros., Microsoft, Coors Brewing Company,
Firaxis, and the State of Minnesota. He is currently working on King Randall’s Party, a game
about using MacGyver like abilities to build castles and defend them. You can view his work
at www.gorillatactics.com
License
GDOL (Gamedev.net Open License)