Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TBCuboid323.java @ 62b9f665

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 org.distorted.library.type.Static3D;
13
import org.distorted.objectlib.R;
14
import org.distorted.objectlib.helpers.OperatingSystemInterface;
15

    
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17

    
18
public class TBCuboid323 extends TablebasesPruning
19
{
20
  private static final int[][] CORNER_MAP = new int[][]
21
      {
22
          {0,4,7,1,2,3,5,6},
23
          {2,0,1,6,3,4,7,5},
24
          {7,1,0,4,5,6,2,3},
25
          {1,6,2,0,7,5,3,4},
26
          {4,3,5,7,0,2,6,1},
27
          {3,2,6,5,4,0,1,7},
28
          {5,7,4,3,6,1,0,2},
29
          {6,5,3,2,1,7,4,0}
30
      };
31
  private static final int[][] EDGE_MAP = new int[][]
32
      {
33
          {0,3,5,1,4,7,2,6},
34
          {3,0,1,5,2,6,4,7},
35
          {5,1,0,3,7,4,6,2},
36
          {1,5,3,0,6,2,7,4},
37
          {2,4,7,6,0,1,3,5},
38
          {7,6,2,4,1,0,5,3},
39
          {4,2,6,7,3,5,0,1},
40
          {6,7,4,2,5,3,1,0}
41
      };
42

    
43
  private static final int[][] CORNER_MAP_INVERTED = new int[8][8];
44
  private static final int[][] EDGE_MAP_INVERTED = new int[8][8];
45

    
46
  static
47
    {
48
    for(int i=0; i<8; i++)
49
      for(int j=0; j<8; j++)
50
        {
51
        CORNER_MAP_INVERTED[i][j] = findIndex(CORNER_MAP[i],j);
52
        EDGE_MAP_INVERTED[i][j]   = findIndex(EDGE_MAP[i],j);
53
        }
54
    };
55

    
56
  private int[][] mAngles;
57
  private boolean mUpsideDown;
58
  private int[] mCornerPerm, mEdgePerm;
59

    
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61
// remove perm[1] which is always equal to 1.
62

    
63
  public static int[] edgePermTo7(int[] perm)
64
    {
65
    int[] ret = new int[7];
66

    
67
    ret[0] = perm[0]; if( ret[0]>1 ) ret[0]--;
68
    ret[1] = perm[2]; if( ret[1]>1 ) ret[1]--;
69
    ret[2] = perm[3]; if( ret[2]>1 ) ret[2]--;
70
    ret[3] = perm[4]; if( ret[3]>1 ) ret[3]--;
71
    ret[4] = perm[5]; if( ret[4]>1 ) ret[4]--;
72
    ret[5] = perm[6]; if( ret[5]>1 ) ret[5]--;
73
    ret[6] = perm[7]; if( ret[6]>1 ) ret[6]--;
74

    
75
    return ret;
76
    }
77

    
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79
// reverse the above
80

    
81
  private static int[] edgePermTo8(int[] perm)
82
    {
83
    int[] ret = new int[8];
84

    
85
    ret[0] = perm[0]; if( ret[0]>=1 ) ret[0]++;
86
    ret[1] = 1;
87
    ret[2] = perm[1]; if( ret[2]>=1 ) ret[2]++;
88
    ret[3] = perm[2]; if( ret[3]>=1 ) ret[3]++;
89
    ret[4] = perm[3]; if( ret[4]>=1 ) ret[4]++;
90
    ret[5] = perm[4]; if( ret[5]>=1 ) ret[5]++;
91
    ret[6] = perm[5]; if( ret[6]>=1 ) ret[6]++;
92
    ret[7] = perm[6]; if( ret[7]>=1 ) ret[7]++;
93

    
94
    return ret;
95
    }
96

    
97
///////////////////////////////////////////////////////////////////////////////////////////////////
98

    
99
  public TBCuboid323()
100
    {
101
    super();
102

    
103
    allocate();
104
    }
105

    
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107

    
108
  public TBCuboid323(OperatingSystemInterface os)
109
    {
110
    super(os,new int[] {R.raw.cu_323_pruning7 ,R.raw.cu_323_pruning8 },
111
             new int[] {R.raw.cu_323_pruning17,R.raw.cu_323_pruning18} );
112

    
113
    allocate();
114
    }
115

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

    
118
  private void allocate()
119
    {
120
    mCornerPerm = new int[8];
121
    mEdgePerm = new int[7];
122
    }
123

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

    
126
  public void initialize()
127
    {
128
    mUpsideDown = false;
129
    }
130

    
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132

    
133
  int[][] getBasicAngles()
134
    {
135
    if( mAngles==null )
136
      {
137
      int[] tmp2 = {2,2,2};
138
      int[] tmp4 = {4,4};
139
      mAngles = new int[][] { tmp2,tmp4,tmp2 };
140
      }
141

    
142
    return mAngles;
143
    }
144

    
145
///////////////////////////////////////////////////////////////////////////////////////////////////
146

    
147
  Static3D[] getRotationAxis()
148
    {
149
    return new Static3D[]
150
         {
151
           new Static3D(1,0,0),
152
           new Static3D(0,1,0),
153
           new Static3D(0,0,1)
154
         };
155
    }
156

    
157
///////////////////////////////////////////////////////////////////////////////////////////////////
158

    
159
  float[][] getPosition()
160
    {
161
    return new float[][]
162
      {
163
        { -1.0f, -0.5f, -1.0f },
164
        { -1.0f, -0.5f,  1.0f },
165
        { -1.0f,  0.5f, -1.0f },
166
        { -1.0f,  0.5f,  1.0f },
167
        {  1.0f, -0.5f, -1.0f },
168
        {  1.0f, -0.5f,  1.0f },
169
        {  1.0f,  0.5f, -1.0f },
170
        {  1.0f,  0.5f,  1.0f },
171

    
172
        {  0.0f, -0.5f, -1.0f },
173
        {  0.0f, -0.5f,  1.0f },
174
        {  0.0f,  0.5f, -1.0f },
175
        {  0.0f,  0.5f,  1.0f },
176
        { -1.0f, -0.5f,  0.0f },
177
        { -1.0f,  0.5f,  0.0f },
178
        {  1.0f, -0.5f,  0.0f },
179
        {  1.0f,  0.5f,  0.0f },
180

    
181
        {  0.0f,  0.5f,  0.0f },
182
        {  0.0f, -0.5f,  0.0f },
183
      };
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
  float[][] getCuts()
189
    {
190
    return new float[][] { {-0.5f,0.5f}, {0.0f}, {-0.5f,0.5f} };
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  boolean[][] getRotatable()
196
    {
197
    return new boolean[][] { {true,false,true},{false,true},{true,true,false} };
198
    }
199

    
200
///////////////////////////////////////////////////////////////////////////////////////////////////
201
// purely for speedup
202

    
203
  @Override
204
  void computeRow(float[] pos, int quat, int[] output)
205
    {
206
    float[] q = mQuats[quat];
207
    float qx = q[0];
208
    float qy = q[1];
209
    float qz = q[2];
210
    float qw = q[3];
211
    float rx = pos[0];
212
    float ry = pos[1];
213
    float rz = pos[2];
214

    
215
    mTmp[0] = qx - rz*qy + ry*qz + rx*qw;
216
    mTmp[1] = qy + rz*qx + ry*qw - rx*qz;
217
    mTmp[2] = qz + rz*qw - ry*qx + rx*qy;
218
    mTmp[3] = qw - rz*qz - ry*qy - rx*qx;
219

    
220
    float x = qw*mTmp[0] + qz*mTmp[1] - qy*mTmp[2] - qx*mTmp[3];
221
    float y = qw*mTmp[1] - qz*mTmp[0] - qy*mTmp[3] + qx*mTmp[2];
222
    float z = qw*mTmp[2] - qz*mTmp[3] + qy*mTmp[0] - qx*mTmp[1];
223

    
224
    output[0] = (x<-0.5f ? 1 : (x<0.5f ? 2:4));
225
    output[1] = (y<0 ? 1:2);
226
    output[2] = (z<-0.5f ? 1 : (z<0.5f ? 2:4));
227
    }
228

    
229
///////////////////////////////////////////////////////////////////////////////////////////////////
230
// we map the move (axis=2, middle layer) to move (axis=2,both middle and back layers).
231
// this way we can imitate move of the front layer (which we do not want to move because
232
// the edge1 piece has to always stay in its place)
233

    
234
  @Override
235
  int computeBitLayer(int ax, int layer)
236
    {
237
    if( ax!=2 ) return (1<<layer);
238

    
239
    switch(layer)
240
      {
241
      case 0 : return 1;
242
      case 1 : return 3;
243
      default: return 4;
244
      }
245
    }
246

    
247
///////////////////////////////////////////////////////////////////////////////////////////////////
248
// this is too slow to be used for scrambling - scramble the 3x3x2 the old way.
249

    
250
  @Override
251
  public boolean useForScrambling()
252
    {
253
    return false;
254
    }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
// specifically for the tablebase
258
///////////////////////////////////////////////////////////////////////////////////////////////////
259
// now turn the (ax=2, middle and back layer) artificial moves [ introduced by computeBitLayer)
260
// back to the natural (ax=2, front layer). Turn the whole thing upside down each time we do it.
261

    
262
  @Override
263
  int[] newMove(int axis, int layer, int angle)
264
    {
265
    if( axis==2 )
266
      {
267
      if( layer==1 )
268
        {
269
        mUpsideDown = !mUpsideDown;
270
        return new int[] { axis, 4, angle };
271
        }
272
      }
273
    else if( mUpsideDown )
274
      {
275
      if( axis==0 ) layer=2-layer;
276
      if( axis==1 ) { layer=1-layer; angle = 4-angle; }
277
      }
278

    
279
    int maxAngle = mAngles[axis][layer];
280
    angle = maxAngle-angle;
281
    if( angle> 0.5f*maxAngle ) angle -= maxAngle;
282
    return new int[] { axis, (1<<layer), angle };
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286
// 8!*8!/4 --> https://www.jaapsch.net/puzzles/domino.htm
287

    
288
  int getSize()
289
    {
290
    return 406425600;
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  int getMinScramble()
296
    {
297
    return 13;
298
    }
299

    
300
///////////////////////////////////////////////////////////////////////////////////////////////////
301

    
302
  int[] getMidPruningLevels()
303
    {
304
    return new int[] {7,8};
305
    }
306

    
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

    
309
  int[] getHighPruningLevels()
310
    {
311
    return new int[] {17,18};
312
    }
313

    
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315

    
316
  int getGodsNumber()
317
    {
318
    return 18;
319
    }
320

    
321
///////////////////////////////////////////////////////////////////////////////////////////////////
322

    
323
  boolean moveCanProceed(int lastA, int lastR, int currA, int currR)
324
    {
325
    return (lastA!=currA) || (lastR!=currR);
326
    }
327

    
328
///////////////////////////////////////////////////////////////////////////////////////////////////
329

    
330
  private static int findIndex(int[] table, int value)
331
    {
332
    for(int i=0; i<8; i++)
333
      if( table[i]==value ) return i;
334

    
335
    return -1;
336
    }
337

    
338
///////////////////////////////////////////////////////////////////////////////////////////////////
339

    
340
  private int centersInverted(int[] quats)
341
    {
342
    int q = quats[16];
343
    return (q==0 || q==2 || q==3 || q==4) ? 0 : 1;
344
    }
345

    
346
///////////////////////////////////////////////////////////////////////////////////////////////////
347

    
348
  public static int[] quatsFromPermutations(int[] corner, int[] edge8, int centers)
349
    {
350
    int[] quats = new int[18];
351

    
352
    for(int i=0; i<8; i++)
353
      {
354
      int q = CORNER_MAP[i][corner[i]];
355
      quats[i] = q;
356
      }
357
    for(int i=0; i<8; i++)
358
      {
359
      int q = EDGE_MAP[i][edge8[i]];
360
      quats[i+8] = q;
361
      }
362

    
363
    if( centers==0 )
364
      {
365
      quats[16]=0;
366
      quats[17]=0;
367
      }
368
    else
369
      {
370
      quats[16]=5;
371
      quats[17]=5;
372
      }
373

    
374
    return quats;
375
    }
376

    
377
///////////////////////////////////////////////////////////////////////////////////////////////////
378

    
379
  private static void cornerFromQuats(int[] corner_perm, int[] quats)
380
    {
381
    for(int i=0; i<8; i++) corner_perm[i] = CORNER_MAP_INVERTED[i][quats[i]];
382
    }
383

    
384
///////////////////////////////////////////////////////////////////////////////////////////////////
385

    
386
  private static void edgeFromQuats(int[] edge_perm, int[] quats)
387
    {
388
    edge_perm[0] = EDGE_MAP_INVERTED[0][quats[ 8]]; if(edge_perm[0]>1) edge_perm[0]--;
389
    edge_perm[1] = EDGE_MAP_INVERTED[2][quats[10]]; if(edge_perm[1]>1) edge_perm[1]--;
390
    edge_perm[2] = EDGE_MAP_INVERTED[3][quats[11]]; if(edge_perm[2]>1) edge_perm[2]--;
391
    edge_perm[3] = EDGE_MAP_INVERTED[4][quats[12]]; if(edge_perm[3]>1) edge_perm[3]--;
392
    edge_perm[4] = EDGE_MAP_INVERTED[5][quats[13]]; if(edge_perm[4]>1) edge_perm[4]--;
393
    edge_perm[5] = EDGE_MAP_INVERTED[6][quats[14]]; if(edge_perm[5]>1) edge_perm[5]--;
394
    edge_perm[6] = EDGE_MAP_INVERTED[7][quats[15]]; if(edge_perm[6]>1) edge_perm[6]--;
395
    }
396

    
397
///////////////////////////////////////////////////////////////////////////////////////////////////
398

    
399
  public int[] getQuats(int index)
400
    {
401
    int cornerPermNum = (index%40320);
402
    index /= 40320;
403
    int centers = (index%2);
404
    int edgePermNum = index/2;
405

    
406
    int[] corner_perm = new int[8];
407
    TablebaseHelpers.getPermutationFromNum(corner_perm,8,cornerPermNum);
408
    int[] edge_perm7 = new int[7];
409
    TablebaseHelpers.getPermutationFromNum(edge_perm7,7,edgePermNum);
410
    int[] edge_perm8 = edgePermTo8(edge_perm7);
411

    
412
    return quatsFromPermutations(corner_perm,edge_perm8,centers);
413
    }
414

    
415
///////////////////////////////////////////////////////////////////////////////////////////////////
416

    
417
  public int getIndex(int[] quats)
418
    {
419
    int centers = centersInverted(quats);
420

    
421
    cornerFromQuats(mCornerPerm,quats);
422
    int corner_perm_num = TablebaseHelpers.computePermutationNum(mCornerPerm);
423

    
424
    edgeFromQuats(mEdgePerm,quats);
425
    int edge_perm_num = TablebaseHelpers.computePermutationNum(mEdgePerm);
426

    
427
    return corner_perm_num + 40320*( centers + 2*edge_perm_num);
428
    }
429
}  
430

    
(5-5/19)