Project

General

Profile

Download (20.5 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / objects / TwistySkewb.java @ c7e23561

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2020 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objects;
21

    
22
import android.content.res.Resources;
23
import android.graphics.Canvas;
24
import android.graphics.Paint;
25

    
26
import org.distorted.library.effect.MatrixEffect;
27
import org.distorted.library.effect.MatrixEffectQuaternion;
28
import org.distorted.library.effect.MatrixEffectScale;
29
import org.distorted.library.main.DistortedEffects;
30
import org.distorted.library.main.DistortedTexture;
31
import org.distorted.library.mesh.MeshBase;
32
import org.distorted.library.mesh.MeshSquare;
33
import org.distorted.library.type.Static3D;
34
import org.distorted.library.type.Static4D;
35
import org.distorted.main.RubikSurfaceView;
36

    
37
import java.util.Random;
38

    
39
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
40

    
41
///////////////////////////////////////////////////////////////////////////////////////////////////
42

    
43
public class TwistySkewb extends TwistyObject
44
{
45
  private static final int FACES_PER_CUBIT =6;
46

    
47
  // the four rotation axis of a RubikSkewb. Must be normalized.
48
  static final Static3D[] ROT_AXIS = new Static3D[]
49
         {
50
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
51
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
52
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
53
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
54
         };
55

    
56
  private static final int[] FACE_COLORS = new int[]
57
         {
58
           COLOR_YELLOW, COLOR_WHITE,
59
           COLOR_BLUE  , COLOR_GREEN,
60
           COLOR_RED   , COLOR_BROWN
61
         };
62

    
63
  // All legal rotation quats of a RubikSkewb
64
  private static final Static4D[] QUATS = new Static4D[]
65
         {
66
           new Static4D(  0.0f,  0.0f,  0.0f,  1.0f ),
67
           new Static4D(  1.0f,  0.0f,  0.0f,  0.0f ),
68
           new Static4D(  0.0f,  1.0f,  0.0f,  0.0f ),
69
           new Static4D(  0.0f,  0.0f,  1.0f,  0.0f ),
70

    
71
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
72
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
73
           new Static4D(  0.5f,  0.5f, -0.5f,  0.5f ),
74
           new Static4D(  0.5f,  0.5f, -0.5f, -0.5f ),
75
           new Static4D(  0.5f, -0.5f,  0.5f,  0.5f ),
76
           new Static4D(  0.5f, -0.5f,  0.5f, -0.5f ),
77
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
78
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
79
         };
80

    
81
  private static final int[][] mCornerMap =
82
         {
83
           {  4, 2, 0, 18,18,18 },
84
           {  2, 5, 0, 18,18,18 },
85
           {  3, 4, 0, 18,18,18 },
86
           {  5, 3, 0, 18,18,18 },
87
           {  1, 2, 4, 18,18,18 },
88
           {  5, 2, 1, 18,18,18 },
89
           {  4, 3, 1, 18,18,18 },
90
           {  1, 3, 5, 18,18,18 },
91
         };
92

    
93
  private static final int[][] mEdgeMap =
94
         {
95
           { 10, 8, 18,18,18,18 },
96
           {  6,10, 18,18,18,18 },
97
           { 10, 9, 18,18,18,18 },
98
           {  7,10, 18,18,18,18 },
99
           {  8, 6, 18,18,18,18 },
100
           {  9, 6, 18,18,18,18 },
101
           {  9, 7, 18,18,18,18 },
102
           {  8, 7, 18,18,18,18 },
103
           { 11, 8, 18,18,18,18 },
104
           {  6,11, 18,18,18,18 },
105
           { 11, 9, 18,18,18,18 },
106
           {  7,11, 18,18,18,18 }
107
         };
108

    
109
  private static final int[][] mCenterMap =
110
         {
111
           { 12, 18,18,18,18,18 },
112
           { 13, 18,18,18,18,18 },
113
           { 14, 18,18,18,18,18 },
114
           { 15, 18,18,18,18,18 },
115
           { 16, 18,18,18,18,18 },
116
           { 17, 18,18,18,18,18 },
117
         };
118

    
119
  private static MeshBase mCornerMesh, mFaceMesh, mEdgeMesh;
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
  TwistySkewb(int size, Static4D quat, DistortedTexture texture,
124
              MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
125
    {
126
    super(size, 2*size-2, 60, quat, texture, mesh, effects, moves, ObjectList.SKEW, res, scrWidth);
127
    }
128

    
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

    
131
  private int getNumCorners(int layers)
132
    {
133
    return 8;
134
    }
135

    
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137

    
138
  private int getNumEdges(int layers)
139
    {
140
    return (layers-2)*12;
141
    }
142

    
143
///////////////////////////////////////////////////////////////////////////////////////////////////
144

    
145
  private int getNumCenters(int layers)
146
    {
147
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1))*6;
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  float getScreenRatio()
153
    {
154
    return 1.0f;
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  Static4D[] getQuats()
160
    {
161
    return QUATS;
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  int getNumFaces()
167
    {
168
    return FACE_COLORS.length;
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172

    
173
  boolean shouldResetTextureMaps()
174
    {
175
    return false;
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  int getNumStickerTypes()
181
    {
182
    return 3;
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  float[] getCuts(int numLayers)
188
    {
189
    float[] cuts = new float[numLayers-1];
190

    
191
    switch(numLayers)
192
      {
193
      case 2: cuts[0] = 0;
194
              break;
195
      case 3: cuts[0] = -SQ3/12;
196
              cuts[1] = +SQ3/12;
197
              break;
198
      case 4: cuts[0] = -SQ3/9;
199
              cuts[1] = 0;
200
              cuts[2] = +SQ3/9;
201
              break;
202
      }
203
    return cuts;
204
    }
205

    
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

    
208
  int getNumCubitFaces()
209
    {
210
    return FACES_PER_CUBIT;
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

    
215
  Static3D[] getCubitPositions(int numLayers)
216
    {
217
    final float DIST_CORNER = (numLayers-1)*0.50f;
218
    final float DIST_EDGE   = (numLayers-1)*0.50f;
219
    final float DIST_CENTER = (numLayers-1)*0.50f;
220

    
221
    final int numCorners = getNumCorners(numLayers);
222
    final int numEdges   = getNumEdges(numLayers);
223
    final int numCenters = getNumCenters(numLayers);
224

    
225
    final Static3D[] CENTERS = new Static3D[numCorners+numEdges+numCenters];
226

    
227
    /// CORNERS //////////////////////////////////////////////
228

    
229
    CENTERS[0] = new Static3D( DIST_CORNER, DIST_CORNER, DIST_CORNER );
230
    CENTERS[1] = new Static3D( DIST_CORNER, DIST_CORNER,-DIST_CORNER );
231
    CENTERS[2] = new Static3D( DIST_CORNER,-DIST_CORNER, DIST_CORNER );
232
    CENTERS[3] = new Static3D( DIST_CORNER,-DIST_CORNER,-DIST_CORNER );
233
    CENTERS[4] = new Static3D(-DIST_CORNER, DIST_CORNER, DIST_CORNER );
234
    CENTERS[5] = new Static3D(-DIST_CORNER, DIST_CORNER,-DIST_CORNER );
235
    CENTERS[6] = new Static3D(-DIST_CORNER,-DIST_CORNER, DIST_CORNER );
236
    CENTERS[7] = new Static3D(-DIST_CORNER,-DIST_CORNER,-DIST_CORNER );
237

    
238
    /// EDGES ///////////////////////////////////////////////
239

    
240
    final float[][]  edgeTable =
241
        {
242
            {0,+DIST_EDGE,+DIST_EDGE},
243
            {+DIST_EDGE,0,+DIST_EDGE},
244
            {0,-DIST_EDGE,+DIST_EDGE},
245
            {-DIST_EDGE,0,+DIST_EDGE},
246
            {+DIST_EDGE,+DIST_EDGE,0},
247
            {+DIST_EDGE,-DIST_EDGE,0},
248
            {-DIST_EDGE,-DIST_EDGE,0},
249
            {-DIST_EDGE,+DIST_EDGE,0},
250
            {0,+DIST_EDGE,-DIST_EDGE},
251
            {+DIST_EDGE,0,-DIST_EDGE},
252
            {0,-DIST_EDGE,-DIST_EDGE},
253
            {-DIST_EDGE,0,-DIST_EDGE}
254
        };
255

    
256
    int index=8;
257

    
258
    for (float[] edges : edgeTable)
259
      {
260
      float c = (3-numLayers)*0.5f;
261

    
262
      for (int j=0; j<numLayers-2; j++, c+=1.0f, index++)
263
        {
264
        CENTERS[index] = new Static3D( edges[0]==0 ? c : edges[0] ,
265
                                       edges[1]==0 ? c : edges[1] ,
266
                                       edges[2]==0 ? c : edges[2] );
267
        }
268
      }
269

    
270
    /// CENTERS //////////////////////////////////////////////
271

    
272
    final float X= -1000.0f;
273
    final float Y= -1001.0f;
274

    
275
    final float[][]  centerTable =
276
        {
277
            {+DIST_CENTER,X,Y},
278
            {-DIST_CENTER,X,Y},
279
            {X,+DIST_CENTER,Y},
280
            {X,-DIST_CENTER,Y},
281
            {X,Y,+DIST_CENTER},
282
            {X,Y,-DIST_CENTER}
283
        };
284

    
285
    float x,y, cen0, cen1, cen2;
286

    
287
    for( float[] centers : centerTable )
288
      {
289
      x = (2-numLayers)*0.5f;
290

    
291
      for(int i=0; i<numLayers-1; i++, x+=1.0f)
292
        {
293
        y = (2-numLayers)*0.5f;
294

    
295
        for(int j=0; j<numLayers-1; j++, y+=1.0f, index++)
296
          {
297
               if( centers[0]==Y ) cen0 = y;
298
          else if( centers[0]==X ) cen0 = x;
299
          else                     cen0 = centers[0];
300

    
301
               if( centers[1]==Y ) cen1 = y;
302
          else if( centers[1]==X ) cen1 = x;
303
          else                     cen1 = centers[1];
304

    
305
               if( centers[2]==Y ) cen2 = y;
306
          else if( centers[2]==X ) cen2 = x;
307
          else                     cen2 = centers[2];
308

    
309
          CENTERS[index] = new Static3D(cen0,cen1,cen2);
310
          }
311
        }
312

    
313
      x = (3-numLayers)*0.5f;
314

    
315
      for(int i=0; i<numLayers-2; i++, x+=1.0f)
316
        {
317
        y = (3-numLayers)*0.5f;
318

    
319
        for(int j=0; j<numLayers-2; j++, y+=1.0f, index++)
320
          {
321
               if( centers[0]==Y ) cen0 = y;
322
          else if( centers[0]==X ) cen0 = x;
323
          else                     cen0 = centers[0];
324

    
325
               if( centers[1]==Y ) cen1 = y;
326
          else if( centers[1]==X ) cen1 = x;
327
          else                     cen1 = centers[1];
328

    
329
               if( centers[2]==Y ) cen2 = y;
330
          else if( centers[2]==X ) cen2 = x;
331
          else                     cen2 = centers[2];
332

    
333
          CENTERS[index] = new Static3D(cen0,cen1,cen2);
334
          }
335
        }
336
      }
337

    
338
    return CENTERS;
339
    }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

    
343
  private Static4D getQuat(int cubit, int size)
344
    {
345
    int numCorners = getNumCorners(size);
346
    int numEdges   = getNumEdges(size);
347

    
348
    if( cubit<numCorners )
349
      {
350
      switch(cubit)
351
        {
352
        case  0: return QUATS[0];                          //  unit quat
353
        case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
354
        case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
355
        case  3: return QUATS[1];                          // 180 along X
356
        case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
357
        case  5: return QUATS[2];                          // 180 along Y
358
        case  6: return QUATS[3];                          // 180 along Z
359
        case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
360
        }
361
      }
362
    else if( cubit<numCorners+numEdges )
363
      {
364
      int edge = (cubit-numCorners)/(size-2);
365

    
366
      switch(edge)
367
        {
368
        case  0: return QUATS[ 0];
369
        case  1: return QUATS[ 5];
370
        case  2: return QUATS[ 3];
371
        case  3: return QUATS[11];
372
        case  4: return QUATS[ 4];
373
        case  5: return QUATS[ 7];
374
        case  6: return QUATS[ 9];
375
        case  7: return QUATS[10];
376
        case  8: return QUATS[ 2];
377
        case  9: return QUATS[ 8];
378
        case 10: return QUATS[ 1];
379
        case 11: return QUATS[ 6];
380
        }
381
      }
382
    else
383
      {
384
      int center = (cubit-numCorners-numEdges)/((size-2)*(size-2)+(size-1)*(size-1));
385

    
386
      switch(center)
387
        {
388
        case 0: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
389
        case 1: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
390
        case 2: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
391
        case 3: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
392
        case 4: return QUATS[0];                          //  unit quaternion
393
        case 5: return QUATS[1];                          // 180 along X
394
        }
395
      }
396

    
397
    return null;
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

    
402
  MeshBase createCubitMesh(int cubit)
403
    {
404
    MeshBase mesh;
405

    
406
    int numLayers = getNumLayers();
407
    int numCorners = getNumCorners(numLayers);
408
    int numEdges   = getNumEdges(numLayers);
409

    
410
    if( cubit<numCorners )
411
      {
412
      if( mCornerMesh==null ) mCornerMesh = FactoryCubit.getInstance().createSkewbCornerMesh();
413
      mesh = mCornerMesh.copy(true);
414
      }
415
    else if( cubit<numCorners+numEdges )
416
      {
417
      if( mEdgeMesh==null )
418
        {
419
        mEdgeMesh = FactoryCubit.getInstance().createDinoMesh();
420
        MatrixEffect effect = new MatrixEffectScale(1.0f/3);
421
        mEdgeMesh.apply(effect,-1,0);
422
        mEdgeMesh.addEmptyTexComponent();
423
        mEdgeMesh.addEmptyTexComponent();
424
        }
425
      mesh = mEdgeMesh.copy(true);
426
      }
427
    else
428
      {
429
      if( mFaceMesh==null ) mFaceMesh = FactoryCubit.getInstance().createSkewbFaceMesh();
430
      mesh = mFaceMesh.copy(true);
431
      }
432

    
433
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,numLayers), new Static3D(0,0,0) );
434
    mesh.apply(quat,0xffffffff,0);
435

    
436
    return mesh;
437
    }
438

    
439
///////////////////////////////////////////////////////////////////////////////////////////////////
440

    
441
  int getFaceColor(int cubit, int cubitface, int size)
442
    {
443
    int numCorners = getNumCorners(size);
444
    int numEdges   = getNumEdges(size);
445

    
446
    if( cubit<numCorners )
447
      {
448
      return mCornerMap[cubit][cubitface];
449
      }
450
    else if( cubit<numCorners+numEdges )
451
      {
452
      int edge = (cubit-numCorners)/(size-2);
453
      return mEdgeMap[edge][cubitface];
454
      }
455
    else
456
      {
457
      int center = (cubit-numCorners-numEdges)/((size-2)*(size-2)+(size-1)*(size-1));
458
      return mCenterMap[center][cubitface];
459
      }
460
    }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

    
464
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left)
465
    {
466
    int COLORS = FACE_COLORS.length;
467
    FactorySticker factory = FactorySticker.getInstance();
468

    
469
    if( face<COLORS )
470
      {
471
      float R = 0.023f;
472
      float S = 0.035f;
473
      float E = 0.5f;
474
      float[] vertices = { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
475
      factory.drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face], R);
476
      }
477
    else if( face<2*COLORS )
478
      {
479
      float F = 0.5f;
480
      float R = 0.025f;
481
      float S = 0.05f;
482
      float[] vertices = { -F,F/3, 0,-2*F/3, +F,F/3 };
483
      factory.drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face-COLORS], R);
484
      }
485
    else
486
      {
487
      float R = 0.055f;
488
      float S = 0.035f;
489
      float E = SQ2/4;
490
      float[] vertices = { -E,-E, +E,-E, +E,+E, -E,+E };
491
      factory.drawRoundedPolygon(canvas, paint, left, vertices, S, FACE_COLORS[face-2*COLORS], R);
492
      }
493
    }
494

    
495
///////////////////////////////////////////////////////////////////////////////////////////////////
496

    
497
  float returnMultiplier()
498
    {
499
    return 2.0f;
500
    }
501

    
502
///////////////////////////////////////////////////////////////////////////////////////////////////
503

    
504
  float[] getRowChances()
505
    {
506
    int numLayers = getNumLayers();
507
    float[] chances = new float[numLayers];
508

    
509
    for(int i=0; i<numLayers; i++)
510
      {
511
      chances[i] = (float)(i+1)/numLayers;
512
      }
513

    
514
    return chances;
515
    }
516

    
517
///////////////////////////////////////////////////////////////////////////////////////////////////
518
// PUBLIC API
519

    
520
  public Static3D[] getRotationAxis()
521
    {
522
    return ROT_AXIS;
523
    }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526

    
527
  public int getBasicAngle()
528
    {
529
    return 3;
530
    }
531

    
532
///////////////////////////////////////////////////////////////////////////////////////////////////
533

    
534
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
535
    {
536
    int numAxis = ROTATION_AXIS.length;
537

    
538
    if( oldRotAxis == START_AXIS )
539
      {
540
      return rnd.nextInt(numAxis);
541
      }
542
    else
543
      {
544
      int newVector = rnd.nextInt(numAxis-1);
545
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
546
      }
547
    }
548

    
549
///////////////////////////////////////////////////////////////////////////////////////////////////
550

    
551
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
552
    {
553
    float rowFloat = rnd.nextFloat();
554

    
555
    for(int row=0; row<mRowChances.length; row++)
556
      {
557
      if( rowFloat<=mRowChances[row] ) return row;
558
      }
559

    
560
    return 0;
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564
// remember about the double cover or unit quaternions!
565

    
566
  private int mulQuat(int q1, int q2)
567
    {
568
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
569

    
570
    float rX = result.get0();
571
    float rY = result.get1();
572
    float rZ = result.get2();
573
    float rW = result.get3();
574

    
575
    final float MAX_ERROR = 0.1f;
576
    float dX,dY,dZ,dW;
577

    
578
    for(int i=0; i<QUATS.length; i++)
579
      {
580
      dX = QUATS[i].get0() - rX;
581
      dY = QUATS[i].get1() - rY;
582
      dZ = QUATS[i].get2() - rZ;
583
      dW = QUATS[i].get3() - rW;
584

    
585
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
586
          dY<MAX_ERROR && dY>-MAX_ERROR &&
587
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
588
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
589

    
590
      dX = QUATS[i].get0() + rX;
591
      dY = QUATS[i].get1() + rY;
592
      dZ = QUATS[i].get2() + rZ;
593
      dW = QUATS[i].get3() + rW;
594

    
595
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
596
          dY<MAX_ERROR && dY>-MAX_ERROR &&
597
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
598
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
599
      }
600

    
601
    return -1;
602
    }
603

    
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605
// The Skewb is solved if and only if:
606
//
607
// 1) all of its corner and edge cubits are rotated with the same quat
608
// 2) all its face cubits are rotated with the same quat like the corner ones,
609
//    and optionally they also might be upside down.
610
//
611
// i.e.
612
// cubits [ 8] and [ 9] - might be extra QUAT[1]
613
// cubits [10] and [11] - might be extra QUAT[2]
614
// cubits [12] and [13] - might be extra QUAT[3]
615

    
616
  public boolean isSolved()
617
    {
618
    int q = CUBITS[0].mQuatIndex;
619

    
620
    int numLayers  = getNumLayers();
621
    int numCorners = getNumCorners(numLayers);
622
    int numEdges   = getNumEdges(numLayers);
623
    int cornersAndEdges = numCorners + numEdges;
624
    int cubitsPerFace = (numLayers-2)*(numLayers-2) + (numLayers-1)*(numLayers-1);
625
    int cubit, q1=q;
626

    
627
    for(cubit=0; cubit<cornersAndEdges; cubit++)
628
      {
629
      if( CUBITS[cubit].mQuatIndex != q ) return false;
630
      }
631

    
632
    for(int face=0; face<6; face++)
633
      {
634
      if( face%2==0 ) q1 = mulQuat(q, (face/2)+1);
635

    
636
      for(int center=0; center<cubitsPerFace; center++)
637
        {
638
        if( CUBITS[cubit].mQuatIndex != q && CUBITS[cubit].mQuatIndex != q1 ) return false;
639
        cubit++;
640
        }
641
      }
642

    
643
    return true;
644
    }
645

    
646
///////////////////////////////////////////////////////////////////////////////////////////////////
647
// only needed for solvers - there are no Skewb solvers ATM)
648

    
649
  public String retObjectString()
650
    {
651
    return "";
652
    }
653
}
(22-22/22)