The R binding
The Clunkyard robot API in R, over the robot core's C ABI through a generated
.Call shim (docs/design/robot-core.md,
section 5.3). src/shim.c and R/api.R are generated by
protocol/v2/codegen/bindings/r.js (make api); the run loop in R/robot.R
and the package files are written by hand. It works on R 4.3.
docs/sdk/names.md gives every name.
- Install:
make install SDK=/opt/clunkyard/sdkbuilds the shim against the core and installs the package into the library$(SDK)/bindings/r. It needs no compiler at run time. - Run:
R_LIBS=/opt/clunkyard/sdk/bindings/r Rscript --vanilla bot.R. - Test:
make test SDK=...runs the installed package against every API vector, exact against the core.
Subsystems are environments on bot (bot$me, bot$match,
bot$scanner$last); facts read like fields and the rest are functions. A
record is a named list and an absent result is NULL. A control sets only
the arguments given, so bot$drive$set(turn = 0.5) keeps the throttle, and
bot$drive$get("throttle") reads a field back. angles holds the angle
helpers, the core's to the last bit. Call forfeit(code, message) to
forfeit; any other error is logged with its calls and the turn answers with
what it had set.
A tiny robot
library(clunkyard)
run(robot(on_turn = function(bot) {
target <- bot$sensors$nearest
if (is.null(target)) {
bot$drive$set(throttle = 0.75, turn = 0.25)
bot$scanner$set(heading = bot$me$heading, arc = 40)
bot$status$set("SEARCH", bot$scanner$last$arc)
return(invisible())
}
power <- bot$gun$power_for_flight_time(target$range, 1)
aim <- bot$gun$lead(target, power)
if (is.null(aim)) bot$gun$aim(target$bearing, target$elevation) else bot$gun$aim(aim$heading, aim$pitch)
if (bot$gun$can_fire(power, 10)) bot$gun$fire(power)
bot$drive$set(throttle = 0.5, turn = angles$clamp(angles$angle_diff(target$bearing, bot$me$heading)))
bot$scanner$set(heading = target$bearing, arc = 10)
bot$status$set("TRACK", target$range)
}))
Names
Every entry of the robot API 2.0.0 in R. names.md has every language side by side.
| Canonical | Form | R |
|---|---|---|
match.mode |
property | bot$match$mode |
match.ruleset |
property | bot$match$ruleset |
match.control |
property | bot$match$control |
match.robots |
property | bot$match$robots |
match.is_3d |
property | bot$match$is_3d |
match.tick_rate |
property | bot$match$tick_rate |
match.max_ticks |
property | bot$match$max_ticks |
match.robot_id |
call | bot$match$robot_id(slot) |
clock.tick |
property | bot$clock$tick |
clock.seconds |
property | bot$clock$seconds |
clock.remaining_ticks |
property | bot$clock$remaining_ticks |
arena.size |
property | bot$arena$size |
arena.gravity |
property | bot$arena$gravity |
arena.terrain_kind |
property | bot$arena$terrain_kind |
arena.ground_height |
call | bot$arena$ground_height(x, y) |
me.health |
property | bot$me$health |
me.position |
property | bot$me$position |
me.velocity |
property | bot$me$velocity |
me.heading |
property | bot$me$heading |
me.pitch |
property | bot$me$pitch |
me.roll |
property | bot$me$roll |
me.angular_velocity |
property | bot$me$angular_velocity |
me.attitude |
property | bot$me$attitude |
me.grounded |
property | bot$me$grounded |
me.altitude |
property | bot$me$altitude |
me.applied |
property | bot$me$applied |
battery.charge |
property | bot$battery$charge |
battery.capacity |
property | bot$battery$capacity |
battery.regen |
property | bot$battery$regen |
battery.sustainable_drive |
property | bot$battery$sustainable_drive |
battery.compute |
property | bot$battery$compute |
battery.drive_cost |
call | bot$battery$drive_cost(fraction) |
drive.hover_lift |
property | bot$drive$hover_lift |
drive.set |
control | bot$drive$set(throttle = NULL, turn = NULL, pitch_turn = NULL) |
drive.forces |
control | bot$drive$forces(thrust = NULL, strafe = NULL, lift = NULL, yaw_torque = NULL, pitch_torque = NULL, roll_torque = NULL, brake = NULL) |
drive.get |
call | bot$drive$get("throttle") |
gun.aim_now |
property | bot$gun$aim_now |
gun.cooldown_ticks |
property | bot$gun$cooldown_ticks |
gun.spread |
property | bot$gun$spread |
gun.max_power |
property | bot$gun$max_power |
gun.damage_scale |
property | bot$gun$damage_scale |
gun.can_fire |
call | bot$gun$can_fire(power, reserve) |
gun.shot_speed |
call | bot$gun$shot_speed(power) |
gun.shot_cost |
call | bot$gun$shot_cost(power) |
gun.reload_ticks |
call | bot$gun$reload_ticks(power) |
gun.shot_damage |
call | bot$gun$shot_damage(power) |
gun.power_for_speed |
call | bot$gun$power_for_speed(speed) |
gun.power_for_flight_time |
call | bot$gun$power_for_flight_time(range, seconds) |
gun.lead |
call | bot$gun$lead(contact, power) |
gun.lead_point |
call | bot$gun$lead_point(position, velocity, power) |
gun.aim |
control | bot$gun$aim(heading = NULL, pitch = NULL) |
gun.fire |
control | bot$gun$fire(power = NULL) |
gun.get |
call | bot$gun$get("heading") |
scanner.last |
property | bot$scanner$last |
scanner.proximity_range |
property | bot$scanner$proximity_range |
scanner.reach |
call | bot$scanner$reach(arc) |
scanner.arc_for_reach |
call | bot$scanner$arc_for_reach(range) |
scanner.set |
control | bot$scanner$set(heading = NULL, arc = NULL, pitch = NULL) |
scanner.get |
call | bot$scanner$get("heading") |
sensors.contacts |
property | bot$sensors$contacts |
sensors.nearest |
property | bot$sensors$nearest |
sensors.cues |
property | bot$sensors$cues |
sensors.contact |
call | bot$sensors$contact(slot) |
sensors.position_of |
call | bot$sensors$position_of(contact) |
tracker.cue |
property | bot$tracker$cue |
tracker.nearest_bearing_rate |
property | bot$tracker$nearest_bearing_rate |
tracker.velocity |
call | bot$tracker$velocity(slot) |
tracker.position |
call | bot$tracker$position(slot) |
tracker.last_seen |
call | bot$tracker$last_seen(slot) |
tracker.configure |
call | bot$tracker$configure(smoothing = 0.5, forget_ticks = 40, cue_ticks = 60) |
nav.zone |
property | bot$nav$zone |
nav.zone.margin |
call | bot$nav$zone$margin(point) |
nav.zone.contains |
call | bot$nav$zone$contains(point, margin = 0) |
nav.zone.distance_from |
call | bot$nav$zone$distance_from(point) |
nav.storm |
property | bot$nav$storm |
nav.storm.margin |
call | bot$nav$storm$margin(point) |
nav.storm.contains |
call | bot$nav$storm$contains(point, margin = 0) |
nav.storm.distance_from |
call | bot$nav$storm$distance_from(point) |
nav.hill |
property | bot$nav$hill |
nav.hill.margin |
call | bot$nav$hill$margin(point) |
nav.hill.contains |
call | bot$nav$hill$contains(point, margin = 0) |
nav.hill.distance_from |
call | bot$nav$hill$distance_from(point) |
nav.pickups |
property | bot$nav$pickups |
nav.nearest_pickup |
call | bot$nav$nearest_pickup(kind = NULL) |
nav.field_distance |
call | bot$nav$field_distance(a, b) |
score.me |
property | bot$score$me |
score.best |
property | bot$score$best |
score.armour |
property | bot$score$armour |
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 = -1, high = 1) |
status.set |
control | bot$status$set(text = NULL, value = NULL) |
status.get |
call | bot$status$get("text") |
raw.number |
call | bot$raw$number(path) |
raw.text |
call | bot$raw$text(path) |
raw.has |
call | bot$raw$has(path) |
raw.flag |
call | bot$raw$flag(path) |
raw.count |
call | bot$raw$count(path) |
raw.line |
call | bot$raw$line() |
raw.extra |
call | bot$raw$extra(json) |