The Haskell binding

Clunkyard provides the core's C functions as Haskell IO actions, native record types with generated Storable instances and camel case names such as cySensorsNearest. Functions return a status and copy values through pointers. check robot status throws CoreError for a negative status; query robot action copies a required result and optional robot action returns Nothing for cyNone.

Install with make install SDK=/opt/clunkyard/sdk. Compile with ghc -O2 -i/opt/clunkyard/sdk/bindings/haskell -odir build -hidir build bot.hs /opt/clunkyard/sdk/lib/libclunkyard.a -lpthread -ldl -lm -o bot. Create build first. The core links statically; only the executable goes in the robot artifact.

run onTurn onStart owns the protocol loop and closes the session. Both callbacks receive the core handle; use const (pure ()) when no start hook is needed. Exceptions are logged and the turn sends controls already set. Throw Forfeit code message for an explicit forfeit. A core fault sends the empty reply and continues. play lines onTurn onStart returns the replies from a memory session. withText scopes a UTF-8 text pointer and byte count.

A tiny robot

module Main where
import Clunkyard
import Foreign
import Control.Monad
turnBot robot = do
  target <- optional robot (cySensorsNearest robot)
  heading <- query robot (cyMeHeading robot)
  case target of
    Nothing -> do
      cyDriveThrottle robot 0.75 >>= check robot
      cyDriveTurn robot 0.25 >>= check robot
      cyScannerHeading robot heading >>= check robot
      cyScannerArc robot 40 >>= check robot
      lastScan <- query robot (cyScannerLast robot)
      withText "SEARCH" (cyStatusText robot) >>= check robot
      cyStatusValue robot (scanArc lastScan) >>= check robot
    Just t -> do
      power <- query robot (cyGunPowerForFlightTime robot (contactRange t) 1)
      lead <- with t $ \contact -> optional robot (cyGunLead robot contact power)
      let (aimHeading,aimPitch) = maybe (contactBearing t,contactElevation t) (\s -> (solutionHeading s,solutionPitch s)) lead
      cyGunAimHeading robot aimHeading >>= check robot
      cyGunAimPitch robot aimPitch >>= check robot
      canFire <- query robot (cyGunCanFire robot power 10)
      when (canFire /= 0) $ do
        cyGunFire robot >>= check robot
        cyGunPower robot power >>= check robot
      delta <- query robot (cyAnglesAngleDiff (contactBearing t) heading)
      control <- query robot (cyAnglesClamp delta (-1) 1)
      cyDriveThrottle robot 0.5 >>= check robot
      cyDriveTurn robot control >>= check robot
      cyScannerHeading robot (contactBearing t) >>= check robot
      cyScannerArc robot 10 >>= check robot
      withText "TRACK" (cyStatusText robot) >>= check robot
      cyStatusValue robot (contactRange t) >>= check robot
main = run turnBot (const (pure ()))

make test checks every Haskell declaration against the core's full vectors, including typed foreign arguments, records, exact floating-point results and serialized acts.

Names

Every entry of the robot API 2.0.0 in Haskell. names.md has every language side by side.

