Table of Contents

Introduction

This year's competition will once again be to write Java programs that play the game of Robocraft. Robocraft is a realtime strategy game 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 manages its own resources.
  • 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 the match 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 Robocraft map, trying to accomplish some objective. This year's objective is to capture the opposing team's flag and bring it together with your own. As can be seen in the below image, the Robocraft world consists of varying terrain types, and a team consists of four different types of robots: Sentries, Falcons, Bombers, and Tanks. 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 Overview

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", which may be land or water. 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 water terrain does not permit ground objects. All squares within the map permit air objects. The GameObjects that you will deal with are Mines and the various types of Robot.

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 to 0 or below, 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.

Robot Types

You will control four types of robots which vary greatly in their abilities. Some are ground robots, which can only traverse land, and some are air robots that can fly over water. Some can attack only ground robots, and some can attack only air robots. Additionally, robots vary in properties such as sensor and attack ranges, speed, and strength.

PictureRobot TypeDescription
Sentry A cheap and fast ground unit that attacks other ground units at close range.
Tank A slow and bulky ground unit that attacks air units with a ranged attack.
Falcon A quick and lightweight air unit that attacks other air units at close range.
Bomber A strong and powerful air unit that can bomb ground units below.

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 may move into any square whose TerrainType permits ground objects and which is not already occupied by another ground object. Air robots 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. Note that moving in a diagonal direction takes sqrt(2) times longer than moving in an orthogonal direction, rounded to the nearest integer.

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. See Appendix E for graphical depictions of different units' sensor ranges.

Flags. Any robot may query the location of its own team's flag at any time, using senseTeamFlag(). The robot carrying your team's flag can additionally sense the location of the enemy team's flag, using senseEnemyFlag(). When a robot that is carrying a flag dies, the flag is immediately dropped into that robot's location.

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).

All robots start with a fixed energon level, and can gain or lose energon over time. Every round that a robot is alive, it receives a bonus of GameConstants.ROUND_ENERGON_BONUS. If a robot calls yield() before the round is up, it is rewarded an additional GameConstants.YIELD_ENERGON_BONUS. However, once a robot has reached its fullEnergon level, it no longer recieves either of these bonuses. (See the section on Robot Characteristics below).

Robots can transfer energon between themselves using transferEnergon and may exceed their fullEnergon level through a transfer. Note that through transfers, a Robot may not exceed its maxEnergon level. A robot can therefore never, under any circumstances, have an energon level greater than maxEnergon for that Robot.

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 of a terrain type traversable by the child. An air robot can spawn any type of air robot, and a ground robot can spawn any type of ground robot. Some robots may need to get energon transfers so that they are above fullEnergon in order to spawn certain types. Child robots initially face in a random direction. They are always on the same team as their parents.

The amount of energon required to spawn each robot is given in Appendix B. Once a robot makes a call to spawn, the child robot appears immediately on the map in front of the parent and starts with that robot type's startEnergon amount 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.

Each team may have a maximum total of GameConstants.TEAM_TOTAL_LIMIT robots on the map at any given time. Also, each team may have a maximum of GameConstants.ROBOT_TYPE_LIMIT of any one robot type.

Laying Mines. Sentry robots have the special ability to lay energon land mines. A sentry can lay a mine into the square directly in front of it using the layMine method. The sentry may choose the amount of energon used, subject to minimum and maximum constraints (see Appendix C below).

A mine may only be laid on a land square that does not contain a robot or flag. If a mine is laid into a square already containing a mine, the energon in the existing mine increases by the amount requested to be laid (as though there were two mines in the same square). Mines are generally undetectable; the exception is that a robot carrying a flag can sense a mine in the square in front of it.

When a ground robot moves into a square containing a mine, the mine is triggered, and explodes shortly thereafter. When a mine explodes:

  • It deals damage to any ground robot in the same square equal to:
    (mine energon level) * GameConstants.MINE_DAMAGE_FACTOR
  • It deals damage to any ground robot in one of the 8 neighboring squares equal to:
    (mine energon level) * GameConstants.MINE_DAMAGE_FACTOR * GameConstants.FALLOUT_FRACTION
  • It triggers any mines in the 8 neighboring squares

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 teamXXX, where XXX is your three-digit team number, with leading zeros included. You may have whatever subpackages you like. You must define teamXXX.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 SentryPlayer and FalconPlayer that extend AbstractRobotPlayer, then the following might be the code of teamXXX.RobotPlayer:

package team999;

import robocraft.common.*;
import robocraft.player.*;

public class RobotPlayer extends AbstractRobotPlayer {
    
    AbstractRobotPlayer player;
    
