Project

General

Profile

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

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

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.helpers.FactoryCubit;
27
import org.distorted.helpers.FactorySticker;
28
import org.distorted.library.effect.MatrixEffectQuaternion;
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

    
37
import java.util.Random;
38

    
39
///////////////////////////////////////////////////////////////////////////////////////////////////
40

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

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

    
180
  TwistySkewb(int size, Static4D quat, DistortedTexture texture,
181
              MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
182
    {
183
    super(size, 2*size-2, quat, texture, mesh, effects, moves, ObjectList.SKEW, res, scrWidth);
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
  private int getNumCorners()
189
    {
190
    return 8;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  private int getNumEdges(int layers)
196
    {
197
    return (layers-2)*12;
198
    }
199

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

    
202
  private int getNumCentersPerFace(int layers)
203
    {
204
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1));
205
    }
206

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

    
209
  float getScreenRatio()
210
    {
211
    return 1.0f;
212
    }
213

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

    
216
  Static4D[] getQuats()
217
    {
218
    return QUATS;
219
    }
220

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

    
223
  int getNumFaces()
224
    {
225
    return FACE_COLORS.length;
226
    }
227

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

    
230
  boolean shouldResetTextureMaps()
231
    {
232
    return false;
233
    }
234

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

    
237
  int getNumStickerTypes(int numLayers)
238
    {
239
    return 3;
240
    }
241

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

    
244
  float[] getCuts(int numLayers)
245
    {
246
    float[] cuts = new float[numLayers-1];
247

    
248
    switch(numLayers)
249
      {
250
      case 2: cuts[0] = 0;
251
              break;
252
      case 3: cuts[0] = -SQ3/12;
253
              cuts[1] = +SQ3/12;
254
              break;
255
      case 4: cuts[0] = -SQ3/9;
256
              cuts[1] = 0;
257
              cuts[2] = +SQ3/9;
258
              break;
259
      }
260
    return cuts;
261
    }
262

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

    
265
  int getNumCubitFaces()
266
    {
267
    return FACES_PER_CUBIT;
268
    }
269

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

    
272
  float[][] getCubitPositions(int numLayers)
273
    {
274
    final float DIST_CORNER = (numLayers-1)*0.50f;
275
    final float DIST_EDGE   = (numLayers-1)*0.50f;
276
    final float DIST_CENTER = (numLayers-1)*0.50f;
277

    
278
    final int numCorners = getNumCorners();
279
    final int numEdges   = getNumEdges(numLayers);
280
    final int numCenters = 6*getNumCentersPerFace(numLayers);
281

    
282
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
283

    
284
    /// CORNERS //////////////////////////////////////////////
285

    
286
    CENTERS[0] = new float[] { DIST_CORNER, DIST_CORNER, DIST_CORNER };
287
    CENTERS[1] = new float[] { DIST_CORNER, DIST_CORNER,-DIST_CORNER };
288
    CENTERS[2] = new float[] { DIST_CORNER,-DIST_CORNER, DIST_CORNER };
289
    CENTERS[3] = new float[] { DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
290
    CENTERS[4] = new float[] {-DIST_CORNER, DIST_CORNER, DIST_CORNER };
291
    CENTERS[5] = new float[] {-DIST_CORNER, DIST_CORNER,-DIST_CORNER };
292
    CENTERS[6] = new float[] {-DIST_CORNER,-DIST_CORNER, DIST_CORNER };
293
    CENTERS[7] = new float[] {-DIST_CORNER,-DIST_CORNER,-DIST_CORNER };
294

    
295
    /// EDGES ///////////////////////////////////////////////
296

    
297
    final float[][]  edgeTable =
298
        {
299
            {0,+DIST_EDGE,+DIST_EDGE},
300
            {+DIST_EDGE,0,+DIST_EDGE},
301
            {0,-DIST_EDGE,+DIST_EDGE},
302
            {-DIST_EDGE,0,+DIST_EDGE},
303
            {+DIST_EDGE,+DIST_EDGE,0},
304
            {+DIST_EDGE,-DIST_EDGE,0},
305
            {-DIST_EDGE,-DIST_EDGE,0},
306
            {-DIST_EDGE,+DIST_EDGE,0},
307
            {0,+DIST_EDGE,-DIST_EDGE},
308
            {+DIST_EDGE,0,-DIST_EDGE},
309
            {0,-DIST_EDGE,-DIST_EDGE},
310
            {-DIST_EDGE,0,-DIST_EDGE}
311
        };
312

    
313
    int index=8;
314

    
315
    for (float[] edges : edgeTable)
316
      {
317
      float c = (3-numLayers)*0.5f;
318

    
319
      for (int j=0; j<numLayers-2; j++, c+=1.0f, index++)
320
        {
321
        CENTERS[index] = new float[] { edges[0]==0 ? c : edges[0] ,
322
                                       edges[1]==0 ? c : edges[1] ,
323
                                       edges[2]==0 ? c : edges[2] };
324
        }
325
      }
326

    
327
    /// CENTERS //////////////////////////////////////////////
328

    
329
    final float X= -1000.0f;
330
    final float Y= -1001.0f;
331

    
332
    final float[][]  centerTable =
333
        {
334
            {+DIST_CENTER,X,Y},
335
            {-DIST_CENTER,X,Y},
336
            {X,+DIST_CENTER,Y},
337
            {X,-DIST_CENTER,Y},
338
            {X,Y,+DIST_CENTER},
339
            {X,Y,-DIST_CENTER}
340
        };
341

    
342
    float x,y, cen0, cen1, cen2;
343

    
344
    for( float[] centers : centerTable )
345
      {
346
      x = (2-numLayers)*0.5f;
347

    
348
      for(int i=0; i<numLayers-1; i++, x+=1.0f)
349
        {
350
        y = (2-numLayers)*0.5f;
351

    
352
        for(int j=0; j<numLayers-1; j++, y+=1.0f, index++)
353
          {
354
               if( centers[0]==Y ) cen0 = y;
355
          else if( centers[0]==X ) cen0 = x;
356
          else                     cen0 = centers[0];
357

    
358
               if( centers[1]==Y ) cen1 = y;
359
          else if( centers[1]==X ) cen1 = x;
360
          else                     cen1 = centers[1];
361

    
362
               if( centers[2]==Y ) cen2 = y;
363
          else if( centers[2]==X ) cen2 = x;
364
          else                     cen2 = centers[2];
365

    
366
          CENTERS[index] = new float[] {cen0,cen1,cen2};
367
          }
368
        }
369

    
370
      x = (3-numLayers)*0.5f;
371

    
372
      for(int i=0; i<numLayers-2; i++, x+=1.0f)
373
        {
374
        y = (3-numLayers)*0.5f;
375

    
376
        for(int j=0; j<numLayers-2; j++, y+=1.0f, index++)
377
          {
378
               if( centers[0]==Y ) cen0 = y;
379
          else if( centers[0]==X ) cen0 = x;
380
          else                     cen0 = centers[0];
381

    
382
               if( centers[1]==Y ) cen1 = y;
383
          else if( centers[1]==X ) cen1 = x;
384
          else                     cen1 = centers[1];
385

    
386
               if( centers[2]==Y ) cen2 = y;
387
          else if( centers[2]==X ) cen2 = x;
388
          else                     cen2 = centers[2];
389

    
390
          CENTERS[index] = new float[] {cen0,cen1,cen2};
391
          }
392
        }
393
      }
394

    
395
    return CENTERS;
396
    }
397

    
398
///////////////////////////////////////////////////////////////////////////////////////////////////
399

    
400
  private Static4D getQuat(int cubit, int numLayers)
401
    {
402
    int numCorners = getNumCorners();
403
    int numEdges   = getNumEdges(numLayers);
404

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

    
423
      switch(edge)
424
        {
425
        case  0: return QUATS[ 0];
426
        case  1: return QUATS[ 5];
427
        case  2: return QUATS[ 3];
428
        case  3: return QUATS[11];
429
        case  4: return QUATS[ 4];
430
        case  5: return QUATS[ 7];
431
        case  6: return QUATS[ 9];
432
        case  7: return QUATS[10];
433
        case  8: return QUATS[ 2];
434
        case  9: return QUATS[ 8];
435
        case 10: return QUATS[ 1];
436
        case 11: return QUATS[ 6];
437
        }
438
      }
439
    else
440
      {
441
      int center = (cubit-numCorners-numEdges)/getNumCentersPerFace(numLayers);
442

    
443
      switch(center)
444
        {
445
        case 0: return new Static4D(0,-SQ2/2,0,SQ2/2);    // -90 along Y
446
        case 1: return new Static4D(0, SQ2/2,0,SQ2/2);    //  90 along Y
447
        case 2: return new Static4D( SQ2/2,0,0,SQ2/2);    //  90 along X
448
        case 3: return new Static4D(-SQ2/2,0,0,SQ2/2);    // -90 along X
449
        case 4: return QUATS[0];                          //  unit quaternion
450
        case 5: return QUATS[1];                          // 180 along X
451
        }
452
      }
453

    
454
    return null;
455
    }
456

    
457
///////////////////////////////////////////////////////////////////////////////////////////////////
458

    
459
  MeshBase createCubitMesh(int cubit, int numLayers)
460
    {
461
    if( mMeshes==null )
462
      {
463
      FactoryCubit factory = FactoryCubit.getInstance();
464
      factory.clear();
465
      mMeshes = new MeshBase[3];
466
      }
467

    
468
    MeshBase mesh;
469

    
470
    int numCorners = getNumCorners();
471
    int numEdges   = getNumEdges(numLayers);
472

    
473
    if( cubit<numCorners )
474
      {
475
      if( mMeshes[0]==null )
476
        {
477
        float[][] bands= new float[][]
478
          {
479
             {0.028f,35,0.16f,0.7f,7,3,3},
480
             {0.000f, 0,1.00f,0.0f,3,1,5}
481
          };
482
        int[] bandIndexes   = new int[] { 0,0,0,1,1,1 };
483
        float[][] corners   = new float[][] { {0.08f,0.15f}, {0.08f,0.20f} };
484
        int[] cornerIndexes = new int[] { 1,1,1,0,0 };
485
        float[][] centers   = new float[][] { {-0.25f, -0.25f, -0.25f} };
486
        int[] centerIndexes = new int[] { 0,0,0,-1,0 };
487

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

    
513
        FactoryCubit factory = FactoryCubit.getInstance();
514
        factory.createNewFaceTransform(VERTICES_EDGE,VERT_INDEXES_EDGE);
515
        mMeshes[1] = factory.createRoundedSolid(VERTICES_EDGE, VERT_INDEXES_EDGE,
516
                                                bands, bandIndexes,
517
                                                corners, cornerIndexes,
518
                                                centers, centerIndexes,
519
                                                getNumCubitFaces() );
520
        }
521
      mesh = mMeshes[1].copy(true);
522
      }
523
    else
524
      {
525
      if( mMeshes[2]==null )
526
        {
527
        float[][] bands= new float[][]
528
          {
529
             {0.051f,35,SQ2/8,0.9f, 7,3,3},
530
             {0.000f, 0,    1,0.0f, 3,0,0}
531
          };
532
        int[] bandIndexes   = new int[] { 0,1,1,1,1 };
533
        float[][] corners   = new float[][] { {0.06f,0.10f} };
534
        int[] cornerIndexes = new int[] { 0,0,0,0,0 };
535
        float[][] centers   = new float[][] { {0,0,-0.2f} };
536
        int[] centerIndexes = new int[] { 0,0,0,0,-1 };
537

    
538
        FactoryCubit factory = FactoryCubit.getInstance();
539
        factory.createNewFaceTransform(VERTICES_FACE,VERT_INDEXES_FACE);
540
        mMeshes[2] = factory.createRoundedSolid(VERTICES_FACE, VERT_INDEXES_FACE,
541
                                                bands, bandIndexes,
542
                                                corners, cornerIndexes,
543
                                                centers, centerIndexes,
544
                                                getNumCubitFaces() );
545
        }
546
      mesh = mMeshes[2].copy(true);
547
      }
548

    
549
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,numLayers), new Static3D(0,0,0) );
550
    mesh.apply(quat,0xffffffff,0);
