The Mercury binding

clunkyard exposes the native API as deterministic IO predicates. Inputs come first, followed by the status and the IO state. Copy-out arguments use typed references: allocate with new_float_ref, call the core predicate, then use read_float_ref. check(Robot, Status, !IO) throws the core's error text for a negative status; cy_none means absent.

Native record types are opaque and owned by Mercury's collector. Allocate with new_contact or new_contact_array(Count, ...), then read fields with predicates such as contact_range. contact_at selects an element of an array. set_vec3 and the other record constructors accept every field in schema order. References and record views must stay within their allocated capacity. Buffers preserve explicit byte lengths, including embedded NUL: text_buffer copies a string, while new_buffer and buffer_set_byte construct arbitrary UTF-8 bytes. buffer_text copies a returned text value.

Install with make install SDK=/opt/clunkyard/sdk. Build in the source directory with mmc --make --mld /opt/clunkyard/sdk/bindings/mercury/lib/mercury --ml clunkyard --mercury-linkage static --c-include-directory /opt/clunkyard/sdk/include --ld-flags -Wl,--whole-archive,/opt/clunkyard/sdk/lib/libclunkyard.a,--no-whole-archive -l pthread -l dl -l m bot. The core and Mercury runtime link statically; the artifact carries the executable. The archive flags make core symbols available before Mercury's library is linked.

run(Turn, Start, !IO) owns the session and protocol loop. Callbacks receive the core handle and IO state. Exceptions are logged and the turn sends any controls already set; forfeit(Code, Message) makes an explicit forfeit. A core fault sends the empty reply and continues. play(Lines, Turn, Start, Replies, !IO) runs a memory session.

A tiny robot

:- module bot.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module clunkyard, int.
:- pred set(pred(robot, float, int, io, io)::in(pred(in, in, out, di, uo) is det), robot::in, float::in, io::di, io::uo) is det.
set(Control, R, Value, !IO) :- Control(R, Value, Status, !IO), check(R, Status, !IO).
:- pred status(robot::in, string::in, float::in, io::di, io::uo) is det.
status(R, Text, Value, !IO) :- text_buffer(Text, Bytes, Length, !IO), cy_status_text(R, Bytes, Length, S, !IO), check(R, S, !IO), set(cy_status_value, R, Value, !IO).
:- pred start(robot::in, io::di, io::uo) is det.
start(_, !IO).
:- pred turn(robot::in, io::di, io::uo) is det.
turn(R, !IO) :-
    new_contact(Target, !IO), cy_sensors_nearest(R, Target, Found, !IO),
    new_float_ref(Number, !IO), cy_me_heading(R, Number, HS, !IO), check(R, HS, !IO), read_float_ref(Number, Heading, !IO),
    (if Found = cy_ok then
        contact_range(Target, Range, !IO), contact_bearing(Target, Bearing, !IO), contact_elevation(Target, Elevation, !IO),
        cy_gun_power_for_flight_time(R, Range, 1.0, Number, PS, !IO), check(R, PS, !IO), read_float_ref(Number, Power, !IO),
        new_solution(Aim, !IO), cy_gun_lead(R, Target, Power, Aim, AS, !IO),
        (if AS = cy_ok then solution_heading(Aim, AH, !IO), solution_pitch(Aim, AP, !IO) else AH = Bearing, AP = Elevation),
        set(cy_gun_aim_heading, R, AH, !IO), set(cy_gun_aim_pitch, R, AP, !IO),
        new_int_ref(Fire, !IO), cy_gun_can_fire(R, Power, 10.0, Fire, FS, !IO), check(R, FS, !IO), read_int_ref(Fire, CanFire, !IO),
        (if CanFire \= 0 then cy_gun_fire(R, Fired, !IO), check(R, Fired, !IO), set(cy_gun_power, R, Power, !IO) else true),
        cy_angles_angle_diff(Bearing, Heading, Number, DS, !IO), check(R, DS, !IO), read_float_ref(Number, Delta, !IO),
        cy_angles_clamp(Delta, -1.0, 1.0, Number, CS, !IO), check(R, CS, !IO), read_float_ref(Number, Control, !IO),
        set(cy_drive_throttle, R, 0.5, !IO), set(cy_drive_turn, R, Control, !IO),
        set(cy_scanner_heading, R, Bearing, !IO), set(cy_scanner_arc, R, 10.0, !IO), status(R, "TRACK", Range, !IO)
    else
        set(cy_drive_throttle, R, 0.75, !IO), set(cy_drive_turn, R, 0.25, !IO),
        set(cy_scanner_heading, R, Heading, !IO), set(cy_scanner_arc, R, 40.0, !IO),
        new_scan(Last, !IO), cy_scanner_last(R, Last, LS, !IO), check(R, LS, !IO), scan_arc(Last, Arc, !IO), status(R, "SEARCH", Arc, !IO)
    ).
main(!IO) :- run(turn, start, !IO).

make test checks every generated Mercury predicate against the core's full vectors, including typed foreign arguments and records, exact floating-point results and serialized acts.

Names

Every entry of the robot API 2.0.0 in Mercury. names.md has every language side by side.

Canonical Form Mercury
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

Download this page as Markdown