Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikCube.java @ 940100d1

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 eab9d8f8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
171
172
  int getNumStickerTypes()
173
    {
174
    return 1;
175
    }
176
177 8f53e513 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
178
179
  int getNumCubitFaces()
180
    {
181
    return FACE_COLORS.length;
182 411c6285 Leszek Koltunski
    }
183 47ba5ddc Leszek Koltunski
184 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
185
186
  float getScreenRatio()
187
    {
188
    return 0.5f;
189
    }
190
191 f6d06256 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
192
193
  int getFaceColor(int cubit, int cubitface, int size)
194
    {
195
    boolean belongs = isOnFace(cubit, cubitface/2, cubitface%2==0 ? size-1:0 );
196
    return belongs ? cubitface : NUM_FACES;
197
    }
198
199 f0fa83ae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
200
201 14bd7976 Leszek Koltunski
  MeshBase createCubitMesh(int cubit)
202 a10ada2a Leszek Koltunski
    {
203 fbca0033 Leszek Koltunski
    int size   = getSize();
204
    int ordinal= RubikObjectList.CUBE.ordinal();
205
    int index  = RubikObjectList.getSizeIndex(ordinal,size);
206 c0b37c89 Leszek Koltunski
    float[] bands;
207
    float D = 0.027f;
208
    float E = 0.5f-D;
209
    float[] vertices = { -E,-E, +E,-E, +E,+E, -E,+E };
210
    int extraI, extraV;
211 fbca0033 Leszek Koltunski
212
    switch(size)
213
      {
214 c0b37c89 Leszek Koltunski
      case 2 : bands = new float[] { 1.0f    ,-D,
215 231771f3 Leszek Koltunski
                                     1.0f-D/2,-D*0.55f,
216
                                     1.0f-D  ,-D*0.25f,
217 c0b37c89 Leszek Koltunski
                                     1.0f-2*D, 0.0f,
218
                                     0.50f, 0.040f,
219
                                     0.0f, 0.048f };
220
               extraI = 2;
221
               extraV = 2;
222 fbca0033 Leszek Koltunski
               break;
223 c0b37c89 Leszek Koltunski
      case 3 : bands = new float[] { 1.0f    ,-D,
224
                                     1.0f-D*1.2f,-D*0.55f,
225
                                     1.0f-2*D, 0.0f,
226
                                     0.50f, 0.040f,
227
                                     0.0f, 0.048f };
228
               extraI = 2;
229
               extraV = 2;
230
               break;
231
      case 4 : bands = new float[] { 1.0f    ,-D,
232
                                     1.0f-D*1.2f,-D*0.55f,
233
                                     1.0f-2*D, 0.0f,
234
                                     0.50f, 0.040f,
235
                                     0.0f, 0.048f };
236
               extraI = 1;
237
               extraV = 2;
238
               break;
239
      default: bands = new float[] { 1.0f    ,-D,
240
                                     1.0f-2*D, 0.0f,
241
                                     0.50f, 0.025f,
242
                                     0.0f, 0.030f };
243
               extraI = 1;
244
               extraV = 1;
245 fbca0033 Leszek Koltunski
               break;
246
      }
247
248 c0b37c89 Leszek Koltunski
    return createCubitMesh(index,vertices,bands,extraI,extraV);
249 55fa2499 Leszek Koltunski
    }
250
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252
253 c0b37c89 Leszek Koltunski
  MeshBase createCubitMesh(int index, float[] vertices, float[] bands, int extraI, int extraV)
