Project

General

Profile

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

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

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()
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 getNumCentersPerFace(int layers)
146
    {
147
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1));
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();
222
    final int numEdges   = getNumEdges(numLayers);
223
    final int numCenters = 6*getNumCentersPerFace(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 numLayers)
344
    {
345
    int numCorners = getNumCorners();
346
    int numEdges   = getNumEdges(numLayers);
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)/(numLayers-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)/getNumCentersPerFace(numLayers);
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();
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 numLayers)
442
    {
443
    int numCorners = getNumCorners();
444
    int numEdges   = getNumEdges(numLayers);
445

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

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

    
464
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
465
    {
466
    int COLORS = FACE_COLORS.length;
467
    float R,S;
468
    float[] vertices;
469

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

    
492
    FactorySticker factory = FactorySticker.getInstance();
493
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%COLORS], R);
494
    }
495

    
496
///////////////////////////////////////////////////////////////////////////////////////////////////
497

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

    
503
///////////////////////////////////////////////////////////////////////////////////////////////////
504

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

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

    
515
    return chances;
516
    }
517

    
518
///////////////////////////////////////////////////////////////////////////////////////////////////
519
// PUBLIC API
520

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

    
526
///////////////////////////////////////////////////////////////////////////////////////////////////
527

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

    
533
///////////////////////////////////////////////////////////////////////////////////////////////////
534

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

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

    
550
///////////////////////////////////////////////////////////////////////////////////////////////////
551

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

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

    
561
    return 0;
562
    }
563

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

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

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

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

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

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

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

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

    
602
    return -1;
603
    }
604

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

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

    
621
    int numLayers      = getNumLayers();
622
    int numCorners     = getNumCorners();
623
    int numEdges       = getNumEdges(numLayers);
624
    int cornersAndEdges= numCorners + numEdges;
625
    int centersPerFace = getNumCentersPerFace(numLayers);
626
    int cubit, q1=q;
627

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

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

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

    
644
    return true;
645
    }
646

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

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