@clunkyard/sdk 0.0.0-stage → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +76 -2
- package/THIRD_PARTY_NOTICES.txt +31 -0
- package/api.js +85 -0
- package/clunkyard-core.wasm +0 -0
- package/core.js +229 -0
- package/index.d.ts +254 -0
- package/index.js +55 -0
- package/licenses/itoa/LICENSE-APACHE +176 -0
- package/licenses/itoa/LICENSE-MIT +23 -0
- package/licenses/libm/LICENSE.txt +258 -0
- package/licenses/memchr/COPYING +3 -0
- package/licenses/memchr/LICENSE-MIT +21 -0
- package/licenses/memchr/UNLICENSE +24 -0
- package/licenses/rust-Apache-2.0.txt +73 -0
- package/licenses/rust-MIT.txt +9 -0
- package/licenses/rust-stdlib-1.96.0.html +8266 -0
- package/licenses/serde_core/LICENSE-APACHE +176 -0
- package/licenses/serde_core/LICENSE-MIT +23 -0
- package/licenses/serde_json/LICENSE-APACHE +176 -0
- package/licenses/serde_json/LICENSE-MIT +23 -0
- package/licenses/zmij/LICENSE-MIT +23 -0
- package/package.json +50 -4
- package/words.js +265 -0
package/api.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// Generated from protocol/v2/api.json; do not edit. Run make api.
|
|
2
|
+
'use strict';
|
|
3
|
+
const API={"version":"2.0.0","records":[{"name":"vec3","description":"A vector in world axes.","versioned":false,"since":"2.0","cName":"cy_vec3","alias":null,"size":24,"align":8,"fields":[{"name":"x","type":{"kind":"f64","description":"x component, east."},"description":"x component, east.","offset":0},{"name":"y","type":{"kind":"f64","description":"y component, north."},"description":"y component, north.","offset":8},{"name":"z","type":{"kind":"f64","description":"z component, up; 0 in 2D."},"description":"z component, up; 0 in 2D.","offset":16}]},{"name":"rotation","description":"A rotation rate or torque about the robot's own axes.","versioned":false,"since":"2.0","cName":"cy_rotation","alias":null,"size":24,"align":8,"fields":[{"name":"yaw","type":{"kind":"f64","description":"About the up axis."},"description":"About the up axis.","offset":0},{"name":"pitch","type":{"kind":"f64","description":"About the right axis; 0 in 2D."},"description":"About the right axis; 0 in 2D.","offset":8},{"name":"roll","type":{"kind":"f64","description":"About the forward axis; 0 in 2D."},"description":"About the forward axis; 0 in 2D.","offset":16}]},{"name":"direction","description":"A direction as a heading and an elevation.","versioned":false,"since":"2.0","cName":"cy_direction","alias":null,"size":16,"align":8,"fields":[{"name":"heading","type":{"kind":"f64","description":"Heading from the +x axis, degrees, 0 to 360."},"description":"Heading from the +x axis, degrees, 0 to 360.","offset":0},{"name":"pitch","type":{"kind":"f64","description":"Elevation, degrees, positive upward; 0 in 2D."},"description":"Elevation, degrees, positive upward; 0 in 2D.","offset":8}]},{"name":"attitude","description":"The chassis axes as unit vectors in world axes.","versioned":true,"since":"2.0","cName":"cy_attitude_v1","alias":"cy_attitude","size":72,"align":8,"fields":[{"name":"forward","type":{"kind":"record","record":"vec3","description":"The chassis forward axis."},"description":"The chassis forward axis.","offset":0},{"name":"right","type":{"kind":"record","record":"vec3","description":"The chassis right axis."},"description":"The chassis right axis.","offset":24},{"name":"up","type":{"kind":"record","record":"vec3","description":"The chassis up axis."},"description":"The chassis up axis.","offset":48}]},{"name":"applied","description":"What the previous tick applied to you, after the battery scaled the drive.","versioned":true,"since":"2.0","cName":"cy_applied_v1","alias":"cy_applied","size":56,"align":8,"fields":[{"name":"force","type":{"kind":"record","description":"Total force, gravity included.","from":"state.self.applied.force","record":"vec3"},"description":"Total force, gravity included.","offset":0},{"name":"torque","type":{"kind":"record","description":"Torque.","from":"state.self.applied.torque","record":"rotation"},"description":"Torque.","offset":24},{"name":"brake","type":{"kind":"f64","description":"Brake, 0 to 1.","from":"state.self.applied.brake","limits":[0,1]},"description":"Brake, 0 to 1.","offset":48}]},{"name":"scan","description":"The scan that produced this tick's contacts: the one your previous act asked for.","versioned":true,"since":"2.0","cName":"cy_scan_v1","alias":"cy_scan","size":32,"align":8,"fields":[{"name":"heading","type":{"kind":"f64","description":"Scan heading.","from":"state.sensors.scan.heading","limits":[0,360]},"description":"Scan heading.","offset":0},{"name":"pitch","type":{"kind":"f64","description":"Scan pitch; 0 in 2D.","from":"state.sensors.scan.pitch","limits":[-90,90]},"description":"Scan pitch; 0 in 2D.","offset":8},{"name":"arc","type":{"kind":"f64","description":"Full cone width.","from":"state.sensors.scan.arc"},"description":"Full cone width.","offset":16},{"name":"range","type":{"kind":"f64","description":"Reach at this arc.","from":"state.sensors.scan.range"},"description":"Reach at this arc.","offset":24}]},{"name":"contact","description":"A robot the sensors detect this tick.","versioned":true,"since":"2.0","cName":"cy_contact_v1","alias":"cy_contact","size":72,"align":8,"fields":[{"name":"slot","type":{"kind":"i32","description":"The robot: you are 1, and the others are numbered from 2 by first sighting (contacts first, then the hill holder), stable all match; 0 for a passive contact, which does not say which robot it heard."},"description":"The robot: you are 1, and the others are numbered from 2 by first sighting (contacts first, then the hill holder), stable all match; 0 for a passive contact, which does not say which robot it heard.","offset":0},{"name":"source","type":{"kind":"enum","description":"What detected it: scan, inside the scan cone and its reach; proximity, within scanner.proximityRange in any direction. A robot both inside the cone and near reports scan. With hello.sensing, passive sources give a noisy direction and no id: faint, inside the scan cone beyond its reach; beam, a robot whose scan swept over you; muzzle, a robot that fired; motion, a robot moving fast; ping, the periodic ping of every robot. Later sensors add sources; ignore ones you do not know.","from":"state.sensors.contacts[].source","enum":"source"},"description":"What detected it: scan, inside the scan cone and its reach; proximity, within scanner.proximityRange in any direction. A robot both inside the cone and near reports scan. With hello.sensing, passive sources give a noisy direction and no id: faint, inside the scan cone beyond its reach; beam, a robot whose scan swept over you; muzzle, a robot that fired; motion, a robot moving fast; ping, the periodic ping of every robot. Later sensors add sources; ignore ones you do not know.","offset":4},{"name":"range","type":{"kind":"f64","description":"Straight-line distance between centres. For a passive source, noisy and rounded to sensing.rangeBin.","from":"state.sensors.contacts[].range"},"description":"Straight-line distance between centres. For a passive source, noisy and rounded to sensing.rangeBin.","offset":8},{"name":"bearing","type":{"kind":"f64","description":"Heading from you to it. For a passive source, noisy.","from":"state.sensors.contacts[].bearing","limits":[0,360]},"description":"Heading from you to it. For a passive source, noisy.","offset":16},{"name":"elevation","type":{"kind":"f64","description":"Elevation from you to it; 0 in 2D. For a passive source, noisy.","from":"state.sensors.contacts[].elevation","limits":[-90,90]},"description":"Elevation from you to it; 0 in 2D. For a passive source, noisy.","offset":24},{"name":"bearing_error","type":{"kind":"f64","description":"Passive sources only: the standard deviation of bearing and elevation, degrees; 0 for scan and proximity."},"description":"Passive sources only: the standard deviation of bearing and elevation, degrees; 0 for scan and proximity.","offset":32},{"name":"range_error","type":{"kind":"f64","description":"Passive sources only: the standard deviation of the natural log of range; 0 for scan and proximity."},"description":"Passive sources only: the standard deviation of the natural log of range; 0 for scan and proximity.","offset":40},{"name":"position","type":{"kind":"record","record":"vec3","description":"Where it is, in world axes: your position plus its range along its bearing and elevation."},"description":"Where it is, in world axes: your position plus its range along its bearing and elevation.","offset":48}]},{"name":"cue","description":"The most accurate passive contact the Tracker holds: where to look, not where to shoot.","versioned":true,"since":"2.0","cName":"cy_cue_v1","alias":"cy_cue","size":40,"align":8,"fields":[{"name":"source","type":{"kind":"enum","description":"What heard it.","from":"state.sensors.contacts[].source","enum":"source"},"description":"What heard it.","offset":0},{"name":"tick","type":{"kind":"i32","description":"The tick it was heard."},"description":"The tick it was heard.","offset":4},{"name":"bearing_error","type":{"kind":"f64","description":"The standard deviation of its bearing and elevation, degrees."},"description":"The standard deviation of its bearing and elevation, degrees.","offset":8},{"name":"position","type":{"kind":"record","record":"vec3","description":"Where it placed the robot it heard, in world axes."},"description":"Where it placed the robot it heard, in world axes.","offset":16}]},{"name":"solution","description":"Where to aim for a shot fired now to meet a target, and when it meets it.","versioned":true,"since":"2.0","cName":"cy_solution_v1","alias":"cy_solution","size":24,"align":8,"fields":[{"name":"heading","type":{"kind":"f64","description":"Turret heading, degrees, 0 to 360."},"description":"Turret heading, degrees, 0 to 360.","offset":0},{"name":"pitch","type":{"kind":"f64","description":"Turret pitch, degrees; 0 in 2D."},"description":"Turret pitch, degrees; 0 in 2D.","offset":8},{"name":"time","type":{"kind":"f64","description":"Seconds of flight until the shot meets the target."},"description":"Seconds of flight until the shot meets the target.","offset":16}]},{"name":"zone","description":"The sudden-death safe zone.","versioned":true,"since":"2.0","cName":"cy_zone_v1","alias":"cy_zone","size":40,"align":8,"fields":[{"name":"shape","type":{"kind":"enum","description":"circle in 2D; sphere in 3D classic and zero-g; column, unbounded in height, in the gravity rulesets.","from":"zone.shape","enum":"shape"},"description":"circle in 2D; sphere in 3D classic and zero-g; column, unbounded in height, in the gravity rulesets.","offset":0},{"name":"reserved","type":{"kind":"i32","reserved":true,"description":"Reserved; always 0. It keeps the record free of hidden padding."},"description":"Reserved; always 0. It keeps the record free of hidden padding.","offset":4},{"name":"radius","type":{"kind":"f64","description":"The radius now. It shrinks evenly from suddenDeath.radiusStart to radiusEnd at suddenDeath.endTick (the last tick when absent).","from":"zone.radius"},"description":"The radius now. It shrinks evenly from suddenDeath.radiusStart to radiusEnd at suddenDeath.endTick (the last tick when absent).","offset":8},{"name":"center","type":{"kind":"record","description":"The zone's centre. A column's centre has z 0 and its height does not matter.","from":"zone.center","record":"vec3"},"description":"The zone's centre. A column's centre has z 0 and its height does not matter.","offset":16}]},{"name":"storm","description":"The storm now.","versioned":true,"since":"2.0","cName":"cy_storm_v1","alias":"cy_storm","size":72,"align":8,"fields":[{"name":"shape","type":{"kind":"enum","description":"circle in 2D, column in 3D.","from":"state.storm.shape","enum":"shape"},"description":"circle in 2D, column in 3D.","offset":0},{"name":"reserved","type":{"kind":"i32","reserved":true,"description":"Reserved; always 0. It keeps the record free of hidden padding."},"description":"Reserved; always 0. It keeps the record free of hidden padding.","offset":4},{"name":"radius","type":{"kind":"f64","description":"Its radius now.","from":"state.storm.radius"},"description":"Its radius now.","offset":8},{"name":"dps","type":{"kind":"f64","description":"Health lost per second inside it.","from":"state.storm.dps"},"description":"Health lost per second inside it.","offset":16},{"name":"center","type":{"kind":"record","description":"Its centre; z is 0.","from":"state.storm.center","record":"vec3"},"description":"Its centre; z is 0.","offset":24},{"name":"velocity","type":{"kind":"record","description":"Its velocity, units/s.","from":"state.storm.velocity","record":"vec3"},"description":"Its velocity, units/s.","offset":48}]},{"name":"hill","description":"The king-of-the-hill zone now.","versioned":true,"since":"2.0","cName":"cy_hill_v1","alias":"cy_hill","size":80,"align":8,"fields":[{"name":"shape","type":{"kind":"enum","description":"As zone.shape.","from":"state.objectives.hill.shape","enum":"shape"},"description":"As zone.shape.","offset":0},{"name":"holder","type":{"kind":"i32","description":"The slot of the robot alone inside it (1 is you), or 0 for nobody."},"description":"The slot of the robot alone inside it (1 is you), or 0 for nobody.","offset":4},{"name":"contested","type":{"kind":"bool","description":"More than one robot is inside it."},"description":"More than one robot is inside it.","offset":8},{"name":"moves_tick","type":{"kind":"i32","description":"When it moves.","from":"state.objectives.hill.movesTick"},"description":"When it moves.","offset":12},{"name":"held_ticks","type":{"kind":"i32","description":"Ticks you have held it.","from":"state.objectives.hill.heldTicks"},"description":"Ticks you have held it.","offset":16},{"name":"best_held_ticks","type":{"kind":"i32","description":"Most ticks any other robot has held it.","from":"state.objectives.hill.bestHeldTicks"},"description":"Most ticks any other robot has held it.","offset":20},{"name":"radius","type":{"kind":"f64","description":"Its radius.","from":"state.objectives.hill.radius"},"description":"Its radius.","offset":24},{"name":"center","type":{"kind":"record","description":"Its centre.","from":"state.objectives.hill.center","record":"vec3"},"description":"Its centre.","offset":32},{"name":"next","type":{"kind":"record","description":"Where it moves at movesTick.","from":"state.objectives.hill.next","record":"vec3"},"description":"Where it moves at movesTick.","offset":56}]},{"name":"pickup","description":"A cell on the field.","versioned":true,"since":"2.0","cName":"cy_pickup_v1","alias":"cy_pickup","size":40,"align":8,"fields":[{"name":"kind","type":{"kind":"enum","description":"energy refills the battery, health repairs, armour absorbs shot damage before health.","from":"pickup.kind","enum":"pickup_kind"},"description":"energy refills the battery, health repairs, armour absorbs shot damage before health.","offset":0},{"name":"expires_tick","type":{"kind":"i32","description":"The tick it disappears if nobody takes it.","from":"pickup.expiresTick"},"description":"The tick it disappears if nobody takes it.","offset":4},{"name":"amount","type":{"kind":"f64","description":"What it gives.","from":"pickup.amount"},"description":"What it gives.","offset":8},{"name":"position","type":{"kind":"record","description":"Where it is. Under gravity it lies on the ground and only x and y count.","from":"pickup.position","record":"vec3"},"description":"Where it is. Under gravity it lies on the ground and only x and y count.","offset":16}]},{"name":"compute","description":"How the match charges compute against the battery.","versioned":true,"since":"2.0","cName":"cy_compute_v1","alias":"cy_compute","size":16,"align":8,"fields":[{"name":"k","type":{"kind":"f64","description":"The charge for a turn that uses its whole budget.","from":"hello.battery.compute.k"},"description":"The charge for a turn that uses its whole budget.","offset":0},{"name":"quanta","type":{"kind":"i32","description":"A trusted CPU turn is charged in steps of 1/quanta of its budget: k × q / quanta, where q = min(quanta, floor(quanta × cpu / budget)).","from":"hello.battery.compute.quanta"},"description":"A trusted CPU turn is charged in steps of 1/quanta of its budget: k × q / quanta, where q = min(quanta, floor(quanta × cpu / budget)).","offset":8},{"name":"unit","type":{"kind":"enum","description":"The meter you are charged by: DSL operations and WebAssembly fuel exactly, k × used / limit; trusted CPU in quanta. null when your turns are not metered, so thinking costs you nothing.","from":"hello.battery.compute.unit","enum":"compute_unit"},"description":"The meter you are charged by: DSL operations and WebAssembly fuel exactly, k × used / limit; trusted CPU in quanta. null when your turns are not metered, so thinking costs you nothing.","offset":12}]}],"enums":[{"name":"source","description":"What detected a contact.","zero":"none","from":"contact.source","values":[{"wire":"scan","name":"scan","value":1},{"wire":"proximity","name":"proximity","value":2},{"wire":"faint","name":"faint","value":3},{"wire":"beam","name":"beam","value":4},{"wire":"muzzle","name":"muzzle","value":5},{"wire":"motion","name":"motion","value":6},{"wire":"ping","name":"ping","value":7}]},{"name":"mode","description":"The match's dimensions.","zero":"none","from":"hello.match.mode","values":[{"wire":"2d","name":"two_d","value":1},{"wire":"3d","name":"three_d","value":2}]},{"name":"ruleset","description":"The ruleset.","zero":"none","from":"hello.match.ruleset","values":[{"wire":"classic","name":"classic","value":1},{"wire":"inertial-2d","name":"inertial_2d","value":2},{"wire":"gravity-flat","name":"gravity_flat","value":3},{"wire":"gravity-hills","name":"gravity_hills","value":4},{"wire":"zero-g","name":"zero_g","value":5}]},{"name":"control","description":"What the drive controls mean: direct speeds in classic, forces elsewhere.","zero":"none","from":"hello.match.control","values":[{"wire":"direct","name":"direct","value":1},{"wire":"forces","name":"forces","value":2}]},{"name":"terrain_kind","description":"The ground.","zero":"none","from":"hello.arena.terrain.kind","values":[{"wire":"none","name":"none","value":1},{"wire":"flat","name":"flat","value":2},{"wire":"hills","name":"hills","value":3}]},{"name":"shape","description":"A region's shape: circle in 2D, sphere in 3D classic and zero-g, column (unbounded in height) under gravity.","zero":"none","from":"zone.shape","values":[{"wire":"circle","name":"circle","value":1},{"wire":"sphere","name":"sphere","value":2},{"wire":"column","name":"column","value":3}]},{"name":"pickup_kind","description":"What a pickup gives. 0 asks for any kind.","zero":"any","from":"pickup.kind","values":[{"wire":"energy","name":"energy","value":1},{"wire":"health","name":"health","value":2},{"wire":"armour","name":"armour","value":3}]},{"name":"compute_unit","description":"The meter compute is charged by; 0 when turns are not metered.","zero":"none","from":"hello.battery.compute.unit","values":[{"wire":"operations","name":"operations","value":1},{"wire":"fuel","name":"fuel","value":2},{"wire":"cpu-ms","name":"cpu_ms","value":3}]},{"name":"event","description":"What session.next read: the hello, a state, or the end of input.","zero":"none","from":null,"values":[{"wire":"hello","name":"hello","value":1},{"wire":"state","name":"state","value":2},{"wire":"end","name":"end","value":3}]}],"subsystems":[{"name":"match","fact":"The match, fixed from the hello.","stateless":false,"rename":{"rust":"r#match"}},{"name":"clock","fact":"Where the match is in time.","stateless":false,"rename":{}},{"name":"arena","fact":"The space robots move in, fixed from the hello.","stateless":false,"rename":{}},{"name":"me","fact":"Your robot, after the previous tick resolved.","stateless":false,"rename":{}},{"name":"battery","fact":"The battery that driving and shooting share.","stateless":false,"rename":{}},{"name":"drive","fact":"The chassis controls.","stateless":false,"rename":{}},{"name":"gun","fact":"The turret and its shots.","stateless":false,"rename":{}},{"name":"scanner","fact":"The scanner.","stateless":false,"rename":{}},{"name":"sensors","fact":"What the sensors detect this tick.","stateless":false,"rename":{}},{"name":"tracker","fact":"Estimates from past sightings, updated once a state inside the core.","stateless":false,"rename":{}},{"name":"nav","fact":"The regions and objects on the field.","stateless":false,"rename":{}},{"name":"score","fact":"Time-limit scoring, when the match scores.","stateless":false,"rename":{}},{"name":"angles","fact":"Angle and vector arithmetic in the core's maths, so every language agrees bit for bit.","stateless":true,"rename":{}},{"name":"status","fact":"The status line spectators see.","stateless":false,"rename":{}},{"name":"raw","fact":"The messages as the arena sent them, for what the API does not cover.","stateless":false,"rename":{}},{"name":"session","fact":"The protocol session: hello, ready, state, act and forfeit.","stateless":false,"rename":{}}],"entries":[{"name":"match.mode","kind":"query","form":"property","since":"2.0","fact":"The match is 2D or 3D.","subsystem":"match","member":"mode","path":["match","mode"],"stateless":false,"args":[],"returns":{"kind":"enum","description":"2d or 3d.","from":"hello.match.mode","enum":"mode"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#mode","symbol":"cy_match_mode","alias":null,"rust":{"module":"match","fn":"mode"}},{"name":"match.ruleset","kind":"query","form":"property","since":"2.0","fact":"The ruleset in play.","subsystem":"match","member":"ruleset","path":["match","ruleset"],"stateless":false,"args":[],"returns":{"kind":"enum","description":"The ruleset.","from":"hello.match.ruleset","enum":"ruleset"},"fields":[],"of":null,"dsl":{"ruleset":"value","physics-mode":{"not":"classic"},"zero-g":{"is":"zero-g"}},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#ruleset","symbol":"cy_match_ruleset","alias":null,"rust":{"module":"match","fn":"ruleset"}},{"name":"match.control","kind":"query","form":"property","since":"2.0","fact":"Whether the drive sets speeds (direct) or forces.","subsystem":"match","member":"control","path":["match","control"],"stateless":false,"args":[],"returns":{"kind":"enum","description":"direct in classic: drive sets speed and turn rate. forces in the other rulesets: controls are forces and torques, and the robot keeps its momentum.","from":"hello.match.control","enum":"control"},"fields":[],"of":null,"dsl":{"control-model":"value","inertial":{"is":"forces"}},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#control","symbol":"cy_match_control","alias":null,"rust":{"module":"match","fn":"control"}},{"name":"match.robots","kind":"query","form":"property","since":"2.0","fact":"Robots in the match, you included; slots run 1 to this.","subsystem":"match","member":"robots","path":["match","robots"],"stateless":false,"args":[],"returns":{"kind":"i32","description":"Robots in the match, you included.","from":"hello.match.robots"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#robots","symbol":"cy_match_robots","alias":null,"rust":{"module":"match","fn":"robots"}},{"name":"match.is_3d","kind":"query","form":"property","since":"2.0","fact":"The match is 3D.","subsystem":"match","member":"is3d","path":["match","is_3d"],"stateless":false,"args":[],"returns":{"kind":"bool","description":"True in a 3D match."},"fields":[],"of":null,"dsl":{"mode3":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#is_3d","symbol":"cy_match_is_3d","alias":null,"rust":{"module":"match","fn":"is_3d"}},{"name":"match.tick_rate","kind":"query","form":"property","since":"2.0","fact":"Ticks per second.","subsystem":"match","member":"tickRate","path":["match","tick_rate"],"stateless":false,"args":[],"returns":{"kind":"i32","description":"Ticks per second.","from":"hello.match.tickRate"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#tick_rate","symbol":"cy_match_tick_rate","alias":null,"rust":{"module":"match","fn":"tick_rate"}},{"name":"match.max_ticks","kind":"query","form":"property","since":"2.0","fact":"The last tick the match can reach.","subsystem":"match","member":"maxTicks","path":["match","max_ticks"],"stateless":false,"args":[],"returns":{"kind":"i32","description":"Ticks in the match; the match ends at this tick at the latest.","from":"hello.match.maxTicks"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#max_ticks","symbol":"cy_match_max_ticks","alias":null,"rust":{"module":"match","fn":"max_ticks"}},{"name":"match.robot_id","kind":"query","form":"call","since":"2.0","fact":"The id the protocol gives the robot in a slot.","subsystem":"match","member":"robotId","path":["match","robot_id"],"stateless":false,"args":[{"name":"slot","type":{"kind":"i32","description":"A slot, 1 to match.robots."},"description":"A slot, 1 to match.robots."}],"returns":{"kind":"text","description":"The robot's id, in UTF-8."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/match.json#robot_id","symbol":"cy_robot_id","alias":null,"rust":{"module":"match","fn":"robot_id"}},{"name":"clock.tick","kind":"query","form":"property","since":"2.0","fact":"This tick, from 0.","subsystem":"clock","member":"tick","path":["clock","tick"],"stateless":false,"args":[],"returns":{"kind":"i32","description":"This tick, from 0. Seconds are tick / match.tickRate.","from":"state.tick"},"fields":[],"of":null,"dsl":{"tick":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/clock.json#tick","symbol":"cy_clock_tick","alias":null,"rust":{"module":"clock","fn":"tick"}},{"name":"clock.seconds","kind":"query","form":"property","since":"2.0","fact":"The match time in seconds.","subsystem":"clock","member":"seconds","path":["clock","seconds"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Seconds since the start: tick / match.tick_rate."},"fields":[],"of":null,"dsl":{"time":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/clock.json#seconds","symbol":"cy_clock_seconds","alias":null,"rust":{"module":"clock","fn":"seconds"}},{"name":"clock.remaining_ticks","kind":"query","form":"property","since":"2.0","fact":"Ticks left: match.max_ticks less this tick.","subsystem":"clock","member":"remainingTicks","path":["clock","remaining_ticks"],"stateless":false,"args":[],"returns":{"kind":"i32","description":"Ticks left before the match ends at the latest."},"fields":[],"of":null,"dsl":{"remaining":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/clock.json#remaining_ticks","symbol":"cy_clock_remaining_ticks","alias":null,"rust":{"module":"clock","fn":"remaining_ticks"}},{"name":"arena.size","kind":"query","form":"property","since":"2.0","fact":"The arena runs from 0 to this on each axis.","subsystem":"arena","member":"size","path":["arena","size"],"stateless":false,"args":[],"returns":{"kind":"record","record":"vec3","description":"Width (x), height (y) and depth (z; 0 in 2D)."},"fields":[],"of":null,"dsl":{"width":"x","height":"y","depth":"z"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/arena.json#size","symbol":"cy_arena_size","alias":null,"rust":{"module":"arena","fn":"size"}},{"name":"arena.gravity","kind":"query","form":"property","since":"2.0","fact":"The acceleration of gravity, units/s².","subsystem":"arena","member":"gravity","path":["arena","gravity"],"stateless":false,"args":[],"returns":{"kind":"record","description":"Acceleration of gravity, units/s²: (0, 0, −85) in the gravity rulesets, zero elsewhere. Shots fall with it too.","from":"hello.arena.gravity","record":"vec3"},"fields":[],"of":null,"dsl":{"gravity-x":"x","gravity-y":"y","gravity-z":"z"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/arena.json#gravity","symbol":"cy_arena_gravity","alias":null,"rust":{"module":"arena","fn":"gravity"}},{"name":"arena.terrain_kind","kind":"query","form":"property","since":"2.0","fact":"The kind of ground: none, flat or hills.","subsystem":"arena","member":"terrainKind","path":["arena","terrain_kind"],"stateless":false,"args":[],"returns":{"kind":"enum","description":"The kind of ground.","from":"hello.arena.terrain.kind","enum":"terrain_kind"},"fields":[],"of":null,"dsl":{"terrain-kind":"value","hills":{"is":"hills"}},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/arena.json#terrain_kind","symbol":"cy_arena_terrain_kind","alias":null,"rust":{"module":"arena","fn":"terrain_kind"}},{"name":"arena.ground_height","kind":"query","form":"call","since":"2.0","fact":"The height of the ground at a point, interpolated as the arena does.","subsystem":"arena","member":"groundHeight","path":["arena","ground_height"],"stateless":false,"args":[{"name":"x","type":{"kind":"f64","description":"Arena x."},"description":"Arena x."},{"name":"y","type":{"kind":"f64","description":"Arena y."},"description":"Arena y."}],"returns":{"kind":"f64","description":"Ground height, units; 0 with no ground."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/arena.json#ground_height","symbol":"cy_arena_ground_height","alias":null,"rust":{"module":"arena","fn":"ground_height"}},{"name":"me.health","kind":"query","form":"property","since":"2.0","fact":"Health left.","subsystem":"me","member":"health","path":["me","health"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Health left.","from":"state.self.health"},"fields":[],"of":null,"dsl":{"health":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#health","symbol":"cy_me_health","alias":null,"rust":{"module":"me","fn":"health"}},{"name":"me.position","kind":"query","form":"property","since":"2.0","fact":"Your centre.","subsystem":"me","member":"position","path":["me","position"],"stateless":false,"args":[],"returns":{"kind":"record","description":"Your centre, in arena units.","from":"state.self.position","record":"vec3"},"fields":[],"of":null,"dsl":{"x":"x","y":"y","z":"z"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#position","symbol":"cy_me_position","alias":null,"rust":{"module":"me","fn":"position"}},{"name":"me.velocity","kind":"query","form":"property","since":"2.0","fact":"Your velocity, units/s.","subsystem":"me","member":"velocity","path":["me","velocity"],"stateless":false,"args":[],"returns":{"kind":"record","description":"Your velocity, units/s.","from":"state.self.velocity","record":"vec3"},"fields":[],"of":null,"dsl":{"vx":"x","vy":"y","vz":"z"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#velocity","symbol":"cy_me_velocity","alias":null,"rust":{"module":"me","fn":"velocity"}},{"name":"me.heading","kind":"query","form":"property","since":"2.0","fact":"Your chassis heading.","subsystem":"me","member":"heading","path":["me","heading"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Chassis heading.","from":"state.self.heading","limits":[0,360]},"fields":[],"of":null,"dsl":{"heading":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#heading","symbol":"cy_me_heading","alias":null,"rust":{"module":"me","fn":"heading"}},{"name":"me.pitch","kind":"query","form":"property","since":"2.0","fact":"Your chassis pitch; 0 in 2D.","subsystem":"me","member":"pitch","path":["me","pitch"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Chassis pitch; 0 in 2D.","from":"state.self.pitch","limits":[-90,90]},"fields":[],"of":null,"dsl":{"pitch":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#pitch","symbol":"cy_me_pitch","alias":null,"rust":{"module":"me","fn":"pitch"}},{"name":"me.roll","kind":"query","form":"property","since":"2.0","fact":"Your chassis roll; 0 in 2D and classic.","subsystem":"me","member":"roll","path":["me","roll"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Chassis roll; 0 in 2D and classic.","from":"state.self.roll","limits":[-180,180]},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#roll","symbol":"cy_me_roll","alias":null,"rust":{"module":"me","fn":"roll"}},{"name":"me.angular_velocity","kind":"query","form":"property","since":"2.0","fact":"Your rotation rates, degrees/s.","subsystem":"me","member":"angularVelocity","path":["me","angular_velocity"],"stateless":false,"args":[],"returns":{"kind":"record","description":"Rotation rates, degrees/s.","from":"state.self.angularVelocity","record":"rotation"},"fields":[],"of":null,"dsl":{"yaw-rate":"yaw","pitch-rate":"pitch","roll-rate":"roll"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#angular_velocity","symbol":"cy_me_angular_velocity","alias":null,"rust":{"module":"me","fn":"angular_velocity"}},{"name":"me.attitude","kind":"query","form":"property","since":"2.0","fact":"Your chassis axes in world axes.","subsystem":"me","member":"attitude","path":["me","attitude"],"stateless":false,"args":[],"returns":{"kind":"record","record":"attitude","description":""},"fields":[],"of":null,"dsl":{"forward-x":"forward.x","forward-y":"forward.y","forward-z":"forward.z","right-x":"right.x","right-y":"right.y","right-z":"right.z","up-x":"up.x","up-y":"up.y","up-z":"up.z"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#attitude","symbol":"cy_me_attitude_v1","alias":"cy_me_attitude","rust":{"module":"me","fn":"attitude"}},{"name":"me.grounded","kind":"query","form":"property","since":"2.0","fact":"You rest on the ground, under gravity.","subsystem":"me","member":"grounded","path":["me","grounded"],"stateless":false,"args":[],"returns":{"kind":"bool","description":"Resting on the ground, in the gravity rulesets.","from":"state.self.grounded"},"fields":[],"of":null,"dsl":{"grounded":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#grounded","symbol":"cy_me_grounded","alias":null,"rust":{"module":"me","fn":"grounded"}},{"name":"me.altitude","kind":"query","form":"property","since":"2.0","fact":"In 3D, the height of your underside above the ground.","subsystem":"me","member":"altitude","path":["me","altitude"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"In 3D, the height of your underside above the ground.","from":"state.self.altitude"},"fields":[],"of":null,"dsl":{"altitude":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#altitude","symbol":"cy_me_altitude","alias":null,"rust":{"module":"me","fn":"altitude"}},{"name":"me.applied","kind":"query","form":"property","since":"2.0","fact":"What the previous tick applied to you.","subsystem":"me","member":"applied","path":["me","applied"],"stateless":false,"args":[],"returns":{"kind":"record","record":"applied","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/me.json#applied","symbol":"cy_me_applied_v1","alias":"cy_me_applied","rust":{"module":"me","fn":"applied"}},{"name":"battery.charge","kind":"query","form":"property","since":"2.0","fact":"Charge now, before this tick's regeneration and driving.","subsystem":"battery","member":"charge","path":["battery","charge"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Charge, 0 to battery.capacity, before this tick's regeneration and driving.","from":"state.self.battery"},"fields":[],"of":null,"dsl":{"battery":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/battery.json#charge","symbol":"cy_battery_charge","alias":null,"rust":{"module":"battery","fn":"charge"}},{"name":"battery.capacity","kind":"query","form":"property","since":"2.0","fact":"Charge when full.","subsystem":"battery","member":"capacity","path":["battery","capacity"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Charge when full. Robots start full.","from":"hello.battery.capacity"},"fields":[],"of":null,"dsl":{"battery-capacity":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/battery.json#capacity","symbol":"cy_battery_capacity","alias":null,"rust":{"module":"battery","fn":"capacity"}},{"name":"battery.regen","kind":"query","form":"property","since":"2.0","fact":"Charge regained each second.","subsystem":"battery","member":"regen","path":["battery","regen"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Charge regained each second.","from":"hello.battery.regen"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/battery.json#regen","symbol":"cy_battery_regen","alias":null,"rust":{"module":"battery","fn":"regen"}},{"name":"battery.sustainable_drive","kind":"query","form":"property","since":"2.0","fact":"The drive fraction regeneration pays for forever.","subsystem":"battery","member":"sustainableDrive","path":["battery","sustainable_drive"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The drive fraction the battery's regeneration pays for forever.","from":"hello.derived.sustainableDrive","limits":[0,1]},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/battery.json#sustainable_drive","symbol":"cy_battery_sustainable_drive","alias":null,"rust":{"module":"battery","fn":"sustainable_drive"}},{"name":"battery.compute","kind":"query","form":"property","since":"2.0","fact":"How compute is charged, when the match charges it.","subsystem":"battery","member":"compute","path":["battery","compute"],"stateless":false,"args":[],"returns":{"kind":"record","record":"compute","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/battery.json#compute","symbol":"cy_battery_compute_v1","alias":"cy_battery_compute","rust":{"module":"battery","fn":"compute"}},{"name":"battery.drive_cost","kind":"query","form":"call","since":"2.0","fact":"What holding a drive fraction costs each second, by hello.formulas.driveCost.","subsystem":"battery","member":"driveCost","path":["battery","drive_cost"],"stateless":false,"args":[{"name":"fraction","type":{"kind":"f64","description":"A drive fraction, -1 to 1."},"description":"A drive fraction, -1 to 1."}],"returns":{"kind":"f64","description":"Charge per second."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/battery.json#drive_cost","symbol":"cy_battery_drive_cost","alias":null,"rust":{"module":"battery","fn":"drive_cost"}},{"name":"drive.hover_lift","kind":"query","form":"property","since":"2.0","fact":"The forces.lift that cancels gravity for a level robot; 0 without gravity.","subsystem":"drive","member":"hoverLift","path":["drive","hover_lift"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The forces.lift that cancels gravity for a level robot; 0 without gravity.","from":"hello.derived.hoverLift","limits":[0,1]},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/drive.json#hover_lift","symbol":"cy_drive_hover_lift","alias":null,"rust":{"module":"drive","fn":"hover_lift"}},{"name":"drive.set","kind":"control","form":"call","since":"2.0","fact":"Ask for direct controls this tick; the arena decides what they do in the ruleset.","subsystem":"drive","member":"set","path":["drive","set"],"stateless":false,"args":[],"returns":null,"fields":[{"key":"throttle","arg":"throttle","type":"number","act":["drive","throttle"],"limits":[-1,1],"optional":true,"description":"Classic: speed along your heading (and pitch), throttle × robot.maxSpeed.","symbol":"cy_drive_throttle","getter":"cy_drive_get_throttle","dsl":"drive","glyph":"drive!"},{"key":"turn","arg":"turn","type":"number","act":["drive","turn"],"limits":[-1,1],"optional":true,"description":"Classic: turn rate, turn × robot.maxTurnRate.","symbol":"cy_drive_turn","getter":"cy_drive_get_turn","dsl":"turn","glyph":"turn!"},{"key":"pitch_turn","arg":"pitch_turn","type":"number","act":["drive","pitchTurn"],"limits":[-1,1],"optional":true,"description":"3D classic: pitch rate, pitchTurn × robot.maxPitchTurnRate, within ±robot.maxPitch.","symbol":"cy_drive_pitch_turn","getter":"cy_drive_get_pitch_turn","dsl":"pitch","glyph":"pitch-turn!"}],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/drive.json#set","symbol":"cy_drive_set","alias":null,"rust":{"module":"drive","fn":"set"}},{"name":"drive.forces","kind":"control","form":"call","since":"2.0","fact":"Ask for forces and torques this tick, in the force rulesets.","subsystem":"drive","member":"forces","path":["drive","forces"],"stateless":false,"args":[],"returns":null,"fields":[{"key":"thrust","arg":"thrust","type":"number","act":["forces","thrust"],"limits":[-1,1],"optional":true,"description":"Force along your forward axis.","symbol":"cy_drive_thrust","getter":"cy_drive_get_thrust","dsl":"thrust","glyph":"thrust!"},{"key":"strafe","arg":"strafe","type":"number","act":["forces","strafe"],"limits":[-1,1],"optional":true,"description":"Force along your right axis.","symbol":"cy_drive_strafe","getter":"cy_drive_get_strafe","dsl":"strafe","glyph":"strafe!"},{"key":"lift","arg":"lift","type":"number","act":["forces","lift"],"limits":[-1,1],"optional":true,"description":"3D: force along your up axis. About 0.85 hovers level under gravity.","symbol":"cy_drive_lift","getter":"cy_drive_get_lift","dsl":"lift","glyph":"lift!"},{"key":"yaw_torque","arg":"yaw_torque","type":"number","act":["forces","yawTorque"],"limits":[-1,1],"optional":true,"description":"Torque about your up axis.","symbol":"cy_drive_yaw_torque","getter":"cy_drive_get_yaw_torque","dsl":"yaw-torque","glyph":"yaw-torque!"},{"key":"pitch_torque","arg":"pitch_torque","type":"number","act":["forces","pitchTorque"],"limits":[-1,1],"optional":true,"description":"3D: torque about your right axis.","symbol":"cy_drive_pitch_torque","getter":"cy_drive_get_pitch_torque","dsl":"pitch-torque","glyph":"pitch-torque!"},{"key":"roll_torque","arg":"roll_torque","type":"number","act":["forces","rollTorque"],"limits":[-1,1],"optional":true,"description":"3D: torque about your forward axis.","symbol":"cy_drive_roll_torque","getter":"cy_drive_get_roll_torque","dsl":"roll-torque","glyph":"roll-torque!"},{"key":"brake","arg":"brake","type":"number","act":["forces","brake"],"limits":[0,1],"optional":true,"description":"Counter-force and counter-torque, 0 to 1.","symbol":"cy_drive_brake","getter":"cy_drive_get_brake","dsl":"brake","glyph":"brake!"}],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/drive.json#forces","symbol":"cy_drive_forces","alias":null,"rust":{"module":"drive","fn":"forces"}},{"name":"drive.get","kind":"getter","form":"call","since":"2.0","fact":"What this tick's act holds for a drive field so far, as set.","subsystem":"drive","member":"get","path":["drive","get"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The value as set, before clamping, or absent while unset.","optional":true},"fields":[{"key":"throttle","arg":"throttle","type":"number","act":["drive","throttle"],"limits":[-1,1],"optional":true,"description":"Classic: speed along your heading (and pitch), throttle × robot.maxSpeed.","symbol":"cy_drive_throttle","getter":"cy_drive_get_throttle","dsl":"drive","glyph":"drive!"},{"key":"turn","arg":"turn","type":"number","act":["drive","turn"],"limits":[-1,1],"optional":true,"description":"Classic: turn rate, turn × robot.maxTurnRate.","symbol":"cy_drive_turn","getter":"cy_drive_get_turn","dsl":"turn","glyph":"turn!"},{"key":"pitch_turn","arg":"pitch_turn","type":"number","act":["drive","pitchTurn"],"limits":[-1,1],"optional":true,"description":"3D classic: pitch rate, pitchTurn × robot.maxPitchTurnRate, within ±robot.maxPitch.","symbol":"cy_drive_pitch_turn","getter":"cy_drive_get_pitch_turn","dsl":"pitch","glyph":"pitch-turn!"},{"key":"thrust","arg":"thrust","type":"number","act":["forces","thrust"],"limits":[-1,1],"optional":true,"description":"Force along your forward axis.","symbol":"cy_drive_thrust","getter":"cy_drive_get_thrust","dsl":"thrust","glyph":"thrust!"},{"key":"strafe","arg":"strafe","type":"number","act":["forces","strafe"],"limits":[-1,1],"optional":true,"description":"Force along your right axis.","symbol":"cy_drive_strafe","getter":"cy_drive_get_strafe","dsl":"strafe","glyph":"strafe!"},{"key":"lift","arg":"lift","type":"number","act":["forces","lift"],"limits":[-1,1],"optional":true,"description":"3D: force along your up axis. About 0.85 hovers level under gravity.","symbol":"cy_drive_lift","getter":"cy_drive_get_lift","dsl":"lift","glyph":"lift!"},{"key":"yaw_torque","arg":"yaw_torque","type":"number","act":["forces","yawTorque"],"limits":[-1,1],"optional":true,"description":"Torque about your up axis.","symbol":"cy_drive_yaw_torque","getter":"cy_drive_get_yaw_torque","dsl":"yaw-torque","glyph":"yaw-torque!"},{"key":"pitch_torque","arg":"pitch_torque","type":"number","act":["forces","pitchTorque"],"limits":[-1,1],"optional":true,"description":"3D: torque about your right axis.","symbol":"cy_drive_pitch_torque","getter":"cy_drive_get_pitch_torque","dsl":"pitch-torque","glyph":"pitch-torque!"},{"key":"roll_torque","arg":"roll_torque","type":"number","act":["forces","rollTorque"],"limits":[-1,1],"optional":true,"description":"3D: torque about your forward axis.","symbol":"cy_drive_roll_torque","getter":"cy_drive_get_roll_torque","dsl":"roll-torque","glyph":"roll-torque!"},{"key":"brake","arg":"brake","type":"number","act":["forces","brake"],"limits":[0,1],"optional":true,"description":"Counter-force and counter-torque, 0 to 1.","symbol":"cy_drive_brake","getter":"cy_drive_get_brake","dsl":"brake","glyph":"brake!"}],"of":["drive.set","drive.forces"],"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/drive.json#get","symbol":"cy_drive_get","alias":null,"rust":{"module":"drive","fn":"get"}},{"name":"gun.aim_now","kind":"query","form":"property","since":"2.0","fact":"Where the turret points now; a shot leaves along it.","subsystem":"gun","member":"aimNow","path":["gun","aim_now"],"stateless":false,"args":[],"returns":{"kind":"record","description":"Where the turret points now. It slews toward act.aim at gun.turnRate; a shot leaves along it.","from":"state.self.aim","record":"direction"},"fields":[],"of":null,"dsl":{"aim":"heading","aim-pitch":"pitch"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#aim_now","symbol":"cy_gun_aim_now","alias":null,"rust":{"module":"gun","fn":"aim_now"}},{"name":"gun.cooldown_ticks","kind":"query","form":"property","since":"2.0","fact":"Ticks until the gun can fire; 0 means it can fire this tick.","subsystem":"gun","member":"cooldownTicks","path":["gun","cooldown_ticks"],"stateless":false,"args":[],"returns":{"kind":"i32","description":"Ticks until the gun can fire; 0 means it can fire this tick.","from":"state.self.cooldownTicks"},"fields":[],"of":null,"dsl":{"cooldown":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#cooldown_ticks","symbol":"cy_gun_cooldown_ticks","alias":null,"rust":{"module":"gun","fn":"cooldown_ticks"}},{"name":"gun.spread","kind":"query","form":"property","since":"2.0","fact":"The aim spread a shot would have at your speed now.","subsystem":"gun","member":"spread","path":["gun","spread"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The aim spread a shot would have at your current speed.","from":"state.self.spread"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#spread","symbol":"cy_gun_spread","alias":null,"rust":{"module":"gun","fn":"spread"}},{"name":"gun.max_power","kind":"query","form":"property","since":"2.0","fact":"The heaviest shot the battery pays for now; 0 when it cannot pay for the lightest.","subsystem":"gun","member":"maxPower","path":["gun","max_power"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The heaviest shot the battery pays for now, floored to 0.001 and at most gun.power.max; 0 when it cannot pay for gun.power.min. It ignores the cooldown.","from":"state.derived.self.maxPower"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#max_power","symbol":"cy_gun_max_power","alias":null,"rust":{"module":"gun","fn":"max_power"}},{"name":"gun.damage_scale","kind":"query","form":"property","since":"2.0","fact":"The escalation multiplier on hit damage this tick.","subsystem":"gun","member":"damageScale","path":["gun","damage_scale"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The escalation multiplier on hit damage this tick: 1, then rising from gun.escalation.startTick.","from":"state.derived.gun.damageScale"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#damage_scale","symbol":"cy_gun_damage_scale","alias":null,"rust":{"module":"gun","fn":"damage_scale"}},{"name":"gun.can_fire","kind":"query","form":"call","since":"2.0","fact":"The cooldown is 0 and the battery pays for a shot at this power and still holds the reserve.","subsystem":"gun","member":"canFire","path":["gun","can_fire"],"stateless":false,"args":[{"name":"power","type":{"kind":"f64","description":"Shot power."},"description":"Shot power."},{"name":"reserve","type":{"kind":"f64","description":"Charge to keep after the shot."},"description":"Charge to keep after the shot."}],"returns":{"kind":"bool","description":"True when it would leave."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#can_fire","symbol":"cy_gun_can_fire","alias":null,"rust":{"module":"gun","fn":"can_fire"}},{"name":"gun.shot_speed","kind":"query","form":"call","since":"2.0","fact":"How fast a shot at this power flies, units/s, by hello.formulas.shotSpeed.","subsystem":"gun","member":"shotSpeed","path":["gun","shot_speed"],"stateless":false,"args":[{"name":"power","type":{"kind":"f64","description":"Shot power."},"description":"Shot power."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#shot_speed","symbol":"cy_gun_shot_speed","alias":null,"rust":{"module":"gun","fn":"shot_speed"}},{"name":"gun.shot_cost","kind":"query","form":"call","since":"2.0","fact":"What a shot at this power costs the battery, by hello.formulas.shotCost.","subsystem":"gun","member":"shotCost","path":["gun","shot_cost"],"stateless":false,"args":[{"name":"power","type":{"kind":"f64","description":"Shot power."},"description":"Shot power."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#shot_cost","symbol":"cy_gun_shot_cost","alias":null,"rust":{"module":"gun","fn":"shot_cost"}},{"name":"gun.reload_ticks","kind":"query","form":"call","since":"2.0","fact":"The reload after a shot at this power, ticks, by hello.formulas.reloadTicks.","subsystem":"gun","member":"reloadTicks","path":["gun","reload_ticks"],"stateless":false,"args":[{"name":"power","type":{"kind":"f64","description":"Shot power."},"description":"Shot power."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#reload_ticks","symbol":"cy_gun_reload_ticks","alias":null,"rust":{"module":"gun","fn":"reload_ticks"}},{"name":"gun.shot_damage","kind":"query","form":"call","since":"2.0","fact":"The damage of a hit at this power before escalation, by hello.formulas.shotDamage.","subsystem":"gun","member":"shotDamage","path":["gun","shot_damage"],"stateless":false,"args":[{"name":"power","type":{"kind":"f64","description":"Shot power."},"description":"Shot power."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#shot_damage","symbol":"cy_gun_shot_damage","alias":null,"rust":{"module":"gun","fn":"shot_damage"}},{"name":"gun.power_for_speed","kind":"query","form":"call","since":"2.0","fact":"The power whose shot flies at this speed, within the legal powers, by hello.formulas.powerForSpeed.","subsystem":"gun","member":"powerForSpeed","path":["gun","power_for_speed"],"stateless":false,"args":[{"name":"speed","type":{"kind":"f64","description":"Shot speed, units/s."},"description":"Shot speed, units/s."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#power_for_speed","symbol":"cy_gun_power_for_speed","alias":null,"rust":{"module":"gun","fn":"power_for_speed"}},{"name":"gun.power_for_flight_time","kind":"query","form":"call","since":"2.0","fact":"The power whose shot covers this range in this time, within the legal powers.","subsystem":"gun","member":"powerForFlightTime","path":["gun","power_for_flight_time"],"stateless":false,"args":[{"name":"range","type":{"kind":"f64","description":"Distance, units."},"description":"Distance, units."},{"name":"seconds","type":{"kind":"f64","description":"Flight time."},"description":"Flight time."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#power_for_flight_time","symbol":"cy_gun_power_for_flight_time","alias":null,"rust":{"module":"gun","fn":"power_for_flight_time"}},{"name":"gun.lead","kind":"query","form":"call","since":"2.0","fact":"The aim at which a shot fired now meets the contact if it holds its tracked velocity; absent when no shot reaches it.","subsystem":"gun","member":"lead","path":["gun","lead"],"stateless":false,"args":[{"name":"contact","type":{"kind":"record","record":"contact","description":"A precise contact."},"description":"A precise contact."},{"name":"power","type":{"kind":"f64","description":"Shot power."},"description":"Shot power."}],"returns":{"kind":"record","record":"solution","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#lead","symbol":"cy_gun_lead_v1","alias":"cy_gun_lead","rust":{"module":"gun","fn":"lead"}},{"name":"gun.lead_point","kind":"query","form":"call","since":"2.0","fact":"The aim at which a shot fired now meets a point moving at this velocity; absent when no shot reaches it.","subsystem":"gun","member":"leadPoint","path":["gun","lead_point"],"stateless":false,"args":[{"name":"position","type":{"kind":"record","record":"vec3","description":"The target's position."},"description":"The target's position."},{"name":"velocity","type":{"kind":"record","record":"vec3","description":"Its velocity, units/s."},"description":"Its velocity, units/s."},{"name":"power","type":{"kind":"f64","description":"Shot power."},"description":"Shot power."}],"returns":{"kind":"record","record":"solution","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#lead_point","symbol":"cy_gun_lead_point_v1","alias":"cy_gun_lead_point","rust":{"module":"gun","fn":"lead_point"}},{"name":"gun.aim","kind":"control","form":"call","since":"2.0","fact":"Ask the turret to turn toward a direction; it slews at gun.turnRate.","subsystem":"gun","member":"aim","path":["gun","aim"],"stateless":false,"args":[],"returns":null,"fields":[{"key":"aim_heading","arg":"heading","type":"number","act":["aim","heading"],"limits":null,"optional":false,"description":"Turret heading.","symbol":"cy_gun_aim_heading","getter":"cy_gun_get_aim_heading","dsl":"aim-heading","glyph":"aim!"},{"key":"aim_pitch","arg":"pitch","type":"number","act":["aim","pitch"],"limits":null,"optional":true,"description":"Turret pitch, within ±robot.maxPitch; ignored in 2D.","symbol":"cy_gun_aim_pitch","getter":"cy_gun_get_aim_pitch","dsl":"aim-pitch","glyph":"aim-pitch!"}],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#aim","symbol":"cy_gun_aim","alias":null,"rust":{"module":"gun","fn":"aim"}},{"name":"gun.fire","kind":"control","form":"call","since":"2.0","fact":"Ask to fire this tick; the arena decides whether the gun and battery allow it.","subsystem":"gun","member":"fire","path":["gun","fire"],"stateless":false,"args":[],"returns":null,"fields":[{"key":"fire","arg":"fire","type":"flag","act":["fire",null],"limits":null,"optional":false,"description":"Fire this tick.","symbol":"cy_gun_fire","getter":"cy_gun_get_fire","dsl":"fire","glyph":"fire!"},{"key":"power","arg":"power","type":"number","act":["fire","power"],"limits":null,"optional":true,"description":"Shot power, gun.power.min to max.","symbol":"cy_gun_power","getter":"cy_gun_get_power","dsl":"power","glyph":"power!"}],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#fire","symbol":"cy_gun_fire","alias":null,"rust":{"module":"gun","fn":"fire"}},{"name":"gun.get","kind":"getter","form":"call","since":"2.0","fact":"What this tick's act holds for a gun field so far, as set.","subsystem":"gun","member":"get","path":["gun","get"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The value as set, before clamping (1 for fire), or absent while unset.","optional":true},"fields":[{"key":"aim_heading","arg":"heading","type":"number","act":["aim","heading"],"limits":null,"optional":false,"description":"Turret heading.","symbol":"cy_gun_aim_heading","getter":"cy_gun_get_aim_heading","dsl":"aim-heading","glyph":"aim!"},{"key":"aim_pitch","arg":"pitch","type":"number","act":["aim","pitch"],"limits":null,"optional":true,"description":"Turret pitch, within ±robot.maxPitch; ignored in 2D.","symbol":"cy_gun_aim_pitch","getter":"cy_gun_get_aim_pitch","dsl":"aim-pitch","glyph":"aim-pitch!"},{"key":"fire","arg":"fire","type":"flag","act":["fire",null],"limits":null,"optional":false,"description":"Fire this tick.","symbol":"cy_gun_fire","getter":"cy_gun_get_fire","dsl":"fire","glyph":"fire!"},{"key":"power","arg":"power","type":"number","act":["fire","power"],"limits":null,"optional":true,"description":"Shot power, gun.power.min to max.","symbol":"cy_gun_power","getter":"cy_gun_get_power","dsl":"power","glyph":"power!"}],"of":["gun.aim","gun.fire"],"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/gun.json#get","symbol":"cy_gun_get","alias":null,"rust":{"module":"gun","fn":"get"}},{"name":"scanner.last","kind":"query","form":"property","since":"2.0","fact":"The scan that produced this tick's contacts.","subsystem":"scanner","member":"last","path":["scanner","last"],"stateless":false,"args":[],"returns":{"kind":"record","record":"scan","description":""},"fields":[],"of":null,"dsl":{"scan-heading":"heading","scan-pitch":"pitch","scan-arc":"arc","scan-range":"range"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/scanner.json#last","symbol":"cy_scanner_last_v1","alias":"cy_scanner_last","rust":{"module":"scanner","fn":"last"}},{"name":"scanner.proximity_range","kind":"query","form":"property","since":"2.0","fact":"Robots this close are detected in any direction.","subsystem":"scanner","member":"proximityRange","path":["scanner","proximity_range"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Robots this close are detected in any direction.","from":"hello.scanner.proximityRange"},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/scanner.json#proximity_range","symbol":"cy_scanner_proximity_range","alias":null,"rust":{"module":"scanner","fn":"proximity_range"}},{"name":"scanner.reach","kind":"query","form":"call","since":"2.0","fact":"How far a scan of this arc reaches, by hello.formulas.reach.","subsystem":"scanner","member":"reach","path":["scanner","reach"],"stateless":false,"args":[{"name":"arc","type":{"kind":"f64","description":"Scan arc, degrees."},"description":"Scan arc, degrees."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/scanner.json#reach","symbol":"cy_scanner_reach","alias":null,"rust":{"module":"scanner","fn":"reach"}},{"name":"scanner.arc_for_reach","kind":"query","form":"call","since":"2.0","fact":"The widest arc that still reaches this far, by hello.formulas.arcForReach.","subsystem":"scanner","member":"arcForReach","path":["scanner","arc_for_reach"],"stateless":false,"args":[{"name":"range","type":{"kind":"f64","description":"Reach, units."},"description":"Reach, units."}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/scanner.json#arc_for_reach","symbol":"cy_scanner_arc_for_reach","alias":null,"rust":{"module":"scanner","fn":"arc_for_reach"}},{"name":"scanner.set","kind":"control","form":"call","since":"2.0","fact":"Ask where the scanner points for the next state.","subsystem":"scanner","member":"set","path":["scanner","set"],"stateless":false,"args":[],"returns":null,"fields":[{"key":"heading","arg":"heading","type":"number","act":["scan","heading"],"limits":null,"optional":true,"description":"Scan heading.","symbol":"cy_scanner_heading","getter":"cy_scanner_get_heading","dsl":"scan-heading","glyph":"scan-heading!"},{"key":"arc","arg":"arc","type":"number","act":["scan","arc"],"limits":null,"optional":true,"description":"Full cone width, scanner.minArc to maxArc.","symbol":"cy_scanner_arc","getter":"cy_scanner_get_arc","dsl":"scan-arc","glyph":"scan-arc!"},{"key":"pitch","arg":"pitch","type":"number","act":["scan","pitch"],"limits":null,"optional":true,"description":"Scan pitch; ignored in 2D.","symbol":"cy_scanner_pitch","getter":"cy_scanner_get_pitch","dsl":"scan-pitch","glyph":"scan-pitch!"}],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/scanner.json#set","symbol":"cy_scanner_set","alias":null,"rust":{"module":"scanner","fn":"set"}},{"name":"scanner.get","kind":"getter","form":"call","since":"2.0","fact":"What this tick's act holds for a scanner field so far, as set.","subsystem":"scanner","member":"get","path":["scanner","get"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The value as set, before clamping, or absent while unset.","optional":true},"fields":[{"key":"heading","arg":"heading","type":"number","act":["scan","heading"],"limits":null,"optional":true,"description":"Scan heading.","symbol":"cy_scanner_heading","getter":"cy_scanner_get_heading","dsl":"scan-heading","glyph":"scan-heading!"},{"key":"arc","arg":"arc","type":"number","act":["scan","arc"],"limits":null,"optional":true,"description":"Full cone width, scanner.minArc to maxArc.","symbol":"cy_scanner_arc","getter":"cy_scanner_get_arc","dsl":"scan-arc","glyph":"scan-arc!"},{"key":"pitch","arg":"pitch","type":"number","act":["scan","pitch"],"limits":null,"optional":true,"description":"Scan pitch; ignored in 2D.","symbol":"cy_scanner_pitch","getter":"cy_scanner_get_pitch","dsl":"scan-pitch","glyph":"scan-pitch!"}],"of":["scanner.set"],"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/scanner.json#get","symbol":"cy_scanner_get","alias":null,"rust":{"module":"scanner","fn":"get"}},{"name":"sensors.contacts","kind":"query","form":"property","since":"2.0","fact":"Every contact this tick: scan and proximity first, nearest first, then passive ones.","subsystem":"sensors","member":"contacts","path":["sensors","contacts"],"stateless":false,"args":[],"returns":{"kind":"record","record":"contact","description":"","list":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/sensors.json#contacts","symbol":"cy_sensors_contacts_v1","alias":"cy_sensors_contacts","rust":{"module":"sensors","fn":"contacts"}},{"name":"sensors.nearest","kind":"query","form":"property","since":"2.0","fact":"The nearest precise contact this tick. Passive contacts are never returned.","subsystem":"sensors","member":"nearest","path":["sensors","nearest"],"stateless":false,"args":[],"returns":{"kind":"record","record":"contact","description":"","optional":true},"fields":[],"of":null,"dsl":{"contact":"present","range":["range",1000000000000],"bearing":["bearing","me.heading"],"elevation":["elevation",0]},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/sensors.json#nearest","symbol":"cy_sensors_nearest_v1","alias":"cy_sensors_nearest","rust":{"module":"sensors","fn":"nearest"}},{"name":"sensors.cues","kind":"query","form":"property","since":"2.0","fact":"This tick's passive contacts, most accurate (smallest bearing error) first.","subsystem":"sensors","member":"cues","path":["sensors","cues"],"stateless":false,"args":[],"returns":{"kind":"record","record":"contact","description":"","list":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/sensors.json#cues","symbol":"cy_sensors_cues_v1","alias":"cy_sensors_cues","rust":{"module":"sensors","fn":"cues"}},{"name":"sensors.contact","kind":"query","form":"call","since":"2.0","fact":"The precise contact for a robot this tick, if it was detected.","subsystem":"sensors","member":"contact","path":["sensors","contact"],"stateless":false,"args":[{"name":"slot","type":{"kind":"i32","description":"A slot, 1 to match.robots."},"description":"A slot, 1 to match.robots."}],"returns":{"kind":"record","record":"contact","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/sensors.json#contact","symbol":"cy_sensors_contact_v1","alias":"cy_sensors_contact","rust":{"module":"sensors","fn":"contact"}},{"name":"sensors.position_of","kind":"query","form":"call","since":"2.0","fact":"Where a contact places its robot: your position plus its range along its bearing and elevation.","subsystem":"sensors","member":"positionOf","path":["sensors","position_of"],"stateless":false,"args":[{"name":"contact","type":{"kind":"record","record":"contact","description":""},"description":""}],"returns":{"kind":"record","record":"vec3","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/sensors.json#position_of","symbol":"cy_sensors_position_of_v1","alias":"cy_sensors_position_of","rust":{"module":"sensors","fn":"position_of"}},{"name":"tracker.cue","kind":"query","form":"property","since":"2.0","fact":"The most accurate passive contact heard in the last cue_ticks (60 by default), or absent.","subsystem":"tracker","member":"cue","path":["tracker","cue"],"stateless":false,"args":[],"returns":{"kind":"record","record":"cue","description":"","optional":true},"fields":[],"of":null,"dsl":{"cue-present":"present","cue-error":["bearing_error",0]},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/tracker.json#cue","symbol":"cy_tracker_cue_v1","alias":"cy_tracker_cue","rust":{"module":"tracker","fn":"cue"}},{"name":"tracker.nearest_bearing_rate","kind":"query","form":"property","since":"2.0","fact":"How fast the nearest contact's bearing turns, from two sightings.","subsystem":"tracker","member":"nearestBearingRate","path":["tracker","nearest_bearing_rate"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Degrees per second; 0 unless the nearest contact was seen this tick and the one before."},"fields":[],"of":null,"dsl":{"bearing-rate":"value"},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/tracker.json#nearest_bearing_rate","symbol":"cy_tracker_nearest_bearing_rate","alias":null,"rust":{"module":"tracker","fn":"nearest_bearing_rate"}},{"name":"tracker.velocity","kind":"query","form":"call","since":"2.0","fact":"The robot's tracked velocity; zero when it has no track.","subsystem":"tracker","member":"velocity","path":["tracker","velocity"],"stateless":false,"args":[{"name":"slot","type":{"kind":"i32","description":"A slot, 1 to match.robots."},"description":"A slot, 1 to match.robots."}],"returns":{"kind":"record","record":"vec3","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/tracker.json#velocity","symbol":"cy_tracker_velocity","alias":null,"rust":{"module":"tracker","fn":"velocity"}},{"name":"tracker.position","kind":"query","form":"call","since":"2.0","fact":"Where the robot was last seen, if it was.","subsystem":"tracker","member":"position","path":["tracker","position"],"stateless":false,"args":[{"name":"slot","type":{"kind":"i32","description":"A slot, 1 to match.robots."},"description":"A slot, 1 to match.robots."}],"returns":{"kind":"record","record":"vec3","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/tracker.json#position","symbol":"cy_tracker_position","alias":null,"rust":{"module":"tracker","fn":"position"}},{"name":"tracker.last_seen","kind":"query","form":"call","since":"2.0","fact":"The tick the robot was last seen, if it was.","subsystem":"tracker","member":"lastSeen","path":["tracker","last_seen"],"stateless":false,"args":[{"name":"slot","type":{"kind":"i32","description":"A slot, 1 to match.robots."},"description":"A slot, 1 to match.robots."}],"returns":{"kind":"i32","description":"A tick.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/tracker.json#last_seen","symbol":"cy_tracker_last_seen","alias":null,"rust":{"module":"tracker","fn":"last_seen"}},{"name":"tracker.configure","kind":"command","form":"call","since":"2.0","fact":"Sets the Tracker's parameters, in the robot's start only; after the first state it refuses with E_PHASE.","subsystem":"tracker","member":"configure","path":["tracker","configure"],"stateless":false,"args":[{"name":"smoothing","type":{"kind":"f64","description":"Weight of the old velocity, 0 to 1 (0.5)."},"description":"Weight of the old velocity, 0 to 1 (0.5).","default":0.5},{"name":"forget_ticks","type":{"kind":"i32","description":"Ticks after which a track restarts (40)."},"description":"Ticks after which a track restarts (40).","default":40},{"name":"cue_ticks","type":{"kind":"i32","description":"Ticks a cue is kept (60)."},"description":"Ticks a cue is kept (60).","default":60}],"returns":null,"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/tracker.json#configure","symbol":"cy_tracker_configure","alias":null,"rust":{"module":"tracker","fn":"configure"}},{"name":"nav.zone","kind":"query","form":"property","since":"2.0","fact":"The sudden-death safe zone, once sudden death starts.","subsystem":"nav","member":"zone","path":["nav","zone"],"stateless":false,"args":[],"returns":{"kind":"record","record":"zone","description":"","optional":true},"fields":[],"of":null,"dsl":{"zone-active":"present","zone-radius":["radius",0]},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#zone","symbol":"cy_nav_zone_v1","alias":"cy_nav_zone","rust":{"module":"nav","fn":"zone"}},{"name":"nav.zone.margin","kind":"query","form":"call","since":"2.0","fact":"How far inside the zone a point is, by its shape's distance; absent while there is none.","subsystem":"nav","member":"margin","path":["nav","zone","margin"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"Units; negative outside.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#zone.margin","symbol":"cy_nav_zone_margin","alias":null,"rust":{"module":"nav","fn":"zone_margin"}},{"name":"nav.zone.contains","kind":"query","form":"call","since":"2.0","fact":"The point is inside the zone by at least the margin; absent while there is none.","subsystem":"nav","member":"contains","path":["nav","zone","contains"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""},{"name":"margin","type":{"kind":"f64","description":"Units the point must be inside by (0)."},"description":"Units the point must be inside by (0).","default":0}],"returns":{"kind":"bool","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#zone.contains","symbol":"cy_nav_zone_contains","alias":null,"rust":{"module":"nav","fn":"zone_contains"}},{"name":"nav.zone.distance_from","kind":"query","form":"call","since":"2.0","fact":"How far a point is from the zone's edge, 0 inside; absent while there is none.","subsystem":"nav","member":"distanceFrom","path":["nav","zone","distance_from"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"Units; 0 inside.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#zone.distance_from","symbol":"cy_nav_zone_distance_from","alias":null,"rust":{"module":"nav","fn":"zone_distance_from"}},{"name":"nav.storm","kind":"query","form":"property","since":"2.0","fact":"The storm, once it enters.","subsystem":"nav","member":"storm","path":["nav","storm"],"stateless":false,"args":[],"returns":{"kind":"record","record":"storm","description":"","optional":true},"fields":[],"of":null,"dsl":{"storm-active":"present","storm-radius":["radius",0]},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#storm","symbol":"cy_nav_storm_v1","alias":"cy_nav_storm","rust":{"module":"nav","fn":"storm"}},{"name":"nav.storm.margin","kind":"query","form":"call","since":"2.0","fact":"How far inside the storm a point is, by its shape's distance; absent while there is none.","subsystem":"nav","member":"margin","path":["nav","storm","margin"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"Units; negative outside.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#storm.margin","symbol":"cy_nav_storm_margin","alias":null,"rust":{"module":"nav","fn":"storm_margin"}},{"name":"nav.storm.contains","kind":"query","form":"call","since":"2.0","fact":"The point is inside the storm by at least the margin; absent while there is none.","subsystem":"nav","member":"contains","path":["nav","storm","contains"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""},{"name":"margin","type":{"kind":"f64","description":"Units the point must be inside by (0)."},"description":"Units the point must be inside by (0).","default":0}],"returns":{"kind":"bool","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#storm.contains","symbol":"cy_nav_storm_contains","alias":null,"rust":{"module":"nav","fn":"storm_contains"}},{"name":"nav.storm.distance_from","kind":"query","form":"call","since":"2.0","fact":"How far a point is from the storm's edge, 0 inside; absent while there is none.","subsystem":"nav","member":"distanceFrom","path":["nav","storm","distance_from"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"Units; 0 inside.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#storm.distance_from","symbol":"cy_nav_storm_distance_from","alias":null,"rust":{"module":"nav","fn":"storm_distance_from"}},{"name":"nav.hill","kind":"query","form":"property","since":"2.0","fact":"The hill, once it appears.","subsystem":"nav","member":"hill","path":["nav","hill"],"stateless":false,"args":[],"returns":{"kind":"record","record":"hill","description":"","optional":true},"fields":[],"of":null,"dsl":{"hill-active":"present","hill-radius":["radius",0]},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#hill","symbol":"cy_nav_hill_v1","alias":"cy_nav_hill","rust":{"module":"nav","fn":"hill"}},{"name":"nav.hill.margin","kind":"query","form":"call","since":"2.0","fact":"How far inside the hill a point is, by its shape's distance; absent while there is none.","subsystem":"nav","member":"margin","path":["nav","hill","margin"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"Units; negative outside.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#hill.margin","symbol":"cy_nav_hill_margin","alias":null,"rust":{"module":"nav","fn":"hill_margin"}},{"name":"nav.hill.contains","kind":"query","form":"call","since":"2.0","fact":"The point is inside the hill by at least the margin; absent while there is none.","subsystem":"nav","member":"contains","path":["nav","hill","contains"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""},{"name":"margin","type":{"kind":"f64","description":"Units the point must be inside by (0)."},"description":"Units the point must be inside by (0).","default":0}],"returns":{"kind":"bool","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#hill.contains","symbol":"cy_nav_hill_contains","alias":null,"rust":{"module":"nav","fn":"hill_contains"}},{"name":"nav.hill.distance_from","kind":"query","form":"call","since":"2.0","fact":"How far a point is from the hill's edge, 0 inside; absent while there is none.","subsystem":"nav","member":"distanceFrom","path":["nav","hill","distance_from"],"stateless":false,"args":[{"name":"point","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"Units; 0 inside.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#hill.distance_from","symbol":"cy_nav_hill_distance_from","alias":null,"rust":{"module":"nav","fn":"hill_distance_from"}},{"name":"nav.pickups","kind":"query","form":"property","since":"2.0","fact":"Every pickup on the field.","subsystem":"nav","member":"pickups","path":["nav","pickups"],"stateless":false,"args":[],"returns":{"kind":"record","record":"pickup","description":"","list":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#pickups","symbol":"cy_nav_pickups_v1","alias":"cy_nav_pickups","rust":{"module":"nav","fn":"pickups"}},{"name":"nav.nearest_pickup","kind":"query","form":"call","since":"2.0","fact":"The pickup of this kind nearest you by field distance, if there is one.","subsystem":"nav","member":"nearestPickup","path":["nav","nearest_pickup"],"stateless":false,"args":[{"name":"kind","type":{"kind":"enum","enum":"pickup_kind","description":"A kind, or 0 for any."},"description":"A kind, or 0 for any."}],"returns":{"kind":"record","record":"pickup","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#nearest_pickup","symbol":"cy_nav_nearest_pickup_v1","alias":"cy_nav_nearest_pickup","rust":{"module":"nav","fn":"nearest_pickup"}},{"name":"nav.field_distance","kind":"query","form":"call","since":"2.0","fact":"The distance between two points as the field measures it: in the plane under gravity, in space otherwise.","subsystem":"nav","member":"fieldDistance","path":["nav","field_distance"],"stateless":false,"args":[{"name":"a","type":{"kind":"record","record":"vec3","description":""},"description":""},{"name":"b","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/nav.json#field_distance","symbol":"cy_nav_field_distance","alias":null,"rust":{"module":"nav","fn":"field_distance"}},{"name":"score.me","kind":"query","form":"property","since":"2.0","fact":"Your score; absent when the match does not score.","subsystem":"score","member":"me","path":["score","me"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Your score.","from":"state.objectives.score.self","optional":true},"fields":[],"of":null,"dsl":{"score":["value",0]},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/score.json#me","symbol":"cy_score_me","alias":null,"rust":{"module":"score","fn":"me"}},{"name":"score.best","kind":"query","form":"property","since":"2.0","fact":"The best other robot's score; absent when the match does not score.","subsystem":"score","member":"best","path":["score","best"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The best other robot's score.","from":"state.objectives.score.best","optional":true},"fields":[],"of":null,"dsl":{"score-best":["value",0]},"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/score.json#best","symbol":"cy_score_best","alias":null,"rust":{"module":"score","fn":"best"}},{"name":"score.armour","kind":"query","form":"property","since":"2.0","fact":"Your armour; absent when the match has no objectives.","subsystem":"score","member":"armour","path":["score","armour"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"Your armour, which absorbs shot damage before health.","from":"state.objectives.armour","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/score.json#armour","symbol":"cy_score_armour","alias":null,"rust":{"module":"score","fn":"armour"}},{"name":"angles.normalize","kind":"query","form":"call","since":"2.0","fact":"An angle brought into 0 to 360, exactly: degrees % 360, plus 360 when that is negative.","subsystem":"angles","member":"normalize","path":["angles","normalize"],"stateless":true,"args":[{"name":"degrees","type":{"kind":"f64","description":""},"description":""}],"returns":{"kind":"f64","description":"0 to 360; exactly 360 for a negative angle too small to subtract from it."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/angles.json#normalize","symbol":"cy_angles_normalize","alias":null,"rust":{"module":"angles","fn":"normalize"}},{"name":"angles.angle_diff","kind":"query","form":"call","since":"2.0","fact":"The signed turn from current to target: normalize(target - current + 540) - 180.","subsystem":"angles","member":"angleDiff","path":["angles","angle_diff"],"stateless":true,"args":[{"name":"target","type":{"kind":"f64","description":""},"description":""},{"name":"current","type":{"kind":"f64","description":""},"description":""}],"returns":{"kind":"f64","description":"-180 to 180."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/angles.json#angle_diff","symbol":"cy_angles_angle_diff","alias":null,"rust":{"module":"angles","fn":"angle_diff"}},{"name":"angles.bearing_to","kind":"query","form":"call","since":"2.0","fact":"The heading from one point to another.","subsystem":"angles","member":"bearingTo","path":["angles","bearing_to"],"stateless":true,"args":[{"name":"from","type":{"kind":"record","record":"vec3","description":""},"description":""},{"name":"to","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"0 to 360."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/angles.json#bearing_to","symbol":"cy_angles_bearing_to","alias":null,"rust":{"module":"angles","fn":"bearing_to"}},{"name":"angles.elevation_to","kind":"query","form":"call","since":"2.0","fact":"The elevation from one point to another.","subsystem":"angles","member":"elevationTo","path":["angles","elevation_to"],"stateless":true,"args":[{"name":"from","type":{"kind":"record","record":"vec3","description":""},"description":""},{"name":"to","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":"-90 to 90."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/angles.json#elevation_to","symbol":"cy_angles_elevation_to","alias":null,"rust":{"module":"angles","fn":"elevation_to"}},{"name":"angles.direction","kind":"query","form":"call","since":"2.0","fact":"The unit vector along a heading and pitch.","subsystem":"angles","member":"direction","path":["angles","direction"],"stateless":true,"args":[{"name":"heading","type":{"kind":"f64","description":""},"description":""},{"name":"pitch","type":{"kind":"f64","description":""},"description":""}],"returns":{"kind":"record","record":"vec3","description":"A unit vector."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/angles.json#direction","symbol":"cy_angles_direction","alias":null,"rust":{"module":"angles","fn":"direction"}},{"name":"angles.distance","kind":"query","form":"call","since":"2.0","fact":"The straight-line distance between two points.","subsystem":"angles","member":"distance","path":["angles","distance"],"stateless":true,"args":[{"name":"a","type":{"kind":"record","record":"vec3","description":""},"description":""},{"name":"b","type":{"kind":"record","record":"vec3","description":""},"description":""}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/angles.json#distance","symbol":"cy_angles_distance","alias":null,"rust":{"module":"angles","fn":"distance"}},{"name":"angles.clamp","kind":"query","form":"call","since":"2.0","fact":"A value held within low and high.","subsystem":"angles","member":"clamp","path":["angles","clamp"],"stateless":true,"args":[{"name":"value","type":{"kind":"f64","description":""},"description":""},{"name":"low","type":{"kind":"f64","description":"(-1)."},"description":"(-1).","default":-1},{"name":"high","type":{"kind":"f64","description":"(1)."},"description":"(1).","default":1}],"returns":{"kind":"f64","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/angles.json#clamp","symbol":"cy_angles_clamp","alias":null,"rust":{"module":"angles","fn":"clamp"}},{"name":"status.set","kind":"control","form":"call","since":"2.0","fact":"Set the status line; leaving it out keeps the last one.","subsystem":"status","member":"set","path":["status","set"],"stateless":false,"args":[],"returns":null,"fields":[{"key":"text","arg":"text","type":"text","act":["status","text"],"limits":null,"optional":true,"description":"Up to 32 characters; control characters are removed.","symbol":"cy_status_text","getter":"cy_status_get_text","dsl":"status-text","glyph":"status-text!"},{"key":"value","arg":"value","type":"number","act":["status","value"],"limits":null,"optional":true,"description":"A number shown beside the text, clamped to ±1,000,000,000.","symbol":"cy_status_value","getter":"cy_status_get_value","dsl":"status-value","glyph":"status-value!"}],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/status.json#set","symbol":"cy_status_set","alias":null,"rust":{"module":"status","fn":"set"}},{"name":"status.get","kind":"getter","form":"call","since":"2.0","fact":"What this tick's act holds for the status line so far, as set.","subsystem":"status","member":"get","path":["status","get"],"stateless":false,"args":[],"returns":{"kind":"f64","description":"The value as set, before clamping, or absent while unset.","optional":true},"fields":[{"key":"text","arg":"text","type":"text","act":["status","text"],"limits":null,"optional":true,"description":"Up to 32 characters; control characters are removed.","symbol":"cy_status_text","getter":"cy_status_get_text","dsl":"status-text","glyph":"status-text!"},{"key":"value","arg":"value","type":"number","act":["status","value"],"limits":null,"optional":true,"description":"A number shown beside the text, clamped to ±1,000,000,000.","symbol":"cy_status_value","getter":"cy_status_get_value","dsl":"status-value","glyph":"status-value!"}],"of":["status.set"],"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/status.json#get","symbol":"cy_status_get","alias":null,"rust":{"module":"status","fn":"get"}},{"name":"raw.number","kind":"query","form":"call","since":"2.0","fact":"The number at a path, if there is one.","subsystem":"raw","member":"number","path":["raw","number"],"stateless":false,"args":[{"name":"path","type":{"kind":"text","description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."},"description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."}],"returns":{"kind":"f64","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/raw.json#number","symbol":"cy_raw_number","alias":null,"rust":{"module":"raw","fn":"number"}},{"name":"raw.text","kind":"query","form":"call","since":"2.0","fact":"The string at a path, if there is one.","subsystem":"raw","member":"text","path":["raw","text"],"stateless":false,"args":[{"name":"path","type":{"kind":"text","description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."},"description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."}],"returns":{"kind":"text","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/raw.json#text","symbol":"cy_raw_text","alias":null,"rust":{"module":"raw","fn":"text"}},{"name":"raw.has","kind":"query","form":"call","since":"2.0","fact":"Something is at the path.","subsystem":"raw","member":"has","path":["raw","has"],"stateless":false,"args":[{"name":"path","type":{"kind":"text","description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."},"description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."}],"returns":{"kind":"bool","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/raw.json#has","symbol":"cy_raw_has","alias":null,"rust":{"module":"raw","fn":"has"}},{"name":"raw.flag","kind":"query","form":"call","since":"2.0","fact":"The boolean at a path, if there is one.","subsystem":"raw","member":"flag","path":["raw","flag"],"stateless":false,"args":[{"name":"path","type":{"kind":"text","description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."},"description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."}],"returns":{"kind":"bool","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/raw.json#flag","symbol":"cy_raw_flag","alias":null,"rust":{"module":"raw","fn":"flag"}},{"name":"raw.count","kind":"query","form":"call","since":"2.0","fact":"The length of the array at a path, if there is one.","subsystem":"raw","member":"count","path":["raw","count"],"stateless":false,"args":[{"name":"path","type":{"kind":"text","description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."},"description":"A wire path: hello or state, then .key and [n] parts, as state.sensors.contacts[0].range."}],"returns":{"kind":"i32","description":"","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/raw.json#count","symbol":"cy_raw_count","alias":null,"rust":{"module":"raw","fn":"count"}},{"name":"raw.line","kind":"query","form":"call","since":"2.0","fact":"The last line the session read: the hello, or the latest state.","subsystem":"raw","member":"line","path":["raw","line"],"stateless":false,"args":[],"returns":{"kind":"text","description":"The line, without its newline."},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/raw.json#line","symbol":"cy_raw_line","alias":null,"rust":{"module":"raw","fn":"line"}},{"name":"raw.extra","kind":"command","form":"call","since":"2.0","fact":"Adds fields the API does not cover to this tick's act; a key the API writes (v, type, tick, drive, forces, aim, scan, fire, status) is refused with E_ARGUMENT.","subsystem":"raw","member":"extra","path":["raw","extra"],"stateless":false,"args":[{"name":"json","type":{"kind":"text","description":"A JSON object, merged into the act at the top level, after the API's own members."},"description":"A JSON object, merged into the act at the top level, after the API's own members."}],"returns":null,"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/raw.json#extra","symbol":"cy_raw_extra","alias":null,"rust":{"module":"raw","fn":"extra"}},{"name":"session.event","kind":"query","form":"property","since":"2.0","fact":"What the last next() read.","subsystem":"session","member":"event","path":["session","event"],"stateless":false,"args":[],"returns":{"kind":"enum","enum":"event","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":false,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/session.json#event","symbol":"cy_session_event","alias":null,"rust":{"module":"session","fn":"event"}},{"name":"session.next","kind":"command","form":"call","since":"2.0","fact":"Reads the next message and decodes it.","subsystem":"session","member":"next","path":["session","next"],"stateless":false,"args":[],"returns":{"kind":"enum","enum":"event","description":""},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":false,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/session.json#next","symbol":"cy_session_next","alias":null,"rust":{"module":"session","fn":"next"}},{"name":"session.send","kind":"command","form":"call","since":"2.0","fact":"Writes the ready reply after a hello, or this tick's act after a state, and clears the pending act.","subsystem":"session","member":"send","path":["session","send"],"stateless":false,"args":[],"returns":null,"fields":[],"of":null,"dsl":null,"rename":{},"wasm":false,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/session.json#send","symbol":"cy_session_send","alias":null,"rust":{"module":"session","fn":"send"}},{"name":"session.forfeit","kind":"command","form":"call","since":"2.0","fact":"Writes a forfeit in place of this tick's act.","subsystem":"session","member":"forfeit","path":["session","forfeit"],"stateless":false,"args":[{"name":"code","type":{"kind":"text","description":"A short code, such as LOST_TRACK."},"description":"A short code, such as LOST_TRACK."},{"name":"message","type":{"kind":"text","description":"Why."},"description":"Why."}],"returns":null,"fields":[],"of":null,"dsl":null,"rename":{},"wasm":false,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/session.json#forfeit","symbol":"cy_session_forfeit","alias":null,"rust":{"module":"session","fn":"forfeit"}},{"name":"session.log","kind":"command","form":"call","since":"2.0","fact":"Writes a line to standard error, never to the protocol.","subsystem":"session","member":"log","path":["session","log"],"stateless":false,"args":[{"name":"line","type":{"kind":"text","description":"A line for the log."},"description":"A line for the log."}],"returns":null,"fields":[],"of":null,"dsl":null,"rename":{},"wasm":true,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/session.json#log","symbol":"cy_session_log","alias":null,"rust":{"module":"session","fn":"log"}},{"name":"session.feed","kind":"command","form":"call","since":"2.0","fact":"Hands the memory port a line, for tests and event-loop runtimes.","subsystem":"session","member":"feed","path":["session","feed"],"stateless":false,"args":[{"name":"line","type":{"kind":"text","description":"One protocol line."},"description":"One protocol line."}],"returns":null,"fields":[],"of":null,"dsl":null,"rename":{},"wasm":false,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/session.json#feed","symbol":"cy_session_feed","alias":null,"rust":{"module":"session","fn":"feed"}},{"name":"session.reply","kind":"command","form":"call","since":"2.0","fact":"Takes the memory port's next written line, if any.","subsystem":"session","member":"reply","path":["session","reply"],"stateless":false,"args":[],"returns":{"kind":"text","description":"The line, without its newline.","optional":true},"fields":[],"of":null,"dsl":null,"rename":{},"wasm":false,"bindings":true,"version":1,"vectors":"protocol/v2/vectors/api/session.json#reply","symbol":"cy_session_reply","alias":null,"rust":{"module":"session","fn":"reply"}}]};
|
|
4
|
+
|
|
5
|
+
const {load,CoreError,CoreFault,NONE,SHORT}=require('./core');
|
|
6
|
+
const core=load(require('node:fs').readFileSync(require('node:path').join(__dirname,'clunkyard-core.wasm')));
|
|
7
|
+
const camel=name=>name.replace(/_([a-z0-9])/g,(_,letter)=>letter.toUpperCase());
|
|
8
|
+
const records=new Map(API.records.map(record=>[record.name,record]));
|
|
9
|
+
const enums=new Map(API.enums.map(item=>[item.name,item.values]));
|
|
10
|
+
const entries=new Map(API.entries.map(entry=>[entry.name,entry]));
|
|
11
|
+
const encoder=new TextEncoder(),decoder=new TextDecoder();
|
|
12
|
+
function read(robot,type,at){
|
|
13
|
+
const view=robot.view();
|
|
14
|
+
if(type.kind==='record'){
|
|
15
|
+
const record=records.get(type.record),value={};
|
|
16
|
+
for(const field of record.fields)if(field.name!=='reserved')value[camel(field.name)]=read(robot,field.type,at+field.offset);
|
|
17
|
+
for(const entry of API.entries.filter(item=>item.bindings&&item.path.length===3&&entries.get(item.path.slice(0,2).join('.'))?.returns.record===record.name))
|
|
18
|
+
Object.defineProperty(value,entry.member,{value:(...args)=>call(robot,entry,args)});
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
if(type.kind==='f64')return view.getFloat64(at,true);
|
|
22
|
+
const value=view.getInt32(at,true);
|
|
23
|
+
return type.kind==='enum'?enums.get(type.enum).find(item=>item.value===value)?.wire??null:type.kind==='bool'?Boolean(value):value;
|
|
24
|
+
}
|
|
25
|
+
function write(robot,type,at,value){
|
|
26
|
+
if(type.kind==='record'){
|
|
27
|
+
for(const field of records.get(type.record).fields)write(robot,field.type,at+field.offset,value?.[camel(field.name)]??0);
|
|
28
|
+
}else if(type.kind==='f64')robot.view().setFloat64(at,Number(value),true);
|
|
29
|
+
else robot.view().setInt32(at,type.kind==='enum'?(enums.get(type.enum).find(item=>item.wire===value)?.value??(value===0?0:-1)):Number(value),true);
|
|
30
|
+
}
|
|
31
|
+
function call(robot,entry,values=[]){
|
|
32
|
+
let size=65536+entry.args.reduce((bytes,arg,index)=>bytes+(arg.type.kind==='text'?encoder.encode(String(values[index]??arg.default??0)).length:arg.type.kind==='record'?records.get(arg.type.record).size:0)+8,0);
|
|
33
|
+
for(;;){
|
|
34
|
+
robot.reserve(size);
|
|
35
|
+
let offset=8;
|
|
36
|
+
const alloc=length=>{const at=robot.scratch+offset;offset=(offset+length+7)&~7;return at;};
|
|
37
|
+
const params=entry.stateless?[]:[robot.handle];
|
|
38
|
+
for(const [index,arg] of entry.args.entries()){
|
|
39
|
+
const value=values[index]??arg.default??0;
|
|
40
|
+
if(arg.type.kind==='text'){
|
|
41
|
+
const bytes=encoder.encode(String(value)),at=alloc(bytes.length);robot.bytes().set(bytes,at);params.push(at,bytes.length);
|
|
42
|
+
}else if(arg.type.kind==='record'){
|
|
43
|
+
const at=alloc(records.get(arg.type.record).size);write(robot,arg.type,at,value);params.push(at);
|
|
44
|
+
}else params.push(arg.type.kind==='enum'?(enums.get(arg.type.enum).find(item=>item.wire===value)?.value??(value===0?0:-1)):Number(value));
|
|
45
|
+
}
|
|
46
|
+
const result=entry.returns,at=robot.scratch+offset;
|
|
47
|
+
if(result){
|
|
48
|
+
params.push(at);
|
|
49
|
+
if(result.list||result.kind==='text')params.push(result.list?Math.floor((size-offset)/records.get(result.record).size):size-offset,robot.scratch);
|
|
50
|
+
}
|
|
51
|
+
const status=robot.check(entry.symbol,robot.invoke(entry.symbol,...params));
|
|
52
|
+
if(status===NONE)return null;
|
|
53
|
+
const count=robot.view().getUint32(robot.scratch,true);
|
|
54
|
+
if(status===SHORT){size=Math.max(size*2,offset+(result.list?count*records.get(result.record).size:count+1));continue;}
|
|
55
|
+
if(!result)return;
|
|
56
|
+
if(result.kind==='text')return decoder.decode(robot.bytes().subarray(at,at+count));
|
|
57
|
+
if(result.list)return Array.from({length:count},(_,index)=>read(robot,{kind:'record',record:result.record},at+index*records.get(result.record).size));
|
|
58
|
+
return read(robot,result,at);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function setter(robot,field,value){
|
|
62
|
+
return call(robot,{symbol:field.symbol,stateless:false,args:field.type==='flag'?[]:[{type:{kind:field.type==='text'?'text':'f64'}}]},field.type==='flag'?[]:[value]);
|
|
63
|
+
}
|
|
64
|
+
function getter(robot,field){return call(robot,{symbol:field.getter,stateless:false,args:[],returns:{kind:field.type==='text'?'text':'f64'}});}
|
|
65
|
+
function subsystem(robot,name){
|
|
66
|
+
const object={};
|
|
67
|
+
for(const entry of API.entries.filter(item=>item.bindings&&item.subsystem===name&&item.path.length===2)){
|
|
68
|
+
let value;
|
|
69
|
+
if(entry.kind==='control')value=(fields={})=>{
|
|
70
|
+
for(const field of entry.fields)if(field.type==='flag'||Object.hasOwn(fields,camel(field.arg)))setter(robot,field,fields[camel(field.arg)]);
|
|
71
|
+
};
|
|
72
|
+
else if(entry.kind==='getter')value=name=>{const field=entry.fields.find(item=>camel(item.arg)===name);if(!field)throw new Error('unknown control field: '+name);return getter(robot,field);};
|
|
73
|
+
else value=(...args)=>call(robot,entry,args);
|
|
74
|
+
Object.defineProperty(object,entry.member,entry.form==='property'?{get:value}:{value,writable:true,configurable:true});
|
|
75
|
+
}
|
|
76
|
+
return object;
|
|
77
|
+
}
|
|
78
|
+
function attach(bot,{bindingName='clunkyard-javascript'}={}){
|
|
79
|
+
const robot=core.robot({binding:bindingName,version:API.version});
|
|
80
|
+
for(const item of API.subsystems)bot[item.name]=subsystem(robot,item.name);
|
|
81
|
+
// Use the shared loader's trap recovery for the memory-port session.
|
|
82
|
+
Object.assign(bot.session,{next:()=>robot.next(),feed:line=>robot.feed(line),send:()=>robot.send(),reply:()=>robot.reply(),forfeit:(code,message)=>robot.forfeit(code,message)});
|
|
83
|
+
return robot;
|
|
84
|
+
}
|
|
85
|
+
module.exports={API,read,call,setter,getter,attach,subsystem,core,CoreError,CoreFault};
|
|
Binary file
|