Project

General

Profile

« Previous | Next » 

Revision 1d581993

Added by Leszek Koltunski about 2 years ago

Introduce ObjectSignature that can incorporate 192-bit signatures (for 5x5x5 bandaged cubes).
ObjectScrambler does not fully work yet.

View differences:

src/main/java/org/distorted/objectlib/scrambling/ScrambleStateBandagedCuboid.java
19 19

  
20 20
package org.distorted.objectlib.scrambling;
21 21

  
22
import java.util.LinkedHashMap;
23
import java.util.Iterator;
24
import java.util.Map;
25

  
26 22
///////////////////////////////////////////////////////////////////////////////////////////////////
27
// Producer of the ScrambleStateGraph for any bandaged 3x3x3.
23
// Info about a scramble state of any bandaged cuboid.
24

  
25
import org.distorted.objectlib.helpers.ObjectSignature;
28 26

  
29 27
public class ScrambleStateBandagedCuboid
30 28
{
29
  public static int MAX_SUPPORTED_SIZE = 5;
30

  
31 31
  public static final int AXIS_NONE = -1;
32 32
  public static final int AXIS_X = 0;
33 33
  public static final int AXIS_Y = 1;
34 34
  public static final int AXIS_Z = 2;
35 35

  
36
  private static final long INVALID_MOVE = -1;
37
  private static final int NUM_MOVES = 27;
38

  
39
  private static final int LAYER_L = 0;
40
  private static final int LAYER_M = 1;
41
  private static final int LAYER_R = 2;
42

  
43
  private long mID;
44
  private int mDistance;
45
  private final long[] mMoves;
36
  private final ObjectSignature[] mMoves;
37
  private final ObjectSignature mSignature;
38
  private final int[] mLayer, mTurns;
39
  private final int mNumMoves;
40
  private final int mStartX, mStartY, mStartZ;
41
  private final boolean[][] mIsUnblocked;
46 42

  
47 43
///////////////////////////////////////////////////////////////////////////////////////////////////
48 44

  
49
  public ScrambleStateBandagedCuboid(long id)
45
  public ScrambleStateBandagedCuboid(int x, int y, int z, ObjectSignature signature)
50 46
    {
51
    mDistance = -1;
52
    mID = id;
53
    mMoves = createMoves(mID);
47
    mLayer = new int[3];
48
    mTurns = new int[3];
49

  
50
    mIsUnblocked = new boolean[3][MAX_SUPPORTED_SIZE];
51

  
52
    mLayer[0] = x;
53
    mLayer[1] = y;
54
    mLayer[2] = z;
55

  
56
    mTurns[0] = mLayer[1]==mLayer[2] ? 3:1;
57
    mTurns[1] = mLayer[0]==mLayer[2] ? 3:1;
58
    mTurns[2] = mLayer[0]==mLayer[1] ? 3:1;
59

  
60
    int xMoves = mLayer[0]>1 ? mTurns[0]*mLayer[0] : 0;
61
    int yMoves = mLayer[1]>1 ? mTurns[1]*mLayer[1] : 0;
62
    int zMoves = mLayer[2]>1 ? mTurns[2]*mLayer[2] : 0;
63

  
64
    mNumMoves = xMoves + yMoves + zMoves;
65

  
66
    mStartX = 0;
67
    mStartY = xMoves;
68
    mStartZ = xMoves + yMoves;
69

  
70
    mSignature = signature;
71

  
72
    mMoves = createMoves();
73

  
74

  
75
android.util.Log.d("D", "sig: "+mSignature.getString() );
76
printMoves();
77

  
54 78
    }
55 79

  
56 80
///////////////////////////////////////////////////////////////////////////////////////////////////
57 81

  
58
  public long getID()
82
  public ObjectSignature getSignature()
59 83
    {
60
    return mID;
84
    return mSignature;
61 85
    }
62 86

  
63 87
///////////////////////////////////////////////////////////////////////////////////////////////////
64 88

  
65
  private void setID(long id)
89
  public ObjectSignature getMove(int index)
66 90
    {
67
    mID = id;
91
    return (index>=0 && index<mNumMoves) ? mMoves[index] : null;
68 92
    }
69 93

  
70 94
///////////////////////////////////////////////////////////////////////////////////////////////////
71 95

  
72
  public long getMove(int index)
96
  public void removeMoves(ObjectSignature signature)
73 97
    {
74
    return (index>=0 && index<NUM_MOVES) ? mMoves[index] : INVALID_MOVE;
98
    for(int m=0; m<mNumMoves; m++)
99
      if( signature.isEqual(mMoves[m]) ) mMoves[m]=null;
75 100
    }
76 101

  
77 102
///////////////////////////////////////////////////////////////////////////////////////////////////
......
80 105
    {
81 106
    int num = 0;
82 107

  
83
    if( mMoves[ 0]!=INVALID_MOVE || mMoves[ 1]!=INVALID_MOVE || mMoves[ 2]!=INVALID_MOVE ||
84
        mMoves[ 3]!=INVALID_MOVE || mMoves[ 4]!=INVALID_MOVE || mMoves[ 5]!=INVALID_MOVE ||
85
        mMoves[ 6]!=INVALID_MOVE || mMoves[ 7]!=INVALID_MOVE || mMoves[ 8]!=INVALID_MOVE   ) num++;
86

  
87
    if( mMoves[ 9]!=INVALID_MOVE || mMoves[10]!=INVALID_MOVE || mMoves[11]!=INVALID_MOVE ||
88
        mMoves[12]!=INVALID_MOVE || mMoves[13]!=INVALID_MOVE || mMoves[14]!=INVALID_MOVE ||
89
        mMoves[15]!=INVALID_MOVE || mMoves[16]!=INVALID_MOVE || mMoves[17]!=INVALID_MOVE   ) num++;
90

  
91
    if( mMoves[18]!=INVALID_MOVE || mMoves[19]!=INVALID_MOVE || mMoves[20]!=INVALID_MOVE ||
92
        mMoves[21]!=INVALID_MOVE || mMoves[22]!=INVALID_MOVE || mMoves[23]!=INVALID_MOVE ||
93
        mMoves[24]!=INVALID_MOVE || mMoves[25]!=INVALID_MOVE || mMoves[26]!=INVALID_MOVE   ) num++;
108
    for(int x=mStartX; x<mStartY  ; x++) if( mMoves[x]!=null ) { num++; break; }
109
    for(int y=mStartY; y<mStartZ  ; y++) if( mMoves[y]!=null ) { num++; break; }
110
    for(int z=mStartZ; z<mNumMoves; z++) if( mMoves[z]!=null ) { num++; break; }
94 111

  
95 112
    return num;
96 113
    }
......
100 117
  private int numXMoves()
101 118
    {
102 119
    int num=0;
103

  
104
    if( mMoves[ 0]!=INVALID_MOVE ) num++;
105
    if( mMoves[ 1]!=INVALID_MOVE ) num++;
106
    if( mMoves[ 2]!=INVALID_MOVE ) num++;
107
    if( mMoves[ 3]!=INVALID_MOVE ) num++;
108
    if( mMoves[ 4]!=INVALID_MOVE ) num++;
109
    if( mMoves[ 5]!=INVALID_MOVE ) num++;
110
    if( mMoves[ 6]!=INVALID_MOVE ) num++;
111
    if( mMoves[ 7]!=INVALID_MOVE ) num++;
112
    if( mMoves[ 8]!=INVALID_MOVE ) num++;
113

  
120
    for(int x=mStartX; x<mStartY; x++) if( mMoves[x]!=null ) num++;
114 121
    return num;
115 122
    }
116 123

  
......
119 126
  private int numYMoves()
120 127
    {
121 128
    int num=0;
122

  
123
    if( mMoves[ 9]!=INVALID_MOVE ) num++;
124
    if( mMoves[10]!=INVALID_MOVE ) num++;
125
    if( mMoves[11]!=INVALID_MOVE ) num++;
126
    if( mMoves[12]!=INVALID_MOVE ) num++;
127
    if( mMoves[13]!=INVALID_MOVE ) num++;
128
    if( mMoves[14]!=INVALID_MOVE ) num++;
129
    if( mMoves[15]!=INVALID_MOVE ) num++;
130
    if( mMoves[16]!=INVALID_MOVE ) num++;
131
    if( mMoves[17]!=INVALID_MOVE ) num++;
132

  
129
    for(int y=mStartY; y<mStartZ; y++) if( mMoves[y]!=null ) num++;
133 130
    return num;
134 131
    }
135 132

  
......
138 135
  private int numZMoves()
139 136
    {
140 137
    int num=0;
141

  
142
    if( mMoves[18]!=INVALID_MOVE ) num++;
143
    if( mMoves[19]!=INVALID_MOVE ) num++;
144
    if( mMoves[20]!=INVALID_MOVE ) num++;
145
    if( mMoves[21]!=INVALID_MOVE ) num++;
146
    if( mMoves[22]!=INVALID_MOVE ) num++;
147
    if( mMoves[23]!=INVALID_MOVE ) num++;
148
    if( mMoves[24]!=INVALID_MOVE ) num++;
149
    if( mMoves[25]!=INVALID_MOVE ) num++;
150
    if( mMoves[26]!=INVALID_MOVE ) num++;
151

  
138
    for(int z=mStartZ; z<mNumMoves; z++) if( mMoves[z]!=null ) num++;
152 139
    return num;
153 140
    }
154 141

  
......
170 157
      case AXIS_Z: return numXMoves()+numYMoves();
171 158
      }
