Project

General

Profile

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

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

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

    
26
  // type=0, i.e. main
27
  private int mCurrState;
28
  private int mIndexExcluded;
29
  private int[][] mScrambleTable;
30
  private int[] mNumOccurences;
31

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

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

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

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

    
52
  public ObjectScrambler(int type, int numAxis, int[] numLayers, ScrambleState[] states)
53
    {
54
    mType = type;
55
    mNumAxis = numAxis;
56
    mNumLayers = numLayers;
57
    mStates = states;
58

    
59
    if( mType==1 )
60
      {
61
      mPermittedAngles = new int[2][BASIC_ANGLE];
62
      mCornerQuat = new int[8];
63
      mLastRot = LAST_SL;
64
      }
65
    }
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  private void initializeScrambling()
70
    {
71
    if( mScrambleTable ==null )
72
      {
73
      mScrambleTable = new int[mNumAxis][];
74
      }
75
    if( mNumOccurences ==null )
76
      {
77
      int max=0;
78

    
79
      for (ScrambleState mState : mStates)
80
        {
81
        int tmp = mState.getTotal(-1);
82
        if (max < tmp) max = tmp;
83
        }
84

    
85
      mNumOccurences = new int[max];
86
      }
87

    
88
    for(int i=0; i<mNumAxis; i++)
89
      {
90
      int len = mNumLayers[i];
91
      mScrambleTable[i] = new int[len];
92
      for(int j=0; j<len; j++) mScrambleTable[i][j] = 0;
93
      }
94
    }
95

    
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97
// PUBLIC API
98

    
99
  private void randomizeNewScramble0(int[][] scramble, Random rnd, int curr)
