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

GNU APL runs one persistent process for a match, with generated `Cy*`
functions calling the Python binding's shared core through a synchronous
pipe. Protocol parsing, tracking, geometry and act serialization stay in
the core. The adapter does not spawn a process per turn.

Install with `make install SDK=/opt/clunkyard/sdk`. Put a tactic beside this
launcher, and run it with `PYTHONPATH` containing both `bindings/python`
and `bindings/apl` from that SDK:

```python
import clunkyard_apl
clunkyard_apl.run("tactic.apl")
```

The tactic defines niladic `OnTurn` and optional `OnStart`. Every API entry
has a generated monadic function, such as `CyGunLead` or `CyMatchIs3d`.
Pass no arguments as `⍬`, text arguments enclosed (`⊂'text'`), and records
flattened in their generated field order. Records have generated accessors,
such as `CyContactRange`; record lists begin with the count. Optional
absence returns `⍬` and sets `CyPresent` to zero, so absent text differs
from present empty text. Numeric values travel as binary GNU APL Common
Data Representation, preserving floating-point bits rather than formatted
decimal text. Controls also have named convenience functions such as
`CyDriveThrottle` and `CyGunFirePower`.

APL errors and core errors are logged by the Python run loop, which sends
the controls already set. `CySessionForfeit` takes enclosed code and
message strings. `clunkyard_apl.play(tactic,lines)` plays a memory session.

## A tiny robot

```apl
∇OnTurn;T;POWER;A;H;P;S
 T←CySensorsNearest ⍬ ⋄ →(0≠⍴T)/TRACK
 CyDriveThrottle 0.75 ⋄ CyDriveTurn 0.25
 CyScannerHeading CyMeHeading ⍬ ⋄ CyScannerArc 40
 CyStatusText 'SEARCH' ⋄ CyStatusValue CyScanArc CyScannerLast ⍬ ⋄ →0
 TRACK: POWER←CyGunPowerForFlightTime (CyContactRange T),1
 A←CyGunLead T,POWER ⋄ H←CyContactBearing T ⋄ P←CyContactElevation T
 →(0=⍴A)/AIM ⋄ H←CySolutionHeading A ⋄ P←CySolutionPitch A
 AIM: CyGunAimHeading H ⋄ CyGunAimPitch P
 →(~CyGunCanFire POWER 10)/DRIVE ⋄ CyGunFirePower POWER
 DRIVE: CyDriveThrottle 0.5
 CyDriveTurn CyAnglesClamp (CyAnglesAngleDiff (CyContactBearing T),CyMeHeading ⍬),¯1 1
 CyScannerHeading CyContactBearing T ⋄ CyScannerArc 10
 CyStatusText 'TRACK' ⋄ CyStatusValue CyContactRange T
∇
```

Save that tactic as `tiny.apl` beside this launcher:

```python
import clunkyard_apl
clunkyard_apl.run("tiny.apl")
```

`make test SDK=...` traverses the generated APL functions for every API
vector and compares their actual APL values with the core transcript.

## Names

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

