Added to meleerumble: proof-of-concept JavaScript bot; please watch inonit.robocode.javascript.MyFirstRobot

134 views
Skip to first unread message

da...@code.davidpcaldwell.com

unread,
Nov 2, 2013, 11:02:10 PM11/2/13
to
So, some potentially exciting news.

I've read a lot about the attempt to implement bots in alternative JVM languages, and I think I've succeeded in doing it for JavaScript, within the following competition-compatible constraints:

1. unmodified Rhino 1.7R3,
2. unmodified Robocode,
3. No Robocode plugins,
4. No classpath changes (Rhino included in bot),
5. Robocode security enabled

It appears to work but as people run the meleerumble we'll know more. I am running it without obvious incident.

Below is the bot's source code, which is based on the MyFirstRobot tutorial. It dispenses with the normal Java source files and properties file; it generates those at build time from the JavaScript code.

I implemented the embedding using the SLIME project at http://code.google.com/p/slime/ which provides a framework for embedding Rhino (among other JavaScript engines). The basic approach exposes the appropriate part of the Robocode API to the bot as a series of JavaScript host objects and functions.

It does not allow the use of server-side Java objects and classes directly, which would run headlong into the security manager's prohibition of reflection. So the bot is not directly exposed to the script. And currently the bot must be written entirely in JavaScript. Only the APIs required by MyFirstRobot are supported so far. :)

It loads the scripts from the robot's data directory. Since MyFirstRobot is a Robot, and my JavaScript robots extend AdvancedRobot so that they can load their scripts, I implemented my own really simple FiringAssistance, which is actually not very good, but puts the bot approximately on par with MyFirstRobot, with some differences in logic I am still learning to understand.

The framework embeds Rhino within the robot itself, so there is an entire JavaScript interpreter bundled with the bot, for better or worse. Obviously a piece of low-level code like that can have strange side effects as it interacts with the enclosing runtime, so I wanted to warn you to be on the lookout for it.

Here's the bot code; feel free to suggest simple improvements to the firing assistance (I am still learning it).

* * *

var turningGun = false;

robot.properties = {
description: "JavaScript/Rhino/SLIME Proof-of-Concept Robot",
"java.source.included": false,
version: "1.0",
"author.name": "David P. Caldwell <da...@look.in.source.code>"
}

robot.run = function() {
while(true) {
ahead(100);
if (!turningGun) turnGunRight(360);
back(100);
if (!turningGun) turnGunRight(360);
}
};

robot.onScannedRobot = function(e) {
turningGun = true;
var aim = getHeading() + e.bearing;
while (aim < 0) aim += 360;
while (aim > 360) aim -= 360;
turnGunRight(aim - getGunHeading());
fire(1);
turningGun = false;
}

-- David P. Caldwell

Pavel Šavara

unread,
Nov 3, 2013, 3:10:42 AM11/3/13
to robo...@googlegroups.com
Nice!
I would like to understand what are security implications.


On Sun, Nov 3, 2013 at 2:44 AM, <da...@code.davidpcaldwell.com> wrote:
So, some potentially exciting news.

I've read a lot about the attempt to implement bots in alternative JVM languages, and I think I've succeeded in doing it for JavaScript, within the following constraints:

1. unmodified Rhino 1.7R3,
2. unmodified Robocode,
3. No Robocode plugins,
4. Robocode security enabled

It appears to work but as people run the meleerumble we'll know more. I am running it without obvious incident.

Below is the bot's source code, which is based on the MyFirstRobot tutorial. It dispenses with the normal Java source files and properties file; it generates those at build time from the JavaScript code.

I implemented the embedding using the SLIME project at http://code.google.com/p/slime/ which provides a framework for embedding Rhino (among other JavaScript engines). The basic approach exposes the appropriate part of the Robocode API to the bot as a series of JavaScript host objects and methods.

It does not allow the use of server-side Java objects and classes directly, which would run headlong into the security manager's prohibition of reflection. So the bot is not directly exposed to the script. And currently the bot must be written entirely in JavaScript. Only the APIs required by MyFirstRobot are supported so far. :)

It loads the scripts from the robot's data directory. Since MyFirstRobot is a Robot, and my JavaScript robots extend AdvancedRobot so that they can load their scripts, I implemented my own really simple FiringAssistance, which is actually not very good, but puts the bot approximately on par with MyFirstRobot, with some differences in logic I am still learning to understand.

