Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikCube.java @ 1576f41c

1 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2019 Leszek Koltunski                                                               //
3
//                                                                                               //
4 fdec60a3 Leszek Koltunski
// This file is part of Magic Cube.                                                              //
5 0c52af30 Leszek Koltunski
//                                                                                               //
6 fdec60a3 Leszek Koltunski
// Magic Cube is free software: you can redistribute it and/or modify                            //
7 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// Magic Cube is distributed in the hope that it will be useful,                                 //
12 0c52af30 Leszek Koltunski
// 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 fdec60a3 Leszek Koltunski
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 1f9772f3 Leszek Koltunski
package org.distorted.objects;
21 0c52af30 Leszek Koltunski
22 ccf9fec5 Leszek Koltunski
import android.content.res.Resources;
23 0c52af30 Leszek Koltunski
import android.graphics.Canvas;
24
import android.graphics.Paint;
25
26 49595e4b Leszek Koltunski
import com.google.firebase.crashlytics.FirebaseCrashlytics;
27
28 14bd7976 Leszek Koltunski
import org.distorted.library.effect.VertexEffectDeform;
29 40ab026e Leszek Koltunski
import org.distorted.library.effect.VertexEffectMove;
30
import org.distorted.library.effect.VertexEffectRotate;
31 0c52af30 Leszek Koltunski
import org.distorted.library.main.DistortedEffects;
32
import org.distorted.library.main.DistortedTexture;
33 b32444ee Leszek Koltunski
import org.distorted.library.mesh.MeshBase;
34 411c6285 Leszek Koltunski
import org.distorted.library.mesh.MeshJoined;
35 c0b37c89 Leszek Koltunski
import org.distorted.library.mesh.MeshPolygon;
36 efa8aa48 Leszek Koltunski
import org.distorted.library.mesh.MeshSquare;
37 411c6285 Leszek Koltunski
import org.distorted.library.type.Static1D;
38 0c52af30 Leszek Koltunski
import org.distorted.library.type.Static3D;
39
import org.distorted.library.type.Static4D;
40 1ebc4767 Leszek Koltunski
import org.distorted.main.RubikSurfaceView;
41 0c52af30 Leszek Koltunski
42 7c969a6d Leszek Koltunski
import java.util.Random;
43
44
import static org.distorted.effects.scramble.ScrambleEffect.START_AXIS;
45
46 0c52af30 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
47
48 27a70eae Leszek Koltunski
class RubikCube extends RubikObject
49 0c52af30 Leszek Koltunski
{
50 10585385 Leszek Koltunski
  static final float SQ2 = (float)Math.sqrt(2);
51
52 e844c116 Leszek Koltunski
  // the three rotation axis of a RubikCube. Must be normalized.
53 ad38d800 Leszek Koltunski
  static final Static3D[] ROT_AXIS = new Static3D[]
54 efef689c Leszek Koltunski
         {
55
           new Static3D(1,0,0),
56
           new Static3D(0,1,0),
57
           new Static3D(0,0,1)
58
         };
59
60 ad38d800 Leszek Koltunski
  // the six axis that determine the faces
61
  static final Static3D[] FACE_AXIS = new Static3D[]
62
         {
63 c7e79b69 Leszek Koltunski
           new Static3D(1,0,0), new Static3D(-1,0,0),
64
           new Static3D(0,1,0), new Static3D(0,-1,0),
65
           new Static3D(0,0,1), new Static3D(0,0,-1)
66 ad38d800 Leszek Koltunski
         };
67
68 37a25788 Leszek Koltunski
  private static final int[] FACE_COLORS = new int[]
69 efef689c Leszek Koltunski
         {
70 ad38d800 Leszek Koltunski
           0xffffff00, 0xffffffff,   // FACE_AXIS[0] (right-YELLOW) FACE_AXIS[1] (left  -WHITE)
71
           0xff0000ff, 0xff00ff00,   // FACE_AXIS[2] (top  -BLUE  ) FACE_AXIS[3] (bottom-GREEN)
72
           0xffff0000, 0xffb5651d    // FACE_AXIS[4] (front-RED   ) FACE_AXIS[5] (back  -BROWN)
73 efef689c Leszek Koltunski
         };
74
75 10585385 Leszek Koltunski
  // All legal rotation quats of a RubikCube of any size.
76 efef689c Leszek Koltunski
  // Here's how to compute this:
77
  // 1) compute how many rotations there are (RubikCube of any size = 24)
78
  // 2) take the AXIS, angles of rotation (90 in RubikCube's case) compute the basic quaternions
79
  // (i.e. rotations of 1 basic angle along each of the axis) and from there start semi-randomly
80
  // multiplying them and eventually you'll find all (24) legal rotations.
81 9f4c44fe Leszek Koltunski
  // Example program in C, res/raw/compute_quats.c , is included.
82 10585385 Leszek Koltunski
  private static final Static4D[] QUATS = new Static4D[]
83 efef689c Leszek Koltunski
         {
84 10585385 Leszek Koltunski
         new Static4D(  0.0f,   0.0f,   0.0f,   1.0f),
85
         new Static4D(  1.0f,   0.0f,   0.0f,   0.0f),
86
         new Static4D(  0.0f,   1.0f,   0.0f,   0.0f),
87
         new Static4D(  0.0f,   0.0f,   1.0f,   0.0f),
88
89
         new Static4D( SQ2/2,  SQ2/2,  0.0f ,   0.0f),
90
         new Static4D( SQ2/2, -SQ2/2,  0.0f ,   0.0f),
91
         new Static4D( SQ2/2,   0.0f,  SQ2/2,   0.0f),
92
         new Static4D(-SQ2/2,   0.0f,  SQ2/2,   0.0f),
93
         new Static4D( SQ2/2,   0.0f,   0.0f,  SQ2/2),
94
         new Static4D( SQ2/2,   0.0f,   0.0f, -SQ2/2),
95
         new Static4D(  0.0f,  SQ2/2,  SQ2/2,   0.0f),
96
         new Static4D(  0.0f,  SQ2/2, -SQ2/2,   0.0f),
97
         new Static4D(  0.0f,  SQ2/2,   0.0f,  SQ2/2),
98
         new Static4D(  0.0f,  SQ2/2,   0.0f, -SQ2/2),
99
         new Static4D(  0.0f,   0.0f,  SQ2/2,  SQ2/2),
100
         new Static4D(  0.0f,   0.0f,  SQ2/2, -SQ2/2),
101
102
         new Static4D(  0.5f,   0.5f,   0.5f,   0.5f),
103
         new Static4D(  0.5f,   0.5f,  -0.5f,   0.5f),
104
         new Static4D(  0.5f,   0.5f,  -0.5f,  -0.5f),
105
         new Static4D(  0.5f,  -0.5f,   0.5f,  -0.5f),
106
         new Static4D( -0.5f,  -0.5f,  -0.5f,   0.5f),
107
         new Static4D( -0.5f,   0.5f,  -0.5f,  -0.5f),
108
         new Static4D( -0.5f,   0.5f,   0.5f,  -0.5f),
109
         new Static4D( -0.5f,   0.5f,   0.5f,   0.5f)
110 efef689c Leszek Koltunski
         };
111 411c6285 Leszek Koltunski
112 fbca0033 Leszek Koltunski
  private static MeshBase[] mMeshes;
113 40ab026e Leszek Koltunski
114 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
115
116 4da7d87a Leszek Koltunski
  RubikCube(int size, Static4D quat, DistortedTexture texture,
117 efa8aa48 Leszek Koltunski
            MeshSquare mesh, DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
118 411c6285 Leszek Koltunski
    {
119 5b893eee Leszek Koltunski
    super(size, 60, quat, texture, mesh, effects, moves, RubikObjectList.CUBE, res, scrWidth);
120 411c6285 Leszek Koltunski
    }
121
122 7289fd6c Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
123 42803ba0 Leszek Koltunski
// paint the square with upper-right corner at (left,top) and side length 'side' with texture
124 7289fd6c Leszek Koltunski
// for face 'face'.
125
126
  void createFaceTexture(Canvas canvas, Paint paint, int face, int left, int top, int side)
127
    {
128
    final float R = side*0.10f;
129
    final float M = side*0.05f;
130
131
    paint.setColor(FACE_COLORS[face]);
132
    canvas.drawRoundRect( left+M, top+M, left+side-M, top+side-M, R, R, paint);
133
    }
134
135 411c6285 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
136
137 10a2e360 Leszek Koltunski
  Static3D[] getCubitPositions(int size)
138 a10ada2a Leszek Koltunski
    {
139 10a2e360 Leszek Koltunski
    int numCubits = size>1 ? 6*size*size - 12*size + 8 : 1;
140
    Static3D[] tmp = new Static3D[numCubits];
141 beb325a0 Leszek Koltunski
142 49f67f9b Leszek Koltunski
    float diff = 0.5f*(size-1);
143 a10ada2a Leszek Koltunski
    int currentPosition = 0;
144 beb325a0 Leszek Koltunski
145 a10ada2a Leszek Koltunski
    for(int x = 0; x<size; x++)
146
      for(int y = 0; y<size; y++)
147
        for(int z = 0; z<size; z++)
148
          if( x==0 || x==size-1 || y==0 || y==size-1 || z==0 || z==size-1 )
149 beb325a0 Leszek Koltunski
            {
150 49f67f9b Leszek Koltunski
            tmp[currentPosition++] = new Static3D(x-diff,y-diff,z-diff);
151 a10ada2a Leszek Koltunski
            }
152 47ba5ddc Leszek Koltunski
153 a10ada2a Leszek Koltunski
    return tmp;
154
    }
155 47ba5ddc Leszek Koltunski
156 beb325a0 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
157
158 10585385 Leszek Koltunski
  Static4D[] getQuats()
159 a10ada2a Leszek Koltunski
    {
160 10585385 Leszek Koltunski
    return QUATS;
161 a10ada2a Leszek Koltunski
    }
162 47ba5ddc Leszek Koltunski
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164
165 411c6285 Leszek Koltunski
  int getNumFaces()
166 a10ada2a Leszek Koltunski
    {
167 411c6285 Leszek Koltunski
    return FACE_COLORS.length;
168 8f53e513 Leszek Koltunski
    }
169
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171
172
  int getNumCubitFaces()
173
    {
174
    return FACE_COLORS.length;
175 411c6285 Leszek Koltunski
    }
176 47ba5ddc Leszek Koltunski
177 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
178
179
  float getScreenRatio()
180
    {
181
    return 0.5f;
182
    }
183
184 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
185
186
  int getFaceColor(int cubit, int cubitface, int size)
187
    {
188
    boolean belongs = isOnFace(cubit, cubitface/2, cubitface%2==0 ? size-1:0 );
189
    return belongs ? cubitface : NUM_FACES;
190
    }
191
192 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
193
194 14bd7976 Leszek Koltunski
  MeshBase createCubitMesh(int cubit)
195 a10ada2a Leszek Koltunski
    {
196 fbca0033 Leszek Koltunski
    int size   = getSize();
197
    int ordinal= RubikObjectList.CUBE.ordinal();
198
    int index  = RubikObjectList.getSizeIndex(ordinal,size);
199 c0b37c89 Leszek Koltunski
    float[] bands;
200
    float D = 0.027f;
201
    float E = 0.5f-D;
202
    float[] vertices = { -E,-E, +E,-E, +E,+E, -E,+E };
203
    int extraI, extraV;
204 fbca0033 Leszek Koltunski
205
    switch(size)
206
      {
207 c0b37c89 Leszek Koltunski
      case 2 : bands = new float[] { 1.0f    ,-D,
208 231771f3 Leszek Koltunski
                                     1.0f-D/2,-D*0.55f,
209
                                     1.0f-D  ,-D*0.25f,
210 c0b37c89 Leszek Koltunski
                                     1.0f-2*D, 0.0f,
211
                                     0.50f, 0.040f,
212
                                     0.0f, 0.048f };
213
               extraI = 2;
214
               extraV = 2;
215 fbca0033 Leszek Koltunski
               break;
216 c0b37c89 Leszek Koltunski
      case 3 : bands = new float[] { 1.0f    ,-D,
217
                                     1.0f-D*1.2f,-D*0.55f,
218
                                     1.0f-2*D, 0.0f,
219
                                     0.50f, 0.040f,
220
                                     0.0f, 0.048f };
221
               extraI = 2;
222
               extraV = 2;
223
               break;
224
      case 4 : bands = new float[] { 1.0f    ,-D,
225
                                     1.0f-D*1.2f,-D*0.55f,
226
                                     1.0f-2*D, 0.0f,
227
                                     0.50f, 0.040f,
228
                                     0.0f, 0.048f };
229
               extraI = 1;
230
               extraV = 2;
231
               break;
232
      default: bands = new float[] { 1.0f    ,-D,
233
                                     1.0f-2*D, 0.0f,
234
                                     0.50f, 0.025f,
235
                                     0.0f, 0.030f };
236
               extraI = 1;
237
               extraV = 1;
238 fbca0033 Leszek Koltunski
               break;
239
      }
240
241 c0b37c89 Leszek Koltunski
    return createCubitMesh(index,vertices,bands,extraI,extraV);
242 55fa2499 Leszek Koltunski
    }
243
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245
246 c0b37c89 Leszek Koltunski
  MeshBase createCubitMesh(int index, float[] vertices, float[] bands, int extraI, int extraV)
247 55fa2499 Leszek Koltunski
    {
248 fbca0033 Leszek Koltunski
    if( mMeshes==null )
249
      {
250
      mMeshes = new MeshBase[RubikObjectList.CUBE.getNumVariants()];
251
      }
252 55fa2499 Leszek Koltunski
253 fbca0033 Leszek Koltunski
    if( mMeshes[index]==null )
254 40ab026e Leszek Koltunski
      {
255
      final int MESHES=6;
256
      int association = 1;
257 c0b37c89 Leszek Koltunski
      MeshBase[] meshes = new MeshPolygon[MESHES];
258
      meshes[0] = new MeshPolygon(vertices,bands,extraI,extraV);
259 e82f3f9c Leszek Koltunski
      meshes[0].setEffectAssociation(0,association,0);
260 40ab026e Leszek Koltunski
261
      for(int i=1; i<MESHES; i++)
262
        {
263
        association <<=1;
264
        meshes[i] = meshes[0].copy(true);
265 e82f3f9c Leszek Koltunski
        meshes[i].setEffectAssociation(0,association,0);
266 40ab026e Leszek Koltunski
        }
267
268 fbca0033 Leszek Koltunski
      mMeshes[index] = new MeshJoined(meshes);
269 40ab026e Leszek Koltunski
270
      Static3D axisY   = new Static3D(0,1,0);
271
      Static3D axisX   = new Static3D(1,0,0);
272
      Static3D center  = new Static3D(0,0,0);
273
      Static1D angle90 = new Static1D(90);
274
      Static1D angle180= new Static1D(180);
275
      Static1D angle270= new Static1D(270);
276
277 14bd7976 Leszek Koltunski
      float d1 = 1.0f;
278
      float d2 =-0.05f;
279
      float d3 = 0.12f;
280
281
      Static3D dCen0 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(+0.5f) );
282
      Static3D dCen1 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(-0.5f) );
283
      Static3D dCen2 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(+0.5f) );
284
      Static3D dCen3 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(-0.5f) );
