Project

General

Profile

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

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

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
  private final ScrambleState[] mStates;
22
  private final int mType;
23
  private final int mNumAxis;
24
  private final int[] mNumLayers;
25
  private final int[][] mAlgorithms;
26

    
27
  // type=0, i.e. main
28
  private int mCurrState;
29
  private int mAxisExcluded;
30
  private int[][] mScrambleTable;
31
  private int[] mNumOccurences;
32
  private int[] mResult;
33
  private int mCurrAlgorithm;
34
  private int mCurrStep;
35

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

    
43
  private int[][] mPermittedAngles;
44
  private int[] mCornerQuat;
45
  private int mPermittedUp, mPermittedDo;
46
  private int[][] mBadCornerQuats;
47
  private int mLastRot;
48
  private int[][] mQuatMult;
49

    
50
  // type=2 , i.e. locally created bandaged cuboids
51
  private ArrayList<ScrambleStateBandagedCuboid> mStatesHistory;
52
  private BlacklistedSignatures mBlacklisted;
53

    
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

    
56
  public ObjectScrambler(int type, int numAxis, int[] numLayers, int[][] algorithms, int[][] edges)
57
    {
58
    mType       = type;
59
    mNumAxis    = numAxis;
60
    mNumLayers  = numLayers;
61
    mAlgorithms = algorithms;
62

    
63
    if( mType==0 )
64
      {
65
      mResult = new int[2];
66
      }
67

    
68
    if( edges!=null )
69
      {
70
      int numEdges = edges.length;
71
      mStates = new ScrambleState[numEdges];
72
      for(int i=0; i<numEdges; i++) mStates[i] = new ScrambleState(edges[i],algorithms);
73
      }
74
    else mStates = null;
75

    
76
    if( mType==1 )
77
      {
78
      mPermittedAngles = new int[2][BASIC_ANGLE];
79
      mCornerQuat = new int[8];
80
      mLastRot = LAST_SL;
81
      }
82
    }
83

    
84
///////////////////////////////////////////////////////////////////////////////////////////////////
85

    
86
  private void initializeScrambling()
87
    {
88
    if( mScrambleTable==null )
89
      {
90
      mScrambleTable = new int[mNumAxis][];
91
      }
92
    if( mNumOccurences==null )
93
      {
94
      int max=0;
95

    
96
      for (ScrambleState mState : mStates)
97
        {
98
        int tmp = mState.getTotal();
99
        if (max < tmp) max = tmp;
100
        }
101

    
102
      mNumOccurences = new int[max];
103
      }
104

    
105
    for(int i=0; i<mNumAxis; i++)
106
      {
107
      int len = mNumLayers[i];
108
      mScrambleTable[i] = new int[len];
109
      for(int j=0; j<len; j++) mScrambleTable[i][j] = 0;
110
      }
111
    }
112

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
// PUBLIC API
115

    
116
  private void randomizeNewScramble0(int[][] scramble, Random rnd, int curr)
