Table of Contents
Introduction
As in previous years, this year's competition will be to write Java
programs that play a realtime strategy game. This year the game is
RoboCraft (name adapted shamelessly from the popular computer game it
resembles).
RoboCraft is a virtual world in which teams of robots battle each
other head-to-head. There are some important differences between
robocraft and the traditional realtime strategy games you may be
familiar with:
- There is no omniscient player controlling a team. Instead, each
robot is controlled by its own instance of a Java program.
- Resources are not gathered and expended from a team's single
account. Instead, each robot must gather resources for itself.
- There is no human intervention in the action of your robot army.
Once a match begins, software controls all the robots in the game,
until it ends.
The screenshot below is an example of a graphical view of a
RoboCraft match. A RoboCraft match is between two teams of robots
which compete on a map, trying to kill the other's queen. As can be
seen in the image, the RoboCraft world consists of varying terrain
types, and a team consists of four different types of robots:
Soldiers, Flyers, Shooters, and a Queen. The robots are autonomous
and controlled by software that you write. The remainder of this
document will describe in detail the physics of the RoboCraft world
and how to write a player.
RoboCraft World
Map. The RoboCraft world is laid out on a grid of squares, each
defined by a pair of integer coordinates. The "map" is a finite
rectangular set of squares. Each square on the map is given a type of
"terrain", such as open land or a wall. On top of the terrain sit
GameObjects, each of which is either on the ground or in the air. A
square may contain at most one ground object and at most one air
object. Objects may not leave the map, and some terrain types, such as
walls, do not permit ground objects. All squares within the map permit
air objects. Each GameObject is either an EnergonCube or a Robot. Each
terrain type is either land, wall, water, or "off map". Only land
tiles are ground-traversable (permit ground objects), and all terrains
are air-traversable except for "off map".
Rounds. Rounds are RoboCraft's unit of time, defined in terms
of bytecodes executed by a player (see the RoboVM section). In short, a player may perform a
limited amount of computation during a single round.
Energon. Energon is the universal life-force in the world of
RoboCraft. Every robot has a supply of energon, and when a robot's
energon supply falls below 0, the robot "dies" and is removed from the
game at the end of the round, unless its energon becomes positive
before that time. Not only do robots need energon to survive, but
energon is also used as a resource, required to perform certain
actions, such as spawning new robots or communicating.
The RoboVM
The RoboCraft software contains a virtual machine called the
RoboVM. It is the RoboVM that runs your compiled Java code during the
game, and not your system's Java implementation. Compiled Java code
(found in class files) consists of instructions called bytecodes, and
the bytecodes that make up your player program are interpreted one by
one by the RoboVM. This means that the RoboVM has complete control
over the execution of your program. It also means that the only
classes and language features accessible to your player are those
explicitly supported by the RoboVM.
Execution. Each round, each robot's player is run for a
certain number of bytecodes; the number is fixed for each kind of
robot. At the end of the round, the state of the RoboCraft world is
updated. Then the next round begins and each player runs for another
round's worth of bytecodes. Thus "time" in the RoboCraft world is
defined in terms of bytecodes executed. From the point of view of the
player, however, the program runs continuously. The only
evidence of changing rounds is that queries of the outside world
return information that is only true for the duration of the current
round. Furthermore, a round may end after any bytecode, even in the
middle of evaluating an expression in your code. Individual bytecodes
are simple instructions such as "subtract" or "get field", and Java
statements are made up of many bytecodes. See Writing a Player for more on the implications of
this.
When an ability is said to "end the current round", this is
equivalent to saying that the ability uses up as many bytecodes as are
left in the current round.
Each robot essentially runs its own virtual machine, walled off
from those of the other robots. Static fields are per-robot, for
example. The only communication between robots is through broadcasting
messages (which will be discussed later).
Libraries. The RoboVM loads its own runtime libraries,
which contain independent but compatible implementations of most
classes in the packages java.lang and
java.util (but not subpackages of these), as well as
java.io.PrintStream for output. Other standard Java
library classes are not supported and are not accessible to your
player, even if it compiles successfully with references to
them. Notably, file access, reflection, threads, and date utilities
are not supported. Also, the synchronized keyword and
native code are not supported by the RoboVM.
Note that since almost all of the classes in java.lang
and java.util are written in Java, methods of these
classes take up bytecodes in the same way as methods that you write.
The RoboVM Java libraries are compatible with JDK 1.4 except for
the absence of certain classes and methods. The following classes are
absent:
java.lang.ClassLoader
java.lang.Compiler
java.lang.InheritableThreadLocal
java.lang.Package
java.lang.Process
java.lang.Runnable
java.lang.RuntimePermission
java.lang.SecurityManager
java.lang.Thread
java.lang.ThreadDeath
java.lang.ThreadGroup
java.lang.ThreadLocal
java.util.Calendar
java.util.Currency
java.util.Date
java.util.EventListener
java.util.EventListenerProxy
java.util.EventObject
java.util.GregorianCalendar
java.util.ListResourceBundle
java.util.MissingResourceException
java.util.Properties
java.util.PropertyPermission
java.util.PropertyPermissionCollection
java.util.PropertyResourceBundle
java.util.ResourceBundle
java.util.SimpleTimeZone
java.util.TimeZone
java.util.Timer
java.util.TimerTask
java.util.WeakHashMap
The following classes support only a subset of JDK 1.4:
java.io.PrintStream
- All
print and
println methods are supported.
java.lang.Class
- The methods
toString , getName , and forName
are supported. (forName will not cause classes to be
loaded that are not otherwise referenced.)
java.lang.Object
- The methods
notify , notifyAll , and wait are
NOT supported.
java.lang.System
currentTimeMillis cannot be used to get the
current time; it will return an undefined
value.arraycopy and
identityHashCode are supported.exit
is supported and will terminate the
player.System.out and System.err
are supported, but not System.in .
Heap. We will try to give players as much heap space as
possible, but keep your memory usage reasonable. During the
tournament, robots that allocate dozens of megabytes of arrays may be
killed if necessary not to run out of memory. A team whose players
routinely allocate 1000x1000 int arrays, for example, is taking an
unnecessary risk. It is hard to imagine a use for such an array. Just
keep things within reason and you'll be fine.
Robot Types
You will control four types of robots in the competition. The robots
vary greatly in their properties, such as sensor and attack ranges,
speed, and strength. Details will come later, but for now, get
familiar with the four types:
Picture | Robot Type | Description |
![](queen.gif) |
QueenRobot |
Each team starts with a single QueenRobot and cannot make new
ones. When a queen dies, the game is over and the team that still has
a queen wins. Queens are very slow but strong and powerful, able to execute
harsh attacks but only at close distances. |
![](flyer.gif) |
FlyerRobot |
FlyerRobots are the only robots that can fly, so they are the only
robots that can pass over walls. Flyers are weak and easy to kill,
but they can move fast and have a broad sensor range. |
![](soldier.gif) |
SoldierRobot |
SoldierRobots are the basic ground unit. They travel at a medium
speed, attack at a medium strength, and have a medium sensor range.
|
![](shooter.gif) |
ShooterRobot |
ShooterRobots are expensive to build, slow, and powerful. They
are the only robot with a long-range attack, so they can attack robots that
are far away from them. However, they have a very limited sensor range.
|
Robot Abilities
Robots are instances of GameObject. See the javadocs for detailed information about the
accessor methods for GameObjects and Robots. This section describes
the abilities that robots have.
Abilities. All abilities are accessed through method calls
in AbstractRobotPlayer
(which you will extend). There are three different kinds of
abilities:
- Passive Abilities: Called like normal
methods. Passive abilities do not affect the state of the world.
- Active Abilities: End the current round for the
calling robot, once the method is called and returns.
- Actions: End the current round for the calling
robot, and also change the Robot's "current action" to a new
ActionType .
Once a robot is engaged in an action, it cannot engage in any other
action for a certain number of rounds (specified in Robot Characteristics). However, actions always
take effect immediately (see Abilities and Timing, below). In
addition, some active abilities require the robot to be idle, meaning
not engaged in any action. When a robot is idle, its current action
is ActionType.IDLE .
Now we shall describe some key robot abilities. For a complete
description of the ability methods, please refer to the javadocs. For the numerical values of ranges,
action durations, etc., see Robot
Characteristics.
Direction. Each robot is facing in a specific Direction
at any given time. Robot players can change their direction with
calls to the setDirection
active ability. A robot's current direction is important for many
active abilities and actions.
Movement. Robots can moveForward
and moveBackward ,
relative to the Direction
they are currently facing. Moving is an action ability. Different
robots move at different speeds. Any ground robot (i.e. any robot
that is not a Flyer) may move into any square whose TerrainType
permits ground objects and which is not already occupied by another
ground object. Air robots (i.e. Flyers) can move into any square that
is within the bounds of the map and is not occupied by another air
robot. A single movement action moves a robot to the adjacent square
in front or behind, with the restriction that a robot may only move in
a diagonal direction if it can also move in both of the two
neigboring orthogonal (non-diagonal) directions. In other words, a
Robot may not pass through walls or other GameObjects while moving
diagonally.
Movement completes as soon as it is initiated, like all actions,
but for the purposes of animation it is drawn as if the robot moves
smoothly over the duration of the action. In other words, once a robot
begins to move towards an adjacent square on the screen, it is already
there for the purposes of the game.
Sensors. Robots use their sensors to inspect the world around
them. Methods that access current information about the world require
that the target GameObject or map square fall within the range of the
calling robot's sensor equipment. This equipment varies between kinds
of robots. Sensor ranges are sectors (pie-slices) of a circle centered
at the robot's location. The sectors are symmetric with respect to
the robot's direction. The two numbers that define robot's sensing
sector are the circle's radius and the sector's total angular extent.
For example, a SoldierRobot can sense for a radius of 4 squares and an
angular extent of 180 degrees. Thus, at any time a SoldierRobot
facing directly NORTH can sense a total of 29 squares (including its
own).
Sensing the Enemy Queen. Queens have the special ability to
sense the location of the enemy Queen at all times. Use the passive
ability method senseEnemyQueen .
Yielding. Yielding is an active ability that simply ends the
current round. When your program has nothing better to do, it should
yield
instead of wasting bytecodes. Yielding when possible helps RoboCraft
run smoothly, and to encourage this, we award a small bonus of energon
to a robot every time it yields. See
GameConstants.YIELD_ENERGON_BONUS in Appendix C.
Attacking. Attacking is an action ability. A robot chooses a
map square to attack, which must be within the robot's attack range,
and if there is a robot at that location, that robot will have its
energon level decreased by the strength of the attack. Different
robots attack with different strengths and different attack ranges.
Attack ranges are defined in a manner similar to sensor ranges
(i.e. parameterized by the radius and angle of a sector). Moreover,
there are two types of attacks: a robot may attackGround
or attackAir .
In a ground attack, only ground robots at the attacked location can be
harmed. Similarly, only air robots can be harmed during an air
attack. Not all robots can attack both air and ground. As with the
movement action, attacks affect the state of the world immediately,
and then occupy the attacking robot for a number of rounds.
Radio Communication. Robots communicate by broadcasting
messages. A message is an instance of class Message ,
and contains an array of integers, an array of Strings, and an array
of MapLocations. When a robot broadcasts a message using the active
ability broadcastMessage ,
the message is added to the message queue of each robot within the
sender's communication range. Communication ranges are always
circular. The receiving robots may use the passive ability getNextMessage
to retrieve the next message from their queue. This method returns
null if there are no messages waiting. There is no other way to
determine if there are messages in the queue, or how many there are.
Any field of a Message instance may be null, and any element of
an array may be null. Messages are essentially "cloned" when broadcast
or received, so a single Message instance may be received, mutated,
transmitted, mutated, and transmitted again.
There is no limit to the size of messages or capacity of message
queues, but sending a message requires an amount of energon that
depends on the size of the message in bytes. Each integer element
takes 4 bytes; each MapLocation takes 8 bytes, whether null or not;
and each String element takes up a number of bytes equal to the
length, with a minimum of 4 whether null or not. A null field of a
Message (i.e. no array at all) takes 0 bytes. Sending a message
requires GameConstants.BROADCAST_FIXED_COST in energon,
plus GameConstants.BROADCAST_COST_PER_BYTE energon per
byte. See Appendix C.
Energon. Energon is the universal resource of the RoboCraft
world. Robots need energon to live and also to use certain
abilities. A robot's energon may be temporarily negative (see
Abilities and Timing).
At the beginning of a match, some squares on the map will contain
EnergonCube objects. If a robot encounters an EnergonCube, it may
position itself so that the EnergonCube is directly in front of it and
use the active ability pickupEnergon
to increase its own energon. Different robots have a different amount
of maximum energon that they can carry. If a robot attempts to pick
up an energon cube that contains more energon that the robot can
carry, the amount of energon the robot can carry is removed from the
energon cube, and the rest stays. If all of the energon in a cube is
removed from it, then the cube dissappears from the map immediately.
Energon is always on the ground, but may be picked up by any robot.
A robot may also depositEnergon
to the square directly in front of it, as an active ability. Energon
may only be deposited in positive integer amounts. When energon is
deposited, a new energon cube appears immediately at the map location
directly in front of the depositing robot. Robots may only deposit
energon cubes when they would be allowed to move forward. Flyers are
not equipped with the machinery to deposit energon.
Spawning. If a robot has enough energon, it may spawn a new
robot in the square directly in front of it, by using the spawn
action. Robots can only spawn when the square in front of them is
empty and accessable (i.e. a robot in the parent's square and in the
same plane (ground/air) as the child could perform a move
action in the direction the parent is facing). QueenRobots may spawn
new robots of any type except for "Queen", but other robots may only
spawn new robots of their own type. Child robots are always on the
same team as their parents.
The amount of energon required to spawn a robot is equal to half the
maximum energon the offspring robot can carry. Once a robot makes a
call to spawn , the child robot appears immediately on the
map in front of the parent and starts with 1 unit of energon. The
parent is then engaged in ActionType.SPAWNING for some
number of rounds, while the child is engaged in
ActionType.WAKING for a certain number of rounds.
Abilities and Timing. During each game round, the existing
robots are run sequentially, roughly in their order of creation. All
active abilities and actions take effect immediately, even before the
remaining robots of the round are run. This means that a movement
action, for example, will not fail due to a "conflict" with another
robot. If the robot can move forward, and does so before the end of
the round, the movement will succeed. In the case of attacking, though
the damage is done immediately, a robot that goes into negative energon
is not removed until the end of the game round, i.e. after all
robots have been run for the round. Thus a robot could theoretically
be attacked, go into negative energon, pick up more energon and live
within the same round.
For the most part, the order in which robots are run during a round
should have a minimal impact on gameplay. For most purposes all that
matters is that between two consecutive rounds of a robot's execution,
each other robot runs for one round's worth of bytecodes and
abilities. The fact that robots do not die immediately after a fatal
blow gives a very slight advantage to "newer" robots on offense, but
this is expected to be negligible.
Writing a Player
Your player program must reside in a Java package named
teamXX , where XX is your two-digit team number. You may
have whatever subpackages you like. You must define
teamXX.RobotPlayer , which extends
robocraft.player.AbstractRobotPlayer . Whenever a new
robot is created, your RobotPlayer class is instantiated
by the game using a constructor with no arguments, and then the game
calls your run() method. If this method ever finishes or
terminates with an exception, the robot dies and is removed from the
game. You are encouraged to wrap your code in loops and exception
handlers so that this does not happen.
Your RobotPlayer inherits the methods used to perform
active abilities and actions. It also has access to
getRobot , which returns a Robot object
representing the calling robot. For your convenience,
AbstractRobotPlayer has methods for accessing the
properties of the player robot, such as getLocation() ,
which is equivalent to getRobot().getLocation() , except
that the former is specified to not throw an exception.
AbstractRobotPlayer implements the
GameConstants interface, which means that the names of
game constants can be used as if they are fields of your class. You
may define other subclasses of AbstractRobotPlayer
besides RobotPlayer in your package, and instantiate and
run them.
If you defined classes in your package called
QueenPlayer and SoldierPlayer that extend
AbstractRobotPlayer , then the following might be the code
of teamXX.RobotPlayer :
package team99;
import robocraft.common.*;
import robocraft.player.*;
public class RobotPlayer extends AbstractRobotPlayer {
AbstractRobotPlayer player;
public RobotPlayer() {
if (getType() == ObjectType.QUEEN_ROBOT) {
player = new QueenPlayer();
}
else if (getType() == ObjectType.SOLDIER_ROBOT) {
player = new SoldierPlayer();
}
//...
}
public void run() {
player.run();
}
}
|
As mentioned before, each robot runs the player program
independently, and no information is shared between the robots'
programs except for information that arrives in broadcast
messages.
Once a robot begins running your player program, the program
retains control as long as the robot exists. Time passes as the
bytecodes of your program are executed, but this is not directly
detectable except through interactions with the world. (See the RoboVM section.) It means, however, that you have
to be prepared for the current round to end and the state of the world
to change at any time. For example, if an object shows up on your
robot's sensors and you then ask for the object's location, the object
could theoretically now be out of sensor range, if a round has ended
between the sensor reading and the location request, and in this case
an exception will be thrown. Similarly, if a Robot has recently died
then abilities referencing that robot will fail. A square seen to be
unoccupied may become occupied before you have a chance to move into
it. These possibilities are unavoidable, as all computation takes a
certain number of bytecodes and only so many bytecodes fit in a
round.
One way to deal with this is to minimize the number of bytecodes
you execute in a round. Actions and active abilities, including
yield , end the current round, meaning that subsequent
code is executed at the beginning of a new round. You could then try
to make it likely that another action or active ability will be used
before a round's worth of bytecodes have been executed. In any case,
you will probably want to write your player efficiently because it
only has so much time to "think". The Clock class
provides a way to identify the current round and thus detect when a
new round has begun, as well as to discover how many bytecodes have
been executed during the current round and thus how many remain.
One point to keep in mind regarding efficiency is that
concatenating Strings, numbers and Objects takes up many bytecodes,
because the classes String and StringBuffer are written in Java. When
constructing debug messages to send to System.out , for
example, you may wish to pass each piece of the message to the
appropriate System.out.print(...) method rather than
using the + concatenation operator. The print commands
themselves are native and consume minimal numbers of bytecodes.
GameActionExceptions. There will very likely be times,
however, when a round does end at some unpredictable place in the
middle of your code. Therefore you must write your player defensively
and handle GameActionExceptions judiciously. GameActionExceptions are
thrown whenever an ability cannot be performed. This is often due to
the changing state of the world. In this case it is usually better not
to try to address and recover from the different kinds of
GameActionExceptions individually, but to be prepared for any ability
to fail and to make sure that this has as little effect as possible on
the control flow of your program. This means catching
GameActionExceptions close to where they may be thrown.
GameActionExceptions may also be thrown by abilities as a result of
faulty program logic as opposed to uncertainty about the world. For
example, a robot may neglect to make sure it has enough energon to
deposit an energon cube. These kinds of exceptions should be
preventable through good programming, and if one is thrown it may
indicate a bug in your program. You may wish to re-throw such
GameActionExceptions when caught, based on their error code, so that
they are not ignored. This re-throwing could even be abstracted into a
function called at the beginning of catch blocks.
Matches & Maps
RoboCraft matches are between two teams at a time. Each team begins
with only a single QueenRobot unit on the map. Each QueenRobot starts
with 100.0 units of energon. Maps will be symmetric enough that no
team will have an obvious advantage.
Objective.The primary objective during a match is to attack and
kill the other team's queen unit. Once a team has killed the enemy
queen, the match is over and the team of the remaining queen wins.
If many rounds elapse and neither queen is dead, then the winning team
will be the team with a live ground robot unit closest to the
enemy queen when the final rounds finishes (Flyers do not count).
There will be no way to determine the EXACT maximum number of turns in
a match.
If, after the game is over, both teams have a unit equally close to
the enemy queen, then the match will be decided by looking at
second-closest unit, third-closest unit, etc.
If, after examining all units' proximity to the enemy queen, both
players are still in a tie, the match will be decided by the total
amount of energon posessed by each team.
MapLocation Coordinates. As an extra challenge, the coordinates
of MapLocations on tournament maps are not based on the (0,0) origin.
Instead, the coordinates are shifted; the upper-left corner of the map
might be location (38282,1022101) (to pick two random numbers). Thus
you cannot use absolute map locations to infer the boundaries of the
map.
Maps. We will ensure the following properties of Maps:
- They will be rectangular (i.e., within the rectangular bounds of the map, you will never get a TerrainType.OFF_MAP).
- Both the width and height of the Map will be between 30 and 40 squares (inclusive).
- Each team will start with a single queen with 100.0 units of energon.
- The initial queens will each be within sensor range of 120.0 units of energon (not including the 100.0 they start with).
- The total amount of energon on the map divided by the total number of squares on the map will be between 1.5 and 2.5.
- The energon cubes will differ in amount of energon they contain, but will average between 29.0 and 31.0
- The energon will tend to be scattered around the map, rather than lumped together in only a few spots
- The maximum number of rounds in a match will be between 6000 and 9000.
- The queens will be placed on opposite ends of the map, at least 35 squares apart.
- There will not be a direct ground path between the starting positions of the two queens.
- At least 60% of the map will be ground-traversable.
- All we will say about the arrangement of walls is that we won't
make the map too intricately "maze-like", and that the maps we create to fit these specs, including the seeding round and tournament maps, will all be somewhat similar in character.
Downloading & Running the Software
robocraft-1.2.2.jar [version 1.2.2, 01-28-2004]
These instructions assume you are on a UNIX-like system. If you are
on windows, we suggest you download cygwin from http://www.cygwin.com/. You also,
obviously, need a recent JDK from Sun. We suggest 1.4.2. We assume
you have basic knowledge of how to get java programs running on your
system.
- First download the jar file from the above link.
- Next extract it somewhere by typing:
$ jar -xvf robocraft-1.2.2.jar
Now you can test it by running the default map with the default players:
$ java -classpath "robocraft-1.2.2:robocraft-1.2.2/classes"
robocraft.MatchRunner
(Note1: type it all in on one line).
(Note2: on cygwin for windows, replace the colon with a semicolon).
That command will run robocraft's MatchRunner on the default map
(located in robocraft-resources/maps/default.map .
You should see a graphical display of the RoboCraft world, which
should animate the green player building a ShooterRobot, then
attacking and killing the enemy Queen.
To run your own player, make sure teamXX is contained in the classpath
and specify a new map with the --mapname argument to
MatchRunner. MatchRunner will search for map files in the
robocraft-1.2.2/resources/maps directory. [Tip: You
can keep your own maps separate from our maps by creating your own
'resources' directory and its own 'maps' folder inside. If your
resources directory is also in your classpath, then MatchRunner should
find your own custom maps as well].
The map file format is pretty self-explanatory, so we think you can
figure out how it works by looking at default.map. Then you can start
writing your own maps for testing purposes.
Note: The current code that reads maps does not handle malformed files
graciously. If you load with --mapname a custom map that is
malformed, you will probably get an indecipherable
NullPointerException.
MatchRunner has a few other arguments that it can take. Run
MatchRunner with the "--help" flag to see them.
Example. Here is an example: you just wrote your own player
called team00 . The compiled class file RobotPlayer.class
is located inside
/path/to/myclasses/team00/RobotPlayer.class . You want to
test team00 against the default built-in team (team99). This is what
you do:
-
The simplest way is to edit the default map. Edit
robocraft-1.2.2/resources/maps/default.map with your
favorite text editor.
-
Change the line that says
teamB=team99.RobotPlayer to say
teamB=team00.RobotPlayer .
-
Now, on the command line, invoke the MatchRunner like this:
$ java -classpath
"/path/to/myclasses:robocraft-1.2.2:robocraft-1.2.2/classes"
robocraft.MatchRunner
(Remember: type it all in on one line)
Or, if you wanted to use your own map called "mymap.map" (located in a
folder in your classpath called "resources/maps"), and you wanted the
match to execute as fast as possible, you would type:
java robocraft.MatchRunner --mapname mymap.map --topspeed
System Requirements. The software has been tested on Athena Sun
and Athena Linux machines, as well as various non-Athena i386-linux
machines, and also on Windows and MacOS X. All that is required is
that you have a recent version of Java 1.4. We assume you have
general knowledge of how to get java programs running and compiling on
your machine.
Getting Help
6.370 is technically a class, but we are not trying to teach
you how to program in Java. Please don't ask us about Java
programming in general. You are on your own for that. We assume you
have a basic knowledge of Java, or a willingness to learn it, and will
consult the appropriate reference materials.
If any parts of this document or the javadocs, or anything about the
competition at all is unclear, please feel free to send email to
6.370-questions @ mit.edu .
Administrative questions about the competition should go to
6.370-chair @ mit.edu
If you think there is a bug in any of the contest software (drawing
glitch, VM exception, anything like "really bad error" gets printed on
your console window, etc.), then please send a bug report with
instructions on how to reproduce your error (include code and map
files if necessary) to 6.370-bugs @ mit.edu .
Specifically, if you ever see an "internal_error" exception being
thrown, please report it right away with instructions on reproducing
the error.
Important: Before sending us email, please check the follwing.
- Make sure your question is not answered in this document (keeping
in mind that they may change over time, as recorded in the Changelog
- Make sure you have the latest version of our jar file, which can
be downloaded in this section.
Finally, Organizers and developers may sometimes haunt the 6370 Zephyr
instance. You can write to them by typing:
zwrite -i 6370
Make sure you are subscribed to the 6370 instance before you write to
it. To do this, refer to this document.
There is also an Athena mailing list
(6.370-discuss @ mit.edu ) for both teams and
organisers to discuss technical issues and answer questions about the
contest. We hope that competitors will help participate in the
technical support effort.
Please keep in mind that 6.370 is completely student run, and
we have limited resources with which to address your questions.
Appendix A: Robot Ability Table
Passive Abilities (do not interrupt your bytecode execution)
Method | Description |
getTerrainType |
Sense the terrain at a given square |
senseNearbyObjects |
return an array of nearby GameObjects |
getNextMessage |
get the next message in your queue |
getGroundObjectAtLocation |
Inspect a location for a ground object |
getAirObjectAtLocation |
Inspect a location for an air object |
senseEnemyQueen |
get location of enemy Queen (used by Queen) |
Active Abilities (end your bytecode execution for the round)
Method | Description |
yield |
End program execution for the current round and receive an energon bonus |
broadcastMessage |
Send out a message |
setDirection |
Change your robot's direciton |
pickupEnergon |
Pick up some energon |
depositEnergon |
Create a new energon cube in front of you |
Action Abilities (end your bytecode execution and require multiple rounds)
(In the following table, FOO stands for one of {SHOOTER, QUEEN, FLYER, or SOLDIER}, depending on the robot).
Method | Description | Duration |
moveForward |
Immediately jump your robot to the square directly in front of you |
FOO_ROUNDS_PER_MOVE |
moveBackward |
Immediately jump your robot to the square directly behind you |
FOO_ROUNDS_PER_MOVE |
attackGround |
Initiate a ground attack. Damage is dealt immediately. |
FOO_ROUNDS_PER_ATTACK |
attackAir |
Initiate an air attack. Damage is dealt immediately. |
FOO_ROUNDS_PER_ATTACK |
spawn |
Create a new robot in front of you. Robot appears immediately |
FOO_ROUNDS_PER_SPAWN (for the parent)
FOO_ROUNDS_PER_WAKE (for the offspring) |
Appendix B: Robot Characteristics
Robot Comparison Chart
|
QueenRobot |
FlyerRobot |
SoldierRobot |
ShooterRobot |
General Properties |
bytecodes per round |
4000 |
3000 |
2400 |
2000 |
airborne? |
no |
yes |
no |
no |
build cost energon |
n/a |
20.0 |
40.0 |
60.0 |
spawn and wake time (rounds) |
10 |
20 |
40 |
60 |
starting energon level |
100.0 |
1.0 |
1.0 |
1.0 |
maximum energon level |
200.0 |
40.0 |
80.0 |
120.0 |
can deposit energon? |
yes |
no |
yes |
yes |
message broadcast radius (squares) |
10.0 |
5.0 |
5.0 |
5.0 |
Movement |
movement time (rounds) |
25 |
4 |
6 |
9 |
Sensor Ranges |
sensor radius (squares) |
8 |
6 |
4 |
3 |
sensor angle (degrees) |
360.0 |
360.0 |
180.0 |
90.0 |
Attack Properties |
can attack ground? |
yes |
no |
yes |
yes |
can attack air? |
yes |
yes |
no |
yes |
attack range radius (squares) |
1.5 (adjacent) |
1.5 (adjacent) |
1.5 (adjacent) |
6.0 (non-adjacent only) |
attack angle (degrees) |
360.0 |
0 (forward-only) |
0 (forward-only) |
45.0 |
attack power (energon) |
10.0 |
2.5 |
5.0 |
15.0 |
attack time (rounds) |
10 |
4 |
6 |
9 |
Appendix C: Other Game Constants
Name |
Value |
YIELD_ENERGON_BONUS |
0.05 |
BROADCAST_FIXED_COST |
0.01 |
BROADCAST_COST_PER_BYTE |
0.0001 |
Appendix D: Javadocs
Please help yourself to some javadocs.
Appendix E: Sensor and Attack Range Diagrams
Key
In Sensor Range
In Attack Range
In Sensor & Attack Ranges
Soldier
Shooter
Flyer
Queen
ChangeLog
2004-01-04
2004-01-05 [JAR release 1.0]
- Fixed a typo in the "Getting Help" section: the course mailing
list is
6.370-discuss (with a period), not
6370-discuss .
- Fixed a typo in the javadoc for
AbstractRobotPlayer.yield() :
ENERGON_YIELD_BONUS should have been YIELD_ENERGON_BONUS. The javadoc
online has been updated, but the javadoc included in the JAR file will
not be updated until the next release of the JAR file.
2004-01-07 [JAR release 1.1]
- Rules Changes
- Flyers do not count in distance-to-queen computation of the
winner of the game when neither Queen has died. This secondary
criterion was used as an approximation of which team has made more
progress toward killing the opponent's queen, but we didn't take into
account that Flyers cannot attack queens anyway.
- Clarifications and Typos
- Corrected and clarified javadocs for
AbstractRobotPlayer. GameActionExceptions are thrown when things are
NOT in sensor range. Spawning does NOT require that you have enough
energon (you can kill yourself this way). The description of
getNextMessage() was incorrect.
- Slight clarification of specs section on Message costs.
- The requirements for spawning have been clarified for the
case of a Queen spawning a Flyer.
- Bug Fixes
- A Queen can no longer spawn multiple Flyers into the same
square. This was an unintentional violation of the rules about
GameObjects and squares.
- getGround/AirObjectAtLocation() now correctly returns an instance
of class Robot or EnergonCube.
- AbstractRobotPlayer.canMove() and Robot.canMove() now return FALSE
if you pass in Direction.NONE or Direction.OMNI.
- AbstractRobotPlayer.setDirection() throws a GameActionException if
you pass in Direction.NONE or Direction.OMNI.
- A RoboVM bug has been fixed that resulted in an occasional
internal NullPointerException when preparing a bytecode-related
(e.g. index-out-of-bounds) exception to be thrown.
- MapLocation.add(Direction) now silently returns the same location
when you try to add OMNI or NONE.
- New Features
- senseNearbyObjects() is now atomic and never fails.
- There is a new Robot method, canSenseObject(), for asking if a
certain object is within sensor range. There is also a corresponding
AbstractRobotPlayer.canSenseObject() that does not throw an
exception.
- Robot methods that depend only on the Robot's type
(canAttackAir(), canAttackGround(), getBytecodesPerRound(),
getAttackPower()) no longer throw an exception.
- AbstractRobotPlayer wrappers for Robot methods are now static,
like getRobot(), but are protected, like the other AbstractRobotPlayer
methods. You must arrange to have them called from an instance of
AbstractRobotPlayer.
- When robots use System.out, the string prefix now indicates the
team of the robot. (i.e.,
"[SHOOTER_B12]" instead of
"[SHOOTER_12]" )
- MatchRunner now supports
--nographics , which prints
text messages about game events (instead of drawing to the
screen).
- The graphical display draws the purple circles (indicating that a
robot broadcasting) out to a radius of 1.5 squares always, instead of
the broadcast radius of the robot. This speeds up the graphics
tremendously. (Try the default map again with --topspeed!).
2004-01-08 [JAR release 1.1.2]
- Bug Fixes
- MapLocation's hashCode() and equals() methods work correctly.
2004-01-11 [JAR release 1.1.3]
- Clarifications
- New section in "Matches & Maps" gives more specifics on maps.
- New section "Abilities and Timing" under Robot Abilities.
Clarified timing of actions and active abilities.
- Improved javadocs for senseNearbyObjects()
- Clarified in Appendix B that Shooters cannot attack the square
directly in front of them. To clarify all the attack and sensor
ranges, we have added Appendix E: Sensor and
Attack Range Diagrams.
- There is now a Heap section under The RoboVM with a note on allocating memory.
- Bug Fixes
- Robot.canAttackAir() now returns TRUE for Queens
- canAttackAir() and canAttackGround() now really don't throw an exception
- fixed bug in canSenseObject() that was causing it to always return true.
- Graphics
- Queen graphic is slightly directional (so you can tell which way a queen is facing).
- New Features
- AbstractRobotPlayer's ability methods are now all public (instead of protected)
- New map file released (resources/maps/first.map) adhering to map specifications.
2004-01-12
2004-01-14 [JAR release 1.1.4]
- Bug Fixes
- Fixed ocassional NullPointerException in internal method GameWorld.getRobot()
- Fixed ocassional ConcurrentModificationException that occured under MacOS X
- New Stuff
- Added the compiled package refplayer (refplayer.RobotPlayer) to the classes folder. (You can now play the ref player).
- World Changes
- We thought Shooters were too weak, so we DOUBLED their attack power!
2004-01-18 [JAR release 1.1.5]
- Bug Fixes
- Fixed bug in VM that would occasionally cause NullPointerException
during exception handling.
- Fixed serious VM bug in handling of fields of types "double" and "long".
These are 8-byte fields, but would often only get 4 bytes reserved for them.
This was causing some ugly stack-traces.
- New Features
- Many optimizations should increase the overall speed of gameplay.
2004-01-18 [JAR release 1.1.6]
- New Features
- Added superref.RobotPlayer (the original, difficult version of the reference player, just for your fun) to the classes in the JAR file.
- Added a src/ directory to the JAR file, with source code to an simple, example player.
- Pressing space during the gameplay will pause/resume the gameplay
- Round number is displayed in the lower-right corner of the screen
- Bug Fixes
- Corrected graphics glitch that sometimes caused squares to not refresh after an energon cube was picked up from them.
- Clarifications to Specs
- No more getMatchRounds() method.
2004-01-20
- Clarifications
- Clarified wording under "Movement" of the conditions for moving
diagonally. To move diagonally north_east, for example, you must have
BOTH moving north and moving east as options, or, in other words, you
must be in a position such that you COULD move in EITHER
direction. Some people may have been confused by the word "either" and
thought that only one of the two (north and east) squares needed to be
open.
2004-01-21 [JAR release 1.1.7]
- Bug Fixes
- Dividing by int/long 0 in your player no longer brings down the game
- Fixed bug where accessing a non-existent EnergonCube would cause a crash
- Fixed bug where throwing a ClassCastException would cause a crash
- Fixed graphics glitch that caused energon cubes to not disappear when removed.
- Fixed integer overflow error that was causing bogus locations to appear in attack range of shooters
- New Features
- --simplegraphics disables the broadcast circles. this speeds up graphics a little
2004-01-21 [JAR release 1.1.8]
- New Features
- The map used for the seeding tournament is included (seeding.map).
- The source to the Java libraries (java.lang, java.util) in included in src/vmlib. Now you can get an idea what your calls are doing.
2004-01-23 [JAR release 1.1.9]
- New Features
- MatchRunner now takes --teamA and --teamB arguments, to override the players specified in the map file.
- Game World Changes
- Each team is limited to having 64 of each unit type total on the map at once. For example: If you try to spawn a flyer while you already have 64 flyers, you will get a GameActionException.CANT_SPAWN_THAT exception.
2004-01-26 [JAR release 1.2]
- New Features
- Sounds Effects! Enabled by default. Turn off with --noaudio.
- Bug Fixes
- Fixed bug in communications that would sometimes cause Messages sitting
in queues to be mutated.
2004-01-27 [JAR release 1.2.1]
- New Features
- Colors of teams are more distinctive
- Bug Fixes
- Sound should work a little better and be more synced with game actions.
2004-01-28 [JAR release 1.2.2]
- New Features
- Directional Audio!
- Energon Cubes shrink when dissappearing.
- Better sound clips.
|