The Ada binding
The generated Clunkyard specification describes the core's C ABI with
Convention => C records, addressable fields and imported functions.
Functions return a status and copy results through access parameters.
CY_NONE means absent; negative statuses are errors. cy_last_error
gives their text. Strings are UTF-8 bytes at a System.Address with an
explicit length. Lists use an addressable first record, capacity and count.
Install with make install SDK=/opt/clunkyard/sdk. Build with
gnatmake -gnat2022 -O2 -I/opt/clunkyard/sdk/bindings/ada bot.adb -largs /opt/clunkyard/sdk/lib/libclunkyard.a -lpthread -ldl -lm.
The binding and core are linked into the robot executable; no JSON library
or runtime compiler is needed.
cy_open opens standard I/O and protects the protocol pipe. Tests can use
cy_open_memory, cy_session_feed and cy_session_reply. After
cy_session_next returns CY_E_INTERNAL, send the core's empty reply and
continue to recover on the next state. cy_session_forfeit reports a robot
forfeit.
A tiny robot
with Clunkyard;use Clunkyard;
with Interfaces.C;use Interfaces.C;
with System;
procedure Bot is
Robot:aliased System.Address;
Target:aliased Cy_Contact;Aim:aliased Cy_Solution;Last:aliased Cy_Scan;
Event,Can_Fire:aliased I32;Code:I32;
Heading,Power,Delta_Value,Control:aliased Real;
Name:constant String:="clunkyard-ada";Version:constant String:="2.0.0";
procedure Show(Text:String;Value:Real)is Status:I32;
begin Status:=cy_status_text(Robot,Text'Address,Text'Length);Status:=cy_status_value(Robot,Value);end;
begin
Code:=cy_open(2,0,Name'Address,Name'Length,Version'Address,Version'Length,Robot'Access);
loop
Code:=cy_session_next(Robot,Event'Access);
if Code=CY_E_INTERNAL then Code:=cy_session_send(Robot);exit when Code<0;
else
exit when Code/=CY_OK or else Event=CY_EVENT_END;
if Event=CY_EVENT_STATE then
Code:=cy_me_heading(Robot,Heading'Access);
if cy_sensors_nearest(Robot,Target'Access)/=CY_OK then
Code:=cy_drive_throttle(Robot,0.75);Code:=cy_drive_turn(Robot,0.25);
Code:=cy_scanner_heading(Robot,Heading);Code:=cy_scanner_arc(Robot,40.0);
Code:=cy_scanner_last(Robot,Last'Access);Show("SEARCH",Last.Arc);
else
Code:=cy_gun_power_for_flight_time(Robot,Target.Range_Value,1.0,Power'Access);
if cy_gun_lead(Robot,Target'Access,Power,Aim'Access)/=CY_OK then Aim.Heading:=Target.Bearing;Aim.Pitch:=Target.Elevation;end if;
Code:=cy_gun_aim_heading(Robot,Aim.Heading);Code:=cy_gun_aim_pitch(Robot,Aim.Pitch);
Code:=cy_gun_can_fire(Robot,Power,10.0,Can_Fire'Access);
if Can_Fire/=0 then Code:=cy_gun_fire(Robot);Code:=cy_gun_power(Robot,Power);end if;
Code:=cy_angles_angle_diff(Target.Bearing,Heading,Delta_Value'Access);Code:=cy_angles_clamp(Delta_Value,-1.0,1.0,Control'Access);
Code:=cy_drive_throttle(Robot,0.5);Code:=cy_drive_turn(Robot,Control);
Code:=cy_scanner_heading(Robot,Target.Bearing);Code:=cy_scanner_arc(Robot,10.0);
Show("TRACK",Target.Range_Value);
end if;
end if;
Code:=cy_session_send(Robot);exit when Code<0;
end if;
end loop;
cy_close(Robot);
end Bot;
make test exercises every generated Ada declaration against the core's
conformance vectors, checking argument and record marshalling, exact numeric
bits and serialized acts.
Names
Every entry of the robot API 2.0.0 in Ada. names.md has every language side by side.
| Canonical | Form | Ada |
|---|---|---|
match.mode |
property | cy_match_mode |
match.ruleset |
property | cy_match_ruleset |
match.control |
property | cy_match_control |
match.robots |
property | cy_match_robots |
match.is_3d |
property | cy_match_is_3d |
match.tick_rate |
property | cy_match_tick_rate |
match.max_ticks |
property | cy_match_max_ticks |
match.robot_id |
call | cy_robot_id |
clock.tick |
property | cy_clock_tick |
clock.seconds |
property | cy_clock_seconds |
clock.remaining_ticks |
property | cy_clock_remaining_ticks |
arena.size |
property | cy_arena_size |
arena.gravity |
property | cy_arena_gravity |
arena.terrain_kind |
property | cy_arena_terrain_kind |
arena.ground_height |
call | cy_arena_ground_height |
me.health |
property | cy_me_health |
me.position |
property | cy_me_position |
me.velocity |
property | cy_me_velocity |
me.heading |
property | cy_me_heading |
me.pitch |
property | cy_me_pitch |
me.roll |
property | cy_me_roll |
me.angular_velocity |
property | cy_me_angular_velocity |
me.attitude |
property | cy_me_attitude |
me.grounded |
property | cy_me_grounded |
me.altitude |
property | cy_me_altitude |
me.applied |
property | cy_me_applied |
battery.charge |
property | cy_battery_charge |
battery.capacity |
property | cy_battery_capacity |
battery.regen |
property | cy_battery_regen |
battery.sustainable_drive |
property | cy_battery_sustainable_drive |
battery.compute |
property | cy_battery_compute |
battery.drive_cost |
call | cy_battery_drive_cost |
drive.hover_lift |
property | cy_drive_hover_lift |
drive.set |
control | cy_drive_throttle, cy_drive_turn, cy_drive_pitch_turn |
drive.forces |
control | cy_drive_thrust, cy_drive_strafe, cy_drive_lift, cy_drive_yaw_torque, cy_drive_pitch_torque, cy_drive_roll_torque, cy_drive_brake |
drive.get |
call | cy_drive_get_throttle, cy_drive_get_turn, cy_drive_get_pitch_turn, cy_drive_get_thrust, cy_drive_get_strafe, cy_drive_get_lift, cy_drive_get_yaw_torque, cy_drive_get_pitch_torque, cy_drive_get_roll_torque, cy_drive_get_brake |
gun.aim_now |
property | cy_gun_aim_now |
gun.cooldown_ticks |
property | cy_gun_cooldown_ticks |
gun.spread |
property | cy_gun_spread |
gun.max_power |
property | cy_gun_max_power |
gun.damage_scale |
property | cy_gun_damage_scale |
gun.can_fire |
call | cy_gun_can_fire |
gun.shot_speed |
call | cy_gun_shot_speed |
gun.shot_cost |
call | cy_gun_shot_cost |
gun.reload_ticks |
call | cy_gun_reload_ticks |
gun.shot_damage |
call | cy_gun_shot_damage |
gun.power_for_speed |
call | cy_gun_power_for_speed |
gun.power_for_flight_time |
call | cy_gun_power_for_flight_time |
gun.lead |
call | cy_gun_lead |
gun.lead_point |
call | cy_gun_lead_point |
gun.aim |
control | cy_gun_aim_heading, cy_gun_aim_pitch |
gun.fire |
control | cy_gun_fire, cy_gun_power |
gun.get |
call | cy_gun_get_aim_heading, cy_gun_get_aim_pitch, cy_gun_get_fire, cy_gun_get_power |
scanner.last |
property | cy_scanner_last |
scanner.proximity_range |
property | cy_scanner_proximity_range |
scanner.reach |
call | cy_scanner_reach |
scanner.arc_for_reach |
call | cy_scanner_arc_for_reach |
scanner.set |
control | cy_scanner_heading, cy_scanner_arc, cy_scanner_pitch |
scanner.get |
call | cy_scanner_get_heading, cy_scanner_get_arc, cy_scanner_get_pitch |
sensors.contacts |
property | cy_sensors_contacts |
sensors.nearest |
property | cy_sensors_nearest |
sensors.cues |
property | cy_sensors_cues |
sensors.contact |
call | cy_sensors_contact |
sensors.position_of |
call | cy_sensors_position_of |
tracker.cue |
property | cy_tracker_cue |
tracker.nearest_bearing_rate |
property | cy_tracker_nearest_bearing_rate |
tracker.velocity |
call | cy_tracker_velocity |
tracker.position |
call | cy_tracker_position |
tracker.last_seen |
call | cy_tracker_last_seen |
tracker.configure |
call | cy_tracker_configure |
nav.zone |
property | cy_nav_zone |
nav.zone.margin |
call | cy_nav_zone_margin |
nav.zone.contains |
call | cy_nav_zone_contains |
nav.zone.distance_from |
call | cy_nav_zone_distance_from |
nav.storm |
property | cy_nav_storm |
nav.storm.margin |
call | cy_nav_storm_margin |
nav.storm.contains |
call | cy_nav_storm_contains |
nav.storm.distance_from |
call | cy_nav_storm_distance_from |
nav.hill |
property | cy_nav_hill |
nav.hill.margin |
call | cy_nav_hill_margin |
nav.hill.contains |
call | cy_nav_hill_contains |
nav.hill.distance_from |
call | cy_nav_hill_distance_from |
nav.pickups |
property | cy_nav_pickups |
nav.nearest_pickup |
call | cy_nav_nearest_pickup |
nav.field_distance |
call | cy_nav_field_distance |
score.me |
property | cy_score_me |
score.best |
property | cy_score_best |
score.armour |
property | cy_score_armour |
angles.normalize |
call | cy_angles_normalize |
angles.angle_diff |
call | cy_angles_angle_diff |
angles.bearing_to |
call | cy_angles_bearing_to |
angles.elevation_to |
call | cy_angles_elevation_to |
angles.direction |
call | cy_angles_direction |
angles.distance |
call | cy_angles_distance |
angles.clamp |
call | cy_angles_clamp |
status.set |
control | cy_status_text, cy_status_value |
status.get |
call | cy_status_get_text, cy_status_get_value |
raw.number |
call | cy_raw_number |
raw.text |
call | cy_raw_text |
raw.has |
call | cy_raw_has |
raw.flag |
call | cy_raw_flag |
raw.count |
call | cy_raw_count |
raw.line |
call | cy_raw_line |
raw.extra |
call | cy_raw_extra |
session.event |
property | cy_session_event |
session.next |
call | cy_session_next |
session.send |
call | cy_session_send |
session.forfeit |
call | cy_session_forfeit |
session.log |
call | cy_session_log |
session.feed |
call | cy_session_feed |
session.reply |
call | cy_session_reply |