285
      Static3D dCen4 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(+0.5f) );
286
      Static3D dCen5 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(-0.5f) );
287
      Static3D dCen6 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(+0.5f) );
288
      Static3D dCen7 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(-0.5f) );
289
290
      Static3D dVec0 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(+0.5f) );
291
      Static3D dVec1 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(-0.5f) );
292
      Static3D dVec2 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(+0.5f) );
293
      Static3D dVec3 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(-0.5f) );
294
      Static3D dVec4 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(+0.5f) );
295
      Static3D dVec5 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(-0.5f) );
296
      Static3D dVec6 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(+0.5f) );
297
      Static3D dVec7 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(-0.5f) );
298
299
      Static4D dReg  = new Static4D(0,0,0,d3);
300
      Static1D dRad  = new Static1D(1);
301
302 40ab026e Leszek Koltunski
      VertexEffectMove   effect0 = new VertexEffectMove(new Static3D(0,0,+0.5f));
303 e82f3f9c Leszek Koltunski
      effect0.setMeshAssociation(63,-1);  // all 6 sides
304 40ab026e Leszek Koltunski
      VertexEffectRotate effect1 = new VertexEffectRotate( angle180, axisX, center );
305 e82f3f9c Leszek Koltunski
      effect1.setMeshAssociation(32,-1);  // back
