Re: Recording RoboCode battles from Java API

fnl <[email protected]> Tue, 15 Mar 2016 13:31:03 -0700 (PDT)
Newsgroups gmane.comp.java.robocode
Message-ID <[email protected]>
Well,

The robocode.control.RobocodeEngine is initialized with this method:

net.sf.robocode.core.RobocodeMainBase.initContainerForRobocodeEngine 
(robocode.core => /src/main/java):


    public static void initContainerForRobocodeEngine(File robocodeHome, 
IBattleListener listener) {
        try {
            if (robocodeHome == null) {
                robocodeHome = FileUtil.getCwd();
            }
            FileUtil.setCwd(robocodeHome);

            File robotsDir = FileUtil.getRobotsDir();

            if (robotsDir == null) {
                throw new RuntimeException("No valid robot directory is 
specified");
            } else if (!(robotsDir.exists() && robotsDir.isDirectory())) {
                throw new RuntimeException('\'' + 
robotsDir.getAbsolutePath() + "' is not a valid robot directory");
            }

        } catch (IOException e) {
            System.err.println(e);
            return;
        }

        // here we cross transition to EngineClassLoader classes using 
interface which is defined in system classLoader
        RobocodeMainBase main = 
Container.getComponent(RobocodeMainBase.class);

        main.initForRobocodeEngine(listener);
    }

Robocode(Engine) is started by this method:

robocode.control.RobocodeEngine.runBattle (robocode.api => /src/main/java)

    public void runBattle(BattleSpecification battleSpecification, String 
initialPositions, boolean waitTillOver) {
        this.battleSpecification = battleSpecification;
        ContainerBase.getComponent(IBattleManagerBase.class).startNewBattle(
battleSpecification, initialPositions,
                waitTillOver, false);
    }

Robocode is using the PicoContainer (more lightweight than e.g. Spring) for 
code injection, where interfaces like IBattleManagerBase are replaced by 
concrete object instaces within Module.java files (found in each Robocode 
module/project).

If the RobocodeEngine must be extended to support saving records to XML 
files, I propose a new method is provided on the IRobocodeEngine interface 
(and RobocodeEngine implementation class) that sets up this stuff - very 
similar to the code you used in your first mail in this thread. :-)

Cheers,
- Flemming

