Programming Java Robots

Robot Concepts

    To create a JRobot, you must be familiar with programming in the Java™ programming language. Robots are created as Java class files which are created with a Java compiler. Extensive knowledge is not required. A programmer only needs to now basic scalar types and how to call the JRobot functions.

    A custom JRobot is created as an extension to the abstract JRobot class. This class provides the robot with its basic capabilities through methods that permit interaction with the world and fair management of robots. An extension to the JRobot class can scan, move, and fire; it can query its position, speed, direction, total damage, ID number, and game time. The class also has shortcut functions for some of the geometric and mathematic operations needed to compute target positions and bearings.

    A JRobot program first gains control when its constructor is called. The robot can do any necessary intialization at this point. The robot then begins playing the game when its main() method is called. The robot program can begin thinking, scanning, moving, and firing to compete in the game. The Robot runs in its own thread, which is managed by the JRobots game. Each Robot is given fair CPU time, and the robot thread will not end until the robot has died.

    The robot program interacts with the game with methods declared in the JRobot class. The JRobots class allows the robot program access only to the methods needed to play the game. The robot is not given the "ominiscient" information of the viewer such as coordinates of other robots, projectiles, explosions, etc. The threads are managed by the game so that no thread may steal CPU time or lock up the game (although it is possible). JRobot threads are given restrictions on what they can and cannot do during the game. Robots attempting to violate the rules will be terminated.


JRobot Class

    The JRobots class provides three types of methods for the JRobot:

JRobots class definition
//
// JRobot:
//   * Base class for all user-defined robots
//   * Stores basic robot information
//   * Provides basic robot functionality, some conveniences
//
public abstract class JRobot {
/********
 Robot Constants:
 ********/

  public static double ROBOTSPEED;
  public static int    ROBOTSIZE;
  public static float  ACCELERATION;
  public static float  DECELERATION;
  public static double TURNRATE;
  public static int    MAXLIFE;
  public static int    MAXTURNSPEED;
  public static int    MAXCANNONDIST;

/********
 Robot Accessors -- Get information about robot state
 ********/

  //
  //   Allow the robot access to information about itself and the game world
  //
  public final float   getX();            // Return robot X,Y coordinates
  public final float   getY();
  public final int     getLife();         // Return amount of life (0-MAXLIFE)
  public final boolean isAlive();         // Return false if dead :)
  public final int     getNumber();       // Return robot number
  public final double  getSetRadians()    // Return direction setting in radians
  public final int     getSetDegrees()    // Return direction setting in degrees
  public final double  getRadians();      // Return actual direction in radians
  public final int     getDegrees();      // Return actual direction in degress
  public final int     getSetSpeed();     // Return speed setting
  public final int     getSpeed();        // Return actual speed
  public final long    getFrame();        // Return current frame number
  public final int     getTeam()          // Return team number

  // Compatibility with crobots
  public final int     loc_x();
  public final int     loc_y();
  public final int     damage();


/********
 Robot Tools - Convenient functions for the robot
 ********/

  //
  // Compute angle or distance from self to another point
  //
  public final double  radiansTo(float x2, float y2);
  public final int     degreesTo(float x2, float y2);
  public final float   distanceTo(float x2, float y2);

  //
  // Compute angle or distance from point to point
  //
  public static final double radiansTo (float x1,float y1, float x2,float y2);
  public static final int    degreesTo (float x1,float y1, float x2,float y2);
  public static final float  distanceTo(float x1,float y1, float x2,float y2);

  //
  // Convenient random numbers
  //
  public static final int rand(int max);

  //
  // Normalize an angle in radians - fit to 0 - 2pi
  //
  public static final double normalize(double rad);


  //
  // Yield remaining robot timeslice
  //
  protected final void Yield();

/********
 Robot Interface - Methods to interact with the JRobots world
 ********/

  //
  // Log a public debug message
  //
  protected final void addMessage(String s);

  //
  // Suicide - kill self, cause a large explosion
  //
  protected final void suicide();

  //
  // Scan for a robot - direction/granularity
  //   Granularity is + or - the specifed direction, no more than 10 degrees
  //   Does not necessarily return the CLOSEST one...
  //
  protected final float scan(double rad, double spread);       // Radians
  protected final float scan(int deg,    int    spread);       // Degrees

  //
  // Fire - direction and distance to explode
  //
  protected final boolean cannon(double rad, int dist);        // Radians
  protected final boolean cannon(int deg,    int dist);        // Degrees

  //
  // Move - specifed direction, speed (0%-100%)
  //
  protected final void drive(double moveAngle, int moveSpeed); // Radians
  protected final void drive(int moveAngle,    int moveSpeed); // Degrees

/********
 Robot Main
 ********/

