Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikCube.java @ 44f95b2a

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