My First Bot for TypeScript / JavaScript
Introduction
This tutorial is meant for the TypeScript/JavaScript platform and is a continuation of the My First Bot tutorial.
The programming language used here is TypeScript, which adds static typing on top of JavaScript and runs on Node.js. Plain JavaScript is equally supported — just omit the type annotations. This tutorial assumes you are already familiar with basic TypeScript or JavaScript programming.
Programming
TypeScript API
The documentation of the TypeScript Bot API for Robocode Tank Royale is available on this page.
Create a source file
Inside your bot directory (../bots/MyFirstBot) create a TypeScript source file named MyFirstBot.ts. You can edit that file using a text editor of your choice, or an IDE like e.g. Visual Studio Code or WebStorm.
Initial code
The initial skeleton of your bot could look like this:
import { Bot } from "@robocode.dev/tank-royale-bot-api";
class MyFirstBot extends Bot {
}The class in this example (MyFirstBot) extends the Bot class from the @robocode.dev/tank-royale-bot-api package, which provides methods for controlling the bot and receiving events from the game. The API handles the communication with the server behind the scenes.
Startup / Main entry
The next thing we need to do is to add a static main method that creates and starts the bot:
class MyFirstBot extends Bot {
// The main method starts our bot
static main() {
new MyFirstBot().start();
}
}
MyFirstBot.main();The main method simply creates the bot and calls its start method, which will let the bot start up, read configuration (from a .json file or environment variables), and start communicating with the server.
If you don't want to use a .json configuration file, you can provide the bot information directly in the constructor:
import { Bot, BotInfo } from "@robocode.dev/tank-royale-bot-api";
class MyFirstBot extends Bot {
constructor() {
super(new BotInfo(
"My First Bot",
"1.0",
["Your Name"],
"My first bot",
null,
["US"],
["classic"],
"Node.js",
"TypeScript",
null
));
}
}When providing BotInfo in the constructor, the .json file is not required. The booter will use heuristic platform detection together with the script files (see Running the bot) to locate and start your TypeScript bot.
Tip: The simplest approach is to always provide a
MyFirstBot.jsonfile alongside your source — it gives the booter everything it needs and lets you skip writing a constructor.
The run method
When the game starts the bot, the run method will be called. Override this method to provide the logic for the bot when the game is started. It should do all required initialization, then enter a loop that runs until the game ends.
class MyFirstBot extends Bot {
// Called when a new round is started -> initialize and do some movement
override run() {
// Repeat while the bot is running
while (this.isRunning()) {
this.forward(100);
this.turnGunLeft(360);
this.back(100);
this.turnGunLeft(360);
}
}
}With the code above, the bot will run in a loop: moving forward 100 units, turning the gun 360°, moving back 100 units, and turning the gun 360° again. The loop continues as long as isRunning returns true. The API sets this flag to false automatically when the bot is told to stop.
Event handlers
The Bot API provides many event handlers (on<SomeEvent> methods) triggered by different types of game events. All event handlers start with the on prefix.
The onScannedBot event handler fires the cannon whenever the bot scans an opponent:
import { Bot, ScannedBotEvent } from "@robocode.dev/tank-royale-bot-api";
class MyFirstBot extends Bot {
// We saw another bot -> fire!
override onScannedBot(e: ScannedBotEvent) {
this.fire(1);
}
}The onHitByBullet event handler turns the bot perpendicular to the bullet to avoid further hits:
import { Bot, HitByBulletEvent } from "@robocode.dev/tank-royale-bot-api";
class MyFirstBot extends Bot {
// We were hit by a bullet -> turn perpendicular to the bullet
override onHitByBullet(e: HitByBulletEvent) {
// Calculate the bearing to the direction of the bullet
const bearing = this.calcBearing(e.bullet.direction);
// Turn 90 degrees to the bullet direction based on the bearing
this.turnRight(90 - bearing);
}
}The Bot API provides helper methods like calcBearing to ease calculating angles and bearings in the game.
Putting it all together
import { Bot, HitByBulletEvent, ScannedBotEvent } from "@robocode.dev/tank-royale-bot-api";
class MyFirstBot extends Bot {
// The main method starts our bot
static main() {
new MyFirstBot().start();
}
// Called when a new round is started -> initialize and do some movement
override run() {
// Repeat while the bot is running
while (this.isRunning()) {
this.forward(100);
this.turnGunLeft(360);
this.back(100);
this.turnGunLeft(360);
}
}
// We saw another bot -> fire!
override onScannedBot(e: ScannedBotEvent) {
this.fire(1);
}
// We were hit by a bullet -> turn perpendicular to the bullet
override onHitByBullet(e: HitByBulletEvent) {
// Calculate the bearing to the direction of the bullet
const bearing = this.calcBearing(e.bullet.direction);
// Turn 90 degrees to the bullet direction based on the bearing
this.turnRight(90 - bearing);
}
}
MyFirstBot.main();import { Bot } from "@robocode.dev/tank-royale-bot-api";
class MyFirstBot extends Bot {
// The main method starts our bot
static main() {
new MyFirstBot().start();
}
// Called when a new round is started -> initialize and do some movement
run() {
// Repeat while the bot is running
while (this.isRunning()) {
this.forward(100);
this.turnGunLeft(360);
this.back(100);
this.turnGunLeft(360);
}
}
// We saw another bot -> fire!
onScannedBot(e) {
this.fire(1);
}
// We were hit by a bullet -> turn perpendicular to the bullet
onHitByBullet(e) {
// Calculate the bearing to the direction of the bullet
const bearing = this.calcBearing(e.bullet.direction);
// Turn 90 degrees to the bullet direction based on the bearing
this.turnRight(90 - bearing);
}
}
MyFirstBot.main();JavaScript differences: Drop all type annotations and the
overridekeyword. Name your source fileMyFirstBot.jsand add"type": "module"to yourpackage.json(required for ES module imports). Usenode MyFirstBot.jsdirectly in your scripts instead oftsx MyFirstBot.ts.
Running the bot
Now we have a JSON configuration file and the source file for our bot. The next step is to set up the dependencies and the scripts for running the bot application.
Install the bot API library
The TypeScript Bot API is published as an npm package. Install it along with tsx (a fast TypeScript runner) and the WebSocket library:
npm install @robocode.dev/tank-royale-bot-api tsx wsIf you downloaded the source from this repository, the TypeScript package is located under bot-api/typescript and you can reference it locally via a file path in package.json.
Scripts for starting the bot
Provide script files so both the command line and the Robocode booter can start your bot.
We create a command file for Windows named MyFirstBot.cmd and put it into our bot directory:
@echo off
cd /d "%~dp0"
set NODE_OPTIONS=--disable-warning=ExperimentalWarning
..\node_modules\.bin\tsx MyFirstBot.tsNext, we create a shell script for macOS and Linux named MyFirstBot.sh and put it into our bot directory:
#!/bin/sh
set -e
cd -- "$(dirname -- "$0")"
export NODE_OPTIONS="--disable-warning=ExperimentalWarning"
exec "../node_modules/.bin/tsx" "MyFirstBot.ts"Make the shell script executable:
chmod 755 MyFirstBot.shNow you have everything in place to run your bot with Robocode Tank Royale.
Note: The server must be running locally when you attempt to run the bot locally; otherwise the bot will fail with an error because it cannot reach the server. The server can be started using the Robocode UI.
Packaging your bot
To package your bot for distribution, zip the bot directory. The archive should contain:
- Source file (
.tsor.js) - JSON config file (
.json) - Script files (
.cmdand.sh) — Optional due to template-based booting package.jsonandnode_modules/(or apackage-lock.jsonso users can runnpm install)
You can download the sample-bots-typescript-x.y.z.zip file from any release, which provides a good example of how to package one or multiple TypeScript bots.
Bot Secrets
When you run your bot outside the GUI, you only need to supply bot secrets if the server is configured to require them. Look for the bots-secrets field in the server's server.properties file:
bots-secrets=zDuQrkCLQU5VQgytofkNrQSet the BOT_SECRETS environment variable before running your bot:
Mac/Linux bash/shell:
export BOT_SECRETS=zDuQrkCLQU5VQgytofkNrQWindows command line:
set BOT_SECRETS=zDuQrkCLQU5VQgytofkNrQWindows PowerShell:
$Env:BOT_SECRETS = "zDuQrkCLQU5VQgytofkNrQ"It is also possible to provide the server secret and URL programmatically via the Bot constructor.