Project

General

Profile

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

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

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 final ObjectSticker[] mStickers;
177

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

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

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

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

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  private int getNumCorners()
205
    {
206
    return 8;
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

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

    
216
///////////////////////////////////////////////////////////////////////////////////////////////////
217

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

    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

    
225
  float getScreenRatio()
226
    {
227
    return 1.0f;
228
    }
229

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

    
232
  Static4D[] getQuats()
233
    {
234
    return QUATS;
235
    }
236

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

    
239
  int getNumFaces()
240
    {
241
    return FACE_COLORS.length;
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245

    
246
  boolean shouldResetTextureMaps()
247
    {
248
    return false;
249
    }
250

    
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252

    
253
  int getNumStickerTypes(int numLayers)
254
    {
255
    return 3;
256
    }
257

    
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259

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

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273

    
274
  int getNumCubitFaces()
275
    {
276
    return FACES_PER_CUBIT;
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

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

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

    
291
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
292

    
293
    /// CORNERS //////////////////////////////////////////////
294

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

    
304
    /// EDGES ///////////////////////////////////////////////
305

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

    
322
    int index=8;
323

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

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

    
336
    /// CENTERS //////////////////////////////////////////////
337

    
338
    final float X= -1000.0f;
339
    final float Y= -1001.0f;
340

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

    
351
    float x,y, cen0, cen1, cen2;
352

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

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

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

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

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

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

    
379
      x = (3-numLayers)*0.5f;
380

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

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

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

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

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

    
404
    return CENTERS;
405
    }
406

    
407
///////////////////////////////////////////////////////////////////////////////////////////////////
408

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

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

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

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

    
463
    return null;
464
    }
465

    
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467

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

    
477
    MeshBase mesh;
478

    
479
    int numCorners = getNumCorners();
480
    int numEdges   = getNumEdges(numLayers);
481

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

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

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

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

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

    
561
    return mesh;
562
    }
563

    
564
///////////////////////////////////////////////////////////////////////////////////////////////////
565

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

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

    
587
///////////////////////////////////////////////////////////////////////////////////////////////////
588

    
589
  int getColor(int face)
590
    {
591
    return FACE_COLORS[face];
592
    }
593

    
594
///////////////////////////////////////////////////////////////////////////////////////////////////
595

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

    
601
///////////////////////////////////////////////////////////////////////////////////////////////////
602

    
603
  float returnMultiplier()
604
    {
605
    return 2.0f;
606
    }
607

    
608
///////////////////////////////////////////////////////////////////////////////////////////////////
609
// PUBLIC API
610

    
611
  public Static3D[] getRotationAxis()
612
    {
613
    return ROT_AXIS;
614
    }
615

    
616
///////////////////////////////////////////////////////////////////////////////////////////////////
617

    
618
  public int[] getBasicAngle()
619
    {
620
    return BASIC_ANGLE;
621
    }
622

    
623
///////////////////////////////////////////////////////////////////////////////////////////////////
624

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

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

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

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

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

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

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

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

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

    
685
    return true;
686
    }
687

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

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

    
700
///////////////////////////////////////////////////////////////////////////////////////////////////
701

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

    
712
///////////////////////////////////////////////////////////////////////////////////////////////////
713

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