100
    {
101
    if( curr==0 )
102
      {
103
      mCurrState     = 0;
104
      mIndexExcluded =-1;
105
      initializeScrambling();
106
      }
107

    
108
    int[] info= mStates[mCurrState].getRandom(rnd, mIndexExcluded, mScrambleTable, mNumOccurences);
109

    
110
    scramble[curr][0] = info[0];
111
    scramble[curr][1] = info[1];
112
    scramble[curr][2] = info[2];
113

    
114
    mCurrState     = info[3];
115
    mIndexExcluded = info[0];
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
// TYPE 1
120
///////////////////////////////////////////////////////////////////////////////////////////////////
121
// QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]
122
///////////////////////////////////////////////////////////////////////////////////////////////////
123

    
124
  void initializeQuatMult()
125
    {
126
    mQuatMult = new int[][]
127
      {
128
        {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,},
129
        {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12,},
130
        {  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13,},
131
        {  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14,},
132
        {  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15,},
133
        {  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16,},
134
        {  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17,},
135
        {  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18,},
136
        {  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19,},
137
        {  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20,},
138
        { 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,},
139
        { 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,},
140
        { 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,},
141
        { 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,},
142
        { 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,},
143
        { 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,},
144
        { 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,},
145
        { 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,},
146
        { 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,},
147
        { 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,},
148
        { 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,},
149
        { 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,},
150
        { 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11,},
151
        { 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,}
152
      };
153
    }
154

    
155
///////////////////////////////////////////////////////////////////////////////////////////////////
156
// TYPE 1
157

    
158
  private boolean cornerIsUp(int index)
159
    {
160
    return ((index<4) ^ (mCornerQuat[index]>=12));
161
    }
162

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164
// TYPE 1
165

    
166
  private boolean cornerIsLeft(int index)
167
    {
168
    int q = mCornerQuat[index];
169

    
170
    switch(index)
171
      {
172
      case 0:
173
      case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
174
      case 1:
175
      case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
176
      case 2:
177
      case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
178
      case 3:
179
      case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
180
      }
181

    
182
    return false;
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186
// TYPE 1
187

    
188
  private boolean quatIsBad(int quatIndex, int corner)
189
    {
190
    if( mBadCornerQuats ==null )
191
      {
192
      // quat indices that make corner cubits bandage the puzzle.
193
      mBadCornerQuats = new int[][] { { 2, 8,17,23}, { 5,11,14,20} };
194
      }
195

    
196
    int index = (corner%2);
197

    
198
    return ( quatIndex== mBadCornerQuats[index][0] ||
199
             quatIndex== mBadCornerQuats[index][1] ||
200
             quatIndex== mBadCornerQuats[index][2] ||
201
             quatIndex== mBadCornerQuats[index][3]  );
202
    }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205
// TYPE 1
206

    
207
  private boolean isPermittedDo(int angle)
208
    {
209
    if( mQuatMult==null ) initializeQuatMult();
210

    
211
    for(int corner=0; corner<8; corner++)
212
      {
213
      if( !cornerIsUp(corner) )
214
        {
215
        int currQuat = mCornerQuat[corner];
216
        int finalQuat= mQuatMult[angle][currQuat];
217
        if( quatIsBad(finalQuat,corner) ) return false;
218
        }
219
      }
220

    
221
    return true;
222
    }
223

    
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225
// TYPE 1
226

    
227
  private boolean isPermittedUp(int angle)
228
    {
229
    if( mQuatMult==null ) initializeQuatMult();
230

    
231
    for(int corner=0; corner<8; corner++)
232
      {
233
      if( cornerIsUp(corner) )
234
        {
235
        int currQuat = mCornerQuat[corner];
236
        int finalQuat= mQuatMult[angle][currQuat];
237
        if( quatIsBad(finalQuat,corner) ) return false;
238
        }
239
      }
240

    
241
    return true;
242
    }
243

    
244
///////////////////////////////////////////////////////////////////////////////////////////////////
245
// TYPE 1
246

    
247
  private void computePermittedAngles()
248
    {
249
    mPermittedDo = 0;
250

    
251
    for(int angle=0; angle<BASIC_ANGLE; angle++)
252
      {
253
      if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
254
      }
255

    
256
    mPermittedUp = 0;
257

    
258
    for(int angle=0; angle<BASIC_ANGLE; angle++)
259
      {
260
      if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
261
      }
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265
// TYPE 1
266

    
267
  private int getNextAngle(Random rnd, int layer)
268
    {
269
    int num = layer==0 ? mPermittedDo:mPermittedUp;
270
    int index = rnd.nextInt(num);
271
    int angle = mPermittedAngles[layer][index];
272
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
273
    }
274

    
275
///////////////////////////////////////////////////////////////////////////////////////////////////
276
// TYPE 1
277

    
278
  private int getNextAngleNotZero(Random rnd, int layer)
279
    {
280
    int num = layer==0 ? mPermittedDo:mPermittedUp;
281
    int index = rnd.nextInt(num-1);
282
    int angle = mPermittedAngles[layer][index+1];
283
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
284
    }
285

    
286
///////////////////////////////////////////////////////////////////////////////////////////////////
287
// TYPE 1
288

    
289
  private int makeQuat(int axis,int index)
290
    {
291
    if( axis==1 ) return 13;
292
    if( index<0 ) index+=12;
293
    return index;
294
    }
295

    
296
///////////////////////////////////////////////////////////////////////////////////////////////////
297
// TYPE 1
298

    
299
  private boolean cornerBelongs(int index, int axis, int layer)
300
    {
301
    if( axis==0 )
302
      {
303
      boolean up = cornerIsUp(index);
304
      return ((up && layer==2) || (!up && layer==0));
305
      }
306
    else
307
      {
308
      boolean le = cornerIsLeft(index);
309
      return ((le && layer==0) || (!le && layer==1));
310
      }
311
    }
312

    
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314
// TYPE 1
315

    
316
  private void updateCornerQuats(int[] rotInfo)
317
    {
318
    if( mQuatMult==null ) initializeQuatMult();
319

    
320
    int axis = rotInfo[0];
321
    int layer= rotInfo[1];
322
    int index=-rotInfo[2];
323

    
324
    int quat = makeQuat(axis,index);
325

    
326
    for(int corner=0; corner<8; corner++)
327
      {
328
      if( cornerBelongs(corner,axis,layer) )
329
        {
330
        int curr = mCornerQuat[corner];
331
        mCornerQuat[corner] = mQuatMult[quat][curr];
332
        }
333
      }
334
    }
335

    
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337
// TYPE 1
338

    
339
  private void randomizeNewScramble1(int[][] scramble, Random rnd, int curr)
340
    {
341
    int layer, nextAngle;
342

    
343
    if( curr==0 )
344
      {
345
      for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
346
      mLastRot = rnd.nextInt(4);
347
      computePermittedAngles();
348
      }
349

    
350
    switch(mLastRot)
351
      {
352
      case LAST_SL: layer = rnd.nextInt(2);
353
                    nextAngle = getNextAngle(rnd,layer);
354

    
355
                    if( nextAngle==0 )
356
                      {
357
                      layer = 1-layer;
358
                      nextAngle = getNextAngleNotZero(rnd,layer);
359
                      }
360

    
361
                    scramble[curr][0] = 0;
362
                    scramble[curr][1] = 2*layer;
363
                    scramble[curr][2] = nextAngle;
364
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
365
                    updateCornerQuats(scramble[curr]);
366
                    break;
367
      case LAST_LO:
368
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
369
                    nextAngle = getNextAngle(rnd,layer);
370

    
371
                    if( nextAngle!=0 )
372
                      {
373
                      scramble[curr][0] = 0;
374
                      scramble[curr][1] = 2*layer;
375
                      scramble[curr][2] = nextAngle;
376
                      updateCornerQuats(scramble[curr]);
377
                      mLastRot = LAST_UL;
378
                      }
379
                    else
380
                      {
381
                      scramble[curr][0] = 1;
382
                      scramble[curr][1] = rnd.nextInt(2);
383
                      scramble[curr][2] = 1;
384
                      mLastRot = LAST_SL;
385
                      updateCornerQuats(scramble[curr]);
386
                      computePermittedAngles();
387
                      }
388

    
389
                    break;
390
      case LAST_UL: scramble[curr][0] = 1;
391
                    scramble[curr][1] = rnd.nextInt(2);
392
                    scramble[curr][2] = 1;
393
                    mLastRot = LAST_SL;
394
                    updateCornerQuats(scramble[curr]);
395
                    computePermittedAngles();
396
                    break;
397
      }
398
    }
399

    
400
///////////////////////////////////////////////////////////////////////////////////////////////////
401
// TYPE 2
402

    
403
  private void buildMoveForced(int[][] scramble, Random rnd, int curr)
404
    {
405
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
406
    int indexExcluded = curr>0 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
407
    int numMoves = currState.numMoves(indexExcluded);
408
    ObjectSignature signature;
409

    
410
    if( numMoves==0 )
411
      {
412
      indexExcluded = ScrambleStateBandagedCuboid.AXIS_NONE;
413
      numMoves = currState.numMoves(indexExcluded);
414
      }
415

    
416
    if( numMoves==0 )
417
      {
418
      scramble[curr][0] = 0;
419
      scramble[curr][1] = 0;
420
      scramble[curr][2] = 0;
421
      signature = currState.getSignature();
422
      }
423
    else
424
      {
425
      int randMove = rnd.nextInt(numMoves);
426
      int moveIndex = currState.getNthMove(randMove,indexExcluded);
427
      signature = currState.getMove(moveIndex);
428
      currState.fillOutScramble(scramble[curr],moveIndex);
429
      }
430

    
431
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
432
    mStatesHistory.add(nextState);
433
    }
434

    
435

    
436
///////////////////////////////////////////////////////////////////////////////////////////////////
437
// TYPE 2
438

    
439
  private boolean buildMove2Cons(int[][] scramble, Random rnd, int curr)
440
    {
441
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
442
    boolean lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
443
    int axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
444
    int layerExcluded= !lock && curr>=1 ? scramble[curr-1][1] : -1;
445
    int numMoves = currState.numMoves(axisExcluded,layerExcluded);
446

    
447
    while( numMoves==0 )
448
      {
449
      if( curr>0 )
450
        {
451
        mStatesHistory.remove(curr);
452
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
453
        ObjectSignature signature = currState.getSignature();
454
        prevState.removeMoves(signature);
455
        mBlacklisted.add(signature);
456
        boolean result = buildMove2Cons(scramble,rnd,curr-1);
457
        if( !result ) return false;
458
        currState = mStatesHistory.get(curr);
459
        lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
460
        axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
461
        layerExcluded= lock ? -1 : scramble[curr-1][1];
462
        numMoves = currState.numMoves(axisExcluded,layerExcluded);
463
        }
464
      else return false;
465
      }
466

    
467
    int randMove = rnd.nextInt(numMoves);
468
    int moveIndex = currState.getNthMove(randMove,axisExcluded,layerExcluded);
469
    ObjectSignature signature = currState.getMove(moveIndex);
470
    currState.fillOutScramble(scramble[curr],moveIndex);
471

    
472
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
473
    mStatesHistory.add(nextState);
474

    
475
    return true;
476
    }
477

    
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479
// TYPE 2
480

    
481
  private boolean buildMove1Cons(int[][] scramble, Random rnd, int curr)
482
    {
483
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
484
    int axisExcluded = curr>=1 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
485
    int numMoves = currState.numMoves(axisExcluded);
486

    
487
    while( numMoves==0 )
488
      {
489
      if( curr>0 )
490
        {
491
        mStatesHistory.remove(curr);
492
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
493
        ObjectSignature signature = currState.getSignature();
494
        prevState.removeMoves(signature);
495
        mBlacklisted.add(signature);
496
        boolean result = buildMove1Cons(scramble,rnd,curr-1);
497
        if( !result ) return false;
498
        currState = mStatesHistory.get(curr);
499
        axisExcluded = scramble[curr-1][0];
500
        numMoves = currState.numMoves(axisExcluded);
501
        }
502
      else
503
        {
504
        return false;
505
        }
506
      }
507

    
508
    int randMove = rnd.nextInt(numMoves);
509
    int moveIndex = currState.getNthMove(randMove,axisExcluded);
510
    ObjectSignature signature = currState.getMove(moveIndex);
511
    currState.fillOutScramble(scramble[curr],moveIndex);
512

    
513
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
514
    mStatesHistory.add(nextState);
515

    
516
    return true;
517
    }
518

    
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520
// TYPE 2
521

    
522
  private void initializeType2Scrambling(int[][] scramble, Random rnd, int total, ObjectSignature signature)
523
    {
524
    if( mStatesHistory==null ) mStatesHistory = new ArrayList<>();
525
    else                       mStatesHistory.clear();
526

    
527
    if( mBlacklisted==null ) mBlacklisted = BlacklistedSignatures.getInstance();
528
    else                     mBlacklisted.clear();
529

    
530
    ScrambleStateBandagedCuboid state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
531
    mStatesHistory.add(state);
532
    boolean success = true;
533

    
534
    for(int curr=0; curr<total; curr++)
535
      {
536
      boolean result = buildMove1Cons(scramble,rnd,curr);
537
      if( !result )
538
        {
539
        success = false;
540
        break;
541
        }
542
      }
543

    
544
    if( !success )
545
      {
546
      success = true;
547
      mStatesHistory.clear();
548
      mBlacklisted.clear();
549
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
550
      mStatesHistory.add(state);
551

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

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

    
570
      for(int curr=0; curr<total; curr++)
571
        {
572
        buildMoveForced(scramble,rnd,curr);
573
        }
574
      }
575
    }
576

    
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578
// TYPE 2   (locally-created bandaged cuboids)
579

    
580
  private void randomizeNewScramble2(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
581
    {
582
    if( curr==0 ) initializeType2Scrambling(scramble,rnd,total,signature);
583
    }
584

    
585
///////////////////////////////////////////////////////////////////////////////////////////////////
586
// PUBLIC API
587

    
588
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
589
    {
590
    switch(mType)
591
      {
592
      case 0: randomizeNewScramble0(scramble, rnd, curr); break;
593
      case 1: randomizeNewScramble1(scramble, rnd, curr); break;
594
      case 2: randomizeNewScramble2(scramble, rnd, curr, total, signature); break;
595
      }
596
    }
597
  }
(2-2/6)