117
    {
118
    if( curr==0 )
119
      {
120
      mCurrStep     = 100000;
121
      mCurrState    = 0;
122
      mAxisExcluded =-1;
123
      initializeScrambling();
124
      }
125

    
126
    if( mCurrStep+6 <= mAlgorithms[mCurrAlgorithm].length )
127
      {
128
      mCurrStep += 3;
129
      }
130
    else
131
      {
132
      mStates[mCurrState].getRandom(rnd, mAlgorithms, mAxisExcluded, mScrambleTable, mNumOccurences, mResult);
133
      mCurrAlgorithm = mResult[0];
134
      mCurrState     = mResult[1];
135
      mCurrStep      = 0;
136
      }
137

    
138
    int[] algorithm = mAlgorithms[mCurrAlgorithm];
139
    scramble[curr][0] = algorithm[mCurrStep  ];
140
    scramble[curr][1] = algorithm[mCurrStep+1];
141
    scramble[curr][2] = algorithm[mCurrStep+2];
142

    
143
    mAxisExcluded = algorithm[0];
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147
// TYPE 1
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149
// QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

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

    
183
///////////////////////////////////////////////////////////////////////////////////////////////////
184
// TYPE 1
185

    
186
  private boolean cornerIsUp(int index)
187
    {
188
    return ((index<4) ^ (mCornerQuat[index]>=12));
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192
// TYPE 1
193

    
194
  private boolean cornerIsLeft(int index)
195
    {
196
    int q = mCornerQuat[index];
197

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

    
210
    return false;
211
    }
212

    
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214
// TYPE 1
215

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

    
224
    int index = (corner%2);
225

    
226
    return ( quatIndex== mBadCornerQuats[index][0] ||
227
             quatIndex== mBadCornerQuats[index][1] ||
228
             quatIndex== mBadCornerQuats[index][2] ||
229
             quatIndex== mBadCornerQuats[index][3]  );
230
    }
231

    
232
///////////////////////////////////////////////////////////////////////////////////////////////////
233
// TYPE 1
234

    
235
  private boolean isPermittedDo(int angle)
236
    {
237
    if( mQuatMult==null ) initializeQuatMult();
238

    
239
    for(int corner=0; corner<8; corner++)
240
      {
241
      if( !cornerIsUp(corner) )
242
        {
243
        int currQuat = mCornerQuat[corner];
244
        int finalQuat= mQuatMult[angle][currQuat];
245
        if( quatIsBad(finalQuat,corner) ) return false;
246
        }
247
      }
248

    
249
    return true;
250
    }
251

    
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253
// TYPE 1
254

    
255
  private boolean isPermittedUp(int angle)
256
    {
257
    if( mQuatMult==null ) initializeQuatMult();
258

    
259
    for(int corner=0; corner<8; corner++)
260
      {
261
      if( cornerIsUp(corner) )
262
        {
263
        int currQuat = mCornerQuat[corner];
264
        int finalQuat= mQuatMult[angle][currQuat];
265
        if( quatIsBad(finalQuat,corner) ) return false;
266
        }
267
      }
268

    
269
    return true;
270
    }
271

    
272
///////////////////////////////////////////////////////////////////////////////////////////////////
273
// TYPE 1
274

    
275
  private void computePermittedAngles()
276
    {
277
    mPermittedDo = 0;
278

    
279
    for(int angle=0; angle<BASIC_ANGLE; angle++)
280
      {
281
      if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
282
      }
283

    
284
    mPermittedUp = 0;
285

    
286
    for(int angle=0; angle<BASIC_ANGLE; angle++)
287
      {
288
      if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
289
      }
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293
// TYPE 1
294

    
295
  private int getNextAngle(Random rnd, int layer)
296
    {
297
    int num = layer==0 ? mPermittedDo:mPermittedUp;
298
    int index = rnd.nextInt(num);
299
    int angle = mPermittedAngles[layer][index];
300
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
301
    }
302

    
303
///////////////////////////////////////////////////////////////////////////////////////////////////
304
// TYPE 1
305

    
306
  private int getNextAngleNotZero(Random rnd, int layer)
307
    {
308
    int num = layer==0 ? mPermittedDo:mPermittedUp;
309
    int index = rnd.nextInt(num-1);
310
    int angle = mPermittedAngles[layer][index+1];
311
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
312
    }
313

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315
// TYPE 1
316

    
317
  private int makeQuat(int axis,int index)
318
    {
319
    if( axis==1 ) return 13;
320
    if( index<0 ) index+=12;
321
    return index;
322
    }
323

    
324
///////////////////////////////////////////////////////////////////////////////////////////////////
325
// TYPE 1
326

    
327
  private boolean cornerBelongs(int index, int axis, int layer)
328
    {
329
    if( axis==0 )
330
      {
331
      boolean up = cornerIsUp(index);
332
      return ((up && layer==2) || (!up && layer==0));
333
      }
334
    else
335
      {
336
      boolean le = cornerIsLeft(index);
337
      return ((le && layer==0) || (!le && layer==1));
338
      }
339
    }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342
// TYPE 1
343

    
344
  private void updateCornerQuats(int[] rotInfo)
345
    {
346
    if( mQuatMult==null ) initializeQuatMult();
347

    
348
    int axis = rotInfo[0];
349
    int layer= rotInfo[1];
350
    int index=-rotInfo[2];
351

    
352
    int quat = makeQuat(axis,index);
353

    
354
    for(int corner=0; corner<8; corner++)
355
      {
356
      if( cornerBelongs(corner,axis,layer) )
357
        {
358
        int curr = mCornerQuat[corner];
359
        mCornerQuat[corner] = mQuatMult[quat][curr];
360
        }
361
      }
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365
// TYPE 1
366

    
367
  private void randomizeNewScramble1(int[][] scramble, Random rnd, int curr)
368
    {
369
    int layer, nextAngle;
370

    
371
    if( curr==0 )
372
      {
373
      for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
374
      mLastRot = rnd.nextInt(4);
375
      computePermittedAngles();
376
      }
377

    
378
    switch(mLastRot)
379
      {
380
      case LAST_SL: layer = rnd.nextInt(2);
381
                    nextAngle = getNextAngle(rnd,layer);
382

    
383
                    if( nextAngle==0 )
384
                      {
385
                      layer = 1-layer;
386
                      nextAngle = getNextAngleNotZero(rnd,layer);
387
                      }
388

    
389
                    scramble[curr][0] = 0;
390
                    scramble[curr][1] = 2*layer;
391
                    scramble[curr][2] = nextAngle;
392
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
393
                    updateCornerQuats(scramble[curr]);
394
                    break;
395
      case LAST_LO:
396
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
397
                    nextAngle = getNextAngle(rnd,layer);
398

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

    
417
                    break;
418
      case LAST_UL: scramble[curr][0] = 1;
419
                    scramble[curr][1] = rnd.nextInt(2);
420
                    scramble[curr][2] = 1;
421
                    mLastRot = LAST_SL;
422
                    updateCornerQuats(scramble[curr]);
423
                    computePermittedAngles();
424
                    break;
425
      }
426
    }
427

    
428
///////////////////////////////////////////////////////////////////////////////////////////////////
429
// TYPE 2
430

    
431
  private void buildMoveForced(int[][] scramble, Random rnd, int curr)
432
    {
433
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
434
    int indexExcluded = curr>0 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
435
    int numMoves = currState.numMoves(indexExcluded);
436
    ObjectSignature signature;
437

    
438
    if( numMoves==0 )
439
      {
440
      indexExcluded = ScrambleStateBandagedCuboid.AXIS_NONE;
441
      numMoves = currState.numMoves(indexExcluded);
442
      }
443

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

    
459
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
460
    mStatesHistory.add(nextState);
461
    }
462

    
463

    
464
///////////////////////////////////////////////////////////////////////////////////////////////////
465
// TYPE 2
466

    
467
  private boolean buildMove2Cons(int[][] scramble, Random rnd, int curr)
468
    {
469
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
470
    boolean lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
471
    int axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
472
    int layerExcluded= !lock && curr>=1 ? scramble[curr-1][1] : -1;
473
    int numMoves = currState.numMoves(axisExcluded,layerExcluded);
474

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

    
495
    int randMove = rnd.nextInt(numMoves);
496
    int moveIndex = currState.getNthMove(randMove,axisExcluded,layerExcluded);
497
    ObjectSignature signature = currState.getMove(moveIndex);
498
    currState.fillOutScramble(scramble[curr],moveIndex);
499

    
500
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
501
    mStatesHistory.add(nextState);
502

    
503
    return true;
504
    }
505

    
506
///////////////////////////////////////////////////////////////////////////////////////////////////
507
// TYPE 2
508

    
509
  private boolean buildMove1Cons(int[][] scramble, Random rnd, int curr)
510
    {
511
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
512
    int axisExcluded = curr>=1 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
513
    int numMoves = currState.numMoves(axisExcluded);
514

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

    
536
    int randMove = rnd.nextInt(numMoves);
537
    int moveIndex = currState.getNthMove(randMove,axisExcluded);
538
    ObjectSignature signature = currState.getMove(moveIndex);
539
    currState.fillOutScramble(scramble[curr],moveIndex);
540

    
541
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
542
    mStatesHistory.add(nextState);
543

    
544
    return true;
545
    }
546

    
547
///////////////////////////////////////////////////////////////////////////////////////////////////
548
// TYPE 2
549

    
550
  private void initializeType2Scrambling(int[][] scramble, Random rnd, int total, ObjectSignature signature)
551
    {
552
    if( mStatesHistory==null ) mStatesHistory = new ArrayList<>();
553
    else                       mStatesHistory.clear();
554

    
555
    if( mBlacklisted==null ) mBlacklisted = BlacklistedSignatures.getInstance();
556
    else                     mBlacklisted.clear();
557

    
558
    ScrambleStateBandagedCuboid state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
559
    mStatesHistory.add(state);
560
    boolean success = true;
561

    
562
    for(int curr=0; curr<total; curr++)
563
      {
564
      boolean result = buildMove1Cons(scramble,rnd,curr);
565
      if( !result )
566
        {
567
        success = false;
568
        break;
569
        }
570
      }
571

    
572
    if( !success )
573
      {
574
      success = true;
575
      mStatesHistory.clear();
576
      mBlacklisted.clear();
577
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
578
      mStatesHistory.add(state);
579

    
580
      for(int curr=0; curr<total; curr++)
581
        {
582
        boolean result = buildMove2Cons(scramble,rnd,curr);
583
        if( !result )
584
          {
585
          success = false;
586
          break;
587
          }
588
        }
589
      }
590

    
591
    if( !success )
592
      {
593
      mStatesHistory.clear();
594
      mBlacklisted.clear();
595
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
596
      mStatesHistory.add(state);
597

    
598
      for(int curr=0; curr<total; curr++)
599
        {
600
        buildMoveForced(scramble,rnd,curr);
601
        }
602
      }
603
    }
604

    
605
///////////////////////////////////////////////////////////////////////////////////////////////////
606
// TYPE 2   (locally-created bandaged cuboids)
607

    
608
  private void randomizeNewScramble2(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
609
    {
610
    if( curr==0 ) initializeType2Scrambling(scramble,rnd,total,signature);
611
    }
612

    
613
///////////////////////////////////////////////////////////////////////////////////////////////////
614
// PUBLIC API
615

    
616
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
617
    {
618
    switch(mType)
619
      {
620
      case 0: randomizeNewScramble0(scramble, rnd, curr); break;
621
      case 1: randomizeNewScramble1(scramble, rnd, curr); break;
622
      case 2: randomizeNewScramble2(scramble, rnd, curr, total, signature); break;
623
      }
624
    }
625
  }
(2-2/7)