librarydemos/rosetta/Comparison.xtl

Comparison: the Rosetta stone's state machine (docs/rosetta.md), a library beside the demo ("cm:" u_se< "Comparison"). The state is one 4 x 5 matrix of numbers. The first three rows are the axes (the idiom drum, the top ring, the bottom ring), four columns each: how many items the axis has, how many steps it has taken (an integer; the item facing is 1 + steps, wrapped, and this is the truth), its angle in degrees (90 per step; the presentation, easing toward 90 * steps) and whether it plays on its own. The fourth row is the pointer: the axis being dragged (0 none, 0.5 pressed and not yet moved, else the axis), where it last was (x, y), how far it has moved in all, and the last turn it gave in degrees (for a flick). The fifth row is the attract mode's clock: seconds since the last interaction, seconds since its last step, and its two counters (how far the bottom ring is through its sweep of the other languages, how far the drum is through its sweep of the idioms). Nothing is ever inferred from an angle except what to draw. Every function gives a new state; none has an effect. Events (RS1) come in as []E_VENT gives them; cm:u_pdate takes one.

source

ˡdwell : Float

value · line 34

The attract mode's pace, in seconds: how long a comparison holds still before the next (long enough to read two faces of code), and how long after an interaction the stone waits before moving on its own again (long enough to look round a comparison by hand). The traversal is the nested loop for top, for idiom, for bottom: the bottom ring steps at each dwell; when it has swept every other language the drum rolls to the next idiom in the same instant, the bottom going on round; and only when every idiom has been shown does the top ring advance to the next language. So the language compared from stays put through the whole table, and no comparison comes round again within minutes (the user, 2026-10-06; before, the top stepped after each sweep of the bottom and the drum after each sweep of the top: two minutes per idiom and the same pairs again and again).

ˡdwell ← 5.0
Used in: ˡt̲ick

ˡidleBefore : Float

value · line 35
ˡidleBefore ← 20.0

ˡs̲tart : (Num a, Num b) => a -> b -> Float

function · line 47

The state for i idioms and l languages, i ᶜᵐs̲tart l: nothing turned, all playing, no pointer, the attract mode ready (idle long enough already).

      ᶜᵐ⁼u̲se< "Comparison"
      31 ᶜᵐs̲tart 7
31.0 0.0 0.0 1.0 0.0
 7.0 0.0 0.0 1.0 0.0
 7.0 0.0 0.0 1.0 0.0
 0.0 0.0 0.0 0.0 0.0
20.0 0.0 0.0 0.0 0.0
ˡs̲tart ← { i l → 5 5 r̲eshape (f̲loat i) c̲at 0.0 0.0 1.0 0.0 c̲at (f̲loat l) c̲at 0.0 0.0 1.0 0.0 c̲at (f̲loat l) c̲at 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 c̲at ˡidleBefore c̲at 0.0 0.0 0.0 0.0 }
Used in: start

ˡIDIOM : Float

value · line 50

The rows and columns, by name.

ˡIDIOM ← 1.0

ˡTOP : Float

value · line 51
ˡTOP ← 2.0

ˡBOTTOM : Float

value · line 52
ˡBOTTOM ← 3.0

ˡPOINTER : Float

value · line 53
ˡPOINTER ← 4.0

ˡATTRACT : Float

value · line 54
ˡATTRACT ← 5.0

ˡIDLE : Float

value · line 55
ˡIDLE ← 1.0

ˡSINCE : Float

value · line 56
ˡSINCE ← 2.0

ˡBOTTOMS : Float

value · line 57
ˡBOTTOMS ← 3.0
Used in: ˡa̲ttract

ˡIDIOMS : Float

value · line 58
ˡIDIOMS ← 4.0
Used in: ˡa̲ttract

ˡCOUNT : Float

value · line 59
ˡCOUNT ← 1.0

ˡSTEPS : Float

value · line 60
ˡSTEPS ← 2.0

ˡANGLE : Float

value · line 61
ˡANGLE ← 3.0

ˡPLAYING : Float

value · line 62
ˡPLAYING ← 4.0

ˡDRAGGING : Float

value · line 63
ˡDRAGGING ← 1.0

ˡX : Float

value · line 64
ˡX ← 2.0
Used in: ˡd̲own, ˡm̲ove

ˡY : Float

value · line 65
ˡY ← 3.0
Used in: ˡd̲own, ˡm̲ove