551

    
552
    return mesh;
553
    }
554

    
555
///////////////////////////////////////////////////////////////////////////////////////////////////
556

    
557
  int getFaceColor(int cubit, int cubitface, int numLayers)
558
    {
559
    int numCorners = getNumCorners();
560
    int numEdges   = getNumEdges(numLayers);
561

    
562
    if( cubit<numCorners )
563
      {
564
      return mCornerMap[cubit][cubitface];
565
      }
566
    else if( cubit<numCorners+numEdges )
567
      {
568
      int edge = (cubit-numCorners)/(numLayers-2);
569
      return mEdgeMap[edge][cubitface];
570
      }
571
    else
572
      {
573
      int center = (cubit-numCorners-numEdges)/getNumCentersPerFace(numLayers);
574
      return mCenterMap[center][cubitface];
575
      }
576
    }
577

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

    
580
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
581
    {
582
    int COLORS = FACE_COLORS.length;
583
    float R=0.0f,S=0.0f;
584
    int index=0, cubitType = face/COLORS;
585

    
586
    switch(cubitType)
587
      {
588
      case 0: R = 0.025f; S = 0.045f; index= 0; break;
589
      case 1: R = 0.025f; S = 0.035f; index= 0; break;
590
      case 2: R = 0.055f; S = 0.035f; index= 1; break;
591
      }
592

    
593
    FactorySticker factory = FactorySticker.getInstance();
594
    factory.drawRoundedPolygon(canvas, paint, left, top, STICKERS[index], S, FACE_COLORS[face%COLORS], R);
595
    }
