Project

General

Profile

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

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

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
///////////////////////////////////////////////////////////////////////////////////////////////////
41

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

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

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

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

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

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

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

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

    
118
  private static MeshBase mCornerMesh, mFaceMesh, mEdgeMesh;
119

    
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121

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

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129

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

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

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

    
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

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

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

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

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

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

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

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

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

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

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

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

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

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

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

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

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

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

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

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

    
224
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
225

    
226
    /// CORNERS //////////////////////////////////////////////
227

    
228
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
229
    CENTERS[1] = new float[] { DIST_CORNER, DIST_CORNER,-DIST_CORNER };
230
    CENTERS[2] = new float[] { DIST_CORNER,-DIST_CORNER, DIST_CORNER };
231
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
232
    CENTERS[4] = new float[] {-DIST_CORNER, DIST_CORNER, DIST_CORNER };
233
    CENTERS[5] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
234
    CENTERS[6] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
235
    CENTERS[7] = new float[] {-DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
236

    
237
    /// EDGES ///////////////////////////////////////////////
238

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

    
255
    int index=8;
256

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

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

    
269
    /// CENTERS //////////////////////////////////////////////
270

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

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

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

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

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

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

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

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

    
308
          CENTERS[index] = new float[] {cen0,cen1,cen2};
309
          }
310
        }
311

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

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

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

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

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

    
332
          CENTERS[index] = new float[] {cen0,cen1,cen2};
333
          }
334
        }
335
      }
336

    
337
    return CENTERS;
338
    }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

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

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

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

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

    
396
    return null;
397
    }
398

    
399
///////////////////////////////////////////////////////////////////////////////////////////////////
400

    
401
  MeshBase createCubitMesh(int cubit, int numLayers)
402
    {
403
    MeshBase mesh;
404

    
405
    int numCorners = getNumCorners();
406
    int numEdges   = getNumEdges(numLayers);
407

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

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

    
434
    return mesh;
435
    }
436

    
437
///////////////////////////////////////////////////////////////////////////////////////////////////
438

    
439
  int getFaceColor(int cubit, int cubitface, int numLayers)
440
    {
441
    int numCorners = getNumCorners();
442
    int numEdges   = getNumEdges(numLayers);
443

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

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

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

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

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

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495

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

    
501
///////////////////////////////////////////////////////////////////////////////////////////////////
502

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

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

    
522
    return chances;
523
    }
524

    
525
///////////////////////////////////////////////////////////////////////////////////////////////////
526
// PUBLIC API
527

    
528
  public Static3D[] getRotationAxis()
529
    {
530
    return ROT_AXIS;
531
    }
532

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

    
535
  public int getBasicAngle()
536
    {
537
    return 3;
538
    }
539

    
540
///////////////////////////////////////////////////////////////////////////////////////////////////
541

    
542
  public void randomizeNewScramble(int[] scramble, Random rnd, int oldRotAxis, int oldRow,
543
                                   int numScramble, int remScrambles, int remDoubleScrambles)
544
    {
545
    if( numScramble==1 )
546
      {
547
      scramble[0] = rnd.nextInt(ROTATION_AXIS.length);
548
      }
549
    else
550
      {
551
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
552
      scramble[0] = (newVector>=oldRotAxis ? newVector+1 : newVector);
553
      }
554

    
555
    float rowFloat = rnd.nextFloat();
556

    
557
    for(int row=0; row<mRowChances.length; row++)
558
      {
559
      if( rowFloat<=mRowChances[row] )
560
        {
561
        scramble[1] = row;
562
        break;
563
        }
564
      }
565

    
566
    int random = rnd.nextInt(remScrambles);
567
    int result = random<remDoubleScrambles ? 2:1;
568
    int sign   = rnd.nextInt(2);
569

    
570
    scramble[2] = sign==0 ? result : -result;
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
}
(35-35/35)