ˡMOVED : Float

value · line 66
ˡMOVED ← 4.0
Used in: ˡd̲own, ˡm̲ove

ˡLAST : Float

value · line 67
ˡLAST ← 5.0

ˡmiddle : Float

value · line 72

The picture's middle, in its own pixels (Stone's size is 420): the top half above it, the bottom half below; and how many degrees a pixel of drag turns an axis (a quarter turn across half the picture).

ˡmiddle ← 210.0
Used in: ˡh̲alf

ˡperPixel : Float

value · line 73
ˡperPixel ← 90.0 ÷ 210.0
Used in: ˡm̲ove

ˡa̲t : Num a => a -> b -> b

function · line 76

A cell of the state: (row c̲at col) ᶜᵐa̲t state.

ˡa̲t ← { rc state → (f̲loor 2 s̲elect rc) s̲elect (f̲loor 1 s̲elect rc) s̲elect state }

ˡp̲ut : Float -> Float -> Float

function · line 80

The state with one cell replaced: (row c̲at col c̲at v) ᶜᵐp̲ut state (a mask over the matrix, so no cell is ever addressed by hand).

ˡp̲ut ← { rcv state →
  mask ← f̲loat (rows = 1 s̲elect rcv) × cols = 2 s̲elect rcv
  (state × 1.0 − mask) + mask × 3 s̲elect rcv
}

rows : Float

value (private) · line 84
rows ← 5 5 r̲eshape 5 r̲eplicate 1.0 2.0 3.0 4.0 5.0
Used in: ˡp̲ut

cols : Float

value (private) · line 85
cols ← 5 5 r̲eshape 1.0 2.0 3.0 4.0 5.0
Used in: ˡp̲ut

ˡw̲rap : Int -> Int -> Int

function · line 88

An item of an axis of n, wrapped around: item k of n for any integer k.

ˡw̲rap ← { n k → 1 + (k − 1) m̲od n }

ˡc̲urrent : Float -> Float -> Int

function · line 94

The item facing on an axis: 1 + its steps, wrapped.

      ᶜᵐ⁼u̲se< "Comparison"
      ᶜᵐTOP ᶜᵐc̲urrent (ᶜᵐTOP c̲at 1.0) ᶜᵐs̲tep 31 ᶜᵐs̲tart 7
2
ˡc̲urrent ← { axis state → (f̲loor 0.5 + (axis c̲at ˡCOUNT) ˡa̲t state) ˡw̲rap f̲loor 1.5 + (axis c̲at ˡSTEPS) ˡa̲t state }

ˡs̲tep : Float -> Float -> Float

function · line 105

An axis stepped by d items (1 forward, -1 back): its steps change, its angle will follow at each tick. A ring never stops on the other ring's language (the two halves always compare two languages): it steps once more the same way. (axis c̲at d) ᶜᵐs̲tep state.

      ᶜᵐ⁼u̲se< "Comparison"
      ᶜᵐIDIOM ᶜᵐc̲urrent (ᶜᵐIDIOM c̲at -1.0) ᶜᵐs̲tep 31 ᶜᵐs̲tart 7
31
      ᶜᵐBOTTOM ᶜᵐc̲urrent (ᶜᵐBOTTOM c̲at 1.0) ᶜᵐs̲tep (ᶜᵐTOP c̲at 2.0) ᶜᵐc̲hoose 31 ᶜᵐs̲tart 7
3
ˡs̲tep ← { ad state →
  axis ← 1 s̲elect ad
  d ← 2 s̲elect ad
  moved ← (axis c̲at ˡSTEPS c̲at d + (axis c̲at ˡSTEPS) ˡa̲t state) ˡp̲ut state
  axis = ˡIDIOM ? moved
  other ← 5.0 − axis
  clash ← (axis ˡc̲urrent moved) = other ˡc̲urrent moved
  "clash" i̲f< "(axis c_at d) l:s_tep moved; moved"
}
i̲f< expands to
{ @ → (clash) ? (axis c̲at d) ˡs̲tep moved◆ moved } @

ˡc̲hoose : Float -> Float -> Float

function · line 124

An axis turned to item k the short way round, and paused: choosing is navigating, turning is exploring. A ring is not turned to the other ring's language (the choice is offered disabled); the state is unchanged. (axis c̲at k) ᶜᵐc̲hoose state.

      ᶜᵐ⁼u̲se< "Comparison"
      ᶜᵐTOP ᶜᵐc̲urrent (ᶜᵐTOP c̲at 7.0) ᶜᵐc̲hoose 31 ᶜᵐs̲tart 7
