Project

General

Profile

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

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

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 num)
543
    {
544
    if( num==0 )
545
      {
546
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
547
      }
548
    else
549
      {
550
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
551
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
552
      }
553

    
554
    float rowFloat = rnd.nextFloat();
555

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

    
565
    switch( rnd.nextInt(2) )
566
      {
567
      case 0: scramble[num][2] = -1; break;
568
      case 1: scramble[num][2] =  1; break;
569
      }
570
    }
571

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

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

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

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

    
587
    for(int i=0; i<QUATS.length; i++)
588
      {
589
      dX = QUATS[i].get0() - rX;
590
      dY = QUATS[i].get1() - rY;
591
      dZ = QUATS[i].get2() - rZ;
592
      dW = QUATS[i].get3() - rW;
593

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

    
599
      dX = QUATS[i].get0() + rX;
600
      dY = QUATS[i].get1() + rY;
601
      dZ = QUATS[i].get2() + rZ;
602
      dW = QUATS[i].get3() + rW;
603

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

    
610
    return -1;
611
    }
612

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

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

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

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

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

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

    
652
    return true;
653
    }
654

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

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

    
663
///////////////////////////////////////////////////////////////////////////////////////////////////
664

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

    
675
///////////////////////////////////////////////////////////////////////////////////////////////////
676

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

    
687
///////////////////////////////////////////////////////////////////////////////////////////////////
688

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