    public RobotPlayer() {
        if (getType() == RobotType.SENTRY) {
            player = new SentryPlayer();
        }
        else if (getType() == RobotType.FALCON) {
            player = new FalconPlayer();
        }
        //...
    }
    
    public void run() {
        player.run();
    }
}

And here is a possible implementation of a SentryPlayer that spins in a circle, laying mines when it has enough energon:

package team999;

import robocraft.common.*;
import robocraft.player.*;
  
public class SentryPlayer extends AbstractRobotPlayer {
    
    public SentryPlayer() {
    }
    
    public void run() {
	while (true) {
	    try {
		while(getEnergonLevel() < MIN_MINE_POWER)
		    yield();

		while (isActive())
		    yield();
		
		layMine(MIN_MINE_POWER);
		
		while (isActive())
		    yield();
		
		setDirection(getDirection().rotateRight());
	    }
	    catch (GameActionException e) {
		System.out.println("GAE: "+e.getMessage());
	    }
	}
    }
}

Although we do not necessarily recommend this as a winning strategy.

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. Alternatively, see the "Debugging" section below for a way to print debug information without consuming 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 before trying to spawn a new robot. 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.

Since most GameActionExceptions are avoidable through programming logic or careful scheduling, there will be a minimal energon charge subtracted from your robot whenever it causes an exception to be thrown. This penalty value is defined in GameConstants.EXCEPTION_ENERGON_COST, and should not be signficant unless you are sloppy about avoiding exceptions and cause many to be thrown.

Debugging. Any output that your robots print to System.out or System.err is directed to the output and error streams of the Robocraft engine, prefixed with information about the robot. This is very useful for debugging, but it can take many bytecodes to generate useful debugging output.

For this reason, the RoboVM has a feature that allows you to separate out debugging code that is unimportant to your player's performance in the tournament. Methods that have names beginning with "debug_" and that have a void return type are given special status. By default, these methods are skipped during execution of the player. When the System property robocraft.debugMethodsEnabled is set to true, however, the methods are executed normally except that they do not count against your robot's bytecodesPerRound limit. (See the Software page for more information about properties.) Code that prepares the arguments to such a method may consume bytecodes, but the body of the method and any methods that it invokes are not counted. This feature has a limit so as not to permanently stall the game engine; only 10,000 bytecodes may be "skipped" per round before they are once again counted in the usual way.

Heap Space. Please keep your memory usage reasonable. If one of your robots uses more than 3 megabytes of memory during a match, we reserve the right to kill that robot or disqualify your team from that match.

Matches & Maps

Robocraft matches are between two teams at a time. Each team begins with a Sentry and a Falcon, each with their RobotType's startEnergon amount of energon. The sentry will start out carrying its team's flag, and the falcon will be positioned directly above it. The orientations of the robots will be random. The teams will start in opposite corners of the map.

Objective. The primary objective during a match is to capture the opposing team's flag and bring it together with your own. As soon as a single ground robot carrying one flag picks up the other flag (thus holding both flags at once), the game is over and that robot's team wins.

If many rounds elapse and neither team has captured both flags, then the match enters overtime, and the world begins to shrink inward from the outer edges. Specifically, every GameConstants.ROUNDS_PER_SHRINK rounds, the outer border of the map will disappear, and any object in a border square will explode. This will continue until either flag explodes, in which case that flag's team loses. If a robot explodes while carrying a flag, the flag will explode in the next round.

If both flags explode in the same round during a shrink, then the winning team is the team that made the most total calls to the yield() method. If these counts are equal, the team with the highest total energon possessed by robots at the start of overtime wins. In the unlikely event that this still produces a tie, the 6.370 chairmen will provide an additional criterion, such as a rematch on a new map.

You may detect that the map has begun shrinking using the isMapShrinking passive ability. If this returns true, you might want to move your flag away from the edge of the map. The shrinking of the map is not otherwise observable by a robot.

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.

The coordinate system is oriented such that x-coordinates increase to the right ("east") and y-coordinates increase going down ("south").

Map Properties. Maps will generally consist of large, connected areas of land terrain, separated from other areas by thin lines of water. In general, all of the land areas will be fairly well-connected, but there will be at least 4 "dead-ends" on the map. Each team starts in an opposite corner area, and the entire map will be symmetrical enough not to favor either team. Please refer to these examples that embody the spirit of such maps:

In addition to the above, maps will specifically have the following properties:

  • 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 20 and 30 squares (inclusive).
  • The maximum number of rounds in a match will be between 5000 and 8000. Once the maximum number of rounds has been reached, the match enters overtime and the map starts shrinking as described above.
  • There will not be a direct ground path between the starting positions of the two flags.
  • There will be some ground path between any two land squares.

Disclaimer