254 55fa2499 Leszek Koltunski
    {
255 fbca0033 Leszek Koltunski
    if( mMeshes==null )
256
      {
257
      mMeshes = new MeshBase[RubikObjectList.CUBE.getNumVariants()];
258
      }
259 55fa2499 Leszek Koltunski
260 fbca0033 Leszek Koltunski
    if( mMeshes[index]==null )
261 40ab026e Leszek Koltunski
      {
262
      final int MESHES=6;
263
      int association = 1;
264 c0b37c89 Leszek Koltunski
      MeshBase[] meshes = new MeshPolygon[MESHES];
265
      meshes[0] = new MeshPolygon(vertices,bands,extraI,extraV);
266 e82f3f9c Leszek Koltunski
      meshes[0].setEffectAssociation(0,association,0);
267 40ab026e Leszek Koltunski
268
      for(int i=1; i<MESHES; i++)
269
        {
270
        association <<=1;
271
        meshes[i] = meshes[0].copy(true);
272 e82f3f9c Leszek Koltunski
        meshes[i].setEffectAssociation(0,association,0);
273 40ab026e Leszek Koltunski
        }
274
275 fbca0033 Leszek Koltunski
      mMeshes[index] = new MeshJoined(meshes);
276 40ab026e Leszek Koltunski
277
      Static3D axisY   = new Static3D(0,1,0);
278
      Static3D axisX   = new Static3D(1,0,0);
279
      Static3D center  = new Static3D(0,0,0);
280
      Static1D angle90 = new Static1D(90);
281
      Static1D angle180= new Static1D(180);
282
      Static1D angle270= new Static1D(270);
283
284 14bd7976 Leszek Koltunski
      float d1 = 1.0f;
285
      float d2 =-0.05f;
286
      float d3 = 0.12f;
287
288
      Static3D dCen0 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(+0.5f) );
289
      Static3D dCen1 = new Static3D( d1*(+0.5f), d1*(+0.5f), d1*(-0.5f) );
290
      Static3D dCen2 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(+0.5f) );
291
      Static3D dCen3 = new Static3D( d1*(+0.5f), d1*(-0.5f), d1*(-0.5f) );
292
      Static3D dCen4 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(+0.5f) );
293
      Static3D dCen5 = new Static3D( d1*(-0.5f), d1*(+0.5f), d1*(-0.5f) );
294
      Static3D dCen6 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(+0.5f) );
295
      Static3D dCen7 = new Static3D( d1*(-0.5f), d1*(-0.5f), d1*(-0.5f) );
296
297
      Static3D dVec0 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(+0.5f) );
298
      Static3D dVec1 = new Static3D( d2*(+0.5f), d2*(+0.5f), d2*(-0.5f) );
299
      Static3D dVec2 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(+0.5f) );
300
      Static3D dVec3 = new Static3D( d2*(+0.5f), d2*(-0.5f), d2*(-0.5f) );
301
      Static3D dVec4 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(+0.5f) );
302
      Static3D dVec5 = new Static3D( d2*(-0.5f), d2*(+0.5f), d2*(-0.5f) );
303
      Static3D dVec6 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(+0.5f) );
304
      Static3D dVec7 = new Static3D( d2*(-0.5f), d2*(-0.5f), d2*(-0.5f) );
305
306
      Static4D dReg  = new Static4D(0,0,0,d3);
307
      Static1D dRad  = new Static1D(1);
308
309 40ab026e Leszek Koltunski
      VertexEffectMove   effect0 = new VertexEffectMove(new Static3D(0,0,+0.5f));
310 e82f3f9c Leszek Koltunski
      effect0.setMeshAssociation(63,-1);  // all 6 sides
311 40ab026e Leszek Koltunski
      VertexEffectRotate effect1 = new VertexEffectRotate( angle180, axisX, center );
312 e82f3f9c Leszek Koltunski
      effect1.setMeshAssociation(32,-1);  // back
313 40ab026e Leszek Koltunski
      VertexEffectRotate effect2 = new VertexEffectRotate( angle90 , axisX, center );
314 e82f3f9c Leszek Koltunski
      effect2.setMeshAssociation( 8,-1);  // bottom
315 40ab026e Leszek Koltunski
      VertexEffectRotate effect3 = new VertexEffectRotate( angle270, axisX, center );
316 e82f3f9c Leszek Koltunski
      effect3.setMeshAssociation( 4,-1);  // top
317 40ab026e Leszek Koltunski
      VertexEffectRotate effect4 = new VertexEffectRotate( angle270, axisY, center );
318 e82f3f9c Leszek Koltunski
      effect4.setMeshAssociation( 2,-1);  // left
319 40ab026e Leszek Koltunski
      VertexEffectRotate effect5 = new VertexEffectRotate( angle90 , axisY, center );
320 e82f3f9c Leszek Koltunski
      effect5.setMeshAssociation( 1,-1);  // right
321 40ab026e Leszek Koltunski
322 14bd7976 Leszek Koltunski
      VertexEffectDeform effect6 = new VertexEffectDeform(dVec0, dRad, dCen0, dReg);
323
      VertexEffectDeform effect7 = new VertexEffectDeform(dVec1, dRad, dCen1, dReg);
324
      VertexEffectDeform effect8 = new VertexEffectDeform(dVec2, dRad, dCen2, dReg);
325
      VertexEffectDeform effect9 = new VertexEffectDeform(dVec3, dRad, dCen3, dReg);
