Project

General

Profile

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

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

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

    
24
import org.distorted.helpers.ObjectShape;
25
import org.distorted.helpers.ObjectSticker;
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28
import org.distorted.library.mesh.MeshSquare;
29
import org.distorted.library.type.Static3D;
30
import org.distorted.library.type.Static4D;
31
import org.distorted.main.R;
32

    
33
import java.util.Random;
34

    
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36

    
37
public class TwistySkewb extends TwistyObject
38
{
39
  private static final int FACES_PER_CUBIT =6;
40

    
41
  // the four rotation axis of a RubikSkewb. Must be normalized.
42
  static final Static3D[] ROT_AXIS = new Static3D[]
43
         {
44
           new Static3D(+SQ3/3,+SQ3/3,+SQ3/3),
45
           new Static3D(+SQ3/3,+SQ3/3,-SQ3/3),
46
           new Static3D(+SQ3/3,-SQ3/3,+SQ3/3),
47
           new Static3D(+SQ3/3,-SQ3/3,-SQ3/3)
48
         };
49

    
50
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
51

    
52
  private static final int[] FACE_COLORS = new int[]
53
         {
54
           COLOR_YELLOW, COLOR_WHITE,
55
           COLOR_BLUE  , COLOR_GREEN,
56
           COLOR_RED   , COLOR_ORANGE
57
         };
58

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

    
67
           new Static4D(  0.5f,  0.5f,  0.5f,  0.5f ),
68
           new Static4D(  0.5f,  0.5f,  0.5f, -0.5f ),
69
           new Static4D(  0.5f,  0.5f, -0.5f,  0.5f ),
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
         };
76

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

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

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

    
115
  private static final double[][] VERTICES_CORNER = new double[][]
116
          {
117
              {-0.5f, 0.0f, 0.0f},
118
              { 0.0f,-0.5f, 0.0f},
119
              { 0.0f, 0.0f,-0.5f},
120
              {-0.5f,-0.5f,-0.5f},
121
              { 0.0f, 0.0f, 0.0f}
122
          };
123

    
124
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
125
          {
126
              {0,1,4},
127
              {2,0,4},
128
              {1,2,4},
129
              {3,1,0},
130
              {3,2,1},
131
              {3,0,2}
132
          };
133

    
134
  private static final double[][] VERTICES_EDGE = new double[][]
135
          {
136
             {-0.5, 0.0, 0.0},
137
             { 0.5, 0.0, 0.0},
138
             { 0.0,-0.5, 0.0},
139
             { 0.0, 0.0,-0.5}
140
          };
141

    
142
  private static final int[][] VERT_INDEXES_EDGE = new int[][]
143
          {
144
             {2,1,0},   // counterclockwise!
145
             {3,0,1},
146
             {2,3,1},
147
             {3,2,0},
148
          };
149

    
150
  private static final double[][] VERTICES_FACE = new double[][]
151
          {
152
             {-0.5f, 0.0f, 0.0f },
153
             { 0.0f,-0.5f, 0.0f },
154
             { 0.5f, 0.0f, 0.0f },
155
             { 0.0f, 0.5f, 0.0f },
156
             { 0.0f, 0.0f,-0.5f }
157
          };
158

    
159
  private static final int[][] VERT_INDEXES_FACE = new int[][]
160
          {
161
             {0,1,2,3},
162
             {4,1,0},
163
             {4,2,1},
164
             {4,3,2},
165
             {4,0,3}
166
          };
167

    
168
  private static final float[][] STICKERS = new float[][]
169
          {
170
             { -0.5f, 0.25f, 0.25f,  -0.5f, 0.25f, 0.25f  },
171
             { -0.5f, 0.00f, 0.00f,  -0.5f, 0.50f, 0.0f, 0.0f, 0.5f }
172
          };
173

    
174
  private static final ObjectSticker[] mStickers;
175

    
176
  static
