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 BattleCode world, and how to write your player.
Our story begins at the University of Evil in the ancient lost city of Evil. The University of Evil has the world's great program in Evil Studies and hosts the largest recruitement center for evil henchmen. At the University of Evil is the lair of tenured Prof. Soren Mordemort. As part of Prof. Mordemort's research on World Domination for the purposes of evil, he has noted the obvious strategic importance of one seemingly unimportant planet (or not a planet), Pluto. Prof. Mordemort will use this world to control all passage from our solar system to the rest of the galaxy and vice versa. Using his evil towers he has has created on Pluto as beacons, Prof. Mordemort plans to summon an evil extraterrestrial race with advanced degrees in Evil Studies to enslave the Earth for him.
Meanwhile, on Earth, we come to a group of 1-4 unknown people. This group of 1-4 has never been extraordinary. This group of 1-4 people has spent their life tooling, churning out large volumes of code and drinking vast pools of caffeine. They were ridiculed for those days they slept in their lab, those funny online comics they read and their sleepless nights spent writing documentation. However, all this was to change.
As soon as the world knew what Dr. Mordemort was up to, prizes were created for whoever could stop him. So, it was declared that the remaining heroes that captured the most of his evil towers would be rewarded. You are the group of 1-4 people. You have decided to stop the evil professor! YOU are the ones who will save the world!
Since humans cannot stand the hardships associated with travelling to Pluto, you have decided to send an army of robots. These robots will run on the mysterious resource, energon. Energon is a recently discovered power source and its full properties are still a mystery. You send a shuttle with 8 archon robots that captures a tower on landing. Archons can produce energon and can assemble combat robots from resources near towers. These combat robots can transform into any other robots that traverse the same medium (land or air).
The land is yours to conquer. Good luck! The winners will gain eternal glory!
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 and air units at close range. Spawned by Archons. |
![]() |
Scout | A fast and lightweight air unit that attacks other air units at close range. Spawned by Archons. |
![]() |
Sniper | A poweful range unit that attacks ground units at long range. Evolves from a Soldier. |
![]() |
Mortar | A seige unit designed to take down towers with a powerful but delayed attack. Evolves from a Soldier. |
![]() |
Bomber | An air unit with a powerful ground attack. Evolves from a Scout. |
This year there is an additional neutral tower unit not controller by either player. Towers however may be captured to fight on your side.
![]() |
![]() |
Tower | A fortified neutral unit which initially attacks either team but may be captured to fight on your side. |
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, attacking, message broadcasts) take effect immediately at the end of a robot's turn, 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 energon upkeep, energon recovery, 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.
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 a certain number of 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.
Robots have an explicit energon reserve to receive energon transfers. Any energon transfers are first placed in a robot's energon reserve. At then end of every round up to GameConstants.ENERGON_TRANSFER_RATE is automatically transferred from a robot's energon reserve to its main energon level. Robots can hold up to GameConstants.ENERGON_RESERVE_SIZE energon in their reserves in addition to their main energon level.
However, if a robot's main energon level is brought below 0 even after the automatic energon transfer then a robot is considered dead regardless of how much extra energon it has in reserve.
The theme of this year's BattleCode game is territory warfare. The goal is to have the greatest number of points by the end of a game by controlling more towers or stronger towers than the opponent. A game ends either when a team loses all of its robots (excluding towers) or when the round number is reached. When this occurs the winning condition is determined by the following criteria, in order:
Towers are neutral units which can be captured by depleting their energon. They initially attack either team but once a tower is captured it will only attack the other team. In either case towers fight in a fixed fashion:
Towers start out being worth GameConstants.TOWER_START_POINTS. Each team starts out with one initial Tower. See appendix B for detailed Tower specifications.
To emphasize the territory warfare aspect of this year's competition only Archons can spawn and can only do so within the spawn radius of an owned tower. The spawn radius of a tower is initially given by GameConstants.INITIAL_SPAWN_RADIUS. Thus towers not only give teams points but also act as bases to regroup and rebuild. Claiming towers helps increase a team's area of influence.
A tower is captured when its energon level is brought to 0. For neutral towers, the team that did the most damage on that final round claims the tower. If both teams did equal damage to the tower then the last team to hit claims it. For owned towers, the tower is transferred to the other team. In either case, the points and spawn radius associated with the tower are now owned by the receiving team.
However, every time a Tower is captured it becomes a bit weaker. Its max energon level, energon production, points, and spawn radius are all scaled down linearly by GameConstants.TOWER_DECAY_FACTOR. This makes the tower easier to retake but also worth less. Thus a heavily contested tower starts losing value and approaches diminishing returns. At that point, it may be better use of a player's time going after other towers. On the other hand, weak towers present easy captures which could become cheap staging areas.
Finally, Towers have a brief waking delay when captured. Towers immediately change teams, transfers their points and spawn radius, and have their stats reduced, but is engaged in waking for 10 rounds where the Tower cannot attack, take damage, or be recaptured. This is to prevent friendly Mortar fire from capturing and then immediately destroying the captured Tower. The method senseRoundsToTowerWake(Robot) can be used to sense if a Tower is currently waking.
On capture the following things take place:
BattleCode maps consist of a grid of squares, each with a pair of integer coordinates. Locations on the map are represented as instances of MapLocation objects. 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. In addition, each square has a terrain height representing the difficulty of traversing that square. Heigher squares incur extra movement delay but reward robots with a slight attack bonus.
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.
Instead of being mostly filled with impassable rivers, the main navigation obstacles this year are terrain heights. There are 5 discrete levels of terrain height. Higher levels are harder to navigate. Ground robots stepping on these squares incur an extra height * GameConstants.MOVEMENT_PENALTY_RATE * movementDelay to their movement delay. However, higher ground robots get a slight attack bonus to help compensate. When a ground robot attacks another ground robot the attack gets a slight (attackerHeight - targetHeight) * GameConstants.ATTACK_BONUS_RATE multiplier to its damage.
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.
Matches this year are all best of 3 games. In each game both players start with 8 Archons and end when a team's robots 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 as 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. On its turn a robot may perform these abilities:
A robot may perform 1 action per turn. Furthermore, each robot has a movement and attack cooldown. When getRoundsUntilAttackIdle() is 0, the robot may issue attack commands. When getRoundsUntilMovmentIdle is 0, the robot may issue movment commands.
Actions are performed at the end of a robot's turn. Calling the associated method like attackGround() or moveForward() simply queues that action to be performed at the end of its turn. A robot may continue executing and when ready call yield() to end its turn and perform the action. Or if the robot runs out of bytecodes the action will automatically be performed. This allows actions to be executed at the end of a robot's turn without explicit bytecode counting.
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 its roundsUntilMovementIdle is set to the appropriate movement delay. The robot would need to wait for the movement cooldown before being able to move again.
The following are the possible actions that a robot can execute.
All attack actions require getRoundsUntilAttackIdle() to be 0.
Attacking - attackGround(MapLocation) and attackAir(MapLocation) 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(). Attacks damage the target robot immediately. Then roundsUntilAttackIdle is set to RobotType.attackDelay().
Mortars are seige units so they receive a GameConstants.MORTAR_MULTIPLIER when attacking towers. However, mortars have incendiary shells which spreads its attack over several rounds. Instead of doing attackPower damage immediately, it does attackPower/attackDelay damage for the next attackDelay rounds to that square. Any ground robot on that square receives that damage but can move away to stop taking damage. There is no longer an attack delay but if a mortar dies then its attack stops.
All movement actions require getRoundsUntilMovementIdle() to be 0.
Direction - Each robot has a direction, as enumerated by Direction. Calling setDirection(Direction) changes the robot's direction. This action has a duration of 1 round.
Movement - moveForward() and moveBackward() makes 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 TerrainTile 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. Then roundsUntilMovementIdle is set to RobotType.moveDelayOrthogonal() or RobotType.moveDelayDiagonal(); note that moving diagonally takes approximately sqrt(2) times longer than moving orthogonally.
Spawning and evolving can be performed even if getRoundsUntilMovementIdle() and getRoundsUntilAttackIdle() are nonzero.
Spawning - Archons may spawn Soldiers and Scouts using spawn(RobotType). 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.
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. Both roundsUntilAttackIdle and roundsUntilMovementIdle of the child robot are set to RobotType.wakeDelay().
The Archon also must be within the spawn radius of a Tower owned by its team.
Evolving - Calling evolve(RobotType) allows a robot to change into a different RobotType. Once a robot executes an evolution, the robot immediately becomes a robot of the new type. Then both roundsUntilAttackIdle and roundsUntilMovementIdle are set to RobotType.wakeDelay() of the new (evolved) robot.
Any robot except Archons and Towers can evolve. Air units can evolve into other air units. Ground units can evolve into other ground units except Archons and Towers. Evolving costs a fixed cost of GameConstants.EVOLVE_COST. If evolution results in the robot's maxEnergon being lower than its energonLevel then the excess goes into its reserve. If its reserve overflows then the rest is lost.
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 senseTerrainTile. Robots automatically remember all terrain they've seen, so senseTerrainTile 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 may broadcast 1 message per turn. This is the only way to communicate with other robots. 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 calls broadcast(Message), 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.
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(MapLocation, RobotInfo), which removes a specified amount of energon from the calling robot and adds it to the energon reserve of the receiving robot. The receiving robot must be adjacent to or on same square as the transferring robot. Then at the end of the round GameConstants.ENERGON_TRANSFER_RATE is transferred from the receiving robot's energon reserve to its main energon level. The rest is left in its reserve until the next round.
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.
Archons have the special ability to remember some limited state between different games of a match. Each Archon can use setArchonMemory(long) 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 8 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. senseRobotInfo(Robot)) and performing actions (e.g., moveForward()). 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.isMovementActive()) {
myRC.yield();
}
if(myRC.canMove(myRC.getDirection())) {
myRC.moveForward();
}
else {
myRC.setDirection(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.isMovementActive()) {myRC.yield();} loop. This loop waits until the robot is movement idle. Once the robot knows it is idle, it checks whether it can move forward in its current direction -- if so, it tries to move forward. Otherwise it tries to turn right.
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.senseRobotInfo(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 RobotInfo 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.YIELD_BONUS * energonUpkeep * (fraction 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.senseRobotInfo(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.
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. 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 against the reference player. We will specify which maps the match will be played before the submission deadline. Since you can play the refplayer on the scrimmage server, you should be able to verify that your player can beat the refplayer. 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 | MORTAR | SCOUT | ARCHON | BOMBER | SNIPER | TOWER |
|---|---|---|---|---|---|---|---|
| General | |||||||
| double startEnergon | 5.0 | 5.0 | 5.0 | 1.0 | 5.0 | 5.0 | 150.0 |
| double maxEnergon | 20.0 | 40.0 | 10.0 | 50.0 | 40.0 | 40.0 | 150.0 |
| double spawnCost | 20.0 | 5.0 | 20.0 | 0.0 | 5.0 | 5.0 | 0.0 |
| int spawnDelay | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| int wakeDelay | 50 | 50 | 50 | 50 | 50 | 50 | 10 |
| int broadcastRadius | 8 | 8 | 8 | 8 | 8 | 8 | 8 |
| boolean isAirborne | false | false | true | false | true | false | false |
| double energonUpkeep | 0.2 | 0.4 | 0.1 | 0.0 | 0.4 | 0.4 | 0.0 |
| Movement | |||||||
| int moveDelayOrthogonal | 5 | 7 | 5 | 6 | 11 | 7 | 1 |
| int moveDelayDiagonal | $((int)Math.round((double)moveDelayOrthogonal*Math.sqrt(2.0))) | ||||||
| Sensor | |||||||
| int sensorRadius | 3 | 3 | 5 | 6 | 4 | 4 | 5 |
| double sensorAngle | 180.0 | 90.0 | 360.0 | 360.0 | 360.0 | 90.0 | 360.0 |
| Attack | |||||||
| double attackAngle | 90.0 | 45.0 | 90.0 | 0.0 | 180.0 | 45.0 | 360.0 |
| int attackRadiusMinSquared | 0 | 9 | 0 | 0 | 0 | 0 | 0 |
| int attackRadiusMaxSquared | 9 | 25 | 2 | 0 | 9 | 25 | 25 |
| boolean canAttackAir | true | false | true | false | false | false | true |
| boolean canAttackGround | true | true | false | false | true | true | true |
| int attackDelay | 5 | 10 | 5 | 0 | 5 | 5 | 2 |
| double attackPower | 7 | 10 | 1 | 0 | 10 | 10 | 2.1 |
| 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 | 50 | The maximum possible map height. |
| MAP_MIN_WIDTH | 25 | The minimum possible map width. |
| MAP_MAX_WIDTH | 50 | The maximum possible map width. |
| YIELD_BONUS | 0.1 | Percentage of upkeep returned 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_PRODUCTION | 1.0 | The amount of energon per round an archon produces |
| INITIAL_SPAWN_RADIUS | 10.0 | The spawn radius that a tower begins with |
| MIN_SPAWN_RADIUS | 2.0 | The minimum spawn radius that a tower can have |
| TOWER_START_PRODUCTION | 1.0 | The amount of energon production per round a tower starts with |
| TOWER_START_POINTS | 1500.0 | The amount of points a tower is initially worth |
| TOWER_DECAY_FACTOR | 2.0/3.0 | The factor by which towers decay when killed |
| MORTAR_MULTIPLIER | 4.0 | Damage multiplier for mortars when attacking towers |
| 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 |
| ENERGON_TRANSFER_RATE | 1.0 | The amount of energon a robot can receive per round from transfers |
| ATTACK_BONUS_RATE | 0.05 | The fractional attack bonus per unit height difference |
| MOVEMENT_PENALTY_RATE | 0.3 | The fractional movement penalty based on terrain height |
| EVOLVE_COST | 5.0 | Cost of evolving robot |
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.
Energon intake is not for everyone. Please consult a physician before use. 6.370 BattleCode Corporation is not responsible in the event of injury due to energon use. Energon's side-effects include loss of limb, death, unbearable pain, tendencies to procrastinate and an unnatural senseless rage. Handle with care. Energon consumption has not been approved by any health agency and you USE IT AT YOUR OWN RISK. For this reason, please be careful when scrimmaging.
January 21, 2008
January 17, 2008
January 15, 2008
January 13, 2008
January 12, 2008
January 11, 2008
January 10, 2008
January 9, 2008
January 8, 2008
January 7, 2008