Project

General

Profile

Download (20.8 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / main / TwistyObjectSolved.java @ 9c7d220a

1 5618c5a9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10
package org.distorted.objectlib.main;
11
12 aacf5e27 Leszek Koltunski
import org.distorted.library.helpers.QuatHelper;
13 5618c5a9 Leszek Koltunski
import org.distorted.library.type.Static3D;
14
import org.distorted.library.type.Static4D;
15 adb5b717 leszek
import org.distorted.objectlib.helpers.ObjectShape;
16
17
import java.util.ArrayList;
18 5618c5a9 Leszek Koltunski
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20
21
class TwistyObjectSolved
22
  {
23
  private final TwistyObject mParent;
24
  private final Static4D[] mObjectQuats;
25
  private final int mNumQuats;
26
  private final float[][] mOrigPos;
27
  private final int mNumCubits;
28
  private final int mFunctionIndex;
29
  private final int[] mTmpQuats;
30
31 be95dbf5 Leszek Koltunski
  private int[][] mSolvedQuats;
32 5618c5a9 Leszek Koltunski
  private int[][] mQuatMult;
33
  private int[] mFaceMap;
34
  private int[][] mScramble;
35
  private int[] mColors;
36
37 f80b9473 leszek
  private static class SurfaceInfo
38
    {
39
    float[] surface;
40
    int[] indices;
41
42
    SurfaceInfo(float[] s) { surface = s; }
43
    void setIndices(int[] i) { indices = i; }
44
    };
45
46 adb5b717 leszek
  private int[][] mSurfaceTable;
47 074a0284 leszek
  private int[][] mFaceColorTable;
48
  private int[][] mCubitFaceToSurfaceMap;
49
  private int[][] mCubitFaceColor;
50 adb5b717 leszek
51 5618c5a9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
52
// remember about the double cover or unit quaternions!
53
54
  private int mulQuat(int q1, int q2)
55
    {
56
    Static4D result = QuatHelper.quatMultiply(mObjectQuats[q1],mObjectQuats[q2]);
57
58
    float rX = result.get0();
59
    float rY = result.get1();
60
    float rZ = result.get2();
61
    float rW = result.get3();
62
63
    final float MAX_ERROR = 0.1f;
64
    float dX,dY,dZ,dW;
65
66
    for(int i=0; i<mNumQuats; i++)
67
      {
68
      dX = mObjectQuats[i].get0() - rX;
69
      dY = mObjectQuats[i].get1() - rY;
70
      dZ = mObjectQuats[i].get2() - rZ;
71
      dW = mObjectQuats[i].get3() - rW;
72
73
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
74
          dY<MAX_ERROR && dY>-MAX_ERROR &&
75
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
76
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
77
78
      dX = mObjectQuats[i].get0() + rX;
79
      dY = mObjectQuats[i].get1() + rY;
80
      dZ = mObjectQuats[i].get2() + rZ;
81
      dW = mObjectQuats[i].get3() + rW;
82
83
      if( dX<MAX_ERROR && dX>-MAX_ERROR &&
84
          dY<MAX_ERROR && dY>-MAX_ERROR &&
85
          dZ<MAX_ERROR && dZ>-MAX_ERROR &&
86
          dW<MAX_ERROR && dW>-MAX_ERROR  ) return i;
87
      }
88
89
    return -1;
90
    }
91
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93
94
  private int getMultQuat(int index1, int index2)
95
    {
96
    if( mQuatMult==null )
97
      {
98
      mQuatMult = new int[mNumQuats][mNumQuats];
99
100
      for(int i=0; i<mNumQuats; i++)
101
        for(int j=0; j<mNumQuats; j++) mQuatMult[i][j] = -1;
102
      }
103
104
    if( index1<mNumQuats && index2<mNumQuats )
105
      {
106
      if( mQuatMult[index1][index2]==-1 ) mQuatMult[index1][index2] = mulQuat(index1,index2);
107
      return mQuatMult[index1][index2];
108
      }
109
110
    return -1;
111
    }
112
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
115
  private int computeScramble(int quatNum, int centerNum)
116
    {
117
    float MAXDIFF = 0.01f;
118
    float[] center= mOrigPos[centerNum];
119
    Static4D sc = new Static4D(center[0], center[1], center[2], 1.0f);
120
    Static4D result = QuatHelper.rotateVectorByQuat(sc,mObjectQuats[quatNum]);
121
122
    float x = result.get0();
123
    float y = result.get1();
124
    float z = result.get2();
125
126
    for(int c=0; c<mNumCubits; c++)
127
      {
128
      float[] cent = mOrigPos[c];
129
130
      float qx = cent[0] - x;
131
      float qy = cent[1] - y;
132
      float qz = cent[2] - z;
133
134
      if( qx>-MAXDIFF && qx<MAXDIFF &&
135
          qy>-MAXDIFF && qy<MAXDIFF &&
136
          qz>-MAXDIFF && qz<MAXDIFF  ) return c;
137
      }
138
139
    return -1;
140
    }
141
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143
// This is used to build internal data structures for the generic 'isSolved()'
144
//
145
// if this is an internal cubit (all faces black): return -1
146
// if this is a face cubit (one non-black face): return the color index of the only non-black face.
147
// Color index, i.e. the index into the 'FACE_COLORS' table.
148
// else (edge or corner cubit, more than one non-black face): return -2.
149
150
  private int retCubitSolvedStatus(int cubit, int[] numLayers, int numCubitFaces, int[][] cubitFaceColors)
151
    {
152
    int numNonBlack=0, nonBlackIndex=-1, stiShape, cubColor;
153
    int variant = mParent.getCubitVariant(cubit,numLayers);
154
155
    for(int face=0; face<numCubitFaces; face++)
156
      {
157
      stiShape = mParent.getVariantStickerShape(variant,face);
158
      int numFaces = cubitFaceColors[cubit].length;
159
      cubColor = face<numFaces ? cubitFaceColors[cubit][face] : -1;
160
161
      if( stiShape>=0 && cubColor>=0 )
162
        {
163
        numNonBlack++;
164
        nonBlackIndex = cubColor;
165
        }
166
      }
167
168
    if( numNonBlack==0 ) return -1;
169
    if( numNonBlack>=2 ) return -2;
170
171
    return nonBlackIndex;
172
    }
173
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175
176
  private int[] buildSolvedQuats(Static3D faceAx)
177
    {
178
    final float MAXD = 0.0001f;
179
    float x = faceAx.get0();
180
    float y = faceAx.get1();
181
    float z = faceAx.get2();
182
    float a,dx,dy,dz,qx,qy,qz;
183
    Static4D quat;
184
    int place = 0;
185
186
    for(int q=1; q<mNumQuats; q++)
187
      {
188
      quat = mObjectQuats[q];
189
      qx = quat.get0();
190
      qy = quat.get1();
191
      qz = quat.get2();
192
193
           if( x!=0.0f ) { a = qx/x; }
194
      else if( y!=0.0f ) { a = qy/y; }
195
      else               { a = qz/z; }
196
197
      dx = a*x-qx;
198
      dy = a*y-qy;
199
      dz = a*z-qz;
200
201
      if( dx>-MAXD && dx<MAXD && dy>-MAXD && dy<MAXD && dz>-MAXD && dz<MAXD )
202
        {
203
        mTmpQuats[place++] = q;
204
        }
205
      }
206
207
    if( place!=0 )
208
      {
209
      int[] ret = new int[place];
210
      System.arraycopy(mTmpQuats,0,ret,0,place);
211
      return ret;
212
      }
213
214
    return null;
215
    }
216
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218
// special SolvedQuats for the case where there are no corner of edge cubits.
219
// first row {0} - means there are no corners or edges.
220
// each next defines all cubits of a singe face (numCubits, firstCubit, cubit1,..,cubitN-1, quat0,..., quatM
221
222
  private boolean isSolvedCentersOnly(TwistyObjectCubit[] cubits)
223
    {
224
    int numGroups = mSolvedQuats.length;
225
226
    for(int group=1; group<numGroups; group++)
227
      {
228 1247bb16 Leszek Koltunski
      int[] gq = mSolvedQuats[group];
229
      int numEntries= gq.length;
230
      int numCubits = gq[0];
231
      int firstCubit= gq[1];
232 5618c5a9 Leszek Koltunski
      int firstQuat = cubits[firstCubit].mQuatIndex;
233
234
      for(int cubit=2; cubit<=numCubits; cubit++)
235
        {
236 1247bb16 Leszek Koltunski
        int currCubit= gq[cubit];
237 5618c5a9 Leszek Koltunski
        int currQuat = cubits[currCubit].mQuatIndex;
238
        boolean isGood= (firstQuat==currQuat);
239
240
        for(int q=numCubits+1; !isGood && q<numEntries; q++)
241 1247bb16 Leszek Koltunski
          if( firstQuat == getMultQuat(currQuat,gq[q]) ) isGood = true;
242 5618c5a9 Leszek Koltunski
243
        if( !isGood ) return false;
244
        }
245
      }
246
247
    return true;
248
    }
249
250 adb5b717 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
251
252 f80b9473 leszek
  private int surfaceExists(ArrayList<SurfaceInfo> list, float[] newSurface)
253 adb5b717 leszek
    {
254 f80b9473 leszek
    final float MAX_ERROR = 0.01f;
255
    int size = list.size();
256
    float dnx,dny,dnz,dnw;
257
258
    for(int s=0; s<size; s++)
259
      {
260
      SurfaceInfo si = list.get(s);
261
      float[] surface = si.surface;
262
263
      dnx = newSurface[0] - surface[0];
264
      dny = newSurface[1] - surface[1];
265
      dnz = newSurface[2] - surface[2];
266
      dnw = newSurface[3] - surface[3];
267
268
      if( dnx*dnx + dny*dny + dnz*dnz + dnw*dnw < MAX_ERROR )
269
        {
270
        //android.util.Log.d("D", "1 Surface "+newSurface[0]+" "+newSurface[1]+" "+newSurface[2]+" "+newSurface[3]+" exists already at "+s);
271
272
        return s;
273
        }
274
275
      dnx = newSurface[0] + surface[0];
276
      dny = newSurface[1] + surface[1];
277
      dnz = newSurface[2] + surface[2];
278
      dnw = newSurface[3] + surface[3];
279
280
      if( dnx*dnx + dny*dny + dnz*dnz + dnw*dnw < MAX_ERROR )
281
        {
282
        //android.util.Log.d("D", "2 Surface "+newSurface[0]+" "+newSurface[1]+" "+newSurface[2]+" "+newSurface[3]+" exists already at "+s);
283
284
        return s;
285
        }
286
      }
287
288
    //android.util.Log.d("D", "Surface "+newSurface[0]+" "+newSurface[1]+" "+newSurface[2]+" "+newSurface[3]+" doesnt exist yet");
289 adb5b717 leszek
    return -1;
290
    }
291
292 f80b9473 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
293
294
  private int adjoinNewSurface(ArrayList<SurfaceInfo> list, float[] newSurface)
295
    {
296
    int index = surfaceExists(list,newSurface);
297
    if( index>=0 ) return index;
298
299
    //android.util.Log.d("D", "Adding new surface "+newSurface[0]+" "+newSurface[1]+" "+newSurface[2]+" "+newSurface[3]+" to "+list.size());
300
301
    SurfaceInfo si = new SurfaceInfo(newSurface);
302
    list.add(si);
303
    return list.size()-1;
304
    }
305
306
///////////////////////////////////////////////////////////////////////////////////////////////////
307
308
  private float[] multiplySurface( float[] surface, Static4D quat )
309
    {
310
    float[] ret = new float[4];
311
    QuatHelper.rotateVectorByQuat(ret,surface[0],surface[1],surface[2],0,quat);
312
    ret[3] = surface[3];
313
314
    return ret;
315
    }
316
317 adb5b717 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
318
319
  private void computeSurfaceTable()
320
    {
321
    int[] numLayers = mParent.getNumLayers();
322
    float[][] pos = mParent.getCubitPositions(numLayers);
323
    int numCubits = pos.length;
324
    int numVariants = mParent.getNumCubitVariants(numLayers);
325
    ObjectShape[] shapes = new ObjectShape[numVariants];
326 074a0284 leszek
    mCubitFaceToSurfaceMap = new int[numCubits][];
327
    mCubitFaceColor = new int[numCubits][];
328 adb5b717 leszek
329
    for(int v=0; v<numVariants; v++) shapes[v] = mParent.getObjectShape(v);
330
331 f80b9473 leszek
    ArrayList<SurfaceInfo> tmpSurfaces = new ArrayList<>();
332 adb5b717 leszek
333
    for(int c=0; c<numCubits; c++)
334
      {
335
      int variant = mParent.getCubitVariant(c,numLayers);
336
      ObjectShape s = shapes[variant];
337
      int numFaces = s.getNumFaces();
338 074a0284 leszek
      mCubitFaceColor[c] = new int[numFaces];
339
      mCubitFaceToSurfaceMap[c] = new int[numFaces];
340
      for(int f=0; f<numFaces; f++) mCubitFaceToSurfaceMap[c][f] = -1;
341
342 f80b9473 leszek
      Static4D cubitQuat = mParent.getCubitQuats(c,numLayers);
343
344
      float[] po = pos[c];
345
      int poslen = po.length/3;
346
      float px=0, py=0, pz=0;
347
      for(int p=0; p<poslen; p++)
348
        {
349
        px += po[3*p  ];
350
        py += po[3*p+1];
351
        pz += po[3*p+2];
352
        }
353
      px /= poslen;
354
      py /= poslen;
355
      pz /= poslen;
356
357
      //android.util.Log.e("D", "cubit "+c+" pos "+px+" "+py+" "+pz+" faces: "+numFaces);
358 adb5b717 leszek
359
      for(int f=0; f<numFaces; f++)
360
        {
361 074a0284 leszek
        mCubitFaceColor[c][f] = mParent.getCubitFaceColor(c,f);
362
363 f80b9473 leszek
        if( !mParent.faceIsOuter(c,f) ) continue;
364
365
        //android.util.Log.e("D", "cubit "+c+" face "+f);
366
367
        float[] surface  = new float[4];
368
        float[] rotPoint = new float[4];
369
        float[] normal   = new float[4];
370
        float[] intPoint = new float[3];
371
372
        s.getFacePoint(f,intPoint);
373
        s.getFaceNormal(f,normal);
374
375
        QuatHelper.rotateVectorByQuat(rotPoint,intPoint[0],intPoint[1],intPoint[2],1,cubitQuat);
376
        QuatHelper.rotateVectorByQuat(surface,normal[0],normal[1],normal[2],0,cubitQuat);
377
378
        float x = rotPoint[0] + px;
379
        float y = rotPoint[1] + py;
380
        float z = rotPoint[2] + pz;
381
        surface[3] = x*surface[0] + y*surface[1] + z*surface[2];
382
383
        int index = surfaceExists(tmpSurfaces,surface);
384
385 074a0284 leszek
        if( index>=0 )
386
          {
387
          mCubitFaceToSurfaceMap[c][f] = index;
388
          }
389
        else
390 f80b9473 leszek
          {
391
          SurfaceInfo si = new SurfaceInfo(surface);
392
          tmpSurfaces.add(si);
393 074a0284 leszek
          mCubitFaceToSurfaceMap[c][f] = tmpSurfaces.size()-1;
394 f80b9473 leszek
395
          //android.util.Log.e("D", "added surface "+tmpSurfaces.size()+" cubit "+c+" face "+f+" variant "+variant);
396
397
          int[] indices = new int[mNumQuats];
398 adb5b717 leszek
399
          for(int q=0; q<mNumQuats; q++)
400
            {
401 f80b9473 leszek
            float[] ts = multiplySurface(surface, mObjectQuats[q]);
402
            int ind = adjoinNewSurface(tmpSurfaces,ts);
403
/*
404
            if( ind==6 || ind==5 )
405
              {
406
              android.util.Log.e("D","SURFACE "+ind+": "+ts[0]+" "+ts[1]+" "+ts[2]+" "+ts[3] );
407
              }
408
*/
409
            indices[q] = ind;
410 adb5b717 leszek
            }
411 f80b9473 leszek
412
          si.setIndices(indices);
413
          }
414
        }
415
      }
416
417
    int size = tmpSurfaces.size();
418
    mSurfaceTable = new int[size][];
419
420
    for(int s=0; s<size; s++)
421
      {
422
      SurfaceInfo si = tmpSurfaces.get(s);
423
424
      if( si.indices == null )
425
        {
426
        float[] surface = si.surface;
427
        int[] indices = new int[mNumQuats];
428
429
        for(int q=0; q<mNumQuats; q++)
430
          {
431
          float[] ts = multiplySurface(surface, mObjectQuats[q]);
432
          int ind = adjoinNewSurface(tmpSurfaces,ts);
433
          indices[q] = ind;
434
          }
435
436
        si.setIndices(indices);
437 adb5b717 leszek
        }
438 f80b9473 leszek
439
      mSurfaceTable[s] = si.indices;
440 adb5b717 leszek
      }
441 7cb1dc53 leszek
    }
442
443
///////////////////////////////////////////////////////////////////////////////////////////////////
444 adb5b717 leszek
445 7cb1dc53 leszek
  private void debugSurfaceTable(ArrayList<SurfaceInfo> surfaces)
446
    {
447
    int size = surfaces.size();
448 f80b9473 leszek
    android.util.Log.e("D", "COMPUTE size: "+size);
449
450
    for(int s=0; s<size; s++)
451
      {
452
      StringBuilder sb = new StringBuilder();
453
      sb.append("surface ");
454
      sb.append(s);
455
      sb.append(" : ");
456
457 7cb1dc53 leszek
      SurfaceInfo si = surfaces.get(s);
458 f80b9473 leszek
      float[] sur = si.surface;
459
460
      sb.append(sur[0]);
461
      sb.append(' ');
462
      sb.append(sur[1]);
463
      sb.append(' ');
464
      sb.append(sur[2]);
465
      sb.append(' ');
466
      sb.append(sur[3]);
467
      sb.append(" indices:");
468
469
      for(int q=0; q<mNumQuats; q++)
470
        {
471
        sb.append(' ');
472
        sb.append(mSurfaceTable[s][q]);
473
        }
474
475
      android.util.Log.d("D", sb.toString() );
476
      }
477 adb5b717 leszek
    }
478
479 5618c5a9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
480
481
  private boolean isSolved0(TwistyObjectCubit[] cubits)
482
    {
483
    if( mSolvedQuats[0][0]==0 ) return isSolvedCentersOnly(cubits);
484
485
    for( int[] solvedQuat : mSolvedQuats )
486
      {
487
      int numCubits = solvedQuat[0];
488
      int firstCubit= solvedQuat[1];
489
      int quat = cubits[firstCubit].mQuatIndex;
490
491
      for( int cubit=2; cubit<=numCubits; cubit++ )
492
        {
493
        int c = solvedQuat[cubit];
494
        if( quat != cubits[c].mQuatIndex ) return false;
495
        }
496
      }
497
498
    int cubit= mSolvedQuats[0][1];
499
    int quat0= cubits[cubit].mQuatIndex;
500
    int numGroups = mSolvedQuats.length;
501
502
    for(int group=1; group<numGroups; group++)
503
      {
504
      int firstCubit= mSolvedQuats[group][1];
505
      int currQuat  = cubits[firstCubit].mQuatIndex;
506
507
      if( quat0==currQuat ) continue;
508
509
      boolean isGood= false;
510
      int numEntries= mSolvedQuats[group].length;
511
      int numCubits = mSolvedQuats[group][0];
512
513
      for(int q=numCubits+1; q<numEntries; q++)
514
        {
515
        int quat = mSolvedQuats[group][q];
516
517
        if( quat0 == getMultQuat(currQuat,quat) )
518
          {
519
          isGood = true;
520
          break;
521
          }
522
        }
523
524
      if( !isGood ) return false;
525
      }
526
527
    return true;
528
    }
529
530
///////////////////////////////////////////////////////////////////////////////////////////////////
531
// Dino4 uses this. It is solved if and only if groups of cubits
532
// (0,3,7), (1,2,5), (4,8,9), (6,10,11)
533
// or
534
// (0,1,4), (2,3,6), (5,9,10), (7,8,11)
535
// are all the same color.
536
537
  private boolean isSolved1(TwistyObjectCubit[] cubits)
538
    {
539
    if( mScramble==null )
540
      {
541
      mScramble = new int[mNumQuats][mNumCubits];
542
      mColors   = new int[mNumCubits];
543
544
      for(int q=0; q<mNumQuats; q++)
545
        for(int c=0; c<mNumCubits; c++) mScramble[q][c] = computeScramble(q,c);
546
      }
547
548
    if( mFaceMap==null )
549
      {
550
      mFaceMap = new int[] { 4, 2, 2, 4, 0, 2, 1, 4, 0, 0, 1, 1 };
551
      }
552
553
    for(int c=0; c<mNumCubits; c++)
554
      {
555
      int index = mScramble[cubits[c].mQuatIndex][c];
556
      mColors[index] = mFaceMap[c];
557
      }
558
559
    if( mColors[0]==mColors[3] && mColors[0]==mColors[7] &&
560
        mColors[1]==mColors[2] && mColors[1]==mColors[5] &&
561
        mColors[4]==mColors[8] && mColors[4]==mColors[9]  ) return true;
562
563
    if( mColors[0]==mColors[1] && mColors[0]==mColors[4] &&
564
        mColors[2]==mColors[3] && mColors[2]==mColors[6] &&
565
        mColors[5]==mColors[9] && mColors[5]==mColors[10] ) return true;
566
567
    return false;
568
    }
569
570 074a0284 leszek
///////////////////////////////////////////////////////////////////////////////////////////////////
571
572
  private int surfaceColor(int filled, int surface)
573
    {
574
    for(int s=0; s<filled; s++)
575
      if( mFaceColorTable[s][0] == surface ) return mFaceColorTable[s][1];
576
577
    return -1;
578
    }
579
580
///////////////////////////////////////////////////////////////////////////////////////////////////
581
582
  private boolean isSolved2(TwistyObjectCubit[] cubits)
583
    {
584
    int filled = 0;
585
    int max = mFaceColorTable.length;
586
587
    for(int c=0; c<mNumCubits; c++)
588
      {
589
      int numFaces = mCubitFaceToSurfaceMap[c].length;
590
      int quat = cubits[c].mQuatIndex;
591
592
      for(int f=0; f<numFaces; f++)
593
        {
594
        int initSurface = mCubitFaceToSurfaceMap[c][f];
595
596
        if( initSurface>=0 )
597
          {
598
          int currSurface = mSurfaceTable[initSurface][quat];
599
          int currColor = mCubitFaceColor[c][f];
600
          int prevColor = surfaceColor(filled,currSurface);
601
602
          if( prevColor<0 )
603
            {
604
            if( filled>=max ) return false;
605
            mFaceColorTable[filled][0] = currSurface;
606
            mFaceColorTable[filled][1] = currColor;
607
            prevColor = currColor;
608
            filled++;
609
            }
610
611
          if( prevColor!=currColor ) return false;
612
          }
613
        }
614
      }
615
616
    return true;
617
    }
618
619 5618c5a9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
620
// Called from TwistyObject
621
///////////////////////////////////////////////////////////////////////////////////////////////////
622
623
  int[][] getSolvedQuats(int[] numLayers, int numCubitFaces, int[][] cubitFaceColors)
624
    {
625
    int[] groups = new int[mNumCubits];
626
    int numGroups = 1;
627
    int numFirst  = 0;
628
629
    for(int cubit=0; cubit<mNumCubits; cubit++)
630
      {
631
      groups[cubit] = retCubitSolvedStatus(cubit,numLayers,numCubitFaces,cubitFaceColors);
632
      if( groups[cubit]>=0 ) numGroups++;
633
      else                   numFirst++;
634
      }
635
636
    int firstIndex = 1;
637
    int groupIndex = 1;
638
    int[][] solvedQuats = new int[numGroups][];
639
    solvedQuats[0] = new int[1+numFirst];
640
    solvedQuats[0][0] = numFirst;
641
    Static3D[] axis = mParent.getFaceAxis();
642
643
    for(int cubit=0; cubit<mNumCubits; cubit++)
644
      {
645
      int group = groups[cubit];
646
647
      if( group<0 )
648
        {
649
        solvedQuats[0][firstIndex] = cubit;
650
        firstIndex++;
651
        }
652
      else
653
        {
654
        int[] quats = buildSolvedQuats(axis[group]);
655
        int len = quats==null ? 0 : quats.length;
656
        solvedQuats[groupIndex] = new int[2+len];
657
        solvedQuats[groupIndex][0] = 1;
658
        solvedQuats[groupIndex][1] = cubit;
659
        for(int i=0; i<len; i++) solvedQuats[groupIndex][i+2] = quats[i];
660
        groupIndex++;
661
        }
662
      }
663
/*
664
    String dbg = "SOLVED GROUPS:\n";
665
666
    for(int g=0; g<numGroups; g++)
667
      {
668
      int len = solvedQuats[g].length;
669
      for(int i=0; i<len; i++) dbg += (" "+solvedQuats[g][i]);
670
      dbg+="\n";
671
      }
672
673
    android.util.Log.e("D", dbg);
674
*/
675
    return solvedQuats;
676
    }
677
678 be95dbf5 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
679
680
  void setupSolvedQuats(int[][] quats)
681
    {
682
    mSolvedQuats = quats;
683
    }
684
685 5618c5a9 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
686
687
  TwistyObjectSolved(TwistyObject parent, float[][] orig, int index)
688
    {
689
    mParent = parent;
690
    mObjectQuats = mParent.mObjectQuats;
691
    mNumQuats = mObjectQuats.length;
692
    mOrigPos = orig;
693
    mNumCubits = orig.length;
694
    mFunctionIndex = index;
695
    mTmpQuats = new int[mNumQuats];
696 adb5b717 leszek
697 074a0284 leszek
    if( mFunctionIndex==2 )
698
      {
699
      computeSurfaceTable();
700
      int numFaces = parent.getNumFaces();
701
      mFaceColorTable = new int[numFaces][2];
702
      }
703 5618c5a9 Leszek Koltunski
    }
704
705
///////////////////////////////////////////////////////////////////////////////////////////////////
706
707
  boolean isSolved(TwistyObjectCubit[] cubits)
708
    {
709 074a0284 leszek
    switch(mFunctionIndex)
710
      {
711
      case 0: return isSolved0(cubits);
712
      case 1: return isSolved1(cubits);
713
      case 2: return isSolved2(cubits);
714
      }
715 5618c5a9 Leszek Koltunski
716
    return false;
717
    }
718
  }