For this year's competition, you will write Java programs that play the game of BattleCode. BattleCode is a realtime strategy game. However, there are a number of differences between BattleCode and other realtime strategy games you may be familiar with.
First, there is no collective player that controls the team. Instead, each robot is controlled by a separate instance of a class, and robots may only share information amongst themselves using radio communication.
Second, there are no collective resources in BattleCode. Instead, there is a single type of resource called "energon," and each robot manages its own energon reserve.
Third, the entire game is run by the BattleCode software; save for a couple exceptions, there is no human intervention during the course of the game.
The rest of this document explains in detail the physics of the BattleCode world, and how to write your player.
Robots are the central part of the BattleCode world. They come in six varieties, each one having a distinct set of properties. These varieties are denoted by the RobotType enum. The following table describes the different robot types:
![]() |
Archon | A special unit that produces energon, and cannot be spawned. |
![]() |
Soldier | A cheap and fast ground unit that attacks other ground units at close range. |
![]() |
SAM | A Surface-to-Air Missile unit that attacks air units at close-medium range but cannot attack ground units. |
![]() |
Tank | A slow but hefty ground unit that attacks ground units with a powerful but delayed attack. |
![]() |
Scout | A fast and lightweight air unit that attacks other air units at close range. |
![]() |
EMP | An air unit that can detonate itself to damage nearby Archons. |
Robots can evolve into different types according to the following evolution chart:
The "round" is the basic unit of time for a BattleCode match. Each round, every robot's player gets to use the processor for a certain amount of computation (see Timing below for more details on this).
During each game round, the existing robots are run sequentially, in their order of creation. All actions (e.g., moving and attacking) take effect immediately, even before the remaining robots of the round are run. This means that if Robot 1 was created before Robot 2, and Robot 1 moves during its turn, Robot 2 will see Robot 1 in its new location in the same round. When all robots' computations have been run, the round is over. At that point, several updates are made, including message broadcasts, energon transfers, energon upkeep, and removing robots that have less than 0 energon (in that order).
Energon is the universal life-force in the BattleCode world. Every robot has an amount of energon, called its energon level. When a robot is attacked, its energon level decreases. If a robot has no energon at the end of a round, it dies and is removed from the game.
Energon is additionally used as a resource. It can be "spent" to create new robots, evolve into a different robot, or broadcast messages. Robots are also capable of transferring energon to adjacent robots.
With the exception of Archons, all robots consume energon simply by existing. Each round, every robot's energon level decreases by an amount specified by RobotType.energonUpkeep().
Special units called Archons can produce energon. Each Archon's energon level increases by a certain amount each round, called its energon production. An Archon's energon production can be increased by picking up a production upgrade (see Upgrades), or decreased by being hit with an EMP (see below).
All units also receive slight energon boosts by conserving computations. This will be discussed further under Yielding below.
Since all units except Archons consume energon, Archons can only support certain many robots each. This imposes a natural unit limit instead of a hardcoded fixed number. The choice of units and their differing decay rates determines how many robots a team may support.
Each robot has a maximum energon level. Archons cannot produce energon to exceed their maximum level, and robots cannot receive energon transfers that would exceed their maximum level. Archons can increase their maximum energon level by picking up maximum energon upgrades (see Upgrades). However, all other robots have a maximum energon level that is fixed by their robot type.
The BattleCode world contains useful upgrades on the map. When an Archon moves to the same location as an upgrade, it is automatically picked up. An upgrade can only be collected once, i.e., once an Archon takes it, it's gone. Note that only Archons can pick up upgrades.
There are two types of upgrades: production upgrades, and max energon upgrades. Collecting a production upgrade permanently increasing the Archon's production. Collecting a max energon upgrade permanently increases the Archon's maximum energon level.
BattleCode maps consist of a grid of squares, each with a pair of integer coordinates. Each square has a type of terrain: land or water. Land squares are traversible by all units; water squares are traversible only by airborne units. Locations on the map are represented as instances of MapLocation objects.
Map coordinates are represented similarly to the pixels on a computer screen: x-coordinates increase moving to the right (East), and y-coordinates increase moving down (South). However, as an extra challenge, the top-left corner of the map is not necessarily (0, 0). The coordinates are randomly shifted, so the top-left corner might be (10573, 49972), to pick two random numbers. Thus, map boundaries cannot be inferred using absolute coordinates.
Objects in the BattleCode world can exist at one of three vertical levels on the map: these levels are for ground robots, air robots, and upgrades. These levels are defined in the MapHeight enumeration. Only one object may exist per location per level at any given time. Certain robot types are restricted to the ground, and so may only occupy land squares, while others inhabit the air and so may traverse land or water squares.
Maps are specified by XML files, and can be found in the maps folder of the release archive. The schema for the files should be fairly intuitive, so if you'd like to add your own maps you can use the provided maps as a basis.
You are welcome to create any map files you'd like, in order to test your players. However, the maps used for the tournaments will abide by the following constraints. If a constraint is not listed here, do not assume that the tournament maps will abide by it.
The goal of this year's BattleCode game is simple: destroy the enemy's Archons. Once a team loses all its Archons, their opponent wins. If the round limit is reached, and each team has Archons, the winner is determined according to the following criteria, in order:
Matches this year are all best of 3 games. Each game both players start with 4 Archons and end when a team's Archons are destroyed or the round limit is hit. Then another game is played until one team collects 2 game victories. No information is transferred between games except through the Archons' memory explained below.
This section describes how robots can interact with the BattleCode world. Your player controls robots with the RobotController class. Unless otherwise noted, all methods referenced in this section are methods of RobotController.
Each robot has a current action, e.g., IDLE, MOVING, ATTACKING, as enumerated by ActionType.
Each robot also has an action queue. When a robot is IDLE, the first action in the action queue is automatically removed, and the robot executes that action. This allows actions to be automatically executed at the end of a robot's turn without explicit bytecode counting. Of course, a robot may yield and choose to execute an enqueued action before the end of its turn. Each action has a duration, of some number of rounds. Once the action is complete, the next action in the queue is automatically removed and executed. If there are no actions in the queue, the robot simply remains IDLE.
In general, the effect of an action takes place immediately, even though the action may have a duration of some number of rounds. For instance, when a robot moves, it instantly appears at its new location, and is then in ActionType.MOVING for some amount of time.
Players can add actions to the action queue using methods of the form RobotController.queue_____. Here are the possible actions that a robot can execute:
Direction - Each robot has a direction, as enumerated by Direction. Calling queueSetDirection adds an action to the queue which, when executed, changes the robot's direction. This action has a duration of 1 round.
Movement - queueMoveForward and queueMoveBackward make a robot move one square forward or backward relative to its current Direction. Moving backward does not change a robot's direction. A 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. The duration of this action is specified by RobotType.moveDelayOrthogonal() and RobotType.moveDelayDiagonal(); note that moving diagonally takes sqrt(2) times longer than moving orthogonally.
Attacking - queueAttackGround and queueAttackAir make a robot attack a specified location. The location must be within the robot's attack range, as defined by its RobotType. If there is a robot at the specified location, that robot will have its energon level decreased by the strength of the attack, as defined by RobotType.attackPower(). Except for the Tank's attack, attacks damage the target robot immediately, and then occupy the attacking robot for a number of rounds.
Tanks' attacks are different in two ways. First, there is a delay between when the Tank fires an artillery shell, and when the shell impacts the target. Thus, damage is dealt GameConstants.TANK_DELAY_ROUNDS after the attack is executed. Second, the shell does "splash damage" -- dealing RobotType.TANK.attackPower() damage to the target location, and RobotType.TANK.attackPower() * GameConstants.TANK_FALLOUT_FRACTION damage to the 8 adjacent locations.
Spawning - A robot may spawn other robots using queueSpawn. The new robot appears directly in front of and adjacent to the parent robot. Thus, robots can only spawn when the square in front of them is empty and of a terrain type traversible by the child. Child robots initially face in a random direction. They are always on the same team as their parents. Robots can only spawn the "basic" robot types, Soldier and Scout. Ground units can spawn ground and air units. Air units may only spawn air units. Note that some robots cannot spawn other robot types simply because they can never have enough energon for the spawn cost. For instance, because of max energon and upkeep, Scouts cannot spawn other Scouts.
The amount of energon required to spawn each robot is given by its RobotType.spawnCost(). Once a robot executes a spawn, the child robot appears immediately on the map in front of the parent and starts with that robot's RobotType.startEnergon() amount of energon. The child is engaged in ActionType.WAKING for a certain number of rounds.
Unlike in previous years, there is no hard limit to the number of units a team can have on the map.
Evolving - queueEvolve makes a robot "evolve" into a different robot type. Once a robot executes an evolution, the robot immediately becomes a robot of the new type. The robot is engaged in ActionType.EVOLVING for a number of rounds determined by rt.wakeDelay(), where rt is the RobotType of the new (evolved) robot.
See above for a chart of which robots can involve into which. Once evolved, a robot cannot revert to its original robot type.
In addition to actions, there are a number of other abilities that robots can perform:
Robots use their sensors to inspect the world around them. Sensor abilities are passive, and usually of the form get____ or sense____. These methods usually require that the target GameObject or map square fall within the calling robot's sensor range. One notable exception to this is the senseTerrainType method, which functions a little differently this year. Robots automatically remember all terrain they've seen, so senseTerrainType returns the terrain type of a square if it has ever been in the robot's sensor range, even if it is not ''currently'' within sensor range.
Robots communicate with each other only 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. Each robot has an outgoing message queue and an incoming message queue. When a robot calls queueBroadcast, a copy of the message is added to the outgoing message queue of the robot. Each round, one message from the outgoing message queue is broadcasted.
When a message is broadcasted, a copy of the message is instantly added to the incoming message queue of each robot within the sender's communication range (not including the sender itself). Communication ranges are always circular. The receiving robots may use the passive abilities getNextMessage or getAllMessages to retrieve messages from their incoming message queue.
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.
The outgoing message queue has a maximum length of GameConstants.BROADCAST_QUEUE_LENGTH; the incoming message queue has no maximum length. There is no limit to the size of messages, 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.
Robots can transfer energon between themselves using transferEnergon, which removes a specified amount of energon from the calling robot and adds it to the receiving robot. The receiving robot must be adjacent to or on same square as the transferring robot. Energon receiving is capped at a rate of GameConstants.ENERGON_TRANSFER_RATE units per round. Thus, if a robot transfers 10.0 energon, the receiving robot receives 2.0 energon per round for the next 5 rounds. The transferring robot is not bound to doing anything once the transfer starts, nor does it have to remain adjacent to the receiving robot.
RobotController has two methods for sensing energon levels. senseEnergonLevelOf senses a robot's current energon level. senseEventualEnergonOf senses a robot's eventual energon level, taking into account pending transfers. Energon transfers are forbidden from increasing a robot's eventual energon past its max energon.
Calling suicide immediately kills the calling robot. As noted above, the robot is not actually removed from the game world until the end of the round.
EMP units are special, because when they die, they create an EMP explosion. Any Archons within a radius of GameConstants.EMP_RADIUS are affected. Their energon production is immediately and permanently reduced by a factor of 1/(2+r), where r is the distance from the Archon to the EMP.
EMPs arm and can detonate after finishing waking/evolving. Then EMPs detonate when they die, even if the death is due to an unexpected attack. The explosion affects both enemy and allied Archons.
Archons have the special ability to remember some limited state between different games of a match. Each Archon can use setArchonMemory to save a long for the next game. If multiple calls to setArchonMemory are made by a single Archon, the last call is what is saved.
Any robot can use getOldArchonMemory to retrieve the four longs that were saved by the Archons in the last game. If there was no previous game in the match, or the Archons did not save anything, the longs default to 0.
There are several ways that the user can interact with robots. First, any robot can use setIndicatorString to set a string that is visible to the user when mousing over the robot. Second, the user can manually set a long for each robot, which the robot can query using getControlBits. Finally, a robot can call breakpoint(), which flags the game engine to pause computation at the end of the round. These methods are for debug purposes only. During tournaments and scrimmages, the user will not be able to interact with the robots. For more information on these debugging interfaces, check out Debugging below.
Only yield and suicide end the turn of a robot. Otherwise a turn ends naturally when the bytecode limit is hit. All other abilities either enqueue something to be performed at the end of the turn or can be performed as many times as the player likes. Thus, it is possible for a robot to transfer energon, broadcast 1 message, dispatch 1 action, and yield all within one round.
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 must implement java.lang.Runnable and have a public constructor that takes one argument, of type battlecode.common.RobotController. Whenever a new robot is created, your RobotPlayer class is instantiated by this constructor and passed the RobotController that controls the new robot. The game then 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.
The RobotController argument to the RobotPlayer constructor is very important -- this is how you will control your robot. RobotController has methods for sensing (e.g. senseLocationOf(Robot r)) and adding actions to the action queue (e.g., queueMoveForward()). If you're not sure how to get your robot to do something, the Javadocs for RobotController are a good place start.
Let's start with an example. Here is a simple implementation of RobotPlayer, that runs straight until it hits something, then turns right, then runs straight, etc.:
package team000;
import battlecode.common.*;
import static battlecode.common.GameConstants.*;
public class RobotPlayer implements Runnable {
private final RobotController myRC;
public RobotPlayer(RobotController rc) {
myRC = rc;
}
public void run() {
while(true){
try{
/*** beginning of main loop ***/
while(myRC.isActive()) {
myRC.yield();
}
if(myRC.canMove(myRC.getDirection())) {
myRC.queueMoveForward();
}
else {
myRC.queueSetDirection(myRC.getDirection().rotateRight());
}
myRC.yield();
/*** end of main loop ***/
}catch(Exception e) {
System.out.println("caught exception:");
e.printStackTrace();
}
}
}
}
Notice the while(true) loop, which prevents the run method from returning. While the robot is alive, it will be continually cycling through this loop. The try/catch block inside the loop prevents the robot from throwing an uncaught exception and dying. Also notice the while(myRC.isActive()) {myRC.yield();} loop. This loop effectively waits until the robot is IDLE. Once the robot knows it is IDLE, it checks whether it can move forward in its current direction -- if so, it adds a "move forward" to the action queue, otherwise it adds a "set direction" to its action queue.
The above team000 is included in the software release. Try compiling and running it to make sure the software works on your system.
Each robot is allowed a certain amount of computation each round. Computation is measured in terms of Java bytecodes, the atomic instructions of compiled Java code. Individual bytecodes are simple instructions such as "subtract" or "get field", and a single line of code generally contains several bytecodes. (For details see http://en.wikipedia.org/wiki/Java_bytecode.) Each round, every player runs a number of bytecodes determined by GameConstants.BYTECODES_PER_ROUND. When a robot hits the bytecode limit, its computation is paused while other robots get to do their computation in a round-robin fashion. On the next round, the robot's computation is resumed exactly where it left off. Thus, to the robot's code, the round change is invisible. Nothing will jump out and shout at you when a round ends.
Because the round can change at the end of any bytecode, unexpected things can happen. For instance, consider the following example:
Robot[] nearbyRobots = myRC.senseNearbyGroundRobots(); MapLocation loc = myRC.senseLocationOf(nearbyRobots[0]);
In the first line, the robot gets a list of all other robots in its sensor range. In the second line, the robot senses the location of the first robot in the list. However, what happens if the round changes between the first and second line? A robot that was in sensor range when line 1 was executed might be out of sensor range when line 2 is executed, resulting in an exception. Because of this, your code should be written defensively. Think of this as a "real-world" robot, where things can fail at any time, and you have to be prepared to handle it.
However, there are ways of dealing with this, as we'll see in the next section.
One way to deal with timing complexities is to use yield() judiciously. Calling RobotController.yield() ends the robot's computation for the current round. This has two advantages.
First, robots receive a slight energon bonus for yielding computation. The bonus is given by GameConstants.ENERGON_BONUS_PER_BYTECODE * (# of unused bytecodes in the round).
Second, after a call to RobotController.yield(), subsequent code is executed at the beginning of a new round. Then, you have the full amount of bytecodes for your robot to do computations before the round changes. For instance, let's modify the example above to be:
myRC.yield(); Robot[] nearbyRobots = myRC.senseNearbyGroundRobots(); MapLocation loc = myRC.senseLocationOf(nearbyRobots[0]);
Since yield is called in line 1, line 2 will be executed at the beginning of a new round. Since senseNearbyGroundRobots does not take very many bytecodes, it is pretty much guaranteed that there won't be a round change between lines 2 and 3.
A common paradigm is to have a main loop, with a yield() at the bottom of the loop. Thus, the top of the loop is always executed at the beginning of the round. If all the robot's computation for one iteration of the loop can fit in one round, then there should be minimal problems with unexpected round changes. Note that team000 above does this.
The Clock class provides a way to identify the current round ( Clock.getRoundNum() ), and how many bytecodes have been executed during the current round ( Clock.getBytecodeNum() ).
GameActionExceptions are thrown whenever an ability cannot be performed. This is sometimes the result of attempting to perform an operation that does not make sense (like trying to attack ground with a Scout). However, it is often the result of uncertainty about the gameworld, or an unexpected round change in your code. Thus, you must write your player defensively and handle GameActionExceptions judiciously. Each GameActionException has a GameActionExceptionType, which tells roughly what went wrong. It is sometimes worthwhile to try to address and recover from the different kinds of GameActionExceptions by switching on their GameActionExceptionTypes. But you should also be prepared for any ability to fail and 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.
Most methods explicitly throw GameActionExceptions (e.g., senseLocationOf). However, because actions in the action queue are executed asynchronously, their GameActionExceptions are handled differently. When an action results in a GameActionException (e.g., a robot tries to move into an occupied square), the GameActionException is not thrown. Instead, the robot's action queue is cleared, and the exception is saved. Your robot should poll for saved GameActionExceptions periodically by calling RobotController.getLastActionException(), which returns the last GameActionException from an action.
This section deals with some of the mechanics of how your players are run in the game engine, including bytecode-counting, library restrictions, etc.
Players may use classes from any of the following packages (not including subpackages):
java.io java.lang java.math java.util battlecode.common
EXCEPT for the following classes:
java.io.File java.io.FileDescriptor java.io.FileInputStream java.io.FileOutputStream java.io.FilePermission java.io.FileReader java.io.FileWriter java.io.RandomAccessFile java.io.SerializablePermission java.lang.Class java.lang.ClassLoader java.lang.Compiler java.lang.InheritableThreadLocal java.lang.Package java.lang.Process java.lang.ProcessBuilder java.lang.Runtime java.lang.RuntimePermission java.lang.SecurityManager java.lang.Thread 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.FormattableFlags java.util.Formatter java.util.GregorianCalendar java.util.ListResourceBundle java.util.Locale java.util.MissingResourceException java.util.Properties java.util.PropertyPermission java.util.PropertyResourceBundle java.util.ResourceBundle java.util.SimpleTimeZone java.util.TimeZone java.util.Timer java.util.TimerTask java.util.UUID java.util.WeakHashMap
Furthermore, the following restrictions apply:
Note that violating any of the above restrictions will cause the robots to self-destruct when run, even if the source files compile without problems.
Robots must keep their memory usage reasonable. If a robot uses more than 8 Mb bytes of heap space during a tournament or scrimmage match, the robot may be killed.
If a robot's stack depth exceeds GameConstants.STACK_SIZE_LIMIT, the game engine will consider it a stack overflow, and will kill the robot.
Throwing exceptions of any kind incurs a bytecode penalty given by GameConstants.EXCEPTION_BYTECODE_PENALTY, so unnecessary throwing of exceptions should be avoided.
This section describes some of the features of the game engine intended to make debugging somewhat less painful. Debug mode reveals valuable information about robots at development time but will be turned off for scrimmages and real tournaments.
Any output that your robots print to System.out is directed to the output stream of the BattleCode engine, prefixed with information about the robot.
The game engine 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 debugMethodsEnabled is set to true, however, the methods are executed normally except that they do not count against your robot's bytecode limit. 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.
Breakpoints allow you to pause the game engine's calculations. If breakpoints are enabled (see the software page), and a robot calls RobotController.breakpoint(), the game engine will stop computing at the end of the round. This gives you a chance to see exactly what's going on in the game when your robot hits a certain point in its code. You can resume the game engine's computation in the client, by hitting the "resume" button. If the match is being dumped straight to a file (i.e., there is no client to resume the game), breakpoints are ignored.
Note that when a robot calls breakpoint(), computation will be stopped at the end of the round, not immediately when breakpoint() is called. Depending on the circumstances, you might want to use breakpoint(); yield(); instead.
There are three important tournaments: the Seeding, Qualifying, and Final tournaments. Check the Calendar page for dates and locations. Here, we'll explain the mechanics of how the tournaments are run.
The Seeding Tournament is a single elimination tournament. Contestants are randomly seeded, and play continues until there is only one undefeated team. Teams are ranked by the following criteria, in order:
The Qualifying Tournament is a double elimination tournament (see e.g. http://en.wikipedia.org/wiki/Image:NSB-doubleelim-draw-2004.png). Contestants are seeded by their place in the Seeding Tournament. If a team did not have a submission for the Seeding Tournament, they are seeded last. Play continues until there are 8 teams remaining. These teams move on to the Final Tournament.
The Final Tournament is another double elimination tournament. Contestants are seeded by their performance in the Qualifying Tournament. The Final Tournament starts with a blank state, i.e., any losses in the Qualifying Tournament are erased.
To determine credit, we will take your team's final submission and have it play one match against the reference player. We will specify which maps the match will be played on a couple days before the submission deadline. Because you can run these matches yourself, so you should know in advance of the submission whether your player will beat the reference player. If your player beats the reference player, everyone on your team receives 6 credits and 6 EDPs.
If your submission does not beat the reference player, we will email you soon after the submission deadline. At this point, you can get credit an alternate way, by sending us a 2-page report on your player: its code design, how it works, an explanation of any AI paradigms you used, etc. We will look over your source code and your report, and if both show a significant amount of effort, thought, and good design techniques, we will give you 6 credits and 6 EDPs.
Also, note that you are allowed to drop 6.370 without penalty very late into IAP.
Javadocs can be found here, and they are also included in the software distribution.
This table is a synopsis of the battlecode.common.RobotType enum.
| Property | SOLDIER | TANK | SCOUT | ARCHON | EMP | SAM |
|---|---|---|---|---|---|---|
| General | ||||||
| double startEnergon | 5.0 | 5.0 | 5.0 | 1.0 | 5.0 | 5.0 |
| double maxEnergon | 30.0 | 50.0 | 15.0 | 60.0 | 50.0 | 50.0 |
| double spawnCost | 20.0 | 10.0 | 20.0 | 0.0 | 10.0 | 10.0 |
| int spawnDelay | 1 | 1 | 1 | 1 | 1 | 1 |
| int wakeDelay | 50 | 25 | 50 | 50 | 50 | 25 |
| int broadcastRadius | 8 | 8 | 8 | 8 | 8 | 8 |
| boolean isAirborne | false | false | true | false | true | false |
| double energonUpkeep | 0.2 | 0.5 | 0.1 | 0.0 | 0.6 | 0.5 |
| Movement | ||||||
| int moveDelayOrthogonal | 5 | 7 | 5 | 10 | 7 | 7 |
| int moveDelayDiagonal | $((int)Math.round((double)moveDelayOrthogonal*Math.sqrt(2.0))) | |||||
| Sensor | ||||||
| int sensorRadius | 3 | 3 | 5 | 6 | 4 | 3 |
| double sensorAngle | 180.0 | 90.0 | 360.0 | 360.0 | 360.0 | 180.0 |
| Attack | ||||||
| double attackAngle | 90.0 | 45.0 | 90.0 | 0.0 | 90.0 | 90.0 |
| int attackRadiusMinSquared | 1 | 9 | 1 | 0 | 1 | 0 |
| int attackRadiusMaxSquared | 2 | 25 | 2 | 0 | 2 | 16 |
| boolean canAttackAir | false | false | true | false | true | true |
| boolean canAttackGround | true | true | false | false | false | false |
| int attackDelay | 5 | 7 | 5 | 0 | 5 | 7 |
| double attackPower | 6 | 9 | 1 | 0 | 5 | 7 |
| Other | ||||||
| double sensorCosHalfTheta | $(Math.cos((sensorAngle/2.0)*Math.PI/180.0)) | |||||
| double attackCosHalfTheta | $(Math.cos((attackAngle/2.0)*Math.PI/180.0)) | |||||
The constants listed here are fields of battlecode.common.GameConstants.
| BROADCAST_FIXED_COST | 0.01 | Fixed cost to send a message |
| BROADCAST_COST_PER_BYTE | 0.0001 | Additional cost per byte of message size |
| MAP_MIN_HEIGHT | 25 | The minimum possible map height. |
| MAP_MAX_HEIGHT | 40 | The maximum possible map height. |
| MAP_MIN_WIDTH | 25 | The minimum possible map width. |
| MAP_MAX_WIDTH | 40 | The maximum possible map width. |
| BYTECODE_ENERGON_BONUS | 0.000008 | Amount of energon you get per unused bytecode for ending the round early |
| EXCEPTION_BYTECODE_PENALTY | 500 | The bytecode penalty that is imposed each time an exception is thrown |
| ARCHON_FULL_PRODUCTION | 1.0 | The amount of energon per round a full archon without upgrades (e.g., one of the starting archons) produces |
| EMP_RADIUS | 5 | The range in which an archon will be hit by an EMP blast |
| TANK_DELAY_ROUNDS | 5 | Number of rounds between when a tank attacks and when its shell impacts |
| TANK_FALLOUT_FRACTION | 0.4 | Fraction of tank damage neighboring squares receive when its shell explodes. |
| NUMBER_OF_INDICATOR_STRINGS | 3 | The number of indicator strings that a player can associate with a robot |
| BYTECODES_PER_ROUND | 6000 | The number of bytecodes a robot can execute each round |
| STACK_SIZE_LIMIT | 64 | The maximum stack size a robot can use without incurring penalties |
| ACTION_QUEUE_LENGTH | 8 | The maximum number of actions that can be scheduled in a robot's action queue |
| BROADCAST_QUEUE_LENGTH | 8 | The maximum number of messages that can be scheduled in a robot's broadcast queue |
| ENERGON_TRANSFER_RATE | 2.0 | The amount of energon a robot can receive per round from transfers |
In the following diagrams, blue squares indicate locations in the robot's sensor range, red ones indicate locations in the robot's attack range, and purple ones are for those locations in both the sensor and attack ranges of the robot.
January 17, 2007
January 15, 2007
January 12, 2007
January 10, 2007
default.xml map (from 2006) in 4.4