306 40ab026e Leszek Koltunski
      VertexEffectRotate effect2 = new VertexEffectRotate( angle90 , axisX, center );
307 e82f3f9c Leszek Koltunski
      effect2.setMeshAssociation( 8,-1);  // bottom
308 40ab026e Leszek Koltunski
      VertexEffectRotate effect3 = new VertexEffectRotate( angle270, axisX, center );
309 e82f3f9c Leszek Koltunski
      effect3.setMeshAssociation( 4,-1);  // top
310 40ab026e Leszek Koltunski
      VertexEffectRotate effect4 = new VertexEffectRotate( angle270, axisY, center );
311 e82f3f9c Leszek Koltunski
      effect4.setMeshAssociation( 2,-1);  // left
312 40ab026e Leszek Koltunski
      VertexEffectRotate effect5 = new VertexEffectRotate( angle90 , axisY, center );
313 e82f3f9c Leszek Koltunski
      effect5.setMeshAssociation( 1,-1);  // right
314 40ab026e Leszek Koltunski
315 14bd7976 Leszek Koltunski
      VertexEffectDeform effect6 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
316
      VertexEffectDeform effect7 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
317
      VertexEffectDeform effect8 = new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
318
      VertexEffectDeform effect9 = new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
319
      VertexEffectDeform effect10= new VertexEffectDeform(dVec4, dRad, dCen4, dReg);
