sourceextensions/scene/demos/voxels-rubik.xtl
1⍝# Voxels, 8: a Rubik's cube. 26 dark cubies with their colored stickers,
2⍝# drawn as voxels; the cube itself is arrays (Rubik.xtl): its 54
3⍝# stickers, each where it is and which way it faces, and each of the
4⍝# twelve quarter turns a permutation of them, computed from the cube's
5⍝# geometry. This demo checks the turns -- each a permutation, four of
6⍝# one solved, a turn and its undoing solved, R U R' U' of order 6, R U
7⍝# of order 105, and U and R turning the right way -- and shows the
8⍝# solved cube, turning slowly; keys turn its faces.
9⍝# Run: just demo scene voxels-rubik
10⍝# u d r l f b turn a face clockwise (as you look at it), Shift with the
11⍝# letter counterclockwise, z undo (back to solved), Space a scramble
12⍝# (25 random turns), 0 reset, drag to look around, q quit
13
14ʳᵇ⁼u̲se< "Rubik"
15ˢᶜ⁼u̲se< "Scene"
16
17⍝## The turns, checked
18
19s ← ʳᵇsolved
20"each turn a permutation of the 54 stickers:"
21'{ (s̲ort ⍵ s̲elect ʳᵇmoves) m̲atch r̲ange 54 } e̲ach r̲ange 12
22ᵘf̲our ← { i → (i ʳᵇt̲urn i ʳᵇt̲urn i ʳᵇt̲urn i ʳᵇt̲urn s) m̲atch s }
23"four of each turn: solved"
24'ᵘf̲our e̲ach r̲ange 12
25ᵘb̲ack ← { i → ((ʳᵇu̲ndo i) ʳᵇt̲urn i ʳᵇt̲urn s) m̲atch s }
26"each turn then its undoing: solved"
27'ᵘb̲ack e̲ach r̲ange 12
28ᵘs̲exy ← { c → 6 ʳᵇt̲urn 2 ʳᵇt̲urn 5 ʳᵇt̲urn 1 ʳᵇt̲urn c }
29ᵘs̲exyN ← { n → (n 'ᵘs̲exy p̲ower s) m̲atch s }
30"R U R' U' solved after 6, not after 1 to 5:"
31(ᵘs̲exyN 6) c̲at 'ᵘs̲exyN e̲ach r̲ange 5
32ᵘr̲u ← { c → 1 ʳᵇt̲urn 5 ʳᵇt̲urn c }
33ᵘr̲uN ← { n → (n 'ᵘr̲u p̲ower s) m̲atch s }
34"R U solved after 105, and how many of 1 to 104:"
35(ᵘr̲uN 105) c̲at '+ r̲/ 'ᵘr̲uN e̲ach r̲ange 104
36m ← ʳᵇstickers
37top ← ((6 s̲elect₂ m) = 1) × (2 s̲elect₂ m) = 1
38"after U, the front's top row has the right face's color (2):"
39(top > 0) r̲eplicate 1 ʳᵇt̲urn s
40
41⍝## The cube, drawn
42
43w ← "Voxels 8: Rubik's cube -- X_eTaL" ˢᶜo̲pen! 560 560
44k ← w ˢᶜc̲amera! 0.6 0.45 7.5 0.3
45b ← ((f̲loat w) c̲at 1.0 0.1 0.1 0.11) ˢᶜq̲uads! ʳᵇbodies
46
47⍝# the stickers, one object of quads for each color
48ᵘd̲raw ← { c →
49 sent ← '{ ((f̲loat w) c̲at (10.0 + f̲loat ⍵) c̲at (⍵ + 1) s̲elect ʳᵇrgb) ˢᶜq̲uads! ⍵ ʳᵇc̲olorSquares c } m̲ap (r̲ange 6) − 1
50 c
51}
52shown ← ᵘd̲raw s
53
54⍝## Turning it
55
56⍝# The state is one Int vector: the 54 colors, then the turns made so
57⍝# far (1 to 12, in the order of rb:names), the history undo walks back.
58⍝# Keys: u d r l f b turn that face clockwise (seen from outside it),
59⍝# with Shift counterclockwise; z undoes the last turn; Space scrambles
60⍝# (25 random turns, never the same face twice in a row); 0 resets.
61
62letters ← "uUdDrRlLfFbB"
63
64⍝# m u:t_ell st: m printed, the state unchanged
65ᵘt̲ell ← { m st →
66 said ← p̲rint! m
67 st
68}
69
70⍝# the turns made, by name (and whether the cube is solved)
71ᵘs̲ay ← { st →
72 h ← 54 d̲rop st
73 0 = t̲ally h ? "solved, no turns" ᵘt̲ell st
74 names ← (n̲ot ʳᵇnames = f̲irst " ") p̲artition ʳᵇnames
75 said ← p̲rint! "turns: " c̲at d̲isclose '{ e̲nclose (d̲isclose ⍺) c̲at " " c̲at d̲isclose ⍵ } r̲/ h s̲elect names
76 ((54 t̲ake st) m̲atch ʳᵇsolved) ? "solved" ᵘt̲ell st
77 st
78}
79
80⍝# i u:t_urnBy st: turn i made and remembered, the cube redrawn
81ᵘt̲urnBy ← { i st →
82 c ← i ʳᵇt̲urn 54 t̲ake st
83 shown ← ᵘd̲raw c
84 c c̲at (54 d̲rop st) c̲at i
85}
86
87⍝# the last turn undone and forgotten
88ᵘu̲ndoLast ← { st →
89 54 = t̲ally st ? st
90 i ← f̲irst -1 t̲ake st
91 c ← (ʳᵇu̲ndo i) ʳᵇt̲urn 54 t̲ake st
92 shown ← ᵘd̲raw c
93 c c̲at 54 d̲rop -1 d̲rop st
94}
95
96⍝# 25 random turns, never the same face twice in a row (so none undoes
97⍝# or repeats the one before), remembered (so undo can walk back to
98⍝# solved)
99ᵘo̲ne ← { st →
100 i ← r̲oll! 12
101 prev ← (55 ≤ t̲ally st) × f̲irst -1 t̲ake st
102 ((i + 1) d̲iv 2) = (prev + 1) d̲iv 2 ? ᵘo̲ne st
103 c ← i ʳᵇt̲urn 54 t̲ake st
104 c c̲at (54 d̲rop st) c̲at i
105}
106ᵘs̲cramble ← { st →
107 st ← 25 'ᵘo̲ne p̲ower st
108 shown ← ᵘd̲raw 54 t̲ake st
109 st
110}
111
112⍝# back to solved, no history
113ᵘr̲eset ← { st →
114 shown ← ᵘd̲raw ʳᵇsolved
115 ʳᵇsolved
116}
117
118ᵘq̲uit ← { st →
119 z ← ˢᶜc̲lose! w
120 0 r̲eshape 0
121}
122
123⍝# one frame: an event, and what it asks for
124ᵘf̲rame ← { st →
125 0 = t̲ally st ? st
126 v ← ˢᶜn̲ext! w
127 ((v m̲atch "close") + v m̲atch "key q") > 0 ? ᵘq̲uit st
128 (v m̲atch "key z") ? ᵘs̲ay ᵘu̲ndoLast st
129 (v m̲atch "key Space") ? ᵘs̲ay ᵘs̲cramble st
130 (v m̲atch "key 0") ? ᵘs̲ay ᵘr̲eset st
131 ch ← -1 t̲ake v
132 i ← letters i̲ndexOf f̲irst ch
133 ((5 = t̲ally v) × i ≤ 12) ? ᵘs̲ay i ᵘt̲urnBy st
134 st
135}
136"keys: u d r l f b turn a face clockwise, Shift+letter counterclockwise, z undo, Space scramble, 0 reset, q quit"
137last ← 100000 'ᵘf̲rame p̲ower ʳᵇsolved
138"bye"