The framework embeds Rhino within the robot itself, so there is an entire JavaScript interpreter bundled with the bot, for better or worse. Obviously a piece of low-level code like that can have strange side effects as it interacts with the enclosing runtime, so I wanted to warn you to be on the lookout for it.

Here's the bot code; feel free to suggest simple improvements to the firing assistance (I am still learning it).

* * *

var turningGun = false;

robot.properties = {
description: "JavaScript/Rhino/SLIME Proof-of-Concept Robot",
"java.source.included": false,
version: "1.0",
"author.name": "David P. Caldwell <da...@davidpcaldwell.com>"
}

robot.run = function() {
while(true) {
ahead(100);
if (!turningGun) turnGunRight(360);
back(100);
if (!turningGun) turnGunRight(360);
}
};

robot.onScannedRobot = function(e) {
turningGun = true;
var aim = getHeading() + e.bearing;
while (aim < 0) aim += 360;
while (aim > 360) aim -= 360;
turnGunRight(aim - getGunHeading());
fire(1);
turningGun = false;
}

-- David P. Caldwell

--
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 robocode+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

da...@code.davidpcaldwell.com

unread,
Nov 3, 2013, 6:18:34 AM11/3/13
to robo...@googlegroups.com

On Sun, Nov 3, 2013 at 2:44 AM, <da...@code.davidpcaldwell.com> wrote:
So, some potentially exciting news.

I've read a lot about the attempt to implement bots in alternative JVM languages, and I think I've succeeded in doing it for JavaScript, within the following constraints:

1. unmodified Rhino 1.7R3,
2. unmodified Robocode,
3. No Robocode plugins,
4. Robocode security enabled
 
On Sunday, November 3, 2013 3:10:42 AM UTC-5, Pavel Savara wrote:
Nice!
I would like to understand what are security implications.

Well, the script engine is bundled in the robot JAR and thus is running under the security manager, and the security manager is definitely enforcing the security constraints. For example, 

1. I had to disable class loader creation in SLIME. Ordinarily SLIME creates a child class loader for scripts but when Robocode loaded SLIME it did not allow SLIME to create class loaders.

2. I also had to disable script debugging in SLIME. Ordinarily one can configure scripts to run under the JavaScript debugger but the debugger utilizes GUI classes so even when debugging was off and the Swing classes were not being used, Robocode would disallow loading the SLIME container because it contained references to classes that ultimately referenced Swing classes (and hence the Swing classes would load).

Anyway, given that the security manager is sandboxing the whole thing (including the interpreter and container), I would say the answer is that there are no security changes under this structure.

Pavel Šavara

unread,
Nov 3, 2013, 10:43:58 AM11/3/13
to robo...@googlegroups.com
OK, that sounds great :) 

Bonus question: Is there something in the package what makes exploit of current sandbox easier/possible ? Does it point us to weak spot in the current sandbox ?


--

jkfl...@gmail.com

unread,
Nov 4, 2013, 2:43:59 PM11/4/13
to robo...@googlegroups.com
Wow, David, very cool that you got that working. There was some talk a while ago about getting around codesize-detection by using the built-in Rhino engine, but it was pointed out that they wouldn't get past the security manager so that was the end of that. There have also been some (possibly even successful) attempts at writing interpreters for the same purpose, but it is generally much lower-level than JavaScript. Usually a custom assembly-style code.

Pavel, I think there might still be some way past the sandbox in the robot object instantiations. For example, if you take the bot metal.small.MCool 1.21 from the roborumble and run that, you see it prints to the general console window instead of the robot console window during loading. Or possibly it is during static{...} code sections. Unfortunately the bot doesn't include source and is obfuscated so I am not sure how it is printing.

Julian

fnl

unread,
Nov 4, 2013, 3:05:19 PM11/4/13
to robo...@googlegroups.com
Hi David,

This is really cool. =)

It would be cool to generate e.g. a library/script that can be used for writing robot using JavaScript.
I would make it easier for some people to learn JavaScript in a fun way. :-)

Do you know if Slime could be used for exposing the complete Robot API for Robocode?
Perhaps Robocode needs to be modified to support JavaScript even better? :-)

