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

The generated Perl API uses a compiled XS bridge to the robot core.
Subsystems are objects, records are hash references, and controls take named
fields. Region records also expose their core methods. Absent results are
`undef`. Later controls merge with earlier ones in the same tick.

Install with `make install SDK=/opt/clunkyard/sdk`. Run with
`PERL5LIB=/opt/clunkyard/sdk/bindings/perl perl bot.pl`. The bridge loads
`libclunkyard.so.2`; no compiler is needed at run time.

## A tiny robot

```perl
use strict;
use warnings;
use Clunkyard;
package Tiny;
use parent -norequire, 'Clunkyard::Robot';
sub on_turn {
  my($self)=@_;my$target=$self->sensors->nearest;
  if(!defined$target){
    $self->drive->set(throttle=>0.75,turn=>0.25);
    $self->scanner->set(heading=>$self->me->heading,arc=>40);
    $self->status->set(text=>'SEARCH',value=>$self->scanner->last->{arc});
    return;
  }
  my$power=$self->gun->power_for_flight_time($target->{range},1);
  my$aim=$self->gun->lead($target,$power);
  $self->gun->aim(heading=>$aim?$aim->{heading}:$target->{bearing},pitch=>$aim?$aim->{pitch}:$target->{elevation});
  $self->gun->fire(power=>$power)if$self->gun->can_fire($power,10);
  $self->drive->set(throttle=>0.5,turn=>Clunkyard::angles()->clamp(Clunkyard::angles()->angle_diff($target->{bearing},$self->me->heading)));
  $self->scanner->set(heading=>$target->{bearing},arc=>10);
  $self->status->set(text=>'TRACK',value=>$target->{range});
}
package main;
Clunkyard::run(Tiny->new);
```

`make test SDK=...` checks the actual generated API against every core
vector, including exact floating-point results and act lines. Core errors
raise a language error carrying their status. A core fault during input
sends its empty act and continues with the next state. User exceptions are
logged and send the controls already set. Use the binding’s forfeit helper
to give up a match; `play` runs protocol lines in memory for tests.

## Names

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

