sourceextensions/scene/demos/voxels-rubik-solve.xtl

1⍝# Voxels, 13: the Rubik's cube solved. Scramble it, or turn it with the 2⍝# six buttons, then Solve: the cube's turns so far are handed to the 3⍝# Eigencube library (X_eTaL-libraries, at LIBRARIES_COMMIT), which holds 4⍝# the cube as 26 rotation matrices and solves it by search, stage by 5⍝# stage -- the first layer by plain search over the twelve turns, the 6⍝# middle and last layers over known move sequences (slot inserts, an 7⍝# edge flip, Sune, a corner cycle), which is what makes it fast enough 8⍝# (2 to 3 seconds; a hundred and some moves). Then Step through the 9⍝# solution a turn at a time, Back to undo one, or Play it through, every 10⍝# turn animated on the voxel cube. The two models are checked to agree 11⍝# (tests/rubik-eigencube.xtl). 12⍝# Run: just demo scene voxels-rubik-solve 13⍝# the buttons, or keys: u r f turn (Shift for '), Space scramble, 14⍝# Enter solve, n step, b back, p play or pause, 0 solved again, drag 15⍝# to look around, q quit 16 17ʳᵇ⁼u̲se< "Rubik" 18ʳᵖ⁼u̲se< "RubikPlay" 19ᵉᶜ⁼u̲se< "Eigencube" 20ˢᶜ⁼u̲se< "Scene" 21 22w ← "Voxels 13: Rubik's cube, solved -- X_eTaL" ˢᶜo̲pen! 640 600 23k ← w ˢᶜc̲amera! 0.6 0.45 7.5 0.25 24z ← (ʳᵇsolved, 0, 0.0) ʳᵇd̲raw w 25 26⍝## The two models 27 28⍝# Rubik's turns (1 to 12: U U' D D' R R' L L' F F' B B') as 29⍝# Eigencube's (U U' D D' F F' B B' R R' L L'), and back: the same vector 30map ← 1 2 3 4 9 10 11 12 5 6 7 8 31 32⍝## The buttons 33 34⍝# the turns: six buttons, their turns, the keys that press them 35names ← "U U' R R' F F'" 36turns ← 1 2 5 6 9 10 37keys ← "uUrRfF" 38top ← 490.0 39⍝# the controls: a second row, wider buttons 40controls ← "Scramble Solve Back Step Play" 41top2 ← 545.0 42cw ← 100.0 43 44⍝ both rows drawn, the turn under way's button lit 45ᵘb̲uttons ← { i → 46 a ← (w, names, top, 640.0, 100, ʳᵖbw) ʳᵖd̲rawRow turns i̲ndexOf a̲bs i 47 b ← (w, controls, top2, 640.0, 200, cw) ʳᵖd̲rawRow 0 48 o ← w ˢᶜo̲verlay! a c̲at b 49 i 50} 51o ← ᵘb̲uttons 0 52title ← ((f̲loat w) c̲at 1.0 20.0 20.0 14.0 1.0 1.0 1.0) ˢᶜl̲abel! "Turns:" 53 54⍝ the status line (solving, the solution, solved) 55ᵘt̲ell ← { m → 56 said ← ((f̲loat w) c̲at 3.0 20.0 44.0 14.0 0.6 1.0 0.6) ˢᶜl̲abel! m 57 m 58} 59 60"keys: u r f turn (Shift for '), Space scramble, Enter solve, n step, b back, p play or pause, 0 solved, q quit; or click the buttons" 61 62⍝## Playing 63 64⍝# The state is a tuple: (the turning -- RubikPlay's colors, turns made, 65⍝# turns waiting, turn under way and its frame -- the solution, in 66⍝# Rubik's numbers; how many of its turns are made; the mode, 0 still, 1 67⍝# playing, 2 solving next frame; whether it runs). 68 69⍝ the last 12 turns made, shown above the cube 70ᵘs̲ay ← { st z → 71 (_, h, _, _, _) ← st 72 said ← ((f̲loat w) c̲at 2.0 100.0 20.0 14.0 1.0 1.0 0.6) ˢᶜl̲abel! ʳᵖn̲ames (0 − 12 m̲in t̲ally h) t̲ake h 73 st 74} 75 76⍝# u:s_crambled n: n random turns, never the same face twice in a row 77ᵘs̲crambled ← { n → 78 (_, ts) ← (n, 0 r̲eshape 0) ᵘm̲ore 0 79 ts 80} 81ᵘm̲ore ← { (n, ts) z → 82 n = 0 ? (n, ts) 83 t ← r̲oll! 12 84 prev ← f̲irst -1 t̲ake 0 c̲at ts 85 ((t + 1) d̲iv 2) = (prev + 1) d̲iv 2 ? (n, ts) ᵘm̲ore 0 86 (n − 1, ts c̲at t) ᵘm̲ore 0 87} 88 89⍝# u:s_olution st: the turns that solve the cube made so far (Rubik's 90⍝# numbers), found by Eigencube from the same turns 91ᵘs̲olution ← { st → 92 (_, h, _, _, _) ← st 93 (m, _, _) ← 1 ᵉᶜs̲olve (h s̲elect map) ᵉᶜd̲o ᵉᶜsolved 94 m s̲elect map 95} 96 97⍝ the turn or control of event v: a turn 1 to 12 (positive), a control 98⍝ 1 to 5 (negative), else 0 99ᵘp̲ressed ← { v → 100 b ← (v, 6, top, 640.0, ʳᵖbw) ʳᵖh̲it 0 101 b > 0 ? b s̲elect turns 102 c ← (v, 5, top2, 640.0, cw) ʳᵖh̲it 0 103 c > 0 ? 0 − c 104 i ← keys i̲ndexOf f̲irst -1 t̲ake v 105 ((5 = t̲ally v) × i ≤ 6) ? i s̲elect turns 106 ks ← (v m̲atch "key Space") c̲at (v m̲atch "key Enter") c̲at (v m̲atch "key b") c̲at (v m̲atch "key n") c̲at v m̲atch "key p" 107 0 < '+ r̲/ ks ? 0 − f̲irst w̲here ks 108 0 109} 110 111⍝ a turn by hand: queued; any solution is stale 112ᵘt̲urnBy ← { t (st, sol, pos, mode, on) → 113 z ← ᵘt̲ell " " 114 (t ʳᵖq̲ueue st, 0 r̲eshape 0, 0, 0, on) 115} 116 117⍝ the controls: 1 scramble, 2 solve, 3 back, 4 step, 5 play or pause 118ᵘc̲ontrol ← { k all → 119 (st, sol, pos, mode, on) ← all 120 0 = ʳᵖi̲dle st ? all 121 k = 1 ? ᵘs̲cramble all 122 k = 2 ? ᵘs̲olveSoon all 123 k = 3 ? ᵘb̲ack all 124 k = 4 ? ᵘs̲tep all 125 ᵘp̲lay all 126} 127ᵘs̲cramble ← { (st, sol, pos, mode, on) → 128 z ← ᵘt̲ell "Scrambled: 20 turns" 129 ((ᵘs̲crambled 20) ʳᵖq̲ueue st, 0 r̲eshape 0, 0, 0, on) 130} 131ᵘs̲olveSoon ← { (st, sol, pos, mode, on) → 132 (c, _, _, _, _) ← st 133 c m̲atch ʳᵇsolved ? (st, sol, pos, mode, on) ᵘs̲ayIt "Already solved" 134 z ← ᵘt̲ell "Solving..." 135 (st, sol, pos, 2, on) 136} 137ᵘs̲ayIt ← { all m → 138 z ← ᵘt̲ell m 139 all 140} 141ᵘb̲ack ← { (st, sol, pos, mode, on) → 142 pos = 0 ? (st, sol, pos, mode, on) 143 z ← ᵘt̲ell "Solution: " c̲at (f̲ormat pos − 1) c̲at " of " c̲at (f̲ormat t̲ally sol) c̲at " made" 144 (ʳᵖu̲ndo st, sol, pos − 1, 0, on) 145} 146ᵘs̲tep ← { (st, sol, pos, mode, on) → 147 pos ≥ t̲ally sol ? (st, sol, pos, 0, on) 148 z ← ᵘt̲ell "Solution: " c̲at (f̲ormat pos + 1) c̲at " of " c̲at (f̲ormat t̲ally sol) c̲at " made" 149 (((pos + 1) s̲elect sol) ʳᵖq̲ueue st, sol, pos + 1, mode, on) 150} 151ᵘp̲lay ← { (st, sol, pos, mode, on) → 152 pos ≥ t̲ally sol ? (st, sol, pos, 0, on) 153 (st, sol, pos, 1 − mode, on) 154} 155 156⍝ the solve, a frame after "Solving..." was shown 157ᵘs̲olveNow ← { (st, sol, pos, mode, on) → 158 sol ← ᵘs̲olution st 159 (_, h, _, _, _) ← st 160 said ← p̲rint! "solved by " c̲at (f̲ormat t̲ally sol) c̲at " turns; the cube solved by them: " c̲at f̲ormat (ʳᵖa̲pplied h c̲at sol) m̲atch ʳᵇsolved 161 z ← ᵘt̲ell "Solution: " c̲at (f̲ormat t̲ally sol) c̲at " turns -- Step or Play" 162 (st, sol, 0, 0, on) 163} 164 165⍝ playing: the next turn of the solution whenever the cube is still 166ᵘp̲layOn ← { all → 167 (st, sol, pos, mode, on) ← all 168 0 = (mode = 1) × ʳᵖi̲dle st ? all 169 pos ≥ t̲ally sol ? (st, sol, pos, 0, on) ᵘs̲ayIt "Solved in " c̲at (f̲ormat t̲ally sol) c̲at " turns" 170 ᵘs̲tep all 171} 172 173ᵘr̲eset ← { (st, sol, pos, mode, on) → 174 d ← (ʳᵇsolved, 0, 0.0) ʳᵇd̲raw w 175 z ← ᵘt̲ell " " 176 (ʳᵖstart ᵘs̲ay 0, 0 r̲eshape 0, 0, 0, on) 177} 178 179ᵘm̲ade ← { (_, h, _, _, _) → t̲ally h } 180ᵘu̲nder ← { (_, _, _, i, _) → i } 181ᵘs̲ayIf ← { yes st → 182 yes ? st ᵘs̲ay 0 183 st 184} 185 186⍝# one frame: an event (a turn, a control, solved again, quit), the 187⍝# solve if it is due, playing, then a frame of turning: 4 frames a 188⍝# quarter turn while more wait, 5 while playing, else 8 189ᵘf̲rame ← { all → 190 (st, sol, pos, mode, on) ← all 191 0 = on ? all 192 v ← ˢᶜn̲ext! w 193 ((v m̲atch "close") + v m̲atch "key q") > 0 ? (st, sol, pos, mode, 0) 194 (v m̲atch "key 0") ? ᵘr̲eset all 195 all ← (mode = 2) ᵘs̲olveIf all 196 p ← ᵘp̲ressed v 197 all ← (p, all) ᵘa̲ct 0 198 all ← ᵘp̲layOn all 199 (st, sol, pos, mode, on) ← all 200 (_, _, q, _, _) ← st 201 fr ← ((mode = 1) × 5) + (mode ≠ 1) × 8 − 4 × 0 < t̲ally q 202 n ← ᵘm̲ade st 203 was ← ᵘu̲nder st 204 st ← (w, fr) ʳᵖa̲dvance st 205 lit ← (was ≠ ᵘu̲nder st) ᵘl̲ightIf ᵘu̲nder st 206 ((n ≠ ᵘm̲ade st) ᵘs̲ayIf st, sol, pos, mode, on) 207} 208ᵘs̲olveIf ← { yes all → 209 yes ? ᵘs̲olveNow all 210 all 211} 212ᵘa̲ct ← { (p, all) z → 213 p > 0 ? p ᵘt̲urnBy all 214 p < 0 ? (0 − p) ᵘc̲ontrol all 215 all 216} 217ᵘl̲ightIf ← { yes i → 218 yes ? ᵘb̲uttons i 219 i 220} 221 222last ← 100000 'ᵘf̲rame p̲ower (ʳᵖstart, 0 r̲eshape 0, 0, 0, 1) 223z ← ˢᶜc̲lose! w 224⍝ (an accessor, not a top-level tuple pattern: xetal doc would list a 225⍝ hidden %N value for one, ask E10) 226ᵘc̲olorsOf ← { ((c, _, _, _, _), _, _, _, _) → c } 227ᵘt̲urnsOf ← { ((_, h, _, _, _), _, _, _, _) → h } 228ᵘm̲adeOf ← { (_, _, pos, _, _) → pos } 229c ← ᵘc̲olorsOf last 230h ← ᵘt̲urnsOf last 231pos ← ᵘm̲adeOf last 232"turns made in all, and the solution's turns made:" 233(t̲ally h) c̲at pos 234"the cube solved at the end:" 235c m̲atch ʳᵇsolved 236"bye"