If so, this is something I will look into for a future version of Robocode. :-)

Thanks,
- Flemming


Den søndag den 3. november 2013 02.44.19 UTC+1 skrev da...@code.davidpcaldwell.com:
So, some potentially exciting news.

I've read a lot about the attempt to implement bots in alternative JVM languages, and I think I've succeeded in doing it for JavaScript, within the following competition-compatible constraints:

1. unmodified Rhino 1.7R3,
2. unmodified Robocode,
3. No Robocode plugins,
4. No classpath changes (Rhino included in bot),
5. Robocode security enabled

It appears to work but as people run the meleerumble we'll know more. I am running it without obvious incident.

Below is the bot's source code, which is based on the MyFirstRobot tutorial. It dispenses with the normal Java source files and properties file; it generates those at build time from the JavaScript code.

I implemented the embedding using the SLIME project at http://code.google.com/p/slime/ which provides a framework for embedding Rhino (among other JavaScript engines). The basic approach exposes the appropriate part of the Robocode API to the bot as a series of JavaScript host objects and functions.

It does not allow the use of server-side Java objects and classes directly, which would run headlong into the security manager's prohibition of reflection. So the bot is not directly exposed to the script. And currently the bot must be written entirely in JavaScript. Only the APIs required by MyFirstRobot are supported so far. :)

It loads the scripts from the robot's data directory. Since MyFirstRobot is a Robot, and my JavaScript robots extend AdvancedRobot so that they can load their scripts, I implemented my own really simple FiringAssistance, which is actually not very good, but puts the bot approximately on par with MyFirstRobot, with some differences in logic I am still learning to understand.

The framework embeds Rhino within the robot itself, so there is an entire JavaScript interpreter bundled with the bot, for better or worse. Obviously a piece of low-level code like that can have strange side effects as it interacts with the enclosing runtime, so I wanted to warn you to be on the lookout for it.

Here's the bot code; feel free to suggest simple improvements to the firing assistance (I am still learning it).

* * *

var turningGun = false;

robot.properties = {
description: "JavaScript/Rhino/SLIME Proof-of-Concept Robot",
"java.source.included": false,
version: "1.0",
"author.name": "David P. Caldwell <da...@look.in.source.code>"
}

robot.run = function() {
while(true) {
ahead(100);
if (!turningGun) turnGunRight(360);
back(100);
if (!turningGun) turnGunRight(360);
}
};

robot.onScannedRobot = function(e) {
turningGun = true;
var aim = getHeading() + e.bearing;
while (aim < 0) aim += 360;
while (aim > 360) aim -= 360;
turnGunRight(aim - getGunHeading());
fire(1);
turningGun = false;
}

da...@code.davidpcaldwell.com

unread,
Nov 5, 2013, 4:30:51 AM11/5/13
to robo...@googlegroups.com

On Monday, November 4, 2013 3:05:19 PM UTC-5, fnl wrote:
Hi David,

Do you know if Slime could be used for exposing the complete Robot API for Robocode?

So far, so good. I've implemented almost all of it (although I've so far tested very little of it).

There are a couple of minor issues I'd need to think through:

(1) Methods from the Robocode API that return String return java.lang.String objects, which do not behave exactly like JavaScript strings. If I was trying to hand-implement each class this would be straightforward to fix, but I'm instead attempting to automatically provide access to the API (for future-proofing and to eliminate manual errors in the tedious mapping code) and thus I would ideally want to use reflection on a method to figure out whether it returned a String, but this may run me into security problems (I haven't tried yet).

(2) I haven't attempted to implement the custom events. It's pretty straightforward to implement a Java class in JavaScript (so, for example, to implement Condition) but again this seems like an area where there's enough low-level class munging going on that the security manager may complain when I try to do it.

Those are the only potential pitfalls I see ahead.

A non-roadblock but another task is of course to try to figure out how to package it to make it possible for other people to use it. I'd have to disentangle it from my local setup and either try to make a few steps easier or write some documentation.

I'll keep you posted!

da...@code.davidpcaldwell.com

unread,
Nov 6, 2013, 11:21:12 AM11/6/13
to
On Monday, November 4, 2013 3:05:19 PM UTC-5, fnl wrote:
Perhaps Robocode needs to be modified to support JavaScript even better? :-)

If so, this is something I will look into for a future version of Robocode. :-)