172 159

  
173
    int ret= numXMoves()+numYMoves()+numZMoves();
174

  
175
    //android.util.Log.e("D", "numMoves returning "+ret+" "+formatMoves() );
176

  
177
    return ret;
160
    return numXMoves()+numYMoves()+numZMoves();
178 161
    }
179 162

  
180 163
///////////////////////////////////////////////////////////////////////////////////////////////////
......
183 166
    {
184 167
    int num = 0;
185 168

  
186
    for(int m=0; m<NUM_MOVES; m++)
169
    if( excludedAxis!=0 )
187 170
      {
188
      if( (m/9)!=excludedAxis && mMoves[m]!=INVALID_MOVE)
189
        {
190
        if( num==n ) return m;
191
        num++;
192
        }
193
      }
194

  
195
    return -1;
196
    }
197

  
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

  
200
  public void removeMoves(long signature)
201
    {
202
    for(int m=0; m<NUM_MOVES; m++)
203
      if( signature==mMoves[m] ) mMoves[m]=INVALID_MOVE;
204
    }
205

  
206
///////////////////////////////////////////////////////////////////////////////////////////////////
207

  
208
  private void setMove(int index, long newMove)
209
    {
210
    if( index>=0 && index<NUM_MOVES ) mMoves[index] = newMove;
211
    }
