Project

General

Profile

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

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

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 NUM_STICKERS = 6;
39

    
40
  private final int[][] mPermittedAngles;
41
  private final int[] mCornerQuat;
42
  private int mPermittedUp, mPermittedDo;
43
  private ObjectSticker[] mStickers;
44
  private int[] mQuatNumber;
45
  private float[][] mCenters;
46
  private int[][] mBadCornerQuats;
47
  private int[][] mStickerColor;
48
  private int[][] mStickerType;
49

    
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51

    
52
  TwistySquare1(int size, Static4D quat, DistortedTexture texture, MeshSquare mesh,
53
                DistortedEffects effects, int[][] moves, Resources res, int scrWidth)
54
    {
55
    super(size, quat, texture, mesh, effects, moves, ObjectList.SQU1, res, scrWidth);
56

    
57
    if( mBasicAngle==null ) initializeBasicAngle();
58
    mLastRot = LAST_SL;
59
    mPermittedAngles = new int[2][mBasicAngle[0]];
60
    mCornerQuat = new int[8];
61
    }
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

    
65
  int[] getSolvedQuats(int cubit, int numLayers)
66
    {
67
    if( mQuats==null ) initializeQuats();
68
    int status = retCubitSolvedStatus(cubit,numLayers);
69
    return status<0 ? null : buildSolvedQuats(MovementSquare.FACE_AXIS[status],mQuats);
70
    }
71

    
72
///////////////////////////////////////////////////////////////////////////////////////////////////
73

    
74
  ObjectShape getObjectShape(int cubit, int numLayers)
75
    {
76
    int variant = getCubitVariant(cubit,numLayers);
77

    
78
    if( variant==0 )
79
      {
80
      double[][] vertices = new double[][]
81
        {
82
         { -1.5-X, 0.5, 1.5 },
83
         {    0.0, 0.5, 1.5 },
84
         {    0.0, 0.5,-1.5 },
85
         { -1.5+X, 0.5,-1.5 },
86
         { -1.5-X,-0.5, 1.5 },
87
         {    0.0,-0.5, 1.5 },
88
         {    0.0,-0.5,-1.5 },
89
         { -1.5+X,-0.5,-1.5 }
90
        };
91

    
92
      int[][] vert_indices = new int[][]
93
        {
94
         {0,1,2,3},
95
         {4,5,6,7},
96
         {4,5,1,0},
97
         {5,6,2,1},
98
         {6,7,3,2},
99
         {7,4,0,3}
100
        };
101

    
102
      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} };
103
      int[] bandIndices   = new int[] { 2,2,1,1,0,2 };
104
      float[][] corners   = new float[][] { {0.03f,0.05f} };
105
      int[] cornerIndices = new int[] { 0,0,0,0,0,0,0,0 };
106
      float[][] centers   = new float[][] { { -0.75f, 0.0f, 0.0f} };
107
      int[] centerIndices = new int[] { 0,0,0,0,0,0,0,0 };
108

    
109
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
110
      }
111
    else if( variant==1 )
112
      {
113
      double[][] vertices = new double[][]
114
        {
115
         { -X, 0.5, 0.0 },
116
         { +X, 0.5, 0.0 },
117
         {0.0, 0.5,-1.5 },
118
         { -X,-0.5, 0.0 },
119
         { +X,-0.5, 0.0 },
120
         {0.0,-0.5,-1.5 },
121
        };
122

    
123
      int[][] vert_indices = new int[][]
124
        {
125
         {0,1,2},
126
         {3,4,5},
127
         {3,4,1,0},
128
         {4,5,2,1},
129
         {5,3,0,2}
130
        };
131

    
132
      float[][] bands     = new float[][] { {0.038f,35,0.5f,0.9f, 5,2,1}, {0.001f,35,0.5f,0.9f, 5,2,1} };
133
      int[] bandIndices   = new int[] { 0,1,0,1,1 };
134
      float[][] corners   = new float[][] { {0.04f,0.15f} };
135
      int[] cornerIndices = new int[] { 0,0,-1,0,0,-1 };
136
      float[][] centers   = new float[][] { { 0.0f, 0.0f,-0.5f} };
137
      int[] centerIndices = new int[] { 0,0,-1,0,0,-1 };
138

    
139
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
140
      }
