Coding your robots is very easy and should be natural if you've ever had any Javascript experience. Let's see an example of a very simple robot:
function Robot(robot) {} // well, we need to do something... // whenever our robot is idle, this method gets called. Robot.prototype.onIdle = function(ev) { var robot; robot = ev.robot; robot.ahead(150); robot.rotateCannon(360); robot.back(100); robot.rotateCannon(360); robot.turn(20); }; // this method gets called whenever we hit another robot... Robot.prototype.onRobotCollision = function(ev) {}; // this method gets called whenever we hit a wall... Robot.prototype.onWallCollision = function(ev) {}; // yay we see another robot! time to wreak some havoc... Robot.prototype.onScannedRobot = function(ev) { var robot; robot = ev.robot; robot.fire(1); }; // ohhh... we were hit by another robot... Robot.prototype.onHitByBullet = function(ev) { var robot; robot = ev.robot; robot.turn(90 - ev.bulletBearing); };
There's a bunch of methods in there that you probably don't quite understand yet, but we'll see more about them in a minute.
Your robot is just a plain old Javascript constructor function. fightcode will use your constructor function to create the instance that will fight against other robots.
This is the simplest possible robot you can build (it doesn't do much, though):
The onIdle function is your robot game loop. fightcode will call it every time your robot runs out of actions to do.
You can use it to run, turn, shoot or anything your robot can do. We can implement it with:
function Robot() {} Robot.prototype.onIdle = function(ev) { var robot = ev.robot; robot.turn(90); // keep turning 90 degrees when idle };
onIdle is a function that takes one argument called ev. The structure of ev is this:
{ robot: { // INFORMATION ON THE CURRENT GAME id, // Id from your robot angle, // Current angle from your robot in degrees cannonRelativeAngle, // Current angle from your cannon // relative to your robot cannonAbsoluteAngle, // Current angle from your cannon // relative to the board position: { x, // X position in the board from your robot y // Y position in the board from your robot }, life, // Percentage of the life from your robot gunCoolDownTime, // Time remaining in the cooldown from your // cannon after shooting availableClones, // Number of available clones you can use availableDisappears, // Number of available disappears you can use parentId, // In the case of being a clone, the id // from your parent element. null otherwise arenaWidth, // Width from the board arenaHeight // Height from the board // AVAILABLE ACTIONS // Moves the given amount ahead ahead: function(amount), // Moves the given amount backwards back: function(amount), // Moves ahead if direction equals to 1, backwards otherwise move: functon(amount, direction), // Rotates your cannon angle by the specified number of degrees rotateCannon: function(amount), // Turns the cannon gun left relative to the robot by the specified // number of degrees (equivalent to rotateCannon(-1 * amount)) turnGunLeft: function(degrees), // Turns the cannon gun right relative to the robot by the specified // number of degrees (equivalent to rotateCannon(amount)) turnGunRight: function(degrees), // Rotates your robot the by the specified number of degrees turn: function(degrees), // Rotates your robot to the left by the specified number of // degrees (equivalent to turn(-1 * degrees)) turnLeft: function(degrees), // Rotates your robot to the right by the specified number of // degrees (equivalent to turn(degrees)) turnRight: function(degrees), // Fires your cannon. This functin has a cooldown before you can // use it again. fire: function(), // Subscribe to get notified whenever this action gets called // in the queue. notify: function(callback), // Removes all remaining actions your robot has from the queue stop: function(), // Clones your robot into another robot and can only be used once // per fight. Remember to check the parentId property to stop // your clone from shooting you. clone: function(), // Disappear your robot for 200 rounds, doing your robot undetected // by enemy robots (onScannedRobot the event is not triggered) and // can only be used once per fight. disappear: function(), // Logs message to the console. log: function(message), // Stops your robot from listening a given event (onWallColision, // for instance). ignore: function(eventName), // Starts listening a given event (onWallColision, for instance). listen: function(eventName) } }
The information available in this object is the base for all other events. In the other event's we'll only document their additional properties.
Your constructor function receives just the "robot" key present in the above object. This means that in your constructor you don't need to assign ev.robot to a variable.
This event will be called whenever your robot hits another robot.
We can implement it as so:
function Robot() {} Robot.prototype.onIdle = function(ev) { // do something }; Robot.prototype.onRobotCollision = function(ev) { var robot = ev.robot; robot.turn(20); robot.ahead(100); // trying to run away };
The object that this function takes as argument is pretty similar to the onIdle function with the following added properties:
{ robot: { // Same as onIdle }, bearing, // Degrees that the other robot relative to my robot // this property can vary from -180 to 180 degrees collidedRobot: { // Information on the robot that collided with mine id, // Id from the robot position: { x, // X position from the other robot relative to the board y // Y position from the other robot relative to the board }, angle, // Angle from the other robot cannonAngle, // Cannon angle relative to the other robot life, // Percentage of life from the other robot parentId // If this is a clone, the clone's parent id. // null otherwise }, myFault // Boolean value that indicates whether I hit the other // robot or the opposite }
This event will be called whenever your robot hits a wall.
We can implement it as so:
function Robot() {} Robot.prototype.onIdle = function(ev) { // do something }; Robot.prototype.onWallCollision = function(ev) { var robot = ev.robot; robot.turn(ev.bearing); // turn enought to be in a straight // angle with the wall. };
The object that this function takes as argument is pretty similar to the onIdle function with the following added properties:
{ robot: { // Same as onIdle }, bearing // Degrees of the wall relative to my robot // this property can vary from -180 to 180 degrees }
This event will be called whenever you see another robot. It's a very important event since it's usually when you want to fire.
This can happen due to a number of things:
We can implement it as so:
function Robot() {} Robot.prototype.onIdle = function(ev) { // do something }; Robot.prototype.onScannedRobot = function(ev) { var robot = ev.robot; robot.fire(); // YAY! };
The object that this function takes as argument is pretty similar to the onIdle function with the following added properties:
{ robot: { // Same as onIdle }, scannedRobot: { id, // Id from the robot position: { x, // X position from the other robot relative to the board y, // Y position from the other robot relative to the board }, angle, // Angle from the other robot cannonAngle, // Cannon angle relative to the other robot life, // Percentage of life from the other robot parentId // If this is a clone, the clone's parent id. // null otherwise } }
This event will be called whenever a bullet hits your robot.
We can implement it as so:
function Robot() {} Robot.prototype.onIdle = function(ev) { // do something }; Robot.prototype.onHitByBullet = function(ev) { var robot = ev.robot; robot.turn(ev.bearing); // Turn to wherever the bullet was fired // so we can see who shot it };
The object that this function takes as argument is pretty similar to the onIdle function with the following added properties:
{ robot: { // Same as onIdle }, bearing // angle that the bullet came from relative // to my tank's angle }