Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TBSkewb.java @ dbcd5ff2

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2023 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Magic Cube.                                                              //
5
//                                                                                               //
6
// 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
///////////////////////////////////////////////////////////////////////////////////////////////////
9

    
10
package org.distorted.objectlib.tablebases;
11

    
12
import static org.distorted.objectlib.main.TwistyObject.SQ3;
13

    
14
import android.content.res.Resources;
15

    
16
import org.distorted.library.type.Static3D;
17
import org.distorted.objectlib.R;
18

    
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

    
21
public class TBSkewb extends TablebasesPruning
22
{
23
  public static final int[] FIXED= {0,3,5,6};
24
  public static final int[] FREE = {1,2,4,7};
25

    
26
  private static final int[][] freeIndex = { {1,3,2},{0,2,3},{3,1,0},{2,0,1} };
27

    
28
  private static final int[][][] centerQuats =
29
    {
30
        { {0,10},{9,11},{1,7},{4,6},{2,5},{3,8} },
31
        { {9,11},{0,10},{4,6},{1,7},{3,8},{2,5} },
32
        { {2,8},{3,5},{0,11},{9,10},{1,4},{6,7} },
33
        { {3,5},{2,8},{9,10},{0,11},{6,7},{1,4} },
34
        { {1,6},{4,7},{2,3},{5,8},{0,9},{10,11} },
35
        { {4,7},{1,6},{5,8},{2,3},{10,11},{0,9} }
36
    };
37

    
38
  // [1][] are the 3 quats the 1st 'fixed' corner will have when 'fakeTwisted' (which in case of
39
  // the fixed corners is the same as the final twist) with respectively twist 0,1,2.
40

    
41
  private static final int[][] fixedQuats = { {0,1,2},{0,7,8},{0,6,5},{0,4,3} };
42

    
43
  // [1][2][] are the 3 quats the 1st free corner, when permuted to the location of the 2nd corner,
44
  // will have when it is 'fakeTwisted' with fakeTwist 0,1,2.
45
  // fakeTwist is an intermediate twist which needs yet to be translated to the final twist of the
46
  // corners (which needs to sum up to something divisible by 3).
47

    
48
  private static final int[][][] freeQuats=
49
    {
50
        { {0,3,4},{9,8,1},{6,11,2},{7,10,5} },
51
        { {9,2,7},{0,5,6},{1,10,3},{4,11,8} },
52
        { {5,1,11},{2,4,10},{0,8,7},{9,3,6} },
53
        { {8,6,10},{3,7,11},{9,5,4},{0,2,1} }
54
    };
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57

    
58
  public TBSkewb()
59
    {
60
    super();
61
    }
62

    
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64

    
65
  public TBSkewb(Resources res)
66
    {
67
    super(res,new int[] {R.raw.skew_2_pruning4,R.raw.skew_2_pruning5},new int[]{R.raw.skew_2_pruning11});
68
    //super(res, R.raw.skew_2_tablebase);
69
    }
70

    
71
///////////////////////////////////////////////////////////////////////////////////////////////////
72

    
73
  int[][] getBasicAngles()
74
    {
75
    int[] tmp = {3,3};
76
    return new int[][] { tmp,tmp,tmp,tmp };
77
    }
78

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

    
81
  Static3D[] getRotationAxis()
82
    {
83
    return new Static3D[]
84
         {
85
           new Static3D( SQ3/3, SQ3/3, SQ3/3),
86
           new Static3D( SQ3/3, SQ3/3,-SQ3/3),
87
           new Static3D( SQ3/3,-SQ3/3, SQ3/3),
88
           new Static3D( SQ3/3,-SQ3/3,-SQ3/3)
89
         };
90
    }
91

    
92
///////////////////////////////////////////////////////////////////////////////////////////////////
93

    
94
  float[][] getPosition()
95
    {
96
    return new float[][]
97
         {
98
             { 1, 1, 1 },
99
             { 1, 1,-1 },
100
             { 1,-1, 1 },
101
             { 1,-1,-1 },
102
             {-1, 1, 1 },
103
             {-1, 1,-1 },
104
             {-1,-1, 1 },
105
             {-1,-1,-1 },
106

    
107
             { 0, 0, 1 },
108
             { 0, 0,-1 },
109
             { 0, 1, 0 },
110
             { 0,-1, 0 },
111
             { 1, 0, 0 },
112
             {-1, 0, 0 }
113
         };
114
    }
115

    
116
///////////////////////////////////////////////////////////////////////////////////////////////////
117

    
118
  float[][] getCuts()
119
    {
120
    float[] cut = {0};
121
    return new float[][] { cut,cut,cut,cut };
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  boolean[][] getRotatable()
127
    {
128
    boolean[] t1 = new boolean[] {false,true};
129
    boolean[] t2 = new boolean[] {true,false};
130
    return new boolean[][] { t1,t2,t2,t1 };
131
    }
132

    
133
///////////////////////////////////////////////////////////////////////////////////////////////////
134
// specifically for the tablebase
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  int getSize()
138
    {
139
    return 3149280;  // see https://www.jaapsch.net/puzzles/skewb.htm
140
    }
141

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

    
144
  int getMinScramble()
145
    {
146
    return 9;
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150

    
151
  int[] getMidPruningLevels()
152
    {
153
    return new int[] {4,5};
154
    }
155

    
156
///////////////////////////////////////////////////////////////////////////////////////////////////
157

    
158
  int[] getHighPruningLevels()
159
    {
160
    return new int[] {11};
161
    }
162

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

    
165
  int getGodsNumber()
166
    {
167
    return 11;
168
    }
169

    
170
///////////////////////////////////////////////////////////////////////////////////////////////////
171

    
172
  boolean moveCanProceed(int lastA, int lastR, int currA, int currR)
173
    {
174
    return lastA!=currA;
175
    }
176

    
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

    
179
  public static int computeLocation(int index, int quat)
180
    {
181
    for(int i=0; i<4; i++)
182
      {
183
      int[] q = freeQuats[index][i];
184
      if( quat==q[0] || quat==q[1] || quat==q[2] ) return i;
185
      }
186

    
187
    android.util.Log.e("D", "error in computeLocation, quat="+quat);
188
    return -1;
189
    }
190

    
191
///////////////////////////////////////////////////////////////////////////////////////////////////
192

    
193
  private static int retFixed(int index, int quat)
194
    {
195
    int[] qs = fixedQuats[index];
196

    
197
    if( quat==qs[0]) return 0;
198
    if( quat==qs[1]) return 1;
199
    if( quat==qs[2]) return 2;
200

    
201
    android.util.Log.e("D", "error in retFixed, index="+index+" quat="+quat);
202
    return -1;
203
    }
204

    
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

    
207
  private static int retFree(int index, int quat)
208
    {
209
    int[][] qs = freeQuats[index];
210

    
211
    for(int i=0; i<4; i++)
212
      {
213
      if( quat==qs[i][0]) return 0;
214
      if( quat==qs[i][1]) return 1;
215
      if( quat==qs[i][2]) return 2;
216
      }
217

    
218
    android.util.Log.e("D", "error in retFree, index="+index+" quat="+quat);
219
    return -1;
220
    }
221

    
222
///////////////////////////////////////////////////////////////////////////////////////////////////
223
// In case of the four 'fixed' corners (0,3,5,6) which do not change their location,
224
// the twist is natural: 0 in the init positions and increasing 1 mod 3 on each CW turn.
225
//
226
// In case of the four 'free' corners their twist is relative to the position of the 'free'
227
// tetrahedron. And so, for example the twist of free corner 1 (whose 0th face is orange) is equal
228
// to 0 if free corner 7 is on the same face like 0th face of corner 1 (which is the case in init
229
// position); then once free corners 2,4,7 permute CW, twist of corner 1 increases by 1 mod 3.
230

    
231
  public static void computeCornerTwists(int[] twists, int[] quats)
232
    {
233
    for(int i=0; i<4; i++) twists[FIXED[i]] = retFixed(i,quats[FIXED[i]]);
234
    for(int i=0; i<4; i++) twists[FREE[i]]  = retFree(i,quats[FREE[i]]);
235
    }
236

    
237
///////////////////////////////////////////////////////////////////////////////////////////////////
238

    
239
  public static void fillInQuats(int[] quats, int[] perm, int[] twist)
240
    {
241
    for(int i=0; i<4; i++)
242
      {
243
      int fixed = FIXED[i];
244
      int free  = FREE[i];
245
      int twFi  = twist[fixed];
246
      int twFr  = twist[free];
247
      int pe    = perm[i];
248

    
249
      quats[fixed] = fixedQuats[i][twFi];
250
      quats[free ] = freeQuats[i][pe][twFr];
251
      }
252
    }
253

    
254
///////////////////////////////////////////////////////////////////////////////////////////////////
255

    
256
  private int[] computeCenterPerm(int[] quats)
257
    {
258
    int[] output = new int[6];
259

    
260
    for(int i=0; i<6; i++)
261
      {
262
      output[i] = -1;
263
      int[][] c = centerQuats[i];
264
      int q = quats[8+i];
265

    
266
      for(int j=0; j<6; j++)
267
        if( c[j][0]==q || c[j][1]==q )
268
          {
269
          output[i] = j;
270
          break;
271
          }
272
      }
273

    
274
    return output;
275
    }
276

    
277
///////////////////////////////////////////////////////////////////////////////////////////////////
278

    
279
  private void fillCenterQuats(int[] quats, int[] perm)
280
    {
281
    for(int i=0; i<6; i++) quats[8+i] = centerQuats[i][perm[i]][0];
282
    }
283

    
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

    
286
  private void fillUpToEvenPerm(int[] perm)
287
    {
288
    int min, max;
289

    
290
         if( perm[0]!=0 && perm[1]!=0 ) min=0;
291
    else if( perm[0]!=1 && perm[1]!=1 ) min=1;
292
    else                                min=2;
293

    
294
         if( perm[0]!=3 && perm[1]!=3 ) max=3;
295
    else if( perm[0]!=2 && perm[1]!=2 ) max=2;
296
    else                                max=1;
297

    
298
    int diff = perm[1]-perm[0];
299

    
300
    if( diff==-2 || diff==1 || diff==3 ) { perm[2]=min; perm[3]=max; }
301
    else                                 { perm[2]=max; perm[3]=min; }
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  public int[] getQuats(int index)
307
    {
308
    int[] permFree = new int[4];
309
    int center_perm_num = (index%360);
310
    index /= 360;
311
    int totalTwist = (index%2187);
312
    permFree[0] = (index/2187);
313

    
314
    int[] quats = new int[14];
315
    int[] center_perm = new int[6];
316
    int[] twist = new int[8];
317

    
318
    TablebaseHelpers.getEvenPermutationFromNum(center_perm, center_perm_num);
319
    fillCenterQuats(quats,center_perm);
320

    
321
    for(int i=0; i<7; i++)
322
      {
323
      twist[i] = (totalTwist%3);
324
      totalTwist /= 3;
325
      }
326

    
327
    int total = twist[FREE[0]]+twist[FREE[1]]+twist[FREE[2]];
328
    twist[7] = ((6-total)%3);
329
    int sumFixedTwists = twist[FIXED[0]]+twist[FIXED[1]]+twist[FIXED[2]]+twist[FIXED[3]];
330
    permFree[1] = freeIndex[permFree[0]][sumFixedTwists%3];
331
    fillUpToEvenPerm(permFree);
332
    fillInQuats(quats,permFree,twist);
333

    
334
    return quats;
335
    }
336

    
337
///////////////////////////////////////////////////////////////////////////////////////////////////
338

    
339
  public int getIndex(int[] quats)
340
    {
341
    int[] center_perm = computeCenterPerm(quats);
342
    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(center_perm);
343
    int[] twist = new int[8];
344
    computeCornerTwists(twist,quats);
345
    int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
346
    int locationOfFree0 = computeLocation(0,quats[1]);
347

    
348
    return center_perm_num+ 360*(totalTwist + 2187*locationOfFree0);
349
    }
350
}  
351

    
(9-9/14)