141
    else
142
      {
143
      double[][] vertices = new double[][]
144
        {
145
         { X-1.5, 0.5,  0.0 },
146
         {   0.0, 0.5,  0.0 },
147
         {   0.0, 0.5,X-1.5 },
148
         {  -1.5, 0.5, -1.5 },
149
         { X-1.5,-0.5,  0.0 },
150
         {   0.0,-0.5,  0.0 },
151
         {   0.0,-0.5,X-1.5 },
152
         {  -1.5,-0.5, -1.5 }
153
        };
154
      int[][] vert_indices = new int[][]
155
        {
156
         {0,1,2,3},
157
         {4,5,6,7},
158
         {4,5,1,0},
159
         {5,6,2,1},
160
         {7,4,0,3},
161
         {6,7,3,2}
162
        };
163

    
164
      float[][] bands     = new float[][] { {0.038f,35,0.9f,1.0f, 5,2,1}, {0.001f,35,0.9f,1.0f, 5,2,1} };
165
      int[] bandIndices   = new int[] { 0,1,0,0,1,1 };
166
      float[][] corners   = new float[][] { {0.05f,0.13f} };
167
      int[] cornerIndices = new int[] { 0,0,0,-1,0,0,0,-1 };
168
      float[][] centers   = new float[][] { { -0.5f, 0.0f,-0.5f} };
169
      int[] centerIndices = new int[] { -1,0,-1,-1,-1,0,-1,-1 };
170

    
171
      return new ObjectShape(vertices,vert_indices,bands,bandIndices,corners,cornerIndices,centers,centerIndices,getNumCubitFaces(), null);
172
      }
173
    }
174

    
175
///////////////////////////////////////////////////////////////////////////////////////////////////
176

    
177
  Static4D getQuat(int cubit, int numLayers)
