FightCode is an online game for programmers, built in the image of the classic
Robocode . JavaScript is used to program tanks, all battles take place right in the browser, and the code editor on the site has a built-in sandbox that allows you to see the effect of code changes in real time. Unlike many other similar games, the creators did a good job on the design - the playing field and the whole site look attractive and bright.

All this makes FightCode one of the best options for beginners in similar games or for learning programming. The project is quite young, and despite the fact that almost 9,000 players are registered on the site, you can effortlessly break into the first hundred of the rankings. A system of battles with random opponents is very conveniently organized - out of all available robots, those whose rating is close to yours are automatically selected. Points are considered by
the Elo system - a victory over a stronger opponent gives much more points than a weak one.
')
Each participant can have any number of robots. Creating a new robot begins with a primitive template that makes almost no meaningful action. By adding handlers for basic events, such as collisions or hitting an enemy projectile, you can give the robot a set of “unconditioned reflexes” that will make its behavior more expedient and serve as a starting point for further development.
First, a few words about the game world and the rules of the game. Robots are fighting on a flat rectangular field. The game world is two-dimensional, so that flights or short projectile here does not happen. Tanks play one on one, but each player can create a “clone” of his tank, which has less health and dies if its parent is killed.
Tanks can move forward and backward, rotate, rotate the turret and shoot. There is no separate radar, as in Robocode. The main game loop is set in the "
onIdle
" event handler. When a tank gets into the field of view of the tower, an "
onScannedRobot
" event occurs, an "
onScannedRobot
" event occurs in a collision with a wall, and so on (there is a full
description of the API on the site).
The default robot code looks like this:
var Robot = function(robot) { }; Robot.prototype.onIdle = function(ev) { var robot = ev.robot;
First of all, we will teach our robot not to lose the goal after the first shot. The robot's rate of fire is limited, so he manages to turn the turret between shots a few degrees and lose sight of the target. Therefore, let's make him turn the tower a little left and right. At the same time, it will not miss the moving target:
Robot.prototype.onScannedRobot = function(ev) { var r = ev.robot;
Now our robot can hold a target. Before moving on, let's plug in some magic. The robot has two magic tricks in reserve: it can create its own clone and become invisible to the enemy for a while. We will create the clone right away - an extra firepower and a distracting goal for the enemy are useful from the very beginning of the game:
Robot.prototype.onIdle = function(ev) { var r = ev.robot; r.clone();
The next step is to teach the robot not to fire on its own. By default, he scorches everything that catches his eye, including his own clone or parent. To wean him from this, you need to check before shooting who is in front of us. This is done using the
id
and
parentId
:
Robot.prototype.onScannedRobot = function(ev) { var r = ev.robot;
Now we will make our robot a little more mobile and teach it to shoot in motion. The easiest way is to move in a circle while firing. Entry-level robots do not know how to shoot ahead of time, so by circling the circles, we will miss most of the enemy’s shells, no matter which side they shoot at us. To do this, after each shot we will slightly rotate the body of the robot and pass a little forward:
Robot.prototype.onScannedRobot = function(ev) { var r = ev.robot; if (ev.scannedRobot.parentId == r.id || ev.scannedRobot.id == r.parentId) { return; }; r.fire(); r.turn(10);
And one more nuance - the
onScannedRobot
event occurs as soon as the “radar beam” intersects with the edge of the enemy tank. Since most of the time we turn the turret to the right, the shells fly to the left edge of the target and often fly past. To beat more precisely, we will turn the turret a few degrees to the right before the shot:
Robot.prototype.onScannedRobot = function(ev) { var r = ev.robot; if (ev.scannedRobot.parentId == r.id || ev.scannedRobot.id == r.parentId) { return; } r.rotateCannon(2);
Instead of uselessly driving back and forth in the same place, we make the tank move actively across the field. This will help avoid situations where we are in one corner, the enemy in another, shells fly across the entire field and almost never fall. We will move all the time forward, and not by 100, but by 150 units. In addition, we will slightly change the course to be less predictable:
Robot.prototype.onIdle = function(ev) { var r = ev.robot; r.clone(); r.rotateCannon(360); r.ahead(150); r.turn(30); r.ahead(150); };
The final touches - in order not to get stuck, stumbled upon a wall or another tank, we will write event handlers for the collision. In order not to knock down the sight, if we collided during the shooting, and not to lose time on the turn, we will just move back a little. As a rule, this is enough, because the robot is spinning most of the time and will not abut the same place several times, and if it does, this is a pretty good maneuver of evading enemy projectiles:
Robot.prototype.onWallCollision = function(ev) { var r = ev.robot; r.back(50); }; Robot.prototype.onRobotCollision = function(ev) { var r = ev.robot; r.back(30); };
Our entry level robot is ready! It is still very stupid, but there are only about 40 lines of code in it. At the same time, he behaves himself on the battlefield rather aggressively and agile, never gets stuck and does not get hung up and quite confidently wins all test robots from the sandbox. In a real battle, if lucky, he can beat an opponent with a rating of 1700. All values ​​of angles and distances in the code are chosen empirically.
The full code of our robot