GlobalAI ABI Compatibility Layer ("ABIC") - Page 2

GlobalAI ABI Compatibility Layer ("ABIC")

Here is where ideas can be collected for the skirmish AI in development

Moderators: hoijui, Moderators

User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

Unresolved issue: the UnitCreated event in the AI is being bound only to the last AI to load.

Example infolog, 2 identical AIs:

Code: Select all

Player hughperkins joined as 0
GlobalAI0: Hello from abi-called dll!
GlobalAI0: The map name is: SmallDivide.smf
GlobalAI0: Our ally team is: 0
GlobalAI0: Num features is: 999
GlobalAI0: First feature: GeoVent
GlobalAI0: Unit created: 4999
GlobalAI0: Unit created: ARMCOM
GlobalAI0: Max Slope: 0.330869
GlobalAI0: Commanderpos: 600.000000 64.395966 600.000000
GlobalAI0: Num unit defs: 285
GlobalAI0: Found solar collector def: 114
GlobalAI0: Closest build site: 600.000000 39.618950 600.000000
GlobalAI1: Hello from abi-called dll!
GlobalAI1: The map name is: SmallDivide.smf
GlobalAI1: Our ally team is: 1
GlobalAI1: Num features is: 999
GlobalAI1: First feature: GeoVent
GlobalAI1: Unit created: 4998
GlobalAI1: Unit created: 4997
User exited
4999 is GlobalAI0's commander, 4998 is GlobalAI1's commander.

4997 is a solar cell built by GlobalAI0, and should not firing a UnitCreated event in GlobalAI1.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

In fact, what is happening, is that the dll is only bound once, and everything is going through exactly the same dll instance. The change from GlobalAI0 to GlobalAI1 is occurring following a reassignment of GlobalAI1's aicallback to the ai dll instance's aicallback global variable.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

Possible solution: pass aicallback "self" as first parameter to each event function in AI.

Results:

Code: Select all

GlobalAI0: Hello from abi-called dll!
GlobalAI0: The map name is: SmallDivide.smf
GlobalAI0: Our ally team is: 0
GlobalAI0: Num features is: 999
GlobalAI0: First feature: GeoVent
GlobalAI0: Unit created: 4999
GlobalAI0: Unit created: ARMCOM
GlobalAI0: Max Slope: 0.330869
GlobalAI0: Commanderpos: 600.000000 64.395966 600.000000
GlobalAI0: Num unit defs: 285
GlobalAI0: Found solar collector def: 114
GlobalAI0: Closest build site: 600.000000 39.618950 600.000000
GlobalAI1: Hello from abi-called dll!
GlobalAI1: The map name is: SmallDivide.smf
GlobalAI1: Our ally team is: 1
GlobalAI1: Num features is: 999
GlobalAI1: First feature: GeoVent
GlobalAI1: Unit created: 4998
GlobalAI1: Unit created: ARMCOM
GlobalAI1: Max Slope: 0.330869
GlobalAI1: Commanderpos: 3600.000000 114.756073 3600.000000
GlobalAI1: Num unit defs: 285
GlobalAI1: Found solar collector def: 114
GlobalAI1: Closest build site: 3608.000000 90.203476 3592.000000
GlobalAI0: Unit created: 4997
GlobalAI0: Unit created: ARMSOLAR
GlobalAI1: Unit created: 4996
GlobalAI1: Unit created: ARMSOLAR
Image
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

New release of ABIC, file pointed to by original URL updated.

ABIC is now feature complete with the .Net Interface, except for GiveGroupOrder, AddMapPoint and GetMapPoints

Here's an example infolog output:

Code: Select all

