Open Article
B000VSFSXA

An Overview of the AI Architecture Inside the F.E.A.R. SDK

Alex J. Champandard on January 7, 2008

In theory, there’s no difference between theory and practice. Of course, in practice when you build a game AI engine, things turn out very differently.

PC games have always been a great source of inspiration for enthusiasts, as they often allow you to look under the hood to see what’s going on. It’s great when the developers release the original SDK, but it’s even better when it’s packed full of AI technology!

This article looks into the latest SDK behind F.E.A.R., the hit first-person shooter acclaimed for its artificial intelligence. The codebase is in C++, like the rest of the AAA games industry, but the code is written in a style that should provide valuable insights for the developers among you using C# or Java.

Downloading and Installing the SDK

A fully working installation of F.E.A.R. is required to install the SDK. Here’s how you should proceed:

  1. You need an original copy of the game. The F.E.A.R. trilogy is particularly good value for money for AI enthusiasts.

  2. Make sure the game is patched to the latest version, 108. Go to this FTP directory and pick the right update for your language.

  3. Now get the F.E.A.R. public tools version 108. This is the latest version of the SDK so it should match the latest patch also.

For those of you that already own the game and don’t have 1 GB of bandwidth to spare, I’ve made a backup of the engine and game source code and attached the package to this thread in the forums. (You’ll need to register to download it.)

Once the installation is finished and all the files have unpacked, you’ll have a .\Tools\ directory — typically within your game folder.

F.E.A.R. Source Code Development Kit SDK

Screenshot 1: A sample of the files available freely in the SDK.

Finding Your Way Around the Codebase

You’ll find a Visual Studio solution file called Game.sln file within the ./Source/Game/ directory. The free Express edition of Visual C++ is suitable for opening that file.

The AI code lives in the ./Source/Game/ObjectDLL directory, along with the rest of the game logic that runs on the server. Predominantly in that directory, you’ll find:

  • Actions, Goals, Sensors and Nodes — Most of the files are modular tasks for gathering information (sensors) and making changes to the world (actions), using objects in space with animations (nodes), and evaluating objectives and for the AI (goals).

  • AI Framework & Algorithms — The other files starting with the prefix AI contain the supporting code for these specific objects listed above. The SDK also contains the implementation also contains the necessary algorithms for making decisions.

  • Game Logic — The rest of the files are the typical game DLL code, with the application logic, code to manage the client/server, etc.

Of course, the SDK doesn’t give you complete access to all the engine code, but there’s a surprisingly large amount of the AI code fully available. Either way, it’s more than enough to get an idea of how the architecture is structured.

F.E.A.R. AI Character

Screenshot 2: An AI character in F.E.A.R. ducking for cover.

Overview

There are a few things you should look out for in particular.

The Planner
F.E.A.R. is famous for its use of planning technology! You get access to a surprisingly large part of it in the SDK. It’s implemented at the core as A* in AIAStarMachine.[h,cpp], which serves as the basis for an object-oriented design including the goal planner (in AIAStarPlanner.[h,cpp]) as well as the pathfinder (in AIAStarNavMesh.[h,cpp]).
Architecture
While you can find similar STRIPS planners elsewhere, what’s interesting about this codebase is how it was integrated with the rest of the game engine. The files AIPlanner.[h,cpp] integrate the low-level A* algorithm by apply the actions over time. Also be sure to look at the way the goals are implemented modularly, based on AIGoalAbstract.[h,cpp], to control the outcome of the planning itself and compete for activation.
Navigation Mesh & SmartObjects
The planner is based on solid underlying systems, specifically the navigation mesh technology. For instance, you’ll find a navmesh generator for the raw polygons from the World Editor in all files called AINavMeshGen*.[h,cpp], as well as the code for handling different kinds of movement within the world in AINavMeshLink(Stairs|Jump|FlyThrough|DuckRun).[h,cpp]. The smart object code is stored in files derived from AINode.[h,cpp], integrating with the animation system.

The Main AI Class

F.E.A.R. C++ Class Hierarchy

Figure 3: The C++ class hierarchy in F.E.A.R.

Here’s a quick overview of the most important classes that compose the primary CAI character class:

  • The static blackboard is used as a software design pattern to help reduce coupling between the AI sub-systems. It provides a central place for modular pieces of code to store their data.

  • A working memory stores the AI’s observations about the environment. By having this separate world model, the AI can be duped and tricked by the player based on what it knows and senses.

  • The world state is a very simple list of attributes that are used to represent the current situation, as used by the planner to perform its reasoning.

  • The brain stores properties only, like roll distance or grenade throw times.

The remaining classes are a bit more self-explanatory. You’ll find some comments in the code, particularly in the lower-level classes, but be sure to browse around to get the big picture.

Download the AI source code from the SDK in this thread of the forum. Free registration required.

Discussion 15 Comments

Saddist on January 8th, 2008