178
    {
179
    if( mQuats==null ) initializeQuats();
180
    if( mQuatNumber ==null )
181
      {
182
      mQuatNumber = new int[]
183
        {
184
        0, 6,
185
        0, 9, 6, 3, 18, 15, 12, 21,
186
        0, 9, 6, 3, 15, 12, 21, 18
187
        };
188
      }
189

    
190
    return mQuats[mQuatNumber[cubit]];
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  int getNumCubitVariants(int numLayers)
196
    {
197
    return 3;
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201

    
202
  int getCubitVariant(int cubit, int numLayers)
203
    {
204
    return cubit<2 ? 0 : (cubit<10 ? 1:2);
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  ObjectSticker retSticker(int face)
210
    {
211
    if( mStickers==null )
212
      {
213
      float[][] STICKERS = new float[][]
214
        {
215
          { -0.5f, -0.26289170f, 0.5f, -0.26289170f, 0.5f, 0.26289170f, -0.5f, 0.26289170f }, // middle front
216
          { -0.5f, -0.16666667f, 0.5f, -0.16666667f, 0.5f, 0.16666667f, -0.5f, 0.16666667f }, // middle right
217
          { -0.5f, -0.45534182f, 0.5f, -0.45534182f, 0.5f, 0.45534182f, -0.5f, 0.45534182f }, // middle back
218
          { -0.20096192f, -0.25f, 0.20096192f, -0.25f, 0.0f, 0.5f },                          // edge top
219
          { -0.40192384f, -0.5f, 0.40192384f, -0.5f, 0.40192384f, 0.5f, -0.40192384f, 0.5f }, // edge face
220
          { -0.2637079f, -0.38185397f, 0.38185397f, -0.38185397f, 0.38185397f, 0.2637079f, -0.5f, 0.5f } // corner top
221
        };
222

    
223
      final float R1 = 0.06f;
224
      final float R2 = 0.04f;
225
      final float R3 = 0.11f;
226
      final float R4 = 0.03f;
227
      final float R5 = 0.11f;
228
      final float R6 = 0.08f;
229
      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} };
230
      final float[] strokes = { 0.05f,0.04f,0.09f,0.05f,0.08f,0.08f };
231

    
232
      mStickers = new ObjectSticker[NUM_STICKERS];
233

    
234
      for(int s=0; s<NUM_STICKERS; s++)
235
        {
236
        mStickers[s] = new ObjectSticker(STICKERS[s],null,radii[s],strokes[s]);
237
        }
238
      }
239

    
240
    return mStickers[face/NUM_FACES];
241
    }
242

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

    
245
  float[][] getCubitPositions(int numLayers)
246
    {
247
    if( mCenters==null )
248
      {
249
      mCenters = new float[][]
250
        {
251
         { 1.5f, 0.0f, 0.0f },
252
         {-1.5f, 0.0f, 0.0f },
253

    
254
         { 0.0f, 1.0f, 1.5f },
255
         { 1.5f, 1.0f, 0.0f },
256
         { 0.0f, 1.0f,-1.5f },
257
         {-1.5f, 1.0f, 0.0f },
258
         { 0.0f,-1.0f, 1.5f },
259
         { 1.5f,-1.0f, 0.0f },
260
         { 0.0f,-1.0f,-1.5f },
261
         {-1.5f,-1.0f, 0.0f },
262

    
263
         { 1.0f, 1.0f, 2.0f, 2.0f, 1.0f, 1.0f },
264
         { 1.0f, 1.0f,-2.0f, 2.0f, 1.0f,-1.0f },
265
         {-1.0f, 1.0f,-2.0f,-2.0f, 1.0f,-1.0f },
266
         {-1.0f, 1.0f, 2.0f,-2.0f, 1.0f, 1.0f },
267
         { 1.0f,-1.0f, 2.0f, 2.0f,-1.0f, 1.0f },
268
         { 1.0f,-1.0f,-2.0f, 2.0f,-1.0f,-1.0f },
269
         {-1.0f,-1.0f,-2.0f,-2.0f,-1.0f,-1.0f },
270
         {-1.0f,-1.0f, 2.0f,-2.0f,-1.0f, 1.0f }
271
        };
272
      }
273
    return mCenters;
274
    }
275

    
276
///////////////////////////////////////////////////////////////////////////////////////////////////
277

    
278
  int getSolvedFunctionIndex()
279
    {
280
    return 0;
281
    }
282

    
283
///////////////////////////////////////////////////////////////////////////////////////////////////
284

    
285
  int getNumStickerTypes(int numLayers)
286
    {
287
    return NUM_STICKERS;
288
    }
289

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291

    
292
  int getFaceColor(int cubit, int cubitface, int numLayers)
293
    {
294
    if( mStickerColor==null )
295
      {
296
      // YELLOW 0 WHITE 1 BLUE 2 GREEN 3 RED 4 ORANGE 5
297
      mStickerColor = new int[][]
298
        {
299
          { 0, 0, 4, 0, 5, 0 },
300
          { 0, 0, 5, 1, 4, 0 },
301

    
302
          { 2, 0, 4, 0, 0, 0 },
303
          { 2, 0, 0, 0, 0, 0 },
304
          { 2, 0, 5, 0, 0, 0 },
305
          { 2, 0, 1, 0, 0, 0 },
306
          { 3, 0, 4, 0, 0, 0 },
307
          { 3, 0, 0, 0, 0, 0 },
308
          { 3, 0, 5, 0, 0, 0 },
309
          { 3, 0, 1, 0, 0, 0 },
310

    
311
          { 2, 0, 4, 0, 0, 0 },
312
          { 2, 0, 0, 5, 0, 0 },
313
          { 2, 0, 5, 1, 0, 0 },
314
          { 2, 0, 1, 4, 0, 0 },
315
          { 3, 0, 0, 4, 0, 0 },
316
          { 3, 0, 5, 0, 0, 0 },
317
          { 3, 0, 1, 5, 0, 0 },
318
          { 3, 0, 4, 1, 0, 0 },
319
        };
320
      }
321

    
322
    if( mStickerType==null )
323
      {
324
      mStickerType = new int[][]
325
        {
326
          {  NUM_STICKERS,NUM_STICKERS,0,           1,           2,NUM_STICKERS },
327
          {             3,NUM_STICKERS,4,NUM_STICKERS,NUM_STICKERS,NUM_STICKERS },
328
          {             5,NUM_STICKERS,2,           2,NUM_STICKERS,NUM_STICKERS }
329
        };
330
      }
331

    
332
    int variant = getCubitVariant(cubit,numLayers);
333
    return mStickerType[variant][cubitface]*FACE_COLORS.length + mStickerColor[cubit][cubitface];
334
    }
335

    
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337

    
338
  private boolean cornerIsUp(int index)
339
    {
340
    return ((index<4) ^ (mCornerQuat[index]>=12));
341
    }
342

    
343
///////////////////////////////////////////////////////////////////////////////////////////////////
344

    
345
  private boolean cornerIsLeft(int index)
346
    {
347
    int q = mCornerQuat[index];
348

    
349
    switch(index)
350
      {
351
      case 0:
352
      case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
353
      case 1:
354
      case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
355
      case 2:
356
      case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
357
      case 3:
358
      case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
359
      }
360

    
361
    return false;
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
  private boolean quatIsBad(int quatIndex, int corner)
367
    {
368
    if( mBadCornerQuats ==null )
369
      {
370
      // quat indices that make corner cubits bandage the puzzle.
371
      mBadCornerQuats = new int[][] { { 2, 8,17,23}, { 5,11,14,20} };
372
      }
373

    
374
    int index = (corner%2);
375

    
376
    return ( quatIndex== mBadCornerQuats[index][0] ||
377
             quatIndex== mBadCornerQuats[index][1] ||
378
             quatIndex== mBadCornerQuats[index][2] ||
379
             quatIndex== mBadCornerQuats[index][3]  );
380
    }
381

    
382
///////////////////////////////////////////////////////////////////////////////////////////////////
383

    
384
  private boolean isPermittedDo(int angle)
385
    {
386
    if( mQuatMult==null ) initializeQuatMult();
387

    
388
    for(int corner=0; corner<8; corner++)
389
      {
390
      if( !cornerIsUp(corner) )
391
        {
392
        int currQuat = mCornerQuat[corner];
393
        int finalQuat= mQuatMult[angle][currQuat];
394
        if( quatIsBad(finalQuat,corner) ) return false;
395
        }
396
      }
397

    
398
    return true;
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  private boolean isPermittedUp(int angle)
404
    {
405
    if( mQuatMult==null ) initializeQuatMult();
406

    
407
    for(int corner=0; corner<8; corner++)
408
      {
409
      if( cornerIsUp(corner) )
410
        {
411
        int currQuat = mCornerQuat[corner];
412
        int finalQuat= mQuatMult[angle][currQuat];
413
        if( quatIsBad(finalQuat,corner) ) return false;
414
        }
415
      }
416

    
417
    return true;
418
    }
419

    
420
///////////////////////////////////////////////////////////////////////////////////////////////////
421

    
422
  private void computePermittedAngles()
423
    {
424
    if( mBasicAngle==null ) initializeBasicAngle();
425

    
426
    mPermittedDo = 0;
427

    
428
    for(int angle=0; angle<mBasicAngle[0]; angle++)
429
      {
430
      if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
431
      }
432

    
433
    mPermittedUp = 0;
434

    
435
    for(int angle=0; angle<mBasicAngle[0]; angle++)
436
      {
437
      if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
438
      }
439
    }
440

    
441
///////////////////////////////////////////////////////////////////////////////////////////////////
442

    
443
  private int getNextAngle(Random rnd, int layer)
444
    {
445
    if( mBasicAngle==null ) initializeBasicAngle();
446
    int basic = mBasicAngle[0];
447
    int num = layer==0 ? mPermittedDo:mPermittedUp;
448
    int index = rnd.nextInt(num);
449
    int angle = mPermittedAngles[layer][index];
450
    return angle<basic/2 ? -angle : basic-angle;
451
    }
452

    
453
///////////////////////////////////////////////////////////////////////////////////////////////////
454

    
455
  private int getNextAngleNotZero(Random rnd, int layer)
456
    {
457
    if( mBasicAngle==null ) initializeBasicAngle();
458
    int basic = mBasicAngle[0];
459
    int num = layer==0 ? mPermittedDo:mPermittedUp;
460
    int index = rnd.nextInt(num-1);
461
    int angle = mPermittedAngles[layer][index+1];
462
    return angle<basic/2 ? -angle : basic-angle;
463
    }
464

    
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466

    
467
  private int makeQuat(int axis,int index)
468
    {
469
    if( axis==1 ) return 13;
470
    if( index<0 ) index+=12;
471
    return index;
472
    }
473

    
474
///////////////////////////////////////////////////////////////////////////////////////////////////
475

    
476
  private boolean cornerBelongs(int index, int axis, int layer)
477
    {
478
    if( axis==0 )
479
      {
480
      boolean up = cornerIsUp(index);
481
      return ((up && layer==2) || (!up && layer==0));
482
      }
483
    else
484
      {
485
      boolean le = cornerIsLeft(index);
486
      return ((le && layer==0) || (!le && layer==1));
487
      }
488
    }
489

    
490
///////////////////////////////////////////////////////////////////////////////////////////////////
491

    
492
  private void updateCornerQuats(int[] rotInfo)
493
    {
494
    if( mQuatMult==null ) initializeQuatMult();
495

    
496
    int axis = rotInfo[0];
497
    int layer= rotInfo[1];
498
    int index=-rotInfo[2];
499

    
500
    int quat = makeQuat(axis,index);
501

    
502
    for(int corner=0; corner<8; corner++)
503
      {
504
      if( cornerBelongs(corner,axis,layer) )
505
        {
506
        int curr = mCornerQuat[corner];
507
        mCornerQuat[corner] = mQuatMult[quat][curr];
508
        }
509
      }
510
    }
511

    
512
///////////////////////////////////////////////////////////////////////////////////////////////////
513
// PUBLIC API
514

    
515
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total)
516
    {
517
    int layer, nextAngle;
518

    
519
    if( curr==0 )
520
      {
521
      for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
522
      mLastRot = rnd.nextInt(4);
523
      computePermittedAngles();
524
      }
525

    
526
    switch(mLastRot)
527
      {
528
      case LAST_SL: layer = rnd.nextInt(2);
529
                    nextAngle = getNextAngle(rnd,layer);
530

    
531
                    if( nextAngle==0 )
532
                      {
533
                      layer = 1-layer;
534
                      nextAngle = getNextAngleNotZero(rnd,layer);
535
                      }
536

    
537
                    scramble[curr][0] = 0;
538
                    scramble[curr][1] = 2*layer;
539
                    scramble[curr][2] = nextAngle;
540
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
541
                    updateCornerQuats(scramble[curr]);
542
                    break;
543
      case LAST_LO:
544
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
545
                    nextAngle = getNextAngle(rnd,layer);
546

    
547
                    if( nextAngle!=0 )
548
                      {
549
                      scramble[curr][0] = 0;
550
                      scramble[curr][1] = 2*layer;
551
                      scramble[curr][2] = nextAngle;
552
                      updateCornerQuats(scramble[curr]);
553
                      mLastRot = LAST_UL;
554
                      }
555
                    else
556
                      {
557
                      scramble[curr][0] = 1;
558
                      scramble[curr][1] = rnd.nextInt(2);
559
                      scramble[curr][2] = 1;
560
                      mLastRot = LAST_SL;
561
                      updateCornerQuats(scramble[curr]);
562
                      computePermittedAngles();
563
                      }
564

    
565
                    break;
566
      case LAST_UL: scramble[curr][0] = 1;
567
                    scramble[curr][1] = rnd.nextInt(2);
568
                    scramble[curr][2] = 1;
569
                    mLastRot = LAST_SL;
570
                    updateCornerQuats(scramble[curr]);
571
                    computePermittedAngles();
572
                    break;
573
      }
574
    }
575

    
576
///////////////////////////////////////////////////////////////////////////////////////////////////
577

    
578
  public int getObjectName(int numLayers)
579
    {
580
    return R.string.squa1;
581
    }
582

    
583
///////////////////////////////////////////////////////////////////////////////////////////////////
584

    
585
  public int getInventor(int numLayers)
586
    {
587
    return R.string.squa1_inventor;
588
    }
589

    
590
///////////////////////////////////////////////////////////////////////////////////////////////////
591

    
592
  public int getComplexity(int numLayers)
593
    {
594
    return 9;
595
    }
596
}
(39-39/41)