Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySkewb.java @ 47d98cd5

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.FactoryCubit;
25
import org.distorted.helpers.ObjectSticker;
26
import org.distorted.library.effect.MatrixEffectQuaternion;
27
import org.distorted.library.main.DistortedEffects;
28
import org.distorted.library.main.DistortedTexture;
29
import org.distorted.library.mesh.MeshBase;
30
import org.distorted.library.mesh.MeshSquare;
31
import org.distorted.library.type.Static3D;
32
import org.distorted.library.type.Static4D;
33
import org.distorted.main.R;
34

    
35
import java.util.Random;
36

    
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

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

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

    
52
  private static final int[] BASIC_ANGLE = new int[] { 3,3,3,3 };
53

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

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

    
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
           new Static4D(  0.5f, -0.5f, -0.5f,  0.5f ),
76
           new Static4D(  0.5f, -0.5f, -0.5f, -0.5f )
77
         };
78

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

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

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

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

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

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

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

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

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

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

    
176
  private static MeshBase[] mMeshes;
177

    
178
  private static final ObjectSticker[] mStickers;
179

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

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

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

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

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  private int getNumCorners()
207
    {
208
    return 8;
209
    }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

    
213
  private int getNumEdges(int layers)
214
    {
215
    return (layers-2)*12;
216
    }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

    
220
  private int getNumCentersPerFace(int layers)
221
    {
222
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1));
223
    }
224

    
225
///////////////////////////////////////////////////////////////////////////////////////////////////
226

    
227
  float getScreenRatio()