| Canonical | Form | APL |
| --- | --- | --- |
| `match.mode` | property | CyMatchMode args |
| `match.ruleset` | property | CyMatchRuleset args |
| `match.control` | property | CyMatchControl args |
| `match.robots` | property | CyMatchRobots args |
| `match.is_3d` | property | CyMatchIs3d args |
| `match.tick_rate` | property | CyMatchTickRate args |
| `match.max_ticks` | property | CyMatchMaxTicks args |
| `match.robot_id` | call | CyMatchRobotId args |
| `clock.tick` | property | CyClockTick args |
| `clock.seconds` | property | CyClockSeconds args |
| `clock.remaining_ticks` | property | CyClockRemainingTicks args |
| `arena.size` | property | CyArenaSize args |
| `arena.gravity` | property | CyArenaGravity args |
| `arena.terrain_kind` | property | CyArenaTerrainKind args |
| `arena.ground_height` | call | CyArenaGroundHeight args |
| `me.health` | property | CyMeHealth args |
| `me.position` | property | CyMePosition args |
| `me.velocity` | property | CyMeVelocity args |
| `me.heading` | property | CyMeHeading args |
| `me.pitch` | property | CyMePitch args |
| `me.roll` | property | CyMeRoll args |
| `me.angular_velocity` | property | CyMeAngularVelocity args |
| `me.attitude` | property | CyMeAttitude args |
| `me.grounded` | property | CyMeGrounded args |
| `me.altitude` | property | CyMeAltitude args |
| `me.applied` | property | CyMeApplied args |
| `battery.charge` | property | CyBatteryCharge args |
| `battery.capacity` | property | CyBatteryCapacity args |
| `battery.regen` | property | CyBatteryRegen args |
| `battery.sustainable_drive` | property | CyBatterySustainableDrive args |
| `battery.compute` | property | CyBatteryCompute args |
| `battery.drive_cost` | call | CyBatteryDriveCost args |
| `drive.hover_lift` | property | CyDriveHoverLift args |
| `drive.set` | control | CyDriveSet args |
| `drive.forces` | control | CyDriveForces args |
| `drive.get` | call | CyDriveGet args |
| `gun.aim_now` | property | CyGunAimNow args |
| `gun.cooldown_ticks` | property | CyGunCooldownTicks args |
| `gun.spread` | property | CyGunSpread args |
| `gun.max_power` | property | CyGunMaxPower args |
| `gun.damage_scale` | property | CyGunDamageScale args |
| `gun.can_fire` | call | CyGunCanFire args |
| `gun.shot_speed` | call | CyGunShotSpeed args |
| `gun.shot_cost` | call | CyGunShotCost args |
| `gun.reload_ticks` | call | CyGunReloadTicks args |
| `gun.shot_damage` | call | CyGunShotDamage args |
| `gun.power_for_speed` | call | CyGunPowerForSpeed args |
| `gun.power_for_flight_time` | call | CyGunPowerForFlightTime args |
| `gun.lead` | call | CyGunLead args |
| `gun.lead_point` | call | CyGunLeadPoint args |
| `gun.aim` | control | CyGunAim args |
| `gun.fire` | control | CyGunFire args |
| `gun.get` | call | CyGunGet args |
| `scanner.last` | property | CyScannerLast args |
| `scanner.proximity_range` | property | CyScannerProximityRange args |
| `scanner.reach` | call | CyScannerReach args |
| `scanner.arc_for_reach` | call | CyScannerArcForReach args |
| `scanner.set` | control | CyScannerSet args |
| `scanner.get` | call | CyScannerGet args |
| `sensors.contacts` | property | CySensorsContacts args |
| `sensors.nearest` | property | CySensorsNearest args |
| `sensors.cues` | property | CySensorsCues args |
| `sensors.contact` | call | CySensorsContact args |
| `sensors.position_of` | call | CySensorsPositionOf args |
| `tracker.cue` | property | CyTrackerCue args |
| `tracker.nearest_bearing_rate` | property | CyTrackerNearestBearingRate args |
| `tracker.velocity` | call | CyTrackerVelocity args |
| `tracker.position` | call | CyTrackerPosition args |
| `tracker.last_seen` | call | CyTrackerLastSeen args |
| `tracker.configure` | call | CyTrackerConfigure args |
| `nav.zone` | property | CyNavZone args |
| `nav.zone.margin` | call | CyNavZoneMargin args |
| `nav.zone.contains` | call | CyNavZoneContains args |
| `nav.zone.distance_from` | call | CyNavZoneDistanceFrom args |
| `nav.storm` | property | CyNavStorm args |
| `nav.storm.margin` | call | CyNavStormMargin args |
| `nav.storm.contains` | call | CyNavStormContains args |
| `nav.storm.distance_from` | call | CyNavStormDistanceFrom args |
| `nav.hill` | property | CyNavHill args |
| `nav.hill.margin` | call | CyNavHillMargin args |
| `nav.hill.contains` | call | CyNavHillContains args |
| `nav.hill.distance_from` | call | CyNavHillDistanceFrom args |
| `nav.pickups` | property | CyNavPickups args |
| `nav.nearest_pickup` | call | CyNavNearestPickup args |
| `nav.field_distance` | call | CyNavFieldDistance args |
| `score.me` | property | CyScoreMe args |
| `score.best` | property | CyScoreBest args |
| `score.armour` | property | CyScoreArmour args |
| `angles.normalize` | call | CyAnglesNormalize args |
| `angles.angle_diff` | call | CyAnglesAngleDiff args |
| `angles.bearing_to` | call | CyAnglesBearingTo args |
| `angles.elevation_to` | call | CyAnglesElevationTo args |
| `angles.direction` | call | CyAnglesDirection args |
| `angles.distance` | call | CyAnglesDistance args |
| `angles.clamp` | call | CyAnglesClamp args |
| `status.set` | control | CyStatusSet args |
| `status.get` | call | CyStatusGet args |
| `raw.number` | call | CyRawNumber args |
| `raw.text` | call | CyRawText args |
| `raw.has` | call | CyRawHas args |
| `raw.flag` | call | CyRawFlag args |
| `raw.count` | call | CyRawCount args |
| `raw.line` | call | CyRawLine args |
| `raw.extra` | call | CyRawExtra args |
| `session.event` | property | CySessionEvent args |
| `session.next` | call | CySessionNext args |
| `session.send` | call | CySessionSend args |
| `session.forfeit` | call | CySessionForfeit args |
| `session.log` | call | CySessionLog args |
| `session.feed` | call | CySessionFeed args |
| `session.reply` | call | CySessionReply args |