| Canonical | Form | Perl |
| --- | --- | --- |
| `match.mode` | property | $robot->match->mode |
| `match.ruleset` | property | $robot->match->ruleset |
| `match.control` | property | $robot->match->control |
| `match.robots` | property | $robot->match->robots |
| `match.is_3d` | property | $robot->match->is_3d |
| `match.tick_rate` | property | $robot->match->tick_rate |
| `match.max_ticks` | property | $robot->match->max_ticks |
| `match.robot_id` | call | $robot->match->robot_id |
| `clock.tick` | property | $robot->clock->tick |
| `clock.seconds` | property | $robot->clock->seconds |
| `clock.remaining_ticks` | property | $robot->clock->remaining_ticks |
| `arena.size` | property | $robot->arena->size |
| `arena.gravity` | property | $robot->arena->gravity |
| `arena.terrain_kind` | property | $robot->arena->terrain_kind |
| `arena.ground_height` | call | $robot->arena->ground_height |
| `me.health` | property | $robot->me->health |
| `me.position` | property | $robot->me->position |
| `me.velocity` | property | $robot->me->velocity |
| `me.heading` | property | $robot->me->heading |
| `me.pitch` | property | $robot->me->pitch |
| `me.roll` | property | $robot->me->roll |
| `me.angular_velocity` | property | $robot->me->angular_velocity |
| `me.attitude` | property | $robot->me->attitude |
| `me.grounded` | property | $robot->me->grounded |
| `me.altitude` | property | $robot->me->altitude |
| `me.applied` | property | $robot->me->applied |
| `battery.charge` | property | $robot->battery->charge |
| `battery.capacity` | property | $robot->battery->capacity |
| `battery.regen` | property | $robot->battery->regen |
| `battery.sustainable_drive` | property | $robot->battery->sustainable_drive |
| `battery.compute` | property | $robot->battery->compute |
| `battery.drive_cost` | call | $robot->battery->drive_cost |
| `drive.hover_lift` | property | $robot->drive->hover_lift |
| `drive.set` | control | $robot->drive->set |
| `drive.forces` | control | $robot->drive->forces |
| `drive.get` | call | $robot->drive->get |
| `gun.aim_now` | property | $robot->gun->aim_now |
| `gun.cooldown_ticks` | property | $robot->gun->cooldown_ticks |
| `gun.spread` | property | $robot->gun->spread |
| `gun.max_power` | property | $robot->gun->max_power |
| `gun.damage_scale` | property | $robot->gun->damage_scale |
| `gun.can_fire` | call | $robot->gun->can_fire |
| `gun.shot_speed` | call | $robot->gun->shot_speed |
| `gun.shot_cost` | call | $robot->gun->shot_cost |
| `gun.reload_ticks` | call | $robot->gun->reload_ticks |
| `gun.shot_damage` | call | $robot->gun->shot_damage |
| `gun.power_for_speed` | call | $robot->gun->power_for_speed |
| `gun.power_for_flight_time` | call | $robot->gun->power_for_flight_time |
| `gun.lead` | call | $robot->gun->lead |
| `gun.lead_point` | call | $robot->gun->lead_point |
| `gun.aim` | control | $robot->gun->aim |
| `gun.fire` | control | $robot->gun->fire |
| `gun.get` | call | $robot->gun->get |
| `scanner.last` | property | $robot->scanner->last |
| `scanner.proximity_range` | property | $robot->scanner->proximity_range |
| `scanner.reach` | call | $robot->scanner->reach |
| `scanner.arc_for_reach` | call | $robot->scanner->arc_for_reach |
| `scanner.set` | control | $robot->scanner->set |
| `scanner.get` | call | $robot->scanner->get |
| `sensors.contacts` | property | $robot->sensors->contacts |
| `sensors.nearest` | property | $robot->sensors->nearest |
| `sensors.cues` | property | $robot->sensors->cues |
| `sensors.contact` | call | $robot->sensors->contact |
| `sensors.position_of` | call | $robot->sensors->position_of |
| `tracker.cue` | property | $robot->tracker->cue |
| `tracker.nearest_bearing_rate` | property | $robot->tracker->nearest_bearing_rate |
| `tracker.velocity` | call | $robot->tracker->velocity |
| `tracker.position` | call | $robot->tracker->position |
| `tracker.last_seen` | call | $robot->tracker->last_seen |
| `tracker.configure` | call | $robot->tracker->configure |
| `nav.zone` | property | $robot->nav->zone |
| `nav.zone.margin` | call | $robot->nav->zone->margin |
| `nav.zone.contains` | call | $robot->nav->zone->contains |
| `nav.zone.distance_from` | call | $robot->nav->zone->distance_from |
| `nav.storm` | property | $robot->nav->storm |
| `nav.storm.margin` | call | $robot->nav->storm->margin |
| `nav.storm.contains` | call | $robot->nav->storm->contains |
| `nav.storm.distance_from` | call | $robot->nav->storm->distance_from |
| `nav.hill` | property | $robot->nav->hill |
| `nav.hill.margin` | call | $robot->nav->hill->margin |
| `nav.hill.contains` | call | $robot->nav->hill->contains |
| `nav.hill.distance_from` | call | $robot->nav->hill->distance_from |
| `nav.pickups` | property | $robot->nav->pickups |
| `nav.nearest_pickup` | call | $robot->nav->nearest_pickup |
| `nav.field_distance` | call | $robot->nav->field_distance |
| `score.me` | property | $robot->score->me |
| `score.best` | property | $robot->score->best |
| `score.armour` | property | $robot->score->armour |
| `angles.normalize` | call | $robot->angles->normalize |
| `angles.angle_diff` | call | $robot->angles->angle_diff |
| `angles.bearing_to` | call | $robot->angles->bearing_to |
| `angles.elevation_to` | call | $robot->angles->elevation_to |
| `angles.direction` | call | $robot->angles->direction |
| `angles.distance` | call | $robot->angles->distance |
| `angles.clamp` | call | $robot->angles->clamp |
| `status.set` | control | $robot->status->set |
| `status.get` | call | $robot->status->get |
| `raw.number` | call | $robot->raw->number |
| `raw.text` | call | $robot->raw->text |
| `raw.has` | call | $robot->raw->has |
| `raw.flag` | call | $robot->raw->flag |
| `raw.count` | call | $robot->raw->count |
| `raw.line` | call | $robot->raw->line |
| `raw.extra` | call | $robot->raw->extra |
| `session.event` | property | $robot->session->event |
| `session.next` | call | $robot->session->next |
| `session.send` | call | $robot->session->send |
| `session.forfeit` | call | $robot->session->forfeit |
| `session.log` | call | $robot->session->log |
| `session.feed` | call | $robot->session->feed |
| `session.reply` | call | $robot->session->reply |
