sourceextensions/scene/demos/Rubik.xtl

1⍝# Rubik.xtl -- a Rubik's cube as arrays, for the voxel cube demos 2⍝# (voxels-rubik and after). The cube is its 54 stickers; each sticker is 3⍝# where it is -- its cubie's position x y z, each -1 0 or 1 -- and which 4⍝# way it faces, a unit normal. A turn rotates the stickers of one layer 5⍝# by a quarter turn; matching the rotated stickers against the stickers 6⍝# gives where each one goes, a permutation of 54, and turning the cube 7⍝# is selecting its colors by that permutation. Every position reached 8⍝# by turns is a real cube's. 9⍝# Import: "rb:" u_se< "Rubik" 10 11⍝## Stickers 12 13⍝ the six faces' normals, in the order of the colors: up (+y), down, 14⍝ right (+x), left, front (+z, toward the viewer), back 15normals ← 6 3 r̲eshape 0 1 0 0 -1 0 1 0 0 -1 0 0 0 0 1 0 0 -1 16 17⍝ the 27 cubies' positions, x slowest 18q ← (r̲ange 27) − 1 19cubies ← 2 1 t̲ranspose 3 27 r̲eshape ((q d̲iv 9) − 1) c̲at (((q d̲iv 3) m̲od 3) − 1) c̲at (q m̲od 3) − 1 20 21⍝# h:m_akeStickers 0: the stickers, face by face: the cubies whose 22⍝# coordinate along the face's normal is the normal's sign 23ʰm̲akeStickers ← { z → 24 pick ← cubies '+ '× i̲nner 2 1 t̲ranspose normals 25 on ← pick = 1 26 rows ← '{ (⍵ s̲elect₂ on) r̲eplicate cubies } m̲ap r̲ange 6 27 ns ← '{ 9 3 r̲eshape ⍵ s̲elect normals } m̲ap r̲ange 6 28 pos ← d̲isclose '{ e̲nclose (d̲isclose ⍺) c̲at d̲isclose ⍵ } r̲/ rows 29 nrm ← d̲isclose '{ e̲nclose (d̲isclose ⍺) c̲at d̲isclose ⍵ } r̲/ ns 30 pos c̲at₂ nrm 31} 32 33⍝# a sticker for each face and each of its 9 cubies, 54 by 6: x y z of 34⍝# the cubie, then the normal; the faces in the order up down right left 35⍝# front back, 9 stickers each 36⍝# >> "rb:" u_se< "Rubik" 37⍝# >> s_hape rb:stickers 38⍝# 54 6 39ˡstickers ← ʰm̲akeStickers 0 40 41⍝# the solved cube's colors: each sticker its face's number, 0 to 5 42⍝# (up down right left front back) 43⍝# >> "rb:" u_se< "Rubik" 44⍝# >> 10 t_ake rb:solved 45⍝# 0 0 0 0 0 0 0 0 0 1 46ˡsolved ← 9 r̲eplicate (r̲ange 6) − 1 47 48⍝## Turns 49 50⍝# h:k_ey m: one number for each sticker row (x y z nx ny nz), the same 51⍝# for the same place and facing 52ʰk̲ey ← { m → (3 3 3 3 3 3 d̲ecode 2 1 t̲ranspose m + 1) } 53 54⍝# k h:r_otate m: the rows (x y z, and the normal) turned a quarter turn 55⍝# counterclockwise about the axis k (1 x, 2 y, 3 z), seen from its 56⍝# positive end -- x y z goes to x -z y about x, z y -x about y, -y x z 57⍝# about z 58ʰr̲otate ← { k m → 59 x ← 1 s̲elect₂ m 60 y ← 2 s̲elect₂ m 61 z ← 3 s̲elect₂ m 62 a ← 4 s̲elect₂ m 63 b ← 5 s̲elect₂ m 64 c ← 6 s̲elect₂ m 65 k = 1 ? 2 1 t̲ranspose 6 54 r̲eshape x c̲at (0 − z) c̲at y c̲at a c̲at (0 − c) c̲at b 66 k = 2 ? 2 1 t̲ranspose 6 54 r̲eshape z c̲at y c̲at (0 − x) c̲at c c̲at b c̲at 0 − a 67 2 1 t̲ranspose 6 54 r̲eshape (0 − y) c̲at x c̲at z c̲at (0 − b) c̲at a c̲at c 68} 69 70⍝# (axis layer quarters) rb:p_ermutation 0: the permutation of the 54 71⍝# stickers for turning the layer (the cubies whose coordinate on the 72⍝# axis is the layer, -1 or 1) by that many counterclockwise quarter 73⍝# turns about the axis: the colors after the turn are this selection of 74⍝# the colors before 75ˡp̲ermutation ← { t z → 76 k ← 1 s̲elect t 77 v ← 2 s̲elect t 78 n ← 3 s̲elect t 79 m ← ˡstickers 80 turned ← n '{ k ʰr̲otate ⍵ } p̲ower m 81 inlayer ← v = k s̲elect₂ m 82 moved ← (2 1 t̲ranspose 6 54 r̲eshape inlayer) + 0 83 after ← (moved × turned) + (1 − moved) × m 84 g̲rade (ʰk̲ey m) i̲ndexOf ʰk̲ey after 85} 86 87⍝# the twelve turns' names: a face turned clockwise as you look at it, 88⍝# and with ' counterclockwise 89ˡnames ← "U U' D D' R R' L L' F F' B B'" 90 91⍝ each turn as axis (1 x, 2 y, 3 z), layer, counterclockwise quarters: 92⍝ a face turned clockwise as seen from outside it is a quarter turn 93⍝ clockwise about its outward normal -- three counterclockwise quarters 94⍝ about the axis for up, right and front, one for down, left and back 95specs ← 12 3 r̲eshape 2 1 3 2 1 1 2 -1 1 2 -1 3 1 1 3 1 1 1 1 -1 1 1 -1 3 3 1 3 3 1 1 3 -1 1 3 -1 3 96⍝# the twelve turns' permutations, 12 by 54, in the order of rb:names 97ˡmoves ← 12 54 r̲eshape r̲avel d̲isclose '{ e̲nclose (d̲isclose ⍺) c̲at d̲isclose ⍵ } r̲/ '{ (⍵ s̲elect specs) ˡp̲ermutation 0 } m̲ap r̲ange 12 98 99⍝# i rb:t_urn c: the colors c after turn i (1 to 12, in the order of 100⍝# rb:names) 101⍝# >> "rb:" u_se< "Rubik" 102⍝# >> (4 '{ 1 rb:t_urn _r } p_ower rb:solved) m_atch rb:solved 103⍝# 1 104ˡt̲urn ← { i c → (i s̲elect ˡmoves) s̲elect c } 105 106⍝# rb:u_ndo i: the turn that undoes turn i (U and U', and so on) 107⍝# >> "rb:" u_se< "Rubik" 108⍝# >> rb:u_ndo 1 2 5 109⍝# 2 1 6 110ˡu̲ndo ← { i → i + 1 − 2 × 0 = i m̲od 2 } 111 112⍝## Drawing 113 114⍝# (offset half) h:s_quaresAt rows: a square for each row (x y z of a 115⍝# cubie, then a normal), its center offset along the normal, its half 116⍝# side half, its 4 corners in order round it; 4n by 3, row by row 117ʰs̲quaresAt ← { oh pn → 118 p ← f̲loat 1 2 3 s̲elect₂ pn 119 n ← f̲loat 4 5 6 s̲elect₂ pn 120 ax ← (a̲bs 4 s̲elect₂ pn) + (2 × a̲bs 5 s̲elect₂ pn) + 3 × a̲bs 6 s̲elect₂ pn 121 u ← ax s̲elect 3 3 r̲eshape 0.0 1.0 0.0 1.0 0.0 0.0 1.0 0.0 0.0 122 w ← ax s̲elect 3 3 r̲eshape 0.0 0.0 1.0 0.0 0.0 1.0 0.0 1.0 0.0 123 c ← p + (1 s̲elect oh) × n 124 h ← 2 s̲elect oh 125 k1 ← c + h × (0.0 − u) − w 126 k2 ← c + h × u − w 127 k3 ← c + h × u + w 128 k4 ← c + h × w − u 129 m ← t̲ally pn 130 ((4 × m) c̲at 3) r̲eshape 2 1 3 t̲ranspose (4 c̲at m c̲at 3) r̲eshape k1 c̲at k2 c̲at k3 c̲at k4 131} 132 133⍝# the stickers as squares for scene, 4 corners each in order round 134⍝# them (216 by 3), in the stickers' order, just outside the cubies' 135⍝# dark bodies 136ˡsquares ← 0.485 0.42 ʰs̲quaresAt ˡstickers 137 138⍝ the 26 cubies one can see (all but the middle), with each normal 139shell ← (0 < '+ r̲/₂ a̲bs cubies) r̲eplicate cubies 140bodyrows ← d̲isclose '{ e̲nclose (d̲isclose ⍺) c̲at d̲isclose ⍵ } r̲/ '{ shell c̲at₂ 26 3 r̲eshape ⍵ s̲elect normals } m̲ap r̲ange 6 141 142⍝# the cubies' dark bodies as squares for scene (624 by 3): six faces 143⍝# each, 0.96 wide 144ˡbodies ← 0.48 0.48 ʰs̲quaresAt bodyrows 145 146⍝# k rb:c_olorSquares c: the squares of the stickers that are color k 147⍝# in the colors c (k 0 to 5), for one object of quads 148⍝# >> "rb:" u_se< "Rubik" 149⍝# >> s_hape 0 rb:c_olorSquares rb:solved 150⍝# 36 3 151ˡc̲olorSquares ← { k c → 152 i ← w̲here c = k 153 (r̲avel (4 × i − 1) '+ t̲able 1 2 3 4) s̲elect ˡsquares 154} 155 156⍝# each color, red green blue: white (up), yellow (down), red (right), 157⍝# orange (left), green (front), blue (back) 158ˡrgb ← 6 3 r̲eshape 0.95 0.95 0.95 1.0 0.84 0.1 0.82 0.12 0.12 1.0 0.5 0.08 0.1 0.62 0.25 0.12 0.32 0.85