212

  
213
///////////////////////////////////////////////////////////////////////////////////////////////////
214

  
215
  public String formatMoves()
216
    {
217
    String x = getTable( 0);
218
    String y = getTable( 9);
219
    String z = getTable(18);
220

  
221
    return mID+"\n"+x+"\n"+y+"\n"+z;
222
    }
223

  
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

  
226
  private String getTable(int index)
227
    {
228
    long m0 = getMove(index  );
229
    long m1 = getMove(index+1);
230
    long m2 = getMove(index+2);
231
    long m3 = getMove(index+3);
232
    long m4 = getMove(index+4);
233
    long m5 = getMove(index+5);
234
    long m6 = getMove(index+6);
235
    long m7 = getMove(index+7);
236
    long m8 = getMove(index+8);
237

  
238
    String ret = "";
239

  
240
    if( m0!=INVALID_MOVE ) ret += formatRet(ret,0,-1,m0);
241
    if( m1!=INVALID_MOVE ) ret += formatRet(ret,0, 2,m1);
242
    if( m2!=INVALID_MOVE ) ret += formatRet(ret,0, 1,m2);
243
    if( m3!=INVALID_MOVE ) ret += formatRet(ret,1,-1,m3);
244
    if( m4!=INVALID_MOVE ) ret += formatRet(ret,1, 2,m4);
245
    if( m5!=INVALID_MOVE ) ret += formatRet(ret,1, 1,m5);
246
    if( m6!=INVALID_MOVE ) ret += formatRet(ret,2,-1,m6);
247
    if( m7!=INVALID_MOVE ) ret += formatRet(ret,2, 2,m7);
248
    if( m8!=INVALID_MOVE ) ret += formatRet(ret,2, 1,m8);
249

  
250
    return formatL("{" + ret + "}");
251
    }
252

  
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

  
255
  private int[] getMoves(int index)
