Project

General

Profile

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

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

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
import org.distorted.main.RubikSurfaceView;
37

    
38
import java.util.Random;
39

    
40
///////////////////////////////////////////////////////////////////////////////////////////////////
41

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

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

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

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

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

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

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

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

    
118
  private static final double[][] VERTICES_CORNER = new double[][]
119
          {
120
             // TODO
121
          };
122

    
123
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
124
          {
125
             // TODO
126
          };
127

    
128
  private static final double[][] VERTICES_EDGE = new double[][]
129
          {
130
             {-0.5, 0.0, 0.0},
131
             { 0.5, 0.0, 0.0},
132
             { 0.0,-0.5, 0.0},
133
             { 0.0, 0.0,-0.5}
134
          };
135

    
136
  private static final int[][] VERT_INDEXES_EDGE = new int[][]
137
          {
138
             {2,1,0},   // counterclockwise!
139
             {3,0,1},
140
             {2,3,1},
141
             {3,2,0},
142
          };
143

    
144
  private static final double[][] VERTICES_FACE = new double[][]
145
          {
146
             // TODO
147
          };
148

    
149
  private static final int[][] VERT_INDEXES_FACE = new int[][]
150
          {
151
             // TODO
152
          };
153

    
154
  private static MeshBase[] mMeshes;
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
  TwistySkewb(int size, Static4D quat, DistortedTexture texture,
159
              MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
160
    {
161
    super(size, 2*size-2, quat, texture, mesh, effects, moves, ObjectList.SKEW, res, scrWidth);
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  double[][] getVertices(int cubitType)
167
    {
168
    if( cubitType==0 ) return VERTICES_CORNER;
169
    if( cubitType==1 ) return VERTICES_EDGE;
170
    if( cubitType==2 ) return VERTICES_FACE;
171
    return null;
172
    }
173

    
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

    
176
  int[][] getVertIndexes(int cubitType)
177
    {
178
    if( cubitType==0 ) return VERT_INDEXES_CORNER;
179
    if( cubitType==1 ) return VERT_INDEXES_EDGE;
180
    if( cubitType==2 ) return VERT_INDEXES_FACE;
181
    return null;
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  int getNumCubitTypes(int numLayers)
187
    {
188
    return numLayers==2 ? 2 : 3;
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
  private int getNumCorners()
194
    {
195
    return 8;
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

    
200
  private int getNumEdges(int layers)
201
    {
202
    return (layers-2)*12;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  private int getNumCentersPerFace(int layers)
208
    {
209
    return ((layers-2)*(layers-2) + (layers-1)*(layers-1));
210
    }
211

    
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213

    
214
  float getScreenRatio()
215
    {
216
    return 1.0f;
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

    
221
  Static4D[] getQuats()
222
    {
223
    return QUATS;
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  int getNumFaces()
229
    {
230
    return FACE_COLORS.length;
231
    }
232

    
233
///////////////////////////////////////////////////////////////////////////////////////////////////
234

    
235
  boolean shouldResetTextureMaps()
236
    {
237
    return false;
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241

    
242
  int getNumStickerTypes(int numLayers)
243
    {
244
    return 3;
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248

    
249
  float[] getCuts(int numLayers)
250
    {
251
    float[] cuts = new float[numLayers-1];
252

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

    
268
///////////////////////////////////////////////////////////////////////////////////////////////////
269

    
270
  int getNumCubitFaces()
271
    {
272
    return FACES_PER_CUBIT;
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276

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

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

    
287
    final float[][] CENTERS = new float[numCorners+numEdges+numCenters][];
288

    
289
    /// CORNERS //////////////////////////////////////////////
290

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

    
300
    /// EDGES ///////////////////////////////////////////////
301

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

    
318
    int index=8;
319

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

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

    
332
    /// CENTERS //////////////////////////////////////////////
333

    
334
    final float X= -1000.0f;
335
    final float Y= -1001.0f;
336

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

    
347
    float x,y, cen0, cen1, cen2;
348

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

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

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

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

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

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

    
375
      x = (3-numLayers)*0.5f;
376

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

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

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

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

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

    
400
    return CENTERS;
401
    }
402

    
403
///////////////////////////////////////////////////////////////////////////////////////////////////
404

    
405
  private Static4D getQuat(int cubit, int numLayers)
406
    {
407
    int numCorners = getNumCorners();
408
    int numEdges   = getNumEdges(numLayers);
409

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

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

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

    
459
    return null;
460
    }
461

    
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

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

    
473
    MeshBase mesh;
474

    
475
    int numCorners = getNumCorners();
476
    int numEdges   = getNumEdges(numLayers);
477

    
478
    if( cubit<numCorners )
479
      {
480
      if( mMeshes[0]==null )
481
        {
482
        mMeshes[0] = FactoryCubit.getInstance().createSkewbCornerMesh();
483
        }
484
      mesh = mMeshes[0].copy(true);
485
      }
486
    else if( cubit<numCorners+numEdges )
487
      {
488
      if( mMeshes[1]==null )
489
        {
490
        float[][] bands= new float[][]
491
          {
492
             {0.035f,30,0.16f,0.8f,7,2,5},
493
             {0.020f,45,0.16f,0.2f,3,1,2}
494
          };
495
        int[] bandIndexes   = new int[] { 0,0,1,1 };
496
        float[][] corners   = new float[][] { {0.07f,0.20f}, {0.02f,0.30f} };
497
        int[] cornerIndexes = new int[] { 0,0,1,1 };
498
        float[][] centers   = new float[][] { {0.0f, -0.25f, -0.25f} };
499
        int[] centerIndexes = new int[] { 0,0,0,0 };
500

    
501
        FactoryCubit factory = FactoryCubit.getInstance();
502
        factory.createNewFaceTransform(VERTICES_EDGE,VERT_INDEXES_EDGE);
503
        mMeshes[1] = factory.createRoundedSolid(VERTICES_EDGE, VERT_INDEXES_EDGE,
504
                                                bands, bandIndexes,
505
                                                corners, cornerIndexes,
506
                                                centers, centerIndexes,
507
                                                getNumCubitFaces() );
508
        }
509
      mesh = mMeshes[1].copy(true);
510
      }
511
    else
512
      {
513
      if( mMeshes[2]==null )
514
        {
515
        mMeshes[2] = FactoryCubit.getInstance().createSkewbFaceMesh();
516
        }
517
      mesh = mMeshes[2].copy(true);
518
      }
519

    
520
    MatrixEffectQuaternion quat = new MatrixEffectQuaternion( getQuat(cubit,numLayers), new Static3D(0,0,0) );
521
    mesh.apply(quat,0xffffffff,0);
522

    
523
    return mesh;
524
    }
525

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

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

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

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

    
551
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top)
552
    {
553
    int COLORS = FACE_COLORS.length;
554
    float R,S;
555
    float[] vertices;
556

    
557
    if( face<COLORS )
558
      {
559
      float E = 0.5f;
560
      R = 0.023f;
561
      S = 0.035f;
562
      vertices = new float[] { -E+E/4,E/4, E/4,-E+E/4, E/4,E/4};
563
      }
564
    else if( face<2*COLORS )
565
      {
566
      float E = 0.5f;
567
      R = 0.025f;
568
      S = 0.05f;
569
      vertices = new float[] { -E,E/3, 0,-2*E/3, +E,E/3 };
570
      }
571
    else
572
      {
573
      float E = SQ2/4;
574
      R = 0.055f;
575
      S = 0.035f;
576
      vertices = new float[] { -E,-E, +E,-E, +E,+E, -E,+E };
577
      }
578

    
579
    FactorySticker factory = FactorySticker.getInstance();
580
    factory.drawRoundedPolygon(canvas, paint, left, top, vertices, S, FACE_COLORS[face%COLORS], R);
581
    }
582

    
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584

    
585
  float returnMultiplier()
586
    {
587
    return 2.0f;
588
    }
589

    
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591

    
592
  float[] getRowChances(int numLayers)
593
    {
594
    float[] chances = new float[numLayers];
595

    
596
    switch(numLayers)
597
      {
598
      case 2: chances[0] = 0.5f;
599
              chances[1] = 1.0f;
600
              break;
601
      case 3: chances[0] = 0.5f;
602
              chances[1] = 0.5f;
603
              chances[2] = 1.0f;
604
              break;
605
      default:for(int i=0; i<numLayers; i++)
606
                {
607
                chances[i] = (float)(i+1)/numLayers;
608
                }
609
      }
610

    
611
    return chances;
612
    }
613

    
614
///////////////////////////////////////////////////////////////////////////////////////////////////
615
// PUBLIC API
616

    
617
  public Static3D[] getRotationAxis()
618
    {
619
    return ROT_AXIS;
620
    }
621

    
622
///////////////////////////////////////////////////////////////////////////////////////////////////
623

    
624
  public int getBasicAngle()
625
    {
626
    return 3;
627
    }
628

    
629
///////////////////////////////////////////////////////////////////////////////////////////////////
630

    
631
  public void randomizeNewScramble(int[][] scramble, Random rnd, int num)
632
    {
633
    if( num==0 )
634
      {
635
      scramble[num][0] = rnd.nextInt(ROTATION_AXIS.length);
636
      }
637
    else
638
      {
639
      int newVector = rnd.nextInt(ROTATION_AXIS.length-1);
640
      scramble[num][0] = (newVector>=scramble[num-1][0] ? newVector+1 : newVector);
641
      }
642

    
643
    float rowFloat = rnd.nextFloat();
644

    
645
    for(int row=0; row<mRowChances.length; row++)
646
      {
647
      if( rowFloat<=mRowChances[row] )
648
        {
649
        scramble[num][1] = row;
650
        break;
651
        }
652
      }
653

    
654
    switch( rnd.nextInt(2) )
655
      {
656
      case 0: scramble[num][2] = -1; break;
657
      case 1: scramble[num][2] =  1; break;
658
      }
659
    }
660

    
661
///////////////////////////////////////////////////////////////////////////////////////////////////
662
// remember about the double cover or unit quaternions!
663

    
664
  private int mulQuat(int q1, int q2)
665
    {
666
    Static4D result = RubikSurfaceView.quatMultiply(QUATS[q1],QUATS[q2]);
667

    
668
    float rX = result.get0();
669
    float rY = result.get1();
670
    float rZ = result.get2();
671
    float rW = result.get3();
672

    
673
    final float MAX_ERROR = 0.1f;
674
    float dX,dY,dZ,dW;
675

    
676
    for(int i=0; i<QUATS.length; i++)
677
      {
678
      dX = QUATS[i].get0() - rX;
679
      dY = QUATS[i].get1() - rY;
680
      dZ = QUATS[i].get2() - rZ;
681
      dW = QUATS[i].get3() - rW;
682

    
683
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
684
          dY<MAX_ERROR && dY>-MAX_ERROR &&
685
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
686
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
687

    
688
      dX = QUATS[i].get0() + rX;
689
      dY = QUATS[i].get1() + rY;
690
      dZ = QUATS[i].get2() + rZ;
691
      dW = QUATS[i].get3() + rW;
692

    
693
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
694
          dY<MAX_ERROR && dY>-MAX_ERROR &&
695
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
696
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
697
      }
698

    
699
    return -1;
700
    }
701

    
702
///////////////////////////////////////////////////////////////////////////////////////////////////
703
// The Skewb is solved if and only if:
704
//
705
// 1) all of its corner and edge cubits are rotated with the same quat
706
// 2) all its face cubits are rotated with the same quat like the corner ones,
707
//    and optionally they also might be upside down.
708
//
709
// i.e.
710
// cubits [ 8] and [ 9] - might be extra QUAT[1]
711
// cubits [10] and [11] - might be extra QUAT[2]
712
// cubits [12] and [13] - might be extra QUAT[3]
713

    
714
  public boolean isSolved()
715
    {
716
    int q = CUBITS[0].mQuatIndex;
717

    
718
    int numLayers      = getNumLayers();
719
    int numCorners     = getNumCorners();
720
    int numEdges       = getNumEdges(numLayers);
721
    int cornersAndEdges= numCorners + numEdges;
722
    int centersPerFace = getNumCentersPerFace(numLayers);
723
    int cubit, q1=q;
724

    
725
    for(cubit=0; cubit<cornersAndEdges; cubit++)
726
      {
727
      if( CUBITS[cubit].mQuatIndex != q ) return false;
728
      }
729

    
730
    for(int face=0; face<6; face++)
731
      {
732
      if( face%2==0 ) q1 = mulQuat(q, (face/2)+1);
733

    
734
      for(int center=0; center<centersPerFace; center++)
735
        {
736
        if( CUBITS[cubit].mQuatIndex != q && CUBITS[cubit].mQuatIndex != q1 ) return false;
737
        cubit++;
738
        }
739
      }
740

    
741
    return true;
742
    }
743

    
744
///////////////////////////////////////////////////////////////////////////////////////////////////
745
// only needed for solvers - there are no Skewb solvers ATM)
746

    
747
  public String retObjectString()
748
    {
749
    return "";
750
    }
751

    
752
///////////////////////////////////////////////////////////////////////////////////////////////////
753

    
754
  public int getObjectName(int numLayers)
755
    {
756
    switch(numLayers)
757
      {
758
      case 2: return R.string.skew2;
759
      case 3: return R.string.skew3;
760
      }
761
    return R.string.skew2;
762
    }
763

    
764
///////////////////////////////////////////////////////////////////////////////////////////////////
765

    
766
  public int getInventor(int numLayers)
767
    {
768
    switch(numLayers)
769
      {
770
      case 2: return R.string.skew2_inventor;
771
      case 3: return R.string.skew3_inventor;
772
      }
773
    return R.string.skew2_inventor;
774
    }
775

    
776
///////////////////////////////////////////////////////////////////////////////////////////////////
777

    
778
  public int getComplexity(int numLayers)
779
    {
780
    switch(numLayers)
781
      {
782
      case 2: return 5;
783
      case 3: return 9;
784
      }
785
    return 5;
786
    }
787
}
(33-33/33)