Project

General

Profile

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

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

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

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

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

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

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

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

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

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

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

    
82
///////////////////////////////////////////////////////////////////////////////////////////////////
83

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

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

    
100
      mNumOccurences = new int[max];
101
      }
102

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

    
111
///////////////////////////////////////////////////////////////////////////////////////////////////
112
// PUBLIC API
113

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

    
123
    mStates[mCurrState].getRandom(rnd, mAlgorithms, mAxisExcluded, mScrambleTable, mNumOccurences, mResult);
124
    int[] algorithm = mAlgorithms[mResult[0]];
125

    
126
    scramble[curr][0] = algorithm[0];
127
    scramble[curr][1] = algorithm[1];
128
    scramble[curr][2] = algorithm[2];
129

    
130
    mCurrState    = mResult[1];
131
    mAxisExcluded = algorithm[0];
132
    }
133

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135
// TYPE 1
136
///////////////////////////////////////////////////////////////////////////////////////////////////
137
// QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139

    
140
  void initializeQuatMult()
141
    {
142
    mQuatMult = new int[][]
143
      {
144
        {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,},
145
        {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12,},
146
        {  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13,},
147
        {  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14,},
148
        {  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15,},
149
        {  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16,},
150
        {  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17,},
151
        {  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18,},
152
        {  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19,},
153
        {  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20,},
154
        { 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,},
155
        { 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,},
156
        { 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,},
157
        { 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,},
158
        { 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,},
159
        { 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,},
160
        { 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,},
161
        { 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,},
162
        { 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,},
163
        { 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,},
164
        { 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,},
165
        { 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,},
166
        { 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11,},
167
        { 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,}
168
      };
169
    }
170

    
171
///////////////////////////////////////////////////////////////////////////////////////////////////
172
// TYPE 1
173

    
174
  private boolean cornerIsUp(int index)
