Project

General

Profile

Download (22 KB) Statistics
| Branch: | Revision:

distorted-objectlib / src / main / java / org / distorted / objectlib / scrambling / ObjectScrambler.java @ ee28f820

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is proprietary software licensed under an EULA which you should have received      //
7
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html        //
8
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.scrambling;
11

    
12
import java.util.ArrayList;
13
import java.util.Random;
14

    
15
import org.distorted.objectlib.helpers.ObjectSignature;
16

    
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18

    
19
public class ObjectScrambler
20
  {
21
  public static final int SCRAMBLING_ALGORITHMS = 0;
22
  public static final int SCRAMBLING_SQUARE1    = 1;
23
  public static final int SCRAMBLING_BANDAGED   = 2;
24
  public static final int SCRAMBLING_TABLEBASES = 3;
25

    
26
  private final ScrambleState[] mStates;
27
  private final int mType;
28
  private final int mNumAxis;
29
  private final int[] mNumLayers;
30
  private final int[][] mAlgorithms;
31

    
32
  // type=0, i.e. main
33
  private int mCurrState;
34
  private int mAxisExcluded;
35
  private int[][] mScrambleTable;
36
  private int[] mNumOccurences;
37
  private int[] mResult;
38
  private int mCurrAlgorithm;
39
  private int mCurrStep;
40

    
41
  // type=1, i.e. the exception: Square-1
42
  private static final int BASIC_ANGLE = 12;
43
  private static final int LAST_SL = 0; // automatic rotations: last rot was a 'slash' i.e. along ROT_AXIS[1]
44
  private static final int LAST_UP = 1; // last rot was along ROT_AXIS[0], upper layer and forelast was a slash
45
  private static final int LAST_LO = 2; // last rot was along ROT_AXIS[0], lower layer and forelast was a slash
46
  private static final int LAST_UL = 3; // two last rots were along ROT_AXIS[0] (so the next must be a slash)
47

    
48
  private int[][] mPermittedAngles;
49
  private int[] mCornerQuat;
50
  private int mPermittedUp, mPermittedDo;
51
  private int[][] mBadCornerQuats;
52
  private int mLastRot;
53
  private int[][] mQuatMult;
54

    
55
  // type=2 , i.e. locally created bandaged cuboids
56
  private ArrayList<ScrambleStateBandagedCuboid> mStatesHistory;
57
  private BlacklistedSignatures mBlacklisted;
58

    
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

    
61
  public ObjectScrambler(int type, int numAxis, int[] numLayers, int[][] algorithms, int[][] edges)
62
    {
63
    mType       = type;
64
    mNumAxis    = numAxis;
65
    mNumLayers  = numLayers;
66
    mAlgorithms = algorithms;
67

    
68
    if( mType==0 )
69
      {
70
      mResult = new int[2];
71
      }
72

    
73
    if( edges!=null )
74
      {
75
      int numEdges = edges.length;
76
      mStates = new ScrambleState[numEdges];
77
      for(int i=0; i<numEdges; i++) mStates[i] = new ScrambleState(edges[i],algorithms);
78
      }
79
    else mStates = null;
80

    
81
    if( mType==1 )
82
      {
83
      mPermittedAngles = new int[2][BASIC_ANGLE];
84
      mCornerQuat = new int[8];
85
      mLastRot = LAST_SL;
86
      }
87
    }
88

    
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90

    
91
  private void initializeScrambling()
92
    {
93
    if( mScrambleTable==null )
94
      {
95
      mScrambleTable = new int[mNumAxis][];
96
      }
97
    if( mNumOccurences==null )
98
      {
99
      int max=0;
100

    
101
      for (ScrambleState mState : mStates)
102
        {
103
        int tmp = mState.getTotal();
104
        if (max < tmp) max = tmp;
105
        }
106

    
107
      mNumOccurences = new int[max];
108
      }
109

    
110
    for(int i=0; i<mNumAxis; i++)
111
      {
112
      int len = mNumLayers[i];
113
      mScrambleTable[i] = new int[len];
114
      for(int j=0; j<len; j++) mScrambleTable[i][j] = 0;
115
      }
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
// PUBLIC API
120

    
121
  private void randomizeNewScramble0(int[][] scramble, Random rnd, int curr)
122
    {
123
    if( curr==0 )
124
      {
125
      mCurrStep     = 100000;
126
      mCurrState    = 0;
127
      mAxisExcluded =-1;
128
      initializeScrambling();
129
      }
130

    
131
    if( mCurrStep+6 <= mAlgorithms[mCurrAlgorithm].length )
132
      {
133
      mCurrStep += 3;
134
      }
135
    else
136
      {
137
      mStates[mCurrState].getRandom(rnd, mAlgorithms, mAxisExcluded, mScrambleTable, mNumOccurences, mResult);
138
      mCurrAlgorithm = mResult[0];
139
      mCurrState     = mResult[1];
140
      mCurrStep      = 0;
141
      }
142

    
143
    int[] algorithm = mAlgorithms[mCurrAlgorithm];
144
    scramble[curr][0] = algorithm[mCurrStep  ];
145
    scramble[curr][1] = algorithm[mCurrStep+1];
146
    scramble[curr][2] = algorithm[mCurrStep+2];
147

    
148
    mAxisExcluded = algorithm[0];
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152
// TYPE 1
153
///////////////////////////////////////////////////////////////////////////////////////////////////
154
// QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156

    
157
  void initializeQuatMult()
158
    {
159
    mQuatMult = new int[][]
160
      {
161
        {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,},
162
        {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12,},
163
        {  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13,},
164
        {  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14,},
165
        {  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15,},
166
        {  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16,},
167
        {  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17,},
168
        {  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18,},
169
        {  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19,},
170
        {  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20,},
171
        { 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,},
172
        { 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,},
173
        { 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,},
174
        { 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,},
175
        { 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,},
176
        { 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,},
177
        { 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,},
178
        { 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,},
179
        { 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,},
180
        { 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,},
181
        { 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,},
182
        { 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,},
183
        { 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11,},
184
        { 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,}
185
      };
186
    }
187

    
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
// TYPE 1
190

    
191
  private boolean cornerIsUp(int index)
192
    {
193
    return ((index<4) ^ (mCornerQuat[index]>=12));
194
    }
195

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197
// TYPE 1
198

    
199
  private boolean cornerIsLeft(int index)
200
    {
201
    int q = mCornerQuat[index];
202

    
203
    switch(index)
204
      {
205
      case 0:
206
      case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
207
      case 1:
208
      case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
209
      case 2:
210
      case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
211
      case 3:
212
      case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
213
      }
214

    
215
    return false;
216
    }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219
// TYPE 1
220

    
221
  private boolean quatIsBad(int quatIndex, int corner)
222
    {
223
    if( mBadCornerQuats ==null )
224
      {
225
      // quat indices that make corner cubits bandage the puzzle.
226
      mBadCornerQuats = new int[][] { { 2, 8,17,23}, { 5,11,14,20} };
227
      }
228

    
229
    int index = (corner%2);
230

    
231
    return ( quatIndex== mBadCornerQuats[index][0] ||
232
             quatIndex== mBadCornerQuats[index][1] ||
233
             quatIndex== mBadCornerQuats[index][2] ||
234
             quatIndex== mBadCornerQuats[index][3]  );
235
    }
236

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238
// TYPE 1
239

    
240
  private boolean isPermittedDo(int angle)
241
    {
242
    if( mQuatMult==null ) initializeQuatMult();
243

    
244
    for(int corner=0; corner<8; corner++)
245
      {
246
      if( !cornerIsUp(corner) )
247
        {
248
        int currQuat = mCornerQuat[corner];
249
        int finalQuat= mQuatMult[angle][currQuat];
250
        if( quatIsBad(finalQuat,corner) ) return false;
251
        }
252
      }
253

    
254
    return true;
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258
// TYPE 1
259

    
260
  private boolean isPermittedUp(int angle)
261
    {
262
    if( mQuatMult==null ) initializeQuatMult();
263

    
264
    for(int corner=0; corner<8; corner++)
265
      {
266
      if( cornerIsUp(corner) )
267
        {
268
        int currQuat = mCornerQuat[corner];
269
        int finalQuat= mQuatMult[angle][currQuat];
270
        if( quatIsBad(finalQuat,corner) ) return false;
271
        }
272
      }
273

    
274
    return true;
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278
// TYPE 1
279

    
280
  private void computePermittedAngles()
281
    {
282
    mPermittedDo = 0;
283

    
284
    for(int angle=0; angle<BASIC_ANGLE; angle++)
285
      {
286
      if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
287
      }
288

    
289
    mPermittedUp = 0;
290

    
291
    for(int angle=0; angle<BASIC_ANGLE; angle++)
292
      {
293
      if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
294
      }
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298
// TYPE 1
299

    
300
  private int getNextAngle(Random rnd, int layer)
301
    {
302
    int num = layer==0 ? mPermittedDo:mPermittedUp;
303
    int index = rnd.nextInt(num);
304
    int angle = mPermittedAngles[layer][index];
305
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
306
    }
307

    
308
///////////////////////////////////////////////////////////////////////////////////////////////////
309
// TYPE 1
310

    
311
  private int getNextAngleNotZero(Random rnd, int layer)
312
    {
313
    int num = layer==0 ? mPermittedDo:mPermittedUp;
314
    int index = rnd.nextInt(num-1);
315
    int angle = mPermittedAngles[layer][index+1];
316
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
317
    }
318

    
319
///////////////////////////////////////////////////////////////////////////////////////////////////
320
// TYPE 1
321

    
322
  private int makeQuat(int axis,int index)
323
    {
324
    if( axis==1 ) return 13;
325
    if( index<0 ) index+=12;
326
    return index;
327
    }
328

    
329
///////////////////////////////////////////////////////////////////////////////////////////////////
330
// TYPE 1
331

    
332
  private boolean cornerBelongs(int index, int axis, int layer)
333
    {
334
    if( axis==0 )
335
      {
336
      boolean up = cornerIsUp(index);
337
      return ((up && layer==2) || (!up && layer==0));
338
      }
339
    else
340
      {
341
      boolean le = cornerIsLeft(index);
342
      return ((le && layer==0) || (!le && layer==1));
343
      }
344
    }
345

    
346
///////////////////////////////////////////////////////////////////////////////////////////////////
347
// TYPE 1
348

    
349
  private void updateCornerQuats(int[] rotInfo)
350
    {
351
    if( mQuatMult==null ) initializeQuatMult();
352

    
353
    int axis = rotInfo[0];
354
    int layer= rotInfo[1];
355
    int index=-rotInfo[2];
356

    
357
    int quat = makeQuat(axis,index);
358

    
359
    for(int corner=0; corner<8; corner++)
360
      {
361
      if( cornerBelongs(corner,axis,layer) )
362
        {
363
        int curr = mCornerQuat[corner];
364
        mCornerQuat[corner] = mQuatMult[quat][curr];
365
        }
366
      }
367
    }
368

    
369
///////////////////////////////////////////////////////////////////////////////////////////////////
370
// TYPE 1
371

    
372
  private void randomizeNewScramble1(int[][] scramble, Random rnd, int curr)
373
    {
374
    int layer, nextAngle;
375

    
376
    if( curr==0 )
377
      {
378
      for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
379
      mLastRot = rnd.nextInt(4);
380
      computePermittedAngles();
381
      }
382

    
383
    switch(mLastRot)
384
      {
385
      case LAST_SL: layer = rnd.nextInt(2);
386
                    nextAngle = getNextAngle(rnd,layer);
387

    
388
                    if( nextAngle==0 )
389
                      {
390
                      layer = 1-layer;
391
                      nextAngle = getNextAngleNotZero(rnd,layer);
392
                      }
393

    
394
                    scramble[curr][0] = 0;
395
                    scramble[curr][1] = 2*layer;
396
                    scramble[curr][2] = nextAngle;
397
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
398
                    updateCornerQuats(scramble[curr]);
399
                    break;
400
      case LAST_LO:
401
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
402
                    nextAngle = getNextAngle(rnd,layer);
403

    
404
                    if( nextAngle!=0 )
405
                      {
406
                      scramble[curr][0] = 0;
407
                      scramble[curr][1] = 2*layer;
408
                      scramble[curr][2] = nextAngle;
409
                      updateCornerQuats(scramble[curr]);
410
                      mLastRot = LAST_UL;
411
                      }
412
                    else
413
                      {
414
                      scramble[curr][0] = 1;
415
                      scramble[curr][1] = rnd.nextInt(2);
416
                      scramble[curr][2] = 1;
417
                      mLastRot = LAST_SL;
418
                      updateCornerQuats(scramble[curr]);
419
                      computePermittedAngles();
420
                      }
421

    
422
                    break;
423
      case LAST_UL: scramble[curr][0] = 1;
424
                    scramble[curr][1] = rnd.nextInt(2);
425
                    scramble[curr][2] = 1;
426
                    mLastRot = LAST_SL;
427
                    updateCornerQuats(scramble[curr]);
428
                    computePermittedAngles();
429
                    break;
430
      }
431
    }
432

    
433
///////////////////////////////////////////////////////////////////////////////////////////////////
434
// TYPE 2
435

    
436
  private void buildMoveForced(int[][] scramble, Random rnd, int curr)
437
    {
438
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
439
    int indexExcluded = curr>0 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
440
    int numMoves = currState.numMoves(indexExcluded);
441
    ObjectSignature signature;
442

    
443
    if( numMoves==0 )
444
      {
445
      indexExcluded = ScrambleStateBandagedCuboid.AXIS_NONE;
446
      numMoves = currState.numMoves(indexExcluded);
447
      }
448

    
449
    if( numMoves==0 )
450
      {
451
      scramble[curr][0] = 0;
452
      scramble[curr][1] = 0;
453
      scramble[curr][2] = 0;
454
      signature = currState.getSignature();
455
      }
456
    else
457
      {
458
      int randMove = rnd.nextInt(numMoves);
459
      int moveIndex = currState.getNthMove(randMove,indexExcluded);
460
      signature = currState.getMove(moveIndex);
461
      currState.fillOutScramble(scramble[curr],moveIndex);
462
      }
463

    
464
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
465
    mStatesHistory.add(nextState);
466
    }
467

    
468

    
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470
// TYPE 2
471

    
472
  private boolean buildMove2Cons(int[][] scramble, Random rnd, int curr)
473
    {
474
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
475
    boolean lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
476
    int axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
477
    int layerExcluded= !lock && curr>=1 ? scramble[curr-1][1] : -1;
478
    int numMoves = currState.numMoves(axisExcluded,layerExcluded);
479

    
480
    while( numMoves==0 )
481
      {
482
      if( curr>0 )
483
        {
484
        mStatesHistory.remove(curr);
485
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
486
        ObjectSignature signature = currState.getSignature();
487
        prevState.removeMoves(signature);
488
        mBlacklisted.add(signature);
489
        boolean result = buildMove2Cons(scramble,rnd,curr-1);
490
        if( !result ) return false;
491
        currState = mStatesHistory.get(curr);
492
        lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
493
        axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
494
        layerExcluded= lock ? -1 : scramble[curr-1][1];
495
        numMoves = currState.numMoves(axisExcluded,layerExcluded);
496
        }
497
      else return false;
498
      }
499

    
500
    int randMove = rnd.nextInt(numMoves);
501
    int moveIndex = currState.getNthMove(randMove,axisExcluded,layerExcluded);
502
    ObjectSignature signature = currState.getMove(moveIndex);
503
    currState.fillOutScramble(scramble[curr],moveIndex);
504

    
505
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
506
    mStatesHistory.add(nextState);
507

    
508
    return true;
509
    }
510

    
511
///////////////////////////////////////////////////////////////////////////////////////////////////
512
// TYPE 2
513

    
514
  private boolean buildMove1Cons(int[][] scramble, Random rnd, int curr)
515
    {
516
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
517
    int axisExcluded = curr>=1 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
518
    int numMoves = currState.numMoves(axisExcluded);
519

    
520
    while( numMoves==0 )
521
      {
522
      if( curr>0 )
523
        {
524
        mStatesHistory.remove(curr);
525
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
526
        ObjectSignature signature = currState.getSignature();
527
        prevState.removeMoves(signature);
528
        mBlacklisted.add(signature);
529
        boolean result = buildMove1Cons(scramble,rnd,curr-1);
530
        if( !result ) return false;
531
        currState = mStatesHistory.get(curr);
532
        axisExcluded = scramble[curr-1][0];
533
        numMoves = currState.numMoves(axisExcluded);
534
        }
535
      else
536
        {
537
        return false;
538
        }
539
      }
540

    
541
    int randMove = rnd.nextInt(numMoves);
542
    int moveIndex = currState.getNthMove(randMove,axisExcluded);
543
    ObjectSignature signature = currState.getMove(moveIndex);
544
    currState.fillOutScramble(scramble[curr],moveIndex);
545

    
546
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
547
    mStatesHistory.add(nextState);
548

    
549
    return true;
550
    }
551

    
552
///////////////////////////////////////////////////////////////////////////////////////////////////
553
// TYPE 2
554

    
555
  private void initializeType2Scrambling(int[][] scramble, Random rnd, int total, ObjectSignature signature)
556
    {
557
    if( mStatesHistory==null ) mStatesHistory = new ArrayList<>();
558
    else                       mStatesHistory.clear();
559

    
560
    if( mBlacklisted==null ) mBlacklisted = BlacklistedSignatures.getInstance();
561
    else                     mBlacklisted.clear();
562

    
563
    ScrambleStateBandagedCuboid state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
564
    mStatesHistory.add(state);
565
    boolean success = true;
566

    
567
    for(int curr=0; curr<total; curr++)
568
      {
569
      boolean result = buildMove1Cons(scramble,rnd,curr);
570
      if( !result )
571
        {
572
        success = false;
573
        break;
574
        }
575
      }
576

    
577
    if( !success )
578
      {
579
      success = true;
580
      mStatesHistory.clear();
581
      mBlacklisted.clear();
582
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
583
      mStatesHistory.add(state);
584

    
585
      for(int curr=0; curr<total; curr++)
586
        {
587
        boolean result = buildMove2Cons(scramble,rnd,curr);
588
        if( !result )
589
          {
590
          success = false;
591
          break;
592
          }
593
        }
594
      }
595

    
596
    if( !success )
597
      {
598
      mStatesHistory.clear();
599
      mBlacklisted.clear();
600
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
601
      mStatesHistory.add(state);
602

    
603
      for(int curr=0; curr<total; curr++)
604
        {
605
        buildMoveForced(scramble,rnd,curr);
606
        }
607
      }
608
    }
609

    
610
///////////////////////////////////////////////////////////////////////////////////////////////////
611
// TYPE 2   (locally-created bandaged cuboids)
612

    
613
  private void randomizeNewScramble2(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
614
    {
615
    if( curr==0 ) initializeType2Scrambling(scramble,rnd,total,signature);
616
    }
617

    
618
///////////////////////////////////////////////////////////////////////////////////////////////////
619
// TYPE 3   (tablebases)
620

    
621
  private void randomizeNewScramble3(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
622
    {
623
    // TODO
624
    }
625

    
626
///////////////////////////////////////////////////////////////////////////////////////////////////
627
// PUBLIC API
628

    
629
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
630
    {
631
    switch(mType)
632
      {
633
      case SCRAMBLING_ALGORITHMS: randomizeNewScramble0(scramble, rnd, curr); break;
634
      case SCRAMBLING_SQUARE1   : randomizeNewScramble1(scramble, rnd, curr); break;
635
      case SCRAMBLING_BANDAGED  : randomizeNewScramble2(scramble, rnd, curr, total, signature); break;
636
      case SCRAMBLING_TABLEBASES: randomizeNewScramble3(scramble, rnd, curr, total, signature); break;
637
      }
638
    }
639
  }
(2-2/7)