There are may ways of coding the AI for a game, each game definitely needs it's custom made AI but that doesn't mean that there aren't certain patterns to apply for similar AI in different games.
The technique I'm about to expose is primarily focused for strategy games of a reduced scope, but works wonders in them. It's basically a Planner with 3 distinct levels to control the global AI of the game (NOT the specific units).
The beauty of the system is that it's simple, elegant and robust. Simple because each module is simple. Elegant because the interaction of the simple elements makes a complex behavior, and robust because adding or modifying the game design at any level has no impact whatsoever on the general AI architecture, only in the corresponding module.
Overview:
The technique consists of 3 levels.
First there is the data generators, that calculate all the data the planner needs. Then there is the actual planner, who calculates the probability of executing each action and calls them. Finally there are the individual actions, that produce different results based on the actual game situation.
The above diagram shows an example of the Planner strategy.
A PlayerAI class has references to external data (player and map), the blue methods are data generators, the red object is the planner, and the yellow objects are actions.
Data generators:
These are usually part of the general AI class, and game specific (you won't change throughout the game because they provide general info of the game the AI needs, regardless of the actual situation).
In the example:
They provide two datum. The % of the battle that is won (to know if the AI is wining and must press the advantage being aggressive, or is losing and must quickly rally to defend) which it calculates from the number of units, defenses and overall power of both contestants. The budget the AI can spend in that turn, cause in the beginning of the game it can spend freely to create cheap units, but later on it needs to save up to create more powerful ones.
Planners:
The planner is a object the AI has. A base Planner class exists to derive different planners from, and could look something like this:
It's the planner's job to decide what to do, and here is how it goes about it.
Creation:
For each kind of scenario we have a different planner, specified in the external game data files. When we load a PlayerAI data file, we create a specific Planner object specified in that file.
In the example:
We have a PlayerAI xml file with this structure:
So we would create for our playerAI a new Planner of type "somePlanner".
Then for each Action assigned to the Planner in the data file, we create a new Action object of type "T" and add it to the planner's action vector, with it's corresponding base percentage, which represents the probability of choosing that particular action.
In the example:
We would create a Order, CastSpell, CreateUnit, CreateBuilding and Wait actions and add them to m_vActions.
Execution:
Each time the AI updates, we update the Planner passing it the data provided by the data generators. Taking those into account, it calculates the new % of choosing each action, from their base %.
Now, knowing what the chances are of executing each action, it chooses those most probable ones and executes them.
In the example:
We would get the BattleStatus and Budget, and for each of the 5 actions, update their probability of being executed according to how much money we have and wherever we are winning the battle or not.
Actions:
All the actions are objects that take the same parameters, and provide some sort of output to the rest of the game system.
They are modular, so you can add new actions, remove actions (changing the xml file of that planner) or modify particular actions (changing the code of that particular action class) and the rest of the system never needs to know.
In the example:
The Order action tells units to attack, stop or retreat, depending on the BattleStatus. The Create Units action chooses one unit or another depending on the need for offensive or defensive units. ... Finally the Wait action puts the AI on idle, so it doesn't do anything.
Notes:
The Planners and actions are implemented by a base Planner (or Action) class and derived classes for each specific Planner (or action) and using those by polymorphism.
A Player AI class might look something like this:
No comments:
Post a Comment