AIWrapper:ModularAI: Difference between revisions
Loidthanead (talk | contribs) Simplified the text to describe only how to build a simple ModularAI. For further information contact the author or consult the javadoc. |
Loidthanead (talk | contribs) mNo edit summary |
||
| Line 31: | Line 31: | ||
As you can see, the super constructor has two arguments. The first is the callback, which allows modules to communicate with the game engine. | As you can see, the super constructor has two arguments. The first is the callback, which allows modules to communicate with the game engine. | ||
The second parameter, <code>updateInterval</code>, tells the module how often it should update. A module is updated at frame 1, and every x frames after that, where x is the update interval. So a module with an update interval of 100 is updated at frames 1, 100, 200, etc. | The second parameter, <code>updateInterval</code>, tells the module how often it should update. The choice for an interval of 6 is only an example. At 1x speed, this interval means that every component updates once per second. | ||
The smallest possible update interval is 1, which means that the module | |||
A module is updated at frame 1, and every x frames after that, where x is the update interval. So a module with an update interval of 100 is updated at frames 1, 100, 200, etc. | |||
The smallest possible update interval is 1, which means that the module updates every frame. This is 6 times per second at 1x speed! Obviously, you will want to keep update intervals reasonable for modules that perform heavy calculations at updates. | |||
If you do not want a module to update besides the first frame, set the updateInterval to 0. For suggestions about appropriate update intervals, you should consult the documentation for the module in question. | If you do not want a module to update besides the first frame, set the updateInterval to 0. For suggestions about appropriate update intervals, you should consult the documentation for the module in question. | ||
Most of the modules provided in <code>DefaultModularAI</code> do not require updating at all, and none require heavy computation. | Most of the modules provided in <code>DefaultModularAI</code> do not require updating at all, and none require heavy computation. | ||
Revision as of 14:28, 27 June 2009
ModularAI
The ModularAI wrapper is a wrapper around the Java Interface. It divides AI functionality up in modules. Each module is self-contained, easily customizable and can be swapped for any the module serving the same function without breaking the AI.
The design goal of the ModularAI wrapper is to provide the AI developer with easily customizable default behaviour as well as the ability to add his or her own, without hiding any of the full power of the Java interface underneath.
PM LoidThanead for a copy of the latest version.
Overview
A ModularAI consists of a collection of modules. Each module is responsible for one aspect of the AI's behaviour. The behaviour of a module could be to manage the AI's contruction queue. Another module might be used to plan and/or execute attacks.
The AI communicates with the modules through Messages. When an event happens in the game, all modules are notified. Modules can also communicate with one another through messages.
To simplify unit handling, the ModularAI wrapper introduces the SimpleUnit. This is a wrapper around the Unit object that provides a convenient interface for giving orders to units. It also makes the unit's properties (i.e. current/max speed, current/max health, available weapons etc) easily accessible.
Use
To use the ModularAI wrapper, you should first have a regular Java AI set up, as described in AI:Development:Lang:Java. Next, add the ModularAI.jar file to your project. (Make sure it is located in the jlib subdirectory of your AI's folder.) Then, instead of having MyJavaAI extend AbstractOOAI, extend DefaultModularAI.
DefaultModularAI has a constructor, which your AI class will need to call. Your constructor may look something like this:
public MyModularAI(OOAICallback callback)
{
super(callback, 6);
}
As you can see, the super constructor has two arguments. The first is the callback, which allows modules to communicate with the game engine.
The second parameter, updateInterval, tells the module how often it should update. The choice for an interval of 6 is only an example. At 1x speed, this interval means that every component updates once per second.
A module is updated at frame 1, and every x frames after that, where x is the update interval. So a module with an update interval of 100 is updated at frames 1, 100, 200, etc.
The smallest possible update interval is 1, which means that the module updates every frame. This is 6 times per second at 1x speed! Obviously, you will want to keep update intervals reasonable for modules that perform heavy calculations at updates.
If you do not want a module to update besides the first frame, set the updateInterval to 0. For suggestions about appropriate update intervals, you should consult the documentation for the module in question.
Most of the modules provided in DefaultModularAI do not require updating at all, and none require heavy computation.
At this point, you technically have a working ModularAI. You may want to export your code and see if there are no errors. However, to make full use of the ModularAI wrapper you will need to know how to use modules.
At this point, you technically have a working ModularAI. You may want to export your code and see if there are no errors when you run it. As you may see, your AI does not do anything yet. In order to have your AI do anything intelligent, you will need to add and communicate with its modules. Since you will likely want to add custom behaviour to the AI, you will need to create your own module(s).
Getting your AI to Do Something
As is customary, the details of creating an ModularAI that actually does something will be explained through an example that shows how to build a solar plant in the BA mod.
Adding a module
If you extended DefaultModularAI, your AI already has the required modules available. For the sake of this example, we will assume that your AI extends ModularAI instead.
Modules are best added in the constructor of your AI class.
The method addModule() is used to add a new module. This method comes in two variants. The first only takes the module that you wish to add as its argument. The second also lets you specify a priority.
This priority determines in what order modules are notified of events, as well as the sequence in which they are initialized and updated. This can be important if, for example, the initialization of a component requires another component to be already initialized.
Note that a lower priority number means a higher priority. A module with priority 1 will be initialized, updated and notified of events before any module with priority 2. The priority number works as an index in a list. The order in which two modules with the same priority number are handled is undefined, and may vary from moment to moment.
If no priority is specified for a module, it is given a default priority of 10.
In order to let your AI build a solar plant, you will need the module BuildManager. This module comes standard with the ModularAI.jar library.
The BuildManager makes use of another module, UnitPool, which we will have to add as well. Since the BuildManager depends on UnitPool, the unitpool should have a lower priority number, to make sure it is initialized first.
To be able to use the BuildManager, your AI's constructor should look like this:
public MyModularAI(OOAICallback callback)
{
super(callback, 6)
this.addModule(5, new UnitPool(callback, 6));
this.addModule(10, new BuildManager(callback, 6));
}
A UnitPool is added with a priority number of 5, and a BuildManager
Now that we have added the BuildManager, we will need to send it orders. In the next section, we will create a module to do exactly that.
Creating a new Module
In order to make use of the BuildManager, we need a custom module that sends it orders. Technically, we could do this in the MyModularAI class, but this defeats the purpose of making the AI modular. Therefor, we create a new module, MyModule, that tells the BuildManager that it has to build a solar plant.
First we create the MyModule class. Creating a new module is as easy as creating a class that extends AbstractAIModule. You will need to create a constructor with parameters OOAICallback callback and int updateInterval.
The callback enables your module to retrieve information from the engine as well as give commands. Note that giving commands to the engine should not be nescessary, as for most actions that require you to talk to the engine directly there are more convenient methods available that do the work for you.
For example, units can be ordered around using the appropriate method. Moving a unit is achieved by using the method moveTo(), which takes the position to move to as its parameter, and will issue to appropriate move order for you.
The most important method of a Module is receiveMessage(). This method takes as argument a Message object, which
Recieving and sending messages
Any internal communication in a ModularAI is done through Messages. In order to receive messages,
As explained in AI:Development:Lang:Java, the AI is informed of any events that happen inside the game. In a standard Java AI, this is done by calling an event method, such as unitCreated() or enemyDestroyed().
ModularAI instead creates a Message for every event
Existing modules
Implementing unit-specific behaviour