326
      VertexEffectDeform effect10= new VertexEffectDeform(dVec4, dRad, dCen4, dReg);
327
      VertexEffectDeform effect11= new VertexEffectDeform(dVec5, dRad, dCen5, dReg);
328
      VertexEffectDeform effect12= new VertexEffectDeform(dVec6, dRad, dCen6, dReg);
329
      VertexEffectDeform effect13= new VertexEffectDeform(dVec7, dRad, dCen7, dReg);
330
331 fbca0033 Leszek Koltunski
      mMeshes[index].apply(effect0);
332
      mMeshes[index].apply(effect1);
333
      mMeshes[index].apply(effect2);
334
      mMeshes[index].apply(effect3);
335
      mMeshes[index].apply(effect4);
336
      mMeshes[index].apply(effect5);
337
      mMeshes[index].apply(effect6);
338
      mMeshes[index].apply(effect7);
339
      mMeshes[index].apply(effect8);
340
      mMeshes[index].apply(effect9);
341
      mMeshes[index].apply(effect10);
342
      mMeshes[index].apply(effect11);
343
      mMeshes[index].apply(effect12);
344
      mMeshes[index].apply(effect13);
345
346
      mMeshes[index].mergeEffComponents();
347 40ab026e Leszek Koltunski
      }
348 411c6285 Leszek Koltunski
349 fbca0033 Leszek Koltunski
    return mMeshes[index].copy(true);
350 a10ada2a Leszek Koltunski
    }
351 e844c116 Leszek Koltunski
352 fb377dae Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
353
354
  float returnMultiplier()
355
    {
356
    return getSize();
357
    }
358
359 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
360
361
  float[] getRowChances()
362
    {
363
    int size = getSize();
364
    float[] chances = new float[size];
365
366
    for(int i=0; i<size; i++)
367
      {
368
      chances[i] = (i+1.0f) / size;
369
      }
370
371
    return chances;
372
    }
373
374 e844c116 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
375
// PUBLIC API
376
377 12ad3fca Leszek Koltunski
  public Static3D[] getRotationAxis()
378
    {
379 ad38d800 Leszek Koltunski
    return ROT_AXIS;
380 12ad3fca Leszek Koltunski
    }
381
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383
384 e844c116 Leszek Koltunski
  public int getBasicAngle()
385
    {
386
    return 4;
387
    }
388 39e74052 Leszek Koltunski
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390
391 fb377dae Leszek Koltunski
  public int computeRowFromOffset(float offset)
392 39e74052 Leszek Koltunski
    {
393 fb377dae Leszek Koltunski
    return (int)(getSize()*offset);
394 39e74052 Leszek Koltunski
    }
395 e46e17fb Leszek Koltunski
396 5cf34c5f Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
397
398 7c969a6d Leszek Koltunski
  public float returnRotationFactor(float offset)
399 5cf34c5f Leszek Koltunski
    {
400 7c969a6d Leszek Koltunski
    return 1.0f;
401
    }
402 5cf34c5f Leszek Koltunski
403 7c969a6d Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
404
405
  public int randomizeNewRotAxis(Random rnd, int oldRotAxis)
406
    {
407
    int numAxis = ROTATION_AXIS.length;
408
409
    if( oldRotAxis == START_AXIS )
410 5cf34c5f Leszek Koltunski
      {
411 7c969a6d Leszek Koltunski
      return rnd.nextInt(numAxis);
412
      }
413
    else
414
      {
415
      int newVector = rnd.nextInt(numAxis-1);
416
      return (newVector>=oldRotAxis ? newVector+1 : newVector);
417 5cf34c5f Leszek Koltunski
      }
418
    }
419
420 e46e17fb Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
421
422 7c969a6d Leszek Koltunski
  public int randomizeNewRow(Random rnd, int oldRotAxis, int oldRow, int newRotAxis)
423 e46e17fb Leszek Koltunski
    {
424 7c969a6d Leszek Koltunski
    float rowFloat = rnd.nextFloat();
425
426
    for(int row=0; row<mRowChances.length; row++)
427
      {
428
      if( rowFloat<=mRowChances[row] ) return row;
429
      }
430
431
    return 0;
432 e46e17fb Leszek Koltunski
    }
433 f0336037 Leszek Koltunski
434 6b6504fe Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
435
436
  public boolean isSolved()