256
    {
257
    int numValid = 0;
258
    for(int i=index; i<index+9; i++) if( mMoves[i]!=INVALID_MOVE ) numValid++;
259

  
260
    int[] ret = new int[3*numValid];
261

  
262
    long m0 = getMove(index  );
263
    long m1 = getMove(index+1);
264
    long m2 = getMove(index+2);
265
    long m3 = getMove(index+3);
266
    long m4 = getMove(index+4);
267
    long m5 = getMove(index+5);
268
    long m6 = getMove(index+6);
269
    long m7 = getMove(index+7);
270
    long m8 = getMove(index+8);
271

  
272
    int pointer=0;
273

  
274
    if( m0!=INVALID_MOVE ) { ret[pointer]=0; ret[pointer+1]=-1; ret[pointer+2]= (int)m0; pointer+=3; }
275
    if( m1!=INVALID_MOVE ) { ret[pointer]=0; ret[pointer+1]= 2; ret[pointer+2]= (int)m1; pointer+=3; }
276
    if( m2!=INVALID_MOVE ) { ret[pointer]=0; ret[pointer+1]= 1; ret[pointer+2]= (int)m2; pointer+=3; }
277
    if( m3!=INVALID_MOVE ) { ret[pointer]=1; ret[pointer+1]=-1; ret[pointer+2]= (int)m3; pointer+=3; }
278
    if( m4!=INVALID_MOVE ) { ret[pointer]=1; ret[pointer+1]= 2; ret[pointer+2]= (int)m4; pointer+=3; }
279
    if( m5!=INVALID_MOVE ) { ret[pointer]=1; ret[pointer+1]= 1; ret[pointer+2]= (int)m5; pointer+=3; }
280
    if( m6!=INVALID_MOVE ) { ret[pointer]=2; ret[pointer+1]=-1; ret[pointer+2]= (int)m6; pointer+=3; }
281
    if( m7!=INVALID_MOVE ) { ret[pointer]=2; ret[pointer+1]= 2; ret[pointer+2]= (int)m7; pointer+=3; }
282
    if( m8!=INVALID_MOVE ) { ret[pointer]=2; ret[pointer+1]= 1; ret[pointer+2]= (int)m8; pointer+=3; }
283

  
284
    return ret;
285
    }
286

  
287
///////////////////////////////////////////////////////////////////////////////////////////////////
288

  
289
  private ScrambleState produceScrambleState()
290
    {
291
    int[] xMoves = getMoves(0);
292
    int[] yMoves = getMoves(9);
293
    int[] zMoves = getMoves(18);
294

  
295
    int[][] moves = { xMoves,yMoves,zMoves };
296

  
297
    return new ScrambleState( moves );
298
    }
299

  
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301
// STATIC STUFF
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303

  
304
  public static ScrambleState[] computeGraph(long id)
305
    {
306
    ScrambleStateBandagedCuboid bsg = new ScrambleStateBandagedCuboid(id);
307
    Map<Long, ScrambleStateBandagedCuboid> graph = new LinkedHashMap<>();
308
    graph.put(id,bsg);
309

  
310
    insertChildren(graph,id);
311
    // if there's only one state, do not prune moves which point to itself
312
    if(graph.size()>1) pruneGraph(graph,id);
313
    computeDistance(graph,id,0);
314
    removeDisconnectedParts(graph);
315
    remapGraph(graph);
316

  
317
    int num = graph.size();
318
    ScrambleState[] ret = new ScrambleState[num];
319

  
320
    for (Map.Entry<Long, ScrambleStateBandagedCuboid> entry : graph.entrySet())
321
      {
322
      ScrambleStateBandagedCuboid value = entry.getValue();
323
      int mid = (int)value.mID;
324
      ret[mid] = value.produceScrambleState();
325
      }
326

  
327
    return ret;
328
    }
329

  
330
///////////////////////////////////////////////////////////////////////////////////////////////////
331

  
332
  private static void insertChildren(Map<Long, ScrambleStateBandagedCuboid> map, long id)
333
    {
334
    ScrambleStateBandagedCuboid bsg = findState(map,id);
335

  
336
    if( bsg==null )
337
      {
338
      android.util.Log.e("D", "error: "+id+" doesn't exist");
339
      return;
340
      }
341

  
342
    for(int i=0; i<NUM_MOVES; i++)
343
      {
344
      long move = bsg.getMove(i);
345

  
346
      if( move!=INVALID_MOVE )
347
        {
348
        ScrambleStateBandagedCuboid tmp = findState(map,move);
349

  
350
        if( tmp==null )
171
      for(int m=mStartX; m<mStartY; m++)
172
        if( mMoves[m]!=null )
351 173
          {
352
          tmp = new ScrambleStateBandagedCuboid(move);
353
          map.put(move,tmp);
354
          insertChildren(map,move);
174
          if( num==n ) return m;
175
          num++;
355 176
          }
356
        }
357 177
      }
358
    }
