<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=AIWrapper%3AModularAI</id>
	<title>AIWrapper:ModularAI - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=AIWrapper%3AModularAI"/>
	<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=AIWrapper:ModularAI&amp;action=history"/>
	<updated>2026-04-21T02:14:21Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=AIWrapper:ModularAI&amp;diff=2432&amp;oldid=prev</id>
		<title>Qrow: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=AIWrapper:ModularAI&amp;diff=2432&amp;oldid=prev"/>
		<updated>2026-03-04T00:15:45Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 17:15, 3 March 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Qrow</name></author>
	</entry>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=AIWrapper:ModularAI&amp;diff=2431&amp;oldid=prev</id>
		<title>interaiwrap&gt;Flozi: 1cat</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=AIWrapper:ModularAI&amp;diff=2431&amp;oldid=prev"/>
		<updated>2013-03-20T18:05:38Z</updated>

		<summary type="html">&lt;p&gt;1cat&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;{{AIWrapper|ModularAI|LoidThanead|?|Java|beta|GNU GPL v2+|[[AIInterface:Java|Java]]}}&lt;br /&gt;
&lt;br /&gt;
== ModularAI ==&lt;br /&gt;
&lt;br /&gt;
The ModularAI wrapper is a wrapper for the [http://springrts.com/wiki/AIInterface:Java Java AI 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.&lt;br /&gt;
&lt;br /&gt;
The design goal of the ModularAI wrapper is to provide the AI developer with easily customizable default behavior as well as the ability to add his or her own, without hiding any of the full power of the Java interface underneath.&lt;br /&gt;
&lt;br /&gt;
PM LoidThanead for a copy of the latest version.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Overview ===&lt;br /&gt;
&lt;br /&gt;
A ModularAI consists of a collection of modules. Each module is responsible for one aspect of the AI&amp;#039;s behavior. The behavior of a module could be to manage the AI&amp;#039;s construction queue. Another module might be used to plan and/or execute attacks.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
To simplify unit handling, the ModularAI wrapper introduces the &amp;lt;code&amp;gt;SimpleUnit&amp;lt;/code&amp;gt;. This is a wrapper around the Unit object that provides a convenient interface for giving orders to units. It also makes the unit&amp;#039;s properties (i.e. current/max speed, current/max health, available weapons etc) easily accessible.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use ===&lt;br /&gt;
&lt;br /&gt;
To use the ModularAI wrapper, we should first have a regular Java AI set up, as described in [[AI:Development:Lang:Java]]. Next, we add the ModularAI.jar file to your project. (Make sure it is located in the &amp;#039;&amp;#039;jlib&amp;#039;&amp;#039; subdirectory of your AI&amp;#039;s folder.) Then, instead of having &amp;lt;code&amp;gt;MyJavaAI&amp;lt;/code&amp;gt; extend &amp;lt;code&amp;gt;AbstractOOAI&amp;lt;/code&amp;gt;, we extend &amp;lt;code&amp;gt;DefaultModularAI&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;DefaultModularAI&amp;lt;/code&amp;gt; has a constructor, which our AI class will need to call. The &amp;lt;code&amp;gt;MyModularAI&amp;lt;/code&amp;gt; class will look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public class MyModularAI extends DefaultModularAI&lt;br /&gt;
{&lt;br /&gt;
   public MyModularAI(OOAICallback callback)&lt;br /&gt;
   {&lt;br /&gt;
      super(callback, 6);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the &amp;lt;code&amp;gt;super&amp;lt;/code&amp;gt; constructor has two arguments. The first is the callback, which allows the AI and its modules to communicate with the game engine.&lt;br /&gt;
The second parameter, &amp;lt;code&amp;gt;updateInterval&amp;lt;/code&amp;gt;, tells the &amp;lt;code&amp;gt;DefaultModularAI&amp;lt;/code&amp;gt; how often the default modules 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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
Most of the modules provided in &amp;lt;code&amp;gt;DefaultModularAI&amp;lt;/code&amp;gt; do not require updating at all, and none require heavy computation.&lt;br /&gt;
&lt;br /&gt;
At this point, we 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 our AI do anything intelligent, we will have to use modules.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Getting your AI to Do Something ===&lt;br /&gt;
&lt;br /&gt;
As is customary, the details of creating an &amp;lt;code&amp;gt;ModularAI&amp;lt;/code&amp;gt; that actually does something will be explained through an example that shows how to build a solar plant in the BA mod.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;DefaultModularAI&amp;lt;/code&amp;gt; that our AI extends has all the required modules to do the building for us. The only thing we still need to tell it is what to build and when. Therefore, we will create a module, &amp;lt;code&amp;gt;ControlModule&amp;lt;/code&amp;gt;, that makes the necessary decisions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Creating a new Module====&lt;br /&gt;
&lt;br /&gt;
We require a custom module that tells our AI what to build. Technically, we could do this in the &amp;lt;code&amp;gt;MyModularAI&amp;lt;/code&amp;gt; class, but this defeats the purpose of making the AI modular. Therefor, we create a new module, &amp;lt;code&amp;gt;ControlModule&amp;lt;/code&amp;gt;, that tells the built-in &amp;lt;code&amp;gt;BuildManager&amp;lt;/code&amp;gt; module that it has to build a solar plant.&lt;br /&gt;
&lt;br /&gt;
First we create the &amp;lt;code&amp;gt;ControlModule&amp;lt;/code&amp;gt; class. Creating a new module is as easy as creating a class that extends AbstractAIModule. You will need to create a constructor with parameters &amp;lt;code&amp;gt;OOAICallback callback&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;int updateInterval&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
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 necessary, 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.&lt;br /&gt;
For example, units can be ordered around using the appropriate method. Moving a unit is achieved by using the method &amp;lt;code&amp;gt;moveTo()&amp;lt;/code&amp;gt;, which takes the position to move to as its parameter, and will issue to appropriate move order for you.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ControlModule&amp;lt;/code&amp;gt; class should look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public class ControlModule extends AbstractAIModule&lt;br /&gt;
{&lt;br /&gt;
   public ControlModule(OOAICallback callback, int updateInterval)&lt;br /&gt;
   {&lt;br /&gt;
      super(callback, updateInterval);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We simple delegate the work to the constructor of &amp;lt;code&amp;gt;AbstractAIModule&amp;lt;/code&amp;gt;. It is often a good idea to let the AI that uses a module specify the updateInterval, rather than hard-coding it inside the module. This is because an AI with many light-weight modules may be able to update modules that perform heavy calculations more often, while other AI&amp;#039;s may wish to do it the other way around.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Let&amp;#039;s have our AI build a solar plant at the first frame of the game, frame 1. The easiest way to do that is to overwrite the &amp;lt;code&amp;gt;update()&amp;lt;/code&amp;gt; method.&lt;br /&gt;
To let our AI build a unit, we need a &amp;lt;code&amp;gt;BuildUnitCommand&amp;lt;/code&amp;gt;. In its simplest form, the &amp;lt;code&amp;gt;BuildUnitCommand&amp;lt;/code&amp;gt; constructor takes two arguments: a priority and an instance of &amp;lt;code&amp;gt;BuildProperties&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The priority of a &amp;lt;code&amp;gt;BuildUnitCommand&amp;lt;/code&amp;gt; works much the same as the priority of a module: the lower the priority number and the earlier the position in the build order queue. The difference is that a build order with a higher priority is not necessarily fulfilled first. The &amp;lt;code&amp;gt;BuildManager&amp;lt;/code&amp;gt; keeps track of which available units can be used to fulfill which requests. When a requests prerequisites are met, it assigns the required units to the module that issued the request. When two requests can be fulfilled using the same units, the request priority comes into play: the request with higher priority is processed, while the other one will have to wait for another usable unit to become available.&lt;br /&gt;
&lt;br /&gt;
The second parameter, &amp;lt;code&amp;gt;buildProperties&amp;lt;/code&amp;gt;, describes the details of the build command. The minimum information needed for a build command is the type of unit you would like to build. For all other properties (i.e. build position, number of units to build) defaults are used when they are not specified.&lt;br /&gt;
&lt;br /&gt;
To actually issue the BuildUnitCommand after we&amp;#039;ve created the object, we can use the &amp;lt;code&amp;gt;sendMessage()&amp;lt;/code&amp;gt; method implemented in &amp;lt;code&amp;gt;AbstractAIModule&amp;lt;code&amp;gt;. This method takes any message as its parameter, then passes it to all AI modules. (This includes the module that sent the message.)&lt;br /&gt;
&lt;br /&gt;
So, to have our AI a build a solar plant, we will overwrite the update method and give a &amp;lt;code&amp;gt;BuildUnitCommand&amp;lt;/code&amp;gt; with unit type &amp;#039;armsolar.&amp;#039; Now our module looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public class ControlModule extends AbstractAIModule&lt;br /&gt;
{&lt;br /&gt;
   public ControlModule(OOAICallback callback, int updateInterval)&lt;br /&gt;
   {&lt;br /&gt;
      super(callback, updateInterval);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public int update(int frame)&lt;br /&gt;
   {&lt;br /&gt;
      int exitcode = 0;&lt;br /&gt;
&lt;br /&gt;
      if (frame == 1 &amp;amp;&amp;amp; exitcode == 0)&lt;br /&gt;
      {&lt;br /&gt;
         BuildProperties properties = new BuildProperties(&amp;quot;armsolar&amp;quot;);&lt;br /&gt;
         Message buildCommand = new BuildUnitCommand(0, properties);&lt;br /&gt;
         exitcode = this.sendMessage(buildCommand);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      return exitcode;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above code, we first construct a &amp;lt;code&amp;gt;BuildProperties&amp;lt;/code&amp;gt; object with as only property the unit type &amp;#039;armsolar,&amp;#039; meaning we will use default values for all other properties.&lt;br /&gt;
Then we create the &amp;lt;code&amp;gt;BuildUnitCommand&amp;lt;/code&amp;gt; with priority 0 and the described properties. Zero is normally the highest priority (or lowest priority number) used, although technically negative values can be used as well.&lt;br /&gt;
Finally the build command is sent and passed to all modules of our AI.&lt;br /&gt;
&lt;br /&gt;
Just having the &amp;lt;code&amp;gt;ControlModule&amp;lt;/code&amp;gt; class is not enough to make our AI do something. We still need to add it to the AI instance. This will be described in the next section.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Adding a module ====&lt;br /&gt;
&lt;br /&gt;
To use a module, we need to it to our AI. Modules are best added in the constructor of your AI class.&lt;br /&gt;
&lt;br /&gt;
The method &amp;lt;code&amp;gt;addModule()&amp;lt;/code&amp;gt; is used to add a new module. This method comes in two variants. The first only takes the module that we wish to add as its argument. The second also lets us specify a priority.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
If no priority is specified for a module, it is given a default priority of 10.&lt;br /&gt;
&lt;br /&gt;
In order to let our AI build a solar plant, we will need to add our &amp;lt;code&amp;gt;ControlModule&amp;lt;/code&amp;gt;. To add the module, &amp;lt;code&amp;gt;MyModularAI&amp;lt;/code&amp;gt; should look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
public class MyModularAI extends DefaultModularAI&lt;br /&gt;
{&lt;br /&gt;
   public MyModularAI(OOAICallback callback)&lt;br /&gt;
   {&lt;br /&gt;
      super(callback, 6);&lt;br /&gt;
      this.addModule(new ControlModule(callback, 6));&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
And with this, our AI should start the game by building a solar plant.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039; [[AIs|&amp;lt;- Back to AI page]]&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Category: AIWrapper]]&lt;/div&gt;</summary>
		<author><name>interaiwrap&gt;Flozi</name></author>
	</entry>
</feed>