320
      VertexEffectDeform effect11= new VertexEffectDeform(dVec5, dRad, dCen5, dReg);
321
      VertexEffectDeform effect12= new VertexEffectDeform(dVec6, dRad, dCen6, dReg);
322
      VertexEffectDeform effect13= new VertexEffectDeform(dVec7, dRad, dCen7, dReg);
323
324 fbca0033 Leszek Koltunski
      mMeshes[index].apply(effect0);
325
      mMeshes[index].apply(effect1);
326
      mMeshes[index].apply(effect2);
327
      mMeshes[index].apply(effect3);
328
      mMeshes[index].apply(effect4);
329
      mMeshes[index].apply(effect5);
330
      mMeshes[index].apply(effect6);
331
      mMeshes[index].apply(effect7);
332
      mMeshes[index].apply(effect8);
333
      mMeshes[index].apply(effect9);
334
      mMeshes[index].apply(effect10);
335
      mMeshes[index].apply(effect11);
336
      mMeshes[index].apply(effect12);
337
      mMeshes[index].apply(effect13);
338
339
      mMeshes[index].mergeEffComponents();
340 40ab026e Leszek Koltunski
      }
341 411c6285 Leszek Koltunski
342 fbca0033 Leszek Koltunski
    return mMeshes[index].copy(true);