  //
  // The robot main function - Robots override this to perform their function
  //
  protected abstract void main();
}

    The first group of methods return direct values stored for each robot. Every robot has position, direction, speed, and life. Angles can be returned in degrees(integer values) or radians(floating point). Note that direction and speed have two versions. When a robot calls the drive(...) method it begins to accelerate and turn. It does not arrive at the requested speed or direction instantly. Thus, you can query the robots actual speed and direction, taking into effect acceleration and turn rates, or the speed and direction that it is intending to go. Robots do not respond instantly.

    The game runs in frames. Periodically, the robot programs will be preempted and virtual time will proceed. Robot positions will be updated, the display is updated, etc. To inform the robot of how much time has passed, a frame counter is implemented. The getFrame() method will return the frame number. The robot can compute the elapsed time in seconds as (float)getFrame()/getFPS(). Note that in FAST mode time runs as quickly as possible, and a 5 minute game may only take seconds to play.

    Some accessors return general game and robot information, which is static for the duration of the match (and probably beyond, although the program would be unwise to assume so). These method return values such as playfield size, game FPS, and robot capabilities. It is valid to hard code the size of the playfield into the program, but these values may change for future game types.

    The robot tools are useful for creating robots that intelligently manupulate the information given to them. It is possible to "pull lead" on a moving target by using scan results along with the radiansTo(...) or degreesTo(...) methods. These can also be used to move to specific locations on the board, such as the center, corners, or edges.

    rand(...) simply returns a random number. Yield(...) gives up the robots timeslice if it is idle. This does NOT affect the time given to other robots, it simply allows the program to run more efficiently.

    To interface with the world, the JRobot has methods that act or get input from the world. These are primarily scan(...), cannon(...), drive(...). Additionally there is suicide() and addMessage(...).

    scan(angle,spread) will send out a virtual beam at the specified direction and spread. The beam will reflect off of objects in the playfield and return the distance to a robot, or 0 if none is found. The spread is the width of the beam, effectively the number of degrees around the specified line that will still return a result. A wider beam results in a larger scan area, allowing a faster scan of a large area, but a less accurate one. A thinner beam results in a more accurate scan, but may take longer and miss quickly moving objects. A spread of 0 will almost never return a result, and spread may not exceed 10 degrees.

    cannon(angle,distance) will fire a shell at the specified angle, set to explode at distance. The shell will explode before this distance if it hits a wall. The distance will be clipped to the getMaxCannonDist() value(currently 700 units). Since a robot has a limited refire rate, the cannon(...) method returns true if the shot was actually fired, and false otherwise. The resulting explosion can damage multiple robots, including the robot that fired the shot. Robot can set shells to detonate at a distance of 0.

    drive(angle,speed) will begin moving at the specified angle and speed. Speed ranges from 0% to 100%. Note that robots can only turn when they are travelling at getMaxTurnSpeed() or slower. Robots must turn and accelerate to reach the desired end. A robot can query the acceleration, deceleration, and turn rates. The access methods described above allow for querying the intended speed and angle as well as the current speed and angle.

    A robot can call the suicide() method to kill itself dramatically.

    addMessage(messageString) can be used to send a public message. This will be displayed in the robot's status area unless in anonymous mode. These messages can also be used for debugging robot programs.

    The method main() is the entry point for a JRobot program. This body may call any JRobots functions, and nearly any Java functions. The JRobot MUST NOT create another thread. This could cause deadlocks in the game system as well as unfairly distribute CPU time. Attempting to do so would be cheating.

Robot example

    Several example robots are included with the JRobots distribution. The simplest is the Rabbit class shown below. The Rabbit class extends the JRobots class and provides a main() method. This method simply runs around the playfield at random using the JRobots accessor and tool functions.

    Other more comprehensive examples are available in the JRobots distribution. These examples use the scan(...) and cannon(...) functions.

Rabbit.java example robot
/* rabbit */
/* rabbit runs around the field, randomly */
/* and never fires;  use as a target */

// Converted from crobots 03/21/99 WHG

import java.util.Random;
import java.awt.Graphics;
import java.awt.Color;

public class Rabbit extends JRobot {
  public void main() {
    while (true)
      go(rand(1000),rand(1000));
  }

  void go(int dest_x, int dest_y) {
    int course;

    course = degreesTo(dest_x,dest_y);
    drive(course,75);

    while(distanceTo(getX(),getY(),dest_x,dest_y) > 50)
      ;

    drive(course,0);
    while (getSpeed() > 0)
      ;
  }
}

Copyright ©1999 William Garrison
® Java is a registered trademark of Sun Microsystems