175
    {
176
    return ((index<4) ^ (mCornerQuat[index]>=12));
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180
// TYPE 1
181

    
182
  private boolean cornerIsLeft(int index)
183
    {
184
    int q = mCornerQuat[index];
185

    
186
    switch(index)
187
      {
188
      case 0:
189
      case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
190
      case 1:
191
      case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
192
      case 2:
193
      case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
194
      case 3:
195
      case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
196
      }
197

    
198
    return false;
199
    }
200

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
// TYPE 1
203

    
204
  private boolean quatIsBad(int quatIndex, int corner)
205
    {
206
    if( mBadCornerQuats ==null )
207
      {
208
      // quat indices that make corner cubits bandage the puzzle.
209
      mBadCornerQuats = new int[][] { { 2, 8,17,23}, { 5,11,14,20} };
210
      }
211

    
212
    int index = (corner%2);
213

    
214
    return ( quatIndex== mBadCornerQuats[index][0] ||
215
             quatIndex== mBadCornerQuats[index][1] ||
216
             quatIndex== mBadCornerQuats[index][2] ||
217
             quatIndex== mBadCornerQuats[index][3]  );
218
    }
219

    
220
///////////////////////////////////////////////////////////////////////////////////////////////////
221
// TYPE 1
222

    
223
  private boolean isPermittedDo(int angle)
224
    {
225
    if( mQuatMult==null ) initializeQuatMult();
226

    
227
    for(int corner=0; corner<8; corner++)
228
      {
229
      if( !cornerIsUp(corner) )
230
        {
231
        int currQuat = mCornerQuat[corner];
232
        int finalQuat= mQuatMult[angle][currQuat];
233
        if( quatIsBad(finalQuat,corner) ) return false;
234
        }
235
      }
236

    
237
    return true;
238
    }
239

    
240
///////////////////////////////////////////////////////////////////////////////////////////////////
241
// TYPE 1
242

    
243
  private boolean isPermittedUp(int angle)
244
    {
245
    if( mQuatMult==null ) initializeQuatMult();
246

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

    
257
    return true;
258
    }
259

    
260
///////////////////////////////////////////////////////////////////////////////////////////////////
261
// TYPE 1
262

    
263
  private void computePermittedAngles()
264
    {
265
    mPermittedDo = 0;
266

    
267
    for(int angle=0; angle<BASIC_ANGLE; angle++)
268
      {
269
      if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
270
      }
271

    
272
    mPermittedUp = 0;
273

    
274
    for(int angle=0; angle<BASIC_ANGLE; angle++)
275
      {
276
      if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
277
      }
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281
// TYPE 1
282

    
283
  private int getNextAngle(Random rnd, int layer)
284
    {
285
    int num = layer==0 ? mPermittedDo:mPermittedUp;
286
    int index = rnd.nextInt(num);
287
    int angle = mPermittedAngles[layer][index];
288
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
289
    }
290

    
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292
// TYPE 1
293

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

    
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303
// TYPE 1
304

    
305
  private int makeQuat(int axis,int index)
306
    {
307
    if( axis==1 ) return 13;
308
    if( index<0 ) index+=12;
309
    return index;
310
    }
311

    
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313
// TYPE 1
314

    
315
  private boolean cornerBelongs(int index, int axis, int layer)
316
    {
317
    if( axis==0 )
318
      {
319
      boolean up = cornerIsUp(index);
320
      return ((up && layer==2) || (!up && layer==0));
321
      }
322
    else
323
      {
324
      boolean le = cornerIsLeft(index);
325
      return ((le && layer==0) || (!le && layer==1));
326
      }
327
    }
328

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

    
332
  private void updateCornerQuats(int[] rotInfo)
333
    {
334
    if( mQuatMult==null ) initializeQuatMult();
335

    
336
    int axis = rotInfo[0];
337
    int layer= rotInfo[1];
338
    int index=-rotInfo[2];
339

    
340
    int quat = makeQuat(axis,index);
341

    
342
    for(int corner=0; corner<8; corner++)
343
      {
344
      if( cornerBelongs(corner,axis,layer) )
345
        {
346
        int curr = mCornerQuat[corner];
347
        mCornerQuat[corner] = mQuatMult[quat][curr];
348
        }
349
      }
350
    }
351

    
352
///////////////////////////////////////////////////////////////////////////////////////////////////
353
// TYPE 1
354

    
355
  private void randomizeNewScramble1(int[][] scramble, Random rnd, int curr)
356
    {
357
    int layer, nextAngle;
358

    
359
    if( curr==0 )
360
      {
361
      for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
362
      mLastRot = rnd.nextInt(4);
363
      computePermittedAngles();
364
      }
365

    
366
    switch(mLastRot)
367
      {
368
      case LAST_SL: layer = rnd.nextInt(2);
369
                    nextAngle = getNextAngle(rnd,layer);
370

    
371
                    if( nextAngle==0 )
372
                      {
373
                      layer = 1-layer;
374
                      nextAngle = getNextAngleNotZero(rnd,layer);
375
                      }
376

    
377
                    scramble[curr][0] = 0;
378
                    scramble[curr][1] = 2*layer;
379
                    scramble[curr][2] = nextAngle;
380
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
381
                    updateCornerQuats(scramble[curr]);
382
                    break;
383
      case LAST_LO:
384
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
385
                    nextAngle = getNextAngle(rnd,layer);
386

    
387
                    if( nextAngle!=0 )
388
                      {
389
                      scramble[curr][0] = 0;
390
                      scramble[curr][1] = 2*layer;
391
                      scramble[curr][2] = nextAngle;
392
                      updateCornerQuats(scramble[curr]);
393
                      mLastRot = LAST_UL;
394
                      }
395
                    else
396
                      {
397
                      scramble[curr][0] = 1;
398
                      scramble[curr][1] = rnd.nextInt(2);
399
                      scramble[curr][2] = 1;
400
                      mLastRot = LAST_SL;
401
                      updateCornerQuats(scramble[curr]);
402
                      computePermittedAngles();
403
                      }
404

    
405
                    break;
406
      case LAST_UL: scramble[curr][0] = 1;
407
                    scramble[curr][1] = rnd.nextInt(2);
408
                    scramble[curr][2] = 1;
409
                    mLastRot = LAST_SL;
410
                    updateCornerQuats(scramble[curr]);
411
                    computePermittedAngles();
412
                    break;
413
      }
414
    }
415

    
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417
// TYPE 2
418

    
419
  private void buildMoveForced(int[][] scramble, Random rnd, int curr)
420
    {
421
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
422
    int indexExcluded = curr>0 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
423
    int numMoves = currState.numMoves(indexExcluded);
424
    ObjectSignature signature;
425

    
426
    if( numMoves==0 )
427
      {
428
      indexExcluded = ScrambleStateBandagedCuboid.AXIS_NONE;
429
      numMoves = currState.numMoves(indexExcluded);
430
      }
431

    
432
    if( numMoves==0 )
433
      {
434
      scramble[curr][0] = 0;
435
      scramble[curr][1] = 0;
436
      scramble[curr][2] = 0;
437
      signature = currState.getSignature();
438
      }
439
    else
440
      {
441
      int randMove = rnd.nextInt(numMoves);
442
      int moveIndex = currState.getNthMove(randMove,indexExcluded);
443
      signature = currState.getMove(moveIndex);
444
      currState.fillOutScramble(scramble[curr],moveIndex);
445
      }
446

    
447
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
448
    mStatesHistory.add(nextState);
449
    }
450

    
451

    
452
///////////////////////////////////////////////////////////////////////////////////////////////////
453
// TYPE 2
454

    
455
  private boolean buildMove2Cons(int[][] scramble, Random rnd, int curr)
456
    {
457
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
458
    boolean lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
459
    int axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
460
    int layerExcluded= !lock && curr>=1 ? scramble[curr-1][1] : -1;
461
    int numMoves = currState.numMoves(axisExcluded,layerExcluded);
462

    
463
    while( numMoves==0 )
464
      {
465
      if( curr>0 )
466
        {
467
        mStatesHistory.remove(curr);
468
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
469
        ObjectSignature signature = currState.getSignature();
470
        prevState.removeMoves(signature);
471
        mBlacklisted.add(signature);
472
        boolean result = buildMove2Cons(scramble,rnd,curr-1);
473
        if( !result ) return false;
474
        currState = mStatesHistory.get(curr);
475
        lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
476
        axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
477
        layerExcluded= lock ? -1 : scramble[curr-1][1];
478
        numMoves = currState.numMoves(axisExcluded,layerExcluded);
479
        }
480
      else return false;
481
      }
482

    
483
    int randMove = rnd.nextInt(numMoves);
484
    int moveIndex = currState.getNthMove(randMove,axisExcluded,layerExcluded);
485
    ObjectSignature signature = currState.getMove(moveIndex);
486
    currState.fillOutScramble(scramble[curr],moveIndex);
487

    
488
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
489
    mStatesHistory.add(nextState);
490

    
491
    return true;
492
    }
493

    
494
///////////////////////////////////////////////////////////////////////////////////////////////////
495
// TYPE 2
496

    
497
  private boolean buildMove1Cons(int[][] scramble, Random rnd, int curr)
498
    {
499
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
500
    int axisExcluded = curr>=1 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
501
    int numMoves = currState.numMoves(axisExcluded);
502

    
503
    while( numMoves==0 )
504
      {
505
      if( curr>0 )
506
        {
507
        mStatesHistory.remove(curr);
508
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
509
        ObjectSignature signature = currState.getSignature();
510
        prevState.removeMoves(signature);
511
        mBlacklisted.add(signature);
512
        boolean result = buildMove1Cons(scramble,rnd,curr-1);
513
        if( !result ) return false;
514
        currState = mStatesHistory.get(curr);
515
        axisExcluded = scramble[curr-1][0];
516
        numMoves = currState.numMoves(axisExcluded);
517
        }
518
      else
519
        {
520
        return false;
521
        }
522
      }
523

    
524
    int randMove = rnd.nextInt(numMoves);
525
    int moveIndex = currState.getNthMove(randMove,axisExcluded);
526
    ObjectSignature signature = currState.getMove(moveIndex);
527
    currState.fillOutScramble(scramble[curr],moveIndex);
528

    
529
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
530
    mStatesHistory.add(nextState);
531

    
532
    return true;
533
    }
534

    
535
///////////////////////////////////////////////////////////////////////////////////////////////////
536
// TYPE 2
537

    
538
  private void initializeType2Scrambling(int[][] scramble, Random rnd, int total, ObjectSignature signature)
539
    {
540
    if( mStatesHistory==null ) mStatesHistory = new ArrayList<>();
541
    else                       mStatesHistory.clear();
542

    
543
    if( mBlacklisted==null ) mBlacklisted = BlacklistedSignatures.getInstance();
544
    else                     mBlacklisted.clear();
545

    
546
    ScrambleStateBandagedCuboid state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
547
    mStatesHistory.add(state);
548
    boolean success = true;
549

    
550
    for(int curr=0; curr<total; curr++)
551
      {
552
      boolean result = buildMove1Cons(scramble,rnd,curr);
553
      if( !result )
554
        {
555
        success = false;
556
        break;
557
        }
558
      }
559

    
560
    if( !success )
561
      {
562
      success = true;
563
      mStatesHistory.clear();
564
      mBlacklisted.clear();
565
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
566
      mStatesHistory.add(state);
567

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

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

    
586
      for(int curr=0; curr<total; curr++)
587
        {
588
        buildMoveForced(scramble,rnd,curr);
589
        }
590
      }
591
    }
592

    
593
///////////////////////////////////////////////////////////////////////////////////////////////////
594
// TYPE 2   (locally-created bandaged cuboids)
595

    
596
  private void randomizeNewScramble2(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
597
    {
598
    if( curr==0 ) initializeType2Scrambling(scramble,rnd,total,signature);
599
    }
600

    
601
///////////////////////////////////////////////////////////////////////////////////////////////////
602
// PUBLIC API
603

    
604
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
605
    {
606
    switch(mType)
607
      {
608
      case 0: randomizeNewScramble0(scramble, rnd, curr); break;
609
      case 1: randomizeNewScramble1(scramble, rnd, curr); break;
610
      case 2: randomizeNewScramble2(scramble, rnd, curr, total, signature); break;
611
      }
612
    }
613
  }
(2-2/7)