7
      (ᶜᵐTOP c̲at ᶜᵐSTEPS) ᶜᵐa̲t (ᶜᵐTOP c̲at 7.0) ᶜᵐc̲hoose 31 ᶜᵐs̲tart 7
-1.0
ˡc̲hoose ← { ak state →
  axis ← 1 s̲elect ak
  n ← f̲loor 0.5 + (axis c̲at ˡCOUNT) ˡa̲t state
  d ← ((f̲loor 2 s̲elect ak) − axis ˡc̲urrent state) m̲od n
  short ← "(2 * d) > n" i̲f< "d - n; d"
  chosen ← (axis c̲at ˡPLAYING c̲at 0.0) ˡp̲ut (axis c̲at f̲loat short) ˡs̲tep state
  axis = ˡIDIOM ? chosen
  (f̲loor 2 s̲elect ak) = (5.0 − axis) ˡc̲urrent state ? state
  chosen
}
i̲f< expands to
({ @ → ((2 × d) > n) ? d − n◆ d } @)
Used in: ˡu̲pdate, start

ˡe̲ase : Float -> Float -> Float

function · line 141

An axis's angle eased toward 90 times its steps over dt seconds: it covers the gap in about half a second, and lands exactly when near. (axis c̲at dt) ᶜᵐe̲ase state.

      ᶜᵐ⁼u̲se< "Comparison"
      (ᶜᵐTOP c̲at ᶜᵐANGLE) ᶜᵐa̲t (ᶜᵐTOP c̲at 0.25) ᶜᵐe̲ase (ᶜᵐTOP c̲at 1.0) ᶜᵐs̲tep 31 ᶜᵐs̲tart 7
45.0
ˡe̲ase ← { adt state →
  axis ← 1 s̲elect adt
  angle ← (axis c̲at ˡANGLE) ˡa̲t state
  target ← 90.0 × (axis c̲at ˡSTEPS) ˡa̲t state
  gap ← target − angle
  moved ← angle + gap × 1.0 m̲in 2.0 × 2 s̲elect adt
  near ← "0.5 > a_bs target - moved" i̲f< "target; moved"
  (axis c̲at ˡANGLE c̲at near) ˡp̲ut state
}
i̲f< expands to
({ @ → (0.5 > a̲bs target − moved) ? target◆ moved } @)

ˡs̲ettle : Float -> Float

function · line 160

Every axis at rest where its steps put it (angles 90 times steps), for a state built by choosing before the first tick.

      ᶜᵐ⁼u̲se< "Comparison"
      ᶜᵐs̲ettle (ᶜᵐIDIOM c̲at 3.0) ᶜᵐc̲hoose 31 ᶜᵐs̲tart 7
31.0 2.0 180.0 0.0 0.0
 7.0 0.0   0.0 1.0 0.0
 7.0 0.0   0.0 1.0 0.0
 0.0 0.0   0.0 0.0 0.0
20.0 0.0   0.0 0.0 0.0
ˡs̲ettle ← { state → (ˡBOTTOM c̲at 9.0) ˡe̲ase (ˡTOP c̲at 9.0) ˡe̲ase (ˡIDIOM c̲at 9.0) ˡe̲ase state }
Used in: start

ˡt̲ick : Float -> Float -> Float

function · line 171

Every axis eased over dt seconds (a tick), and the attract mode's clock advanced: when the stone has been left alone long enough and the last comparison has held still for a dwell, the attract mode steps (cm:a_ttract).

      ᶜᵐ⁼u̲se< "Comparison"
      ᶜᵐBOTTOM ᶜᵐc̲urrent ᶜᵐdwell ᶜᵐt̲ick 31 ᶜᵐs̲tart 7
2
      ᶜᵐBOTTOM ᶜᵐc̲urrent (ᶜᵐdwell − 0.1) ᶜᵐt̲ick 31 ᶜᵐs̲tart 7
1
ˡt̲ick ← { dt state →
  eased ← (ˡBOTTOM c̲at dt) ˡe̲ase (ˡTOP c̲at dt) ˡe̲ase (ˡIDIOM c̲at dt) ˡe̲ase state
  idle ← dt + (ˡATTRACT c̲at ˡIDLE) ˡa̲t state
  since ← dt + (ˡATTRACT c̲at ˡSINCE) ˡa̲t state
  timed ← (ˡATTRACT c̲at ˡSINCE c̲at since) ˡp̲ut (ˡATTRACT c̲at ˡIDLE c̲at idle) ˡp̲ut eased
  (idle < ˡidleBefore) ∨ since < ˡdwell ? timed
  ˡa̲ttract (ˡATTRACT c̲at ˡSINCE c̲at 0.0) ˡp̲ut timed
}
Used in: ˡu̲pdate

ˡa̲ttract : Float -> Float

function · line 196

One step of the attract mode: the bottom ring steps (if it plays); when it has swept every other language (its count reaches one less than the languages), the drum rolls to the next idiom too and the bottom's count starts over; when the drum has rolled through every idiom, the top ring steps too and the drum's count starts over. A paused axis is counted but not turned, so the sweeps keep their rhythm. With 3 idioms and 4 languages: the drum rolls at every third step, the top steps at the ninth.

      ᶜᵐ⁼u̲se< "Comparison"
      s ← 3 ᶜᵐs̲tart 4
      (ᶜᵐIDIOM ᶜᵐc̲urrent ᶜᵐa̲ttract² s) c̲at ᶜᵐIDIOM ᶜᵐc̲urrent ᶜᵐa̲ttract³ s
1 2
      (ᶜᵐTOP ᶜᵐc̲urrent ᶜᵐa̲ttract⁸ s) c̲at ᶜᵐTOP ᶜᵐc̲urrent ᶜᵐa̲ttract⁹ s
1 2
      ᶜᵐIDIOM ᶜᵐc̲urrent ᶜᵐa̲ttract⁹ s
1
ˡa̲ttract ← { state →
  n ← (f̲loor 0.5 + (ˡTOP c̲at ˡCOUNT) ˡa̲t state) − 1
  m ← f̲loor 0.5 + (ˡIDIOM c̲at ˡCOUNT) ˡa̲t state
  bottoms ← 1.0 + (ˡATTRACT c̲at ˡBOTTOMS) ˡa̲t state
  idioms ← 1.0 + (ˡATTRACT c̲at ˡIDIOMS) ˡa̲t state
  moved ← ˡBOTTOM ˡp̲lay state
  bottoms < f̲loat n ? (ˡATTRACT c̲at ˡBOTTOMS c̲at bottoms) ˡp̲ut moved
  rolled ← ˡIDIOM ˡp̲lay (ˡATTRACT c̲at ˡBOTTOMS c̲at 0.0) ˡp̲ut moved
  idioms < f̲loat m ? (ˡATTRACT c̲at ˡIDIOMS c̲at idioms) ˡp̲ut rolled
  ˡTOP ˡp̲lay (ˡATTRACT c̲at ˡIDIOMS c̲at 0.0) ˡp̲ut rolled
}
Used in: ˡt̲ick

ˡp̲lay : Float -> Float -> Float

function · line 209

An axis stepped forward if it plays, else left as it is.

ˡp̲lay ← { axis state → "1.0 = (axis c_at l:PLAYING) l:a_t state" i̲f< "(axis c_at 1.0) l:s_tep state; state" }
i̲f< expands to
{ @ → (1.0 = (axis c̲at ˡPLAYING) ˡa̲t state) ? (axis c̲at 1.0) ˡs̲tep state◆ state } @
Used in: ˡa̲ttract

ˡt̲ouched : Float -> Float

function · line 212

The stone touched: the attract mode waits again from now.

ˡt̲ouched ← { state → (ˡATTRACT c̲at ˡSINCE c̲at 0.0) ˡp̲ut (ˡATTRACT c̲at ˡIDLE c̲at 0.0) ˡp̲ut state }
Used in: ˡu̲pdate

ˡr̲esume : Float -> Float

function · line 215

Every axis playing again (a start chosen with cm:c_hoose is paused).

ˡr̲esume ← { state → (ˡBOTTOM c̲at ˡPLAYING c̲at 1.0) ˡp̲ut (ˡTOP c̲at ˡPLAYING c̲at 1.0) ˡp̲ut (ˡIDIOM c̲at ˡPLAYING c̲at 1.0) ˡp̲ut state }

ˡt̲oggleTour : Float -> Float

function · line 226

The tour paused when any axis plays, else every axis resumed (the space bar: one key stops everything, and starts it again).

      ᶜᵐ⁼u̲se< "Comparison"
      (ᶜᵐTOP c̲at ᶜᵐPLAYING) ᶜᵐa̲t ᶜᵐt̲oggleTour 31 ᶜᵐs̲tart 7
0.0
      (ᶜᵐBOTTOM c̲at ᶜᵐPLAYING) ᶜᵐa̲t ᶜᵐt̲oggleTour ᶜᵐTOP ᶜᵐt̲oggle 31 ᶜᵐs̲tart 7
0.0
      (ᶜᵐTOP c̲at ᶜᵐPLAYING) ᶜᵐa̲t ᶜᵐt̲oggleTour ᶜᵐt̲oggleTour 31 ᶜᵐs̲tart 7
1.0
ˡt̲oggleTour ← { state →
  playing ← ((ˡIDIOM c̲at ˡPLAYING) ˡa̲t state) + ((ˡTOP c̲at ˡPLAYING) ˡa̲t state) + (ˡBOTTOM c̲at ˡPLAYING) ˡa̲t state
  0.0 < playing ? (ˡBOTTOM c̲at ˡPLAYING c̲at 0.0) ˡp̲ut (ˡTOP c̲at ˡPLAYING c̲at 0.0) ˡp̲ut (ˡIDIOM c̲at ˡPLAYING c̲at 0.0) ˡp̲ut state
  ˡr̲esume state
}
Used in: ˡk̲ey

ˡm̲ode : Float -> Char

function · line 244

The tour's mode, for the host to show: "paused" when every axis is paused, "paused: top, bottom" naming the axes paused when some are, "holding" while the stone waits after a touch, else "touring".

      ᶜᵐ⁼u̲se< "Comparison"
      ᶜᵐm̲ode 31 ᶜᵐs̲tart 7
touring
      ᶜᵐm̲ode ᶜᵐt̲ouched 31 ᶜᵐs̲tart 7
holding
      ᶜᵐm̲ode ᶜᵐTOP ᶜᵐt̲oggle 31 ᶜᵐs̲tart 7
paused: top
      ᶜᵐm̲ode ᶜᵐt̲oggleTour 31 ᶜᵐs̲tart 7
paused
ˡm̲ode ← { state →
  p̲aused ← { axis → 0.0 = (axis c̲at ˡPLAYING) ˡa̲t state }
  paused ← (p̲aused ˡIDIOM) c̲at (p̲aused ˡTOP) c̲at p̲aused ˡBOTTOM
  3 = '+ r̲/ paused ? "paused"
  names ← paused r̲eplicate (e̲nclose "roll") c̲at (e̲nclose "top") c̲at e̲nclose "bottom"
  0 < '+ r̲/ paused ? "paused: " c̲at d̲isclose '{ x y → e̲nclose (d̲isclose x) c̲at ", " c̲at d̲isclose y } r̲/ names
  ˡidleBefore > (ˡATTRACT c̲at ˡIDLE) ˡa̲t state ? "holding"
  "touring"
}
Used in: ᵘl̲oop, mode

ˡt̲oggle : Float -> Float -> Float

function · line 255

An axis paused or resumed.

ˡt̲oggle ← { axis state → (axis c̲at ˡPLAYING c̲at 1.0 − (axis c̲at ˡPLAYING) ˡa̲t state) ˡp̲ut state }
Used in: ˡc̲lick, ˡk̲ey

ˡu̲pdate : Float -> Event -> Float

function · line 267

The state after an event: a tick eases every axis; the arrow keys step the drum (Up, Down) and the top ring (Left, Right), a and d the bottom ring, space pauses or resumes the whole tour (cm:t_oggleTour), r resumes it at once, the idle wait over (cm:r_esume; the host sends it after its opening choices, since a choice pauses its axis), s the bottom ring and w the drum on their own; the pointer drags and clicks (cm:d_own, cm:m_ove, cm:u_p, cm:c_lick); a choice from the host's controls, choose AXIS ITEM, turns that axis to the item (cm:c_hoose).

ˡu̲pdate ← { state e →
  kind ← ⎕E̲KIND e
  kind m̲atch "tick" ? (f̲irst ⎕E̲AT e) ˡt̲ick state
  touched ← ˡt̲ouched state
  kind m̲atch "key" ? (⎕E̲KEY e) ˡk̲ey touched
  kind m̲atch "down" ? (⎕E̲AT e) ˡd̲own touched
  kind m̲atch "move" ? (⎕E̲AT e) ˡm̲ove touched
  kind m̲atch "up" ? (⎕E̲AT e) ˡu̲p touched
  kind m̲atch "click" ? (⎕E̲AT e) ˡc̲lick touched
  kind m̲atch "choose" ? (⎕E̲AT e) ˡc̲hoose touched
  state
}
Used in: ᵘl̲oop

ˡh̲alf : Float -> Float

function · line 282

The half under a point: the top ring above the middle, the bottom ring below.

ˡh̲alf ← { xy → "(2 s_elect xy) < l:middle" i̲f< "l:TOP; l:BOTTOM" }
i̲f< expands to
{ @ → ((2 s̲elect xy) < ˡmiddle) ? ˡTOP◆ ˡBOTTOM } @

ˡd̲own : Float -> Float -> Float

function · line 289

The pointer pressed at a point: remembered, nothing turned yet. xy ᶜᵐd̲own state.

      ᶜᵐ⁼u̲se< "Comparison"
      4 s̲elect 100.0 50.0 ᶜᵐd̲own 31 ᶜᵐs̲tart 7
0.5 100.0 50.0 0.0 0.0
ˡd̲own ← { xy state → (ˡPOINTER c̲at ˡLAST c̲at 0.0) ˡp̲ut (ˡPOINTER c̲at ˡMOVED c̲at 0.0) ˡp̲ut (ˡPOINTER c̲at ˡY c̲at 2 s̲elect xy) ˡp̲ut (ˡPOINTER c̲at ˡX c̲at 1 s̲elect xy) ˡp̲ut (ˡPOINTER c̲at ˡDRAGGING c̲at 0.5) ˡp̲ut state }
Used in: ˡu̲pdate

ˡm̲ove : Float -> Float -> Float

function · line 303

The pointer moved to a point: nothing unless it is pressed; the first move of more than a few pixels decides which axis it drags (a sideways move the half it is over, an up or down move the drum); then each move turns that axis by its distance, a drag right or down turning toward the previous item. A drag does not pause the axis for good: the stone waits cm:idleBefore seconds after any touch before moving on its own again. xy ᶜᵐm̲ove state.

      ᶜᵐ⁼u̲se< "Comparison"
      (ᶜᵐTOP c̲at ᶜᵐANGLE) ᶜᵐa̲t 142.0 50.0 ᶜᵐm̲ove 100.0 50.0 ᶜᵐd̲own 31 ᶜᵐs̲tart 7
-18.0
      (ᶜᵐBOTTOM c̲at ᶜᵐANGLE) ᶜᵐa̲t 142.0 50.0 ᶜᵐm̲ove 100.0 50.0 ᶜᵐd̲own 31 ᶜᵐs̲tart 7
0.0
ˡm̲ove ← { xy state →
  held ← (ˡPOINTER c̲at ˡDRAGGING) ˡa̲t state
  held = 0.0 ? state
  dx ← (1 s̲elect xy) − (ˡPOINTER c̲at ˡX) ˡa̲t state
  dy ← (2 s̲elect xy) − (ˡPOINTER c̲at ˡY) ˡa̲t state
  moved ← (a̲bs dx) + (a̲bs dy) + (ˡPOINTER c̲at ˡMOVED) ˡa̲t state
  placed ← (ˡPOINTER c̲at ˡMOVED c̲at moved) ˡp̲ut (ˡPOINTER c̲at ˡY c̲at 2 s̲elect xy) ˡp̲ut (ˡPOINTER c̲at ˡX c̲at 1 s̲elect xy) ˡp̲ut state
  (held = 0.5) ∧ moved ≤ 4.0 ? placed
  axis ← "held = 0.5" i̲f< "\"(a_bs dx) >= a_bs dy\" i_f< \"l:h_alf xy; l:IDIOM\"; held"
  along ← "axis = l:IDIOM" i̲f< "dy; dx"
  turn ← n̲eg along × ˡperPixel
  angle ← turn + (axis c̲at ˡANGLE) ˡa̲t placed
  (ˡPOINTER c̲at ˡLAST c̲at turn) ˡp̲ut (ˡPOINTER c̲at ˡDRAGGING c̲at axis) ˡp̲ut (axis c̲at ˡANGLE c̲at angle) ˡp̲ut placed
}
i̲f< expands to
({ @ → (held = 0.5) ? "(a_bs dx) >= a_bs dy" i̲f< "l:h_alf xy; l:IDIOM"◆ held } @)
i̲f< expands to
({ @ → ((a̲bs dx) ≥ a̲bs dy) ? ˡh̲alf xy◆ ˡIDIOM } @)
i̲f< expands to
({ @ → (axis = ˡIDIOM) ? dy◆ dx } @)
Used in: ˡu̲pdate

