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

The Clunkyard robot API in COBOL, through a generated, logic-free layer over
the robot core's C ABI ([docs/design/robot-core.md](../design/robot-core.md),
section 5.3). `clunkyard.cpy` and `clunkyard_cobol.c` are generated by
`protocol/v2/codegen/bindings/cobol.js` (`make api`); nothing here is written
by hand but the Makefile and the test's fixed C, `test/support.c`.

- **Install:** `make install SDK=/opt/clunkyard/sdk` puts the copybook and the
  compiled layer, `clunkyard_cobol.o`, in `$(SDK)/bindings/cobol`.
- **Build:** `cobc -x -free -I/opt/clunkyard/sdk/bindings/cobol bot.cob
  /opt/clunkyard/sdk/bindings/cobol/clunkyard_cobol.o
  /opt/clunkyard/sdk/lib/libclunkyard.a -lm`. The core links statically.
- **Test:** `make test SDK=...` builds the generated conformance program on the
  installed layer and runs it against every API vector, exact against the core.

`CALL "CY-READ" USING CY-GAME CY-STATE` reads one message a turn and fills
both records: every fact is `CY-<SUBSYSTEM>-<MEMBER>` (`CY-ME-HEADING`,
`CY-SCANNER-LAST-ARC`, `CY-SENSORS-NEAREST-RANGE`), with an 88-level
`-FOUND` or `-NONE` beside it, and a list has `-COUNT` and a table.
`CY-SESSION-EVENT-HELLO`, `-STATE` and `-END` say what was read, and
`CALL "CY-SEND"` answers it. Every other core function is a by-reference
`CALL` under its C name in COBOL case, with no handle and the result in the
last argument: `CALL "CY-GUN-LEAD" USING CY-SENSORS-NEAREST SHOT-POWER CY-SOLUTION`.
`RETURN-CODE` is the core's status, 0 for found and 1 for none
(`CY-OK`, `CY-NONE`). Each control field is its own call
(`CALL "CY-DRIVE-TURN" USING TURN`), so only the fields called are set. Text
in is NUL-terminated (`Z"TRACK"`). The layer's names are in COBOL case
because the core's own C names (`cy_gun_fire`) are taken by its by-value
functions.

COBOL's own `COMPUTE` on `COMP-2` is not IEEE arithmetic, so a robot that
must match the other languages to the bit asks the core (`CY-ANGLES-...`).

## A tiny robot

```cobol
IDENTIFICATION DIVISION.
PROGRAM-ID. TINY.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY "clunkyard.cpy".
01 ONE-SECOND USAGE COMP-2 VALUE 1.
01 SHOT-RESERVE USAGE COMP-2 VALUE 10.
01 SEARCH-THROTTLE USAGE COMP-2 VALUE 0.75.
01 SEARCH-TURN USAGE COMP-2 VALUE 0.25.
01 SEARCH-ARC USAGE COMP-2 VALUE 40.
01 TRACK-THROTTLE USAGE COMP-2 VALUE 0.5.
01 TRACK-ARC USAGE COMP-2 VALUE 10.
01 TURN-LOW USAGE COMP-2 VALUE -1.
01 TURN-HIGH USAGE COMP-2 VALUE 1.
01 SHOT-POWER USAGE COMP-2.
01 OFF-BEARING USAGE COMP-2.
01 TURN USAGE COMP-2.
01 CAN-FIRE PIC S9(9) COMP-5.
PROCEDURE DIVISION.
    PERFORM UNTIL CY-SESSION-EVENT-END
        CALL "CY-READ" USING CY-GAME CY-STATE
        IF RETURN-CODE < 0
            STOP RUN
        END-IF
        EVALUATE TRUE
            WHEN CY-SESSION-EVENT-HELLO CALL "CY-SEND"
            WHEN CY-SESSION-EVENT-STATE PERFORM TAKE-TURN CALL "CY-SEND"
        END-EVALUATE
    END-PERFORM
    STOP RUN.
TAKE-TURN.
    IF CY-SENSORS-NEAREST-NONE
        CALL "CY-DRIVE-THROTTLE" USING SEARCH-THROTTLE
        CALL "CY-DRIVE-TURN" USING SEARCH-TURN
        CALL "CY-SCANNER-HEADING" USING CY-ME-HEADING
        CALL "CY-SCANNER-ARC" USING SEARCH-ARC
        CALL "CY-STATUS-TEXT" USING Z"SEARCH"
        CALL "CY-STATUS-VALUE" USING CY-SCANNER-LAST-ARC
        EXIT PARAGRAPH
    END-IF
    CALL "CY-GUN-POWER-FOR-FLIGHT-TIME" USING CY-SENSORS-NEAREST-RANGE ONE-SECOND SHOT-POWER
    CALL "CY-GUN-LEAD" USING CY-SENSORS-NEAREST SHOT-POWER CY-SOLUTION
    IF RETURN-CODE = CY-OK
        CALL "CY-GUN-AIM-HEADING" USING CY-SOLUTION-HEADING
        CALL "CY-GUN-AIM-PITCH" USING CY-SOLUTION-PITCH
    ELSE
        CALL "CY-GUN-AIM-HEADING" USING CY-SENSORS-NEAREST-BEARING
        CALL "CY-GUN-AIM-PITCH" USING CY-SENSORS-NEAREST-ELEVATION
    END-IF
    CALL "CY-GUN-CAN-FIRE" USING SHOT-POWER SHOT-RESERVE CAN-FIRE
    IF CAN-FIRE = 1
        CALL "CY-GUN-FIRE"
        CALL "CY-GUN-POWER" USING SHOT-POWER
    END-IF
    CALL "CY-ANGLES-ANGLE-DIFF" USING CY-SENSORS-NEAREST-BEARING CY-ME-HEADING OFF-BEARING
    CALL "CY-ANGLES-CLAMP" USING OFF-BEARING TURN-LOW TURN-HIGH TURN
    CALL "CY-DRIVE-THROTTLE" USING TRACK-THROTTLE
    CALL "CY-DRIVE-TURN" USING TURN
    CALL "CY-SCANNER-HEADING" USING CY-SENSORS-NEAREST-BEARING
    CALL "CY-SCANNER-ARC" USING TRACK-ARC
    CALL "CY-STATUS-TEXT" USING Z"TRACK"
    CALL "CY-STATUS-VALUE" USING CY-SENSORS-NEAREST-RANGE.
```

