Every few days or weeks I’m asked about AI development in spring. I was today offered work porting the music AI and NTai over to linux and asked questions about how to develop AI in general as I seemed to be the person to know. (note this post is for nostalgic purposes now that the C AI interface has been implemented) I have not talked with the other AI developers but I would assume they have the same questions asked of them ( and maybe their answer is to point the budding programmers in my direction hehe ).
What kinds of AI Do Springs AI Interfaces support?
There are several interfaces in spring that can be used to implement an AI. Not all the interfaces are appropriate for every type of AI task however and they all have their merits and downsides. The main focus of this text will be the native C/C++ AI, however it would be unfair of me not to mention the lua based alternatives.
Lua based AI code
The Lua AI Interface
A while ago, Trepan, a spring engine developer, bowed to pressure to implement and AI interface addition that would allow communication between C++ AI and lua gadgets, in order to allow co-operation in non-TA game mechanics.
Trepan it seems had another idea, the lua AI. He implemented a lua based AI interface to allow enemy players to be controlled by lua based skirmish AIs. I myself am not aware of the specifics of actually implementing a lua AI, but I know enough to give a few points:
- At the time of writing this, there are no working lua AI available, nor are there any publicly available or in development. You will have no examples to work from when developing using these itnerfaces. Also, trepan wrote alot of APIs for the various lua GUI and game rule interfaces, so much so he did not have time to document them. You may find yourself digging through C++ headers for the specifics of lua <-> spring callouts.
- Some of the API is shared with widgets and gadgets and they may provide useful examples for certain actions and callouts.
- This interface should be easier to develop for due to the plain text nature of lua. All the issues of AI interface versions, binary compatibility, library dependencies and compiling are all magicked away by the dynamic language aspects fo lua.
- An instance of your AI must be created and ran on each and every players machine including spectators, regardless of who owns the AI. This means that there is a lot of duplicate calculations, and you may end up having to run an AI on your machine despite the AI already being ran on your friends much faster machine causing a performance hit.
- As fast as lua is it cannot compare to the speed of native code.
- Better integration with mod specific game rules for custom game mechanics.
The Lua Widget Interface
Trepans first venture into the land of lua involved adding an interface for users to implement lua GUI widgets, small pieces of modular lua code implementing buttons and controls to extend the default ingame GUI. These widgets cannot implement an entire skirmish AI and are ultimately aides to the active player. They may provide extra information or visual aides, or they may automate simple but tedious tasks such as turning metal makers on and off, the latter point being subject to a vast discussion on what constitutes a cheating widget or a helper widget. Widgets can eb turned on and off by the user and other widgets.
The Lua Gadget Interface
Gadgets are game rules, pieces of code that always run regardless of what the user says. Bundled with their associated content, they extend or implement unit behaviours that support the game mechanic the content creator wants. For example, there is a gadget that implements restricted building hierarchies in games, and there is a gadget that implement commando units that plant bombs on buildings, as well as a gadget that implements warcraft/starcraft style resource harvesting.
This sort of interface is not appropriate for building a full skirmish AI, nor is it appropriate for helper AIs, however gadgets are useful for acting as aides to other AIs, by implementing extra unit behaviours to improve AI performance when its detected that the current player is non-Human. Another use of gadgets would be to implement behaviours in gaiag/neutral units.
Native Binary AIs
The other side of AI development involves native compiled code. This is the oldest type of AI interface in the spring community and has access to a lot more abilities, as well as the benefits of speed and the vast number of native libraries. It does come with its downsides however.
Native Languages & API versions/compatibility
Springs native Interfaces use spring headers to define classes and objects passed across. As a result the interface is a C++ interface. Because of this every AI must be built using the same compiler as that used to build spring, and every AI must be recompiled if the respective classes and headers inside spring change between versions.
The official spring release is compiled using mingw32 in order to reduce sync errors with Linux and other non-windows ports, and therefore to release to the public you must use mingw32 too. Failure to follow these rules will lead to crashes, or spring may refuse to load your AI full-stop giving the end user a “Incorrect AI interface” style error prompt.
Other advantages of native AI are the greater speed potential, as well as the vast amount of C++ libraries and documentation for features, allowing AIs with multiple threads, networking, and other features not provided directly by the spring engine itself. A native AI also runs on only the owners machine, reducing the load on the other players by reducing unnecessary calculations.
The Global AI Interface
This interface implements full skirmish AIs that are given full control over an entire team. These types of AI are what are shown in the lobby in the AI drop down lists and are the most widely supported kind of AI available, as well as the most developed. All the major skirmish AI for spring are C++ ai written for this interface.
Spring will look for these AIs when they’re specified by reading the aidll=…; tag in the script.txt which is written by the lobby. Spring will then load the library and make calls to a small C interface in order to retrieve a pointer to a class implementing the IGlobalAI interface. This interface is used to issue events such as UnitFinished, UnitCreated Update etc, and it is this interface you should derive from to create your initial AI object within which to do all your AI work. Spring will also call this object passing in an IGlobalAICallback pointer which can be used to retrieve an AI interface and a cheating interface.
The GroupAI Interface
This interface was created in order to allow the end user to assign helper AIs to groups of units in game. The role of this interface has been greatly diminished however because of the new lua widgets, which are far easier to develop and test since they require only text editor to make. GroupAIs have a similar interface to GlobalAIs however they receives far fewer callbacks, as such less is possibly with them.
But since they are native code, they can make use of libraries and interfaces unavailable to lua, such as networking, threading, or music interfaces.
Next Blog Post: Compiling and Testing a C++ AI.
In the next post, I’ll detail how to create an AI project, and the various steps to compile and test an AI under spring.