Build the best - destroy the rest!

Saturday, 28 June 2008

Robocode 1.6.1 Beta

We are proud to present new version of Robocode for community testing.

Robot visible changes


  • We introduced new feature -DRANDOMSEED, which must be set to a specific random seed value. When this option is set, the random number generator used in Robocode becomes deterministic. So your robots will appear in exactly the same positions, when you rerun battles. This is very useful when testing and debugging your robot, because you will be able to repeat problematic situations again and again.

  • The new random number generator for the -DRANDOMSEED also overrides method e.g. Math.random(), so it will make robots based on this also deterministic. We are also looking for smart trick to replace instances of Random class used by robots in the future, but we didn't figured it out yet. Note that this random generator is only deterministic when the -DRANDOMSEED has been set. Otherwise we use same Java generator as before, making game pseudo-random.

  • We introduced new experimental feature -DPARALLEL (set to true or false). It allows robots run in parallel intended to take advantage of more CPU's available in the system. (Default is that for each turn robots are resumed sequentially). It may speedup battles with multiple CPU consuming robots. Time measuring is not per robot, so it cannot be used in contest, but might be nice for training. Please let us know if you like it or not.

  • We introduced new feature 1878233: onBattleEnded event. It is useful for learning robots, because event will always be sent at the end of each battle no matter if you won, lost or the battle was aborted. When the onBattleEnded event occur you could save your settings to disk. Also the battle results are dispatched to you.

  • Robot has new method getGraphics(). It allows you to draw your custom drawings to the battle view any time, not only during onPaint() event. Drawing will appear on end of turn.

  • Interactive events like onMouse*(), onKey*() and also onPaint() are now dispatched thru standard robot's event queue, so they will be called on robot's thread. So your robot will pay a bit of CPU time when using these.

  • Messages from robots to console are now dispatched on end of each turn.

  • AdvancedRobot and IAdvancedRobotPeer has got the new method getStatusEvents(), so a robot is now able to handle status events in the middle of an event handler.

  • Feature 1954853 : Name of robot's package was extended from 16 to 32 characters. The Robocode Repository is able to handle this (verified with Dan Lynn).


User interface changes


  • Robocode user interface was improved a bit. Also some dialogs are modal now.

  • The TPS slider has been redesigned to be more exponential, so it covers battle in slow speed (1-30 TPS), higher speed (30 - 120 TPS), and fast speed (120 - 1000 TPS). Move to zero will now pause the game.

  • New battle dialog and results dialog can be closed by pressing the Esc key.

  • The title on the Robocode window is now showing the current turn in a battle, and is updated every half second. In addition, the layout of the information shown in the title has been improved a bit.

  • The system log output has now been split, so that logged errors are sent to System.err and logged messages are sent to System.out. This makes it possible to filter out messages from errors when reading out the logs from Robocode. The system log now also includes a full stack trace when errors are logged, making it easier to determine where an error has occurred.

  • Battle view was redesigned and now it is redrawn at max 50 FPS, which saves CPU cycles, and thus allows the TPS (turns per second) to be even higher/faster.


Bug fixes


  • The field 'others' on the JuniorRobot was not updated properly when other robots dies.

  • Fixed issue with duplicate team name. The 'short name' in RobotPeer was same as 'name' for duplicate robots. Now, duplicate team named are dedupped.

  • The New Battle Dialog was resized after the robot selection.

  • After the intro battle, the Restart button was disabled.

  • InterruptedException are now being handled properly by interrupting the current thread, so it will keep its interrupted state after the InterruptedException has been caught.


Implementation details

What happened inside? Well, we were able to decouple UI and battle engine core. Till this version, the core of Robocode was tightly coupled to various components. For example, the battle thread was directly calling the BattleView to repaint each frame. We had the same issues with sounds, battle results dialog, window title and more.

On the other side, i.e. in UI, there were dependencies on the Battle class, which is the real core. The UI thread from the RobocodeFrame was calling it directly in order to stop or pause the battle. Also, the BattleView was making calls directly to the Battle to paint the battle field. Even worse, it was touching the RobotPeers (handles all logic of the individual robot) heavily causing a synchronization nightmare.

What we did? We cleaned up the mess. ;-) In the first step we introduced set of battle events, which are fired from the battle. These events are fired on the start and end of each battle, round and turn. They carry along a package of information, which is interesting for the specific type of battle event. For example, TurnEndedEvent contains all information about single turn, including current info about robots and score, and BattleCompletedEvent contains the final score, etc. The battle events are fired from the battle to a battle event dispatcher, which then dispatches these events to all registered battle listeners. Notice that the battle does not have to know know or deal with implementations of battle listeners, making the design cleaner. We implemented IBattleListener interface on all coupled UI components. And moved actions from core Battle to battle listener handlers. We also refactored components, so they now use data delivered by battle events, rather than calling the battle back to get this data.

Some of the battle listeners are just storing the event and processing it on the ATW/Swing thread. In case of the BattleView it helps us to speedup the battle, because painting is done asynchronously to the battle turns.

Next we also refactored various UI controls, so that they use the new IBattleManager interface to control the battle or robots, rather that calling these directly.

The implementation of most commands is sent to command queue on the battle and then processed on the battle thread, rather than directly on the ATW/Swing thread. This helps us to keep UI responsive while battle is being stopped and afterwards cleaned up. It also helps to gain synchronization purity.


Robocode 1.6.1

Both of the interfaces IBattleManager and IBattleListener are considered internal. They are not visible to robots (undoubtedly), but shouldn't be used by users of the RobocodeEngine as well. We plan to to make it more accessible as soon as these interfaces are stabilized.


JUnit tests

We have brand new JUnit test infrastructure based on -DRANDOMSEED feature and battle events. The current number of test is actually small, but we will continue to add more and more tests as we get along.
If you are interested to help us with creating unit tests, please drop us an email on robocode-devel group.
We will be able to provide you with test cases, which needs to be implemented. But we welcome your own test cases as well.



Update 3.7.2008: We are looking to hear your opinions about this release, bug reports, ideas for next releases. Please don't be shy and talk to us. Thanks!

For curious: I put together plan for next version 1.6.2. Comments welcome.

No comments: