Jump to content
Sign in to follow this  
JuKu96

[Tutorial] Develop a new AI

Recommended Posts

Because the documentation of the AIs are not so much, i want to create a litte tutorial with the first steps to develop a new AI while i develop my own AI. :D

Execuse me for my english, I am from Germany and my english is not the best. :D

At first you must create the following directory structur in the directory <Install Path>/binaries/data/mods, if it does not exists.

  • <Module Name>
    • simulation
      • ai
        • <Your AI Name>

In this directory you add a new file data.json with the following text:

{
    "name": "<AI Name>",
    "description": "<AI Description>",
    "moduleName" : "<Module Name>",
    "constructor": "<The Constructor Method>",
    "useShared": true
}

My data.json hast the following content:

{
    "name": "NewAI",
    "description": "newAI",
    "moduleName" : "NEWAI",
    "constructor": "NewAIConstruct",
    "useShared": true
}

After this we create a new javascript file _init.js, if you want to use the common-api module (optional), with this module you dont have to develop the AI from low-level.

AegisBot use this common-api too.

Engine.IncludeModule("common-api");

This line loads the common-api module, which can be founded in the mods/public/public.zip/simulation/ai/common-api, but you dont have to copy this module, the game find this module in the public.zip, which is in this directory by default.

After this we create a new javascript file, called as your modulename, e.q. "newAI.js" and must contains the constructor method in an anonymous function, saved in a var.

var NEWAI = (function() {
    var m = {};//an empty object
    
    //your code must be placed here
    
    //return the module object
    
    return m;
}());

This constructor method must return the module AI object!

----------------------------------------------------------------

This tutorial hasnt finished yet!

I want to edit this post to append new steps.

Edited by JuKu96
format of code.
  • Like 2

Share this post


Link to post
Share on other sites

In the function at your code must be placed here we add the following lines:

// "local" global variables for stuffs that will need a unique ID
// Note that since order of loading is alphabetic, this means this file must go before any other file using them.

m.playerGlobals = [];

I copied this lines from aegisBot and i dont know so much, what this line does.

I think they will be create a new object, which will contains the game goals and will be filled by common-api.

After this lines we append the following lines:

m.NewAI = function NewAI(settings) {
    API3.BaseAI.call(this, settings);
    
    this.turn = 0;
    this.playedTurn = 0;
    this.Config = new m.Config();
    this.Config.updateDifficulty(settings.difficulty);
    this.Config.personality = settings.personality;
    this.firstTime = true;
    this.savedEvents = {};
    this.defcon = 5;
    this.defconChangeTime = -10000000;
};

This lines are also copied from AegisBot and loads the BaseAI from the common-api module.

After this lines you have to add the following line:

m.NewAI.prototype = new API3.BaseAI();

You have to replace NewAI with your own module name!

At the moment my file newai.js contains the following text:

var NEWAI = (function() {
    var m = {}; //an empty object
    // "local" global variables for stuffs that will need a unique ID
    // Note that since order of loading is alphabetic, this means this file must go before any other file using them.
    
    m.playerGlobals = [];
    m.NewAI = function NewAI(settings) {
        API3.BaseAI.call(this, settings);
        this.turn = 0;	this.playedTurn = 0;
        this.Config = new m.Config();
        this.Config.updateDifficulty(settings.difficulty);
        this.Config.personality = settings.personality;
        this.firstTime = true;	this.savedEvents = {};
        this.defcon = 5;
        this.defconChangeTime = -10000000;
    };
    
    m.NewAI.prototype = new API3.BaseAI();

    //your code must be placed here

    //return the module object

    return m;

}());

 

Edited by JuKu96
format code.
  • Like 2

Share this post


Link to post
Share on other sites

Please create your new AI in a mod of your own rather than in the public mod, that way it's a lot easier to avoid issues when the main game is updated. And perhaps most importantly: when you want to give it to someone else to try it out :) Then it's a lot easier to have it as a mod that one can install and activate/deactivate at will :)

  • Like 1

Share this post


Link to post
Share on other sites

thanks! :)

