rebol [ Title: "Rubic Cube Simulation" Date: 01-Jan-2006 File: %vcube2.r Version: 1.0.0 Email: phil.bevan@bigfoot.com Category: [game] Purpose: { Rubic Cube Simulation } License: {Copyright (c) <2004,2005, 2006>, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.} History: [ 0.0.1 - Initial Test Version 1.0.0 - Initial Release ] ] cube: "111111111222222222333333333444444444555555555666666666" ncube: "" gv-moves: [] gv-record: false gv-rec-moves: [] gv-1: [ [01 03 09 07 02 06 08 04 10 11 12 37 38 39 28 29 30 19 20 21] [07 19 46 45 08 22 49 42 09 25 52 39 10 12 18 16 11 15 17 13] [09 28 48 18 06 31 47 15 03 34 46 12 19 21 27 25 20 24 26 22] [25 34 43 16 26 35 44 17 27 36 45 18 46 48 54 52 47 51 53 49] [01 43 48 21 02 40 51 24 03 37 54 27 28 30 36 34 29 33 35 31] [01 10 52 36 04 13 53 33 07 16 54 30 37 39 45 43 38 42 44 40] [05 14 50 32 08 17 51 29 02 11 49 35] [05 23 50 41 04 20 47 44 06 26 53 38] [23 32 41 14 22 31 40 13 24 33 42 15] ] gv-2: [ [03 09 07 01 06 08 04 02 37 38 39 28 29 30 19 20 21 10 11 12] [19 46 45 07 22 49 42 08 25 52 39 09 12 18 16 10 15 17 13 11] [28 48 18 09 31 47 15 06 34 46 12 03 21 27 25 19 24 26 22 20] [34 43 16 25 35 44 17 26 36 45 18 27 48 54 52 46 51 53 49 47] [43 48 21 01 40 51 24 02 37 54 27 03 30 36 34 28 33 35 31 29] [10 52 36 01 13 53 33 04 16 54 30 07 39 45 43 37 42 44 40 38] [14 50 32 05 17 51 29 08 11 49 35 02] [23 50 41 05 20 47 44 04 26 53 38 06] [14 23 32 41 13 22 31 40 15 24 33 42] ] fn-move: func [ip-idx [integer!] ip-clockwise [logic!]] [ ncube: copy cube for i 1 (length? gv-1/:ip-idx) 1 [ either ip-clockwise [ f-fr: pick gv-1/:ip-idx i f-to: pick gv-2/:ip-idx i ] [ f-fr: pick gv-2/:ip-idx i f-to: pick gv-1/:ip-idx i ] ncube/:f-to: cube/:f-fr ] cube: copy ncube ] uc: func [/undo][ if not undo [append gv-moves "uc"] if gv-record [append gv-rec-moves "uc"] fn-move 1 true ] ua: func [/undo][ if not undo [append gv-moves "ua"] if gv-record [append gv-rec-moves "ua"] fn-move 1 false ] fc: func [/undo][ if not undo [append gv-moves "fc"] if gv-record [append gv-rec-moves "fc"] fn-move 2 true ] fa: func [/undo][ if not undo [append gv-moves "fa"] if gv-record [append gv-rec-moves "fa"] fn-move 2 false ] rc: func [/undo][ if not undo [append gv-moves "rc"] if gv-record [append gv-rec-moves "rc"] fn-move 3 true ] ra: func [/undo][ if not undo [append gv-moves "ra"] if gv-record [append gv-rec-moves "ra"] fn-move 3 false ] dc: func [/undo][ if not undo [append gv-moves "dc"] if gv-record [append gv-rec-moves "dc"] fn-move 4 true ] da: func [/undo][ if not undo [append gv-moves "da"] if gv-record [append gv-rec-moves "da"] fn-move 4 false ] bc: func [/undo][ if not undo [append gv-moves "bc"] if gv-record [append gv-rec-moves "bc"] fn-move 5 true ] ba: func [/undo][ if not undo [append gv-moves "ba"] if gv-record [append gv-rec-moves "ba"] fn-move 5 false ] lc: func [/undo][ if not undo [append gv-moves "lc"] if gv-record [append gv-rec-moves "lc"] fn-move 6 true ] la: func [/undo][ if not undo [append gv-moves "la"] if gv-record [append gv-rec-moves "la"] fn-move 6 false ] c1c: func [/undo][ if not undo [append gv-moves "c1c"] if gv-record [append gv-rec-moves "c1c"] fn-move 7 true ] c1a: func [/undo][ if not undo [append gv-moves "c1a"] if gv-record [append gv-rec-moves "c1a"] fn-move 7 false ] c2c: func [/undo][ if not undo [append gv-moves "c2c"] if gv-record [append gv-rec-moves "c2c"] fn-move 8 true ] c2a: func [/undo][ if not undo [append gv-moves "c2a"] if gv-record [append gv-rec-moves "c2a"] fn-move 8 false ] c3c: func [/undo][ if not undo [append gv-moves "c3c"] if gv-record [append gv-rec-moves "c3c"] fn-move 9 true ] c3a: func [/undo][ if not undo [append gv-moves "c3a"] if gv-record [append gv-rec-moves "c3c"] fn-move 9 false ] fn-str-move: func [ip-str [string!]][ switch ip-str [ "uc" [uc] "ua" [ua] "fc" [fc] "fa" [fa] "rc" [rc] "ra" [ra] "bc" [bc] "ba" [ba] "lc" [lc] "la" [la] "dc" [dc] "da" [da] "c1c" [c1c] "c1a" [c1a] "c2c" [c2c] "c2a" [c2a] "c3c" [c3c] "c3a" [c3a] ] ] fn-str-move-rev: func [ip-str [string!]][ switch ip-str [ "uc" [ua/undo] "ua" [uc/undo] "fc" [fa/undo] "fa" [fc/undo] "rc" [ra/undo] "ra" [rc/undo] "bc" [ba/undo] "ba" [bc/undo] "lc" [la/undo] "la" [lc/undo] "dc" [da/undo] "da" [dc/undo] "c1c" [c1a/undo] "c1a" [c1c/undo] "c2c" [c2a/undo] "c2a" [c2c/undo] "c3c" [c3a/undo] "c3a" [c3c/undo] ] ] ; move names gv-move-names: [] ; associated moves gv-dec-moves: [] fn-load-comb: func [][ context [ if exists? %combinations.rbc [ lv-lines: read/lines %combinations.rbc foreach lv-line lv-lines [ lv-moves: parse lv-line none append gv-move-names first lv-moves remove lv-moves append/only gv-dec-moves lv-moves ] ] ] ; probe gv-move-names ; probe gv-dec-moves ] ; do a sequence of moves fn-do-seq: func [ip-moves [block!]][ context [ foreach lv-move ip-moves [ either #"m" = first lv-move [ lv-idx: to integer! pick parse lv-move none 2 ; print ["Iter " lv-move pick gv-dec-moves lv-idx] fn-do-seq pick gv-dec-moves lv-idx ] [ ; print lv-move fn-str-move lv-move fn-draw ] ] ] ] ; display a move combination fn-disp: func [ip-sel [block!]][ context [ foreach lv-sel-move ip-sel [ lv-move: find gv-move-names lv-sel-move lv-moves: pick gv-dec-moves (index? lv-move) ; print ["AAA" lv-moves] view/new layout [ backdrop 0.150.0 text-list data lv-moves 100 ] ] ] ] ; display a move combination fn-del: func [ip-sel [block!] ip-info [object!]][ context [ foreach lv-sel-move ip-sel [ lv-move: find gv-move-names lv-sel-move lv-moves: skip gv-dec-moves ((index? lv-move) - 1) remove lv-move remove lv-moves ] ] fn-save-macros show ip-info ] ; decode the moves fn-dec-moves: func [ip-sel [block!]][ context [ foreach lv-sel-move ip-sel [ lv-move: find gv-move-names lv-sel-move lv-moves: pick gv-dec-moves (index? lv-move) ; print ["AAA" lv-moves] fn-do-seq lv-moves ] ] ] ; save the position fn-save: func [/local fil][ fil: request-file/title/keep/only "Save Position" "Save" either fil = none [alert "Position not Saved"] [write fil cube] ] ; save a position fn-load: func [/local fil t-cube t-col][ fil: request-file/title/keep/only "Load Position" "Load" either fil = none [ alert "Position not Loaded" return ] [ t-cube: read fil if 54 <> length? t-cube [alert "Position Invalid" return] for i 1 54 1 [ t-col: pick t-cube i if any [t-col < #"1" t-col > #"9"] [alert "Position Invalid" return] ] cube: t-cube fn-draw ] ] fn-reset: func [][ clear gv-moves cube: "111111111222222222333333333444444444555555555666666666" fn-draw ] ; create a Random position fn-random: func [][ cube: "111111111222222222333333333444444444555555555666666666" random/seed now/precise 12 for i 1 100 1 [ mov: random 12 either mov > 6 [fn-move (mov - 6) false] [fn-move mov true] fn-draw ] ] ; remove a move fn-undo: func [][ context [ either 0 = length? gv-moves [alert "No more moves to remove"] [ lv-last: first back tail gv-moves ; print [lv-last type? lv-last] fn-str-move-rev lv-last remove back tail gv-moves fn-draw ] ] ] fn-record: func [ip-info [object!]][ clear gv-rec-moves gv-record: true ip-info/text: "Recording" show ip-info ] fn-save-macros: func [/local lv-os][ context [ lv-str: "" for i 1 (length? gv-move-names) 1 [ lv-str: rejoin [lv-str (mold pick gv-move-names i) " " (mold/only pick gv-dec-moves i) "^/"] ] write %combinations.rbc lv-str ] ] fn-record-stop: func [ip-info [object!]][ context [ fn-ok: func [][ if f-name/text = "" [ alert "A name must be entered" return false ] append gv-move-names copy f-name/text append/only gv-dec-moves copy gv-rec-moves fn-save-macros show f-moves return true ] lv-lay: layout [ across f-name: field 200 return btn "OK" 60 [if fn-ok [hide-popup]] btn "Cancel" 60 [hide-popup] ] focus f-name inform/title lv-lay "Save Moves" gv-record: false clear gv-rec-moves ip-info/text: "" show ip-info ] ] ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Draw the Cube in 3-D Persective ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; objs: [ ; Cube, side 6, centre origin [ ; angles & co-ordinates [0 0 0 -45 0 120] ;obj/1 ;points [ ; layer 1 [-3 3 3] [-1 3 3] [1 3 3] [3 3 3] [-3 1 3] [-1 1 3] [1 1 3] [3 1 3] [-3 -1 3] [-1 -1 3] [1 -1 3] [3 -1 3] [-3 -3 3] [-1 -3 3] [1 -3 3] [3 -3 3] ; layer 2 [-3 3 1] [-1 3 1] [1 3 1] [3 3 1] [-3 1 1] [3 1 1] [-3 -1 1] [3 -1 1] [-3 -3 1] [-1 -3 1] [1 -3 1] [3 -3 1] ; layer 3 [-3 3 -1] [-1 3 -1] [1 3 -1] [3 3 -1] [-3 1 -1] [3 1 -1] [-3 -1 -1] [3 -1 -1] [-3 -3 -1] [-1 -3 -1] [1 -3 -1] [3 -3 -1] ; layer 4 [-3 3 -3] [-1 3 -3] [1 3 -3] [3 3 -3] [-3 1 -3] [-1 1 -3] [1 1 -3] [3 1 -3] [-3 -1 -3] [-1 -1 -3] [1 -1 -3] [3 -1 -3] [-3 -3 -3] [-1 -3 -3] [1 -3 -3] [3 -3 -3] ] ;obj/2 ; points after rotation & translation [] ;obj/3 ; points after perspective transformation [] ;obj/4 ; faces ; [verticies] show [type type-no] distance [vertex orientation] name] [ ; top [[1 5 6 2] false [2 1] 0] [[2 6 7 3] false [2 1] 0] [[3 7 8 4] false [2 1] 0] [[5 9 10 6] false [2 1] 0] [[6 10 11 7] false [2 1] 0] [[7 11 12 8] false [2 1] 0] [[9 13 14 10] false [2 1] 0] [[10 14 15 11] false [2 1] 0] [[11 15 16 12] false [2 1] 0] ; front [[13 25 26 14] false [2 2] 0] [[14 26 27 15] false [2 2] 0] [[15 27 28 16] false [2 2] 0] [[25 37 38 26] false [2 2] 0] [[26 38 39 27] false [2 2] 0] [[27 39 40 28] false [2 2] 0] [[37 53 54 38] false [2 2] 0] [[38 54 55 39] false [2 2] 0] [[39 55 56 40] false [2 2] 0] ; right [[16 28 24 12] false [2 3] 0] [[12 24 22 8] false [2 3] 0] [[8 22 20 4] false [2 3] 0] [[28 40 36 24] false [2 3] 0] [[24 36 34 22] false [2 3] 0] [[22 34 32 20] false [2 3] 0] [[40 56 52 36] false [2 3] 0] [[36 52 48 34] false [2 3] 0] [[34 48 44 32] false [2 3] 0] ; back [[3 4 20 19] false [2 4] 0] [[2 3 19 18] false [2 4] 0] [[1 2 18 17] false [2 4] 0] [[19 20 32 31] false [2 4] 0] [[18 19 31 30] false [2 4] 0] [[17 18 30 29] false [2 4] 0] [[31 32 44 43] false [2 4] 0] [[30 31 43 42] false [2 4] 0] [[29 30 42 41] false [2 4] 0] ; left [[5 1 17 21] false [2 5] 0] [[9 5 21 23] false [2 5] 0] [[13 9 23 25] false [2 5] 0] [[21 17 29 33] false [2 5] 0] [[23 21 33 35] false [2 5] 0] [[25 23 35 37] false [2 5] 0] [[33 29 41 45] false [2 5] 0] [[35 33 45 49] false [2 5] 0] [[37 35 49 53] false [2 5] 0] ; bottom [[51 52 56 55] false [2 6] 0] [[47 48 52 51] false [2 6] 0] [[43 44 48 47] false [2 6] 0] [[50 51 55 54] false [2 6] 0] [[46 47 51 50] false [2 6] 0] [[42 43 47 46] false [2 6] 0] [[49 50 54 53] false [2 6] 0] [[45 46 50 49] false [2 6] 0] [[41 42 46 45] false [2 6] 0] ] ;obj/5 ] ] camera: [0 0 60 0 0 1600 1600] ; x y z a1 a2 xsc ysc clrs: reduce['White 'Orange 'Blue 'Red 'Green 'Yellow] fn-rot: func ["Rotate the cube" obj [block!]][ context [ c1: cosine obj/1/4 c2: cosine obj/1/5 c3: cosine obj/1/6 s1: sine obj/1/4 s2: sine obj/1/5 s3: sine obj/1/6 clear obj/3 clear obj/4 obj/3: copy/deep obj/2 ; calculate the perspective of the points after the roation & translation foreach point obj/3 [ ; Roation about z axis x1: (point/1 * c1) - (point/2 * s1) y1: (point/1 * s1) + (point/2 * c1) z1: point/3 ; Roation about y axis x2: (x1 * c2) + (point/3 * s2) y2: y1 z2: - (x1 * s2) + (point/3 * c2) x3: x2 + obj/1/1 y3: (y2 * c3) - (z2 * s3) + obj/1/2 z3: (y2 * s3) + (z2 * c3) + obj/1/3 poke point 1 (x3 + camera/1) poke point 2 (y3 + camera/2) poke point 3 (z3 + camera/3) x: point/1 / point/3 * camera/6 y: point/2 / point/3 * camera/7 append obj/4 to pair! reduce[(x + origin/x) (y + origin/y)] ] foreach f obj/5 [ p1: f/1/1 p2: f/1/2 p3: f/1/3 d1: reduce [(obj/3/:p2/1 - obj/3/:p1/1) (obj/3/:p2/2 - obj/3/:p1/2) (obj/3/:p2/3 - obj/3/:p1/3)] d2: reduce [(obj/3/:p3/1 - obj/3/:p1/1) (obj/3/:p3/2 - obj/3/:p1/2) (obj/3/:p3/3 - obj/3/:p1/3)] poke f 4 (-2 * obj/3/:p1/3 - d1/3 - d2/3) n1: (d1/2 * d2/3) - (d1/3 * d2/2) n2: - (d1/1 * d2/3) + (d1/3 * d2/1) n3: (d1/1 * d2/2) - (d1/2 * d2/1) v: 0 > ((obj/3/:p1/1 * n1) + (obj/3/:p1/2 * n2) + (obj/3/:p1/3 * n3)) poke f 2 v ] ] ] fn-show: func ["Show the cube" ip-face [object!] d-bl [block!]][ context [ ; setup the faces to be shown pts: [] clear draw-o foreach o objs [ foreach f o/5 [ if f/2 = true [ append draw-o f/4 switch f/3/1 [ 1 [append/only draw-o reduce ['image (pick bmps f/3/2) pick o/4 f/1/1 pick o/4 f/1/2 pick o/4 f/1/3 pick o/4 f/1/4]] 2 [ pts: copy reduce ['fill-pen (pick clrs f/3/2) 'polygon] foreach coord f/1 [append pts pick o/4 coord] append/only draw-o pts ] ] ] ] ] ; sort the faces sort/skip draw-o 2 ; reset the draw-block clear d-bl append d-bl reduce ['pen black] ; create the draw block forskip draw-o 2 [append d-bl draw-o/2] ; show the face show ip-face ] ] origin: 150x150 fn-draw: func [][ for i 1 54 1 [objs/1/5/:i/3/2: (to integer! cube/:i - 48)] foreach o objs [fn-rot o] fn-show f-box1 draw-bl-1 objs/1/1/4: objs/1/1/4 + 180 foreach o objs [fn-rot o] fn-show f-box2 draw-bl-2 objs/1/1/4: objs/1/1/4 - 180 ] fn-reset-view: func ["Reset the view"][ objs/1/1: copy [0 0 0 -45 0 120] fn-draw ] fn-help: func [][ context [ help-data: { The faces of the cube are labelled U - Up, the Top face, D - Down, the Top face F - Front, the face to the left looking from the front B - Back, the face to the left looking from the front R - Front, the face to the right looking from the front L - Back, the face to the left looking from the front Press the buttons to move the faces : U+ = Up Clockwise by 90 degrees, U- = Up Anti clockwise by 90 degrees U++ = Up Clockwise by 180 degrees, U-- = Up Anti clockwise by 180 degrees F+ = Front Clockwise by 90 degrees, F- = Front Anti clockwise by 90 degrees F++ = Front Clockwise by 180 degrees, F-- = Front Anti clockwise by 180 degrees R+ = Right Clockwise by 90 degrees, R- = Right Anti clockwise by 90 degrees R++ = Right Clockwise by 180 degrees, R-- = Right Anti clockwise by 180 degrees B+ = Back Clockwise by 90 degrees, B- = Back Anti clockwise by 90 degrees B++ = Back Clockwise by 180 degrees, B-- = Back Anti clockwise by 180 degrees L+ = Left Clockwise by 90 degrees, L- = Left Anti clockwise by 90 degrees L++ = Left Clockwise by 180 degrees, L-- = Left Anti clockwise by 180 degrees D+ = Down Clockwise by 90 degrees, D- = Down Anti clockwise by 90 degrees D++ = Down Clockwise by 180 degrees, D-- = Down Anti clockwise by 180 degrees To Rotate the view of the cube use the following keys Keys: cusror up - Rotate about the X axis clockwise cusror down - Rotate about the X axis anti-clockwise cusror left - Rotate about the Y axis clockwise cusror right - Rotate about the Y axis anti-clockwise "+" - Rotate about the Y axis clockwise "-" - Rotate about the Y axis anti-clockwise } view/title/new layout [ space 4x4 backdrop 0.150.0 Banner "A Simple Rubic Cube explorer" area help-data font-fixed 500x500 ] "Rubic Cube Simulator - Help" ] ] ;;;;;;;;;;; ; ; Main Line ; ;;;;;;;;;;; ; draw order for all faces draw-o: [] ; draw block draw-bl: [] draw-bl-1: [] draw-bl-2: [] ;load in move combinations fn-load-comb ; probe draw-bl next-move: 0 lay: layout [ style mbtn btn 30 space 10x10 across backdrop 0.150.0 panel [ across space 0x0 vh1 "Front View" center font-size 20 300 vh1 "Back View" center font-size 20 300 vh1 "Moves" center font-size 20 200 ] 820x30 return f-box1: box 300x300 effect [draw draw-bl-1] edge [size: 2x2 color: gray effect: 'bevel] f-box2: box 300x300 effect [draw draw-bl-2] edge [size: 2x2 color: gray effect: 'bevel] panel [ f-moves: text-list 200 data gv-move-names across space 0x10 btn "Run" [fn-dec-moves f-moves/picked] btn "Rec" [fn-record f-info] btn "Save" [fn-record-stop f-info] btn "Disp" [fn-disp f-moves/picked] btn "Del" [fn-del f-moves/picked f-moves] return f-info: info silver ] return space 0 mbtn "U+" [uc fn-draw] mbtn "U-" [ua fn-draw] mbtn "R+" [rc fn-draw] mbtn "R-" [ra fn-draw] mbtn "F+" [fc fn-draw] mbtn "F-" [fa fn-draw] mbtn "L+" [lc fn-draw] mbtn "L-" [la fn-draw] mbtn "B+" [bc fn-draw] mbtn "B-" [ba fn-draw] mbtn "D+" [dc fn-draw] mbtn "D-" [da fn-draw] mbtn "C1+" [c1c fn-draw] mbtn "C1-" [c1a fn-draw] mbtn "C2+" [c2c fn-draw] mbtn "C2-" [c2a fn-draw] mbtn "C3+" [c3c fn-draw] mbtn "C3-" [c3a fn-draw] return mbtn "U++" [uc uc fn-draw] mbtn "U--" [ua ua fn-draw] mbtn "R++" [rc rc fn-draw] mbtn "R--" [ra ra fn-draw] mbtn "F++" [fc fc fn-draw] mbtn "F--" [fa fa fn-draw] mbtn "L++" [lc lc fn-draw] mbtn "L--" [la la fn-draw] mbtn "B++" [bc bc fn-draw] mbtn "B--" [ba ba fn-draw] mbtn "D++" [dc dc fn-draw] space 0x4 mbtn "D--" [da da fn-draw] return btn "Reset" [fn-reset] btn "Save" [fn-save] btn "Load" [fn-load] btn "Random" [fn-random] btn "Undo" [fn-undo] btn "Reset View" [fn-reset-view] btn "Help" [fn-help] sensor 0x0 keycode [#"+" #"-" up down left right] [ switch value [ up [objs/1/1/4: objs/1/1/4 + 5 fn-draw if objs/1/1/4 > 360 [objs/1/1/4: objs/1/1/4 - 360]] down [objs/1/1/4: objs/1/1/4 - 5 fn-draw if objs/1/1/4 < 0 [objs/1/1/4: objs/1/1/4 + 360]] left [objs/1/1/5: objs/1/1/5 + 5 fn-draw if objs/1/1/5 > 360 [objs/1/1/5: objs/1/1/5 - 360]] right [objs/1/1/5: objs/1/1/5 - 5 fn-draw if objs/1/1/5 < 0 [objs/1/1/5: objs/1/1/5 + 360]] #"+" [objs/1/1/6: objs/1/1/6 + 5 fn-draw if objs/1/1/6 < 0 [objs/1/1/6: objs/1/1/6 + 360]] #"-" [objs/1/1/6: objs/1/1/6 - 5 fn-draw if objs/1/1/6 < 0 [objs/1/1/6: objs/1/1/6 + 360]] ] ] ] ; Setup Draw Blaock draw-bl: copy [pen black] fn-draw view/title lay "Rubic Cube Simulation"