I did come up with one idea for enhancement as I work with this embedding.

Treating the scripts as "data" works -- but it sort of defeats the design of the data directory. They're really code. And thus, for example, two versions of a JavaScript bot really can't (easily) each have their own code. The versions will clobber each other in the shared data directory.

Several workarounds are possible; I think the best one is to (for JavaScript bots) have the version number be part of the generated Java class name; thus each version of a bot would have its own class name, thus its own data directory, and thus its own scripts. But this is obviously not ideal. Other workarounds would include manually versioning the scripts, but then various versions are sharing the data directory quota, which is obviously not what was intended.

One solution from the Robocode side hearkens back to my original message to the newsgroup -- allow a bot to read from its own JAR file via getResource() and its related cousins. I'm not aware that this involves any security risk.

There are other options, like creating a separate concept of a "code" directory or something like that, or like having bots be able to have a data directory per version (but then I suppose this would have to be configurable).

Patrick Cupka

unread,
Nov 6, 2013, 11:22:22 AM11/6/13
to robo...@googlegroups.com
Isn't the JAR name, including the version number, part of the path of
the data directory after bots are extracted from JARs? I remember it
used to be something like
robocode/robots/.data/voidious.Diamond_1.8.22_/voidious would have
Diamond.class, Diamond.data in it. If multiple versions of the same
bot are sharing data dirs now, that would be a surprise to me. (Of
course before packaging, they would always go to eg
robocode/robots/voidious/Diamond.data.)

On Wed, Nov 6, 2013 at 11:17 AM, <da...@code.davidpcaldwell.com> wrote:
> On Monday, November 4, 2013 3:05:19 PM UTC-5, fnl wrote:
>>
>> Perhaps Robocode needs to be modified to support JavaScript even better?
>> :-)
>>
>> If so, this is something I will look into for a future version of
>> Robocode. :-)
>
>
> I did come up with one idea for enhancement as I work with this embedding.
>
> Treat the scripts as "data" works -- but it sort of defeats the design of
> the data directory. They're really code. And thus, for example, two versions
> of a JavaScript bot really can't (easily) each have their own code. The
> versions will clobber each other in the shared data directory.
>
> Several workarounds are possible; I think the best one is to (for JavaScript
> bots) have the version number be part of the generated Java class name; thus
> each version of a bot would have its own class name, thus its own data
> directory, and thus its own scripts. But this is obviously not ideal. Other
> workarounds would include manually versioning the scripts, but then various
> versions are sharing the data directory quota, which is obviously not what
> was intended.
>
> One solution from the server side hearkens back to my original message to
> the newsgroup -- allow a bot to read from its own JAR file via getResource()
> and its related cousins. I'm not aware that this involves any security risk.
>
> There are other options, like creating a separate concept of a "code"
> directory or something like that, or like having bots be able to have a data
> directory per version (but then I suppose this would have to be
> configurable).
>
> -- David P. Caldwell
> http://www.davidpcaldwell.com/
>
> --
> 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 robocode+u...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.



--
Patrick Cupka, pcu...@gmail.com
--

da...@code.davidpcaldwell.com

unread,
Nov 6, 2013, 11:43:51 AM11/6/13
to
On Wednesday, November 6, 2013 11:22:22 AM UTC-5, Patrick Cupka wrote:
Isn't the JAR name, including the version number, part of the path of
the data directory after bots are extracted from JARs? I remember it
used to be something like
robocode/robots/.data/voidious.Diamond_1.8.22_/voidious would have
Diamond.class, Diamond.data in it. If multiple versions of the same
bot are sharing data dirs now, that would be a surprise to me. (Of
course before packaging, they would always go to eg
robocode/robots/voidious/Diamond.data.)

Maybe once, but not now:

dcaldwell ~/tools/robocode/1.8.2.0/robots/.data Wed Nov 06 11:38:00
$ ls -R abc
Shadow.data/ Tron.data/   tron3/

abc/Shadow.data:
Shadow.properties

abc/Tron.data:
Tron.properties

abc/tron3:
Tron.data/

abc/tron3/Tron.data:
Shadow.properties  Tron.properties

But if this is a regression, all the better -- it'd be helpful to switch back to the old behavior. :)
Reply all
Reply to author
Forward
0 new messages