I have currently the current alpha version and I will download the current svn trunk.

I have to compile the source code first, or?

feneur

Please create your new AI in a mod of your own rather than in the public mod

But how can I load the AI in the game?

I have try to create a mod, but I couldnt load it.

Edited by JuKu96

Share this post


Link to post
Share on other sites

The Update Loop

How does an AI works?

Every AI has an update loop, an method, which is executed every n seconds or milliseconds.

We have set the difficulty from the game settings dialog, which calculate the interval time and balancing it in this code lines:

this.Config = new m.Config();
this.Config.updateDifficulty(<Difficulty>);
this.Config.personality = settings.personality;

The update loop in an ai is the most important method of an AI.

In this method the AI will be moved Units, build buildings and so on.

We want to use the onUpdate Event and add the following lines to the file newai.js:

m.NewAI.prototype.OnUpdate = function(sharedScript) {
    /* If the game has finished, the AI hasnt to do anything. */
    if (this.gameFinished){
        return;
    }
    
    //Your update code
    
};

Important!:

The this Object in Javascript is not the same as in Java!

this is in Javascript the reference object, which represented the function, which has executed the current Javascript function.

Every Javascript function has the hidden argument this.

this is an reference.

Source: http://www.mediaevent.de/javascript/this.html

Now my complete file newai.js contains the following code.

Spoiler

var NEWAI = (function() {
    var m = {};//an empty object
    // "local" global variables for stuffs that will need a unique ID
    // Note that since order of loading is alphabetic, this means this file must go before any other file using them.
    m.playerGlobals = [];
    
    m.NewAI = function NewAI(settings) {
        API3.BaseAI.call(this, settings);
        this.turn = 0;
        this.playedTurn = 0;
        this.Config = new m.Config();
        this.Config.updateDifficulty(settings.difficulty);
        this.Config.personality = settings.personality;
        this.firstTime = true;
        this.savedEvents = {};
        this.defcon = 5;
        this.defconChangeTime = -10000000;
    };
    
    m.NewAI.prototype = new API3.BaseAI();
    
    /** The AI update loop*/
    m.NewAI.prototype.OnUpdate = function(sharedScript) {
        if (this.gameFinished){
            return;
        }
        
        //Your update code
    };
        
    //your code must be placed here
        
    //return the module object
    return m;
}());

 

Edited by JuKu96
  • Like 3

Share this post


Link to post
Share on other sites

Update to Release 17 - Make the AI to an Mod

yesterday the dev team released the new Alpha Version 17, this version comes with some changes, also with the mod system.

The game has an integrated mod system now, you can add mods in the config dialog, if they are in the correct directory.

To make the AI as an mod, we have to create an file mod.json in the first mod directory, e.q. mods/<Module Name>/mod.json with the following code:

{
    "name": "<Module Name>",
    "version": "0.0.17",
    "label": "A new AI for 0 A.D.",
    "url": "<Website>",
    "description": "A new AI for 0 A.D.",
    "dependencies": ["0ad=0.0.17"],
    "type": "ai"
}

Thanks to niektb and leper!

The version is the version of the game, not of your mod!

0.0.17 means the game version Alpha 17.

I have add the 0ad dependency, because there can also exists any other pyrogenesis games.

Is this correct?

Edited by JuKu96

Share this post


Link to post
Share on other sites

Version refers to the version of the game to be used with (so 0.0.17 for Alpha 17 and 0.0.18 for SVN)

Dependencies should be set at 0ad (the public mod folder) assuming you want to use your AI for 0 A.D. instead of an other Pyrogenesis game (if they exist).

I think I would set the type to be something more specific e.g. "ai".

Share this post


Link to post
Share on other sites

[...]

Dependencies should be set at 0ad (the public mod folder) assuming you want to use our AI for 0 A.D. instead of an other Pyrogenesis game (if they exist).

[...]

?

Like:

"dependencies": ["0ad"]

Share this post


Link to post
Share on other sites

Version refers to the version of the game to be used with (so 0.0.17 for Alpha 17 and 0.0.18 for SVN)