343 a10ada2a Leszek Koltunski
    }
344 e844c116 Leszek Koltunski
345 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
346
347
  float returnMultiplier()
348
    {
349
    return getSize();
350
    }
351
352 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
353
354
  float[] getRowChances()
355
    {
356
    int size = getSize();
357
    float[] chances = new float[size];
358
359
    for(int i=0; i<size; i++)
360
      {
361
      chances[i] = (i+1.0f) / size;
362
      }
363
364
    return chances;
365
    }
366
367 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
368
// PUBLIC API
369
370 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
371
    {
372 ad38d800 Leszek Koltunski
    return ROT_AXIS;
373 12ad3fca Leszek Koltunski
    }
374
375
///////////////////////////////////////////////////////////////////////////////////////////////////
376
377 e844c116 Leszek Koltunski
  public int getBasicAngle()
378
    {
379
    return 4;
380
    }
381 39e74052 Leszek Koltunski
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
384 fb377dae Leszek Koltunski
  public int computeRowFromOffset(float offset)
385 39e74052 Leszek Koltunski
    {
386 fb377dae Leszek Koltunski
    return (int)(getSize()*offset);
387 39e74052 Leszek Koltunski
    }
388 e46e17fb Leszek Koltunski
389 5cf34c5f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
390
391 7c969a6d Leszek Koltunski
  public float returnRotationFactor(float offset)