359 178

  
360
///////////////////////////////////////////////////////////////////////////////////////////////////
361

  
362
  private static void pruneGraph(Map<Long, ScrambleStateBandagedCuboid> map, long startingID)
363
    {
364
    boolean pruned = false;
365
    boolean startingIsSingle = false;
366

  
367
    Iterator<Map.Entry<Long, ScrambleStateBandagedCuboid>> it = map.entrySet().iterator();
368

  
369
    while (it.hasNext())
179
    if( excludedAxis!=1 )
370 180
      {
371
      Map.Entry<Long, ScrambleStateBandagedCuboid> entry = it.next();
372
      ScrambleStateBandagedCuboid value = entry.getValue();
373

  
374
      if( value.numAxis()<2 )
375
        {
376
        long prunedID = value.getID();
377

  
378
        if( prunedID!=startingID ) // do not remove the starting point, even if it does have only 1 axis
379
          {
380
          it.remove();
381
          pruned = true;
382
          }
383
        else
181
      for(int m=mStartY; m<mStartZ; m++)
182
        if( mMoves[m]!=null )
384 183
          {
385
          startingIsSingle = true;
184
          if( num==n ) return m;
185
          num++;
386 186
          }
387
        }
388 187
      }
389 188

  
390
    for (Map.Entry<Long, ScrambleStateBandagedCuboid> entry : map.entrySet() )
189
    if( excludedAxis!=2 )
391 190
      {
392
      ScrambleStateBandagedCuboid value = entry.getValue();
393

  
394
      for(int m=0; m<NUM_MOVES; m++)
395
        {
396
        long move = value.mMoves[m];
397
        ScrambleStateBandagedCuboid tmp = findState(map,move);
398

  
399
        if( tmp==null || (startingIsSingle && move==startingID) )
400
          {
401
          value.mMoves[m]=INVALID_MOVE;
402
          }
403
        }
404
      }
405

  
406
    if( pruned ) pruneGraph(map,startingID);
407
    }
408

  
409
///////////////////////////////////////////////////////////////////////////////////////////////////
410

  
411
  private static void remapGraph(Map<Long, ScrambleStateBandagedCuboid> map)
412
    {
413
    int id=0;
414

  
415
    for (Map.Entry<Long, ScrambleStateBandagedCuboid> entry : map.entrySet())
416
      {
417
      ScrambleStateBandagedCuboid value = entry.getValue();
418
      value.mID = id++;
419
      }
420

  
421
    for (Map.Entry<Long, ScrambleStateBandagedCuboid> entry : map.entrySet())
422
      {
423
      ScrambleStateBandagedCuboid value = entry.getValue();
424

  
425
      for(int m=0; m<NUM_MOVES; m++)
426
        {
427
        long move = value.mMoves[m];
428

  
429
        if( move!=INVALID_MOVE )
430
          {
431
          ScrambleStateBandagedCuboid tmp = map.get(move);
432
          value.mMoves[m] = tmp.mID;
433
          }
434
        }
435
      }
436
    }
437

  
438
///////////////////////////////////////////////////////////////////////////////////////////////////
439

  
440
  private static void computeDistance(Map<Long, ScrambleStateBandagedCuboid> map, long id, int distance)
441
    {
442
    ScrambleStateBandagedCuboid state = findState(map,id);
443

  
444
    if( state==null )
445
      {
446
      android.util.Log.e("D", "error: "+id+" doesn't exist");
447
      return;
448
      }
449

  
450
    if( state.mDistance<0 )
451
      {
452
      state.mDistance = distance;
453

  
454
      for(int i=0; i<NUM_MOVES; i++)
455
        {
456
        long move = state.getMove(i);
457

  
458
        if( move!=INVALID_MOVE )
191
      for(int m=mStartZ; m<mNumMoves; m++)
192
        if( mMoves[m]!=null )
459 193
          {
460
          computeDistance(map,move,distance+1);
194
          if( num==n ) return m;
195
          num++;
461 196
          }
462
        }
463 197
      }
464
    }
465

  
466
///////////////////////////////////////////////////////////////////////////////////////////////////
467

  
468
  private static void removeDisconnectedParts(Map<Long, ScrambleStateBandagedCuboid> map)