No, version refers to the version of the mod. If you want to specify a versioned dependency use eg

"dependencies": ["0ad=0.0.17"]
(supports <, <=, =, >=, >)

Share this post


Link to post
Share on other sites

> Please create your new AI in a mod of your own rather than in the public mod...

I tried this with Hannibal, but something goes wrong with loading maps:

> /usr/games/0ad -quickstart -autostart="scenarios/Arcadia 02" -mod=public -mod=charts -mod=hannibal -autostart-ai=1:hannibal...file_system.cpp(122): Function call failed: return value was -110301 (Error during IO)Function call failed: return value was -110301 (Error during IO)Location: file_system.cpp:122 (GetDirectoryEntries)Call stack:(0x8498c4c) /usr/games/pyrogenesis() [0x8498c4c](0x844256c) /usr/games/pyrogenesis() [0x844256c](0x84428b7) /usr/games/pyrogenesis() [0x84428b7](0x844fd21) /usr/games/pyrogenesis() [0x844fd21](0x846c0bf) /usr/games/pyrogenesis() [0x846c0bf](0x8467ea9) /usr/games/pyrogenesis() [0x8467ea9](0x846c4cd) /usr/games/pyrogenesis() [0x846c4cd](0x8467ea9) /usr/games/pyrogenesis() [0x8467ea9](0x8466075) /usr/games/pyrogenesis() [0x8466075](0x845e47e) /usr/games/pyrogenesis() [0x845e47e](0x82506b3) /usr/games/pyrogenesis() [0x82506b3](0x8253c06) /usr/games/pyrogenesis() [0x8253c06](0x821ad20) /usr/games/pyrogenesis() [0x821ad20](0x820f58e) /usr/games/pyrogenesis() [0x820f58e](0x8211004) /usr/games/pyrogenesis() [0x8211004](0x8213a64) /usr/games/pyrogenesis() [0x8213a64]errno = 0 (Error during IO)OS error = ?

It is possible to continue after the dialog appears, but it comes back every time I click single player. Is there a more special configuration needed to run bots as mods. I like the idea as it probably allows a custom aiconfig dialog.

Share this post


Link to post
Share on other sites

I've just tried with a dummy AI as a mod, and this works. Can you double-check that your svn version is sane, i.e. if just running "/usr/games/0ad -quickstart -autostart="scenarios/Arcadia 02" -mod=public -mod=charts" does not give the same problem.

Share this post


Link to post
Share on other sites

I now think it might have to do with the fact the bot mod also has a a map folder, will check. I tested svn and release both behave the same. Btw. is there a trick to have both svn and release, atlas and pyrogenesis use same scenario folder?

Share this post


Link to post
Share on other sites

Place them

Btw. is there a trick to have both svn and release, atlas and pyrogenesis use same scenario folder?

Place them in the user mod in the user mod folder. You will have to specify -mod=user for the svn version only (as the last mod).

Or specify -noUserMod for the release version and specify the same mod (which should be in the user mod folder) for both.

Share this post


Link to post
Share on other sites

This thread is marked with the label hot. :D

So i want to write more in this tutorial. :D

How can i move some soldiers or get a list of all the soldiers?

Share this post


Link to post
Share on other sites

> How can i move some soldiers

That's pretty simple. I copy the API (entity.js):

  Engine.PostCommand( PlayerID, {    "type": "walk",     "entities": [this.id()],     "x": x, "z": z,     "queued": queued   });  

If queue is true, it means the AI has "shift key pressed". PlayerId: a integer, 1-8 are meaningful, entities expects an array with integers and x, z are map coordinates.

> or get a list of all the soldiers?

A bit harder. Assuming you mean units which are part of class "infantry", you loop through all entities, check the classes, collect the ids in an array and feed it into the code above to send them around.

Share this post


Link to post
Share on other sites

Why is code syntax highlighting now so good?

There are only shown 1 line of code, where is the rest?

 

@agentx:
How can i get the first units, if the game starts, for example to request them to build a store house?

Edited by JuKu96

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...