The Common Lisp binding
The Clunkyard robot API in SBCL, directly over the core's C ABI through
sb-alien. Native declarations, records and wrappers are generated from
protocol/v2/api.json. Loading, the run loop and exception mapping are
written by hand. Tracking, geometry, parsing and serialization stay in the
core.
Install with make install SDK=/opt/clunkyard/sdk. The installer compiles
the binding into FASL files with the same SBCL version as the runtime image.
Run with sbcl --noinform --disable-debugger --load /opt/clunkyard/sdk/bindings/common-lisp/clunkyard.fasl --script bot.lisp.
The binding loads libclunkyard.so.2, or CLUNKYARD_LIB.
API functions use kebab-case and take the robot first, except stateless
angle functions. Records use structure accessors, and enums are keywords
matching their protocol names. Optional values return two values: the
value and whether it is present, so an absent optional boolean differs
from false. API lists are vectors. Controls take keyword fields and merge
in the turn. (cy:drive-get bot :throttle) reads a pending field.
Call (cy:forfeit code message) to forfeit. Other errors are logged with a
backtrace and send the controls already set. cy:play plays lines in memory.
A tiny robot
(defun tiny-turn (bot)
(let ((target (cy:sensors-nearest bot)))
(unless target
(cy:drive-set bot :throttle 0.75d0 :turn 0.25d0)
(cy:scanner-set bot :heading (cy:me-heading bot) :arc 40d0)
(cy:status-set bot :text "SEARCH" :value (cy:scan-arc (cy:scanner-last bot)))
(return-from tiny-turn))
(let* ((power (cy:gun-power-for-flight-time bot (cy:contact-range target) 1d0))
(aim (cy:gun-lead bot target power)))
(cy:gun-aim bot :heading (if aim (cy:solution-heading aim) (cy:contact-bearing target))
:pitch (if aim (cy:solution-pitch aim) (cy:contact-elevation target)))
(when (cy:gun-can-fire bot power 10d0) (cy:gun-fire bot :power power))
(cy:drive-set bot :throttle 0.5d0 :turn (cy:angles-clamp (cy:angles-angle-diff (cy:contact-bearing target) (cy:me-heading bot))))
(cy:scanner-set bot :heading (cy:contact-bearing target) :arc 10d0)
(cy:status-set bot :text "TRACK" :value (cy:contact-range target)))))
(cy:run (cy:make-robot :on-turn #'tiny-turn))
make test SDK=... compares every API vector with the core's transcript,
including exact floating-point bits and act lines. The README robot also
participates in the cross-language identity check.
Names
Every entry of the robot API 2.0.0 in Common Lisp. names.md has every language side by side.
| Canonical | Form | Common Lisp |
|---|---|---|
match.mode |
property | (match-mode robot) |
match.ruleset |
property | (match-ruleset robot) |
match.control |
property | (match-control robot) |
match.robots |
property | (match-robots robot) |
match.is_3d |
property | (match-is-3d robot) |
match.tick_rate |
property | (match-tick-rate robot) |
match.max_ticks |
property | (match-max-ticks robot) |
match.robot_id |
call | (match-robot-id robot slot) |
clock.tick |
property | (clock-tick robot) |
clock.seconds |
property | (clock-seconds robot) |
clock.remaining_ticks |
property | (clock-remaining-ticks robot) |
arena.size |
property | (arena-size robot) |
arena.gravity |
property | (arena-gravity robot) |
arena.terrain_kind |
property | (arena-terrain-kind robot) |
arena.ground_height |
call | (arena-ground-height robot x y) |
me.health |
property | (me-health robot) |
me.position |
property | (me-position robot) |
me.velocity |
property | (me-velocity robot) |
me.heading |
property | (me-heading robot) |
me.pitch |
property | (me-pitch robot) |
me.roll |
property | (me-roll robot) |
me.angular_velocity |
property | (me-angular-velocity robot) |
me.attitude |
property | (me-attitude robot) |
me.grounded |
property | (me-grounded robot) |
me.altitude |
property | (me-altitude robot) |
me.applied |
property | (me-applied robot) |
battery.charge |
property | (battery-charge robot) |
battery.capacity |
property | (battery-capacity robot) |
battery.regen |
property | (battery-regen robot) |
battery.sustainable_drive |
property | (battery-sustainable-drive robot) |
battery.compute |
property | (battery-compute robot) |
battery.drive_cost |
call | (battery-drive-cost robot fraction) |
drive.hover_lift |
property | (drive-hover-lift robot) |
drive.set |
control | (drive-set robot) |
drive.forces |
control | (drive-forces robot) |
drive.get |
call | (drive-get robot) |
gun.aim_now |
property | (gun-aim-now robot) |
gun.cooldown_ticks |
property | (gun-cooldown-ticks robot) |
gun.spread |
property | (gun-spread robot) |
gun.max_power |
property | (gun-max-power robot) |
gun.damage_scale |
property | (gun-damage-scale robot) |
gun.can_fire |
call | (gun-can-fire robot power reserve) |
gun.shot_speed |
call | (gun-shot-speed robot power) |
gun.shot_cost |
call | (gun-shot-cost robot power) |
gun.reload_ticks |
call | (gun-reload-ticks robot power) |
gun.shot_damage |
call | (gun-shot-damage robot power) |
gun.power_for_speed |
call | (gun-power-for-speed robot speed) |
gun.power_for_flight_time |
call | (gun-power-for-flight-time robot range seconds) |
gun.lead |
call | (gun-lead robot contact power) |
gun.lead_point |
call | (gun-lead-point robot position velocity power) |
gun.aim |
control | (gun-aim robot) |
gun.fire |
control | (gun-fire robot) |
gun.get |
call | (gun-get robot) |
scanner.last |
property | (scanner-last robot) |
scanner.proximity_range |
property | (scanner-proximity-range robot) |
scanner.reach |
call | (scanner-reach robot arc) |
scanner.arc_for_reach |
call | (scanner-arc-for-reach robot range) |
scanner.set |
control | (scanner-set robot) |
scanner.get |
call | (scanner-get robot) |
sensors.contacts |
property | (sensors-contacts robot) |
sensors.nearest |
property | (sensors-nearest robot) |
sensors.cues |
property | (sensors-cues robot) |
sensors.contact |
call | (sensors-contact robot slot) |
sensors.position_of |
call | (sensors-position-of robot contact) |
tracker.cue |
property | (tracker-cue robot) |
tracker.nearest_bearing_rate |
property | (tracker-nearest-bearing-rate robot) |
tracker.velocity |
call | (tracker-velocity robot slot) |
tracker.position |
call | (tracker-position robot slot) |
tracker.last_seen |
call | (tracker-last-seen robot slot) |
tracker.configure |
call | (tracker-configure robot smoothing forget-ticks cue-ticks) |
nav.zone |
property | (nav-zone robot) |
nav.zone.margin |
call | (nav-zone-margin region point) |
nav.zone.contains |
call | (nav-zone-contains region point margin) |
nav.zone.distance_from |
call | (nav-zone-distance-from region point) |
nav.storm |
property | (nav-storm robot) |
nav.storm.margin |
call | (nav-storm-margin region point) |
nav.storm.contains |
call | (nav-storm-contains region point margin) |
nav.storm.distance_from |
call | (nav-storm-distance-from region point) |
nav.hill |
property | (nav-hill robot) |
nav.hill.margin |
call | (nav-hill-margin region point) |
nav.hill.contains |
call | (nav-hill-contains region point margin) |
nav.hill.distance_from |
call | (nav-hill-distance-from region point) |
nav.pickups |
property | (nav-pickups robot) |
nav.nearest_pickup |
call | (nav-nearest-pickup robot kind) |
nav.field_distance |
call | (nav-field-distance robot a b) |
score.me |
property | (score-me robot) |
score.best |
property | (score-best robot) |
score.armour |
property | (score-armour robot) |
angles.normalize |
call | (angles-normalize degrees) |
angles.angle_diff |
call | (angles-angle-diff target current) |
angles.bearing_to |
call | (angles-bearing-to from to) |
angles.elevation_to |
call | (angles-elevation-to from to) |
angles.direction |
call | (angles-direction heading pitch) |
angles.distance |
call | (angles-distance a b) |
angles.clamp |
call | (angles-clamp value low high) |
status.set |
control | (status-set robot) |
status.get |
call | (status-get robot) |
raw.number |
call | (raw-number robot path) |
raw.text |
call | (raw-text robot path) |
raw.has |
call | (raw-has robot path) |
raw.flag |
call | (raw-flag robot path) |
raw.count |
call | (raw-count robot path) |
raw.line |
call | (raw-line robot) |
raw.extra |
call | (raw-extra robot json) |
session.event |
property | (session-event robot) |
session.next |
call | (session-next robot) |
session.send |
call | (session-send robot) |
session.forfeit |
call | (session-forfeit robot code message) |
session.log |
call | (session-log robot line) |
session.feed |
call | (session-feed robot line) |
session.reply |
call | (session-reply robot) |