469
    {
470
    Iterator<Map.Entry<Long, ScrambleStateBandagedCuboid>> it = map.entrySet().iterator();
471

  
472
    while (it.hasNext())
473
      {
474
      Map.Entry<Long, ScrambleStateBandagedCuboid> entry = it.next();
475
      ScrambleStateBandagedCuboid value = entry.getValue();
476
      if( value.mDistance<0 ) it.remove();
477
      }
478
    }
479

  
480
///////////////////////////////////////////////////////////////////////////////////////////////////
481

  
482
  private static ScrambleStateBandagedCuboid findState(Map<Long, ScrambleStateBandagedCuboid> map, long id)
483
    {
484
    return map.get(id);
485
    }
486

  
487
///////////////////////////////////////////////////////////////////////////////////////////////////
488

  
489
  private static String formatRet(String str, int row, int angle, long id)
490
    {
491
    String ret = str.length()!=0 ? ",":"";
492

  
493
    ret += row;
494
    ret += angle<0 ? "," : ", ";
495
    ret += angle;
496

  
497
         if( id< 10 ) ret += (",  "+id);
498
    else if( id<100 ) ret += (", " +id);
499
    else              ret += (","  +id);
500

  
501
    return ret;
502
    }
503

  
504
///////////////////////////////////////////////////////////////////////////////////////////////////
505

  
506
  private static final int LENGTH = 28;
507 198

  
508
  private static String formatL(String input)
509
    {
510
    int len = input.length();
511
    String ret = input;
512
    for(int i=0 ;i<LENGTH-len; i++) ret += " ";
513
    return ret;
199
    return -1;
514 200
    }
515 201

  
516 202
///////////////////////////////////////////////////////////////////////////////////////////////////
517 203

  
518
  private static long[] createMoves(long id)
204
  private ObjectSignature[] createMoves()
519 205
    {
520
    long[] ret = new long[NUM_MOVES];
206
    ObjectSignature[] ret = new ObjectSignature[mNumMoves];
521 207
    int index = 0;
522 208

  
523 209
    for(int axis=0; axis<3; axis++)
524
      for(int layer=0; layer<3; layer++)
525
        {
526
        long x1 = turn(id,axis,layer);
210
      for(int layer=0; layer<mLayer[axis]; layer++)
211
        mIsUnblocked[axis][layer] = mSignature.isUnblockedFromLeft(axis,layer);
527 212

  
528
        if( x1!=INVALID_MOVE )
529
          {
530
          long x2 = turn(x1,axis,layer);
531
          long x3 = turn(x2,axis,layer);
532

  
533
          ret[index  ] = x1;
534
          ret[index+1] = x2;
535
          ret[index+2] = x3;
536
          }
537
        else
213
    for(int axis=0; axis<3; axis++)
214
      if( mLayer[axis]>1 )
215
        for(int turn=0; turn<mTurns[axis]; turn++)
538 216
          {
539
          ret[index  ] = INVALID_MOVE;
540
          ret[index+1] = INVALID_MOVE;
541
          ret[index+2] = INVALID_MOVE;
217
          boolean allLayersLocked = true;
218

  
219
          for(int layer=0; layer<mLayer[axis]; layer++)
220
            {
221
            if( mIsUnblocked[axis][layer] )
222
              {
223
              if( layer>0 ) allLayersLocked = false;
224
              ret[index] = mSignature.turn(axis,layer,turn);
225
              }
226
            else
227
              {
228
              ret[index] = ret[index-1].turn(axis,layer,turn);
229
              ret[index-1] = null;
230
              }
231

  
232
            index++;
233
            }
234

  
235
          if( allLayersLocked ) ret[index-1] = null;
542 236
          }
543 237

  
544
        index+=3;
545
        }
546

  
547 238
    return ret;
548 239
    }
549 240

  
550
///////////////////////////////////////////////////////////////////////////////////////////////////
551
// Definition of the id: it's an 'Andreas signature' of a bandaged cube.
552
// https://twistypuzzles.com/forum/viewtopic.php?t=24452&sid=f3b4ac0c611c4713e4d7840f1aabbb0b&start=350
553

  
554
  private static long turn(long id, int axis, int layer)
