/* SLICES Slices are thin layers sliced out of the Cube composed of 9 Cubelets (3x3 grid). The position of these Cubelets can be mapped as follows: ----------- ----------- ----------- | | | | | northWest | north | northEast | | 0 | 1 | 2 | | | | | ----------- ----------- ----------- | | | | | west | origin | east | | 3 | 4 | 5 | | | | | ----------- ----------- ----------- | | | | | southWest | south | southEast | | 6 | 7 | 8 | | | | | ----------- ----------- ----------- The cubelets[] Array is mapped to names for convenience: this.cubelets[ 0 ] === this.northWest this.cubelets[ 1 ] === this.north this.cubelets[ 2 ] === this.northEast this.cubelets[ 3 ] === this.west this.cubelets[ 4 ] === this.origin this.cubelets[ 5 ] === this.east this.cubelets[ 6 ] === this.southWest this.cubelets[ 7 ] === this.south this.cubelets[ 8 ] === this.southEast Portions of Slices can be Grouped: Rows and columns as strips (1x3) this.up this.equator this.down this.left this.middle this.right Other combinations this.cross this.edges this.ex this.corners this.ring this.dexter this.sinister A Slice may be inspected from the browser's JavaScript console with: this.inspect() This will reveal the Slice's Cubelets, their Indexes, and colors. A compact inspection mode is also available: this.inspect( true ) This is most useful for Slices that are also Faces. For Slices that are not Faces, or for special cases, it may be useful to send a side argument which is usually by default the Slice's origin's only visible side if it has one. this.inspect( false, 'up' ) this.inspect( true, 'up' ) CUBE FACES vs CUBE SLICES All Cube faces are Slices, but not all Slices are Cube faces. For example, a Cube has 6 faces: front, up, right, down, left, back. But it also has slices that that cut through the center of the Cube itself: equator, middle, and standing. When a Slice maps itself it inspects the faces of the Cubelet in the origin position of the Slice -- the center piece -- which can either have a single visible face or no visible face. If it has a visible face then the Slice's face and the face's direction is in the direction of that Cubelet's visible face. This seems redundant from the Cube's perspective: cube.front.face === 'front' However it becomes valuable from inside a Slice or Fold when a relationship to the Cube's orientation is not immediately clear: if( this.face === 'front' )... Therefore a Slice (s) is also a face if s.face !== undefined. */ export function Slice(){ this.cubelets = Array.prototype.slice.call( arguments ) this.map() } globalThis.setupTasks = globalThis.setupTasks || [] globalThis.setupTasks.push( function(){ augment( Slice, { inspect: function( compact, side ){ var getColorName = function( cubelet ){ return cubelet[ side ].color.name.toUpperCase().justifyCenter( 9 ) }, sideLabel = '' if( side === undefined ){ if( this.face !== undefined ) side = this.face else side = 'front' } if( side instanceof Direction ) side = side.name if( side !== this.face ) sideLabel = side + 's' if( compact ){ console.log( '\n' + this.name.capitalize().justifyLeft( 10 ) + '%c '+ this.northWest.id.toPaddedString( 2 ) +' %c '+ '%c '+ this.north.id.toPaddedString( 2 ) +' %c '+ '%c '+ this.northEast.id.toPaddedString( 2 ) +' %c '+ '\n' + sideLabel +'\n'+ ' %c '+ this.west.id.toPaddedString( 2 ) +' %c '+ '%c '+ this.origin.id.toPaddedString( 2 ) +' %c '+ '%c '+ this.east.id.toPaddedString( 2 ) +' %c '+ '\n\n'+ ' %c '+ this.southWest.id.toPaddedString( 2 ) +' %c '+ '%c '+ this.south.id.toPaddedString( 2 ) +' %c '+ '%c '+ this.southEast.id.toPaddedString( 2 ) +' %c '+ '\n', this.northWest[ side ].color.styleB, '', this.north[ side ].color.styleB, '', this.northEast[ side ].color.styleB, '', this.west[ side ].color.styleB, '', this.origin[ side ].color.styleB, '', this.east[ side ].color.styleB, '', this.southWest[ side ].color.styleB, '', this.south[ side ].color.styleB, '', this.southEast[ side ].color.styleB, '' ) } else { console.log( '\n %c %c %c %c %c %c '+ '\n'+ this.name.capitalize().justifyLeft( 10 ) + '%c northWest %c '+ '%c north %c '+ '%c northEast %c '+ '\n' + sideLabel.justifyLeft( 10 ) + '%c '+ this.northWest.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '%c '+ this.north.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '%c '+ this.northEast.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '\n' + ' %c ' + getColorName( this.northWest ) +' %c '+ '%c '+ getColorName( this.north ) +' %c '+ '%c '+ getColorName( this.northEast ) +' %c '+ '\n %c %c %c %c %c %c '+ '\n\n %c %c %c %c %c %c '+ '\n %c west %c '+ '%c origin %c '+ '%c east %c '+ '\n' + ' %c ' + this.west.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '%c '+ this.origin.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '%c '+ this.east.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '\n' + ' %c ' + getColorName( this.west ) +' %c '+ '%c '+ getColorName( this.origin ) +' %c '+ '%c '+ getColorName( this.east ) +' %c '+ '\n %c %c %c %c %c %c '+ '\n\n %c %c %c %c %c %c '+ '\n %c southWest %c '+ '%c south %c '+ '%c southEast %c '+ '\n' + ' %c ' + this.southWest.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '%c '+ this.south.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '%c '+ this.southEast.id.toPaddedString( 2 ).justifyCenter( 9 ) +' %c '+ '\n' + ' %c ' + getColorName( this.southWest ) +' %c '+ '%c '+ getColorName( this.south ) +' %c '+ '%c '+ getColorName( this.southEast ) +' %c '+ '\n %c %c %c %c %c %c\n', this.northWest[ side ].color.styleB, '', this.north[ side ].color.styleB, '', this.northEast[ side ].color.styleB, '', this.northWest[ side ].color.styleB, '', this.north[ side ].color.styleB, '', this.northEast[ side ].color.styleB, '', this.northWest[ side ].color.styleB, '', this.north[ side ].color.styleB, '', this.northEast[ side ].color.styleB, '', this.northWest[ side ].color.styleB, '', this.north[ side ].color.styleB, '', this.northEast[ side ].color.styleB, '', this.northWest[ side ].color.styleB, '', this.north[ side ].color.styleB, '', this.northEast[ side ].color.styleB, '', this.west[ side ].color.styleB, '', this.origin[ side ].color.styleB, '', this.east[ side ].color.styleB, '', this.west[ side ].color.styleB, '', this.origin[ side ].color.styleB, '', this.east[ side ].color.styleB, '', this.west[ side ].color.styleB, '', this.origin[ side ].color.styleB, '', this.east[ side ].color.styleB, '', this.west[ side ].color.styleB, '', this.origin[ side ].color.styleB, '', this.east[ side ].color.styleB, '', this.west[ side ].color.styleB, '', this.origin[ side ].color.styleB, '', this.east[ side ].color.styleB, '', this.southWest[ side ].color.styleB, '', this.south[ side ].color.styleB, '', this.southEast[ side ].color.styleB, '', this.southWest[ side ].color.styleB, '', this.south[ side ].color.styleB, '', this.southEast[ side ].color.styleB, '', this.southWest[ side ].color.styleB, '', this.south[ side ].color.styleB, '', this.southEast[ side ].color.styleB, '', this.southWest[ side ].color.styleB, '', this.south[ side ].color.styleB, '', this.southEast[ side ].color.styleB, '', this.southWest[ side ].color.styleB, '', this.south[ side ].color.styleB, '', this.southEast[ side ].color.styleB, '' ) } }, map: function(){ // Addressing single Cubelets can best be done by // compass notation. this.origin = this.cubelets[ 4 ] this.north = this.cubelets[ 1 ] this.northEast = this.cubelets[ 2 ] this.east = this.cubelets[ 5 ] this.southEast = this.cubelets[ 8 ] this.south = this.cubelets[ 7 ] this.southWest = this.cubelets[ 6 ] this.west = this.cubelets[ 3 ] this.northWest = this.cubelets[ 0 ] // Now that we know what the origin Cubelet is // we can determine if this is merely a Slice // or if it is also a Face. // If a face we'll know what direction it faces // and what the color of the face *should* be. for( var i = 0; i < 6; i ++ ){ if( this.origin.faces[ i ].color && this.origin.faces[ i ].color !== COLORLESS ){ this.color = this.origin.faces[ i ].color this.face = Direction.getNameById( i ) break } } // Addressing orthagonal strips of Cubelets is more easily done by // cube notation for the X and Y axes. this.up = new Group( this.northWest, this.north, this.northEast ) this.equator = new Group( this.west, this.origin, this.east ) this.down = new Group( this.southWest, this.south, this.southEast ) this.left = new Group( this.northWest, this.west, this.southWest ) this.middle = new Group( this.north, this.origin, this.south ) this.right = new Group( this.northEast, this.east, this.southEast ) // If our Slice has only one center piece // (ie. a Cubelet with only ONE single Sticker) // then it is a Face -- a special kind of Slice. var hasCenter = this.hasType( 'center' ) if( hasCenter && hasCenter.cubelets.length === 1 ){ this.center = this.hasType( 'center' )//.cubelets[ 0 ] this.corners = new Group( this.hasType( 'corner' )) this.cross = new Group( this.center, this.hasType( 'edge' )) this.ex = new Group( this.center, this.hasType( 'corner' )) } // Otherwise our Slice will have multiple center pieces // (again, that means Cubelets with only ONE single Sticker) // and this is why a Slice's "origin" is NOT the same as // its "center" or "centers!" else { this.centers = new Group( this.hasType( 'center' )) } this.edges = new Group( this.hasType( 'edge' )) // I'm still debating whether this should be Sticker-related // or if it's merely a fun grouping. // Writing the solver should clarify this further... this.ring = new Group( this.northWest, this.north, this.northEast, this.west, this.east, this.southWest, this.south, this.southEast ) // And finally for the hell of it let's try diagonals via // Blazon notation: this.dexter = new Group(// From top-left to bottom-right. this.northWest, this.origin, this.southEast ) this.sinister = new Group(// From top-right to bottom-left. this.northEast, this.origin, this.southWest ) }, // Given a Cubelet in this Slice, // what is its compass location? getLocation: function( cubelet ){ if( cubelet === this.origin ) return 'origin' if( cubelet === this.north ) return 'north' if( cubelet === this.northEast ) return 'northEast' if( cubelet === this.east ) return 'east' if( cubelet === this.southEast ) return 'southEast' if( cubelet === this.south ) return 'south' if( cubelet === this.southWest ) return 'southWest' if( cubelet === this.west ) return 'west' if( cubelet === this.northWest ) return 'northWest' return false } }) // We want Slice to learn from Group // but we don't want their prototypes to actually be linked. // Hence we use Skip.js's learn function: learn( Slice.prototype, Group.prototype ) })