## Names

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

| Canonical | Form | COBOL |
| --- | --- | --- |
| `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 | `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 | `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 | `CALL "CY-BATTERY-DRIVE-COST"` |
| `drive.hover_lift` | property | `CY-DRIVE-HOVER-LIFT` |
| `drive.set` | control | `CALL "CY-DRIVE-THROTTLE"`, `CALL "CY-DRIVE-TURN"`, … |
| `drive.forces` | control | `CALL "CY-DRIVE-THRUST"`, `CALL "CY-DRIVE-STRAFE"`, … |
| `drive.get` | call | `CALL "CY-DRIVE-GET-THROTTLE"`, `CALL "CY-DRIVE-GET-TURN"`, … |
| `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 | `CALL "CY-GUN-CAN-FIRE"` |
| `gun.shot_speed` | call | `CALL "CY-GUN-SHOT-SPEED"` |
| `gun.shot_cost` | call | `CALL "CY-GUN-SHOT-COST"` |
| `gun.reload_ticks` | call | `CALL "CY-GUN-RELOAD-TICKS"` |
| `gun.shot_damage` | call | `CALL "CY-GUN-SHOT-DAMAGE"` |
| `gun.power_for_speed` | call | `CALL "CY-GUN-POWER-FOR-SPEED"` |
| `gun.power_for_flight_time` | call | `CALL "CY-GUN-POWER-FOR-FLIGHT-TIME"` |
| `gun.lead` | call | `CALL "CY-GUN-LEAD"` |
| `gun.lead_point` | call | `CALL "CY-GUN-LEAD-POINT"` |
| `gun.aim` | control | `CALL "CY-GUN-AIM-HEADING"`, `CALL "CY-GUN-AIM-PITCH"` |
| `gun.fire` | control | `CALL "CY-GUN-FIRE"`, `CALL "CY-GUN-POWER"` |
| `gun.get` | call | `CALL "CY-GUN-GET-AIM-HEADING"`, `CALL "CY-GUN-GET-AIM-PITCH"`, … |
| `scanner.last` | property | `CY-SCANNER-LAST` |
| `scanner.proximity_range` | property | `CY-SCANNER-PROXIMITY-RANGE` |
| `scanner.reach` | call | `CALL "CY-SCANNER-REACH"` |
| `scanner.arc_for_reach` | call | `CALL "CY-SCANNER-ARC-FOR-REACH"` |
| `scanner.set` | control | `CALL "CY-SCANNER-HEADING"`, `CALL "CY-SCANNER-ARC"`, … |
| `scanner.get` | call | `CALL "CY-SCANNER-GET-HEADING"`, `CALL "CY-SCANNER-GET-ARC"`, … |
| `sensors.contacts` | property | `CY-SENSORS-CONTACTS` |
| `sensors.nearest` | property | `CY-SENSORS-NEAREST` |
| `sensors.cues` | property | `CY-SENSORS-CUES` |
| `sensors.contact` | call | `CALL "CY-SENSORS-CONTACT"` |
| `sensors.position_of` | call | `CALL "CY-SENSORS-POSITION-OF"` |
| `tracker.cue` | property | `CY-TRACKER-CUE` |
| `tracker.nearest_bearing_rate` | property | `CY-TRACKER-NEAREST-BEARING-RATE` |
| `tracker.velocity` | call | `CALL "CY-TRACKER-VELOCITY"` |
| `tracker.position` | call | `CALL "CY-TRACKER-POSITION"` |
| `tracker.last_seen` | call | `CALL "CY-TRACKER-LAST-SEEN"` |
| `tracker.configure` | call | `CALL "CY-TRACKER-CONFIGURE"` |
| `nav.zone` | property | `CY-NAV-ZONE` |
| `nav.zone.margin` | call | `CALL "CY-NAV-ZONE-MARGIN"` |
| `nav.zone.contains` | call | `CALL "CY-NAV-ZONE-CONTAINS"` |
| `nav.zone.distance_from` | call | `CALL "CY-NAV-ZONE-DISTANCE-FROM"` |
| `nav.storm` | property | `CY-NAV-STORM` |
| `nav.storm.margin` | call | `CALL "CY-NAV-STORM-MARGIN"` |
| `nav.storm.contains` | call | `CALL "CY-NAV-STORM-CONTAINS"` |
| `nav.storm.distance_from` | call | `CALL "CY-NAV-STORM-DISTANCE-FROM"` |
| `nav.hill` | property | `CY-NAV-HILL` |
| `nav.hill.margin` | call | `CALL "CY-NAV-HILL-MARGIN"` |
| `nav.hill.contains` | call | `CALL "CY-NAV-HILL-CONTAINS"` |
| `nav.hill.distance_from` | call | `CALL "CY-NAV-HILL-DISTANCE-FROM"` |
| `nav.pickups` | property | `CY-NAV-PICKUPS` |
| `nav.nearest_pickup` | call | `CALL "CY-NAV-NEAREST-PICKUP"` |
| `nav.field_distance` | call | `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 | `CALL "CY-ANGLES-NORMALIZE"` |
| `angles.angle_diff` | call | `CALL "CY-ANGLES-ANGLE-DIFF"` |
| `angles.bearing_to` | call | `CALL "CY-ANGLES-BEARING-TO"` |
| `angles.elevation_to` | call | `CALL "CY-ANGLES-ELEVATION-TO"` |
| `angles.direction` | call | `CALL "CY-ANGLES-DIRECTION"` |
| `angles.distance` | call | `CALL "CY-ANGLES-DISTANCE"` |
| `angles.clamp` | call | `CALL "CY-ANGLES-CLAMP"` |
| `status.set` | control | `CALL "CY-STATUS-TEXT"`, `CALL "CY-STATUS-VALUE"` |
| `status.get` | call | `CALL "CY-STATUS-GET-TEXT"`, `CALL "CY-STATUS-GET-VALUE"` |
| `raw.number` | call | `CALL "CY-RAW-NUMBER"` |
| `raw.text` | call | `CALL "CY-RAW-TEXT"` |
| `raw.has` | call | `CALL "CY-RAW-HAS"` |
| `raw.flag` | call | `CALL "CY-RAW-FLAG"` |
| `raw.count` | call | `CALL "CY-RAW-COUNT"` |
| `raw.line` | call | `CALL "CY-RAW-LINE"` |
| `raw.extra` | call | `CALL "CY-RAW-EXTRA"` |
| `session.event` | property | `CY-SESSION-EVENT` |
| `session.next` | call | `CALL "CY-SESSION-NEXT"` |
| `session.send` | call | `CALL "CY-SESSION-SEND"` |
| `session.forfeit` | call | `CALL "CY-SESSION-FORFEIT"` |
| `session.log` | call | `CALL "CY-SESSION-LOG"` |
| `session.feed` | call | `CALL "CY-SESSION-FEED"` |
| `session.reply` | call | `CALL "CY-SESSION-REPLY"` |
