The JavaScript and TypeScript binding
The Clunkyard robot API in Node, over the robot core's WebAssembly build. The generated API and TypeScript declarations share the DSL's core loader; the binding contains no physics, tracking or protocol parser.
Requires Node 20 or later. For local development, install the npm package under the same name your robot imports in the arena:
npm install clunkyard@npm:@clunkyard/sdk
Keep require('clunkyard') or import ... from 'clunkyard' in robot source.
The alias includes the core's WebAssembly build and TypeScript declarations.
Commit package.json and package-lock.json; keep node_modules/ out of source
uploads. The arena supplies its own matching binding during hosted builds.
Standalone Node applications may instead install @clunkyard/sdk and
import @clunkyard/sdk directly.
To build and play a real match, clone the
JavaScript starter or
TypeScript starter and run
make, make match and make replay. Without Make, use
npx @clunkyard/cli build, match and replay. The shared CLI
downloads the separate engine and launcher; the npm SDK package provides the
robot API. The player kit explains setup and
current tooling. cy.play(robot, lines) also accepts recorded protocol
lines for in-memory tests.
For a shared SDK installation, run make install SDK=/opt/clunkyard/sdk.
The arena's TypeScript 6 compiler resolves the declaration with
tsc --ignoreConfig --ignoreDeprecations 6.0 --target ES2022 --module commonjs --baseUrl /opt/clunkyard/sdk/bindings/javascript bot.ts.
Run either language with NODE_PATH=/opt/clunkyard/sdk/bindings/javascript /opt/clunkyard/sdk/bindings/javascript/run bot.js. The launcher preserves
the protocol pipe and sends standard output to standard error before user
code runs, including writes made through fs.
Subsystems are properties of the robot. Facts are properties, calls use
camelCase, and controls take an object of the fields to set. Later controls
merge with earlier ones in the same turn. Optional results are null.
Throw new cy.Forfeit(code, message) to forfeit. Other exceptions are
logged with their trace and the turn sends the controls already set.
A tiny robot
const cy = require('clunkyard');
class Tiny extends cy.Robot {
onTurn() {
const target = this.sensors.nearest;
if (target === null) {
this.drive.set({ throttle: 0.75, turn: 0.25 });
this.scanner.set({ heading: this.me.heading, arc: 40 });
this.status.set({ text: 'SEARCH', value: this.scanner.last.arc });
return;
}
const power = this.gun.powerForFlightTime(target.range, 1);
const aim = this.gun.lead(target, power);
this.gun.aim({ heading: aim ? aim.heading : target.bearing,
pitch: aim ? aim.pitch : target.elevation });
if (this.gun.canFire(power, 10)) this.gun.fire({ power });
this.drive.set({ throttle: 0.5,
turn: cy.angles.clamp(cy.angles.angleDiff(target.bearing, this.me.heading)) });
this.scanner.set({ heading: target.bearing, arc: 10 });
this.status.set({ text: 'TRACK', value: target.range });
}
}
cy.run(new Tiny());
make test SDK=/opt/clunkyard/sdk checks the generated API against the
core's conformance vectors, including exact floating-point results and act
lines. The README example also participates in the cross-language identity
check.
Names
Every entry of the robot API 2.0.0 in JavaScript / TypeScript. names.md has every language side by side.
| Canonical | Form | JavaScript / TypeScript |
|---|---|---|
match.mode |
property | match.mode |
match.ruleset |
property | match.ruleset |
match.control |
property | match.control |
match.robots |
property | match.robots |
match.is_3d |
property | match.is3d |
match.tick_rate |
property | match.tickRate |
match.max_ticks |
property | match.maxTicks |
match.robot_id |
call | match.robotId |
clock.tick |
property | clock.tick |
clock.seconds |
property | clock.seconds |
clock.remaining_ticks |
property | clock.remainingTicks |
arena.size |
property | arena.size |
arena.gravity |
property | arena.gravity |
arena.terrain_kind |
property | arena.terrainKind |
arena.ground_height |
call | arena.groundHeight |
me.health |
property | me.health |
me.position |
property | me.position |
me.velocity |
property | me.velocity |
me.heading |
property | me.heading |
me.pitch |
property | me.pitch |
me.roll |
property | me.roll |
me.angular_velocity |
property | me.angularVelocity |
me.attitude |
property | me.attitude |
me.grounded |
property | me.grounded |
me.altitude |
property | me.altitude |
me.applied |
property | me.applied |
battery.charge |
property | battery.charge |
battery.capacity |
property | battery.capacity |
battery.regen |
property | battery.regen |
battery.sustainable_drive |
property | battery.sustainableDrive |
battery.compute |
property | battery.compute |
battery.drive_cost |
call | battery.driveCost |
drive.hover_lift |
property | drive.hoverLift |
drive.set |
control | drive.set |
drive.forces |
control | drive.forces |
drive.get |
call | drive.get |
gun.aim_now |
property | gun.aimNow |
gun.cooldown_ticks |
property | gun.cooldownTicks |
gun.spread |
property | gun.spread |
gun.max_power |
property | gun.maxPower |
gun.damage_scale |
property | gun.damageScale |
gun.can_fire |
call | gun.canFire |
gun.shot_speed |
call | gun.shotSpeed |
gun.shot_cost |
call | gun.shotCost |
gun.reload_ticks |
call | gun.reloadTicks |
gun.shot_damage |
call | gun.shotDamage |
gun.power_for_speed |
call | gun.powerForSpeed |
gun.power_for_flight_time |
call | gun.powerForFlightTime |
gun.lead |
call | gun.lead |
gun.lead_point |
call | gun.leadPoint |
gun.aim |
control | gun.aim |
gun.fire |
control | gun.fire |
gun.get |
call | gun.get |
scanner.last |
property | scanner.last |
scanner.proximity_range |
property | scanner.proximityRange |
scanner.reach |
call | scanner.reach |
scanner.arc_for_reach |
call | scanner.arcForReach |
scanner.set |
control | scanner.set |
scanner.get |
call | scanner.get |
sensors.contacts |
property | sensors.contacts |
sensors.nearest |
property | sensors.nearest |
sensors.cues |
property | sensors.cues |
sensors.contact |
call | sensors.contact |
sensors.position_of |
call | sensors.positionOf |
tracker.cue |
property | tracker.cue |
tracker.nearest_bearing_rate |
property | tracker.nearestBearingRate |
tracker.velocity |
call | tracker.velocity |
tracker.position |
call | tracker.position |
tracker.last_seen |
call | tracker.lastSeen |
tracker.configure |
call | tracker.configure |
nav.zone |
property | nav.zone |
nav.zone.margin |
call | nav.zone.margin |
nav.zone.contains |
call | nav.zone.contains |
nav.zone.distance_from |
call | nav.zone.distanceFrom |
nav.storm |
property | nav.storm |
nav.storm.margin |
call | nav.storm.margin |
nav.storm.contains |
call | nav.storm.contains |
nav.storm.distance_from |
call | nav.storm.distanceFrom |
nav.hill |
property | nav.hill |
nav.hill.margin |
call | nav.hill.margin |
nav.hill.contains |
call | nav.hill.contains |
nav.hill.distance_from |
call | nav.hill.distanceFrom |
nav.pickups |
property | nav.pickups |
nav.nearest_pickup |
call | nav.nearestPickup |
nav.field_distance |
call | nav.fieldDistance |
score.me |
property | score.me |
score.best |
property | score.best |
score.armour |
property | score.armour |
angles.normalize |
call | angles.normalize |
angles.angle_diff |
call | angles.angleDiff |
angles.bearing_to |
call | angles.bearingTo |
angles.elevation_to |
call | angles.elevationTo |
angles.direction |
call | angles.direction |
angles.distance |
call | angles.distance |
angles.clamp |
call | angles.clamp |
status.set |
control | status.set |
status.get |
call | status.get |
raw.number |
call | raw.number |
raw.text |
call | raw.text |
raw.has |
call | raw.has |
raw.flag |
call | raw.flag |
raw.count |
call | raw.count |
raw.line |
call | raw.line |
raw.extra |
call | raw.extra |
session.event |
property | session.event |
session.next |
call | session.next |
session.send |
call | session.send |
session.forfeit |
call | session.forfeit |
session.log |
call | session.log |
session.feed |
call | session.feed |
session.reply |
call | session.reply |