177
    {
178
    mStickers = new ObjectSticker[STICKERS.length+1];
179
    final float R1 = 0.025f;
180
    final float R2 = 0.025f;
181
    final float R3 = 0.055f;
182
    final float[][] radii  = { { R1,R1,R1 },{ R2,R2,R2 },{ R3,R3,R3,R3 } };
183
    final float[] strokes = { 0.045f, 0.035f, 0.035f };
184

    
185
    for(int s=0; s<STICKERS.length+1; s++)
186
      {
187
      int index = s<2 ? 0:1;
188
      mStickers[s] = new ObjectSticker(STICKERS[index],null,radii[s],strokes[s]);
189
      }
190
    }
191

    
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

    
194
  TwistySkewb(int size, Static4D quat, DistortedTexture texture,
195
              MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
196
    {
197
    super(size, 2*size-2, quat, texture, mesh, effects, moves, ObjectList.SKEW, res, scrWidth);
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
  private int getNumCorners()
203
    {
204
    return 8;
205
    }
206

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

    
209
  private int getNumEdges(int layers)
210
    {
211
    return (layers-2)*12;
212
    }
213

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

    
216
  private int getNumCentersPerFace(int layers)
217
    {
218
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1));
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  float getScreenRatio()
224
    {
225
    return 1.0f;
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  Static4D[] getQuats()
231
    {
232
    return QUATS;
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  int getNumFaces()
238
    {
239
    return FACE_COLORS.length;
240
    }
241

    
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243

    
244
  boolean shouldResetTextureMaps()
245
    {
246
    return false;
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  int getNumStickerTypes(int numLayers)
252
    {
253
    return 3;
254
    }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257

    
258
  float[][] getCuts(int numLayers)
259
    {
260
    switch(numLayers)
261
      {
262
      case 2: float[] c2 = new float[] {0.0f};
263
              return new float[][] { c2,c2,c2,c2 };
264
      case 3: float[] c3 = new float[] {-SQ3/12,+SQ3/12};
265
              return new float[][] { c3,c3,c3,c3 };
266
      }
267
    return null;
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
  int getNumCubitFaces()
273
    {
274
    return FACES_PER_CUBIT;
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  float[][] getCubitPositions(int numLayers)
280
    {
281
    final float DIST_CORNER = (numLayers-1)*0.50f;
282
    final float DIST_EDGE   = (numLayers-1)*0.50f;
283
    final float DIST_CENTER = (numLayers-1)*0.50f;
284

    
285
    final int numCorners = getNumCorners();
286
    final int numEdges   = getNumEdges(numLayers);
287
    final int numCenters = 6*getNumCentersPerFace(numLayers);
288

    
289
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
290

    
291
    /// CORNERS //////////////////////////////////////////////
292

    
293
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
294
    CENTERS[1] = new float[] { DIST_CORNER, DIST_CORNER,-DIST_CORNER };
295
    CENTERS[2] = new float[] { DIST_CORNER,-DIST_CORNER, DIST_CORNER };
296
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
297
    CENTERS[4] = new float[] {-DIST_CORNER, DIST_CORNER, DIST_CORNER };
298
    CENTERS[5] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
299
    CENTERS[6] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
300
    CENTERS[7] = new float[] {-DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
301

    
302
    /// EDGES ///////////////////////////////////////////////
303

    
304
    final float[][]  edgeTable =
305
        {
306
            {0,+DIST_EDGE,+DIST_EDGE},
307
            {+DIST_EDGE,0,+DIST_EDGE},
308
            {0,-DIST_EDGE,+DIST_EDGE},
309
            {-DIST_EDGE,0,+DIST_EDGE},
310
            {+DIST_EDGE,+DIST_EDGE,0},
311
            {+DIST_EDGE,-DIST_EDGE,0},
312
            {-DIST_EDGE,-DIST_EDGE,0},
313
            {-DIST_EDGE,+DIST_EDGE,0},
314
            {0,+DIST_EDGE,-DIST_EDGE},
315
            {+DIST_EDGE,0,-DIST_EDGE},
316
            {0,-DIST_EDGE,-DIST_EDGE},
317
            {-DIST_EDGE,0,-DIST_EDGE}
318
        };
319

    
320
    int index=8;
321

    
322
    for (float[] edges : edgeTable)
323
      {
324
      float c = (3-numLayers)*0.5f;
325

    
326
      for (int j=0; j<numLayers-2; j++, c+=1.0f, index++)
327
        {
328
        CENTERS[index] = new float[] { edges[0]==0 ? c : edges[0] ,
329
                                       edges[1]==0 ? c : edges[1] ,
330
                                       edges[2]==0 ? c : edges[2] };
331
        }
332
      }
333

    
334
    /// CENTERS //////////////////////////////////////////////
335

    
336
    final float X= -1000.0f;
337
    final float Y= -1001.0f;
338

    
339
    final float[][]  centerTable =
340
        {
341
            {+DIST_CENTER,X,Y},
342
            {-DIST_CENTER,X,Y},
343
            {X,+DIST_CENTER,Y},
344
            {X,-DIST_CENTER,Y},
345
            {X,Y,+DIST_CENTER},
346
            {X,Y,-DIST_CENTER}
347
        };
348

    
349
    float x,y, cen0, cen1, cen2;
350

    
351
    for( float[] centers : centerTable )
352
      {
353
      x = (2-numLayers)*0.5f;
354

    
355
      for(int i=0; i<numLayers-1; i++, x+=1.0f)
356
        {
357
        y = (2-numLayers)*0.5f;
358

    
359
        for(int j=0; j<numLayers-1; j++, y+=1.0f, index++)
360
          {
361
               if( centers[0]==Y ) cen0 = y;
362
          else if( centers[0]==X ) cen0 = x;
363
          else                     cen0 = centers[0];
364

    
365
               if( centers[1]==Y ) cen1 = y;
366
          else if( centers[1]==X ) cen1 = x;
367
          else                     cen1 = centers[1];
368

    
369
               if( centers[2]==Y ) cen2 = y;
370
          else if( centers[2]==X ) cen2 = x;
371
          else                     cen2 = centers[2];
372

    
373
          CENTERS[index] = new float[] {cen0,cen1,cen2};
374
          }
375
        }
376

    
377
      x = (3-numLayers)*0.5f;
378

    
379
      for(int i=0; i<numLayers-2; i++, x+=1.0f)
380
        {
381
        y = (3-numLayers)*0.5f;
382

    
383
        for(int j=0; j<numLayers-2; j++, y+=1.0f, index++)
384
          {
385
               if( centers[0]==Y ) cen0 = y;
386
          else if( centers[0]==X ) cen0 = x;
387
          else                     cen0 = centers[0];
388

    
389
               if( centers[1]==Y ) cen1 = y;
390
          else if( centers[1]==X ) cen1 = x;
391
          else                     cen1 = centers[1];
392

    
393
               if( centers[2]==Y ) cen2 = y;
394
          else if( centers[2]==X ) cen2 = x;
395
          else                     cen2 = centers[2];
396

    
397
          CENTERS[index] = new float[] {cen0,cen1,cen2};
398
          }
399
        }
400
      }
401

    
402
    return CENTERS;
403
    }
404

    
405
///////////////////////////////////////////////////////////////////////////////////////////////////
406

    
407
  Static4D getQuat(int cubit, int numLayers)
408
    {
409
    int numCorners = getNumCorners();
410
    int numEdges   = getNumEdges(numLayers);
411

    
412
    if( cubit<numCorners )
413
      {
414
      switch(cubit)
415
        {
416
        case  0: return QUATS[0];                          //  unit quat
417
        case  1: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
418
        case  2: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
419
        case  3: return QUATS[1];                          // 180 along X
420
        case  4: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
421
        case  5: return QUATS[2];                          // 180 along Y
422
        case  6: return QUATS[3];                          // 180 along Z
423
        case  7: return new Static4D(SQ2/2,0,-SQ2/2,0);    // 180 along (SQ2/2,0,-SQ2/2)
424
        }
425
      }
426
    else if( cubit<numCorners+numEdges )
427
      {
428
      int edge = (cubit-numCorners)/(numLayers-2);
429

    
430
      switch(edge)
431
        {
432
        case  0: return QUATS[ 0];
433
        case  1: return QUATS[ 5];
434
        case  2: return QUATS[ 3];
435
        case  3: return QUATS[11];
436
        case  4: return QUATS[ 4];
437
        case  5: return QUATS[ 7];
438
        case  6: return QUATS[ 9];
439
        case  7: return QUATS[10];
440
        case  8: return QUATS[ 2];
441
        case  9: return QUATS[ 8];
442
        case 10: return QUATS[ 1];
443
        case 11: return QUATS[ 6];
444
        }
445
      }
446
    else
447
      {
448
      int center = (cubit-numCorners-numEdges)/getNumCentersPerFace(numLayers);
449

    
450
      switch(center)
451
        {
452
        case 0: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
453
        case 1: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
454
        case 2: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
455
        case 3: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
456
        case 4: return QUATS[0];                          //  unit quaternion
457
        case 5: return QUATS[1];                          // 180 along X
458
        }
459
      }
460

    
461
    return null;
462
    }
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465

    
466
  ObjectShape getObjectShape(int cubit, int numLayers)
467
    {
468
    int variant = getCubitVariant(cubit,numLayers);
469

    
470
    if( variant==0 )
471
      {
472
      int N = numLayers==2 ? 7:5;
473
      int E1= numLayers==2 ? 3:2;
474
      int E2= numLayers==2 ? 5:3;
475
      float[][] bands     = new float[][] { {0.028f,35,0.16f,0.7f,N,E1,E1}, {0.000f, 0,1.00f,0.0f,3,1,E2} };
476
      int[] bandIndices   = new int[] { 0,0,0,1,1,1 };
477
      float[][] corners   = new float[][] { {0.08f,0.15f}, {0.08f,0.20f} };
478
      int[] cornerIndices = new int[] { 1,1,1,0,0 };
479
      float[][] centers   = new float[][] { {-0.25f, -0.25f, -0.25f} };
480
      int[] centerIndices = new int[] { 0,0,0,-1,0 };
481
      return new ObjectShape(VERTICES_CORNER,VERT_INDEXES_CORNER,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
482
      }
483
    else if( variant==1 )
484
      {
485
      int N = numLayers==2 ? 7:5;
486
      int E = numLayers==2 ? 5:2;
487
      float[][] bands     = new float[][] { {0.035f,30,0.16f,0.8f,N,2,E}, {0.020f,45,0.16f,0.2f,3,1,2} };
488
      int[] bandIndices   = new int[] { 0,0,1,1 };
489
      float[][] corners   = new float[][] { {0.07f,0.20f}, {0.02f,0.30f} };
490
      int[] cornerIndices = new int[] { 0,0,1,1 };
491
      float[][] centers   = new float[][] { {0.0f, -0.25f, -0.25f} };
492
      int[] centerIndices = new int[] { 0,0,0,0 };
493
      return new ObjectShape(VERTICES_EDGE,VERT_INDEXES_EDGE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
494
      }
495
    else
496
      {
497
      int N = numLayers==2 ? 7:6;
498
      int E = numLayers==2 ? 3:1;
499
      float[][] bands     = new float[][] { {0.051f,35,SQ2/8,0.9f,N,E,E}, {0.000f,0,1,0.0f,3,0,0} };
500
      int[] bandIndices   = new int[] { 0,1,1,1,1 };
501
      float[][] corners   = new float[][] { {0.06f,0.10f} };
502
      int[] cornerIndices = new int[] { 0,0,0,0,0 };
503
      float[][] centers   = new float[][] { {0,0,-0.2f} };
504
      int[] centerIndices = new int[] { 0,0,0,0,-1 };
505
      return new ObjectShape(VERTICES_FACE,VERT_INDEXES_FACE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
506
      }
507
    }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
  int getNumCubitVariants(int numLayers)
512
    {
513
    return 3;
514
    }
515

    
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
  int getCubitVariant(int cubit, int numLayers)
519
    {
520
    int numCorners = getNumCorners();
521
    if( cubit<numCorners ) return 0;
522
    int numEdges = getNumEdges(numLayers);
523
    return cubit<numCorners+numEdges ? 1:2;
524
    }
525

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

    
528
  int getFaceColor(int cubit, int cubitface, int numLayers)
529
    {
530
    int numCorners = getNumCorners();
531
    int numEdges   = getNumEdges(numLayers);
532

    
533
    if( cubit<numCorners )
534
      {
535
      return mCornerMap[cubit][cubitface];
536
      }
537
    else if( cubit<numCorners+numEdges )
538
      {
539
      int edge = (cubit-numCorners)/(numLayers-2);
540
      return mEdgeMap[edge][cubitface];
541
      }
542
    else
543
      {
544
      int center = (cubit-numCorners-numEdges)/getNumCentersPerFace(numLayers);
545
      return mCenterMap[center][cubitface];
546
      }
547
    }
548

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

    
551
  int getColor(int face)
552
    {
553
    return FACE_COLORS[face];
554
    }
555

    
556
///////////////////////////////////////////////////////////////////////////////////////////////////
557

    
558
  ObjectSticker retSticker(int face)
559
    {
560
    return mStickers[face/NUM_FACES];
561
    }
562

    
563
///////////////////////////////////////////////////////////////////////////////////////////////////
564

    
565
  float returnMultiplier()
566
    {
567
    return 2.0f;
568
    }
569

    
570
///////////////////////////////////////////////////////////////////////////////////////////////////
571
// PUBLIC API
572

    
573
  public Static3D[] getRotationAxis()
574
    {
575
    return ROT_AXIS;
576
    }
577

    
578
///////////////////////////////////////////////////////////////////////////////////////////////////
579

    
580
  public int[] getBasicAngle()
581
    {
582
    return BASIC_ANGLE;
583
    }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586

    
587
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
588
    {
589
    if( curr==0 )
590
      {
591
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
592
      }
593
    else
594
      {
595
      int newVector = rnd.nextInt(NUM_AXIS -1);
596
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
597
      }
598

    
599
    scramble[curr][1] = rnd.nextFloat()<=0.5f ? 0 : getNumLayers()-1;
600

    
601
    switch( rnd.nextInt(2) )
602
      {
603
      case 0: scramble[curr][2] = -1; break;
604
      case 1: scramble[curr][2] =  1; break;
605
      }
606
    }
607

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

    
620
  public boolean isSolved()
621
    {
622
    int q = CUBITS[0].mQuatIndex;
623

    
624
    int numLayers      = getNumLayers();
625
    int numCorners     = getNumCorners();
626
    int numEdges       = getNumEdges(numLayers);
627
    int cornersAndEdges= numCorners + numEdges;
628
    int centersPerFace = getNumCentersPerFace(numLayers);
629
    int cubit, q1=q;
630

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

    
636
    for(int face=0; face<6; face++)
637
      {
638
      if( face%2==0 ) q1 = mulQuat(q, (face/2)+1);
639

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

    
647
    return true;
648
    }
649

    
650
///////////////////////////////////////////////////////////////////////////////////////////////////
651

    
652
  public int getObjectName(int numLayers)
653
    {
654
    switch(numLayers)
655
      {
656
      case 2: return R.string.skew2;
657
      case 3: return R.string.skew3;
658
      }
659
    return R.string.skew2;
660
    }
661

    
662
///////////////////////////////////////////////////////////////////////////////////////////////////
663

    
664
  public int getInventor(int numLayers)
665
    {
666
    switch(numLayers)
667
      {
668
      case 2: return R.string.skew2_inventor;
669
      case 3: return R.string.skew3_inventor;
670
      }
671
    return R.string.skew2_inventor;
672
    }
673

    
674
///////////////////////////////////////////////////////////////////////////////////////////////////
675

    
676
  public int getComplexity(int numLayers)
677
    {
678
    switch(numLayers)
679
      {
680
      case 2: return 4;
681
      case 3: return 8;
682
      }
683
    return 5;
684
    }
685
}
(37-37/41)