Can't use BodyInfo in Scrimmage
battlecode.instrumenter.InstrumentationException: ILLEGAL Illegal class: battlecode/schema/BodyType
this class cannot be referenced by player code.
Can't use Polymorphism.
Edit: mistake in title.
Why do you need BodyType? Player code can only rely on battlecode/common, you shouldn't need anything in battlecode/schema.
As far as polymorphishm goes, Robotinfo, BulletInfo, and TreeInfo all implement BodyInfo.
This really needs to be solved ASAP, as it really slows down the development process.
Polymorphism in general works as this example shows:
def testPolymorphism[T](array: Array[T]): Boolean = true
def minimalExample() = {
val trees: Array[TreeInfo] = rc.senseNearbyTrees()
assert(testPolymorphism(array)))
// No exception whatsoever
}
But there is something wrong as this example shows:
def minimalExample() = {
System.out.println(
rc.senseNearbyTrees() ++ rc.senseNearbyRobots() // InstrumentationException!
)
// This also throws an exception
(rc.senseNearbyTrees(): Array[BodyInfo]) ++ (rc.senseNearbyRobots(): Array[BodyInfo])
// The following work fine
(rc.senseNearbyTrees(): Array[TreeInfo]) ++ (rc.senseNearbyRobots(): Array[TreeInfo])
(rc.senseNearbyTrees(): Seq[BodyInfo]) ++ (rc.senseNearbyRobots(): Seq[BodyInfo])
}
Running it results in this stack trace:
Stack trace:
battlecode.instrumenter.InstrumentationException: ILLEGAL Illegal class: scala/reflect/ClassTag$
this class cannot be referenced by player code.
at battlecode.instrumenter.bytecode.ClassReferenceUtil.classReference(ClassReferenceUtil.java:172)
at battlecode.instrumenter.bytecode.InstrumentingMethodVisitor.classReference(InstrumentingMethodVisitor.java:78)
at battlecode.instrumenter.bytecode.InstrumentingMethodVisitor.visitFieldInsnNode(InstrumentingMethodVisitor.java:251)
at battlecode.instrumenter.bytecode.InstrumentingMethodVisitor.visitMaxs(InstrumentingMethodVisitor.java:108)
at org.objectweb.asm.ClassReader.a(Unknown Source)
at org.objectweb.asm.ClassReader.b(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at org.objectweb.asm.ClassReader.accept(Unknown Source)
at battlecode.instrumenter.TeamClassLoaderFactory$Loader.instrument(TeamClassLoaderFactory.java:522)
at battlecode.instrumenter.TeamClassLoaderFactory$Loader.loadClass(TeamClassLoaderFactory.java:443)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
These are really two separate issues.
For @revalo's issue:
Make sure your code doesn't rely on (even import) any battlecode code that isn't in battlecode/common.
For @omelkonian's issue:
To fix this, the devs need to whitelist scala/reflect/ClassTag$ and possibly scala/reflect/ClassTag, but as a workaround, you can convert to any other collection and it should work just fine:
object RobotPlayer {
def run(rc: RobotController) {
val things = rc.senseNearbyRobots().toList ++ rc.senseNearbyTrees().toList // this works
println(things)
}
}
Explanation:
For historical reasons, all container types except arrays undergo type erasure. A side effect of this is that in Java, generic arrays new E[] cannot be instantiated while other containers can. Scala gets around that by using ClassTag objects which store the Class object and can use reflection to instantiate new arrays of a generic type.
Edit: reformatted some things