Project

General

Profile

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

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

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 9ba7f3f6 Leszek Koltunski
  private final int[][] mAlgorithms;
26 29b82486 Leszek Koltunski
27
  // type=0, i.e. main
28
  private int mCurrState;
29 9ba7f3f6 Leszek Koltunski
  private int mAxisExcluded;
30 29b82486 Leszek Koltunski
  private int[][] mScrambleTable;
31
  private int[] mNumOccurences;
32 e9ec2e9d Leszek Koltunski
  private int[] mResult;
33 1b5f9f0e Leszek Koltunski
  private int mCurrAlgorithm;
34
  private int mCurrStep;
35 29b82486 Leszek Koltunski
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 95123ad0 Leszek Koltunski
  // type=2 , i.e. locally created bandaged cuboids
51 e342c3f7 Leszek Koltunski
  private ArrayList<ScrambleStateBandagedCuboid> mStatesHistory;
52
  private BlacklistedSignatures mBlacklisted;
53 0e311558 Leszek Koltunski
54 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
55
56 9ba7f3f6 Leszek Koltunski
  public ObjectScrambler(int type, int numAxis, int[] numLayers, int[][] algorithms, int[][] edges)
57 29b82486 Leszek Koltunski
    {
58 9ba7f3f6 Leszek Koltunski
    mType       = type;
59
    mNumAxis    = numAxis;
60
    mNumLayers  = numLayers;
61
    mAlgorithms = algorithms;
62
63 e9ec2e9d Leszek Koltunski
    if( mType==0 )
64
      {
65
      mResult = new int[2];
66
      }
67
68 9ba7f3f6 Leszek Koltunski
    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 29b82486 Leszek Koltunski
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 9ba7f3f6 Leszek Koltunski
    if( mScrambleTable==null )
89 29b82486 Leszek Koltunski
      {
90 a57e6870 Leszek Koltunski
      mScrambleTable = new int[mNumAxis][];
91 29b82486 Leszek Koltunski
      }
92 9ba7f3f6 Leszek Koltunski
    if( mNumOccurences==null )
93 29b82486 Leszek Koltunski
      {
94
      int max=0;
95
96
      for (ScrambleState mState : mStates)
97
        {
98 9ba7f3f6 Leszek Koltunski
        int tmp = mState.getTotal();
99 29b82486 Leszek Koltunski
        if (max < tmp) max = tmp;
100
        }
101
102
      mNumOccurences = new int[max];
103
      }
104
105
    for(int i=0; i<mNumAxis; i++)
106 a57e6870 Leszek Koltunski
      {
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 29b82486 Leszek Koltunski
    }
112
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114
// PUBLIC API
115
116 a72a4b6a Leszek Koltunski
  private void randomizeNewScramble0(int[][] scramble, Random rnd, int curr)
117 29b82486 Leszek Koltunski
    {
118
    if( curr==0 )
119
      {
120 9ba7f3f6 Leszek Koltunski
      mCurrState    = 0;
121
      mAxisExcluded =-1;
122 29b82486 Leszek Koltunski
      initializeScrambling();
123
      }
124
125 1b5f9f0e Leszek Koltunski
    if( mCurrStep+6 <= mAlgorithms[mCurrAlgorithm].length )
126
      {
127
      mCurrStep += 3;
128
      }
129
    else
130
      {
131
      mStates[mCurrState].getRandom(rnd, mAlgorithms, mAxisExcluded, mScrambleTable, mNumOccurences, mResult);
132
      mCurrAlgorithm = mResult[0];
133
      mCurrState     = mResult[1];
134
      mCurrStep      = 0;
135
      }
136 29b82486 Leszek Koltunski
137 1b5f9f0e Leszek Koltunski
    int[] algorithm = mAlgorithms[mCurrAlgorithm];
138
    scramble[curr][0] = algorithm[mCurrStep  ];
139
    scramble[curr][1] = algorithm[mCurrStep+1];
140
    scramble[curr][2] = algorithm[mCurrStep+2];
141 29b82486 Leszek Koltunski
142 9ba7f3f6 Leszek Koltunski
    mAxisExcluded = algorithm[0];
143 29b82486 Leszek Koltunski
    }
144
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146 4a5157a1 Leszek Koltunski
// TYPE 1
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148
// QUATS[i]*QUATS[j] = QUATS[QUAT_MULT[i][j]]
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
151
  void initializeQuatMult()
152
    {
153
    mQuatMult = new int[][]
154
      {
155
        {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,},
156
        {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12,},
157
        {  2,  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13,},
158
        {  3,  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2, 15, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14,},
159
        {  4,  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3, 16, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15,},
160
        {  5,  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4, 17, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16,},
161
        {  6,  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5, 18, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17,},
162
        {  7,  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6, 19, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18,},
163
        {  8,  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7, 20, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19,},
164
        {  9, 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8, 21, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20,},
165
        { 10, 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 22, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,},
166
        { 11,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 23, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,},
167
        { 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,},
168
        { 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,},
169
        { 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16, 15,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,  3,},
170
        { 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17, 16,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,  4,},
171
        { 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18, 17,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,  5,},
172
        { 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19, 18,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,  6,},
173
        { 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20, 19,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,  7,},
174
        { 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21, 20,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,  8,},
175
        { 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,  9,},
176
        { 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11, 10,},
177
        { 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0, 11,},
178
        { 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,}
179
      };
180
    }
181
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183
// TYPE 1
184 29b82486 Leszek Koltunski
185
  private boolean cornerIsUp(int index)
186
    {
187
    return ((index<4) ^ (mCornerQuat[index]>=12));
188
    }
189
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191 4a5157a1 Leszek Koltunski
// TYPE 1
192 29b82486 Leszek Koltunski
193
  private boolean cornerIsLeft(int index)
194
    {
195
    int q = mCornerQuat[index];
196
197
    switch(index)
198
      {
199
      case 0:
200
      case 4: return ((q>=3 && q<= 7) || (q>=18 && q<=22));
201
      case 1:
202
      case 5: return ((q>=6 && q<=10) || (q>=15 && q<=19));
203
      case 2:
204
      case 6: return ((q==0 || q==1 || (q>=9 && q<=11)) || (q>=12 && q<=16));
205
      case 3:
206
      case 7: return ((q>=0 && q<=4) || (q==12 || q==13 || (q>=21 && q<=23)));
207
      }
208
209
    return false;
210
    }
211
212
///////////////////////////////////////////////////////////////////////////////////////////////////
213 4a5157a1 Leszek Koltunski
// TYPE 1
214 29b82486 Leszek Koltunski
215
  private boolean quatIsBad(int quatIndex, int corner)
216
    {
217
    if( mBadCornerQuats ==null )
218
      {
219
      // quat indices that make corner cubits bandage the puzzle.
220
      mBadCornerQuats = new int[][] { { 2, 8,17,23}, { 5,11,14,20} };
221
      }
222
223
    int index = (corner%2);
224
225
    return ( quatIndex== mBadCornerQuats[index][0] ||
226
             quatIndex== mBadCornerQuats[index][1] ||
227
             quatIndex== mBadCornerQuats[index][2] ||
228
             quatIndex== mBadCornerQuats[index][3]  );
229
    }
230
231
///////////////////////////////////////////////////////////////////////////////////////////////////
232 4a5157a1 Leszek Koltunski
// TYPE 1
233 29b82486 Leszek Koltunski
234
  private boolean isPermittedDo(int angle)
235
    {
236
    if( mQuatMult==null ) initializeQuatMult();
237
238
    for(int corner=0; corner<8; corner++)
239
      {
240
      if( !cornerIsUp(corner) )
241
        {
242
        int currQuat = mCornerQuat[corner];
243
        int finalQuat= mQuatMult[angle][currQuat];
244
        if( quatIsBad(finalQuat,corner) ) return false;
245
        }
246
      }
247
248
    return true;
249
    }
250
251
///////////////////////////////////////////////////////////////////////////////////////////////////
252 4a5157a1 Leszek Koltunski
// TYPE 1
253 29b82486 Leszek Koltunski
254
  private boolean isPermittedUp(int angle)
255
    {
256
    if( mQuatMult==null ) initializeQuatMult();
257
258
    for(int corner=0; corner<8; corner++)
259
      {
260
      if( cornerIsUp(corner) )
261
        {
262
        int currQuat = mCornerQuat[corner];
263
        int finalQuat= mQuatMult[angle][currQuat];
264
        if( quatIsBad(finalQuat,corner) ) return false;
265
        }
266
      }
267
268
    return true;
269
    }
270
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272 4a5157a1 Leszek Koltunski
// TYPE 1
273 29b82486 Leszek Koltunski
274
  private void computePermittedAngles()
275
    {
276
    mPermittedDo = 0;
277
278
    for(int angle=0; angle<BASIC_ANGLE; angle++)
279
      {
280
      if( isPermittedDo(angle ) ) mPermittedAngles[0][mPermittedDo++] = angle;
281
      }
282
283
    mPermittedUp = 0;
284
285
    for(int angle=0; angle<BASIC_ANGLE; angle++)
286
      {
287
      if( isPermittedUp(angle ) ) mPermittedAngles[1][mPermittedUp++] = angle;
288
      }
289
    }
290
291
///////////////////////////////////////////////////////////////////////////////////////////////////
292 4a5157a1 Leszek Koltunski
// TYPE 1
293 29b82486 Leszek Koltunski
294
  private int getNextAngle(Random rnd, int layer)
295
    {
296
    int num = layer==0 ? mPermittedDo:mPermittedUp;
297
    int index = rnd.nextInt(num);
298
    int angle = mPermittedAngles[layer][index];
299
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
300
    }
301
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303 4a5157a1 Leszek Koltunski
// TYPE 1
304 29b82486 Leszek Koltunski
305
  private int getNextAngleNotZero(Random rnd, int layer)
306
    {
307
    int num = layer==0 ? mPermittedDo:mPermittedUp;
308
    int index = rnd.nextInt(num-1);
309
    int angle = mPermittedAngles[layer][index+1];
310
    return angle<BASIC_ANGLE/2 ? -angle : BASIC_ANGLE-angle;
311
    }
312
313
///////////////////////////////////////////////////////////////////////////////////////////////////
314 4a5157a1 Leszek Koltunski
// TYPE 1
315 29b82486 Leszek Koltunski
316
  private int makeQuat(int axis,int index)
317
    {
318
    if( axis==1 ) return 13;
319
    if( index<0 ) index+=12;
320
    return index;
321
    }
322
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324 4a5157a1 Leszek Koltunski
// TYPE 1
325 29b82486 Leszek Koltunski
326
  private boolean cornerBelongs(int index, int axis, int layer)
327
    {
328
    if( axis==0 )
329
      {
330
      boolean up = cornerIsUp(index);
331
      return ((up && layer==2) || (!up && layer==0));
332
      }
333
    else
334
      {
335
      boolean le = cornerIsLeft(index);
336
      return ((le && layer==0) || (!le && layer==1));
337
      }
338
    }
339
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341 4a5157a1 Leszek Koltunski
// TYPE 1
342 29b82486 Leszek Koltunski
343
  private void updateCornerQuats(int[] rotInfo)
344
    {
345
    if( mQuatMult==null ) initializeQuatMult();
346
347
    int axis = rotInfo[0];
348
    int layer= rotInfo[1];
349
    int index=-rotInfo[2];
350
351
    int quat = makeQuat(axis,index);
352
353
    for(int corner=0; corner<8; corner++)
354
      {
355
      if( cornerBelongs(corner,axis,layer) )
356
        {
357
        int curr = mCornerQuat[corner];
358
        mCornerQuat[corner] = mQuatMult[quat][curr];
359
        }
360
      }
361
    }
362
363
///////////////////////////////////////////////////////////////////////////////////////////////////
364 4a5157a1 Leszek Koltunski
// TYPE 1
365 29b82486 Leszek Koltunski
366 a72a4b6a Leszek Koltunski
  private void randomizeNewScramble1(int[][] scramble, Random rnd, int curr)
367 29b82486 Leszek Koltunski
    {
368
    int layer, nextAngle;
369
370
    if( curr==0 )
371
      {
372
      for(int corner=0; corner<8; corner++) mCornerQuat[corner] = 0;
373
      mLastRot = rnd.nextInt(4);
374
      computePermittedAngles();
375
      }
376
377
    switch(mLastRot)
378
      {
379
      case LAST_SL: layer = rnd.nextInt(2);
380
                    nextAngle = getNextAngle(rnd,layer);
381
382
                    if( nextAngle==0 )
383
                      {
384
                      layer = 1-layer;
385
                      nextAngle = getNextAngleNotZero(rnd,layer);
386
                      }
387
388
                    scramble[curr][0] = 0;
389
                    scramble[curr][1] = 2*layer;
390
                    scramble[curr][2] = nextAngle;
391
                    mLastRot = layer==0 ? LAST_LO : LAST_UP;
392
                    updateCornerQuats(scramble[curr]);
393
                    break;
394
      case LAST_LO:
395
      case LAST_UP: layer = mLastRot==LAST_LO ? 1:0;
396
                    nextAngle = getNextAngle(rnd,layer);
397
398
                    if( nextAngle!=0 )
399
                      {
400
                      scramble[curr][0] = 0;
401
                      scramble[curr][1] = 2*layer;
402
                      scramble[curr][2] = nextAngle;
403
                      updateCornerQuats(scramble[curr]);
404
                      mLastRot = LAST_UL;
405
                      }
406
                    else
407
                      {
408
                      scramble[curr][0] = 1;
409
                      scramble[curr][1] = rnd.nextInt(2);
410
                      scramble[curr][2] = 1;
411
                      mLastRot = LAST_SL;
412
                      updateCornerQuats(scramble[curr]);
413
                      computePermittedAngles();
414
                      }
415
416
                    break;
417
      case LAST_UL: scramble[curr][0] = 1;
418
                    scramble[curr][1] = rnd.nextInt(2);
419
                    scramble[curr][2] = 1;
420
                    mLastRot = LAST_SL;
421
                    updateCornerQuats(scramble[curr]);
422
                    computePermittedAngles();
423
                    break;
424
      }
425
    }
426
427 0e311558 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
428
// TYPE 2
429
430
  private void buildMoveForced(int[][] scramble, Random rnd, int curr)
431
    {
432 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
433 95123ad0 Leszek Koltunski
    int indexExcluded = curr>0 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
434 0e311558 Leszek Koltunski
    int numMoves = currState.numMoves(indexExcluded);
435 a72a4b6a Leszek Koltunski
    ObjectSignature signature;
436 0e311558 Leszek Koltunski
437
    if( numMoves==0 )
438
      {
439 95123ad0 Leszek Koltunski
      indexExcluded = ScrambleStateBandagedCuboid.AXIS_NONE;
440 0e311558 Leszek Koltunski
      numMoves = currState.numMoves(indexExcluded);
441
      }
442
443 c60d98c4 Leszek Koltunski
    if( numMoves==0 )
444
      {
445
      scramble[curr][0] = 0;
446
      scramble[curr][1] = 0;
447
      scramble[curr][2] = 0;
448 a72a4b6a Leszek Koltunski
      signature = currState.getSignature();
449 c60d98c4 Leszek Koltunski
      }
450
    else
451
      {
452
      int randMove = rnd.nextInt(numMoves);
453
      int moveIndex = currState.getNthMove(randMove,indexExcluded);
454 a72a4b6a Leszek Koltunski
      signature = currState.getMove(moveIndex);
455 338e42aa Leszek Koltunski
      currState.fillOutScramble(scramble[curr],moveIndex);
456 0e311558 Leszek Koltunski
      }
457
458 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
459
    mStatesHistory.add(nextState);
460 0e311558 Leszek Koltunski
    }
461
462 3a5aa558 Leszek Koltunski
463 0e311558 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
464
// TYPE 2
465
466 3a5aa558 Leszek Koltunski
  private boolean buildMove2Cons(int[][] scramble, Random rnd, int curr)
467 0e311558 Leszek Koltunski
    {
468 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
469 3a5aa558 Leszek Koltunski
    boolean lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
470
    int axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
471
    int layerExcluded= !lock && curr>=1 ? scramble[curr-1][1] : -1;
472
    int numMoves = currState.numMoves(axisExcluded,layerExcluded);
473 0e311558 Leszek Koltunski
474
    while( numMoves==0 )
475
      {
476
      if( curr>0 )
477
        {
478 e342c3f7 Leszek Koltunski
        mStatesHistory.remove(curr);
479
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
480 1d581993 Leszek Koltunski
        ObjectSignature signature = currState.getSignature();
481 0e311558 Leszek Koltunski
        prevState.removeMoves(signature);
482 e342c3f7 Leszek Koltunski
        mBlacklisted.add(signature);
483 3a5aa558 Leszek Koltunski
        boolean result = buildMove2Cons(scramble,rnd,curr-1);
484 0e311558 Leszek Koltunski
        if( !result ) return false;
485 e342c3f7 Leszek Koltunski
        currState = mStatesHistory.get(curr);
486 3a5aa558 Leszek Koltunski
        lock= (curr>=2 && scramble[curr-2][0]==scramble[curr-1][0] );
487
        axisExcluded = lock ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
488
        layerExcluded= lock ? -1 : scramble[curr-1][1];
489
        numMoves = currState.numMoves(axisExcluded,layerExcluded);
490
        }
491
      else return false;
492
      }
493
494
    int randMove = rnd.nextInt(numMoves);
495
    int moveIndex = currState.getNthMove(randMove,axisExcluded,layerExcluded);
496
    ObjectSignature signature = currState.getMove(moveIndex);
497
    currState.fillOutScramble(scramble[curr],moveIndex);
498
499 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
500
    mStatesHistory.add(nextState);
501 3a5aa558 Leszek Koltunski
502
    return true;
503
    }
504
505
///////////////////////////////////////////////////////////////////////////////////////////////////
506
// TYPE 2
507
508
  private boolean buildMove1Cons(int[][] scramble, Random rnd, int curr)
509
    {
510 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid currState = mStatesHistory.get(curr);
511 3a5aa558 Leszek Koltunski
    int axisExcluded = curr>=1 ? scramble[curr-1][0] : ScrambleStateBandagedCuboid.AXIS_NONE;
512
    int numMoves = currState.numMoves(axisExcluded);
513
514
    while( numMoves==0 )
515
      {
516
      if( curr>0 )
517
        {
518 e342c3f7 Leszek Koltunski
        mStatesHistory.remove(curr);
519
        ScrambleStateBandagedCuboid prevState = mStatesHistory.get(curr-1);
520 3a5aa558 Leszek Koltunski
        ObjectSignature signature = currState.getSignature();
521
        prevState.removeMoves(signature);
522 e342c3f7 Leszek Koltunski
        mBlacklisted.add(signature);
523 3a5aa558 Leszek Koltunski
        boolean result = buildMove1Cons(scramble,rnd,curr-1);
524
        if( !result ) return false;
525 e342c3f7 Leszek Koltunski
        currState = mStatesHistory.get(curr);
526 3a5aa558 Leszek Koltunski
        axisExcluded = scramble[curr-1][0];
527
        numMoves = currState.numMoves(axisExcluded);
528 0e311558 Leszek Koltunski
        }
529
      else
530
        {
531
        return false;
532
        }
533
      }
534
535
    int randMove = rnd.nextInt(numMoves);
536 3a5aa558 Leszek Koltunski
    int moveIndex = currState.getNthMove(randMove,axisExcluded);
537 a72a4b6a Leszek Koltunski
    ObjectSignature signature = currState.getMove(moveIndex);
538 338e42aa Leszek Koltunski
    currState.fillOutScramble(scramble[curr],moveIndex);
539 0e311558 Leszek Koltunski
540 e342c3f7 Leszek Koltunski
    ScrambleStateBandagedCuboid nextState = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
541
    mStatesHistory.add(nextState);
542 0e311558 Leszek Koltunski
543
    return true;
544
    }
545
546
///////////////////////////////////////////////////////////////////////////////////////////////////
547
// TYPE 2
548
549 a72a4b6a Leszek Koltunski
  private void initializeType2Scrambling(int[][] scramble, Random rnd, int total, ObjectSignature signature)
550 0e311558 Leszek Koltunski
    {
551 e342c3f7 Leszek Koltunski
    if( mStatesHistory==null ) mStatesHistory = new ArrayList<>();
552
    else                       mStatesHistory.clear();
553 0e311558 Leszek Koltunski
554 e342c3f7 Leszek Koltunski
    if( mBlacklisted==null ) mBlacklisted = BlacklistedSignatures.getInstance();
555
    else                     mBlacklisted.clear();
556
557
    ScrambleStateBandagedCuboid state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
558
    mStatesHistory.add(state);
559 0e311558 Leszek Koltunski
    boolean success = true;
560
561
    for(int curr=0; curr<total; curr++)
562
      {
563 3a5aa558 Leszek Koltunski
      boolean result = buildMove1Cons(scramble,rnd,curr);
564 0e311558 Leszek Koltunski
      if( !result )
565
        {
566
        success = false;
567
        break;
568
        }
569
      }
570
571 3a5aa558 Leszek Koltunski
    if( !success )
572
      {
573
      success = true;
574 e342c3f7 Leszek Koltunski
      mStatesHistory.clear();
575 2d7aea5b Leszek Koltunski
      mBlacklisted.clear();
576 e342c3f7 Leszek Koltunski
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
577
      mStatesHistory.add(state);
578 3a5aa558 Leszek Koltunski
579
      for(int curr=0; curr<total; curr++)
580
        {
581
        boolean result = buildMove2Cons(scramble,rnd,curr);
582
        if( !result )
583
          {
584
          success = false;
585
          break;
586
          }
587
        }
588
      }
589
590 0e311558 Leszek Koltunski
    if( !success )
591
      {
592 e342c3f7 Leszek Koltunski
      mStatesHistory.clear();
593 1a7bab14 Leszek Koltunski
      mBlacklisted.clear();
594 e342c3f7 Leszek Koltunski
      state = new ScrambleStateBandagedCuboid(mNumLayers[0], mNumLayers[1], mNumLayers[2], signature, mBlacklisted);
595
      mStatesHistory.add(state);
596 0e311558 Leszek Koltunski
597
      for(int curr=0; curr<total; curr++)
598
        {
599
        buildMoveForced(scramble,rnd,curr);
600
        }
601
      }
602
    }
603
604
///////////////////////////////////////////////////////////////////////////////////////////////////
605 95123ad0 Leszek Koltunski
// TYPE 2   (locally-created bandaged cuboids)
606 0e311558 Leszek Koltunski
607 a72a4b6a Leszek Koltunski
  private void randomizeNewScramble2(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
608 0e311558 Leszek Koltunski
    {
609 a72a4b6a Leszek Koltunski
    if( curr==0 ) initializeType2Scrambling(scramble,rnd,total,signature);
610 0e311558 Leszek Koltunski
    }
611
612 29b82486 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
613
// PUBLIC API
614
615 a72a4b6a Leszek Koltunski
  public void randomizeNewScramble(int[][] scramble, Random rnd, int curr, int total, ObjectSignature signature)
616 29b82486 Leszek Koltunski
    {
617 a72a4b6a Leszek Koltunski
    switch(mType)
618
      {
619
      case 0: randomizeNewScramble0(scramble, rnd, curr); break;
620
      case 1: randomizeNewScramble1(scramble, rnd, curr); break;
621
      case 2: randomizeNewScramble2(scramble, rnd, curr, total, signature); break;
622
      }
623 29b82486 Leszek Koltunski
    }
624
  }