Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / RubikCube.java @ b0a56742

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