Player hughperkins joined as 0
GlobalAI0: Hello from abi-called dll!
GlobalAI0: The map name is: SmallDivide.smf
GlobalAI0: Our ally team is: 0
GlobalAI0: Num features is: 999
GlobalAI0: First feature: GeoVent
GlobalAI0: Unit created: 4999
GlobalAI0: Unit created: ARMCOM
GlobalAI0: Max Slope: 0.330869
GlobalAI0: Build options: armsolar, armwin, armestor, armmstor, armmex, armmakr, armlab, armvp, armap, armsy, armllt, armrad, armsonar, armtide, armuwes, armuwms, armuwmex, armfmkr, armtl, armdrag, armhp, armfdrag, armavp, armalab, armaap, armasy, armplat, 
GlobalAI0: Commanderpos: 600.000000 64.395966 600.000000
GlobalAI0: Num unit defs: 285
GlobalAI0: Found solar collector def: 114
GlobalAI0: Closest build site: 600.000000 39.618950 600.000000
GlobalAI0: Unit finished: 4999
GlobalAI1: Hello from abi-called dll!
GlobalAI1: The map name is: SmallDivide.smf
GlobalAI1: Our ally team is: 1
GlobalAI1: Num features is: 999
GlobalAI1: First feature: GeoVent
GlobalAI1: Unit created: 4998
GlobalAI1: Unit created: ARMCOM
GlobalAI1: Max Slope: 0.330869
GlobalAI1: Build options: armsolar, armwin, armestor, armmstor, armmex, armmakr, armlab, armvp, armap, armsy, armllt, armrad, armsonar, armtide, armuwes, armuwms, armuwmex, armfmkr, armtl, armdrag, armhp, armfdrag, armavp, armalab, armaap, armasy, armplat, 
GlobalAI1: Commanderpos: 3600.000000 114.756073 3600.000000
GlobalAI1: Num unit defs: 285
GlobalAI1: Found solar collector def: 114
GlobalAI1: Closest build site: 3608.000000 90.203476 3592.000000
GlobalAI1: Unit finished: 4998
GlobalAI2: Hello from mingw!
GlobalAI2: The map name is: SmallDivide.smf
GlobalAI2: Our ally team is: 2
GlobalAI2: Num features is: 999
GlobalAI2: First feature: GeoVent
GlobalAI2: Unit created: 4997
GlobalAI2: Unit created: ARMCOM
GlobalAI2: Max Slope: 0.330869
GlobalAI2: Build options: armsolar, armwin, armestor, armmstor, armmex, armmakr, armlab, armvp, armap, armsy, armllt, armrad, armsonar, armtide, armuwes, armuwms, armuwmex, armfmkr, armtl, armdrag, armhp, armfdrag, armavp, armalab, armaap, armasy, armplat, 
GlobalAI2: Commanderpos: 3600.000000 65.683197 600.000000
GlobalAI2: Num unit defs: 285
GlobalAI2: Found solar collector def: 114
GlobalAI2: Closest build site: 3608.000000 40.711403 600.000000
GlobalAI3: Hello from mingw!
GlobalAI3: The map name is: SmallDivide.smf
GlobalAI3: Our ally team is: 3
GlobalAI3: Num features is: 999
GlobalAI3: First feature: GeoVent
GlobalAI3: Unit created: 4996
GlobalAI3: Unit created: ARMCOM
GlobalAI3: Max Slope: 0.330869
GlobalAI3: Build options: armsolar, armwin, armestor, armmstor, armmex, armmakr, armlab, armvp, armap, armsy, armllt, armrad, armsonar, armtide, armuwes, armuwms, armuwmex, armfmkr, armtl, armdrag, armhp, armfdrag, armavp, armalab, armaap, armasy, armplat, 
GlobalAI3: Commanderpos: 600.000000 91.958527 3600.000000
GlobalAI3: Num unit defs: 285
GlobalAI3: Found solar collector def: 114
GlobalAI3: Closest build site: 600.000000 68.069305 3608.000000
GlobalAI2: Unit created: 4995
GlobalAI2: Unit created: ARMSOLAR
GlobalAI1: Unit created: 4994
GlobalAI1: Unit created: ARMSOLAR
GlobalAI0: Unit created: 4993
GlobalAI0: Unit created: ARMSOLAR
GlobalAI0: Unit finished: 4993
GlobalAI0: Unit idle: 4999
GlobalAI1: Unit finished: 4994
GlobalAI1: Unit idle: 4998
User exited
You can see that there are 4 AIs running simultaneously, of which 2 are msvc and 2 are mingw.
User avatar
MadRat
Posts: 532
Joined: 24 Oct 2006, 13:45

Post by MadRat »

Just curious, but does the compiler choice seem to affect performance from either AI?
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

hmm, in that case I was correct after all global values should end up being shared because they're all in the same instance of that dll loaded.

This is a veritable minefield of epic proportions, you need to manage to separate these rather than hack around with passing team n#s or callback pointers....
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

New release of ABIC. The file pointed to by URL above has been updated.

Changes:
*InitAI returns a pointer to void. ABIC will pass this pointer as the first parameter to each GlobalAI method.
*method calls are now prefixed with the typename

The first change makes it trivial to wrap a C++ AI class:

Code: Select all

class MyAI
{
    struct IAICallback *aicallback;
    int team;

public:
    void InitAI( struct IAICallback *aicallback, int team)
    {    
        this->aicallback = aicallback;
        this->team = team;
    }
    void UnitCreated( int unit)
    {
    }
};

