slices.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*
  2. SLICES
  3. Slices are thin layers sliced out of the Cube
  4. composed of 9 Cubelets (3x3 grid).
  5. The position of these Cubelets can be mapped as follows:
  6. ----------- ----------- -----------
  7. | | | |
  8. | northWest | north | northEast |
  9. | 0 | 1 | 2 |
  10. | | | |
  11. ----------- ----------- -----------
  12. | | | |
  13. | west | origin | east |
  14. | 3 | 4 | 5 |
  15. | | | |
  16. ----------- ----------- -----------
  17. | | | |
  18. | southWest | south | southEast |
  19. | 6 | 7 | 8 |
  20. | | | |
  21. ----------- ----------- -----------
  22. The cubelets[] Array is mapped to names for convenience:
  23. this.cubelets[ 0 ] === this.northWest
  24. this.cubelets[ 1 ] === this.north
  25. this.cubelets[ 2 ] === this.northEast
  26. this.cubelets[ 3 ] === this.west
  27. this.cubelets[ 4 ] === this.origin
  28. this.cubelets[ 5 ] === this.east
  29. this.cubelets[ 6 ] === this.southWest
  30. this.cubelets[ 7 ] === this.south
  31. this.cubelets[ 8 ] === this.southEast
  32. Portions of Slices can be Grouped:
  33. Rows and columns as strips (1x3)
  34. this.up
  35. this.equator
  36. this.down
  37. this.left
  38. this.middle
  39. this.right
  40. Other combinations
  41. this.cross
  42. this.edges
  43. this.ex
  44. this.corners
  45. this.ring
  46. this.dexter
  47. this.sinister
  48. A Slice may be inspected from the browser's JavaScript console with:
  49. this.inspect()
  50. This will reveal the Slice's Cubelets, their Indexes, and colors.
  51. A compact inspection mode is also available:
  52. this.inspect( true )
  53. This is most useful for Slices that are also Faces. For Slices that are
  54. not Faces, or for special cases, it may be useful to send a side
  55. argument which is usually by default the Slice's origin's only visible
  56. side if it has one.
  57. this.inspect( false, 'up' )
  58. this.inspect( true, 'up' )
  59. CUBE FACES vs CUBE SLICES
  60. All Cube faces are Slices, but not all Slices are Cube faces.
  61. For example, a Cube has 6 faces: front, up, right, down, left, back.
  62. But it also has slices that that cut through the center of the Cube
  63. itself: equator, middle, and standing. When a Slice maps itself it
  64. inspects the faces of the Cubelet in the origin position of the Slice --
  65. the center piece -- which can either have a single visible face or no
  66. visible face. If it has a visible face then the Slice's face and the
  67. face's direction is in the direction of that Cubelet's visible face.
  68. This seems redundant from the Cube's perspective:
  69. cube.front.face === 'front'
  70. However it becomes valuable from inside a Slice or Fold when a
  71. relationship to the Cube's orientation is not immediately clear:
  72. if( this.face === 'front' )...
  73. Therefore a Slice (s) is also a face if s.face !== undefined.
  74. */
  75. export function Slice(){
  76. this.cubelets = Array.prototype.slice.call( arguments )
  77. this.map()
  78. }
  79. globalThis.setupTasks = globalThis.setupTasks || []
  80. globalThis.setupTasks.push( function(){
  81. augment( Slice, {
  82. inspect: function( compact, side ){
  83. var
  84. getColorName = function( cubelet ){
  85. return cubelet[ side ].color.name.toUpperCase().justifyCenter( 9 )
  86. },
  87. sideLabel = ''
  88. if( side === undefined ){
  89. if( this.face !== undefined ) side = this.face
  90. else side = 'front'
  91. }
  92. if( side instanceof Direction ) side = side.name
  93. if( side !== this.face ) sideLabel = side + 's'
  94. if( compact ){
  95. console.log(
  96. '\n' + this.name.capitalize().justifyLeft( 10 ) +
  97. '%c '+ this.northWest.id.toPaddedString( 2 ) +' %c '+
  98. '%c '+ this.north.id.toPaddedString( 2 ) +' %c '+
  99. '%c '+ this.northEast.id.toPaddedString( 2 ) +' %c '+
  100. '\n' + sideLabel +'\n'+
  101. ' %c '+ this.west.id.toPaddedString( 2 ) +' %c '+
  102. '%c '+ this.origin.id.toPaddedString( 2 ) +' %c '+
  103. '%c '+ this.east.id.toPaddedString( 2 ) +' %c '+
  104. '\n\n'+
  105. ' %c '+ this.southWest.id.toPaddedString( 2 ) +' %c '+
  106. '%c '+ this.south.id.toPaddedString( 2 ) +' %c '+
  107. '%c '+ this.southEast.id.toPaddedString( 2 ) +' %c '+
  108. '\n',
  109. this.northWest[ side ].color.styleB, '',
  110. this.north[ side ].color.styleB, '',
  111. this.northEast[ side ].color.styleB, '',
  112. this.west[ side ].color.styleB, '',
  113. this.origin[ side ].color.styleB, '',
  114. this.east[ side ].color.styleB, '',
  115. this.southWest[ side ].color.styleB, '',
  116. this.south[ side ].color.styleB, '',
  117. this.southEast[ side ].color.styleB, ''
  118. )
  119. }
  120. else {
  121. console.log(
  122. '\n %c %c %c %c %c %c '+
  123. '\n'+ this.name.capitalize().justifyLeft( 10 ) +
  124. '%c northWest %c '+
  125. '%c north %c '+
  126. '%c northEast %c '+
  127. '\n' + sideLabel.justifyLeft( 10 ) +
  128. '%c '+ this.northWest.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  129. '%c '+ this.north.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  130. '%c '+ this.northEast.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  131. '\n' +
  132. ' %c ' + getColorName( this.northWest ) +' %c '+
  133. '%c '+ getColorName( this.north ) +' %c '+
  134. '%c '+ getColorName( this.northEast ) +' %c '+
  135. '\n %c %c %c %c %c %c '+
  136. '\n\n %c %c %c %c %c %c '+
  137. '\n %c west %c '+
  138. '%c origin %c '+
  139. '%c east %c '+
  140. '\n' +
  141. ' %c ' + this.west.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  142. '%c '+ this.origin.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  143. '%c '+ this.east.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  144. '\n' +
  145. ' %c ' + getColorName( this.west ) +' %c '+
  146. '%c '+ getColorName( this.origin ) +' %c '+
  147. '%c '+ getColorName( this.east ) +' %c '+
  148. '\n %c %c %c %c %c %c '+
  149. '\n\n %c %c %c %c %c %c '+
  150. '\n %c southWest %c '+
  151. '%c south %c '+
  152. '%c southEast %c '+
  153. '\n' +
  154. ' %c ' + this.southWest.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  155. '%c '+ this.south.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  156. '%c '+ this.southEast.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+
  157. '\n' +
  158. ' %c ' + getColorName( this.southWest ) +' %c '+
  159. '%c '+ getColorName( this.south ) +' %c '+
  160. '%c '+ getColorName( this.southEast ) +' %c '+
  161. '\n %c %c %c %c %c %c\n',
  162. this.northWest[ side ].color.styleB, '',
  163. this.north[ side ].color.styleB, '',
  164. this.northEast[ side ].color.styleB, '',
  165. this.northWest[ side ].color.styleB, '',
  166. this.north[ side ].color.styleB, '',
  167. this.northEast[ side ].color.styleB, '',
  168. this.northWest[ side ].color.styleB, '',
  169. this.north[ side ].color.styleB, '',
  170. this.northEast[ side ].color.styleB, '',
  171. this.northWest[ side ].color.styleB, '',
  172. this.north[ side ].color.styleB, '',
  173. this.northEast[ side ].color.styleB, '',
  174. this.northWest[ side ].color.styleB, '',
  175. this.north[ side ].color.styleB, '',
  176. this.northEast[ side ].color.styleB, '',
  177. this.west[ side ].color.styleB, '',
  178. this.origin[ side ].color.styleB, '',
  179. this.east[ side ].color.styleB, '',
  180. this.west[ side ].color.styleB, '',
  181. this.origin[ side ].color.styleB, '',
  182. this.east[ side ].color.styleB, '',
  183. this.west[ side ].color.styleB, '',
  184. this.origin[ side ].color.styleB, '',
  185. this.east[ side ].color.styleB, '',
  186. this.west[ side ].color.styleB, '',
  187. this.origin[ side ].color.styleB, '',
  188. this.east[ side ].color.styleB, '',
  189. this.west[ side ].color.styleB, '',
  190. this.origin[ side ].color.styleB, '',
  191. this.east[ side ].color.styleB, '',
  192. this.southWest[ side ].color.styleB, '',
  193. this.south[ side ].color.styleB, '',
  194. this.southEast[ side ].color.styleB, '',
  195. this.southWest[ side ].color.styleB, '',
  196. this.south[ side ].color.styleB, '',
  197. this.southEast[ side ].color.styleB, '',
  198. this.southWest[ side ].color.styleB, '',
  199. this.south[ side ].color.styleB, '',
  200. this.southEast[ side ].color.styleB, '',
  201. this.southWest[ side ].color.styleB, '',
  202. this.south[ side ].color.styleB, '',
  203. this.southEast[ side ].color.styleB, '',
  204. this.southWest[ side ].color.styleB, '',
  205. this.south[ side ].color.styleB, '',
  206. this.southEast[ side ].color.styleB, ''
  207. )
  208. }
  209. },
  210. map: function(){
  211. // Addressing single Cubelets can best be done by
  212. // compass notation.
  213. this.origin = this.cubelets[ 4 ]
  214. this.north = this.cubelets[ 1 ]
  215. this.northEast = this.cubelets[ 2 ]
  216. this.east = this.cubelets[ 5 ]
  217. this.southEast = this.cubelets[ 8 ]
  218. this.south = this.cubelets[ 7 ]
  219. this.southWest = this.cubelets[ 6 ]
  220. this.west = this.cubelets[ 3 ]
  221. this.northWest = this.cubelets[ 0 ]
  222. // Now that we know what the origin Cubelet is
  223. // we can determine if this is merely a Slice
  224. // or if it is also a Face.
  225. // If a face we'll know what direction it faces
  226. // and what the color of the face *should* be.
  227. for( var i = 0; i < 6; i ++ ){
  228. if( this.origin.faces[ i ].color && this.origin.faces[ i ].color !== COLORLESS ){
  229. this.color = this.origin.faces[ i ].color
  230. this.face = Direction.getNameById( i )
  231. break
  232. }
  233. }
  234. // Addressing orthagonal strips of Cubelets is more easily done by
  235. // cube notation for the X and Y axes.
  236. this.up = new Group(
  237. this.northWest, this.north, this.northEast
  238. )
  239. this.equator = new Group(
  240. this.west, this.origin, this.east
  241. )
  242. this.down = new Group(
  243. this.southWest, this.south, this.southEast
  244. )
  245. this.left = new Group(
  246. this.northWest,
  247. this.west,
  248. this.southWest
  249. )
  250. this.middle = new Group(
  251. this.north,
  252. this.origin,
  253. this.south
  254. )
  255. this.right = new Group(
  256. this.northEast,
  257. this.east,
  258. this.southEast
  259. )
  260. // If our Slice has only one center piece
  261. // (ie. a Cubelet with only ONE single Sticker)
  262. // then it is a Face -- a special kind of Slice.
  263. var hasCenter = this.hasType( 'center' )
  264. if( hasCenter && hasCenter.cubelets.length === 1 ){
  265. this.center = this.hasType( 'center' )//.cubelets[ 0 ]
  266. this.corners = new Group( this.hasType( 'corner' ))
  267. this.cross = new Group( this.center, this.hasType( 'edge' ))
  268. this.ex = new Group( this.center, this.hasType( 'corner' ))
  269. }
  270. // Otherwise our Slice will have multiple center pieces
  271. // (again, that means Cubelets with only ONE single Sticker)
  272. // and this is why a Slice's "origin" is NOT the same as
  273. // its "center" or "centers!"
  274. else {
  275. this.centers = new Group( this.hasType( 'center' ))
  276. }
  277. this.edges = new Group( this.hasType( 'edge' ))
  278. // I'm still debating whether this should be Sticker-related
  279. // or if it's merely a fun grouping.
  280. // Writing the solver should clarify this further...
  281. this.ring = new Group(
  282. this.northWest, this.north, this.northEast,
  283. this.west, this.east,
  284. this.southWest, this.south, this.southEast
  285. )
  286. // And finally for the hell of it let's try diagonals via
  287. // Blazon notation:
  288. this.dexter = new Group(// From top-left to bottom-right.
  289. this.northWest,
  290. this.origin,
  291. this.southEast
  292. )
  293. this.sinister = new Group(// From top-right to bottom-left.
  294. this.northEast,
  295. this.origin,
  296. this.southWest
  297. )
  298. },
  299. // Given a Cubelet in this Slice,
  300. // what is its compass location?
  301. getLocation: function( cubelet ){
  302. if( cubelet === this.origin ) return 'origin'
  303. if( cubelet === this.north ) return 'north'
  304. if( cubelet === this.northEast ) return 'northEast'
  305. if( cubelet === this.east ) return 'east'
  306. if( cubelet === this.southEast ) return 'southEast'
  307. if( cubelet === this.south ) return 'south'
  308. if( cubelet === this.southWest ) return 'southWest'
  309. if( cubelet === this.west ) return 'west'
  310. if( cubelet === this.northWest ) return 'northWest'
  311. return false
  312. }
  313. })
  314. // We want Slice to learn from Group
  315. // but we don't want their prototypes to actually be linked.
  316. // Hence we use Skip.js's learn function:
  317. learn( Slice.prototype, Group.prototype )
  318. })