Project

General

Profile

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

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

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