437
    {
438
    int index = CUBITS[0].mQuatIndex;
439
440
    for(int i=1; i<NUM_CUBITS; i++)
441
      {
442
      if( !thereIsNoVisibleDifference(CUBITS[i], index) ) return false;
443
      }
444
445
    return true;
446
    }
447
448 1ebc4767 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
449
// return if the Cubit, when rotated with its own mQuatScramble, would have looked any different
450
// then if it were rotated by quaternion 'quat'.
451
// No it is not so simple as the quats need to be the same - imagine a 4x4x4 cube where the two
452
// middle squares get interchanged. No visible difference!
453
//
454
// So: this is true iff the cubit
455
// a) is a corner or edge and the quaternions are the same
456
// b) is inside one of the faces and after rotations by both quats it ends up on the same face.
457
458 6b6504fe Leszek Koltunski
  private boolean thereIsNoVisibleDifference(Cubit cubit, int quatIndex)
459 1ebc4767 Leszek Koltunski
    {
460
    if ( cubit.mQuatIndex == quatIndex ) return true;
461
462
    int belongsToHowManyFaces = 0;
463
    int size = getSize()-1;
464
    float row;
465
    final float MAX_ERROR = 0.01f;
466
467
    for(int i=0; i<NUM_AXIS; i++)
468
      {
469
      row = cubit.mRotationRow[i];
470
      if( (row     <MAX_ERROR && row     >-MAX_ERROR) ||
471
          (row-size<MAX_ERROR && row-size>-MAX_ERROR)  ) belongsToHowManyFaces++;
472
      }
473
474
    switch(belongsToHowManyFaces)
475
      {
476
      case 0 : return true ;  // 'inside' cubit that does not lie on any face
477
      case 1 :                // cubit that lies inside one of the faces
478
               Static3D orig = cubit.getOrigPosition();
479
               Static4D quat1 = QUATS[quatIndex];
480
               Static4D quat2 = QUATS[cubit.mQuatIndex];
481
482
               Static4D cubitCenter = new Static4D( orig.get0(), orig.get1(), orig.get2(), 0);
483
               Static4D rotated1 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat1 );
484
               Static4D rotated2 = RubikSurfaceView.rotateVectorByQuat( cubitCenter, quat2 );
485
486
               float row1, row2, row3, row4;
487
               float ax,ay,az;
488
               Static3D axis;
489
               float x1 = rotated1.get0();
490
               float y1 = rotated1.get1();
491
               float z1 = rotated1.get2();
492
               float x2 = rotated2.get0();
493
               float y2 = rotated2.get1();
494
               float z2 = rotated2.get2();
495
496
               for(int i=0; i<NUM_AXIS; i++)
497
                 {
498
                 axis = ROTATION_AXIS[i];
499
                 ax = axis.get0();
500
                 ay = axis.get1();
501
                 az = axis.get2();
502
503
                 row1 = ((x1*ax + y1*ay + z1*az) - mStart) / mStep;
504
                 row2 = ((x2*ax + y2*ay + z2*az) - mStart) / mStep;
505
                 row3 = row1 - size;
506
                 row4 = row2 - size;
507
508
                 if( (row1<MAX_ERROR && row1>-MAX_ERROR && row2<MAX_ERROR && row2>-MAX_ERROR) ||
509
                     (row3<MAX_ERROR && row3>-MAX_ERROR && row4<MAX_ERROR && row4>-MAX_ERROR)  )
510
                   {
511
                   return true;
512
                   }
513
                 }
514
               return false;
515
516
      default: return false;  // edge or corner
517
      }
518
    }
519
520 f0336037 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
521 a304ee64 Leszek Koltunski
// order: Up --> Right --> Front --> Down --> Left --> Back
522
// (because the first implemented Solver - the two-phase Cube3 one - expects such order)
523
//
524 fa0f7a56 Leszek Koltunski
// Solved 3x3x3 Cube maps to "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB"
525 a304ee64 Leszek Koltunski
//
526 fa0f7a56 Leszek Koltunski
// s : size of the cube; let index = a*s + b    (i.e. a,b = row,column)
527
//
528
// Up    :   index --> b<s-1 ? (s-1)*(s+4b)+a : 6*s*s -13*s +8 +a
529 a304ee64 Leszek Koltunski
// Right :   index --> 6*s*s - 12*s + 7 - index
530 fa0f7a56 Leszek Koltunski
// Front :   index --> if b==0  : s*s - 1 - index
531
//                     if b==s-1: 6*s*s -11*s +6 - index
532
//                     else
533
//                         a==0: s*s + s-1 + 4*(b-1)*(s-1) + 2*(s-2) + s
534
//                         else: s*s + s-1 + 4*(b-1)*(s-1) + 2*(s-1-a)
535
// Down  :   index --> b==0 ? (s-1-a) : s*s + s-1 + 4*(b-1)*(s-1) - a
536
// Left  :   index --> (s-1-a)*s + b
537
// Back  :   index --> if b==s-1: s*(s-1-a)
538
//                     if b==0  : 5*s*s -12*s + 8 + (s-1-a)*s
539
//                     else
540
//                        if a==s-1: s*s + 4*(s-2-b)*(s-1)
541
//                        else     : s*s + 4*(s-2-b)*(s-1) + s + (s-2-a)*2
542 f0336037 Leszek Koltunski
543 20931cf6 Leszek Koltunski
  public String retObjectString()
