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:

PictureRobot TypeDescription
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.
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.
SoldierRobot SoldierRobots are the basic ground unit. They travel at a medium speed, attack at a medium strength, and have a medium sensor range.
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
  • Initial release
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.