Project

General

Profile

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

magiccube / src / main / java / org / distorted / objects / TwistySquare1.java @ e42a9e87

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 TwistySquare1 extends TwistySquare
37
{
38
  private static final int[] QUAT_NUMBER = new int[]
39
    {
40
      0, 6,
41
      0, 9, 6, 3, 18, 15, 12, 21,
42
      0, 9, 6, 3, 15, 12, 21, 18
43
    };
44

    
45
  // centers of the 2 middles + 8 edges + 8 corners
46
  private static final float[][] CENTERS = new float[][]
47
    {
48
      { 1.5f, 0.0f, 0.0f },
49
      {-1.5f, 0.0f, 0.0f },
50

    
51
      { 0.0f, 1.0f, 1.5f },
52
      { 1.5f, 1.0f, 0.0f },
53
      { 0.0f, 1.0f,-1.5f },
54
      {-1.5f, 1.0f, 0.0f },
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

    
60
      { 1.0f, 1.0f, 2.0f, 2.0f, 1.0f, 1.0f },
61
      { 1.0f, 1.0f,-2.0f, 2.0f, 1.0f,-1.0f },
62
      {-1.0f, 1.0f,-2.0f,-2.0f, 1.0f,-1.0f },
63
      {-1.0f, 1.0f, 2.0f,-2.0f, 1.0f, 1.0f },
64
      { 1.0f,-1.0f, 2.0f, 2.0f,-1.0f, 1.0f },
65
      { 1.0f,-1.0f,-2.0f, 2.0f,-1.0f,-1.0f },
66
      {-1.0f,-1.0f,-2.0f,-2.0f,-1.0f,-1.0f },
67
      {-1.0f,-1.0f, 2.0f,-2.0f,-1.0f, 1.0f }
68
    };
69

    
70
  private static final double[][] VERTICES_CORNER = new double[][]
71
    {
72
      { X-1.5, 0.5,  0.0 },
73
      {   0.0, 0.5,  0.0 },
74
      {   0.0, 0.5,X-1.5 },
75
      {  -1.5, 0.5, -1.5 },
76
      { X-1.5,-0.5,  0.0 },
77
      {   0.0,-0.5,  0.0 },
78
      {   0.0,-0.5,X-1.5 },
79
      {  -1.5,-0.5, -1.5 }
80
    };
81

    
82
  private static final int[][] VERT_INDEXES_CORNER = new int[][]
83
    {
84
      {0,1,2,3},   // counterclockwise!
85
      {4,5,6,7},
86
      {4,5,1,0},
87
      {5,6,2,1},
88
      {7,4,0,3},
89
      {6,7,3,2}
90
    };
91

    
92
  private static final float[][] STICKERS = new float[][]
93
    {
94
      { -0.5f, -0.26289170f, 0.5f, -0.26289170f, 0.5f, 0.26289170f, -0.5f, 0.26289170f }, // middle front
95
      { -0.5f, -0.16666667f, 0.5f, -0.16666667f, 0.5f, 0.16666667f, -0.5f, 0.16666667f }, // middle right
96
      { -0.5f, -0.45534182f, 0.5f, -0.45534182f, 0.5f, 0.45534182f, -0.5f, 0.45534182f }, // middle back
97
      { -0.20096192f, -0.25f, 0.20096192f, -0.25f, 0.0f, 0.5f },                          // edge top
98
      { -0.40192384f, -0.5f, 0.40192384f, -0.5f, 0.40192384f, 0.5f, -0.40192384f, 0.5f }, // edge face
99
      { -0.2637079f, -0.38185397f, 0.38185397f, -0.38185397f, 0.38185397f, 0.2637079f, -0.5f, 0.5f } // corner top
100
    };
101

    
102
  private static final int NUM_STICKERS = STICKERS.length;
103

    
104
  private static final int[][] mStickerType = new int[][]
105
    {
106
      {  NUM_STICKERS,NUM_STICKERS,0,           1,           2,NUM_STICKERS },
107
      {             3,NUM_STICKERS,4,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS },
108
      {             5,NUM_STICKERS,2,           2,NUM_STICKERS,NUM_STICKERS }
109
    };
110

    
111
  // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4 ORANGE 5
112
  private static final int[][] mStickerColor = new int[][]
113
    {
114
      { 0, 0, 4, 0, 5, 0 },
115
      { 0, 0, 5, 1, 4, 0 },
116

    
117
      { 2, 0, 4, 0, 0, 0 },
118
      { 2, 0, 0, 0, 0, 0 },
119
      { 2, 0, 5, 0, 0, 0 },
120
      { 2, 0, 1, 0, 0, 0 },
121
      { 3, 0, 4, 0, 0, 0 },
122
      { 3, 0, 0, 0, 0, 0 },
123
      { 3, 0, 5, 0, 0, 0 },
124
      { 3, 0, 1, 0, 0, 0 },
125

    
126
      { 2, 0, 4, 0, 0, 0 },
127
      { 2, 0, 0, 5, 0, 0 },
128
      { 2, 0, 5, 1, 0, 0 },
129
      { 2, 0, 1, 4, 0, 0 },
130
      { 3, 0, 0, 4, 0, 0 },
131
      { 3, 0, 5, 0, 0, 0 },
132
      { 3, 0, 1, 5, 0, 0 },
133
      { 3, 0, 4, 1, 0, 0 },
134
    };
135

    
136
  // quat indices that make corner cubits bandage the puzzle.
137
  private static final int[][] BAD_CORNER_QUATS = new int[][]
138
    {
139
      { 2, 8,17,23},
140
      { 5,11,14,20},
141
    };
142

    
143
  private final int[][] mPermittedAngles;
144
  private final int[] mCornerQuat;
145
  private int mPermittedUp, mPermittedDo;
146

    
147
  private static final ObjectSticker[] mStickers;
148

    
149
  static
150
    {
151
    mStickers = new ObjectSticker[NUM_STICKERS];
152
    final float R1 = 0.06f;
153
    final float R2 = 0.04f;
154
    final float R3 = 0.11f;
155
    final float R4 = 0.03f;
156
    final float R5 = 0.11f;
157
    final float R6 = 0.08f;
158
    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,R6} };