596

    
597
///////////////////////////////////////////////////////////////////////////////////////////////////
598

    
599
  float returnMultiplier()
600
    {
601
    return 2.0f;
602
    }
603

    
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605

    
606
  float[] getRowChances(int numLayers)
607
    {
608
    float[] chances = new float[numLayers];
609

    
610
    switch(numLayers)
611
      {
612
      case 2: chances[0] = 0.5f;
613
              chances[1] = 1.0f;
614
              break;
615
      case 3: chances[0] = 0.5f;
616
              chances[1] = 0.5f;
617
              chances[2] = 1.0f;
618
              break;
619
      default:for(int i=0; i<numLayers; i++)
620
                {
621
                chances[i] = (float)(i+1)/numLayers;
622
                }
623
      }
624

    
625
    return chances;
626
    }
627

    
628
///////////////////////////////////////////////////////////////////////////////////////////////////
629
// PUBLIC API
630

    
631
  public Static3D[] getRotationAxis()
632
    {
633
    return ROT_AXIS;
634
    }
635

    
636
///////////////////////////////////////////////////////////////////////////////////////////////////
637

    
638
  public int getBasicAngle()
639
    {
640
    return 3;
641
    }
642

    
643
///////////////////////////////////////////////////////////////////////////////////////////////////
644

    
645
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
646
    {
647
    if( num==0 )
648
      {
649
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
650
      }
651
    else
652
      {
653
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
654
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
655
      }
656

    
657
    float rowFloat = rnd.nextFloat();
658

    
659
    for(int row=0; row<mRowChances.length; row++)
660
      {
661
      if( rowFloat<=mRowChances[row] )
662
        {
663
        scramble[num][1] = row;
664
        break;
665
        }
666
      }
667

    
668
    switch( rnd.nextInt(2) )
669
      {
670
      case 0: scramble[num][2] = -1; break;
671
      case 1: scramble[num][2] =  1; break;
672
      }
673
    }
