No more .NET AI?
Moderators: hoijui, Moderators
No more .NET AI?
I read on the BOO Hello world! - thread that csailoader wont be supported in newer versions of Spring. Does this mean that you can't make .net - ai's anymore? Would it be possible with Mono instead? Where can i get an older versions that is compiled in msvc then?
Not easily, you would first need to update the .net-AI loader (which must be built with VS since it's written in managed C++) and then bind it to Spring somehow (a rather messy process due to ABI differences between g++ and the VS C++ compiler, meaning you can't link their object-files together directly). If you want to experiment with CSAI and the loader without dealing with those binding issues, check out the VS-based 0.73b1 Spring release from SVN, and read Hugh's documentation here, here and here. This is useful too.
-
- Posts: 59
- Joined: 07 May 2005, 23:48
All the AIs will be broken when 0.75 is released because some of the AI interfaces implementation has been changed with bugfixes, and the UnitDef class has been changed to hold more data for other 0.75 features.
Hughs .Net loader AI was abandoned in favor of direct integration into spring, however that integration was managed c++ and there were no mono bindings, so they werent compiled in because mingw32 doesnt support it.
Hughs .Net loader AI was abandoned in favor of direct integration into spring, however that integration was managed c++ and there were no mono bindings, so they werent compiled in because mingw32 doesnt support it.
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
errr yeah it's kindof dead at the moment. It worked great until the change to mingw came along, and then it just sortof fell apart.
It'd be possible to get it working again.
There are a few ways to do this:
1. Do it for Java instead of .Net
Not saying this is a good option, but it would at least make it more opensource-friendly
2. Link with Mono
Mono provides linkage in C, so you'll need some way to downgrade from Spring's C++ binding to C-binding, then backup to object-oriented binding within Mono.
Mono is so-so in an embedded environment, and seriously undocumented.
3. Link with .Net
Linking with .Net is a good option.
Whatever you do, you'll need to downgrade Spring's C++ binding to a C binding, then remap back to an object-oriented approach on the C# side.
Once it's downgraded to a C interface, there are two options to link with C#:
- use P/Invoke (?) to call into the C# directly
- link with an msvc managed C++ dll which links with C#
Initially, Spring was built with msvc, so we didnt need to downgrade to a C interface, and the managed C++ bindings worked nicely.
With the build of Spring in mingw, I'd be tempted to get JNI bindings working. You lose a lot of build-environment performance, but you gain in opensource-friendliness.
In all cases, maximum use of Reflection is strongly adviced to generate the interface layers. You really dont want to be writing these interfaces by hand...
It'd be possible to get it working again.
There are a few ways to do this:
1. Do it for Java instead of .Net
Not saying this is a good option, but it would at least make it more opensource-friendly
2. Link with Mono
Mono provides linkage in C, so you'll need some way to downgrade from Spring's C++ binding to C-binding, then backup to object-oriented binding within Mono.
Mono is so-so in an embedded environment, and seriously undocumented.
3. Link with .Net
Linking with .Net is a good option.
Whatever you do, you'll need to downgrade Spring's C++ binding to a C binding, then remap back to an object-oriented approach on the C# side.
Once it's downgraded to a C interface, there are two options to link with C#:
- use P/Invoke (?) to call into the C# directly
- link with an msvc managed C++ dll which links with C#
Initially, Spring was built with msvc, so we didnt need to downgrade to a C interface, and the managed C++ bindings worked nicely.
With the build of Spring in mingw, I'd be tempted to get JNI bindings working. You lose a lot of build-environment performance, but you gain in opensource-friendliness.
In all cases, maximum use of Reflection is strongly adviced to generate the interface layers. You really dont want to be writing these interfaces by hand...
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
Oh man, so many dlls ...
Kindof tempted just to start from basics again, and rip out the ABIC layer from spring, since I assume no-one's actually using it? and it's just complicating things.
What would be really amazingly useful would be some way of parsing C++ class files easily, preferably from C#. Does anyone happen to know a good way to do this?
Kindof tempted just to start from basics again, and rip out the ABIC layer from spring, since I assume no-one's actually using it? and it's just complicating things.
What would be really amazingly useful would be some way of parsing C++ class files easily, preferably from C#. Does anyone happen to know a good way to do this?
Nobody uses the ABIC layer for the following reasons:
Incomplete support and missing functions
No cheat interface
No real examples
The whole interface is spread across numerous folders, the c++ wrappers are in the CSAI folder for example
Confusion as to what headers to include
Nobody really knows where or how to extend the C API so its not maintained.
The c++ wrapper there is, is incomplete
The c++ wrapper doesnt conform to the c++ API as such you cant just drop it in as a replacement
The differences in the c++ wrapper also mean that most existing AI code cant be taken and retrofitted into new AIs/features
AI devs have their hands full as it is. Your interface is a workload that isnt necessary and doesnt justify the means at the moment as it lacks necessary functionality and forces the AI dev to make lots of little semantic changes to API calls that werent necessary.
Incomplete support and missing functions
No cheat interface
No real examples
The whole interface is spread across numerous folders, the c++ wrappers are in the CSAI folder for example
Confusion as to what headers to include
Nobody really knows where or how to extend the C API so its not maintained.
The c++ wrapper there is, is incomplete
The c++ wrapper doesnt conform to the c++ API as such you cant just drop it in as a replacement
The differences in the c++ wrapper also mean that most existing AI code cant be taken and retrofitted into new AIs/features
AI devs have their hands full as it is. Your interface is a workload that isnt necessary and doesnt justify the means at the moment as it lacks necessary functionality and forces the AI dev to make lots of little semantic changes to API calls that werent necessary.
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
Yeah I agree. See this thread http://spring.clan-sy.com/phpbb/viewtop ... 526#187526
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
Ok, this is working. For now, here's some skimpy instructions. Maybe some binaries later.
You'll need the AI\Global\CSAI directory from the spring SVN
requirements:
- visual C++ 2003 Toolkit (may work with Visual C++ 2005 Express)
- microsoft framework 1.1 (need this even if you have framework 2.0)
- nant
- taspring
- taspring sourcecode that matches the version of your taspring
1.1 vs 2
I'm using visual C++ 2003, so we have to force framework 1.1 on csaiinterfaces and csailoader.
* The CSAI itself can be framework 2.0 *
1. CSAIInterfaces: C# reference classes for GlobalAI interfaces
global for all AIs, only one copy needed, only changes if Spring AI API changes (or if we
implement more functions)
use nant with .build file
The resulting dll should be copied into root of Taspring directory
2.ABICCompatiblityLayer
change paths in buildabic.bat
run "buildabic csaiabic.dll csailoader.dll"
csaiabic.dll is the dll that you will load in the lobby
csaiabic.dll will load the dll csailoader.dll (which isnt created in this step)
csailoader.dll should have a C interface conform to what the ABIC layer is expecting
csaiabic.dll copied into Taspring\AI\Bot-libs
3. CSAiLoader
change paths in buildcsailoader.bat
run "buildcsailoader.bat"
creates csailoader.dll, which will be loaded by csaiabic.dll, and which loads the C# AI itself
There is a config file with the same name as the csailoader dll, which decides what C# AI to load
ie, you can rename csailoader.dll to anything you like (rebuild abiccompatibilitylayer to match the new name),
then copy csailoader.dll to the same name but with ".xml" instead of ".dll",eg
mycsailoader.dll
mycsailoader.xml -> which could point to mycsai.dll
It's copied into root of Taspring , along with the .xml file
4. CSAI
- make sure to add csaiinterfaces.dll as a reference to csai project
- you can find this in the root of the taspring directory, or in the csaiinterfaces project directory
CSAI needs to contain a public class that derives from IGlobalAI ,which is in csaiinterfaces.dll
- you'll want to save the IAICallback object, passed into the Init function, as a member variable
- as a hello world, you can call "aicallback.SendTextMsg("Hello world", 0);", eg in the Init function
- Place the resulting dll in a subfolder of taspring\ai such as taspring\ai\csai
- make sure your csailoader xml file points to this directory, filename, and has the classname of the class that derives from IGlobalAI
5. Run
Open lobby, select abic dll (from step 2), cross fingers
Debug files available, in root of taspring directory:
- out.log ->generated by abic dll
- outm.log -> generated by csailoader dll
- infolog.txt -> generated by spring; you can check which dlls have been successfully loaded
Note that there was a fair bit of tweaking of the various build files mentionted here, plus a lot of other files too, so only do this if you're feeling particularly adventurous/impatient.
I'll try to provide this in a more usable format soonish.
You'll need the AI\Global\CSAI directory from the spring SVN
requirements:
- visual C++ 2003 Toolkit (may work with Visual C++ 2005 Express)
- microsoft framework 1.1 (need this even if you have framework 2.0)
- nant
- taspring
- taspring sourcecode that matches the version of your taspring
1.1 vs 2
I'm using visual C++ 2003, so we have to force framework 1.1 on csaiinterfaces and csailoader.
* The CSAI itself can be framework 2.0 *
1. CSAIInterfaces: C# reference classes for GlobalAI interfaces
global for all AIs, only one copy needed, only changes if Spring AI API changes (or if we
implement more functions)
use nant with .build file
The resulting dll should be copied into root of Taspring directory
2.ABICCompatiblityLayer
change paths in buildabic.bat
run "buildabic csaiabic.dll csailoader.dll"
csaiabic.dll is the dll that you will load in the lobby
csaiabic.dll will load the dll csailoader.dll (which isnt created in this step)
csailoader.dll should have a C interface conform to what the ABIC layer is expecting
csaiabic.dll copied into Taspring\AI\Bot-libs
3. CSAiLoader
change paths in buildcsailoader.bat
run "buildcsailoader.bat"
creates csailoader.dll, which will be loaded by csaiabic.dll, and which loads the C# AI itself
There is a config file with the same name as the csailoader dll, which decides what C# AI to load
ie, you can rename csailoader.dll to anything you like (rebuild abiccompatibilitylayer to match the new name),
then copy csailoader.dll to the same name but with ".xml" instead of ".dll",eg
mycsailoader.dll
mycsailoader.xml -> which could point to mycsai.dll
It's copied into root of Taspring , along with the .xml file
4. CSAI
- make sure to add csaiinterfaces.dll as a reference to csai project
- you can find this in the root of the taspring directory, or in the csaiinterfaces project directory
CSAI needs to contain a public class that derives from IGlobalAI ,which is in csaiinterfaces.dll
- you'll want to save the IAICallback object, passed into the Init function, as a member variable
- as a hello world, you can call "aicallback.SendTextMsg("Hello world", 0);", eg in the Init function
- Place the resulting dll in a subfolder of taspring\ai such as taspring\ai\csai
- make sure your csailoader xml file points to this directory, filename, and has the classname of the class that derives from IGlobalAI
5. Run
Open lobby, select abic dll (from step 2), cross fingers
Debug files available, in root of taspring directory:
- out.log ->generated by abic dll
- outm.log -> generated by csailoader dll
- infolog.txt -> generated by spring; you can check which dlls have been successfully loaded
Note that there was a fair bit of tweaking of the various build files mentionted here, plus a lot of other files too, so only do this if you're feeling particularly adventurous/impatient.
I'll try to provide this in a more usable format soonish.
Last edited by hughperkins on 12 May 2007, 02:06, edited 2 times in total.
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
Note that a .Net AI needs the Singleton pattern. I'm not sure if this is a good thing, but presumably it seemed so at the time.
The simplest C# AI looks something like:
The simplest C# AI looks something like:
Code: Select all
using System;
using CSharpAI;
namespace CSharpAI
{
/// <summary>
/// Description of CSAI.
/// </summary>
public class CSAI : IGlobalAI
{
static CSAI instance = new CSAI();
public static CSAI GetInstance(){ return instance; } // Singleton pattern
IAICallback aicallback;
int team;
CSAI()
{
}
public void InitAI(IAICallback aicallback, int team)
{
this.aicallback = aicallback;
this.team = team;
//aicallback.SendTextMsg("Hello world", 0 );
}
public void Shutdown()
{
}
public void UnitCreated(int unit)
{
}
public void UnitFinished(int unit)
{
}
public void UnitDestroyed(int unit, int attacker)
{
}
public void EnemyEnterLOS(int enemy)
{
}
public void EnemyLeaveLOS(int enemy)
{
}
public void EnemyEnterRadar(int enemy)
{
}
public void EnemyLeaveRadar(int enemy)
{
}
public void EnemyDamaged(int damaged, int attacker, float damage, Float3 dir)
{
}
public void EnemyDestroyed(int enemy, int attacker)
{
}
public void UnitIdle(int unit)
{
}
public void GotChatMsg(string msg, int player)
{
}
public void UnitDamaged(int damaged, int attacker, float damage, Float3 dir)
{
}
public void UnitMoveFailed(int unit)
{
}
public int HandleEvent(int msg, object data)
{
return 0;
}
public void Update()
{
}
}
}
The lobby will present all 3 dlls to the user even though onyl 1 is to be used.
tasclient doesnt actually do anything or make any calls it just lists all the dlls in the folder, which is the beginning of a GUI nightmare with CSAI for new users.
Whats nant?
AI devs follow:
open project
press build
copy dll to spring folder
I'm sure you should be able to do the same with this. You are the only AI dev to use this sort of thing, everyone else uses VS2003/5 or codeblocks projects, kloot being under linux is a different story too, all he has to do is 'scons AI' iirc.
As for the singleton pattern, doesnt that mean there can only be 1 CSAI? AIs are commonly used in packs of 2 4 5 and 8, rarely are they seen on there own ingame.
tasclient doesnt actually do anything or make any calls it just lists all the dlls in the folder, which is the beginning of a GUI nightmare with CSAI for new users.
Whats nant?
AI devs follow:
open project
press build
copy dll to spring folder
I'm sure you should be able to do the same with this. You are the only AI dev to use this sort of thing, everyone else uses VS2003/5 or codeblocks projects, kloot being under linux is a different story too, all he has to do is 'scons AI' iirc.
As for the singleton pattern, doesnt that mean there can only be 1 CSAI? AIs are commonly used in packs of 2 4 5 and 8, rarely are they seen on there own ingame.
- hughperkins
- AI Developer
- Posts: 836
- Joined: 17 Oct 2006, 04:14
> The lobby will present all 3 dlls to the user even though onyl 1 is to be used.
Luckily, only the initial ABIC dll is in the bot-libs folder. The other dlls are scattered elsewhere (see the comments: csailoader goes in taspring root, AI itself goes wherever you choose, according to the csailoader config file)
> open project
> press build
> copy dll to spring folder
Once you've built the csailoader dll, it just sits there not changing ,and so you just rebuild the AI.
You can reload the AI itself dynamically during a game by saying ".reloadai".
> As for the singleton pattern, doesnt that mean there can only be 1 CSAI? AIs are commonly used in packs of 2 4 5 and 8, rarely are they seen on there own ingame.
Yes, that's why I'm wondering why it's a Singleton.
For the .Net loader, it doesnt seem to matter. For the monoloader, it is a problem, but I don't think the only one.
On .Net, it's perfectly possible to have multiple AIs in parallel.
Edit:
> what's nant
It's a standard build tool for C# projects. Look on google.
I guess you mean: why dont I use a Visual Studio project?
I think there is a Visual Studio project in certain of the directories. They might need mild tweaking.
Luckily, only the initial ABIC dll is in the bot-libs folder. The other dlls are scattered elsewhere (see the comments: csailoader goes in taspring root, AI itself goes wherever you choose, according to the csailoader config file)
> open project
> press build
> copy dll to spring folder
Once you've built the csailoader dll, it just sits there not changing ,and so you just rebuild the AI.
You can reload the AI itself dynamically during a game by saying ".reloadai".
> As for the singleton pattern, doesnt that mean there can only be 1 CSAI? AIs are commonly used in packs of 2 4 5 and 8, rarely are they seen on there own ingame.
Yes, that's why I'm wondering why it's a Singleton.
For the .Net loader, it doesnt seem to matter. For the monoloader, it is a problem, but I don't think the only one.
On .Net, it's perfectly possible to have multiple AIs in parallel.
Edit:
> what's nant
It's a standard build tool for C# projects. Look on google.
I guess you mean: why dont I use a Visual Studio project?
I think there is a Visual Studio project in certain of the directories. They might need mild tweaking.