Project

General

Profile

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

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

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.R;
36
import org.distorted.main.RubikSurfaceView;
37

    
38
import java.util.Random;
39

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

    
42
///////////////////////////////////////////////////////////////////////////////////////////////////
43

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

    
48
  // the four rotation axis of a RubikSkewb. Must be normalized.
49
  static final Static3D[] ROT_AXIS = new Static3D[]
50
         {
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
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
55
         };
56

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

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

    
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
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
80
         };
81

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

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

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

    
120
  private static MeshBase mCornerMesh, mFaceMesh, mEdgeMesh;
121

    
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

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

    
130
///////////////////////////////////////////////////////////////////////////////////////////////////
131

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

    
137
///////////////////////////////////////////////////////////////////////////////////////////////////
138

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

    
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

    
146
  private int getNumCentersPerFace(int layers)
147
    {
148
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1));
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152

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

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

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

    
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166

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

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

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

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

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

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

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

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

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

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

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

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

    
222
    final int numCorners = getNumCorners();
223
    final int numEdges   = getNumEdges(numLayers);
224
    final int numCenters = 6*getNumCentersPerFace(numLayers);
225

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

    
228
    /// CORNERS //////////////////////////////////////////////
229

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

    
239
    /// EDGES ///////////////////////////////////////////////
240

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

    
257
    int index=8;
258

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

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

    
271
    /// CENTERS //////////////////////////////////////////////
272

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
339
    return CENTERS;
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

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

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

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

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

    
398
    return null;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  MeshBase createCubitMesh(int cubit, int numLayers)
404
    {
405
    MeshBase mesh;
406

    
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(int numLayers)
506
    {
507
    float[] chances = new float[numLayers];
508

    
509
    switch(numLayers)
510
      {
511
      case 2: chances[0] = 0.5f;
512
              chances[1] = 1.0f;
513
              break;
514
      case 3: chances[0] = 0.5f;
515
              chances[1] = 0.5f;
516
              chances[2] = 1.0f;
517
              break;
518
      default:for(int i=0; i<numLayers; i++)
519
                {
520
                chances[i] = (float)(i+1)/numLayers;
521
                }
522
      }
523

    
524
    return chances;
525
    }
526

    
527
///////////////////////////////////////////////////////////////////////////////////////////////////
528
// PUBLIC API
529

    
530
  public Static3D[] getRotationAxis()
531
    {
532
    return ROT_AXIS;
533
    }
534

    
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536

    
537
  public int getBasicAngle()
538
    {
539
    return 3;
540
    }
541

    
542
///////////////////////////////////////////////////////////////////////////////////////////////////
543

    
544
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
545
    {
546
    int numAxis = ROTATION_AXIS.length;
547

    
548
    if( oldRotAxis == START_AXIS )
549
      {
550
      return rnd.nextInt(numAxis);
551
      }
552
    else
553
      {
554
      int newVector = rnd.nextInt(numAxis-1);
555
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
556
      }
557
    }
558

    
559
///////////////////////////////////////////////////////////////////////////////////////////////////
560

    
561
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
562
    {
563
    float rowFloat = rnd.nextFloat();
564

    
565
    for(int row=0; row<mRowChances.length; row++)
566
      {
567
      if( rowFloat<=mRowChances[row] ) return row;
568
      }
569

    
570
    return 0;
571
    }
572

    
573
///////////////////////////////////////////////////////////////////////////////////////////////////
574
// remember about the double cover or unit quaternions!
575

    
576
  private int mulQuat(int q1, int q2)
577
    {
578
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
579

    
580
    float rX = result.get0();
581
    float rY = result.get1();
582
    float rZ = result.get2();
583
    float rW = result.get3();
584

    
585
    final float MAX_ERROR = 0.1f;
586
    float dX,dY,dZ,dW;
587

    
588
    for(int i=0; i<QUATS.length; 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
      dX = QUATS[i].get0() + rX;
601
      dY = QUATS[i].get1() + rY;
602
      dZ = QUATS[i].get2() + rZ;
603
      dW = QUATS[i].get3() + rW;
604

    
605
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
606
          dY<MAX_ERROR && dY>-MAX_ERROR &&
607
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
608
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
609
      }
610

    
611
    return -1;
612
    }
613

    
614
///////////////////////////////////////////////////////////////////////////////////////////////////
615
// The Skewb is solved if and only if:
616
//
617
// 1) all of its corner and edge cubits are rotated with the same quat
618
// 2) all its face cubits are rotated with the same quat like the corner ones,
619
//    and optionally they also might be upside down.
620
//
621
// i.e.
622
// cubits [ 8] and [ 9] - might be extra QUAT[1]
623
// cubits [10] and [11] - might be extra QUAT[2]
624
// cubits [12] and [13] - might be extra QUAT[3]
625

    
626
  public boolean isSolved()
627
    {
628
    int q = CUBITS[0].mQuatIndex;
629

    
630
    int numLayers      = getNumLayers();
631
    int numCorners     = getNumCorners();
632
    int numEdges       = getNumEdges(numLayers);
633
    int cornersAndEdges= numCorners + numEdges;
634
    int centersPerFace = getNumCentersPerFace(numLayers);
635
    int cubit, q1=q;
636

    
637
    for(cubit=0; cubit<cornersAndEdges; cubit++)
638
      {
639
      if( CUBITS[cubit].mQuatIndex != q ) return false;
640
      }
641

    
642
    for(int face=0; face<6; face++)
643
      {
644
      if( face%2==0 ) q1 = mulQuat(q, (face/2)+1);
645

    
646
      for(int center=0; center<centersPerFace; center++)
647
        {
648
        if( CUBITS[cubit].mQuatIndex != q && CUBITS[cubit].mQuatIndex != q1 ) return false;
649
        cubit++;
650
        }
651
      }
652

    
653
    return true;
654
    }
655

    
656
///////////////////////////////////////////////////////////////////////////////////////////////////
657
// only needed for solvers - there are no Skewb solvers ATM)
658

    
659
  public String retObjectString()
660
    {
661
    return "";
662
    }
663

    
664
///////////////////////////////////////////////////////////////////////////////////////////////////
665

    
666
  public int getObjectName(int numLayers)
667
    {
668
    switch(numLayers)
669
      {
670
      case 2: return R.string.skew2;
671
      case 3: return R.string.skew3;
672
      }
673
    return R.string.skew2;
674
    }
675

    
676
///////////////////////////////////////////////////////////////////////////////////////////////////
677

    
678
  public int getInventor(int numLayers)
679
    {
680
    switch(numLayers)
681
      {
682
      case 2: return R.string.skew2_inventor;
683
      case 3: return R.string.skew3_inventor;
684
      }
685
    return R.string.skew2_inventor;
686
    }
687

    
688
///////////////////////////////////////////////////////////////////////////////////////////////////
689

    
690
  public int getComplexity(int numLayers)
691
    {
692
    switch(numLayers)
693
      {
694
      case 2: return 5;
695
      case 3: return 9;
696
      }
697
    return 5;
698
    }
699
}
(30-30/30)