<!-- Generated from sdk/bindings/hew/README.md and protocol/v2/api.json by protocol/v2/codegen/docs.js; do not edit. Run `make api`. -->
# The Hew binding

`import hew.clunkyard;` exposes typed records, subsystem methods, `Option`
for absent values and `Vec` for lists. Methods use `fails CoreError` and `?`.
Controls take optional fields: `robot.drive.set(throttle: .Some(0.5))?`
changes the throttle while retaining any turn already set this tick.
`match_info` names the match subsystem because `match` is a Hew keyword.

Install with `make install SDK=/opt/clunkyard/sdk`. Build a robot with
`hew build --release --pkg-path /opt/clunkyard/sdk/bindings/hew/packages --link-lib /opt/clunkyard/sdk/bindings/hew/libclunkyard_hew.a --link-lib /opt/clunkyard/sdk/lib/libclunkyard.a bot.hew -o bot`.
The executable links both the core and Hew runtime statically. The generated
C shim copies native fields through Hew's scalar and bytes FFI; parsing,
tracking, geometry and control decisions stay in the core.

Implement `Strategy.on_turn(var self, robot)` and optionally `on_start`.
`clunkyard.run(strategy)` owns the protocol loop; `clunkyard.play(strategy,
lines)` returns replies from a memory session. Returned strategy errors are
logged and controls already set are sent. Return `error clunkyard.forfeit(
code, message)` for an explicit forfeit. A core fault sends the empty reply
and resumes on the next state. Hew panics terminate the process; use returned
errors for recoverable strategy failures. Keep the robot handle within its
session and let `run` or `play` close it.

## A tiny robot

```hew
import hew.clunkyard;
import hew.clunkyard.{Robot, Strategy, CoreError, Direction};
type Tiny {}
impl Strategy for Tiny {
    fn on_turn(var self, robot: Robot) fails CoreError {
        let target = match robot.sensors.nearest()? {
            .Some(target) => target,
            .None => {
                robot.drive.set(.Some(0.75), .Some(0.25))?;
                robot.scanner.set(.Some(robot.me.heading()?), .Some(40.0))?;
                robot.status.set(.Some("SEARCH"), .Some((robot.scanner.last()?).arc))?;
                return;
            }
        };
        let power = robot.gun.power_for_flight_time(target.range, 1.0)?;
        let aim = match robot.gun.lead(target, power)? {
            .Some(aim) => Direction { heading: aim.heading, pitch: aim.pitch },
            .None => Direction { heading: target.bearing, pitch: target.elevation },
        };
        robot.gun.aim(.Some(aim.heading), .Some(aim.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()?)?)?))?;
        robot.scanner.set(.Some(target.bearing), .Some(10.0))?;
        robot.status.set(.Some("TRACK"), .Some(target.range))?;
    }
}
fn main() { let _ = clunkyard.run(Tiny {}); }
```

`make test` checks every generated Hew method against the core's full vectors,
including typed arguments, records, optional values, lists, text, exact
floating-point results and serialized acts.

## Names

Every entry of the robot API 2.0.0 in Hew.
[names.md](names.md) has every language side by side.

| Canonical | Form | Hew |
| --- | --- | --- |
| `match.mode` | property | match_info.mode() |
| `match.ruleset` | property | match_info.ruleset() |
| `match.control` | property | match_info.control() |
| `match.robots` | property | match_info.robots() |
| `match.is_3d` | property | match_info.is_3d() |
| `match.tick_rate` | property | match_info.tick_rate() |
| `match.max_ticks` | property | match_info.max_ticks() |
| `match.robot_id` | call | match_info.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_<field>() |
| `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_<field>() |
| `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_<field>() |
| `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_<field>() |
| `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() |
