Project

General

Profile

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

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

1 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6 babb7b08 Leszek Koltunski
// 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 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
9
10 10b7e306 Leszek Koltunski
package org.distorted.objectlib.scrambling;
11 198c5bf0 Leszek Koltunski
12 0e311558 Leszek Koltunski
import java.util.ArrayList;
13 29b82486 Leszek Koltunski
import java.util.Random;
14
15 1d581993 Leszek Koltunski
import org.distorted.objectlib.helpers.ObjectSignature;
16
17 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
18
19 10b7e306 Leszek Koltunski
public class ObjectScrambler
20 29b82486 Leszek Koltunski
  {
21
  private final ScrambleState[] mStates;
22
  private final int mType;
23
  private final int mNumAxis;
24 a57e6870 Leszek Koltunski
  private final int[] mNumLayers;
25 29b82486 Leszek Koltunski
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 95123ad0 Leszek Koltunski
  // type=2 , i.e. locally created bandaged cuboids
47 e342c3f7 Leszek Koltunski
  private ArrayList<ScrambleStateBandagedCuboid> mStatesHistory;
48
  private BlacklistedSignatures mBlacklisted;
49 0e311558 Leszek Koltunski
50 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
51
52 10b7e306 Leszek Koltunski
  public ObjectScrambler(int type, int numAxis, int[] numLayers, ScrambleState[] states)
53 29b82486 Leszek Koltunski
    {
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 a57e6870 Leszek Koltunski
      mScrambleTable = new int[mNumAxis][];
74 29b82486 Leszek Koltunski
      }
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 a57e6870 Leszek Koltunski
      {
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 29b82486 Leszek Koltunski
    }
95
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97
// PUBLIC API
98
99 a72a4b6a Leszek Koltunski
  private void randomizeNewScramble0(int[][] scramble, Random rnd, int curr)
100 29b82486 Leszek Koltunski
    {
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 4a5157a1 Leszek Koltunski
// 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 29b82486 Leszek Koltunski
158
  private boolean cornerIsUp(int index)
159
    {
160
    return ((index<4) ^ (mCornerQuat[index]>=12));
161
    }
162
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164 4a5157a1 Leszek Koltunski
// TYPE 1
165 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
187 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
206 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
226 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
246 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
266 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
277 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
288 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
298 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
315 29b82486 Leszek Koltunski
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 4a5157a1 Leszek Koltunski
// TYPE 1
338 29b82486 Leszek Koltunski
339 a72a4b6a Leszek Koltunski
  private void randomizeNewScramble1(int[][] scramble, Random rnd, int curr)
340 29b82486 Leszek Koltunski
    {
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 0e311558 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
401
// TYPE 2
402
403
  private void buildMoveForced(int[][] scramble, Random rnd, int curr)
404
    {
405 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
406 95123ad0 Leszek Koltunski
    int indexExcluded = curr>0 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
407 0e311558 Leszek Koltunski
    int numMoves = currState.numMoves(indexExcluded);
408 a72a4b6a Leszek Koltunski
    ObjectSignature signature;
409 0e311558 Leszek Koltunski
410
    if( numMoves==0 )
411
      {
412 95123ad0 Leszek Koltunski
      indexExcluded = ScrambleStateBandagedCuboid.AXIS_NONE;
413 0e311558 Leszek Koltunski
      numMoves = currState.numMoves(indexExcluded);
414
      }
415
416 c60d98c4 Leszek Koltunski
    if( numMoves==0 )
417
      {
418
      scramble[curr][0] = 0;
419
      scramble[curr][1] = 0;
420
      scramble[curr][2] = 0;
421 a72a4b6a Leszek Koltunski
      signature = currState.getSignature();
422 c60d98c4 Leszek Koltunski
      }
423
    else
424
      {
425
      int randMove = rnd.nextInt(numMoves);
426
      int moveIndex = currState.getNthMove(randMove,indexExcluded);
427 a72a4b6a Leszek Koltunski
      signature = currState.getMove(moveIndex);
428 338e42aa Leszek Koltunski
      currState.fillOutScramble(scramble[curr],moveIndex);
429 0e311558 Leszek Koltunski
      }
430
431 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
432
    mStatesHistory.add(nextState);
433 0e311558 Leszek Koltunski
    }
434
435 3a5aa558 Leszek Koltunski
436 0e311558 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
437
// TYPE 2
438
439 3a5aa558 Leszek Koltunski
  private boolean buildMove2Cons(int[][] scramble, Random rnd, int curr)
440 0e311558 Leszek Koltunski
    {
441 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
442 3a5aa558 Leszek Koltunski
    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 0e311558 Leszek Koltunski
447
    while( numMoves==0 )
448
      {
449
      if( curr>0 )
450
        {
451 e342c3f7 Leszek Koltunski
        mStatesHistory.remove(curr);
452
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
453 1d581993 Leszek Koltunski
        ObjectSignature signature = currState.getSignature();
454 0e311558 Leszek Koltunski
        prevState.removeMoves(signature);
455 e342c3f7 Leszek Koltunski
        mBlacklisted.add(signature);
456 3a5aa558 Leszek Koltunski
        boolean result = buildMove2Cons(scramble,rnd,curr-1);
457 0e311558 Leszek Koltunski
        if( !result ) return false;
458 e342c3f7 Leszek Koltunski
        currState = mStatesHistory.get(curr);
459 3a5aa558 Leszek Koltunski
        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 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
473
    mStatesHistory.add(nextState);
474 3a5aa558 Leszek Koltunski
475
    return true;
476
    }
477
478
///////////////////////////////////////////////////////////////////////////////////////////////////
479
// TYPE 2
480
481
  private boolean buildMove1Cons(int[][] scramble, Random rnd, int curr)
482
    {
483 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
484 3a5aa558 Leszek Koltunski
    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 e342c3f7 Leszek Koltunski
        mStatesHistory.remove(curr);
492
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
493 3a5aa558 Leszek Koltunski
        ObjectSignature signature = currState.getSignature();
494
        prevState.removeMoves(signature);
495 e342c3f7 Leszek Koltunski
        mBlacklisted.add(signature);
496 3a5aa558 Leszek Koltunski
        boolean result = buildMove1Cons(scramble,rnd,curr-1);
497
        if( !result ) return false;
498 e342c3f7 Leszek Koltunski
        currState = mStatesHistory.get(curr);
499 3a5aa558 Leszek Koltunski
        axisExcluded = scramble[curr-1][0];
500
        numMoves = currState.numMoves(axisExcluded);
501 0e311558 Leszek Koltunski
        }
502
      else
503
        {
504
        return false;
505
        }
506
      }
507
508
    int randMove = rnd.nextInt(numMoves);
509 3a5aa558 Leszek Koltunski
    int moveIndex = currState.getNthMove(randMove,axisExcluded);
510 a72a4b6a Leszek Koltunski
    ObjectSignature signature = currState.getMove(moveIndex);
511 338e42aa Leszek Koltunski
    currState.fillOutScramble(scramble[curr],moveIndex);
512 0e311558 Leszek Koltunski
513 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
514
    mStatesHistory.add(nextState);
515 0e311558 Leszek Koltunski
516
    return true;
517
    }
518
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520
// TYPE 2
521
522 a72a4b6a Leszek Koltunski
  private void initializeType2Scrambling(int[][] scramble, Random rnd, int total, ObjectSignature signature)
523 0e311558 Leszek Koltunski
    {
524 e342c3f7 Leszek Koltunski
    if( mStatesHistory==null ) mStatesHistory = new ArrayList<>();
525
    else                       mStatesHistory.clear();
526 0e311558 Leszek Koltunski
527 e342c3f7 Leszek Koltunski
    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 0e311558 Leszek Koltunski
    boolean success = true;
533
534
    for(int curr=0; curr<total; curr++)
535
      {
536 3a5aa558 Leszek Koltunski
      boolean result = buildMove1Cons(scramble,rnd,curr);
537 0e311558 Leszek Koltunski
      if( !result )
538
        {
539
        success = false;
540
        break;
541
        }
542
      }
543
544 3a5aa558 Leszek Koltunski
    if( !success )
545
      {
546
      success = true;
547 e342c3f7 Leszek Koltunski
      mStatesHistory.clear();
548 2d7aea5b Leszek Koltunski
      mBlacklisted.clear();
549 e342c3f7 Leszek Koltunski
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
550
      mStatesHistory.add(state);
551 3a5aa558 Leszek Koltunski
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 0e311558 Leszek Koltunski
    if( !success )
564
      {
565 e342c3f7 Leszek Koltunski
      mStatesHistory.clear();
566 1a7bab14 Leszek Koltunski
      mBlacklisted.clear();
567 e342c3f7 Leszek Koltunski
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
568
      mStatesHistory.add(state);
569 0e311558 Leszek Koltunski
570
      for(int curr=0; curr<total; curr++)
571
        {
572
        buildMoveForced(scramble,rnd,curr);
573
        }
574
      }
575
    }
576
577
///////////////////////////////////////////////////////////////////////////////////////////////////
578 95123ad0 Leszek Koltunski
// TYPE 2   (locally-created bandaged cuboids)
579 0e311558 Leszek Koltunski
580 a72a4b6a Leszek Koltunski
  private void randomizeNewScramble2(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
581 0e311558 Leszek Koltunski
    {
582 a72a4b6a Leszek Koltunski
    if( curr==0 ) initializeType2Scrambling(scramble,rnd,total,signature);
583 0e311558 Leszek Koltunski
    }
584
585 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
586
// PUBLIC API
587
588 a72a4b6a Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
589 29b82486 Leszek Koltunski
    {
590 a72a4b6a Leszek Koltunski
    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 29b82486 Leszek Koltunski
    }
597
  }