555
    {
556
    switch(axis)
557
      {
558
      case AXIS_X: switch(layer)
559
                     {
560
                     case LAYER_L: if( getBit(id, 1)==1 || getBit(id, 6)==1 || getBit(id,11)==1 ||
561
                                       getBit(id,22)==1 || getBit(id,27)==1 || getBit(id,32)==1 ||
562
                                       getBit(id,43)==1 || getBit(id,48)==1 || getBit(id,53)==1  ) return INVALID_MOVE;
563

  
564
                                   long x1 = cycle(id,9,14,46,41);
565
                                   long x2 = cycle(x1,4,35,51,20);
566
                                   return    cycle(x2,17,25,38,30);
567

  
568
                     case LAYER_M: if( getBit(id, 1)==1 || getBit(id, 6)==1 || getBit(id,11)==1 ||
569
                                       getBit(id,22)==1 || getBit(id,27)==1 || getBit(id,32)==1 ||
570
                                       getBit(id,43)==1 || getBit(id,48)==1 || getBit(id,53)==1 ||
571
                                       getBit(id, 0)==1 || getBit(id, 5)==1 || getBit(id,10)==1 ||
572
                                       getBit(id,21)==1 || getBit(id,26)==1 || getBit(id,31)==1 ||
573
                                       getBit(id,42)==1 || getBit(id,47)==1 || getBit(id,52)==1  ) return INVALID_MOVE;
574

  
575
                                   long x4 = cycle(id,8,13,45,40);
576
                                   long x5 = cycle(x4,3,34,50,19);
577
                                   return    cycle(x5,16,24,37,29);
578

  
579
                     case LAYER_R: if( getBit(id, 0)==1 || getBit(id, 5)==1 || getBit(id,10)==1 ||
580
                                       getBit(id,21)==1 || getBit(id,26)==1 || getBit(id,31)==1 ||
581
                                       getBit(id,42)==1 || getBit(id,47)==1 || getBit(id,52)==1  ) return INVALID_MOVE;
582

  
583
                                   long x7 = cycle(id,7,12,44,39);
584
                                   long x8 = cycle(x7,2,33,49,18);
585
                                   return    cycle(x8,15,23,36,28);
586
                     }
587

  
588
      case AXIS_Y: switch(layer)
589
                     {
590
                     case LAYER_L: if( getBit(id,12)==1 || getBit(id,13)==1 || getBit(id,14)==1 ||
591
                                       getBit(id,15)==1 || getBit(id,16)==1 || getBit(id,17)==1 ||
592
                                       getBit(id,18)==1 || getBit(id,19)==1 || getBit(id,20)==1  ) return INVALID_MOVE;
593

  
594
                                   long y1 = cycle(id,1,9,10,2);
595
                                   long y2 = cycle(y1,0,4,11,7);
596
                                   return    cycle(y2,3,6,8,5);
597

  
598
                     case LAYER_M: if( getBit(id,12)==1 || getBit(id,13)==1 || getBit(id,14)==1 ||
599
                                       getBit(id,15)==1 || getBit(id,16)==1 || getBit(id,17)==1 ||
600
                                       getBit(id,18)==1 || getBit(id,19)==1 || getBit(id,20)==1 ||
601
                                       getBit(id,33)==1 || getBit(id,34)==1 || getBit(id,35)==1 ||
602
                                       getBit(id,36)==1 || getBit(id,37)==1 || getBit(id,38)==1 ||
603
                                       getBit(id,39)==1 || getBit(id,40)==1 || getBit(id,41)==1  ) return INVALID_MOVE;
604

  
605
                                   long y4 = cycle(id,21,25,32,28);
606
                                   long y5 = cycle(y4,22,30,31,23);
607
                                   return    cycle(y5,24,27,29,26);
608

  
609
                     case LAYER_R: if( getBit(id,33)==1 || getBit(id,34)==1 || getBit(id,35)==1 ||
610
                                       getBit(id,36)==1 || getBit(id,37)==1 || getBit(id,38)==1 ||
611
                                       getBit(id,39)==1 || getBit(id,40)==1 || getBit(id,41)==1  ) return INVALID_MOVE;
612

  
613
                                   long y7 = cycle(id,42,46,53,49);
614
                                   long y8 = cycle(y7,43,51,52,44);
615
                                   return    cycle(y8,45,48,50,47);
616
                     }
617

  
618
      case AXIS_Z: switch(layer)
619
                     {
620
                     case LAYER_L: if( getBit(id, 7)==1 || getBit(id, 8)==1 || getBit(id, 9)==1 ||
621
                                       getBit(id,28)==1 || getBit(id,29)==1 || getBit(id,30)==1 ||
622
                                       getBit(id,49)==1 || getBit(id,50)==1 || getBit(id,51)==1  ) return INVALID_MOVE;
623

  
624
                                   long z1 = cycle(id,10,20,53,39);
625
                                   long z2 = cycle(z1,11,41,52,18);
626
                                   return    cycle(z2,19,32,40,31);
627

  
628
                     case LAYER_M: if( getBit(id, 7)==1 || getBit(id, 8)==1 || getBit(id, 9)==1 ||
629
                                       getBit(id,28)==1 || getBit(id,29)==1 || getBit(id,30)==1 ||
630
                                       getBit(id,49)==1 || getBit(id,50)==1 || getBit(id,51)==1 ||
631
                                       getBit(id, 2)==1 || getBit(id, 3)==1 || getBit(id, 4)==1 ||
632
                                       getBit(id,23)==1 || getBit(id,24)==1 || getBit(id,25)==1 ||
633
                                       getBit(id,44)==1 || getBit(id,45)==1 || getBit(id,46)==1  ) return INVALID_MOVE;
634

  
635
                                   long z4 = cycle(id,5,17,48,36);
636
                                   long z5 = cycle(z4,6,38,47,15);
637
                                   return    cycle(z5,16,27,37,26);
638

  
639
                     case LAYER_R: if( getBit(id, 2)==1 || getBit(id, 3)==1 || getBit(id, 4)==1 ||
640
                                       getBit(id,23)==1 || getBit(id,24)==1 || getBit(id,25)==1 ||
641
                                       getBit(id,44)==1 || getBit(id,45)==1 || getBit(id,46)==1  ) return INVALID_MOVE;
642

  
643
                                   long z7 = cycle(id,0,14,43,33);
644
                                   long z8 = cycle(z7,1,35,42,12);
645
                                   return    cycle(z8,13,22,34,21);
646
                     }
647
      }
648

  
649
    return 0;
650
    }