DLL_EXPORT void *InitAI( struct IAICallback *aicallback, int team)
{
    MyAI *ai = new MyAI();
    ai->InitAI( aicallback, team );
    return ai;
}

DLL_EXPORT void UnitCreated( void *ai, int unit)
{
    ( ( MyAI *)ai )->UnitCreated( unit );
}
The second change avoids polluting the global namespace.
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

pfft, now I shall have to start my spring->ABI dll->->ABI spring interface-> ABI AI interface-> Reconstructed proper C++ interface project.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

Spring version compatibility test:
*Tried AAI, CSAI, NTAi with Spring SVN version -> all crashed
*Tried the ABIC test AI with Spring SVN version and a recompiled ABIC -> worked ok

Screenshot:

Image

You can tell it is Spring SVN version because of the 4 colored squares at the bottom right of the map.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

GlobalAI C interface is now integrated into Spring, and committed to SVN.

AIs that export a function IsCInterface are linked to using the C interface, otherwise the C++ interface is used.

See AI/Global/TestABICAI for an example of a GlobalAI using the C interface.
Kloot
Spring Developer
Posts: 1867
Joined: 08 Oct 2006, 16:58

Post by Kloot »

e: outdated
Last edited by Kloot on 09 Jul 2008, 15:49, edited 1 time in total.
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

hmm, if I update my svn to see that example then I've broken compatability with the 0.73b1 spring build and have to recompile spring and then I have to go about maintaining 2 spring code setups on my PC for the svn and current builds.

AI devs only work with the current build not the svn build, and although they have been known to sometimes work with the svn build, its is not advisable todo so, nor is it common practice.

So please link to the relevant websvn page or post an example here.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

Created C++ wrapper classes, see AI/Global/CSAI/CSAILoader in SVN. The wrapper classes are:
*AbicAICallbackWrapper.h
*AbicFeatureDefWrapper.h
*AbicMoveDataWrapper.h
*AbicUnitDefWrapper.h

Any instance of these classes will have been created with new, so you will need to delete the instances as appropriate.

Properties are accessed via accessor functions, eg:

Code: Select all

AbicUnitDefWrapper *unitdef = aicallback->GetUnitDef( unit );
aicallback->SendTextMsg( unitdef->get_humanName(), 0 );
Certain functions have been modified to make them easier to send across the C interface:

*new function bool IsGamePaused() in aicallback
*new funciton int GetCurrentUnitCommandsCount( int unit ) in aicallback
*new functions GetNumUnitDefs and GetUnitDefByTypeId( int typeid ) replace GetUnitDefList in aicallback
*new functions int GetNumBuildOptions() and char *GetBuildOption( int index ) replace buildOptions in unitdef
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

for(int i = 0; i < GetNumBuildOptions(); i++){
buildoptions = GetBuildOption(i);
}

You can add that in and reconstruct the buildoption map properly.

And there was already a method of getting the isgamepaused aswell as many other things via the callback that used C primitive data types.

And reconstructing all the other data would be very easy and would make the whole C++ wrapper a lot lot prettier for existing AI devs.

And once again please reread my svn comment.
User avatar
hughperkins
AI Developer
Posts: 836
Joined: 17 Oct 2006, 04:14

Post by hughperkins »

And there was already a method of getting the isgamepaused aswell as many other things via the callback that used C primitive data types.
The generic GetValue/SetValue functions pass void * pointers containing a mixture of structs and value types. IsGamePaused calls the GetValue function on the spring side then passes the boolean across the C interface as a boolean.

The dll is binding per-function so adding new functions to the interface will not break older AIs.
And reconstructing all the other data would be very easy and would make the whole C++ wrapper a lot lot prettier for existing AI devs.
Unitdefs contain a lot of data so it is more efficient to pass by reference.
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

Unitdefs contain a lot of data so it is more efficient to pass by reference.
But its only done once at the beginning of the game anyway. Infact AAI and OTAI maintain copies of them so they can cache them to disk already, and AAI and NTai do operations at startup which require all the unitdefs be loaded anyway.

Otherwise your C++ wrapper is just as useful as the plain C interface, being only a little bit better in not being totally flatened out.

Besides there's nothing you stopping the UnitDef being mostly comprised of stuff like the original untidef, e.g. ud->canmove = &oud->canmove; etc for primitive data types of bool int and using const char* for mentions of string, which would in the end funnel all the necessary changes down to map<> and vector<> containers, and the odd bit where you have ud->name+" is" where you have 2 const char* values being added.
Post Reply

Return to “AI”