Project

General

Profile

« Previous | Next » 

Revision 6cf89a3e

Added by Leszek Koltunski about 3 years ago

Introduce pseudorandom balancing into scrambling in case of the two Dinos (from now on, the more times a particular (ax,layer) combination has been chosen already in the scrambling sequence, the less likely it is to be chosen next).
Fix Dino6 - isSolved(). Sadly, it cannot be the geeneric function - it needs to be another special case.

View differences:

src/main/java/org/distorted/helpers/ScrambleState.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
package org.distorted.helpers;
21

  
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23

  
24
import java.util.Random;
25

  
26
public class ScrambleState
27
{
28
  private final int mTotal, mNumAxis;
29
  private final int[] mNum;
30
  private final int[] mInfo;
31
  private final int[] mTmp;
32
  private final int LEN = 4;
33

  
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35

  
36
  public ScrambleState(int[][] axis)
37
    {
38
    mTmp = new int[LEN];
39

  
40
    mNumAxis = axis.length;
41
    mNum = new int[mNumAxis];
42
    int total =0;
43

  
44
    for(int i=0; i<mNumAxis; i++)
45
      {
46
      mNum[i] = axis[i]==null ? 0 : axis[i].length/(LEN-1);
47
      total += mNum[i];
48
      }
49

  
50
    mTotal = total;
51

  
52
    mInfo = new int[LEN*total];
53
    int start = 0;
54

  
55
    for(int i=0; i<mNumAxis; i++)
56
      {
57
      for(int j=0; j<mNum[i]; j++)
58
        {
59
        mInfo[LEN*j   + start] = i;
60
        mInfo[LEN*j+1 + start] = axis[i][(LEN-1)*j  ];
61
        mInfo[LEN*j+2 + start] = axis[i][(LEN-1)*j+1];
62
        mInfo[LEN*j+3 + start] = axis[i][(LEN-1)*j+2];
63
        }
64

  
65
      start += LEN*mNum[i];
66
      }
67
    }
68

  
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

  
71
  private int getIndex(int num, int indexExcluded)
72
    {
73
    int current= -1;
74

  
75
    for(int i=0; i<mTotal; i++)
76
      if( mInfo[LEN*i]!=indexExcluded && ++current==num ) return i;
77

  
78
    return -1;
79
    }
80

  
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

  
83
  public int[] getRandom(Random rnd, int indexExcluded, int[][] scrambleTable, int[] numOccurences)
84
    {
85
    int num=0, total=0, max=0, ax, layer;
86

  
87
    for(int i=0; i<mTotal; i++)
88
      {
89
      ax = mInfo[LEN*i];
90

  
91
      if( ax!=indexExcluded )
92
        {
93
        layer = mInfo[LEN*i+1];
94
        int value = scrambleTable[ax][layer];
95
        if( value>max ) max=value;
96
        }
97
      }
98

  
99
    for(int i=0; i<mTotal; i++)
100
      {
101
      ax = mInfo[LEN*i];
102

  
103
      if( ax!=indexExcluded )
104
        {
105
        layer = mInfo[LEN*i+1];
106
        int value = scrambleTable[ax][layer];
107
        numOccurences[total] = 1 + max - value + (total==0 ? 0 : numOccurences[total-1]);
108
        total++;
109
        }
110
      }
111

  
112
    float random= rnd.nextFloat()*numOccurences[total-1];
113

  
114
    for(int i=0; i<total; i++)
115
      {
116
      if( random <= numOccurences[i] )
117
        {
118
        num=i;
119
        break;
120
        }
121
      }
122

  
123
    int index = getIndex(num,indexExcluded);
124

  
125
    mTmp[0] = mInfo[LEN*index  ];   // axis
126
    mTmp[1] = mInfo[LEN*index+1];   // row
127
    mTmp[2] = mInfo[LEN*index+2];   // angle
128
    mTmp[3] = mInfo[LEN*index+3];   // next state
129

  
130
    scrambleTable[mTmp[0]][mTmp[1]]++;
131

  
132
    return mTmp;
133
    }
134

  
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

  
137
  public int getTotal(int indexExcluded)
138
    {
139
    return ( indexExcluded>=0 && indexExcluded<mNumAxis ) ? mTotal-mNum[indexExcluded] : mTotal;
140
    }
141

  
142
///////////////////////////////////////////////////////////////////////////////////////////////////
143

  
144
  public int[] getInfo(int num, int indexExcluded)
145
    {
146
    int index = getIndex(num,indexExcluded);
147

  
148
    mTmp[0] = mInfo[LEN*index  ];   // axis
149
    mTmp[1] = mInfo[LEN*index+1];   // row
150
    mTmp[2] = mInfo[LEN*index+2];   // angle
151
    mTmp[3] = mInfo[LEN*index+3];   // next state
152

  
153
    return mTmp;
154
    }
155
}
src/main/java/org/distorted/helpers/ScrambleStateBandagedEvil.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
package org.distorted.helpers;
21

  
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23
// producer of the ScrambleStateGraph - but only for a single Twisty Puzzle, the 'BandagedEvil'.
24

  
25
import java.util.ArrayList;
26

  
27
public class ScrambleStateBandagedEvil
28
{
29
  private static final int INVALID_MOVE = -1;
30

  
31
  private static final int CORNER_S = 0;
32
  private static final int CORNER_X = 1;
33
  private static final int CORNER_Y = 2;
34
  private static final int CORNER_Z = 3;
35

  
36
  private static final int CENTER_0 = 0;
37
  private static final int CENTER_1 = 1;
38
  private static final int CENTER_2 = 2;
39
  private static final int CENTER_3 = 3;
40

  
41
  private int mID;
42
  private final int[] mMoves;
43

  
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

  
46
  public ScrambleStateBandagedEvil(int id)
47
    {
48
    mID = id;
49
    mMoves = createMoves(mID);
50
    }
51

  
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

  
54
  public static void computeGraph()
55
    {
56
    ArrayList<ScrambleStateBandagedEvil> graph;
57

  
58
    int id = 0;
59
    int id1 = setCenter(id  , CENTER_2, 0);
60
    int id2 = setCenter(id1 , CENTER_2, 1);
61
    int id3 = setCenter(id2 , CENTER_3, 2);
62
    int id4 = setCenter(id3 , CENTER_2, 3);
63

  
64
    int id5 = setCorner(id4 , CORNER_X, 0);
65
    int id6 = setCorner(id5 , CORNER_Y, 1);
66
    int id7 = setCorner(id6 , CORNER_X, 2);
67
    int id8 = setCorner(id7 , CORNER_Z, 3);
68
    int id9 = setCorner(id8 , CORNER_Y, 4);
69
    int id10= setCorner(id9 , CORNER_Y, 5);
70
    int id11= setCorner(id10, CORNER_S, 6);
71
    int id12= setCorner(id11, CORNER_Z, 7);
72

  
73
    ScrambleStateBandagedEvil bsg = new ScrambleStateBandagedEvil(id12);
74
    graph = new ArrayList<>();
75
    graph.add(bsg);
76

  
77
    insertChildren(graph,id12);
78
    pruneGraph(graph);
79
    remapGraph(graph);
80

  
81
    int num = graph.size();
82
    android.util.Log.e("D", "\n"+num+" states\n");
83

  
84
    for(int i=0; i<num; i++)
85
      {
86
      bsg = graph.get(i);
87
      android.util.Log.e("D", formatMoves(bsg));
88
      }
89
    }
90

  
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

  
93
  private static void insertChildren(ArrayList<ScrambleStateBandagedEvil> list, int id)
94
    {
95
    ScrambleStateBandagedEvil bsg = findState(list,id);
96

  
97
    if( bsg==null )
98
      {
99
      android.util.Log.e("D", "error: "+id+" doesn't exist");
100
      return;
101
      }
102

  
103
    for(int i=0; i<12; i++)
104
      {
105
      int move = bsg.getMove(i);
106

  
107
      if( move!=INVALID_MOVE )
108
        {
109
        ScrambleStateBandagedEvil tmp = findState(list,move);
110

  
111
        if( tmp==null )
112
          {
113
          tmp = new ScrambleStateBandagedEvil(move);
114
          list.add(tmp);
115
          insertChildren(list,move);
116
          }
117
        }
118
      }
119
    }
120

  
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

  
123
  private static void pruneGraph(ArrayList<ScrambleStateBandagedEvil> list)
124
    {
125
    int num = list.size(), numAxis;
126
    boolean pruned = false;
127
    ScrambleStateBandagedEvil bsg;
128

  
129
    for(int i=0; i<num; i++)
130
      {
131
      bsg = list.get(i);
132
      numAxis = bsg.numAxis();
133

  
134
      if( numAxis<2 )
135
        {
136
        list.remove(i);
137
        int id = bsg.getID();
138
        pruned = true;
139
        remapID(list,id,INVALID_MOVE);
140
        break;
141
        }
142
      }
143

  
144
    if( pruned ) pruneGraph(list);
145
    }
146

  
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

  
149
  private static void remapGraph(ArrayList<ScrambleStateBandagedEvil> list)
150
    {
151
    int id, num = list.size();
152
    ScrambleStateBandagedEvil bsg;
153

  
154
    for(int i=0; i<num; i++ )
155
      {
156
      bsg = list.get(i);
157
      id = bsg.getID();
158
      bsg.setID(i);
159
      remapID(list,id,i);
160
      }
161
    }
162

  
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

  
165
  private static void remapID(ArrayList<ScrambleStateBandagedEvil> list, int id, int newId)
166
    {
167
    ScrambleStateBandagedEvil bsg;
168
    int size = list.size();
169

  
170
    for(int i=0; i<size; i++)
171
      {
172
      bsg = list.get(i);
173

  
174
      for(int j=0; j<12; j++)
175
        {
176
        if( bsg.getMove(j)==id ) bsg.setMove(j,newId);
177
        }
178
      }
179
    }
180

  
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

  
183
  private static ScrambleStateBandagedEvil findState(ArrayList<ScrambleStateBandagedEvil> list, int id)
184
    {
185
    ScrambleStateBandagedEvil bsg;
186
    int num = list.size();
187

  
188
    for(int i=0; i<num; i++)
189
      {
190
      bsg= list.get(i);
191
      if( bsg.getID() == id ) return bsg;
192
      }
193

  
194
    return null;
195
    }
196

  
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

  
199
  private static String formatMoves(ScrambleStateBandagedEvil bsg)
200
    {
201
    String x = getTable(bsg,0);
202
    String y = getTable(bsg,3);
203
    String z = getTable(bsg,6);
204

  
205
    return "    new ScrambleStateGraph( new int[][] { "+x+", "+y+", "+z+" } ),";
206
    }
207

  
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

  
210
  private static String getTable(ScrambleStateBandagedEvil sc, int index)
211
    {
212
    String ret = "";
213

  
214
    if( index==0 || index==3 )
215
      {
216
      int m0 = sc.getMove(index  );
217
      int m1 = sc.getMove(index+1);
218
      int m2 = sc.getMove(index+2);
219

  
220
      if( m0==INVALID_MOVE && m1==INVALID_MOVE && m2==INVALID_MOVE ) return formatL("{}");
221

  
222
      if( m0!=INVALID_MOVE ) ret += formatRet(ret,2, 1,m0);
223
      if( m1!=INVALID_MOVE ) ret += formatRet(ret,2, 2,m1);
224
      if( m2!=INVALID_MOVE ) ret += formatRet(ret,2,-1,m2);
225
      }
226
    else
227
      {
228
      int m0 = sc.getMove(index  );
229
      int m1 = sc.getMove(index+1);
230
      int m2 = sc.getMove(index+2);
231
      int m3 = sc.getMove(index+3);
232
      int m4 = sc.getMove(index+4);
233
      int m5 = sc.getMove(index+5);
234

  
235
      if( m0==INVALID_MOVE && m1==INVALID_MOVE && m2==INVALID_MOVE &&
236
          m3==INVALID_MOVE && m4==INVALID_MOVE && m5==INVALID_MOVE  )
237
        {
238
        return formatL("{}");
239
        }
240

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

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

  
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

  
254
  private static String formatRet(String str, int row, int angle, int id)
255
    {
256
    String ret = str.length()!=0 ? ",":"";
257

  
258
    ret += row;
259
    ret += angle<0 ? "," : ", ";
260
    ret += angle;
261

  
262
         if( id< 10 ) ret += (",  "+id);
263
    else if( id<100 ) ret += (", " +id);
264
    else              ret += (","  +id);
265

  
266
    return ret;
267
    }
268

  
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270

  
271
  private static final int LENGTH = 28;
272

  
273
  private static String formatL(String input)
274
    {
275
    int len = input.length();
276
    String ret = input;
277
    for(int i=0 ;i<LENGTH-len; i++) ret += " ";
278
    return ret;
279
    }
280

  
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

  
283
  private int getID()
284
    {
285
    return mID;
286
    }
287

  
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

  
290
  private void setID(int id)
291
    {
292
    mID = id;
293
    }
294

  
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

  
297
  private int getMove(int index)
298
    {
299
    return (index>=0 && index<12) ? mMoves[index] : -1;
300
    }
301

  
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303

  
304
  private int numAxis()
305
    {
306
    int num = 0;
307

  
308
    if( mMoves[ 0]!=INVALID_MOVE || mMoves[ 1]!=INVALID_MOVE || mMoves[ 2]!=INVALID_MOVE ) num++;
309
    if( mMoves[ 3]!=INVALID_MOVE || mMoves[ 4]!=INVALID_MOVE || mMoves[ 5]!=INVALID_MOVE ) num++;
310
    if( mMoves[ 6]!=INVALID_MOVE || mMoves[ 7]!=INVALID_MOVE || mMoves[ 8]!=INVALID_MOVE ) num++;
311
    if( mMoves[ 9]!=INVALID_MOVE || mMoves[10]!=INVALID_MOVE || mMoves[11]!=INVALID_MOVE ) num++;
312

  
313
    return num;
314
    }
315

  
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

  
318
  private void setMove(int index, int newMove)
319
    {
320
    if( index>=0 && index<12 ) mMoves[index] = newMove;
321
    }
322

  
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

  
325
  private static String debug(int id)
326
    {
327
    int ce0 = getCenter(id,0);
328
    int ce1 = getCenter(id,1);
329
    int ce2 = getCenter(id,2);
330
    int ce3 = getCenter(id,3);
331

  
332
    int co0 = getCorner(id,0);
333
    int co1 = getCorner(id,1);
334
    int co2 = getCorner(id,2);
335
    int co3 = getCorner(id,3);
336
    int co4 = getCorner(id,4);
337
    int co5 = getCorner(id,5);
338
    int co6 = getCorner(id,6);
339
    int co7 = getCorner(id,7);
340

  
341
    String center = centerString(ce0) + centerString(ce1) + centerString(ce2) + centerString(ce3);
342
    String corner = cornerString(co0) + cornerString(co1) + cornerString(co2) + cornerString(co3) +
343
                    cornerString(co4) + cornerString(co5) + cornerString(co6) + cornerString(co7);
344

  
345
    return center + " -" + corner;
346
    }
347

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

  
350
  private static String centerString(int center)
351
    {
352
    return " "+center;
353
    }
354

  
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

  
357
  private static String cornerString(int corner)
358
    {
359
    switch(corner)
360
      {
361
      case CORNER_S: return " S";
362
      case CORNER_X: return " X";
363
      case CORNER_Y: return " Y";
364
      case CORNER_Z: return " Z";
365
      }
366

  
367
    return "?";
368
    }
369

  
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

  
372
  private static int[] createMoves(int id)
373
    {
374
    int[] ret = new int[12];
375

  
376
    boolean moveX  = xPossible(id);
377
    boolean moveY  = yPossible(id);
378
    boolean moveZ0 = z0Possible(id);
379
    boolean moveZ2 = z2Possible(id);
380

  
381
    if( moveX ) createXmoves(id,ret);
382
    else        { ret[ 0] = INVALID_MOVE; ret[ 1] = INVALID_MOVE; ret[ 2] = INVALID_MOVE; }
383
    if( moveY ) createYmoves(id,ret);
384
    else        { ret[ 3] = INVALID_MOVE; ret[ 4] = INVALID_MOVE; ret[ 5] = INVALID_MOVE; }
385
    if( moveZ0) createZ0moves(id,ret);
386
    else        { ret[ 6] = INVALID_MOVE; ret[ 7] = INVALID_MOVE; ret[ 8] = INVALID_MOVE; }
387
    if( moveZ2) createZ2moves(id,ret);
388
    else        { ret[ 9] = INVALID_MOVE; ret[10] = INVALID_MOVE; ret[11] = INVALID_MOVE; }
389

  
390
    return ret;
391
    }
392

  
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

  
395
  private static boolean xPossible(int id)
396
    {
397
    if( getCorner(id,4)==CORNER_X ) return false;
398
    if( getCorner(id,5)==CORNER_X ) return false;
399
    if( getCorner(id,6)==CORNER_X ) return false;
400
    if( getCorner(id,7)==CORNER_X ) return false;
401

  
402
    if( getCenter(id,1)==CENTER_1 ) return false;
403
    if( getCenter(id,2)==CENTER_1 ) return false;
404
    if( getCenter(id,3)==CENTER_1 ) return false;
405

  
406
    return true;
407
    }
408

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

  
411
  private static boolean yPossible(int id)
412
    {
413
    if( getCorner(id,2)==CORNER_Y ) return false;
414
    if( getCorner(id,3)==CORNER_Y ) return false;
415
    if( getCorner(id,6)==CORNER_Y ) return false;
416
    if( getCorner(id,7)==CORNER_Y ) return false;
417

  
418
    if( getCenter(id,0)==CENTER_0 ) return false;
419
    if( getCenter(id,2)==CENTER_0 ) return false;
420
    if( getCenter(id,3)==CENTER_0 ) return false;
421

  
422
    return true;
423
    }
424

  
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

  
427
  private static boolean z0Possible(int id)
428
    {
429
    if( getCorner(id,0)==CORNER_Z ) return false;
430
    if( getCorner(id,2)==CORNER_Z ) return false;
431
    if( getCorner(id,4)==CORNER_Z ) return false;
432
    if( getCorner(id,6)==CORNER_Z ) return false;
433

  
434
    if( getCenter(id,0)==CENTER_1 ) return false;
435
    if( getCenter(id,1)==CENTER_0 ) return false;
436

  
437
    return true;
438
    }
439

  
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

  
442
  private static boolean z2Possible(int id)
443
    {
444
    if( getCorner(id,1)==CORNER_Z ) return false;
445
    if( getCorner(id,3)==CORNER_Z ) return false;
446
    if( getCorner(id,5)==CORNER_Z ) return false;
447
    if( getCorner(id,7)==CORNER_Z ) return false;
448

  
449
    if( getCenter(id,0)==CENTER_3 ) return false;
450
    if( getCenter(id,1)==CENTER_2 ) return false;
451

  
452
    return true;
453
    }
454

  
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

  
457
  private static int getCorner(int id, int index)
458
    {
459
    return (id>>(14-2*index))&3;
460
    }
461

  
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

  
464
  private static int getCenter(int id, int index)
465
    {
466
    return (id>>(22-2*index))&3;
467
    }
468

  
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

  
471
  private static int setCorner(int id, int corner, int index)
472
    {
473
    return id + ((corner-getCorner(id,index))<<(14-2*index));
474
    }
475

  
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

  
478
  private static int setCenter(int id, int center, int index)
479
    {
480
    return id + ((center-getCenter(id,index))<<(22-2*index));
481
    }
482

  
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484

  
485
  private static void createXmoves(int id, int[] moves)
486
    {
487
    int id1 = rotateX(id);
488
    moves[0] = id1;
489
    int id2 = rotateX(id1);
490
    moves[1] = id2;
491
    int id3 = rotateX(id2);
492
    moves[2] = id3;
493
    }
494

  
495
///////////////////////////////////////////////////////////////////////////////////////////////////
496

  
497
  private static void createYmoves(int id, int[] moves)
498
    {
499
    int id1 = rotateY(id);
500
    moves[3] = id1;
501
    int id2 = rotateY(id1);
502
    moves[4] = id2;
503
    int id3 = rotateY(id2);
504
    moves[5] = id3;
505
    }
506

  
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508

  
509
  private static void createZ0moves(int id, int[] moves)
510
    {
511
    int id1 = rotateZ0(id);
512
    moves[6] = id1;
513
    int id2 = rotateZ0(id1);
514
    moves[7] = id2;
515
    int id3 = rotateZ0(id2);
516
    moves[8] = id3;
517
    }
518

  
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

  
521
  private static void createZ2moves(int id, int[] moves)
522
    {
523
    int id1 = rotateZ2(id);
524
    moves[ 9] = id1;
525
    int id2 = rotateZ2(id1);
526
    moves[10] = id2;
527
    int id3 = rotateZ2(id2);
528
    moves[11] = id3;
529
    }
530

  
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532

  
533
  private static int rotateX(int id)
534
    {
535
    int newCorner4 = rotCornerX(getCorner(id,5));
536
    int newCorner5 = rotCornerX(getCorner(id,7));
537
    int newCorner6 = rotCornerX(getCorner(id,4));
538
    int newCorner7 = rotCornerX(getCorner(id,6));
539
    int newCenter  = rotCenter (getCenter(id,0));
540

  
541
    int id1 = setCorner(id ,newCorner4,4);
542
    int id2 = setCorner(id1,newCorner5,5);
543
    int id3 = setCorner(id2,newCorner6,6);
544
    int id4 = setCorner(id3,newCorner7,7);
545
    int id5 = setCenter(id4,newCenter ,0);
546

  
547
    return id5;
548
    }
549

  
550
///////////////////////////////////////////////////////////////////////////////////////////////////
551

  
552
  private static int rotateY(int id)
553
    {
554
    int newCorner2 = rotCornerY(getCorner(id,6));
555
    int newCorner3 = rotCornerY(getCorner(id,2));
556
    int newCorner6 = rotCornerY(getCorner(id,7));
557
    int newCorner7 = rotCornerY(getCorner(id,3));
558
    int newCenter  = rotCenter (getCenter(id,1));
559

  
560
    int id1 = setCorner(id ,newCorner2,2);
561
    int id2 = setCorner(id1,newCorner3,3);
562
    int id3 = setCorner(id2,newCorner6,6);
563
    int id4 = setCorner(id3,newCorner7,7);
564
    int id5 = setCenter(id4,newCenter ,1);
565

  
566
    return id5;
567
    }
568

  
569
///////////////////////////////////////////////////////////////////////////////////////////////////
570

  
571
  private static int rotateZ0(int id)
572
    {
573
    int newCorner0 = rotCornerZ(getCorner(id,2));
574
    int newCorner2 = rotCornerZ(getCorner(id,6));
575
    int newCorner4 = rotCornerZ(getCorner(id,0));
576
    int newCorner6 = rotCornerZ(getCorner(id,4));
577
    int newCenter  = rotCenter (getCenter(id,2));
578

  
579
    int id1 = setCorner(id ,newCorner0,0);
580
    int id2 = setCorner(id1,newCorner2,2);
581
    int id3 = setCorner(id2,newCorner4,4);
582
    int id4 = setCorner(id3,newCorner6,6);
583
    int id5 = setCenter(id4,newCenter ,2);
584

  
585
    return id5;
586
    }
587

  
588
///////////////////////////////////////////////////////////////////////////////////////////////////
589

  
590
  private static int rotateZ2(int id)
591
    {
592
    int newCorner1 = rotCornerZ(getCorner(id,3));
593
    int newCorner3 = rotCornerZ(getCorner(id,7));
594
    int newCorner5 = rotCornerZ(getCorner(id,1));
595
    int newCorner7 = rotCornerZ(getCorner(id,5));
596
    int newCenter  = rotCenter (getCenter(id,3));
597

  
598
    int id1 = setCorner(id ,newCorner1,1);
599
    int id2 = setCorner(id1,newCorner3,3);
600
    int id3 = setCorner(id2,newCorner5,5);
601
    int id4 = setCorner(id3,newCorner7,7);
602
    int id5 = setCenter(id4,newCenter ,3);
603

  
604
    return id5;
605
    }
606

  
607
///////////////////////////////////////////////////////////////////////////////////////////////////
608

  
609
  private static int rotCornerX(int corner)
610
    {
611
    switch(corner)
612
      {
613
      case CORNER_S: return CORNER_S;
614
      case CORNER_X: android.util.Log.e("DIST", "rotateX: ERROR");
615
                     return CORNER_S;
616
      case CORNER_Y: return CORNER_Z;
617
      case CORNER_Z: return CORNER_Y;
618
      }
619

  
620
    return CORNER_S;
621
    }
622

  
623
///////////////////////////////////////////////////////////////////////////////////////////////////
624

  
625
  private static int rotCornerY(int corner)
626
    {
627
    switch(corner)
628
      {
629
      case CORNER_S: return CORNER_S;
630
      case CORNER_X: return CORNER_Z;
631
      case CORNER_Y: android.util.Log.e("DIST", "rotateY: ERROR");
632
                     return CORNER_S;
633
      case CORNER_Z: return CORNER_X;
634
      }
635

  
636
    return CORNER_S;
637
    }
638

  
639
///////////////////////////////////////////////////////////////////////////////////////////////////
640

  
641
  private static int rotCornerZ(int corner)
642
    {
643
    switch(corner)
644
      {
645
      case CORNER_S: return CORNER_S;
646
      case CORNER_X: return CORNER_Y;
647
      case CORNER_Y: return CORNER_X;
648
      case CORNER_Z: android.util.Log.e("DIST", "rotateZ: ERROR");
649
                     return CORNER_S;
650
      }
651

  
652
    return CORNER_S;
653
    }
654

  
655
///////////////////////////////////////////////////////////////////////////////////////////////////
656

  
657
  private static int rotCenter(int center)
658
    {
659
    switch(center)
660
      {
661
      case CENTER_0: return CENTER_3;
662
      case CENTER_1: return CENTER_0;
663
      case CENTER_2: return CENTER_1;
664
      case CENTER_3: return CENTER_2;
665
      }
666

  
667
    return CENTER_0;
668
    }
669
}
src/main/java/org/distorted/helpers/ScrambleStateGraph.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
package org.distorted.helpers;
21

  
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23

  
24
public class ScrambleStateGraph
25
{
26
  private final int mTotal, mNumAxis;
27
  private final int[] mNum;
28
  private final int[] mInfo;
29
  private final int[] mTmp;
30
  private final int LEN = 4;
31

  
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33

  
34
  public ScrambleStateGraph(int[][] axis)
35
    {
36
    mTmp = new int[LEN];
37

  
38
    mNumAxis = axis.length;
39
    mNum = new int[mNumAxis];
40
    int total =0;
41

  
42
    for(int i=0; i<mNumAxis; i++)
43
      {
44
      mNum[i] = axis[i]==null ? 0 : axis[i].length/(LEN-1);
45
      total += mNum[i];
46
      }
47

  
48
    mTotal = total;
49

  
50
    mInfo = new int[LEN*total];
51
    int start = 0;
52

  
53
    for(int i=0; i<mNumAxis; i++)
54
      {
55
      for(int j=0; j<mNum[i]; j++)
56
        {
57
        mInfo[LEN*j   + start] = i;
58
        mInfo[LEN*j+1 + start] = axis[i][(LEN-1)*j  ];
59
        mInfo[LEN*j+2 + start] = axis[i][(LEN-1)*j+1];
60
        mInfo[LEN*j+3 + start] = axis[i][(LEN-1)*j+2];
61
        }
62

  
63
      start += LEN*mNum[i];
64
      }
65
    }
66

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

  
69
  private int getIndex(int num, int indexExcluded)
70
    {
71
    int current= -1;
72

  
73
    for(int i=0; i<mTotal; i++)
74
      if( mInfo[LEN*i]!=indexExcluded && ++current==num ) return i;
75

  
76
    return -1;
77
    }
78

  
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80

  
81
  public int getTotal(int indexExcluded)
82
    {
83
    return ( indexExcluded>=0 && indexExcluded<mNumAxis ) ? mTotal-mNum[indexExcluded] : mTotal;
84
    }
85

  
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

  
88
  public int[] getInfo(int num, int indexExcluded)
89
    {
90
    int index = getIndex(num,indexExcluded);
91

  
92
    mTmp[0] = mInfo[LEN*index  ];   // axis
93
    mTmp[1] = mInfo[LEN*index+1];   // row
94
    mTmp[2] = mInfo[LEN*index+2];   // angle
95
    mTmp[3] = mInfo[LEN*index+3];   // next state
96

  
97
    return mTmp;
98
    }
99
}
src/main/java/org/distorted/helpers/ScrambleStateGraphProducer.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2021 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// Magic Cube is free software: you can redistribute it and/or modify                            //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Magic Cube is distributed in the hope that it will be useful,                                 //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Magic Cube.  If not, see <http://www.gnu.org/licenses/>.                           //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
package org.distorted.helpers;
21

  
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23
// producer of the ScrambleStateGraph - but only for a single Twisty Puzzle, the 'BandagedEvil'.
24

  
25
import java.util.ArrayList;
26

  
27
public class ScrambleStateGraphProducer
28
{
29
  private static final int INVALID_MOVE = -1;
30

  
31
  private static final int CORNER_S = 0;
32
  private static final int CORNER_X = 1;
33
  private static final int CORNER_Y = 2;
34
  private static final int CORNER_Z = 3;
35

  
36
  private static final int CENTER_0 = 0;
37
  private static final int CENTER_1 = 1;
38
  private static final int CENTER_2 = 2;
39
  private static final int CENTER_3 = 3;
40

  
41
  private int mID;
42
  private final int[] mMoves;
43

  
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

  
46
  public ScrambleStateGraphProducer(int id)
47
    {
48
    mID = id;
49
    mMoves = createMoves(mID);
50
    }
51

  
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

  
54
  public static void computeGraph()
55
    {
56
    ArrayList<ScrambleStateGraphProducer> graph;
57

  
58
    int id = 0;
59
    int id1 = setCenter(id  , CENTER_2, 0);
60
    int id2 = setCenter(id1 , CENTER_2, 1);
61
    int id3 = setCenter(id2 , CENTER_3, 2);
62
    int id4 = setCenter(id3 , CENTER_2, 3);
63

  
64
    int id5 = setCorner(id4 , CORNER_X, 0);
65
    int id6 = setCorner(id5 , CORNER_Y, 1);
66
    int id7 = setCorner(id6 , CORNER_X, 2);
67
    int id8 = setCorner(id7 , CORNER_Z, 3);
68
    int id9 = setCorner(id8 , CORNER_Y, 4);
69
    int id10= setCorner(id9 , CORNER_Y, 5);
70
    int id11= setCorner(id10, CORNER_S, 6);
71
    int id12= setCorner(id11, CORNER_Z, 7);
72

  
73
    ScrambleStateGraphProducer bsg = new ScrambleStateGraphProducer(id12);
74
    graph = new ArrayList<>();
75
    graph.add(bsg);
76

  
77
    insertChildren(graph,id12);
78
    pruneGraph(graph);
79
    remapGraph(graph);
80

  
81
    int num = graph.size();
82
    android.util.Log.e("D", "\n"+num+" states\n");
83

  
84
    for(int i=0; i<num; i++)
85
      {
86
      bsg = graph.get(i);
87
      android.util.Log.e("D", formatMoves(bsg));
88
      }
89
    }
90

  
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

  
93
  private static void insertChildren(ArrayList<ScrambleStateGraphProducer> list, int id)
94
    {
95
    ScrambleStateGraphProducer bsg = findState(list,id);
96

  
97
    if( bsg==null )
98
      {
99
      android.util.Log.e("D", "error: "+id+" doesn't exist");
100
      return;
101
      }
102

  
103
    for(int i=0; i<12; i++)
104
      {
105
      int move = bsg.getMove(i);
106

  
107
      if( move!=INVALID_MOVE )
108
        {
109
        ScrambleStateGraphProducer tmp = findState(list,move);
110

  
111
        if( tmp==null )
112
          {
113
          tmp = new ScrambleStateGraphProducer(move);
114
          list.add(tmp);
115
          insertChildren(list,move);
116
          }
117
        }
118
      }
119
    }
120

  
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

  
123
  private static void pruneGraph(ArrayList<ScrambleStateGraphProducer> list)
124
    {
125
    int num = list.size(), numAxis;
126
    boolean pruned = false;
127
    ScrambleStateGraphProducer bsg;
128

  
129
    for(int i=0; i<num; i++)
130
      {
131
      bsg = list.get(i);
132
      numAxis = bsg.numAxis();
133

  
134
      if( numAxis<2 )
135
        {
136
        list.remove(i);
137
        int id = bsg.getID();
138
        pruned = true;
139
        remapID(list,id,INVALID_MOVE);
140
        break;
141
        }
142
      }
143

  
144
    if( pruned ) pruneGraph(list);
145
    }
146

  
147
///////////////////////////////////////////////////////////////////////////////////////////////////
148

  
149
  private static void remapGraph(ArrayList<ScrambleStateGraphProducer> list)
150
    {
151
    int id, num = list.size();
152
    ScrambleStateGraphProducer bsg;
153

  
154
    for(int i=0; i<num; i++ )
155
      {
156
      bsg = list.get(i);
157
      id = bsg.getID();
158
      bsg.setID(i);
159
      remapID(list,id,i);
160
      }
161
    }
162

  
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

  
165
  private static void remapID(ArrayList<ScrambleStateGraphProducer> list, int id, int newId)
166
    {
167
    ScrambleStateGraphProducer bsg;
168
    int size = list.size();
169

  
170
    for(int i=0; i<size; i++)
171
      {
172
      bsg = list.get(i);
173

  
174
      for(int j=0; j<12; j++)
175
        {
176
        if( bsg.getMove(j)==id ) bsg.setMove(j,newId);
177
        }
178
      }
179
    }
180

  
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

  
183
  private static ScrambleStateGraphProducer findState(ArrayList<ScrambleStateGraphProducer> list, int id)
184
    {
185
    ScrambleStateGraphProducer bsg;
186
    int num = list.size();
187

  
188
    for(int i=0; i<num; i++)
189
      {
190
      bsg= list.get(i);
191
      if( bsg.getID() == id ) return bsg;
192
      }
193

  
194
    return null;
195
    }
196

  
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

  
199
  private static String formatMoves(ScrambleStateGraphProducer bsg)
200
    {
201
    String x = getTable(bsg,0);
202
    String y = getTable(bsg,3);
203
    String z = getTable(bsg,6);
204

  
205
    return "    new ScrambleStateGraph( new int[][] { "+x+", "+y+", "+z+" } ),";
206
    }
207

  
208
///////////////////////////////////////////////////////////////////////////////////////////////////
209

  
210
  private static String getTable(ScrambleStateGraphProducer sc, int index)
211
    {
212
    String ret = "";
213

  
214
    if( index==0 || index==3 )
215
      {
216
      int m0 = sc.getMove(index  );
217
      int m1 = sc.getMove(index+1);
218
      int m2 = sc.getMove(index+2);
219

  
220
      if( m0==INVALID_MOVE && m1==INVALID_MOVE && m2==INVALID_MOVE ) return formatL("{}");
221

  
222
      if( m0!=INVALID_MOVE ) ret += formatRet(ret,2, 1,m0);
223
      if( m1!=INVALID_MOVE ) ret += formatRet(ret,2, 2,m1);
224
      if( m2!=INVALID_MOVE ) ret += formatRet(ret,2,-1,m2);
225
      }
226
    else
227
      {
228
      int m0 = sc.getMove(index  );
229
      int m1 = sc.getMove(index+1);
230
      int m2 = sc.getMove(index+2);
231
      int m3 = sc.getMove(index+3);
232
      int m4 = sc.getMove(index+4);
233
      int m5 = sc.getMove(index+5);
234

  
235
      if( m0==INVALID_MOVE && m1==INVALID_MOVE && m2==INVALID_MOVE &&
236
          m3==INVALID_MOVE && m4==INVALID_MOVE && m5==INVALID_MOVE  )
237
        {
238
        return formatL("{}");
239
        }
240

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

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

  
252
///////////////////////////////////////////////////////////////////////////////////////////////////
253

  
254
  private static String formatRet(String str, int row, int angle, int id)
255
    {
256
    String ret = str.length()!=0 ? ",":"";
257

  
258
    ret += row;
259
    ret += angle<0 ? "," : ", ";
260
    ret += angle;
261

  
262
         if( id< 10 ) ret += (",  "+id);
263
    else if( id<100 ) ret += (", " +id);
264
    else              ret += (","  +id);
265

  
266
    return ret;
267
    }
268

  
269
///////////////////////////////////////////////////////////////////////////////////////////////////
270

  
271
  private static final int LENGTH = 28;
272

  
273
  private static String formatL(String input)
274
    {
275
    int len = input.length();
276
    String ret = input;
277
    for(int i=0 ;i<LENGTH-len; i++) ret += " ";
278
    return ret;
279
    }
280

  
281
///////////////////////////////////////////////////////////////////////////////////////////////////
282

  
283
  private int getID()
284
    {
285
    return mID;
286
    }
287

  
288
///////////////////////////////////////////////////////////////////////////////////////////////////
289

  
290
  private void setID(int id)
291
    {
292
    mID = id;
293
    }
294

  
295
///////////////////////////////////////////////////////////////////////////////////////////////////
296

  
297
  private int getMove(int index)
298
    {
299
    return (index>=0 && index<12) ? mMoves[index] : -1;
300
    }
301

  
302
///////////////////////////////////////////////////////////////////////////////////////////////////
303

  
304
  private int numAxis()
305
    {
306
    int num = 0;
307

  
308
    if( mMoves[ 0]!=INVALID_MOVE || mMoves[ 1]!=INVALID_MOVE || mMoves[ 2]!=INVALID_MOVE ) num++;
309
    if( mMoves[ 3]!=INVALID_MOVE || mMoves[ 4]!=INVALID_MOVE || mMoves[ 5]!=INVALID_MOVE ) num++;
310
    if( mMoves[ 6]!=INVALID_MOVE || mMoves[ 7]!=INVALID_MOVE || mMoves[ 8]!=INVALID_MOVE ) num++;
311
    if( mMoves[ 9]!=INVALID_MOVE || mMoves[10]!=INVALID_MOVE || mMoves[11]!=INVALID_MOVE ) num++;
312

  
313
    return num;
314
    }
315

  
316
///////////////////////////////////////////////////////////////////////////////////////////////////
317

  
318
  private void setMove(int index, int newMove)
319
    {
320
    if( index>=0 && index<12 ) mMoves[index] = newMove;
321
    }
322

  
323
///////////////////////////////////////////////////////////////////////////////////////////////////
324

  
325
  private static String debug(int id)
326
    {
327
    int ce0 = getCenter(id,0);
328
    int ce1 = getCenter(id,1);
329
    int ce2 = getCenter(id,2);
330
    int ce3 = getCenter(id,3);
331

  
332
    int co0 = getCorner(id,0);
333
    int co1 = getCorner(id,1);
334
    int co2 = getCorner(id,2);
335
    int co3 = getCorner(id,3);
336
    int co4 = getCorner(id,4);
337
    int co5 = getCorner(id,5);
338
    int co6 = getCorner(id,6);
339
    int co7 = getCorner(id,7);
340

  
341
    String center = centerString(ce0) + centerString(ce1) + centerString(ce2) + centerString(ce3);
342
    String corner = cornerString(co0) + cornerString(co1) + cornerString(co2) + cornerString(co3) +
343
                    cornerString(co4) + cornerString(co5) + cornerString(co6) + cornerString(co7);
344

  
345
    return center + " -" + corner;
346
    }
347

  
348
///////////////////////////////////////////////////////////////////////////////////////////////////
349

  
350
  private static String centerString(int center)
351
    {
352
    return " "+center;
353
    }
354

  
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356

  
357
  private static String cornerString(int corner)
358
    {
359
    switch(corner)
360
      {
361
      case CORNER_S: return " S";
362
      case CORNER_X: return " X";
363
      case CORNER_Y: return " Y";
364
      case CORNER_Z: return " Z";
365
      }
366

  
367
    return "?";
368
    }
369

  
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371

  
372
  private static int[] createMoves(int id)
373
    {
374
    int[] ret = new int[12];
375

  
376
    boolean moveX  = xPossible(id);
377
    boolean moveY  = yPossible(id);
378
    boolean moveZ0 = z0Possible(id);
379
    boolean moveZ2 = z2Possible(id);
380

  
381
    if( moveX ) createXmoves(id,ret);
382
    else        { ret[ 0] = INVALID_MOVE; ret[ 1] = INVALID_MOVE; ret[ 2] = INVALID_MOVE; }
383
    if( moveY ) createYmoves(id,ret);
384
    else        { ret[ 3] = INVALID_MOVE; ret[ 4] = INVALID_MOVE; ret[ 5] = INVALID_MOVE; }
385
    if( moveZ0) createZ0moves(id,ret);
386
    else        { ret[ 6] = INVALID_MOVE; ret[ 7] = INVALID_MOVE; ret[ 8] = INVALID_MOVE; }
387
    if( moveZ2) createZ2moves(id,ret);
388
    else        { ret[ 9] = INVALID_MOVE; ret[10] = INVALID_MOVE; ret[11] = INVALID_MOVE; }
389

  
390
    return ret;
391
    }
392

  
393
///////////////////////////////////////////////////////////////////////////////////////////////////
394

  
395
  private static boolean xPossible(int id)
396
    {
397
    if( getCorner(id,4)==CORNER_X ) return false;
398
    if( getCorner(id,5)==CORNER_X ) return false;
399
    if( getCorner(id,6)==CORNER_X ) return false;
400
    if( getCorner(id,7)==CORNER_X ) return false;
401

  
402
    if( getCenter(id,1)==CENTER_1 ) return false;
403
    if( getCenter(id,2)==CENTER_1 ) return false;
404
    if( getCenter(id,3)==CENTER_1 ) return false;
405

  
406
    return true;
407
    }
408

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

  
411
  private static boolean yPossible(int id)
412
    {
413
    if( getCorner(id,2)==CORNER_Y ) return false;
414
    if( getCorner(id,3)==CORNER_Y ) return false;
415
    if( getCorner(id,6)==CORNER_Y ) return false;
416
    if( getCorner(id,7)==CORNER_Y ) return false;
417

  
418
    if( getCenter(id,0)==CENTER_0 ) return false;
419
    if( getCenter(id,2)==CENTER_0 ) return false;
420
    if( getCenter(id,3)==CENTER_0 ) return false;
421

  
422
    return true;
423
    }
424

  
425
///////////////////////////////////////////////////////////////////////////////////////////////////
426

  
427
  private static boolean z0Possible(int id)
428
    {
429
    if( getCorner(id,0)==CORNER_Z ) return false;
430
    if( getCorner(id,2)==CORNER_Z ) return false;
431
    if( getCorner(id,4)==CORNER_Z ) return false;
432
    if( getCorner(id,6)==CORNER_Z ) return false;
433

  
434
    if( getCenter(id,0)==CENTER_1 ) return false;
435
    if( getCenter(id,1)==CENTER_0 ) return false;
436

  
437
    return true;
438
    }
439

  
440
///////////////////////////////////////////////////////////////////////////////////////////////////
441

  
442
  private static boolean z2Possible(int id)
443
    {
444
    if( getCorner(id,1)==CORNER_Z ) return false;
445
    if( getCorner(id,3)==CORNER_Z ) return false;
446
    if( getCorner(id,5)==CORNER_Z ) return false;
447
    if( getCorner(id,7)==CORNER_Z ) return false;
448

  
449
    if( getCenter(id,0)==CENTER_3 ) return false;
450
    if( getCenter(id,1)==CENTER_2 ) return false;
451

  
452
    return true;
453
    }
454

  
455
///////////////////////////////////////////////////////////////////////////////////////////////////
456

  
457
  private static int getCorner(int id, int index)
458
    {
459
    return (id>>(14-2*index))&3;
460
    }
461

  
462
///////////////////////////////////////////////////////////////////////////////////////////////////
463

  
464
  private static int getCenter(int id, int index)
465
    {
466
    return (id>>(22-2*index))&3;
467
    }
468

  
469
///////////////////////////////////////////////////////////////////////////////////////////////////
470

  
471
  private static int setCorner(int id, int corner, int index)
472
    {
473
    return id + ((corner-getCorner(id,index))<<(14-2*index));
474
    }
475

  
476
///////////////////////////////////////////////////////////////////////////////////////////////////
477

  
478
  private static int setCenter(int id, int center, int index)
479
    {
480
    return id + ((center-getCenter(id,index))<<(22-2*index));
481
    }
482

  
483
///////////////////////////////////////////////////////////////////////////////////////////////////
484

  
485
  private static void createXmoves(int id, int[] moves)
486
    {
487
    int id1 = rotateX(id);
488
    moves[0] = id1;
489
    int id2 = rotateX(id1);
490
    moves[1] = id2;
491
    int id3 = rotateX(id2);
492
    moves[2] = id3;
493
    }
494

  
495
///////////////////////////////////////////////////////////////////////////////////////////////////
496

  
497
  private static void createYmoves(int id, int[] moves)
498
    {
499
    int id1 = rotateY(id);
500
    moves[3] = id1;
501
    int id2 = rotateY(id1);
502
    moves[4] = id2;
503
    int id3 = rotateY(id2);
504
    moves[5] = id3;
505
    }
506

  
507
///////////////////////////////////////////////////////////////////////////////////////////////////
508

  
509
  private static void createZ0moves(int id, int[] moves)
510
    {
511
    int id1 = rotateZ0(id);
512
    moves[6] = id1;
513
    int id2 = rotateZ0(id1);
514
    moves[7] = id2;
515
    int id3 = rotateZ0(id2);
516
    moves[8] = id3;
517
    }
518

  
519
///////////////////////////////////////////////////////////////////////////////////////////////////
520

  
521
  private static void createZ2moves(int id, int[] moves)
522
    {
523
    int id1 = rotateZ2(id);
524
    moves[ 9] = id1;
525
    int id2 = rotateZ2(id1);
526
    moves[10] = id2;
527
    int id3 = rotateZ2(id2);
528
    moves[11] = id3;
529
    }
530

  
531
///////////////////////////////////////////////////////////////////////////////////////////////////
532

  
533
  private static int rotateX(int id)
534
    {
535
    int newCorner4 = rotCornerX(getCorner(id,5));
536
    int newCorner5 = rotCornerX(getCorner(id,7));
537
    int newCorner6 = rotCornerX(getCorner(id,4));
538
    int newCorner7 = rotCornerX(getCorner(id,6));
539
    int newCenter  = rotCenter (getCenter(id,0));
540

  
541
    int id1 = setCorner(id ,newCorner4,4);
542
    int id2 = setCorner(id1,newCorner5,5);
543
    int id3 = setCorner(id2,newCorner6,6);
544
    int id4 = setCorner(id3,newCorner7,7);
545
    int id5 = setCenter(id4,newCenter ,0);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff