sourcedemos/rosetta/Comparison.xtl

1⍝# Comparison: the Rosetta stone's state machine (docs/rosetta.md), a 2⍝# library beside the demo ("cm:" u_se< "Comparison"). The state is one 3⍝# 4 x 5 matrix of numbers. The first three rows are the axes (the 4⍝# idiom drum, the top ring, the bottom ring), four columns each: how 5⍝# many items the axis has, how many steps it has taken (an integer; the 6⍝# item facing is 1 + steps, wrapped, and this is the truth), its angle 7⍝# in degrees (90 per step; the presentation, easing toward 90 * steps) 8⍝# and whether it plays on its own. The fourth row is the pointer: the 9⍝# axis being dragged (0 none, 0.5 pressed and not yet moved, else the 10⍝# axis), where it last was (x, y), how far it has moved in all, and the 11⍝# last turn it gave in degrees (for a flick). The fifth row is the 12⍝# attract mode's clock: seconds since the last interaction, seconds 13⍝# since its last step, and its two counters (how far the bottom ring 14⍝# is through its sweep of the other languages, how far the drum is 15⍝# through its sweep of the idioms). Nothing 16⍝# is ever inferred from an angle except what to draw. Every function 17⍝# gives a new state; none has an effect. Events (RS1) come in as 18⍝# []E_VENT gives them; cm:u_pdate takes one. 19 20⍝# The attract mode's pace, in seconds: how long a comparison holds 21⍝# still before the next (long enough to read two faces of code), and 22⍝# how long after an interaction the stone waits before moving on its 23⍝# own again (long enough to look round a comparison by hand). The 24⍝# traversal is the nested loop for top, for idiom, for bottom: the 25⍝# bottom ring steps at each dwell; when it has swept every other 26⍝# language the drum rolls to the next idiom in the same instant, the 27⍝# bottom going on round; and only when every idiom has been shown 28⍝# does the top ring advance to the next language. So the language 29⍝# compared from stays put through the whole table, and no comparison 30⍝# comes round again within minutes (the user, 2026-10-06; before, 31⍝# the top stepped after each sweep of the bottom and the drum after 32⍝# each sweep of the top: two minutes per idiom and the same pairs 33⍝# again and again). 34ˡdwell ← 5.0 35ˡidleBefore ← 20.0 36 37⍝# The state for i idioms and l languages, i ᶜᵐs̲tart l: nothing 38⍝# turned, all playing, no pointer, the attract mode ready (idle long 39⍝# enough already). 40⍝# >> "cm:" u_se< "Comparison" 41⍝# >> 31 cm:s_tart 7 42⍝# 31.0 0.0 0.0 1.0 0.0 43⍝# 7.0 0.0 0.0 1.0 0.0 44⍝# 7.0 0.0 0.0 1.0 0.0 45⍝# 0.0 0.0 0.0 0.0 0.0 46⍝# 20.0 0.0 0.0 0.0 0.0 47ˡ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 } 48 49⍝# The rows and columns, by name. 50ˡIDIOM ← 1.0 51ˡTOP ← 2.0 52ˡBOTTOM ← 3.0 53ˡPOINTER ← 4.0 54ˡATTRACT ← 5.0 55ˡIDLE ← 1.0 56ˡSINCE ← 2.0 57ˡBOTTOMS ← 3.0 58ˡIDIOMS ← 4.0 59ˡCOUNT ← 1.0 60ˡSTEPS ← 2.0 61ˡANGLE ← 3.0 62ˡPLAYING ← 4.0 63ˡDRAGGING ← 1.0 64ˡX ← 2.0 65ˡY ← 3.0 66ˡMOVED ← 4.0 67ˡLAST ← 5.0 68 69⍝# The picture's middle, in its own pixels (Stone's size is 420): the 70⍝# top half above it, the bottom half below; and how many degrees a 71⍝# pixel of drag turns an axis (a quarter turn across half the picture). 72ˡmiddle ← 210.0 73ˡperPixel ← 90.0 ÷ 210.0 74 75⍝# A cell of the state: (row c̲at col) ᶜᵐa̲t state. 76ˡa̲t ← { rc state → (f̲loor 2 s̲elect rc) s̲elect (f̲loor 1 s̲elect rc) s̲elect state } 77 78⍝# The state with one cell replaced: (row c̲at col c̲at v) ᶜᵐp̲ut state (a 79⍝# mask over the matrix, so no cell is ever addressed by hand). 80ˡp̲ut ← { rcv state → 81 mask ← f̲loat (rows = 1 s̲elect rcv) × cols = 2 s̲elect rcv 82 (state × 1.0 − mask) + mask × 3 s̲elect rcv 83} 84rows ← 5 5 r̲eshape 5 r̲eplicate 1.0 2.0 3.0 4.0 5.0 85cols ← 5 5 r̲eshape 1.0 2.0 3.0 4.0 5.0 86 87⍝# An item of an axis of n, wrapped around: item k of n for any integer k. 88ˡw̲rap ← { n k → 1 + (k − 1) m̲od n } 89 90⍝# The item facing on an axis: 1 + its steps, wrapped. 91⍝# >> "cm:" u_se< "Comparison" 92⍝# >> cm:TOP cm:c_urrent (cm:TOP c_at 1.0) cm:s_tep 31 cm:s_tart 7 93⍝# 2 94ˡ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 } 95 96⍝# An axis stepped by d items (1 forward, -1 back): its steps change, 97⍝# its angle will follow at each tick. A ring never stops on the other 98⍝# ring's language (the two halves always compare two languages): it 99⍝# steps once more the same way. (axis c̲at d) ᶜᵐs̲tep state. 100⍝# >> "cm:" u_se< "Comparison" 101⍝# >> cm:IDIOM cm:c_urrent (cm:IDIOM c_at -1.0) cm:s_tep 31 cm:s_tart 7 102⍝# 31 103⍝# >> cm:BOTTOM cm:c_urrent (cm:BOTTOM c_at 1.0) cm:s_tep (cm:TOP c_at 2.0) cm:c_hoose 31 cm:s_tart 7 104⍝# 3 105ˡs̲tep ← { ad state → 106 axis ← 1 s̲elect ad 107 d ← 2 s̲elect ad 108 moved ← (axis c̲at ˡSTEPS c̲at d + (axis c̲at ˡSTEPS) ˡa̲t state) ˡp̲ut state 109 axis = ˡIDIOM ? moved 110 other ← 5.0 − axis 111 clash ← (axis ˡc̲urrent moved) = other ˡc̲urrent moved 112 "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 } @
113} 114 115⍝# An axis turned to item k the short way round, and paused: choosing 116⍝# is navigating, turning is exploring. A ring is not turned to the 117⍝# other ring's language (the choice is offered disabled); the state is 118⍝# unchanged. (axis c̲at k) ᶜᵐc̲hoose state. 119⍝# >> "cm:" u_se< "Comparison" 120⍝# >> cm:TOP cm:c_urrent (cm:TOP c_at 7.0) cm:c_hoose 31 cm:s_tart 7 121⍝# 7 122⍝# >> (cm:TOP c_at cm:STEPS) cm:a_t (cm:TOP c_at 7.0) cm:c_hoose 31 cm:s_tart 7 123⍝# -1.0 124ˡc̲hoose ← { ak state → 125 axis ← 1 s̲elect ak 126 n ← f̲loor 0.5 + (axis c̲at ˡCOUNT) ˡa̲t state 127 d ← ((f̲loor 2 s̲elect ak) − axis ˡc̲urrent state) m̲od n 128 short ← "(2 * d) > n" i̲f< "d - n; d"
i̲f< expands to
({ @ → ((2 × d) > n) ? d − n◆ d } @)
129 chosen ← (axis c̲at ˡPLAYING c̲at 0.0) ˡp̲ut (axis c̲at f̲loat short) ˡs̲tep state 130 axis = ˡIDIOM ? chosen 131 (f̲loor 2 s̲elect ak) = (5.0 − axis) ˡc̲urrent state ? state 132 chosen 133} 134 135⍝# An axis's angle eased toward 90 times its steps over dt seconds: it 136⍝# covers the gap in about half a second, and lands exactly when near. 137⍝# (axis c̲at dt) ᶜᵐe̲ase state. 138⍝# >> "cm:" u_se< "Comparison" 139⍝# >> (cm:TOP c_at cm:ANGLE) cm:a_t (cm:TOP c_at 0.25) cm:e_ase (cm:TOP c_at 1.0) cm:s_tep 31 cm:s_tart 7 140⍝# 45.0 141ˡe̲ase ← { adt state → 142 axis ← 1 s̲elect adt 143 angle ← (axis c̲at ˡANGLE) ˡa̲t state 144 target ← 90.0 × (axis c̲at ˡSTEPS) ˡa̲t state 145 gap ← target − angle 146 moved ← angle + gap × 1.0 m̲in 2.0 × 2 s̲elect adt 147 near ← "0.5 > a_bs target - moved" i̲f< "target; moved"
i̲f< expands to
({ @ → (0.5 > a̲bs target − moved) ? target◆ moved } @)
148 (axis c̲at ˡANGLE c̲at near) ˡp̲ut state 149} 150 151⍝# Every axis at rest where its steps put it (angles 90 times steps), 152⍝# for a state built by choosing before the first tick. 153⍝# >> "cm:" u_se< "Comparison" 154⍝# >> cm:s_ettle (cm:IDIOM c_at 3.0) cm:c_hoose 31 cm:s_tart 7 155⍝# 31.0 2.0 180.0 0.0 0.0 156⍝# 7.0 0.0 0.0 1.0 0.0 157⍝# 7.0 0.0 0.0 1.0 0.0 158⍝# 0.0 0.0 0.0 0.0 0.0 159⍝# 20.0 0.0 0.0 0.0 0.0 160ˡ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 } 161 162⍝# Every axis eased over dt seconds (a tick), and the attract mode's 163⍝# clock advanced: when the stone has been left alone long enough and 164⍝# the last comparison has held still for a dwell, the attract mode 165⍝# steps (cm:a_ttract). 166⍝# >> "cm:" u_se< "Comparison" 167⍝# >> cm:BOTTOM cm:c_urrent cm:dwell cm:t_ick 31 cm:s_tart 7 168⍝# 2 169⍝# >> cm:BOTTOM cm:c_urrent (cm:dwell - 0.1) cm:t_ick 31 cm:s_tart 7 170⍝# 1 171ˡt̲ick ← { dt state → 172 eased ← (ˡBOTTOM c̲at dt) ˡe̲ase (ˡTOP c̲at dt) ˡe̲ase (ˡIDIOM c̲at dt) ˡe̲ase state 173 idle ← dt + (ˡATTRACT c̲at ˡIDLE) ˡa̲t state 174 since ← dt + (ˡATTRACT c̲at ˡSINCE) ˡa̲t state 175 timed ← (ˡATTRACT c̲at ˡSINCE c̲at since) ˡp̲ut (ˡATTRACT c̲at ˡIDLE c̲at idle) ˡp̲ut eased 176 (idle < ˡidleBefore) ∨ since < ˡdwell ? timed 177 ˡa̲ttract (ˡATTRACT c̲at ˡSINCE c̲at 0.0) ˡp̲ut timed 178} 179 180⍝# One step of the attract mode: the bottom ring steps (if it plays); 181⍝# when it has swept every other language (its count reaches one less 182⍝# than the languages), the drum rolls to the next idiom too and the 183⍝# bottom's count starts over; when the drum has rolled through every 184⍝# idiom, the top ring steps too and the drum's count starts over. A 185⍝# paused axis is counted but not turned, so the sweeps keep their 186⍝# rhythm. With 3 idioms and 4 languages: the drum rolls at every 187⍝# third step, the top steps at the ninth. 188⍝# >> "cm:" u_se< "Comparison" 189⍝# >> s := 3 cm:s_tart 4 190⍝# >> (cm:IDIOM cm:c_urrent cm:a_ttract^2 s) c_at cm:IDIOM cm:c_urrent cm:a_ttract^3 s 191⍝# 1 2 192⍝# >> (cm:TOP cm:c_urrent cm:a_ttract^8 s) c_at cm:TOP cm:c_urrent cm:a_ttract^9 s 193⍝# 1 2 194⍝# >> cm:IDIOM cm:c_urrent cm:a_ttract^9 s 195⍝# 1 196ˡa̲ttract ← { state → 197 n ← (f̲loor 0.5 + (ˡTOP c̲at ˡCOUNT) ˡa̲t state) − 1 198 m ← f̲loor 0.5 + (ˡIDIOM c̲at ˡCOUNT) ˡa̲t state 199 bottoms ← 1.0 + (ˡATTRACT c̲at ˡBOTTOMS) ˡa̲t state 200 idioms ← 1.0 + (ˡATTRACT c̲at ˡIDIOMS) ˡa̲t state 201 moved ← ˡBOTTOM ˡp̲lay state 202 bottoms < f̲loat n ? (ˡATTRACT c̲at ˡBOTTOMS c̲at bottoms) ˡp̲ut moved 203 rolled ← ˡIDIOM ˡp̲lay (ˡATTRACT c̲at ˡBOTTOMS c̲at 0.0) ˡp̲ut moved 204 idioms < f̲loat m ? (ˡATTRACT c̲at ˡIDIOMS c̲at idioms) ˡp̲ut rolled 205 ˡTOP ˡp̲lay (ˡATTRACT c̲at ˡIDIOMS c̲at 0.0) ˡp̲ut rolled 206} 207 208⍝# An axis stepped forward if it plays, else left as it is. 209ˡ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 } @
210 211⍝# The stone touched: the attract mode waits again from now. 212ˡt̲ouched ← { state → (ˡATTRACT c̲at ˡSINCE c̲at 0.0) ˡp̲ut (ˡATTRACT c̲at ˡIDLE c̲at 0.0) ˡp̲ut state } 213 214⍝# Every axis playing again (a start chosen with cm:c_hoose is paused). 215ˡ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 } 216 217⍝# The tour paused when any axis plays, else every axis resumed (the 218⍝# space bar: one key stops everything, and starts it again). 219⍝# >> "cm:" u_se< "Comparison" 220⍝# >> (cm:TOP c_at cm:PLAYING) cm:a_t cm:t_oggleTour 31 cm:s_tart 7 221⍝# 0.0 222⍝# >> (cm:BOTTOM c_at cm:PLAYING) cm:a_t cm:t_oggleTour cm:TOP cm:t_oggle 31 cm:s_tart 7 223⍝# 0.0 224⍝# >> (cm:TOP c_at cm:PLAYING) cm:a_t cm:t_oggleTour cm:t_oggleTour 31 cm:s_tart 7 225⍝# 1.0 226ˡt̲oggleTour ← { state → 227 playing ← ((ˡIDIOM c̲at ˡPLAYING) ˡa̲t state) + ((ˡTOP c̲at ˡPLAYING) ˡa̲t state) + (ˡBOTTOM c̲at ˡPLAYING) ˡa̲t state 228 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 229 ˡr̲esume state 230} 231 232⍝# The tour's mode, for the host to show: "paused" when every axis is 233⍝# paused, "paused: top, bottom" naming the axes paused when some are, 234⍝# "holding" while the stone waits after a touch, else "touring". 235⍝# >> "cm:" u_se< "Comparison" 236⍝# >> cm:m_ode 31 cm:s_tart 7 237⍝# touring 238⍝# >> cm:m_ode cm:t_ouched 31 cm:s_tart 7 239⍝# holding 240⍝# >> cm:m_ode cm:TOP cm:t_oggle 31 cm:s_tart 7 241⍝# paused: top 242⍝# >> cm:m_ode cm:t_oggleTour 31 cm:s_tart 7 243⍝# paused 244ˡm̲ode ← { state → 245 p̲aused ← { axis → 0.0 = (axis c̲at ˡPLAYING) ˡa̲t state } 246 paused ← (p̲aused ˡIDIOM) c̲at (p̲aused ˡTOP) c̲at p̲aused ˡBOTTOM 247 3 = '+ r̲/ paused ? "paused" 248 names ← paused r̲eplicate (e̲nclose "roll") c̲at (e̲nclose "top") c̲at e̲nclose "bottom" 249 0 < '+ r̲/ paused ? "paused: " c̲at d̲isclose '{ x y → e̲nclose (d̲isclose x) c̲at ", " c̲at d̲isclose y } r̲/ names 250 ˡidleBefore > (ˡATTRACT c̲at ˡIDLE) ˡa̲t state ? "holding" 251 "touring" 252} 253 254⍝# An axis paused or resumed. 255ˡt̲oggle ← { axis state → (axis c̲at ˡPLAYING c̲at 1.0 − (axis c̲at ˡPLAYING) ˡa̲t state) ˡp̲ut state } 256 257⍝# The state after an event: a tick eases every axis; the arrow keys 258⍝# step the drum (Up, Down) and the top ring (Left, Right), a and d the 259⍝# bottom ring, space pauses or resumes the whole tour (cm:t_oggleTour), 260⍝# r resumes it at once, the idle wait over (cm:r_esume; the host 261⍝# sends it after its opening choices, since a choice pauses its 262⍝# axis), s the bottom ring and w 263⍝# the drum on their own; the pointer drags and 264⍝# clicks (cm:d_own, cm:m_ove, cm:u_p, 265⍝# cm:c_lick); a choice from the host's controls, choose AXIS ITEM, 266⍝# turns that axis to the item (cm:c_hoose). 267ˡu̲pdate ← { state e → 268 kind ← ⎕E̲KIND e 269 kind m̲atch "tick" ? (f̲irst ⎕E̲AT e) ˡt̲ick state 270 touched ← ˡt̲ouched state 271 kind m̲atch "key" ? (⎕E̲KEY e) ˡk̲ey touched 272 kind m̲atch "down" ? (⎕E̲AT e) ˡd̲own touched 273 kind m̲atch "move" ? (⎕E̲AT e) ˡm̲ove touched 274 kind m̲atch "up" ? (⎕E̲AT e) ˡu̲p touched 275 kind m̲atch "click" ? (⎕E̲AT e) ˡc̲lick touched 276 kind m̲atch "choose" ? (⎕E̲AT e) ˡc̲hoose touched 277 state 278} 279 280⍝# The half under a point: the top ring above the middle, the bottom 281⍝# ring below. 282ˡ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 } @
283 284⍝# The pointer pressed at a point: remembered, nothing turned yet. 285⍝# xy ᶜᵐd̲own state. 286⍝# >> "cm:" u_se< "Comparison" 287⍝# >> 4 s_elect 100.0 50.0 cm:d_own 31 cm:s_tart 7 288⍝# 0.5 100.0 50.0 0.0 0.0 289ˡ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 } 290 291⍝# The pointer moved to a point: nothing unless it is pressed; the 292⍝# first move of more than a few pixels decides which axis it drags (a 293⍝# sideways move the half it is over, an up or down move the drum); 294⍝# then each move turns that axis by its distance, a drag right or down 295⍝# turning toward the previous item. A drag does not pause the axis for 296⍝# good: the stone waits cm:idleBefore seconds after any touch before 297⍝# moving on its own again. xy ᶜᵐm̲ove state. 298⍝# >> "cm:" u_se< "Comparison" 299⍝# >> (cm:TOP c_at cm:ANGLE) cm:a_t 142.0 50.0 cm:m_ove 100.0 50.0 cm:d_own 31 cm:s_tart 7 300⍝# -18.0 301⍝# >> (cm:BOTTOM c_at cm:ANGLE) cm:a_t 142.0 50.0 cm:m_ove 100.0 50.0 cm:d_own 31 cm:s_tart 7 302⍝# 0.0 303ˡm̲ove ← { xy state → 304 held ← (ˡPOINTER c̲at ˡDRAGGING) ˡa̲t state 305 held = 0.0 ? state 306 dx ← (1 s̲elect xy) − (ˡPOINTER c̲at ˡX) ˡa̲t state 307 dy ← (2 s̲elect xy) − (ˡPOINTER c̲at ˡY) ˡa̲t state 308 moved ← (a̲bs dx) + (a̲bs dy) + (ˡPOINTER c̲at ˡMOVED) ˡa̲t state 309 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 310 (held = 0.5) ∧ moved ≤ 4.0 ? placed 311 axis ← "held = 0.5" i̲f< "\"(a_bs dx) >= a_bs dy\" i_f< \"l:h_alf xy; l:IDIOM\"; held"
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 } @)
312 along ← "axis = l:IDIOM" i̲f< "dy; dx"
i̲f< expands to
({ @ → (axis = ˡIDIOM) ? dy◆ dx } @)
313 turn ← n̲eg along × ˡperPixel 314 angle ← turn + (axis c̲at ˡANGLE) ˡa̲t placed 315 (ˡ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 316} 317 318⍝# The pointer released: a drag settles on the nearest item, one 319⍝# further along when the last move was a flick (more than 6 degrees), 320⍝# its steps becoming that item so the angle eases the rest of the way; 321⍝# a press that never moved is a click. xy ᶜᵐu̲p state. 322⍝# >> "cm:" u_se< "Comparison" 323⍝# >> (cm:TOP c_at cm:STEPS) cm:a_t 142.0 50.0 cm:u_p 142.0 50.0 cm:m_ove 100.0 50.0 cm:d_own 31 cm:s_tart 7 324⍝# -1.0 325⍝# >> (cm:TOP c_at cm:STEPS) cm:a_t 125.0 50.0 cm:u_p 125.0 50.0 cm:m_ove 120.0 50.0 cm:m_ove 100.0 50.0 cm:d_own 31 cm:s_tart 7 326⍝# 0.0 327ˡu̲p ← { xy state → 328 held ← (ˡPOINTER c̲at ˡDRAGGING) ˡa̲t state 329 held = 0.0 ? state 330 released ← (ˡPOINTER c̲at ˡDRAGGING c̲at 0.0) ˡp̲ut state 331 held = 0.5 ? xy ˡc̲lick released 332 last ← (ˡPOINTER c̲at ˡLAST) ˡa̲t state 333 flick ← "6.0 < a_bs last" i̲f< "45.0 * last / a_bs last; 0.0"
i̲f< expands to
({ @ → (6.0 < a̲bs last) ? 45.0 × last ÷ a̲bs last◆ 0.0 } @)
334 angle ← (held c̲at ˡANGLE) ˡa̲t state 335 (held c̲at ˡSTEPS c̲at f̲loat f̲loor 0.5 + (angle + flick) ÷ 90.0) ˡp̲ut released 336} 337 338⍝# A click on a half pauses or resumes it. xy ᶜᵐc̲lick state. 339⍝# >> "cm:" u_se< "Comparison" 340⍝# >> (cm:BOTTOM c_at cm:PLAYING) cm:a_t 100.0 300.0 cm:c_lick 31 cm:s_tart 7 341⍝# 0.0 342ˡc̲lick ← { xy state → (ˡh̲alf xy) ˡt̲oggle state } 343 344⍝# A key's effect: see cm:u_pdate. Named keys compare with []K_NAMED 345⍝# (1 Up, 2 Down, 3 Left, 4 Right); printing keys by their character. 346ˡk̲ey ← { k state → 347 k = ⎕K̲NAMED 1 ? (ˡIDIOM c̲at -1.0) ˡs̲tep state 348 k = ⎕K̲NAMED 2 ? (ˡIDIOM c̲at 1.0) ˡs̲tep state 349 k = ⎕K̲NAMED 3 ? (ˡTOP c̲at -1.0) ˡs̲tep state 350 k = ⎕K̲NAMED 4 ? (ˡTOP c̲at 1.0) ˡs̲tep state 351 c ← ⎕K̲CHAR k 352 c m̲atch "a" ? (ˡBOTTOM c̲at -1.0) ˡs̲tep state 353 c m̲atch "d" ? (ˡBOTTOM c̲at 1.0) ˡs̲tep state 354 c m̲atch " " ? ˡt̲oggleTour state 355 c m̲atch "r" ? (ˡATTRACT c̲at ˡIDLE c̲at ˡidleBefore) ˡp̲ut ˡr̲esume state 356 c m̲atch "s" ? ˡBOTTOM ˡt̲oggle state 357 c m̲atch "w" ? ˡIDIOM ˡt̲oggle state 358 state 359}