392 5cf34c5f Leszek Koltunski
    {
393 7c969a6d Leszek Koltunski
    return 1.0f;
394
    }
395 5cf34c5f Leszek Koltunski
396 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
397
398
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
399
    {
400
    int numAxis = ROTATION_AXIS.length;
401
402
    if( oldRotAxis == START_AXIS )
403 5cf34c5f Leszek Koltunski
      {
404 7c969a6d Leszek Koltunski
      return rnd.nextInt(numAxis);
405
      }
406
    else
407
      {
408
      int newVector = rnd.nextInt(numAxis-1);
409
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
410 5cf34c5f Leszek Koltunski
      }
411
    }
412
413 e46e17fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
414
415 7c969a6d Leszek Koltunski
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
416 e46e17fb Leszek Koltunski
    {
417 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
418
419
    for(int row=0; row<mRowChances.length; row++)
420
      {
421
      if( rowFloat<=mRowChances[row] ) return row;
422
      }
423
424
    return 0;
425 e46e17fb Leszek Koltunski
    }
426 f0336037 Leszek Koltunski
427 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
428
429
  public boolean isSolved()
430
    {
431
    int index = CUBITS[0].mQuatIndex;
432
433
    for(int i=1; i<NUM_CUBITS; i++)
434
      {
435
      if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false;
436
      }
437
438
    return true;
439
    }
440
441 1ebc4767 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
442
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
443
// then if it were rotated by quaternion 'quat'.
444
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
445
// middle squares get interchanged. No visible difference!
446
//
447
// So: this is true iff the cubit
448
// a) is a corner or edge and the quaternions are the same
449
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
450
451 6b6504fe Leszek Koltunski
  private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