159
    final float[] strokes = { 0.05f,0.04f,0.09f,0.05f,0.08f,0.08f };
160

    
161
    for(int s=0; s<NUM_STICKERS; s++)
162
      {
163
      mStickers[s] = new ObjectSticker(STICKERS[s],null,radii[s],strokes[s]);
164
      }
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  TwistySquare1(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
170
                DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
171
    {
172
    super(size, quat, texture, mesh, effects, moves, ObjectList.SQU1, res, scrWidth);
173

    
174
    mLastRot = LAST_SL;
175
    mPermittedAngles = new int[2][BASIC_ANGLE[0]];
176
    mCornerQuat = new int[8];
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
  int[] getSolvedQuats(int cubit, int numLayers)
182
    {
183
    int status = retCubitSolvedStatus(cubit,numLayers);
184
    return status<0 ? null : buildSolvedQuats(MovementSquare.FACE_AXIS[status],QUATS);
185
    }
186

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

    
189
  ObjectShape getObjectShape(int cubit, int numLayers)
190
    {
191
    int variant = getCubitVariant(cubit,numLayers);
192

    
193
    if( variant==0 )
194
      {
195
      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} };
196
      int[] bandIndices   = new int[] { 2,2,1,1,0,2 };
197
      float[][] corners   = new float[][] { {0.03f,0.05f} };
198
      int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
199
      float[][] centers   = new float[][] { { -0.75f, 0.0f, 0.0f} };
200
      int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
201

    
202
      return new ObjectShape(VERTICES_MIDDLE,VERT_INDEXES_MIDDLE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
203
      }
204
    else if( variant==1 )
205
      {
206
      float[][] bands     = new float[][] { {0.038f,35,0.5f,0.9f, 5,2,1}, {0.001f,35,0.5f,0.9f, 5,2,1} };
207
      int[] bandIndices   = new int[] { 0,1,0,1,1 };
208
      float[][] corners   = new float[][] { {0.04f,0.15f} };
209
      int[] cornerIndices = new int[] { 0,0,-1,0,0,-1 };
210
      float[][] centers   = new float[][] { { 0.0f, 0.0f,-0.5f} };
211
      int[] centerIndices = new int[] { 0,0,-1,0,0,-1 };
212

    
213
      return new ObjectShape(VERTICES_EDGE,VERT_INDEXES_EDGE,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
214
      }
215
    else
216
      {
217
      float[][] bands     = new float[][] { {0.038f,35,0.9f,1.0f, 5,2,1}, {0.001f,35,0.9f,1.0f, 5,2,1} };
218
      int[] bandIndices   = new int[] { 0,1,0,0,1,1 };
219
      float[][] corners   = new float[][] { {0.05f,0.13f} };
220
      int[] cornerIndices = new int[] { 0,0,0,-1,0,0,0,-1 };
221
      float[][] centers   = new float[][] { { -0.5f, 0.0f,-0.5f} };
222
      int[] centerIndices = new int[] { -1,0,-1,-1,-1,0,-1,-1 };
223

    
224
      return new ObjectShape(VERTICES_CORNER,VERT_INDEXES_CORNER,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
225
      }
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  Static4D getQuat(int cubit, int numLayers)
231
    {
232
    return QUATS[QUAT_NUMBER[cubit]];
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  int getNumCubitVariants(int numLayers)
238
    {
239
    return 3;
240
    }
241

    
242
///////////////////////////////////////////////////////////////////////////////////////////////////
243

    
244
  int getCubitVariant(int cubit, int numLayers)
245
    {
246
    return cubit<2 ? 0 : (cubit<10 ? 1:2);
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  ObjectSticker retSticker(int face)
252
    {
253
    return mStickers[face/NUM_FACES];
254
    }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257

    
258
  float[][] getCubitPositions(int numLayers)
259
    {
260
    return CENTERS;
261
    }
262

    
263
///////////////////////////////////////////////////////////////////////////////////////////////////
264

    
265
  int getSolvedFunctionIndex()
266
    {
267
    return 0;
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
  int getNumStickerTypes(int numLayers)
273
    {
274
    return NUM_STICKERS;
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  int getFaceColor(int cubit, int cubitface, int numLayers)
280
    {
281
    int variant = getCubitVariant(cubit,numLayers);
282
    return mStickerType[variant][cubitface]*FACE_COLORS.length + mStickerColor[cubit][cubitface];
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  private boolean cornerIsUp(int index)
288
    {
289
    return ((index<4) ^ (mCornerQuat[index]>=12));
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  private boolean cornerIsLeft(int index)
295
    {
296
    int q = mCornerQuat[index];
297

    
298
    switch(index)
299
      {
300
      case 0:
301
      case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
302
      case 1:
303
      case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
304
      case 2:
305
      case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
306
      case 3:
307
      case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
308
      }
309

    
310
    return false;
311
    }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314

    
315
  private boolean quatIsBad(int quatIndex, int corner)
316
    {
317
    int index = (corner%2);
318

    
319
    return ( quatIndex==BAD_CORNER_QUATS[index][0] ||
320
             quatIndex==BAD_CORNER_QUATS[index][1] ||
321
             quatIndex==BAD_CORNER_QUATS[index][2] ||
322
             quatIndex==BAD_CORNER_QUATS[index][3]  );
323
    }
324

    
325
///////////////////////////////////////////////////////////////////////////////////////////////////
326

    
327
  private boolean isPermittedDo(int angle)
328
    {
329
    for(int corner=0; corner<8; corner++)
330
      {
331
      if( !cornerIsUp(corner) )
332
        {
333
        int currQuat = mCornerQuat[corner];
334
        int finalQuat= QUAT_MULT[angle][currQuat];
335
        if( quatIsBad(finalQuat,corner) ) return false;
336
        }
337
      }
338

    
339
    return true;
340
    }
341

    
342
///////////////////////////////////////////////////////////////////////////////////////////////////
343

    
344
  private boolean isPermittedUp(int angle)
345
    {
346
    for(int corner=0; corner<8; corner++)
347
      {
348
      if( cornerIsUp(corner) )
349
        {
350
        int currQuat = mCornerQuat[corner];
351
        int finalQuat= QUAT_MULT[angle][currQuat];
352
        if( quatIsBad(finalQuat,corner) ) return false;
353
        }
354
      }
355

    
356
    return true;
357
    }
358

    
359
///////////////////////////////////////////////////////////////////////////////////////////////////
360

    
361
  private void computePermittedAngles()
362
    {
363
    mPermittedDo = 0;
364

    
365
    for(int angle=0; angle<BASIC_ANGLE[0]; angle++)
366
      {
367
      if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
368
      }
369

    
370
    mPermittedUp = 0;
371

    
372
    for(int angle=0; angle<BASIC_ANGLE[0]; angle++)
373
      {
374
      if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
375
      }
376
    }
377

    
378
///////////////////////////////////////////////////////////////////////////////////////////////////
379

    
380
  private int getNextAngle(Random rnd, int layer)
381
    {
382
    int basic = BASIC_ANGLE[0];
383
    int num = layer==0 ? mPermittedDo:mPermittedUp;
384
    int index = rnd.nextInt(num);
385
    int angle = mPermittedAngles[layer][index];
386
    return angle<basic/2 ? -angle : basic-angle;
387
    }
388

    
389
///////////////////////////////////////////////////////////////////////////////////////////////////
390

    
391
  private int getNextAngleNotZero(Random rnd, int layer)
392
    {
393
    int basic = BASIC_ANGLE[0];
394
    int num = layer==0 ? mPermittedDo:mPermittedUp;
395
    int index = rnd.nextInt(num-1);
396
    int angle = mPermittedAngles[layer][index+1];
397
    return angle<basic/2 ? -angle : basic-angle;
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401

    
402
  private int makeQuat(int axis,int index)
403
    {
404
    if( axis==1 ) return 13;
405
    if( index<0 ) index+=12;
406
    return index;
407
    }
408

    
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

    
411
  private boolean cornerBelongs(int index, int axis, int layer)
412
    {
413
    if( axis==0 )
414
      {
415
      boolean up = cornerIsUp(index);
416
      return ((up && layer==2) || (!up && layer==0));
417
      }
418
    else
419
      {
420
      boolean le = cornerIsLeft(index);
421
      return ((le && layer==0) || (!le && layer==1));
422
      }
423
    }
424

    
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

    
427
  private void updateCornerQuats(int[] rotInfo)
428
    {
429
    int axis = rotInfo[0];
430
    int layer= rotInfo[1];
431
    int index=-rotInfo[2];
432

    
433
    int quat = makeQuat(axis,index);
434

    
435
    for(int corner=0; corner<8; corner++)
436
      {
437
      if( cornerBelongs(corner,axis,layer) )
438
        {
439
        int curr = mCornerQuat[corner];
440
        mCornerQuat[corner] = QUAT_MULT[quat][curr];
441
        }
442
      }
443
    }
444

    
445
///////////////////////////////////////////////////////////////////////////////////////////////////
446
// PUBLIC API
447

    
448
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
449
    {
450
    int layer, nextAngle;
451

    
452
    if( curr==0 )
453
      {
454
      for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
455
      mLastRot = rnd.nextInt(4);
456
      computePermittedAngles();
457
      }
458

    
459
    switch(mLastRot)
460
      {
461
      case LAST_SL: layer = rnd.nextInt(2);
462
                    nextAngle = getNextAngle(rnd,layer);
463

    
464
                    if( nextAngle==0 )
465
                      {
466
                      layer = 1-layer;
467
                      nextAngle = getNextAngleNotZero(rnd,layer);
468
                      }
469

    
470
                    scramble[curr][0] = 0;
471
                    scramble[curr][1] = 2*layer;
472
                    scramble[curr][2] = nextAngle;
473
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
474
                    updateCornerQuats(scramble[curr]);
475
                    break;
476
      case LAST_LO:
477
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
478
                    nextAngle = getNextAngle(rnd,layer);
479

    
480
                    if( nextAngle!=0 )
481
                      {
482
                      scramble[curr][0] = 0;
483
                      scramble[curr][1] = 2*layer;
484
                      scramble[curr][2] = nextAngle;
485
                      updateCornerQuats(scramble[curr]);
486
                      mLastRot = LAST_UL;
487
                      }
488
                    else
489
                      {
490
                      scramble[curr][0] = 1;
491
                      scramble[curr][1] = rnd.nextInt(2);
492
                      scramble[curr][2] = 1;
493
                      mLastRot = LAST_SL;
494
                      updateCornerQuats(scramble[curr]);
495
                      computePermittedAngles();
496
                      }
497

    
498
                    break;
499
      case LAST_UL: scramble[curr][0] = 1;
500
                    scramble[curr][1] = rnd.nextInt(2);
501
                    scramble[curr][2] = 1;
502
                    mLastRot = LAST_SL;
503
                    updateCornerQuats(scramble[curr]);
504
                    computePermittedAngles();
505
                    break;
506
      }
507
    }
508

    
509
///////////////////////////////////////////////////////////////////////////////////////////////////
510

    
511
  public int getObjectName(int numLayers)
512
    {
513
    return R.string.squa1;
514
    }
515

    
516
///////////////////////////////////////////////////////////////////////////////////////////////////
517

    
518
  public int getInventor(int numLayers)
519
    {
520
    return R.string.squa1_inventor;
521
    }
522

    
523
///////////////////////////////////////////////////////////////////////////////////////////////////
524

    
525
  public int getComplexity(int numLayers)
526
    {
527
    return 9;
528
    }
529
}
(39-39/41)