1

So I'm playing with writing a battlecode player in Scala. In battlecode certain classes are disallowed and there is a runtime exception if you ever try to access them. When I use the Array.fill function I get a message from the battlecode server saying [java] Illegal class: scala/reflect/Manifest$. This is the offending line:

val g_score = Array.fill[Int](rc.getMapWidth(), rc.getMapHeight())(0)

The method takes an implicit ClassManifest argument which has the following documentation:

A ClassManifest[T] is an opaque descriptor for type T. It is used by the compiler
to preserve information necessary for instantiating Arrays in those cases where
the element type is unknown at compile time.

But I do know the type of the array elements at compile time, as shown above I explicitly state that they will be Int. Is there a way to avoid this? To workaround I've written my own version of Array.fill. This seems like a hack. As an aside, does Scala have real 2D arrays? Array.fill seems to return an Array[Array[T]] which is the only way I found to write my own. This also seems inelegant.

Edit: Using Scala 2.9.1

asm
  • 8,758
  • 3
  • 27
  • 48
  • As a comment, Scala 2.10 replaced this with `ClassTag`. Not sure if that matters. – asm Jan 16 '13 at 19:49

1 Answers1

3

For background information, see this related question: What is a Manifest in Scala and when do you need it?. In this answer, you will find an explanation why manifests are needed for arrays.

In short: Although the JVM uses type erasure, arrays are an exception and need a manifest. Since you could compile your code, that manifest was found (manifests are always available for proper types). Your error occurs at runtime.

I don't know the details of the battlecode server, but there are two possibilities: Either you are running your compiled classes with a binary incompatible version of Scala (difference in major version, e.g. compiled with Scala 2.9 and server uses 2.10). Or the server doesn't even have the scala-library.jar on its class path.

As said in the comment, manifests are deprecated in Scala 2.10 and replaced by ClassTag.


EDIT: So it seems the class loader is artificially restricting the allowed classes. My suggestion would be: Add a helper Java class. You can easily mix Java and Scala code. If it's just about the Int-Array instantiation, you could provide something like:

public static class Helper {
    public static int[][] makeArray(int d1, int d2) { return new int[d1][d2](); }
}

(hope that's valid java code, a bit rusty)

Also, have you tried to create the outer array with new Array[Array[Int]](d1), and then iterate to create the inner arrays?

Community
  • 1
  • 1
0__
  • 66,707
  • 21
  • 171
  • 266
  • The battlecode server has Scala 2.9 and everything is compatible. The problem is that according to the battlecode rule set you're _not allowed_ to use instances of certain classes. Use of any classes that would give you an opportunity to exploit the game are detected and an exception thrown. – asm Jan 16 '13 at 20:01
  • Looking at the battlecode page, they seem to use Scala 2.9.1; they say you should include both scala-compiler.jar (for whatever reason?) and scala-library.jar; did you do that? – 0__ Jan 16 '13 at 20:01
  • Yeah, I misspoke in my question (edited). The system version I have installed is 2.9.2 but the version being used by battlecode is 2.9.1. – asm Jan 16 '13 at 20:02
  • @AndrewMyers -- you mean, you cannot use any other classes than the ones you provide? That will be a bit tricky with Scala. Already a case class will add `Product` and so forth. See my edit, though. – 0__ Jan 16 '13 at 20:02
  • You can use standard library classes, but there's a proscribed list that you can't use. It's generally things involving reflection or online compilation. Anything that would allow you to modify the state of the VM to somehow work around game rules or get more information about game state than you're supposed to have. – asm Jan 16 '13 at 20:06
  • Good idea, that should work great since it's already a hybrid project. Thanks for the info! – asm Jan 16 '13 at 20:07
  • I have done that and it works fine. I was hoping there was a way for me to use the library functions. – asm Jan 16 '13 at 20:10