Den tirsdag den 15. marts 2016 kl. 17.25.17 UTC+1 skrev Andrea Giardini:
>
> Hi Flemming
>
> Can you give me a couple of more hints about this?
>
> Cheers
> Andrea
>
> On 03/09/2016 10:36 PM, fnl wrote:
>
> Hi Andrea, 
>
> It is possible, if the RobocodeEngine is extended to provide the recording 
> feature (both Java and .NET version).
> But it is time consuming to implement, and you might be the only one 
> asking for such a feature.
> You are welcome to add this feature to the RobocodeEngine as Robocode is 
> Open Source. :-)
>
> Otherwise, I think you'll have to live with the JVM reloading or take 
> advantage of the auto-recording feature, which also works with the 
> RobocodeEngine.
>
> Cheers,
> - Flemming
>
>
> Den mandag den 7. marts 2016 kl. 11.13.27 UTC+1 skrev Andrea Giardini: 
>>
>> Hi Flemming
>>
>> Thank you for your answer, it was helpful :)
>>
>> However, it didn't really solve my problem... maybe it's better if i 
>> explain you my use case a little:
>>
>> I would like to trigger a set of battles on my server every time i push 
>> to a git repository. The battles are run using a CI system that, ideally, 
>> will give me the artifacts of the recorded battles once the process is 
>> complete. Using the graphic interface is not an option here.
>>
>> As you suggested i could just create several Java processes triggering 
>> the Robocode CLI with different battle files. This solution would work for 
>> sure, but I would like to know it we could do something better (it reloads 
>> a JVM after every battle, definitely not optimal). All i need is something 
>> like this example 
>> http://robocode.sourceforge.net/docs/robocode/robocode/control/package-summary.html 
>> but able to record the battles to a br file.
>>
>> Is it possible?
>>
>> Cheers
>> Andrea
>>
>> On 03/06/2016 11:53 PM, fnl wrote:
>>
>> Hi Andrea,
>>
>> First of all, the robocode.control.RobocodeEngine does not support saving 
>> the games. It should be added to the RobocodeEngine.
>>
>> Note that you should only use classes that are a part of the public API. 
>> That is robocode.* classes like e.g. robocode.control.
>> You are not supposed to "hack" into the internals of Robocode by 
>> accessing net.sf.robocode classes. Those are internal and could change at 
>> any time.
>> Code based on internal classes might work now, but not in the future. 
>> Only the public API is guaranteed to be backward compatible.
>>
>> What you could do instead is enabling "auto recording" in Robocode from 
>> the UI by selecting Options -> Preferences -> Common Options -> "Enable 
>> auto recording ..."
>>
>> This feature will automatically record the battles and store these into 
>> the /battles directory under the /robocode directory.
>> A record will get a name like "
>> 20160306-233521-sample.RamFire-sample.Corners.zip.br" (br stands for 
>> Battle Record)
>>
>> You can replay this in Robocode (Battle -> Open Record).
>>
>> Alternatively, you could use the Robocode command-line option 
>> <http://robowiki.net/wiki/Robocode/Console_Usage>s, where you can set 
>> '-battle <battle file>' to run a specific battle specification and also set 
>> '-recordXML' in order to record the battle in XML format.
>> You can replay the records using '-replay <record file>' .
>>
>> Note that you could run Robocode in a Java Process 
>> <https://docs.oracle.com/javase/7/docs/api/java/lang/Process.html>. If 
>> you do this, you should use robocode.sh as the first command-line argument 
>> and the add the command-line options, you need. :-)
>>
>> I hope this helps? 
>>
>> Kind regards
>> - Flemming
>>
>> Den fredag den 4. marts 2016 kl. 15.24.17 UTC+1 skrev Andrea Giardini: 
>>>
>>> Hello everyone
>>>
>>> I'm trying to record battles from the java API. I would like to trigger 
>>> battles inside Java and then, at the end of the run, be able to see the 
>>> replay only of the battles i'm interested in.
>>>
>>> This is my code:
>>>
>>>
>>> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>>>
>>> import robocode.control.*;
>>> import net.sf.robocode.battle.events.BattleEventDispatcher;
>>> import net.sf.robocode.io.Logger;
>>> import net.sf.robocode.recording.BattleRecordFormat;
>>> import net.sf.robocode.recording.RecordManager;
>>> import net.sf.robocode.serialization.SerializableOptions;
>>> import net.sf.robocode.settings.SettingsManager;
>>>
>>> public class BattleRunner {
>>>      
>>>     // Path configuration
>>>     public static String roboCodePath = 
>>> "/home/andrea/git/AttProgIA_2016/RoboCode";
>>>
>>>     private static String recordFile = "/tmp/testingLOL.xml";
>>>     
>>>     // Recording 
>>>     private static SettingsManager settingsManager = new 
>>> SettingsManager();
>>>     private static BattleEventDispatcher battleEventDispatcher = new 
>>> BattleEventDispatcher();
>>>     private static RecordManager recordManager = new 
>>> RecordManager(settingsManager);
>>>  
>>>     public static void main(String[] args) {
>>>  
>>>
>>>         // Disable log messages from Robocode
>>>         RobocodeEngine.setLogMessagesEnabled(false);
>>>
>>>         // Create the RobocodeEngine
>>>         RobocodeEngine engine = new RobocodeEngine(new 
>>> java.io.File(roboCodePath));
>>>
>>>  
>>>         // Setup the battle specification
>>>  
>>>         int numberOfRounds = 5;
>>>         BattlefieldSpecification battlefield = new 
>>> BattlefieldSpecification(800, 600); // 800x600
>>>         RobotSpecification[] selectedRobots = 
>>> engine.getLocalRepository("sample.RamFire,sample.Corners");
>>>  
>>>         BattleSpecification battleSpec = new 
>>> BattleSpecification(numberOfRounds, battlefield, selectedRobots);
>>>
>>>         // *********************
>>>         Logger.setLogListener(battleEventDispatcher);
>>>         recordManager.attachRecorder(battleEventDispatcher);
>>>         
>>>  
>>>         // Show the Robocode battle view
>>>         engine.setVisible(false);
>>>         
>>>         // *********************
>>>                
>>>         // Run our specified battle and let it run till it is over
>>>         engine.runBattle(battleSpec, true); // waits till the battle 
>>> finishes
>>>  
>>>         // Save the recording
>>>         
>>>         recordManager.saveRecord(recordFile, BattleRecordFormat.XML, new 
>>> SerializableOptions(false));
>>>         // Cleanup our RobocodeEngine
>>>         engine.close();
>>>  
>>>         // Make sure that the Java VM is shut down properly
>>>         System.exit(0);
>>>      }
>>>  }
>>>
>>>
>>> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>>>
>>> Unfortunately all i get it's:
>>>
>>>
>>> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>>>
>>> No robocode.properties. Using defaults.
>>> Exception in thread "Application Thread" java.lang.NullPointerException
>>>     at 
>>> net.sf.robocode.recording.RecordManager.saveRecord(RecordManager.java:344)
>>>     at BattleRunner.main(BattleRunner.java:57)
>>>
>>>
>>> -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>>>
>>> Which i really don't understand... battles run properly (i tried to 
>>> print the results and it works correctly), but as soon as i try to save the 
>>> record i receive this null pointer exception. It looks like the recordInfo 
>>> variable inside RecordManager it's not initialized properly...
>>>
>>> Can you give me a hint? It's really annoying, and unfortunately i can't 
>>> find any documentation or examples online...
>>>
>>> Thank you
>>>
>>> Andrea
>>>
>>
>>
>

-- 
You received this message because you are subscribed to the Google Groups "robocode" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
For more options, visit https://groups.google.com/d/optout.