Visible Robot differences
between Java and brand new
.NET API for Robocode robots.
- Namespaces start with uppercase Robocode.AdvancedRobot instead of robocode.AdvancedRobot from Java.
- Methods start with uppercase AdvancedRobot.Execute() instead of AdvancedRobot.execute() from Java.
- Getter and setter methods are represented by properties BulletHitEvent.VictimEnergy instead of BulletHitEvent.getVictimEnergy() from Java.
- Droids are marked with Robocode.IDroid interface instead of robocode.Droid from java.
- Painting robot uses Robocode.IGraphics interface, which is similar to System.Drawing.Graphics.
- Robocode.Condition could be implemented by delegate, see SampleCs.Target.
- Interactive robot should use Robocode.Keys constants, see SampleCs.Interactive.
- team Robot messages should be binary serializable and marked with [Serializable] attribute.
- .NET robot pays more work to submit each turn into battle (to overcome the interop layer). We will probably adjust CPU time given to robot to keep fair competition. The ratio Java/.NET is for discussion yet.
- Access to files is done thru AdvancedRobot.GetDataFile() which returns System.IO.Stream
- there is difference in implementation of floating point between CLR & JVM. The JVM uses strictfp - rounding after each operation, which is more portable. Whereas CLR uses FPU wide registers to achieve better speed and precision. If you recursively recompute same numbers, it will produce a little bit different result. Nothing to worry about.
- System.Threading.Thread is banned, use Robocode.Thread instead.
About the implementation
Two years ago, when we came with the idea of introducing .NET for Robocode we had no idea what so ever how much work it would require from us. :-O
We had raw idea that the main problem is speed. Robocode version 1.6 and below used shared state in RobotPeer between Battle thread and Robot thread.
Each call on the Robot API was synchronized to one big mutex. Now imagine that each call from a .NET robot will come through interop layer and then through synchronization in Java. Our estimate was that we would need 10.000 calls per second across CLR/transport/JVM boundaries to satisfy all calls which robot does on RobotAPI. That's not very realistic!
After several trials and failures we came to idea that we will make communication between robot and battle chunky rather than chatty. We cache all commands from robot till end of turn (Execute) and then we send it to battle as a message.
The other way around it's the same. At end of turn, the battle produces a message for each robot. The message contains all the information a robot could ever ask for, i.e., all the events, positions - everything. The message is used by robot as cache for all queries on the Robot API.
And that's big success. The Java version of Robocode speedup about 10x in version 1.6.2. This design as well allows for .NET robot to cross the CLR/JVM boundary just once per turn! The messages are serializable to binary form, so the interface between robot and battle could be reused for C++/Delphi/Python/Ruby/Basic/Foxpro :-D robots in the future.
So now, how to connect two virtual machines? Webservice or tcp - slooow, named pipe - slow, COM - yeah maybe, but COM registration, JNI & PIvoke & C++ & in same process - that would be almost it.
In the end as by-product of need for Robocode, I started off new opensource project -
jni4net. It's is fast intraprocess bridge, without any native code and it's object oriented. It's generally useful for .NET+Java solutions.
There were challenges about sandboxing the robot in .NET. We use AppDomain, CAS security and static code analysis to prevent you from cheating.
There is plenty of work ahead. I would not name it now, because we would like to hear from you, what you think we should
improve?
Enjoy!