228
    {
229
    return 1.0f;
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233

    
234
  Static4D[] getQuats()
235
    {
236
    return QUATS;
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  int getNumFaces()
242
    {
243
    return FACE_COLORS.length;
244
    }
245

    
246
///////////////////////////////////////////////////////////////////////////////////////////////////
247

    
248
  boolean shouldResetTextureMaps()
249
    {
250
    return false;
251
    }
252

    
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

    
255
  int getNumStickerTypes(int numLayers)
256
    {
257
    return 3;
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261

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

    
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275

    
276
  int getNumCubitFaces()
277
    {
278
    return FACES_PER_CUBIT;
279
    }
280

    
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

    
283
  float[][] getCubitPositions(int numLayers)
284
    {
285
    final float DIST_CORNER = (numLayers-1)*0.50f;
286
    final float DIST_EDGE   = (numLayers-1)*0.50f;
287
    final float DIST_CENTER = (numLayers-1)*0.50f;
288

    
289
    final int numCorners = getNumCorners();
290
    final int numEdges   = getNumEdges(numLayers);
291
    final int numCenters = 6*getNumCentersPerFace(numLayers);
292

    
293
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
294

    
295
    /// CORNERS //////////////////////////////////////////////
296

    
297
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
298
    CENTERS[1] = new float[] { DIST_CORNER, DIST_CORNER,-DIST_CORNER };
299
    CENTERS[2] = new float[] { DIST_CORNER,-DIST_CORNER, DIST_CORNER };
300
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
301
    CENTERS[4] = new float[] {-DIST_CORNER, DIST_CORNER, DIST_CORNER };
302
    CENTERS[5] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
303
    CENTERS[6] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
304
    CENTERS[7] = new float[] {-DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
305

    
306
    /// EDGES ///////////////////////////////////////////////
307

    
308
    final float[][]  edgeTable =
309
        {
310
            {0,+DIST_EDGE,+DIST_EDGE},
311
            {+DIST_EDGE,0,+DIST_EDGE},
312
            {0,-DIST_EDGE,+DIST_EDGE},
313
            {-DIST_EDGE,0,+DIST_EDGE},
314
            {+DIST_EDGE,+DIST_EDGE,0},
315
            {+DIST_EDGE,-DIST_EDGE,0},
316
            {-DIST_EDGE,-DIST_EDGE,0},
317
            {-DIST_EDGE,+DIST_EDGE,0},
318
            {0,+DIST_EDGE,-DIST_EDGE},
319
            {+DIST_EDGE,0,-DIST_EDGE},
320
            {0,-DIST_EDGE,-DIST_EDGE},
321
            {-DIST_EDGE,0,-DIST_EDGE}
322
        };
323

    
324
    int index=8;
325

    
326
    for (float[] edges : edgeTable)
327
      {
328
      float c = (3-numLayers)*0.5f;
329

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

    
338
    /// CENTERS //////////////////////////////////////////////
339

    
340
    final float X= -1000.0f;
341
    final float Y= -1001.0f;
342

    
343
    final float[][]  centerTable =
344
        {
345
            {+DIST_CENTER,X,Y},
346
            {-DIST_CENTER,X,Y},
347
            {X,+DIST_CENTER,Y},
348
            {X,-DIST_CENTER,Y},
349
            {X,Y,+DIST_CENTER},
350
            {X,Y,-DIST_CENTER}
351
        };
352

    
353
    float x,y, cen0, cen1, cen2;
354

    
355
    for( float[] centers : centerTable )
356
      {
357
      x = (2-numLayers)*0.5f;
358

    
359
      for(int i=0; i<numLayers-1; i++, x+=1.0f)
360
        {
361
        y = (2-numLayers)*0.5f;
362

    
363
        for(int j=0; j<numLayers-1; j++, y+=1.0f, index++)
364
          {
365
               if( centers[0]==Y ) cen0 = y;
366
          else if( centers[0]==X ) cen0 = x;
367
          else                     cen0 = centers[0];
368

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

    
373
               if( centers[2]==Y ) cen2 = y;
374
          else if( centers[2]==X ) cen2 = x;
375
          else                     cen2 = centers[2];
376

    
377
          CENTERS[index] = new float[] {cen0,cen1,cen2};
378
          }
379
        }
380

    
381
      x = (3-numLayers)*0.5f;
382

    
383
      for(int i=0; i<numLayers-2; i++, x+=1.0f)
384
        {
385
        y = (3-numLayers)*0.5f;
386

    
387
        for(int j=0; j<numLayers-2; j++, y+=1.0f, index++)
388
          {
389
               if( centers[0]==Y ) cen0 = y;
390
          else if( centers[0]==X ) cen0 = x;
391
          else                     cen0 = centers[0];
392

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

    
397
               if( centers[2]==Y ) cen2 = y;
398
          else if( centers[2]==X ) cen2 = x;
399
          else                     cen2 = centers[2];
400

    
401
          CENTERS[index] = new float[] {cen0,cen1,cen2};
402
          }
403
        }
404
      }
405

    
406
    return CENTERS;
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

    
411
  private Static4D getQuat(int cubit, int numLayers)
412
    {
413
    int numCorners = getNumCorners();
414
    int numEdges   = getNumEdges(numLayers);
415

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

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

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

    
465
    return null;
466
    }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
  MeshBase createCubitMesh(int cubit, int numLayers)
471
    {
472
    if( mMeshes==null )
473
      {
474
      FactoryCubit factory = FactoryCubit.getInstance();
475
      factory.clear();
476
      mMeshes = new MeshBase[3];
477
      }
478

    
479
    MeshBase mesh;
480

    
481
    int numCorners = getNumCorners();
482
    int numEdges   = getNumEdges(numLayers);
483

    
484
    if( cubit<numCorners )
485
      {
486
      if( mMeshes[0]==null )
487
        {
488
        float[][] bands= new float[][]
489
          {
490
             {0.028f,35,0.16f,0.7f,7,3,3},
491
             {0.000f, 0,1.00f,0.0f,3,1,5}
492
          };
493
        int[] bandIndexes   = new int[] { 0,0,0,1,1,1 };
494
        float[][] corners   = new float[][] { {0.08f,0.15f}, {0.08f,0.20f} };
495
        int[] cornerIndexes = new int[] { 1,1,1,0,0 };
496
        float[][] centers   = new float[][] { {-0.25f, -0.25f, -0.25f} };
497
        int[] centerIndexes = new int[] { 0,0,0,-1,0 };
498

    
499
        FactoryCubit factory = FactoryCubit.getInstance();
500
        factory.createNewFaceTransform(VERTICES_CORNER,VERT_INDEXES_CORNER);
501
        mMeshes[0] = factory.createRoundedSolid(VERTICES_CORNER, VERT_INDEXES_CORNER,
502
                                                bands, bandIndexes,
503
                                                corners, cornerIndexes,
504
                                                centers, centerIndexes,
505
                                                getNumCubitFaces(), null );
506
        }
507
      mesh = mMeshes[0].copy(true);
508
      }
509
    else if( cubit<numCorners+numEdges )
510
      {
511
      if( mMeshes[1]==null )
512
        {
513
        float[][] bands= new float[][]
514
          {
515
             {0.035f,30,0.16f,0.8f,7,2,5},
516
             {0.020f,45,0.16f,0.2f,3,1,2}
517
          };
518
        int[] bandIndexes   = new int[] { 0,0,1,1 };
519
        float[][] corners   = new float[][] { {0.07f,0.20f}, {0.02f,0.30f} };
520
        int[] cornerIndexes = new int[] { 0,0,1,1 };
521
        float[][] centers   = new float[][] { {0.0f, -0.25f, -0.25f} };
522
        int[] centerIndexes = new int[] { 0,0,0,0 };
523

    
524
        FactoryCubit factory = FactoryCubit.getInstance();
525
        factory.createNewFaceTransform(VERTICES_EDGE,VERT_INDEXES_EDGE);
526
        mMeshes[1] = factory.createRoundedSolid(VERTICES_EDGE, VERT_INDEXES_EDGE,
527
                                                bands, bandIndexes,
528
                                                corners, cornerIndexes,
529
                                                centers, centerIndexes,
530
                                                getNumCubitFaces(), null );
531
        }
532
      mesh = mMeshes[1].copy(true);
533
      }
534
    else
535
      {
536
      if( mMeshes[2]==null )
537
        {
538
        float[][] bands= new float[][]
539
          {
540
             {0.051f,35,SQ2/8,0.9f, 7,3,3},
541
             {0.000f, 0,    1,0.0f, 3,0,0}
542
          };
543
        int[] bandIndexes   = new int[] { 0,1,1,1,1 };
544
        float[][] corners   = new float[][] { {0.06f,0.10f} };
545
        int[] cornerIndexes = new int[] { 0,0,0,0,0 };
546
        float[][] centers   = new float[][] { {0,0,-0.2f} };
547
        int[] centerIndexes = new int[] { 0,0,0,0,-1 };
548

    
549
        FactoryCubit factory = FactoryCubit.getInstance();
550
        factory.createNewFaceTransform(VERTICES_FACE,VERT_INDEXES_FACE);
551
        mMeshes[2] = factory.createRoundedSolid(VERTICES_FACE, VERT_INDEXES_FACE,
552
                                                bands, bandIndexes,
553
                                                corners, cornerIndexes,
554
                                                centers, centerIndexes,
555
                                                getNumCubitFaces(), null );
556
        }
557
      mesh = mMeshes[2].copy(true);
558
      }
559

    
560
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,numLayers), new Static3D(0,0,0) );
561
    mesh.apply(quat,0xffffffff,0);
562

    
563
    return mesh;
564
    }
565

    
566
///////////////////////////////////////////////////////////////////////////////////////////////////
567

    
568
  int getFaceColor(int cubit, int cubitface, int numLayers)
569
    {
570
    int numCorners = getNumCorners();
571
    int numEdges   = getNumEdges(numLayers);
572

    
573
    if( cubit<numCorners )
574
      {
575
      return mCornerMap[cubit][cubitface];
576
      }
577
    else if( cubit<numCorners+numEdges )
578
      {
579
      int edge = (cubit-numCorners)/(numLayers-2);
580
      return mEdgeMap[edge][cubitface];
581
      }
582
    else
583
      {
584
      int center = (cubit-numCorners-numEdges)/getNumCentersPerFace(numLayers);
585
      return mCenterMap[center][cubitface];
586
      }
587
    }
588

    
589
///////////////////////////////////////////////////////////////////////////////////////////////////
590

    
591
  int getColor(int face)
592
    {
593
    return FACE_COLORS[face];
594
    }
595

    
596
///////////////////////////////////////////////////////////////////////////////////////////////////
597

    
598
  ObjectSticker retSticker(int face)
599
    {
600
    return mStickers[face/NUM_FACES];
601
    }
602

    
603
///////////////////////////////////////////////////////////////////////////////////////////////////
604

    
605
  float returnMultiplier()
606
    {
607
    return 2.0f;
608
    }
609

    
610
///////////////////////////////////////////////////////////////////////////////////////////////////
611
// PUBLIC API
612

    
613
  public Static3D[] getRotationAxis()
614
    {
615
    return ROT_AXIS;
616
    }
617

    
618
///////////////////////////////////////////////////////////////////////////////////////////////////
619

    
620
  public int[] getBasicAngle()
621
    {
622
    return BASIC_ANGLE;
623
    }
624

    
625
///////////////////////////////////////////////////////////////////////////////////////////////////
626

    
627
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
628
    {
629
    if( curr==0 )
630
      {
631
      scramble[curr][0] = rnd.nextInt(NUM_AXIS);
632
      }
633
    else
634
      {
635
      int newVector = rnd.nextInt(NUM_AXIS -1);
636
      scramble[curr][0] = (newVector>=scramble[curr-1][0] ? newVector+1 : newVector);
637
      }
638

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

    
641
    switch( rnd.nextInt(2) )
642
      {
643
      case 0: scramble[curr][2] = -1; break;
644
      case 1: scramble[curr][2] =  1; break;
645
      }
646
    }
647

    
648
///////////////////////////////////////////////////////////////////////////////////////////////////
649
// The Skewb is solved if and only if:
650
//
651
// 1) all of its corner and edge cubits are rotated with the same quat
652
// 2) all its face cubits are rotated with the same quat like the corner ones,
653
//    and optionally they also might be upside down.
654
//
655
// i.e.
656
// cubits [ 8] and [ 9] - might be extra QUAT[1]
657
// cubits [10] and [11] - might be extra QUAT[2]
658
// cubits [12] and [13] - might be extra QUAT[3]
659

    
660
  public boolean isSolved()
661
    {
662
    int q = CUBITS[0].mQuatIndex;
663

    
664
    int numLayers      = getNumLayers();
665
    int numCorners     = getNumCorners();
666
    int numEdges       = getNumEdges(numLayers);
667
    int cornersAndEdges= numCorners + numEdges;
668
    int centersPerFace = getNumCentersPerFace(numLayers);
669
    int cubit, q1=q;
670

    
671
    for(cubit=0; cubit<cornersAndEdges; cubit++)
672
      {
673
      if( CUBITS[cubit].mQuatIndex != q ) return false;
674
      }
675

    
676
    for(int face=0; face<6; face++)
677
      {
678
      if( face%2==0 ) q1 = mulQuat(q, (face/2)+1);
679

    
680
      for(int center=0; center<centersPerFace; center++)
681
        {
682
        if( CUBITS[cubit].mQuatIndex != q && CUBITS[cubit].mQuatIndex != q1 ) return false;
683
        cubit++;
684
        }
685
      }
686

    
687
    return true;
688
    }
689

    
690
///////////////////////////////////////////////////////////////////////////////////////////////////
691

    
692
  public int getObjectName(int numLayers)
693
    {
694
    switch(numLayers)
695
      {
696
      case 2: return R.string.skew2;
697
      case 3: return R.string.skew3;
698
      }
699
    return R.string.skew2;
700
    }
701

    
702
///////////////////////////////////////////////////////////////////////////////////////////////////
703

    
704
  public int getInventor(int numLayers)
705
    {
706
    switch(numLayers)
707
      {
708
      case 2: return R.string.skew2_inventor;
709
      case 3: return R.string.skew3_inventor;
710
      }
711
    return R.string.skew2_inventor;
712
    }
713

    
714
///////////////////////////////////////////////////////////////////////////////////////////////////
715

    
716
  public int getComplexity(int numLayers)
717
    {
718
    switch(numLayers)
719
      {
720
      case 2: return 4;
721
      case 3: return 8;
722
      }
723
    return 5;
724
    }
725
}
(37-37/41)