651

  
652
///////////////////////////////////////////////////////////////////////////////////////////////////
653
// bit b1 in place of b2 etc.
654

  
655
  private static long cycle(long id, int b1, int b2, int b3, int b4)
656
    {
657
    long bit1 = getBit(id,b1);
658
    long bit2 = getBit(id,b2);
659
    long bit3 = getBit(id,b3);
660
    long bit4 = getBit(id,b4);
661

  
662
    long i1 = setBit(id,b2,bit1);
663
    long i2 = setBit(i1,b3,bit2);
664
    long i3 = setBit(i2,b4,bit3);
665
    return    setBit(i3,b1,bit4);
666
    }
667

  
668
///////////////////////////////////////////////////////////////////////////////////////////////////
669

  
670
  private static long getBit(long id, int bit)
671
    {
672
    return (id>>bit)&0x1;
673
    }
674

  
675
///////////////////////////////////////////////////////////////////////////////////////////////////
676

  
677
  private static long setBit(long id, int bit, long value)
678
    {
679
    long old = getBit(id,bit);
680

  
681
    if( old!=value )
682
      {
683
      long diff = (1L<<bit);
684
      id += (value==0 ? -diff : diff);
685
      }
686

  
687
    return id;
688
    }
689

  
690 241
///////////////////////////////////////////////////////////////////////////////////////////////////
691 242

  
692 243
  private void printMoves()
693 244
    {
694 245
    String moves = "";
695 246

  
696
    for(int i=0; i<NUM_MOVES; i++)
247
    for(int i=0; i<mNumMoves; i++)
697 248
      {
698
      moves += (" " + mMoves[i]);
249
      moves += (mMoves[i]!=null ? " "+mMoves[i].getString() : " NULL");
699 250
      }
700 251

  
701 252
    android.util.Log.e("D", moves);
......
721 272

  
722 273
    return ret + "]";
723 274
    }
724

  
725
///////////////////////////////////////////////////////////////////////////////////////////////////
726

  
727
  private static void printGraph(Map<Long, ScrambleStateBandagedCuboid> map)
728
    {
729
    int num = map.size();
730
    android.util.Log.e("D", "\n"+num+" states\n");
731

  
732
    for (Map.Entry<Long, ScrambleStateBandagedCuboid> entry : map.entrySet())
733
      {
734
      ScrambleStateBandagedCuboid value = entry.getValue();
735
      android.util.Log.e("D", value.formatMoves());
736
      }
737
    }
738 275
}

Also available in: Unified diff