544 f0336037 Leszek Koltunski
    {
545 fa0f7a56 Leszek Koltunski
    StringBuilder objectString = new StringBuilder();
546
    int size = getSize();
547
    int len = size*size;
548 49595e4b Leszek Koltunski
    int cubitIndex=-1, row=-1, col=-1;
549
    int color=-1, face=-1;
550 fa0f7a56 Leszek Koltunski
551
    final int RIGHT= 0;
552
    final int LEFT = 1;
553
    final int UP   = 2;
554
    final int DOWN = 3;
555
    final int FRONT= 4;
556
    final int BACK = 5;
557
558 fb52fae9 Leszek Koltunski
    // 'I' - interior, theoretically can happen
559
    final char[] FACE_NAMES = { 'R', 'L', 'U', 'D', 'F', 'B', 'I'};
560 49595e4b Leszek Koltunski
561
    face = UP;
562
563 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
564
      {
565
      row = i/size;
566
      col = i%size;
567
568
      cubitIndex = col<size-1 ? (size-1)*(size+4*col) + row : 6*size*size - 13*size + 8 + row;
569 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
570 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
571
      }
572
573 49595e4b Leszek Koltunski
    face = RIGHT;
574
575 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
576
      {
577
      cubitIndex = 6*size*size - 12*size +7 - i;
578 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
579 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
580
      }
581
582 49595e4b Leszek Koltunski
     face = FRONT;
583
584 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
585
      {
586
      row = i/size;
587
      col = i%size;
588
589
      if( col==size-1 ) cubitIndex = 6*size*size - 11*size + 6 -i;
590
      else if( col==0 ) cubitIndex = size*size - 1 - i;
591
      else
592
        {
593
        if( row==0 ) cubitIndex = size*size + size-1 + 4*(col-1)*(size-1) + 2*(size-2) + size;
594
        else         cubitIndex = size*size + size-1 + 4*(col-1)*(size-1) + 2*(size-1-row);
595
        }
596
597 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
598 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
599
      }
600
601 49595e4b Leszek Koltunski
    face = DOWN;
602
603 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
604
      {
605
      row = i/size;
606
      col = i%size;
607
608
      cubitIndex = col==0 ? size-1-row : size*size + size-1 + 4*(col-1)*(size-1) - row;
609 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
610 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
611
      }
612
613 49595e4b Leszek Koltunski
    face = LEFT;
614
615 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
616
      {
617
      row = i/size;
618
      col = i%size;
619
620
      cubitIndex = (size-1-row)*size + col;
621 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
622 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
623
      }
624
625 49595e4b Leszek Koltunski
    face = BACK;
626
627 fa0f7a56 Leszek Koltunski
    for(int i=0; i<len; i++)
628
      {
629
      row = i/size;
630
      col = i%size;
631
632
      if( col==size-1 ) cubitIndex = size*(size-1-row);
633
      else if( col==0 ) cubitIndex = 5*size*size - 12*size + 8 + (size-1-row)*size;
634
      else
635
        {
636
        if( row==size-1 ) cubitIndex = size*size + 4*(size-2-col)*(size-1);
637
        else              cubitIndex = size*size + 4*(size-2-col)*(size-1) + size + 2*(size-2-row);
638
        }
639
640 49595e4b Leszek Koltunski
      color = getCubitFaceColorIndex(cubitIndex,face);
641 fa0f7a56 Leszek Koltunski
      objectString.append(FACE_NAMES[color]);
642
      }
643
644
    return objectString.toString();
645 f0336037 Leszek Koltunski
    }
646 0c52af30 Leszek Koltunski
}