Canonical Form Haskell
match.mode property cyMatchMode
match.ruleset property cyMatchRuleset
match.control property cyMatchControl
match.robots property cyMatchRobots
match.is_3d property cyMatchIs3d
match.tick_rate property cyMatchTickRate
match.max_ticks property cyMatchMaxTicks
match.robot_id call cyRobotId
clock.tick property cyClockTick
clock.seconds property cyClockSeconds
clock.remaining_ticks property cyClockRemainingTicks
arena.size property cyArenaSize
arena.gravity property cyArenaGravity
arena.terrain_kind property cyArenaTerrainKind
arena.ground_height call cyArenaGroundHeight
me.health property cyMeHealth
me.position property cyMePosition
me.velocity property cyMeVelocity
me.heading property cyMeHeading
me.pitch property cyMePitch
me.roll property cyMeRoll
me.angular_velocity property cyMeAngularVelocity
me.attitude property cyMeAttitude
me.grounded property cyMeGrounded
me.altitude property cyMeAltitude
me.applied property cyMeApplied
battery.charge property cyBatteryCharge
battery.capacity property cyBatteryCapacity
battery.regen property cyBatteryRegen
battery.sustainable_drive property cyBatterySustainableDrive
battery.compute property cyBatteryCompute
battery.drive_cost call cyBatteryDriveCost
drive.hover_lift property cyDriveHoverLift
drive.set control cyDriveThrottle, cyDriveTurn, cyDrivePitchTurn
drive.forces control cyDriveThrust, cyDriveStrafe, cyDriveLift, cyDriveYawTorque, cyDrivePitchTorque, cyDriveRollTorque, cyDriveBrake
drive.get call cyDriveGetThrottle, cyDriveGetTurn, cyDriveGetPitchTurn, cyDriveGetThrust, cyDriveGetStrafe, cyDriveGetLift, cyDriveGetYawTorque, cyDriveGetPitchTorque, cyDriveGetRollTorque, cyDriveGetBrake
gun.aim_now property cyGunAimNow
gun.cooldown_ticks property cyGunCooldownTicks
gun.spread property cyGunSpread
gun.max_power property cyGunMaxPower
gun.damage_scale property cyGunDamageScale
gun.can_fire call cyGunCanFire
gun.shot_speed call cyGunShotSpeed
gun.shot_cost call cyGunShotCost
gun.reload_ticks call cyGunReloadTicks
gun.shot_damage call cyGunShotDamage
gun.power_for_speed call cyGunPowerForSpeed
gun.power_for_flight_time call cyGunPowerForFlightTime
gun.lead call cyGunLead
gun.lead_point call cyGunLeadPoint
gun.aim control cyGunAimHeading, cyGunAimPitch
gun.fire control cyGunFire, cyGunPower
gun.get call cyGunGetAimHeading, cyGunGetAimPitch, cyGunGetFire, cyGunGetPower
scanner.last property cyScannerLast
scanner.proximity_range property cyScannerProximityRange
scanner.reach call cyScannerReach
scanner.arc_for_reach call cyScannerArcForReach
scanner.set control cyScannerHeading, cyScannerArc, cyScannerPitch
scanner.get call cyScannerGetHeading, cyScannerGetArc, cyScannerGetPitch
sensors.contacts property cySensorsContacts
sensors.nearest property cySensorsNearest
sensors.cues property cySensorsCues
sensors.contact call cySensorsContact
sensors.position_of call cySensorsPositionOf
tracker.cue property cyTrackerCue
tracker.nearest_bearing_rate property cyTrackerNearestBearingRate
tracker.velocity call cyTrackerVelocity
tracker.position call cyTrackerPosition
tracker.last_seen call cyTrackerLastSeen
tracker.configure call cyTrackerConfigure
nav.zone property cyNavZone
nav.zone.margin call cyNavZoneMargin
nav.zone.contains call cyNavZoneContains
nav.zone.distance_from call cyNavZoneDistanceFrom
nav.storm property cyNavStorm
nav.storm.margin call cyNavStormMargin
nav.storm.contains call cyNavStormContains
nav.storm.distance_from call cyNavStormDistanceFrom
nav.hill property cyNavHill
nav.hill.margin call cyNavHillMargin
nav.hill.contains call cyNavHillContains
nav.hill.distance_from call cyNavHillDistanceFrom
nav.pickups property cyNavPickups
nav.nearest_pickup call cyNavNearestPickup
nav.field_distance call cyNavFieldDistance
score.me property cyScoreMe
score.best property cyScoreBest
score.armour property cyScoreArmour
angles.normalize call cyAnglesNormalize
angles.angle_diff call cyAnglesAngleDiff
angles.bearing_to call cyAnglesBearingTo
angles.elevation_to call cyAnglesElevationTo
angles.direction call cyAnglesDirection
angles.distance call cyAnglesDistance
angles.clamp call cyAnglesClamp
status.set control cyStatusText, cyStatusValue
status.get call cyStatusGetText, cyStatusGetValue
raw.number call cyRawNumber
raw.text call cyRawText
raw.has call cyRawHas
raw.flag call cyRawFlag
raw.count call cyRawCount
raw.line call cyRawLine
raw.extra call cyRawExtra
session.event property cySessionEvent
session.next call cySessionNext
session.send call cySessionSend
session.forfeit call cySessionForfeit
session.log call cySessionLog
session.feed call cySessionFeed
session.reply call cySessionReply

Download this page as Markdown