ˡu̲p : Float -> Float -> Float

function · line 327

The pointer released: a drag settles on the nearest item, one further along when the last move was a flick (more than 6 degrees), its steps becoming that item so the angle eases the rest of the way; a press that never moved is a click. xy ᶜᵐu̲p state.

      ᶜᵐ⁼u̲se< "Comparison"
      (ᶜᵐTOP c̲at ᶜᵐSTEPS) ᶜᵐa̲t 142.0 50.0 ᶜᵐu̲p 142.0 50.0 ᶜᵐm̲ove 100.0 50.0 ᶜᵐd̲own 31 ᶜᵐs̲tart 7
-1.0
      (ᶜᵐTOP c̲at ᶜᵐSTEPS) ᶜᵐa̲t 125.0 50.0 ᶜᵐu̲p 125.0 50.0 ᶜᵐm̲ove 120.0 50.0 ᶜᵐm̲ove 100.0 50.0 ᶜᵐd̲own 31 ᶜᵐs̲tart 7
0.0
ˡu̲p ← { xy state →
  held ← (ˡPOINTER c̲at ˡDRAGGING) ˡa̲t state
  held = 0.0 ? state
  released ← (ˡPOINTER c̲at ˡDRAGGING c̲at 0.0) ˡp̲ut state
  held = 0.5 ? xy ˡc̲lick released
  last ← (ˡPOINTER c̲at ˡLAST) ˡa̲t state
  flick ← "6.0 < a_bs last" i̲f< "45.0 * last / a_bs last; 0.0"
  angle ← (held c̲at ˡANGLE) ˡa̲t state
  (held c̲at ˡSTEPS c̲at f̲loat f̲loor 0.5 + (angle + flick) ÷ 90.0) ˡp̲ut released
}
i̲f< expands to
({ @ → (6.0 < a̲bs last) ? 45.0 × last ÷ a̲bs last◆ 0.0 } @)
Used in: ˡu̲pdate

ˡc̲lick : Float -> Float -> Float

function · line 342

A click on a half pauses or resumes it. xy ᶜᵐc̲lick state.

      ᶜᵐ⁼u̲se< "Comparison"
      (ᶜᵐBOTTOM c̲at ᶜᵐPLAYING) ᶜᵐa̲t 100.0 300.0 ᶜᵐc̲lick 31 ᶜᵐs̲tart 7
0.0
ˡc̲lick ← { xy state → (ˡh̲alf xy) ˡt̲oggle state }
Used in: ˡu̲pdate, ˡu̲p

ˡk̲ey : Key -> Float -> Float

function · line 346

A key's effect: see cm:u_pdate. Named keys compare with []K_NAMED (1 Up, 2 Down, 3 Left, 4 Right); printing keys by their character.

ˡk̲ey ← { k state →
  k = ⎕K̲NAMED 1 ? (ˡIDIOM c̲at -1.0) ˡs̲tep state
  k = ⎕K̲NAMED 2 ? (ˡIDIOM c̲at 1.0) ˡs̲tep state
  k = ⎕K̲NAMED 3 ? (ˡTOP c̲at -1.0) ˡs̲tep state
  k = ⎕K̲NAMED 4 ? (ˡTOP c̲at 1.0) ˡs̲tep state
  c ← ⎕K̲CHAR k
  c m̲atch "a" ? (ˡBOTTOM c̲at -1.0) ˡs̲tep state
  c m̲atch "d" ? (ˡBOTTOM c̲at 1.0) ˡs̲tep state
  c m̲atch " " ? ˡt̲oggleTour state
  c m̲atch "r" ? (ˡATTRACT c̲at ˡIDLE c̲at ˡidleBefore) ˡp̲ut ˡr̲esume state
  c m̲atch "s" ? ˡBOTTOM ˡt̲oggle state
  c m̲atch "w" ? ˡIDIOM ˡt̲oggle state
  state
}
Used in: ˡu̲pdate