I loved this edition for your blog, do you plan on following up with more in depth issues for both beginners and advance users? Or will this be the just a post to get people interested and expect them to self study? (Don't get me wrong, of course we have to self study) I just mean, will you follow up this post with more later on?

BrianL on January 8th, 2008

A few comments on the Fear AI for someone other than Jeff who worked with it - The brain class is legacy; it is mostly redundant. In a previous incarnation of the AI system, it allowed designers to specify parameters which drove the behavior. These parameters were merged into the database records which drove most of the character parameters. A goal of the blackboard was to reduce the data duplication (and thus hidden invariants) between behaviors. Decoupling was definitely a goal as well, just not the only one. In theory, all AI types could be a single class with the implementation swapped out at the component level. At the implementation level, this is problematic if the per-instance designer configuration data is constrained to a statically exposed set of properties on the AI. More succinctly, the Fear tools expose properties per class type. As all AI are derived from a single class, it isn't possible to expose attributes which only apply to a subset of the AI. The relationship between AIMovement and AINavigationMgr is too decoupled in some ways. AINavigationMgr handles path planning and sets a destination waypoint for AIMovement. AIMovement handles local pathing to the point. These classes execute in lock step; if the AI has 5 feet worth of movement in a frame but his next waypoint is only 1 foot ahead, he essentially 'loses' 4 feet worth of velocity. While separation can definitely be useful, this relationship could use some work. For Fear, the AIActivities (which coordinated squad behavior and a lot of the communication) are worth looking at. You can think of the activities as 'automated scripting' in some ways. Long term, these will probably be expanded to become more dynamic. The translation between behaviors and animation (via CAnimationContext) is powerful but difficult to manage. Basically, behaviors generate a pattern. AnimationContext uses the animation trees to find an animation matching the pattern. If no match is found, an error is issued. Insuring all pattern permutations have runtime matches can be a challenge - a simpler translation layer with a primary key and secondary data (ie play a motion behavior Jump, parameterized with information on the weapon/jump height/etc) would potentially be more robust and scalable to complex behaviors. The AISoundMgr may also be worth a glance, as it handled prioritizing AI callouts. The SmartObject terminology may be confusing. AINodeSmartObject and its children are designer placed and configured hints for the AI about the environment. These specify a SmartObject chunk of data which indirectly specified animation, behavior, etc. The SmartObject data chunks were eventually reused to specify animation/behavior for procedural behaviors like reloading a gun.

alexjc on January 8th, 2008

[B]Saddist, [/B]Thanks for the feedback. There will be many more articles; see my introduction to the [URL="http://aigamedev.com/forums/showthread.php?p=406"]code studies[/URL] column in the forums. I'll also go into more depth with this codebase... it's fascinating. What level of expertize would you like to see? [B]BrianL[/B], Many thanks for your comment! That's really useful. I've only been reading the source for hours today, so I'm glad I didn't get anything too wrong... If you're allowed to say, what did you use the F.E.A.R. engine for? Alex

BrianL on January 8th, 2008

I was the AI programmer on Condemned: Criminal Origins. It was developed on the same code base as Fear. Our development started a little later; Jeff had the core planner and navmesh system in place before I started with it - the architecture is 95% his. I was focused on the AI components specific to Condemned, optimization to make it run better on the consoles, cleanup, etc. Quite a few of the AI classes in the SDK were probably Condemned behaviors I authored that weren't actually used in Fear due to the code sharing methods. After the games shipped, Jeff left for MIT and I moved to a lead programmer position. Most of my involvement with the AI the last few years has been in the form of training, feedback, review, high level direction, etc.

Veksi on January 8th, 2008

Oh! I must say this is the ultimate! Something real and concrete to build studies on. So sad (too bad) there are only so many hours a day and some of them has to be used for sleeping. The next three months I'm super busy at work. I guess resigning and suspending my preliminary masters thesis plans aren't real options either. :-P Thanks for this. I see if I'm able to spread out the good news.

Saddist on January 9th, 2008

[B]alexjc, [/B] In between. I'm not advance in this section. So carry on the way you do, but try to make it easy to follow. Not that any of your other writings are hard to follow. I guess I'll just ask questions along the way. And you'll be able to set the pace from there. That way, both beginners can cope, maybe with a little brain racking along the way.

bcorfman on August 14th, 2008

Alex, the links to the SDK code don't seem to be valid any longer. Is there another place to download the code?

alexjc on August 14th, 2008

Sorry, I don't know where else to find the SDK, etc. Try to do a search for the exact filenames; something should show up. Also, you can still download the archives I attached to this thread though. Alex

bcorfman on August 14th, 2008

Alex, thanks for the fast reply. I am not able to retrieve the archive files you attached to the forum. I get the following message: "Firefox can't find the file at http://forums.aigamedev.com/attachment.php?attachmentid=5&d=1199759384." Were the files moved accidentally? Thanks for your help.

randomuser on January 16th, 2009

Hello everyone, It's pretty cool to have this available, and the explanations help a lot. Many thanks. What is the license attached to this code, for instance, if one wanted to port parts of it to another language?

raveneyesdead on March 17th, 2009

Well...how I inegrate this with a irrlicht project?

bariel on September 23rd, 2009

Appologies for digging up an old thread but we're developing AI for our game and game across the F.E.A.R. source posted here whilst researching things. Does anyone know the status of this code and whether it's available under any form of license that we would be able to utilize it in our own game? I presume not but if it helps me having to re-invent the wheel then I'm all for that.

alexjc on September 23rd, 2009

Unfortunately, I doubt this code will ever be licensed to integrate into third party games. It's also the case that the architecture is somewhat specific to what Monolith uses, so I'm not sure if it wouldn't be quicker to rewrite it yourself. Alex

bariel on September 24th, 2009

Thanks Alex it's what I had presumed was the case but though it was worth checking, I was only thinking of taking elements and concepts as the full blown piece would be overkill for the AI we're trying to create. Guess I'll start from the ground up. Thanks again :) and great site

alvares89 on September 12th, 2012

All the good times, I would be very grateful if somebody help me with the source code, I do not know how to prescribe the paths to the resources game. I want to add new paths to resources, the editor saw them.

If you'd like to add a comment or question on this page, simply log-in to the site. You can create an account from the sign-up page if necessary... It takes less than a minute!