674

    
675
///////////////////////////////////////////////////////////////////////////////////////////////////
676
// The Skewb is solved if and only if:
677
//
678
// 1) all of its corner and edge cubits are rotated with the same quat
679
// 2) all its face cubits are rotated with the same quat like the corner ones,
680
//    and optionally they also might be upside down.
681
//
682
// i.e.
683
// cubits [ 8] and [ 9] - might be extra QUAT[1]
684
// cubits [10] and [11] - might be extra QUAT[2]
685
// cubits [12] and [13] - might be extra QUAT[3]
686

    
687
  public boolean isSolved()
688
    {
689
    int q = CUBITS[0].mQuatIndex;
690

    
691
    int numLayers      = getNumLayers();
692
    int numCorners     = getNumCorners();
693
    int numEdges       = getNumEdges(numLayers);
694
    int cornersAndEdges= numCorners + numEdges;
695
    int centersPerFace = getNumCentersPerFace(numLayers);
696
    int cubit, q1=q;
697

    
698
    for(cubit=0; cubit<cornersAndEdges; cubit++)
699
      {
700
      if( CUBITS[cubit].mQuatIndex != q ) return false;
701
      }
702

    
703
    for(int face=0; face<6; face++)
704
      {
705
      if( face%2==0 ) q1 = mulQuat(q, (face/2)+1);
706

    
707
      for(int center=0; center<centersPerFace; center++)
708
        {
709
        if( CUBITS[cubit].mQuatIndex != q && CUBITS[cubit].mQuatIndex != q1 ) return false;
710
        cubit++;
711
        }
712
      }
713

    
714
    return true;
715
    }
716

    
717
///////////////////////////////////////////////////////////////////////////////////////////////////
718
// only needed for solvers - there are no Skewb solvers ATM)
719

    
720
  public String retObjectString()
721
    {
722
    return "";
723
    }
724

    
725
///////////////////////////////////////////////////////////////////////////////////////////////////
726

    
727
  public int getObjectName(int numLayers)
728
    {
729
    switch(numLayers)
730
      {
731
      case 2: return R.string.skew2;
732
      case 3: return R.string.skew3;
733
      }
734
    return R.string.skew2;
735
    }
736

    
737
///////////////////////////////////////////////////////////////////////////////////////////////////
738

    
739
  public int getInventor(int numLayers)
740
    {
741
    switch(numLayers)
742
      {
743
      case 2: return R.string.skew2_inventor;
744
      case 3: return R.string.skew3_inventor;
745
      }
746
    return R.string.skew2_inventor;
747
    }
748

    
749
///////////////////////////////////////////////////////////////////////////////////////////////////
750

    
751
  public int getComplexity(int numLayers)
752
    {
753
    switch(numLayers)
754
      {
755
      case 2: return 5;
756
      case 3: return 9;
757
      }
758
    return 5;
759
    }
760
}
(33-33/33)