Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySquare2.java @ abe288a3

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// 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
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// 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
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.objects;
21

    
22
import android.content.res.Resources;
23

    
24
import org.distorted.helpers.ObjectShape;
25
import org.distorted.helpers.ObjectSticker;
26
import org.distorted.library.main.DistortedEffects;
27
import org.distorted.library.main.DistortedTexture;
28
import org.distorted.library.mesh.MeshSquare;
29
import org.distorted.library.type.Static4D;
30
import org.distorted.main.R;
31

    
32
import java.util.Random;
33

    
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35

    
36
class TwistySquare2 extends TwistySquare
37
{
38
  private static final float Y = 0.75f + X/2;
39
  private static final float Z = 0.75f - X/2;
40

    
41
  private static final int[] QUAT_NUMBER = new int[]
42
    {
43
      0, 6,
44
      0, 9, 6, 3, 18, 15, 12, 21,
45
      0, 9, 6, 3, 0, 9, 6, 3,
46
      15, 12, 21, 18, 15, 12, 21, 18
47
    };
48

    
49
  // centers of the 2 middles + 8 edges + 8 left corners + 8 right corners
50
  private static final float[][] CENTERS = new float[][]
51
    {
52
      { 1.5f, 0.0f, 0.0f },
53
      {-1.5f, 0.0f, 0.0f },
54

    
55
      { 0.0f, 1.0f, 1.5f },
56
      { 1.5f, 1.0f, 0.0f },
57
      { 0.0f, 1.0f,-1.5f },
58
      {-1.5f, 1.0f, 0.0f },
59
      { 0.0f,-1.0f, 1.5f },
60
      { 1.5f,-1.0f, 0.0f },
61
      { 0.0f,-1.0f,-1.5f },
62
      {-1.5f,-1.0f, 0.0f },
63

    
64
      {    Y, 1.0f, 1.5f },
65
      { 1.5f, 1.0f,   -Y },
66
      {   -Y, 1.0f,-1.5f },
67
      {-1.5f, 1.0f,    Y },
68
      {    Y,-1.0f, 1.5f },
69
      { 1.5f,-1.0f,   -Y },
70
      {   -Y,-1.0f,-1.5f },
71
      {-1.5f,-1.0f,    Y },
72

    
73
      { 1.5f, 1.0f,    Y },
74
      {    Y, 1.0f,-1.5f },
75
      {-1.5f, 1.0f,   -Y },
76
      {   -Y, 1.0f, 1.5f },
77
      { 1.5f,-1.0f,    Y },
78
      {    Y,-1.0f,-1.5f },
79
      {-1.5f,-1.0f,   -Y },
80
      {   -Y,-1.0f, 1.5f },
81
    };
82

    
83
  private static final double[][] VERTICES_CORNER = new double[][]
84
    {
85
      { X-1.5+Z, 0.5,  0.0 },
86
      {       Z, 0.5,  0.0 },
87
      {  -1.5+Z, 0.5, -1.5 },
88
      { X-1.5+Z,-0.5,  0.0 },
89
      {       Z,-0.5,  0.0 },
90
      {  -1.5+Z,-0.5, -1.5 }
91
    };
92

    
93
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
94
    {
95
      {0,1,2},   // counterclockwise!
96
      {5,4,3},
97
      {3,4,1,0},
98
      {4,5,2,1},
99
      {5,3,0,2}
100
    };
101

    
102
  private static final float[][] STICKERS = new float[][]
103
    {
104
      { -0.5f, -0.26289170f, 0.5f, -0.26289170f, 0.5f, 0.26289170f, -0.5f, 0.26289170f }, // middle front
105
      { -0.5f, -0.16666667f, 0.5f, -0.16666667f, 0.5f, 0.16666667f, -0.5f, 0.16666667f }, // middle right
106
      { -0.5f, -0.45534182f, 0.5f, -0.45534182f, 0.5f, 0.45534182f, -0.5f, 0.45534182f }, // middle back
107
      { -0.20096192f, -0.25f, 0.20096192f, -0.25f, 0.0f, 0.5f },                          // edge top
108
      { -0.40192384f, -0.5f, 0.40192384f, -0.5f, 0.40192384f, 0.5f, -0.40192384f, 0.5f }, // edge face
109
      { -0.11602539f, -0.25f, 0.4330127f, -0.25f, -0.3169873f, 0.5f }                     // corner top
110
    };
111

    
112
  private static final int NUM_STICKERS = STICKERS.length;
113

    
114
  private static final int[][] mStickerType = new int[][]
115
    {
116
      {  NUM_STICKERS,NUM_STICKERS,0,           1,           2,NUM_STICKERS },
117
      {             3,NUM_STICKERS,4,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS },
118
      {             5,NUM_STICKERS,2,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS },
119
      {  NUM_STICKERS,           5,2,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS }
120
    };
121

    
122
  // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4 ORANGE 5
123
  private static final int[][] mStickerColor = new int[][]
124
    {
125
      { 0, 0, 4, 0, 5, 0 }, // 0
126
      { 0, 0, 5, 1, 4, 0 },
127

    
128
      { 2, 0, 4, 0, 0, 0 }, // 2
129
      { 2, 0, 0, 0, 0, 0 },
130
      { 2, 0, 5, 0, 0, 0 },
131
      { 2, 0, 1, 0, 0, 0 },
132
      { 3, 0, 4, 0, 0, 0 },
133
      { 3, 0, 0, 0, 0, 0 },
134
      { 3, 0, 5, 0, 0, 0 },
135
      { 3, 0, 1, 0, 0, 0 },
136

    
137
      { 2, 0, 4, 0, 0, 0 }, // 10
138
      { 2, 0, 0, 0, 0, 0 },
139
      { 2, 0, 5, 0, 0, 0 },
140
      { 2, 0, 1, 0, 0, 0 },
141
      { 0, 3, 4, 0, 0, 0 },
142
      { 0, 3, 0, 0, 0, 0 },
143
      { 0, 3, 5, 0, 0, 0 },
144
      { 0, 3, 1, 0, 0, 0 },
145

    
146
      { 0, 2, 0, 0, 0, 0 }, // 18
147
      { 0, 2, 5, 0, 0, 0 },
148
      { 0, 2, 1, 0, 0, 0 },
149
      { 0, 2, 4, 0, 0, 0 },
150
      { 3, 0, 0, 0, 0, 0 },
151
      { 3, 0, 5, 0, 0, 0 },
152
      { 3, 0, 1, 0, 0, 0 },
153
      { 3, 0, 4, 0, 0, 0 },
154
    };
155

    
156
  private static final ObjectSticker[] mStickers;
157

    
158
  static
159
    {
160
    mStickers = new ObjectSticker[NUM_STICKERS];
161
    final float R1 = 0.06f;
162
    final float R2 = 0.04f;
163
    final float R3 = 0.11f;
164
    final float R4 = 0.03f;
165
    final float R5 = 0.11f;
166
    final float R6 = 0.025f;
167
    final float[][] radii  = { {R1,R1,R1,R1},{R2,R2,R2,R2},{R3,R3,R3,R3},{R4,R4,R4},{R5,R5,R5,R5},{R6,R6,R6} };
168
    final float[] strokes = { 0.05f,0.04f,0.09f,0.05f,0.08f,0.06f };
169

    
170
    for(int s=0; s<NUM_STICKERS; s++)
171
      {
172
      mStickers[s] = new ObjectSticker(STICKERS[s],null,radii[s],strokes[s]);
173
      }
174
    }
175

    
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

    
178
  TwistySquare2(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
179
                DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
180
    {
181
    super(size, quat, texture, mesh, effects, moves, ObjectList.SQU2, res, scrWidth);
182
    }
183

    
184
///////////////////////////////////////////////////////////////////////////////////////////////////
185

    
186
  ObjectShape getObjectShape(int cubit, int numLayers)
187
    {
188
    int variant = getCubitVariant(cubit,numLayers);
189

    
190
    if( variant==0 )
191
      {
192
      float[][] bands     = new float[][] { {0.040f,35,0.8f,1.0f,5,2,1}, {0.020f,35,0.8f,1.0f,5,2,1}, {0.001f,35,0.8f,1.0f,5,2,1} };
193
      int[] bandIndices   = new int[] { 2,2,1,1,0,2 };
194
      float[][] corners   = new float[][] { {0.03f,0.05f} };
195
      int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
196
      float[][] centers   = new float[][] { { -0.75f, 0.0f, 0.0f} };
197
      int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
198
      return new ObjectShape(VERTICES_MIDDLE,VERT_INDEXES_MIDDLE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
199
      }
200
    else if( variant==1 )
201
      {
202
      float[][] bands     = new float[][] { {0.038f,35,0.5f,0.9f, 5,2,1}, {0.001f,35,0.5f,0.9f, 5,2,1} };
203
      int[] bandIndices   = new int[] { 0,1,0,1,1 };
204
      float[][] corners   = new float[][] { {0.04f,0.15f} };
205
      int[] cornerIndices = new int[] { 0,0,-1,0,0,-1 };
206
      float[][] centers   = new float[][] { { 0.0f, 0.0f,-0.5f} };
207
      int[] centerIndices = new int[] { 0,0,-1,0,0,-1 };
208
      return new ObjectShape(VERTICES_EDGE,VERT_INDEXES_EDGE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
209
      }
210
    else
211
      {
212
      float[][] bands     = new float[][] { {0.030f,35,0.9f,1.0f, 5,2,1}, {0.001f,35,0.9f,1.0f, 5,2,1} };
213
      int[] bandIndices   = new int[] { 0,0,0,1,1 };
214
      float[][] corners   = new float[][] { {0.05f,0.13f} };
215
      int[] cornerIndices = new int[] { 0,0,-1,0,0,-1 };
216
      float[][] centers   = new float[][] { { 0.0f, 0.0f,-0.5f} };
217
      int[] centerIndices = new int[] { 0,0,-1,0,0,-1 };
218
      return new ObjectShape(VERTICES_CORNER,VERT_INDEXES_CORNER,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
219
      }
220
    }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223

    
224
  Static4D getQuat(int cubit, int numLayers)
225
    {
226
    return QUATS[QUAT_NUMBER[cubit]];
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230

    
231
  int getNumCubitVariants(int numLayers)
232
    {
233
    return 3;
234
    }
235

    
236
///////////////////////////////////////////////////////////////////////////////////////////////////
237

    
238
  int getCubitVariant(int cubit, int numLayers)
239
    {
240
    return cubit<2 ? 0 : (cubit<10 ? 1:2);
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
  ObjectSticker retSticker(int face)
246
    {
247
    return mStickers[face/NUM_FACES];
248
    }
249

    
250
///////////////////////////////////////////////////////////////////////////////////////////////////
251

    
252
  float[][] getCubitPositions(int numLayers)
253
    {
254
    return CENTERS;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  int getNumStickerTypes(int numLayers)
260
    {
261
    return NUM_STICKERS;
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  int getFaceColor(int cubit, int cubitface, int numLayers)
267
    {
268
    int type;
269

    
270
         if( cubit< 2             ) type = 0;
271
    else if( cubit<10             ) type = 1;
272
    else if( cubit>13 && cubit<22 ) type = 3;
273
    else                            type = 2;
274

    
275
    return mStickerType[type][cubitface]*FACE_COLORS.length + mStickerColor[cubit][cubitface];
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279
// PUBLIC API
280

    
281
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
282
    {
283
    int layer, nextAngle;
284

    
285
    if( curr==0 ) mLastRot = rnd.nextInt(4);
286

    
287
    switch(mLastRot)
288
      {
289
      case LAST_SL: layer = rnd.nextInt(2);
290
                    nextAngle = rnd.nextInt(12)-6;
291

    
292
                    if( nextAngle==0 )
293
                      {
294
                      layer = 1-layer;
295
                      nextAngle = (2*rnd.nextInt(2)-1)*(rnd.nextInt(5)+1);
296
                      }
297

    
298
                    scramble[curr][0] = 0;
299
                    scramble[curr][1] = 2*layer;
300
                    scramble[curr][2] = nextAngle;
301
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
302
                    break;
303
      case LAST_LO:
304
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
305
                    nextAngle = rnd.nextInt(12)-6;
306

    
307
                    if( nextAngle!=0 )
308
                      {
309
                      scramble[curr][0] = 0;
310
                      scramble[curr][1] = 2*layer;
311
                      scramble[curr][2] = nextAngle;
312
                      mLastRot = LAST_UL;
313
                      }
314
                    else
315
                      {
316
                      scramble[curr][0] = 1;
317
                      scramble[curr][1] = rnd.nextInt(2);
318
                      scramble[curr][2] = 1;
319
                      mLastRot = LAST_SL;
320
                      }
321
                    break;
322
      case LAST_UL: scramble[curr][0] = 1;
323
                    scramble[curr][1] = rnd.nextInt(2);
324
                    scramble[curr][2] = 1;
325
                    mLastRot = LAST_SL;
326
                    break;
327
      }
328
    }
329

    
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331
// Square-2 is solved iff
332
// a) all of its cubits are rotated with the same quat
333
// b) its two 'middle' cubits are rotated with the same quat, the 6 'front' and 6 'back'
334
// edges and corners with this quat multiplied by QUATS[18] (i.e. those are upside down)
335
// and all the 12 left and right edges and corners also with the same quat multiplied by
336
// QUATS[12] - i.e. also upside down.
337

    
338
  public boolean isSolved()
339
    {
340
    int index = CUBITS[0].mQuatIndex;
341

    
342
    if( CUBITS[1].mQuatIndex!=index ) return false;
343

    
344
    int indexX = mulQuat(index,12);  // QUATS[12] = 180deg (1,0,0)
345
    int indexZ = mulQuat(index,18);  // QUATS[18] = 180deg (0,0,1)
346

    
347
    for(int i=2; i<18; i+=2)
348
      {
349
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexZ ) return false;
350
      }
351
    for(int i=3; i<18; i+=2)
352
      {
353
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexX ) return false;
354
      }
355
    for(int i=18; i<NUM_CUBITS; i+=2)
356
      {
357
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexX ) return false;
358
      }
359
    for(int i=19; i<NUM_CUBITS; i+=2)
360
      {
361
      if( CUBITS[i].mQuatIndex != index && CUBITS[i].mQuatIndex != indexZ ) return false;
362
      }
363

    
364
    return true;
365
    }
366

    
367
///////////////////////////////////////////////////////////////////////////////////////////////////
368

    
369
  public int getObjectName(int numLayers)
370
    {
371
    return R.string.squa2;
372
    }
373

    
374
///////////////////////////////////////////////////////////////////////////////////////////////////
375

    
376
  public int getInventor(int numLayers)
377
    {
378
    return R.string.squa2_inventor;
379
    }
380

    
381
///////////////////////////////////////////////////////////////////////////////////////////////////
382

    
383
  public int getComplexity(int numLayers)
384
    {
385
    return 7;
386
    }
387
}
(40-40/41)