Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySkewb.java @ 7d8cc029

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

    
171
  private static final float[][] STICKERS = new float[][]
172
          {
173
             { -0.5f,   0.25f, 0.25f,  -0.5f, 0.25f, 0.25f  },
174
             {  0.0f, -1.0f/3, 0.50f, 1.0f/6, -0.5f, 1.0f/6 },
175
             { -0.5f,    0.0f, 0.00f,  -0.5f, 0.50f, 0.0f, 0.0f, 0.5f }
176
          };
177

    
178
  private static MeshBase[] mMeshes;
179

    
180
///////////////////////////////////////////////////////////////////////////////////////////////////
181

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

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189

    
190
  private int getNumCorners()
191
    {
192
    return 8;
193
    }
194

    
195
///////////////////////////////////////////////////////////////////////////////////////////////////
196

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

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

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

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

    
211
  float getScreenRatio()
212
    {
213
    return 1.0f;
214
    }
215

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

    
218
  Static4D[] getQuats()
219
    {
220
    return QUATS;
221
    }
222

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

    
225
  int getNumFaces()
226
    {
227
    return FACE_COLORS.length;
228
    }
229

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

    
232
  boolean shouldResetTextureMaps()
233
    {
234
    return false;
235
    }
236

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

    
239
  int getNumStickerTypes(int numLayers)
240
    {
241
    return 3;
242
    }
243

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

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

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

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266

    
267
  int getNumCubitFaces()
268
    {
269
    return FACES_PER_CUBIT;
270
    }
271

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

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

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

    
284
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
285

    
286
    /// CORNERS //////////////////////////////////////////////
287

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

    
297
    /// EDGES ///////////////////////////////////////////////
298

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

    
315
    int index=8;
316

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

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

    
329
    /// CENTERS //////////////////////////////////////////////
330

    
331
    final float X= -1000.0f;
332
    final float Y= -1001.0f;
333

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

    
344
    float x,y, cen0, cen1, cen2;
345

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

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

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

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

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

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

    
372
      x = (3-numLayers)*0.5f;
373

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

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

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

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

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

    
397
    return CENTERS;
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

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

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

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

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

    
456
    return null;
457
    }
458

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460

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

    
470
    MeshBase mesh;
471

    
472
    int numCorners = getNumCorners();
473
    int numEdges   = getNumEdges(numLayers);
474

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

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

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

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

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

    
554
    return mesh;
555
    }
556

    
557
///////////////////////////////////////////////////////////////////////////////////////////////////
558

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

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

    
580
///////////////////////////////////////////////////////////////////////////////////////////////////
581

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

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

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

    
599
///////////////////////////////////////////////////////////////////////////////////////////////////
600

    
601
  float returnMultiplier()
602
    {
603
    return 2.0f;
604
    }
605

    
606
///////////////////////////////////////////////////////////////////////////////////////////////////
607

    
608
  float[] getRowChances(int numLayers)
609
    {
610
    float[] chances = new float[numLayers];
611

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

    
627
    return chances;
628
    }
629

    
630
///////////////////////////////////////////////////////////////////////////////////////////////////
631
// PUBLIC API
632

    
633
  public Static3D[] getRotationAxis()
634
    {
635
    return ROT_AXIS;
636
    }
637

    
638
///////////////////////////////////////////////////////////////////////////////////////////////////
639

    
640
  public int getBasicAngle()
641
    {
642
    return 3;
643
    }
644

    
645
///////////////////////////////////////////////////////////////////////////////////////////////////
646

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

    
659
    float rowFloat = rnd.nextFloat();
660

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

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

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

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

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

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

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

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

    
716
    return true;
717
    }
718

    
719
///////////////////////////////////////////////////////////////////////////////////////////////////
720
// only needed for solvers - there are no Skewb solvers ATM)
721

    
722
  public String retObjectString()
723
    {
724
    return "";
725
    }
726

    
727
///////////////////////////////////////////////////////////////////////////////////////////////////
728

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

    
739
///////////////////////////////////////////////////////////////////////////////////////////////////
740

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

    
751
///////////////////////////////////////////////////////////////////////////////////////////////////
752

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