We have done our best to test and balance the properties of the Robocraft world. Inevitably, however, we will need to make adjustments in the interest of having a fair competition that allows a variety of creative strategies. We will endeavor to keep these changes to a minimum, and release them as early as possible. All changes will be carefully documented in the ChangeLog.

Appendix A: Robot Ability Table

Passive Abilities (do not interrupt your bytecode execution)

Method Description
getTerrainType Sense the terrain at a given square
senseNearbyGroundRobots return an array of nearby Robots on the ground.
senseNearbyAirRobots return an array of nearby Robots in the air.
senseMineAhead see if there is a mine in front of you (if you are carrying a flag).
getGroundRobotAtLocation Inspect a location for a ground robot
getAirRobotAtLocation Inspect a location for an airborne robot
getFlagTeam Returns the team of the flag you are currently carrying.
senseTeamFlag returns the location of your team's flag
senseEnemyFlag returns the location of the opposing team's flag
getNextMessage get the next message in your queue
getUnitCount returns the number of units of a particular type your team has on the map
isMapShrinking returns whether the map has begun to shrink inwards

Active Abilities (end your bytecode execution for the round)

Method Description
yield End program execution for the current round and receive an energon bonus
setDirection Change your robot's direciton
pickupFlag Pick up a flag
depositFlag Drop your flag
transferEnergon Transfer some of your energon to another robot
broadcastMessage Send out a message

Action Abilities (end your bytecode execution and require multiple rounds)

(In the following table, rt stands for one of {RobotType.SENTRY, RobotType.TANK, RobotType.FALCON, or RobotType.BOMBER}).

Method Description Duration
moveForward Immediately jump your robot to the square directly in front of you rt.moveDelayOrthogonal() (for non-diagonal movement)
rt.moveDelayDiagonal() (for diagonal movement)
moveBackward Immediately jump your robot to the square directly behind you rt.moveDelayOrthogonal() (for non-diagonal movement)
rt.moveDelayDiagonal() (for diagonal movement)
attackGround Initiate a ground attack. Damage is dealt immediately. rt.attackDelay()
attackAir Initiate an air attack. Damage is dealt immediately. rt.attackDelay()
layMine Create a mine in front of you. rt.mineDelay()
spawn Create a new robot in front of you. The robot appears immediately. rt.spawnDelay() (for the parent)
rt.wakeDelay() (for the offspring)

Appendix B: Robot Characteristics

Robot Comparison Chart

PropertySentryTankFalconBomber
General
bytecodesPerRound2500250025002500
startEnergon1.01.01.01.0
fullEnergon65.080.035.080.0
maxEnergon130.0160.070.0160.0
spawnCost25.060.030.050.0
spawnDelay5010050100
wakeDelay5010050100
broadcastRadius4444
isAirbornefalsefalsetruetrue
canLayMinetruefalsefalsefalse
mineDelay10101010
canCarryFlag(! isAirborne)
Movement
moveDelayOrthogonal20251520
moveDelayDiagonal((int)Math.round((double)moveDelayOrthogonal*Math.sqrt(2.0)))
Sensor
sensorRadius2334
sensorAngle180.090.0180.0360.0
Attack
attackAngle0.045.00.00.0
attackRadiusMin0200
attackRadiusMax1510
canAttackAirfalsetruetruefalse
canAttackGroundtruefalsefalsetrue
attackDelay15251525
attackPower20151050

Appendix C: Other Game Constants

Name Description Value
BROADCAST_FIXED_COST Fixed cost to send a message 0.01
BROADCAST_COST_PER_BYTE Additional cost per byte of message size 0.0001
YIELD_ENERGON_BONUS Amount of energon you get for calling yield() 0.02
ROUND_ENERGON_BONUS Amount of energon you get every round, unconditionally 0.1
EXCEPTION_ENERGON_COST Amount of energon you lose for causing a GameActionException 0.1
ROBOT_TYPE_LIMIT Max number of robots each team can have of a single RobotType at a given time 24
TEAM_TOTAL_LIMIT Max number of robots each team can have total at a given time 32
ROUNDS_PER_SHRINK Number of rounds between shrink events when a match goes into overtime. 100
MIN_MINE_POWER Minimum amount of energon you can use to build a mine 1.0
MAX_MINE_POWER Maximum amount of energon you can use to build a mine Double.MAX_VALUE
MINE_DELAY_ROUNDS Rounds between mine being triggered and exploding 5
MINE_DAMAGE_FACTOR Multiplied by energon in a mine when computing damage 5.0
FALLOUT_FRACTION Fraction of mine damage neighboring squares receive when mine explodes 0.1

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

Sentry

Tank

Falcon

Bomber