The Rust binding
The generated Rust binding wraps the core's C ABI with value records,
subsystem objects and Result and Option results. Every record has its
checked C layout. Tracking, geometry, protocol parsing and act serialization
remain in the core. Controls take optional fields, so later calls merge with
earlier ones; typed getters read pending fields back.
Install with make install SDK=/opt/clunkyard/sdk. Build with
rustc --edition=2021 -O --extern clunkyard=/opt/clunkyard/sdk/bindings/rust/libclunkyard.rlib -L native=/opt/clunkyard/sdk/lib -C link-arg=-lpthread -C link-arg=-ldl -C link-arg=-lm bot.rs -o bot. The native core is statically linked.
Implement Strategy, then call clunkyard::run(strategy). A returned error
or panic logs its trace and sends the controls already set.
Error::forfeit(code, message) reports a robot forfeit.
clunkyard::play(strategy, lines) uses a memory session for tests.
A tiny robot
use clunkyard::{Error, Robot, Strategy};
struct Tiny;
impl Strategy for Tiny {
fn on_turn(&mut self, robot: &Robot) -> Result<(), Error> {
let Some(target) = robot.sensors.nearest()? else {
robot.drive.set(Some(0.75), Some(0.25), None)?;
robot.scanner.set(Some(robot.me.heading()?), Some(40.0), None)?;
robot.status.set(Some("SEARCH"), Some(robot.scanner.last()?.arc))?;
return Ok(());
};
let power = robot.gun.power_for_flight_time(target.range, 1.0)?;
let aim = robot.gun.lead(&target, power)?;
let (heading, pitch) = aim.map(|aim| (aim.heading, aim.pitch)).unwrap_or((target.bearing, target.elevation));
robot.gun.aim(Some(heading), Some(pitch))?;
if robot.gun.can_fire(power, 10.0)? { robot.gun.fire(Some(power))?; }
robot.drive.set(Some(0.5), Some(robot.angles.clamp(robot.angles.angle_diff(target.bearing, robot.me.heading()?)?, -1.0, 1.0)?), None)?;
robot.scanner.set(Some(target.bearing), Some(10.0), None)?;
robot.status.set(Some("TRACK"), Some(target.range))?;
Ok(())
}
}
fn main() -> Result<(), Error> { clunkyard::run(Tiny) }
make test runs the complete core conformance transcript through the safe
Rust wrapper. It checks exact floating-point bits, layouts, optional records,
text, controls and act lines. The tiny robot is also compared across bindings.
Names
Every entry of the robot API 2.0.0 in Rust. names.md has every language side by side.
| Canonical | Form | Rust |
|---|---|---|
match.mode |
property | r#match.mode() |
match.ruleset |
property | r#match.ruleset() |
match.control |
property | r#match.control() |
match.robots |
property | r#match.robots() |
match.is_3d |
property | r#match.is_3d() |
match.tick_rate |
property | r#match.tick_rate() |
match.max_ticks |
property | r#match.max_ticks() |
match.robot_id |
call | r#match.robot_id() |
clock.tick |
property | clock.tick() |
clock.seconds |
property | clock.seconds() |
clock.remaining_ticks |
property | clock.remaining_ticks() |
arena.size |
property | arena.size() |
arena.gravity |
property | arena.gravity() |
arena.terrain_kind |
property | arena.terrain_kind() |
arena.ground_height |
call | arena.ground_height() |
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.angular_velocity() |
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.sustainable_drive() |
battery.compute |
property | battery.compute() |
battery.drive_cost |
call | battery.drive_cost() |
drive.hover_lift |
property | drive.hover_lift() |
drive.set |
control | drive.set() |
drive.forces |
control | drive.forces() |
drive.get |
call | drive.get_ |
gun.aim_now |
property | gun.aim_now() |
gun.cooldown_ticks |
property | gun.cooldown_ticks() |
gun.spread |
property | gun.spread() |
gun.max_power |
property | gun.max_power() |
gun.damage_scale |
property | gun.damage_scale() |
gun.can_fire |
call | gun.can_fire() |
gun.shot_speed |
call | gun.shot_speed() |
gun.shot_cost |
call | gun.shot_cost() |
gun.reload_ticks |
call | gun.reload_ticks() |
gun.shot_damage |
call | gun.shot_damage() |
gun.power_for_speed |
call | gun.power_for_speed() |
gun.power_for_flight_time |
call | gun.power_for_flight_time() |
gun.lead |
call | gun.lead() |
gun.lead_point |
call | gun.lead_point() |
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.proximity_range() |
scanner.reach |
call | scanner.reach() |
scanner.arc_for_reach |
call | scanner.arc_for_reach() |
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.position_of() |
tracker.cue |
property | tracker.cue() |
tracker.nearest_bearing_rate |
property | tracker.nearest_bearing_rate() |
tracker.velocity |
call | tracker.velocity() |
tracker.position |
call | tracker.position() |
tracker.last_seen |
call | tracker.last_seen() |
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_distance_from() |
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_distance_from() |
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_distance_from() |
nav.pickups |
property | nav.pickups() |
nav.nearest_pickup |
call | nav.nearest_pickup() |
nav.field_distance |
call | nav.field_distance() |
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.angle_diff() |
angles.bearing_to |
call | angles.bearing_to() |
angles.elevation_to |
call | angles.elevation_to() |
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() |