Open Interview
0AD-teaser1

Planting the Seeds of AI in Open-Source RTS 0 A.D.

richardk on May 14, 2012

0 A.D. is an open-source RTS inspired by the Age of Empires series. From the AI perspective, it also features most of the challenges in commercial games too, such as economy management, strategy and tactics, etc.

This interview with Jonathan Waller digs into his work on the AI for the game. You'll find out how the AI picks spots for buildings, and how pathfinding is used to select building sites for defensive buildings — among other things.

NOTE: This interview is the first in a series of articles about AI implementations in open source games, which offer a unique opportunity to learn from their AI code! Stay tuned to Twitter or Facebook for the next edition.

Introduction

Q: First of all tell us something about you. How did you get started on the AI for 0 A.D. and how did you get up to speed with the development?

JW: I'm currently studying for my final year of a maths degree in the UK. During the summer break from University I decided to get involved with an open source project. The Age of Empires game series is my favourite game series so 0 A.D. was an attractive project. Also the existing AI was simple, so I could rapidly produce a competitive AI.

To get up to speed with development I started from the demo AI which was a simple example of how to use the AI api and had a basic implementation of all of the necessary parts. I was able to gradually replace pieces while keeping a working AI. My AI, qBot, is currently the default AI for the game.

Screenshot 1: One qBot player (red) attacks another qBot player's base (blue). The lack of battle level control makes combat chaotic.

Q: Can you give a short overview over the gameplay of 0 A.D.?

JW: 0 A.D. is a classic RTS style game, most strongly inspired by the Age of Empires series. The basic gameplay is to gather resources and build up a base, then to train military units to attack and destroy the enemy.

There are 4 types of resources (food, wood, stone, metal) which can be gathered. Each map has limited amounts of each resource available but there is also trade which is an unlimited source but is slower.

There are 6 different factions, each with a different set of units and technologies that can be bought for various prices. Each unit has a set of bonuses and weaknesses in a rock-paper-scissors logic (e.g. spearmen defeat melee cavalry, but are countered by skirmishers and cavalry archers). The game has three phases which you must unlock to access advanced technology and units. The technologies come in pairs, each providing an irreversible choice, e.g. improve armour while decreasing speed or vice versa.

A planned feature of the gameplay is formations, there will be a selection of formations available each giving a different set of bonuses to the units within the formation. There will be an advantage when attacking the flanks of rear of a formation. Heroes will also be available and will give bonuses to nearby units.

Architecture

Q: What does the current Architecture of 0 A.D. look like at the moment, how does the AI interface look like and what are the plans for future of this architecture?

JW: 0 A.D. is structured with three main sections, there is a network synchronised gameplay simulation, a graphics engine and a gui system. The graphics engine and core parts of the engine are written in C++. Javascript is the preferred language for the rest of the game, but some parts are written in C++ for performance reasons.

The AI is a sub-section of the network synchronised gameplay simulation, the AI is run on each players machine which minimizes network latency and bandwidth use. Because the simulation state is network synchronised the AIs will run identically on each players computer. The game provides a proxy representation of the state of the simulation for the AI. This means that in the future the AI can be run in a background thread so that slow computations will run over multiple turns without having to deal with a changing simulation state. The number of turns taken by the AI will be predetermined and any computers which are too slow will block the simulation causing lag.

The proxy representation is a set of Javascript objects, with one for every entity in the game, with appropriate properties. Other simulation components send messages to the AI's interface where they are stored until the next AI turn. An example of the data sent when a new unit is created is:

{
    id:1733, 
    template:"units/pers_support_female_citizen", 
    position:[685.3661193847656, 792.2939605712891], 
    hitpoints:75, 
    owner:1, 
    idle:true
}

An example set of changes for this unit to keep the AI up to date might look like:

{ 
    position:[689.2837918372832, 790.3748268267827], 
    idle:false
}

So in this case the position of the unit has changed and it is no longer idle.

Each turn, apart from the entity data, there is also a set of events which give information about entity creation and destruction, attacks, player defeat, and construction completion. Obstruction and territory maps are given along with diplomacy information. The AI has access to the full unit definitions.

Screenshot 2: Block diagram of the 0 A.D AI architecture.

The AI acts by sending a list of commands to the game engine at the end of its turn. These commands are shared with the GUI so the AI can take exactly the same actions that a player can. An example of a command is to get two entities (34 and 56) to attack another unit (29). Then the behaviour will be identical to a player selecting those two units and giving an attack command.

{"type": "attack", "entities": [34, 56], "target": 29}

To help the AI deal with this information there is a common-api which provides some functions and classes which are useful for an AI. AI's do not have to use the common-api but all of the current AI's do. The common-api handles the set of changes sent each turn, applying then to its internal copy of the simulation state so it remains up to date.

Since an RTS game has thousands of entities an important part of the common-api is providing filtering. The common api has entity collections and a set of filters which can be applied to the entity collections. These filtered entity collections can be registered to automatically update to avoid having to do a costly filter operation each turn. The common api uses the sets of changes to efficiently keep the collections up to date.

Economy

Q: What features are currently implemented in the qBot AI?

JW: My main development focus on qBot so far has been on the economy. The AI is split into a set of managers which each have an update function which is called each AI turn. The queue manager handles resource distribution based on a list of priorities. Other managers can add items to the queue and they will be executed by the queue manager when enough resources are available. The queue manager also provides a prediction of what resources will be needed.

Building placement is done using a potential field which has the potential determined by existing buildings and resources. Different structures use different weightings so farms are built near food dropsites, dropsites are built near resources etc. The building is placed at the highest potential location which is not obstructed.

