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)

Download this page as Markdown