452 1ebc4767 Leszek Koltunski
    {
453
    if ( cubit.mQuatIndex == quatIndex ) return true;
454
455
    int belongsToHowManyFaces = 0;
456
    int size = getSize()-1;
457
    float row;
458
    final float MAX_ERROR = 0.01f;
459
460
    for(int i=0; i<NUM_AXIS; i++)
461
      {
462
      row = cubit.mRotationRow[i];
463
      if( (row     <MAX_ERROR && row     >-MAX_ERROR) ||
464
          (row-size<MAX_ERROR && row-size>-MAX_ERROR)  ) belongsToHowManyFaces++;
465
      }
466
467
    switch(belongsToHowManyFaces)
468
      {
469
      case 0 : return true ;  // 'inside' cubit that does not lie on any face
470
      case 1 :                // cubit that lies inside one of the faces
471
               Static3D orig = cubit.getOrigPosition();
472
               Static4D quat1 = QUATS[quatIndex];
473
               Static4D quat2 = QUATS[cubit.mQuatIndex];
474
475
               Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0);
476
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );
477
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
478
479
               float row1, row2, row3, row4;
480
               float ax,ay,az;
481
               Static3D axis;
482
               float x1 = rotated1.get0();
483
               float y1 = rotated1.get1();
484
               float z1 = rotated1.get2();
485
               float x2 = rotated2.get0();
486
               float y2 = rotated2.get1();
487
               float z2 = rotated2.get2();
488
489
               for(int i=0; i<NUM_AXIS; i++)
490
                 {
491
                 axis = ROTATION_AXIS[i];
492
                 ax = axis.get0();
493
                 ay = axis.get1();
494
                 az = axis.get2();
495
496
                 row1 = ((x1*ax + y1*ay + z1*az) - mStart) / mStep;
497
                 row2 = ((x2*ax + y2*ay + z2*az) - mStart) / mStep;
498
                 row3 = row1 - size;
499
                 row4 = row2 - size;
500
501
                 if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) ||
502
                     (row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR)  )
503
                   {
504
                   return true;
505
                   }
506
                 }
507
               return false;
508
509
      default: return false;  // edge or corner
510
      }
511
    }
512
513 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
514 a304ee64 Leszek Koltunski
// order: Up --> Right --> Front --> Down --> Left --> Back
515
// (because the first implemented Solver - the two-phase Cube3 one - expects such order)
516
//
517 fa0f7a56 Leszek Koltunski
// Solved 3x3x3 Cube maps to "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB"
518 a304ee64 Leszek Koltunski
//
519 fa0f7a56 Leszek Koltunski
// s : size of the cube; let index = a*s + b    (i.e. a,b = row,column)
520
//
521
// Up    :   index --> b<s-1 ? (s-1)*(s+4b)+a : 6*s*s -13*s +8 +a
522 a304ee64 Leszek Koltunski
// Right :   index --> 6*s*s - 12*s + 7 - index
523 fa0f7a56 Leszek Koltunski
// Front :   index --> if b==0  : s*s - 1 - index
524
//                     if b==s-1: 6*s*s -11*s +6 - index
525
//                     else
526
//                         a==0: s*s + s-1 + 4*(b-1)*(s-1) + 2*(s-2) + s
527
//                         else: s*s + s-1 + 4*(b-1)*(s-1) + 2*(s-1-a)
528
// Down  :   index --> b==0 ? (s-1-a) : s*s + s-1 + 4*(b-1)*(s-1) - a
529
// Left  :   index --> (s-1-a)*s + b
530
// Back  :   index --> if b==s-1: s*(s-1-a)
531
//                     if b==0  : 5*s*s -12*s + 8 + (s-1-a)*s
532
//                     else
533
//                        if a==s-1: s*s + 4*(s-2-b)*(s-1)
534
//                        else     : s*s + 4*(s-2-b)*(s-1) + s + (s-2-a)*2
535 f0336037 Leszek Koltunski
536 20931cf6 Leszek Koltunski
  public String retObjectString()
