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.
Picture |
Robot Type |
Description |
|
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. Finally,
moving robots have damage dealt to them decreased by a factor
of GameConstants.MOVING_DAMAGE_REDUCTION
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.
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.
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
Property |
Sentry |
Tank |
Falcon |
Bomber |
General |
bytecodesPerRound |
2250 |
2500 |
2250 |
2500 |
startEnergon |
1.0 |
1.0 |
1.0 |
1.0 |
fullEnergon |
65.0 |
80.0 |
35.0 |
80.0 |
maxEnergon |
130.0 |
160.0 |
70.0 |
160.0 |
spawnCost |
25.0 |
50.0 |
30.0 |
50.0 |
spawnDelay |
50 |
100 |
50 |
100 |
wakeDelay |
50 |
100 |
50 |
100 |
broadcastRadius |
4 |
4 |
4 |
4 |
isAirborne |
false |
false |
true |
true |
canLayMine |
true |
false |
false |
false |
mineDelay |
10 |
10 |
10 |
10 |
canCarryFlag |
(! isAirborne) |
Movement |
moveDelayOrthogonal |
20 |
25 |
15 |
20 |
moveDelayDiagonal |
((int)Math.round((double)moveDelayOrthogonal*Math.sqrt(2.0))) |
Sensor |
sensorRadius |
2 |
3 |
3 |
4 |
sensorAngle |
180.0 |
90.0 |
180.0 |
360.0 |
Attack |
attackAngle |
0.0 |
45.0 |
0.0 |
0.0 |
attackRadiusMin |
0 |
2 |
0 |
0 |
attackRadiusMax |
1 |
5 |
1 |
0 |
canAttackAir |
false |
true |
true |
false |
canAttackGround |
true |
false |
false |
true |
attackDelay |
15 |
25 |
15 |
25 |
attackPower |
20 |
20 |
10 |
50 |
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 |
20 |
TEAM_TOTAL_LIMIT |
Max number of robots each team can have total at a given time |
28 |
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 |
6.0 |
FALLOUT_FRACTION |
Fraction of mine damage neighboring squares receive when mine explodes |
0.1 |
MOVING_DAMAGE_REDUCTION |
When moving, damage dealt is equal to (power of attacker) * (1 - MOVING_DAMAGE_REDUCTION) |
(1.0/3.0) |
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
|