Screenshot 3: 1. The potential field for placing a standard building, based on locations of existing buildings. 2. The available build locations, shading is proportional to the Manhattan distance to the nearest obstruction. 3. Potential field for a wood dropsite, based on tree density and distance from the AI's base.

For the economy manager resource gathering is done based on the predicted resource needs from the queue manager. Units pick a gather location by picking the nearest dropsite (which still has nearby resources) and picking the nearest resource to that dropsite. Since the resource dropsites are built based on resource density units will automatically gather from large resource deposits. At regular intervals workers are redistributed between resource types to keep income in the correct proportions.

Defense is handled by detecting enemy units which are near to the AI's base and sending a proportionate number of troops to attack them.

Attacks are handled by having a set of attack plans, the AI can then pick an attack plan at a suitable time, the plan contains logic for executing the plan. When the plan is executed it is assigned soldiers which is controls until it chooses to release them. Currently there is only a single attack plan which move the soldiers to an enemy structure along a randomly chosen route, retaliating to any enemy attack on route. Since the AI is deterministic the randomness is generated from the simulation state, simply using the number of events received.

There is a pathfinding component which can generate a set of distinct paths from one location to another and determine if a location is accessible. The accessibility check is used for checking resources before trying to gather them.

Screenshot 4: This shows the steps for the multiple path finder. Since the map is small the blockers are placed around halfway along the paths.

The path finder works by finding the shortest path, then adding a blocking element on that path near to the destination, then it finds the next shortest path and repeats the process until there is no route to the destination left. This ordered set of paths is used by the attack manager to pick a random route to the enemy base and by the fortress builder which builds forts on the routes into the AI's base.

Strategy

Q: In 0 A.D. there is a big difference between early, mid and late game. Does the AI take this into account and how is it implemented?

JW: In 0 A.D. the game play can be split into three stages. Initially the focus is on quickly building a strong economy, any attacks at this stage would be targeted at resource gatherers to try and disrupt the enemy economy. The second stage is when the player expands, capturing territory and building a large base, which economic expansion is still continuing rapidly. The final stage is when players have maximised they resource gathering and advanced military units are produced since the focus switches to warfare.

These stages are fairly subtle currently but with the introduction of technologies, which have recently been put into svn, the game will have three phases (Village Town and City) with restrictions on what can be produced emphasizing the three stages.

The AI currently deals with this by adjusting the training priorities. Units are classified into 4 types; female citizens, citizen soldiers, champion soldiers and siege weapons. Female citizens can only perform economic tasks, they are cheap and are built at the start of the game for rapid economic growth. qBot uses the number of female citizens to determine the training priorities. Citizen soldiers can perform all economic tasks and can also build military structures and fight, they are trained in mid and late game. Champion units are strong soldiers and cannot gather or build, these are trained in late game along with siege units.

Testing

Q: One of the tricky aspects of developing an AI is to find subtle errors and to debug the inner workings as well as testing. How is this done in 0 A.D. and which tools are available to you. What tools would you like to have in order to be more productive.

JW: Practically all testing is done AI vs AI. This allows the AI behaviour to be observed and analysed at speeds much faster than standard game speed. Current debugging tools are text output which is shown in game and written to a file. The Javascript interpreter uses strict warnings and a stack trace is provided for errors. Images can also be saved which have been useful for building placement and pathfinding.

A recently added debugging feature is being able to set the color of units from the AI. I also hope to create a tool which will make it easy to plot certain properties as time progresses, e.g. showing the gathering rates or the number of workers.

Screenshot 5: Units coloured by economic activity, gatherers are red and builders are green.

There is no step through debugging interface. I have not found this to be too large a problem. Similar effects can be achieved by strategic placement of print statements which then act like watches so you get a rough trace of the program flow. This can be a bit less efficient in some cases though.

Other Features

Q: When there are multiple AI factions on a map is there a way to coordinate their behaviour and if not would that be something you think about implementing?

There is currently no team behaviour in the AI. I would like to implement attack coordination between AI's. I similar communication system with humans could also be done, with a set of commands such as "Attack Player 2" or "Give me 100 wood".

Q: Are there special entities which can be placed by a level designer in order to give hints to the AI? Like rallying points or important points to hold?

There aren't any special entities to give the AI hints or any plans to add them currently. I would prefer to avoid these types of manual hints as much as possible. This makes things easier for map designers which is helpful since we can't provide formal training to maps designers and random maps will be common so then random map designer would have difficulties adding these.

A scripted campaign is not planned for the first release of 0 A.D. but if we did add one then AI hints would probably be a part of it.

Future Work

Q: When would you consider your AI to be done and what is currently on your wish-list for the AI implementation?

JW: An AI is a very open ended task so realistically it will probably just be stabilised as we approach a release date. With a volunteer based project, manpower is always uncertain so determining how much will get done by a certain point is tricky.

There are a few things which I think are essential improvements which need to be made. Firstly support needs to be added for all of the game features. Some of these are still in development currently. These include trade, ships, healing and technologies.

Secondly the military side is currently pretty terrible. The AI has no battle level AI at all. It is easy to achieve a 4:1 kill ratio vs the AI with simple tactics, one player claimed a 30:1 kill ratio. Also siege functionality to take out fortifications is vital.

Lastly performance needs improving. Recent changes to the AI api (common-api-v2) help this to some extent by providing convenient caching functionality to avoid having to perform lots of re-computation each turn. Some parts of the AI will be rewritten in C++ as well.

If you enjoyed this interview don't forget to take a look at the 0AD Project Page or dive directly into the source code of qbot at the SVN Repository!

Discussion 0 Comments

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!