537 f0336037 Leszek Koltunski
    {
538 fa0f7a56 Leszek Koltunski
    StringBuilder objectString = new StringBuilder();
539
    int size = getSize();
540
    int len = size*size;
541 49595e4b Leszek Koltunski
    int cubitIndex=-1, row=-1, col=-1;
542
    int color=-1, face=-1;
543 fa0f7a56 Leszek Koltunski
544
    final int RIGHT= 0;
545
    final int LEFT = 1;
546
    final int UP   = 2;
547
    final int DOWN = 3;
548
    final int FRONT= 4;
549
    final int BACK = 5;
550
551
    final char[] FACE_NAMES = { 'R', 'L', 'U', 'D', 'F', 'B'};
552
553 49595e4b Leszek Koltunski
/////////////////////
554
// LIVE DEBUGGING
555
/////////////////////
556
try
557
  {
558
/////////////////////
559
560
    face = UP;
561
562 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
563
      {
564
      row = i/size;
565
      col = i%size;
566
567
      cubitIndex = col<size-1 ? (size-1)*(size+4*col) + row : 6*size*size - 13*size + 8 + row;
568 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
569 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
570
      }
571
572 49595e4b Leszek Koltunski
    face = RIGHT;
573
574 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
575
      {
576
      cubitIndex = 6*size*size - 12*size +7 - i;
577 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
578 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
579
      }
580
581 49595e4b Leszek Koltunski
     face = FRONT;
582
583 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
584
      {
585
      row = i/size;
586
      col = i%size;
587
588
      if( col==size-1 ) cubitIndex = 6*size*size - 11*size + 6 -i;
589
      else if( col==0 ) cubitIndex = size*size - 1 - i;
590
      else
591
        {
592
        if( row==0 ) cubitIndex = size*size + size-1 + 4*(col-1)*(size-1) + 2*(size-2) + size;
593
        else         cubitIndex = size*size + size-1 + 4*(col-1)*(size-1) + 2*(size-1-row);
594
        }
595
596 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
597 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
598
      }
599
600 49595e4b Leszek Koltunski
    face = DOWN;
601
602 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
603
      {
604
      row = i/size;
605
      col = i%size;
606
607
      cubitIndex = col==0 ? size-1-row : size*size + size-1 + 4*(col-1)*(size-1) - row;
608 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
609 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
610
      }
611
612 49595e4b Leszek Koltunski
    face = LEFT;
613
614 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
615
      {
616
      row = i/size;
617
      col = i%size;
618
619
      cubitIndex = (size-1-row)*size + col;
620 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
621 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
622
      }
623
624 49595e4b Leszek Koltunski
    face = BACK;
625
626 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
627
      {
628
      row = i/size;
629
      col = i%size;
630
631
      if( col==size-1 ) cubitIndex = size*(size-1-row);
632
      else if( col==0 ) cubitIndex = 5*size*size - 12*size + 8 + (size-1-row)*size;
633
      else
634
        {
635
        if( row==size-1 ) cubitIndex = size*size + 4*(size-2-col)*(size-1);
636
        else              cubitIndex = size*size + 4*(size-2-col)*(size-1) + size + 2*(size-2-row);
637
        }
638
639 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
640 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
641
      }
642
643 49595e4b Leszek Koltunski
/////////////////////
644
  }
645
catch(java.lang.ArrayIndexOutOfBoundsException ex)
646
  {
647
  FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance();
648
649
  String str="";
650
  for(int i=0; i<NUM_CUBITS; i++)
651
    {
652
    str += (CUBITS[i].mQuatIndex+" ");
653
    }
654
655
  crashlytics.setCustomKey("ObjectString", "color="+color+" cubitIndex="+cubitIndex+" face="+face+" row="+row+" col="+col );
656
  crashlytics.setCustomKey("Quaternion", "NUM_CUBITS: "+NUM_CUBITS+" quats: "+str );
657
  crashlytics.recordException(ex);
658
  }
659
/////////////////////
660
// END LIVE DEBUGGING
661
/////////////////////
662
663 fa0f7a56 Leszek Koltunski
    return objectString.toString();
664 f0336037 Leszek Koltunski
    }
665 0c52af30 Leszek Koltunski
}