The BQN adapter
One persistent CBQN process runs the tactic. The installed JavaScript
binding owns its robot core session. Generated cy.* functions synchronously
query that core over the existing pipe; geometry, lead, tracking and protocol
logic remain in the core. Install with make install SDK=/opt/clunkyard/sdk
after the JavaScript binding. Run with
NODE_PATH=/opt/clunkyard/sdk/bindings/bqn:/opt/clunkyard/sdk/bindings/javascript /opt/clunkyard/sdk/bindings/javascript/run bot.js.
The namespace is passed to the tactic through •args; start with
cy ← ⊑•args. A property call takes @, a single argument is passed directly,
and multiple arguments form a list: cy.GunPowerForFlightTime range‿1.
Vectors are three numbers. Other records are namespaces with camelCase
fields. An absent result is @. Controls take namespaces;
cy.DriveSet {throttle⇐0.5} sets only that field. Getters take a field name.
All names and record shapes are generated from protocol/v2/api.json.
The familiar g cy.ShotSpeed power, g cy.Lead args, region helpers and
control builders are also available. Turn returns a list of control pairs,
or calls the canonical control functions and returns ⟨⟩. Controls from
both paths reach the same core. Start is optional. run and play handle
session failures and forfeits through the JavaScript binding. Tactic errors
are logged and the turn preserves controls already set.
A tiny robot
Save this tactic as tiny.bqn:
cy ← ⊑•args
Search ← {𝕊:
cy.DriveSet {throttle⇐0.75 ⋄ turn⇐0.25}
cy.ScannerSet {heading⇐cy.MeHeading @ ⋄ arc⇐40}
cy.StatusSet {text⇐"SEARCH" ⋄ value⇐(cy.ScannerLast @).arc}
}
Track ← {target←𝕩
power←cy.GunPowerForFlightTime target.range‿1
aim←cy.GunLead target‿power
direction←{6=•Type 𝕩 ? 𝕩 ; {heading⇐target.bearing ⋄ pitch⇐target.elevation}} aim
cy.GunAim {heading⇐direction.heading ⋄ pitch⇐direction.pitch}
{cy.GunCanFire power‿10 ? cy.GunFire {power⇐power} ; @}
cy.DriveSet {throttle⇐0.5 ⋄ turn⇐cy.AnglesClamp ⟨cy.AnglesAngleDiff target.bearing‿(cy.MeHeading @),¯1,1⟩}
cy.ScannerSet {heading⇐target.bearing ⋄ arc⇐10}
cy.StatusSet {text⇐"TRACK" ⋄ value⇐target.range}
}
Turn ⇐ {g 𝕊 state:
target←cy.SensorsNearest @
(6=•Type target)◶Search‿Track target
⟨⟩
}
Save the launcher as bot.js:
const {run} = require('clunkyard_bqn');
run(require('node:path').join(__dirname, 'tiny.bqn'));
make test calls the actual CBQN query and control functions against the
API vectors. Complete names.
Names
Every entry of the robot API 2.0.0 in BQN. names.md has every language side by side.
| Canonical | Form | BQN |
|---|---|---|
match.mode |
property | cy.MatchMode |
match.ruleset |
property | cy.MatchRuleset |
match.control |
property | cy.MatchControl |
match.robots |
property | cy.MatchRobots |
match.is_3d |
property | cy.MatchIs3d |
match.tick_rate |
property | cy.MatchTickRate |
match.max_ticks |
property | cy.MatchMaxTicks |
match.robot_id |
call | cy.MatchRobotId |
clock.tick |
property | cy.ClockTick |
clock.seconds |
property | cy.ClockSeconds |
clock.remaining_ticks |
property | cy.ClockRemainingTicks |
arena.size |
property | cy.ArenaSize |
arena.gravity |
property | cy.ArenaGravity |
arena.terrain_kind |
property | cy.ArenaTerrainKind |
arena.ground_height |
call | cy.ArenaGroundHeight |
me.health |
property | cy.MeHealth |
me.position |
property | cy.MePosition |
me.velocity |
property | cy.MeVelocity |
me.heading |
property | cy.MeHeading |
me.pitch |
property | cy.MePitch |
me.roll |
property | cy.MeRoll |
me.angular_velocity |
property | cy.MeAngularVelocity |
me.attitude |
property | cy.MeAttitude |
me.grounded |
property | cy.MeGrounded |
me.altitude |
property | cy.MeAltitude |
me.applied |
property | cy.MeApplied |
battery.charge |
property | cy.BatteryCharge |
battery.capacity |
property | cy.BatteryCapacity |
battery.regen |
property | cy.BatteryRegen |
battery.sustainable_drive |
property | cy.BatterySustainableDrive |
battery.compute |
property | cy.BatteryCompute |
battery.drive_cost |
call | cy.BatteryDriveCost |
drive.hover_lift |
property | cy.DriveHoverLift |
drive.set |
control | cy.DriveSet |
drive.forces |
control | cy.DriveForces |
drive.get |
call | cy.DriveGet |
gun.aim_now |
property | cy.GunAimNow |
gun.cooldown_ticks |
property | cy.GunCooldownTicks |
gun.spread |
property | cy.GunSpread |
gun.max_power |
property | cy.GunMaxPower |
gun.damage_scale |
property | cy.GunDamageScale |
gun.can_fire |
call | cy.GunCanFire |
gun.shot_speed |
call | cy.GunShotSpeed |
gun.shot_cost |
call | cy.GunShotCost |
gun.reload_ticks |
call | cy.GunReloadTicks |
gun.shot_damage |
call | cy.GunShotDamage |
gun.power_for_speed |
call | cy.GunPowerForSpeed |
gun.power_for_flight_time |
call | cy.GunPowerForFlightTime |
gun.lead |
call | cy.GunLead |
gun.lead_point |
call | cy.GunLeadPoint |
gun.aim |
control | cy.GunAim |
gun.fire |
control | cy.GunFire |
gun.get |
call | cy.GunGet |
scanner.last |
property | cy.ScannerLast |
scanner.proximity_range |
property | cy.ScannerProximityRange |
scanner.reach |
call | cy.ScannerReach |
scanner.arc_for_reach |
call | cy.ScannerArcForReach |
scanner.set |
control | cy.ScannerSet |
scanner.get |
call | cy.ScannerGet |
sensors.contacts |
property | cy.SensorsContacts |
sensors.nearest |
property | cy.SensorsNearest |
sensors.cues |
property | cy.SensorsCues |
sensors.contact |
call | cy.SensorsContact |
sensors.position_of |
call | cy.SensorsPositionOf |
tracker.cue |
property | cy.TrackerCue |
tracker.nearest_bearing_rate |
property | cy.TrackerNearestBearingRate |
tracker.velocity |
call | cy.TrackerVelocity |
tracker.position |
call | cy.TrackerPosition |
tracker.last_seen |
call | cy.TrackerLastSeen |
tracker.configure |
call | cy.TrackerConfigure |
nav.zone |
property | cy.NavZone |
nav.zone.margin |
call | cy.NavZoneMargin |
nav.zone.contains |
call | cy.NavZoneContains |
nav.zone.distance_from |
call | cy.NavZoneDistanceFrom |
nav.storm |
property | cy.NavStorm |
nav.storm.margin |
call | cy.NavStormMargin |
nav.storm.contains |
call | cy.NavStormContains |
nav.storm.distance_from |
call | cy.NavStormDistanceFrom |
nav.hill |
property | cy.NavHill |
nav.hill.margin |
call | cy.NavHillMargin |
nav.hill.contains |
call | cy.NavHillContains |
nav.hill.distance_from |
call | cy.NavHillDistanceFrom |
nav.pickups |
property | cy.NavPickups |
nav.nearest_pickup |
call | cy.NavNearestPickup |
nav.field_distance |
call | cy.NavFieldDistance |
score.me |
property | cy.ScoreMe |
score.best |
property | cy.ScoreBest |
score.armour |
property | cy.ScoreArmour |
angles.normalize |
call | cy.AnglesNormalize |
angles.angle_diff |
call | cy.AnglesAngleDiff |
angles.bearing_to |
call | cy.AnglesBearingTo |
angles.elevation_to |
call | cy.AnglesElevationTo |
angles.direction |
call | cy.AnglesDirection |
angles.distance |
call | cy.AnglesDistance |
angles.clamp |
call | cy.AnglesClamp |
status.set |
control | cy.StatusSet |
status.get |
call | cy.StatusGet |
raw.number |
call | cy.RawNumber |
raw.text |
call | cy.RawText |
raw.has |
call | cy.RawHas |
raw.flag |
call | cy.RawFlag |
raw.count |
call | cy.RawCount |
raw.line |
call | cy.RawLine |
raw.extra |
call | cy.RawExtra |
session.event |
property | cy.SessionEvent |
session.next |
call | cy.SessionNext |
session.send |
call | cy.SessionSend |
session.forfeit |
call | cy.SessionForfeit |
session.log |
call | cy.SessionLog |
session.feed |
call | cy.SessionFeed |
session.reply |
call | cy.SessionReply |