Project

General

Profile

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

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

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

    
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18

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

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

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

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

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

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

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

    
76
    return ret;
77
    }
78

    
79
///////////////////////////////////////////////////////////////////////////////////////////////////
80
// reverse the above
81

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

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

    
95
    return ret;
96
    }
97

    
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99

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

    
104
    allocate();
105
    }
106

    
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108

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

    
114
    allocate();
115
    }
116

    
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118

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

    
125
///////////////////////////////////////////////////////////////////////////////////////////////////
126

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

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

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

    
143
    return mAngles;
144
    }
145

    
146
///////////////////////////////////////////////////////////////////////////////////////////////////
147

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

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159

    
160
  float[][] getPosition()
161
    {
162
    return new float[][]
163
      {
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
        {  1.0f,  0.5f,  1.0f },
172

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

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

    
187
///////////////////////////////////////////////////////////////////////////////////////////////////
188

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

    
194
///////////////////////////////////////////////////////////////////////////////////////////////////
195

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

    
201
///////////////////////////////////////////////////////////////////////////////////////////////////
202
// purely for speedup
203

    
204
  @Override
205
  int computeRow(float[] pos, int quat, int axisIndex)
206
    {
207
    Static4D q = mQuats[quat];
208
    float qx = q.get0();
209
    float qy = q.get1();
210
    float qz = q.get2();
211
    float qw = q.get3();
212
    float rx = pos[0];
213
    float ry = pos[1];
214
    float rz = pos[2];
215

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

    
221
    switch(axisIndex)
222
      {
223
      case 0: float res0 = qw*mTmp[0] + qz*mTmp[1] - qy*mTmp[2] - qx*mTmp[3];
224
              if( res0<-0.5f ) return 1;
225
              if( res0< 0.5f ) return 2;
226
              return 4;
227
      case 1: float res1 = qw*mTmp[1] - qz*mTmp[0] - qy*mTmp[3] + qx*mTmp[2];
228
              return (res1<0 ? 1:2);
229
      case 2: float res2 = qw*mTmp[2] - qz*mTmp[3] + qy*mTmp[0] - qx*mTmp[1];
230
              if( res2<-0.5f ) return 1;
231
              if( res2< 0.5f ) return 2;
232
              return 4;
233
      }
234

    
235
    return 0;
236
    }
237

    
238
///////////////////////////////////////////////////////////////////////////////////////////////////
239
// we map the move (axis=2, middle layer) to move (axis=2,both middle and back layers).
240
// this way we can imitate move of the front layer (which we do not want to move because
241
// the edge1 piece has to always stay in its place)
242

    
243
  @Override
244
  int computeBitLayer(int ax, int layer)
245
    {
246
    if( ax!=2 ) return (1<<layer);
247

    
248
    switch(layer)
249
      {
250
      case 0 : return 1;
251
      case 1 : return 3;
252
      default: return 4;
253
      }
254
    }
255

    
256
///////////////////////////////////////////////////////////////////////////////////////////////////
257
// this is too slow to be used for scrambling - scramble the 3x3x2 the old way.
258

    
259
  @Override
260
  public boolean useForScrambling()
261
    {
262
    return false;
263
    }
264

    
265
///////////////////////////////////////////////////////////////////////////////////////////////////
266
// specifically for the tablebase
267
///////////////////////////////////////////////////////////////////////////////////////////////////
268
// now turn the (ax=2, middle and back layer) artificial moves [ introduced by computeBitLayer)
269
// back to the natural (ax=2, front layer). Turn the whole thing upside down each time we do it.
270

    
271
  @Override
272
  int[] newMove(int axis, int layer, int angle)
273
    {
274
    if( axis==2 )
275
      {
276
      if( layer==1 )
277
        {
278
        mUpsideDown = !mUpsideDown;
279
        return new int[] { axis, 4, angle };
280
        }
281
      }
282
    else if( mUpsideDown )
283
      {
284
      if( axis==0 ) layer=2-layer;
285
      if( axis==1 ) { layer=1-layer; angle = 4-angle; }
286
      }
287

    
288
    int maxAngle = mAngles[axis][layer];
289
    angle = maxAngle-angle;
290
    if( angle> 0.5f*maxAngle ) angle -= maxAngle;
291
    return new int[] { axis, (1<<layer), angle };
292
    }
293

    
294
///////////////////////////////////////////////////////////////////////////////////////////////////
295
// 8!*8!/4 --> https://www.jaapsch.net/puzzles/domino.htm
296

    
297
  int getSize()
298
    {
299
    return 406425600;
300
    }
301

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

    
304
  int getMinScramble()
305
    {
306
    return 13;
307
    }
308

    
309
///////////////////////////////////////////////////////////////////////////////////////////////////
310

    
311
  int[] getMidPruningLevels()
312
    {
313
    return new int[] {7,8};
314
    }
315

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

    
318
  int[] getHighPruningLevels()
319
    {
320
    return new int[] {17,18};
321
    }
322

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

    
325
  int getGodsNumber()
326
    {
327
    return 18;
328
    }
329

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

    
332
  boolean moveCanProceed(int lastA, int lastR, int currA, int currR)
333
    {
334
    return (lastA!=currA) || (lastR!=currR);
335
    }
336

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

    
339
  private static int findIndex(int[] table, int value)
340
    {
341
    for(int i=0; i<8; i++)
342
      if( table[i]==value ) return i;
343

    
344
    return -1;
345
    }
346

    
347
///////////////////////////////////////////////////////////////////////////////////////////////////
348

    
349
  private int centersInverted(int[] quats)
350
    {
351
    int q = quats[16];
352
    return (q==0 || q==2 || q==3 || q==4) ? 0 : 1;
353
    }
354

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

    
357
  public static int[] quatsFromPermutations(int[] corner, int[] edge8, int centers)
358
    {
359
    int[] quats = new int[18];
360

    
361
    for(int i=0; i<8; i++)
362
      {
363
      int q = CORNER_MAP[i][corner[i]];
364
      quats[i] = q;
365
      }
366
    for(int i=0; i<8; i++)
367
      {
368
      int q = EDGE_MAP[i][edge8[i]];
369
      quats[i+8] = q;
370
      }
371

    
372
    if( centers==0 )
373
      {
374
      quats[16]=0;
375
      quats[17]=0;
376
      }
377
    else
378
      {
379
      quats[16]=5;
380
      quats[17]=5;
381
      }
382

    
383
    return quats;
384
    }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  private static void cornerFromQuats(int[] corner_perm, int[] quats)
389
    {
390
    for(int i=0; i<8; i++) corner_perm[i] = CORNER_MAP_INVERTED[i][quats[i]];
391
    }
392

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

    
395
  private static void edgeFromQuats(int[] edge_perm, int[] quats)
396
    {
397
    edge_perm[0] = EDGE_MAP_INVERTED[0][quats[ 8]]; if(edge_perm[0]>1) edge_perm[0]--;
398
    edge_perm[1] = EDGE_MAP_INVERTED[2][quats[10]]; if(edge_perm[1]>1) edge_perm[1]--;
399
    edge_perm[2] = EDGE_MAP_INVERTED[3][quats[11]]; if(edge_perm[2]>1) edge_perm[2]--;
400
    edge_perm[3] = EDGE_MAP_INVERTED[4][quats[12]]; if(edge_perm[3]>1) edge_perm[3]--;
401
    edge_perm[4] = EDGE_MAP_INVERTED[5][quats[13]]; if(edge_perm[4]>1) edge_perm[4]--;
402
    edge_perm[5] = EDGE_MAP_INVERTED[6][quats[14]]; if(edge_perm[5]>1) edge_perm[5]--;
403
    edge_perm[6] = EDGE_MAP_INVERTED[7][quats[15]]; if(edge_perm[6]>1) edge_perm[6]--;
404
    }
405

    
406
///////////////////////////////////////////////////////////////////////////////////////////////////
407

    
408
  public int[] getQuats(int index)
409
    {
410
    int cornerPermNum = (index%40320);
411
    index /= 40320;
412
    int centers = (index%2);
413
    int edgePermNum = index/2;
414

    
415
    int[] corner_perm = new int[8];
416
    TablebaseHelpers.getPermutationFromNum(corner_perm,8,cornerPermNum);
417
    int[] edge_perm7 = new int[7];
418
    TablebaseHelpers.getPermutationFromNum(edge_perm7,7,edgePermNum);
419
    int[] edge_perm8 = edgePermTo8(edge_perm7);
420

    
421
    return quatsFromPermutations(corner_perm,edge_perm8,centers);
422
    }
423

    
424
///////////////////////////////////////////////////////////////////////////////////////////////////
425

    
426
  public int getIndex(int[] quats)
427
    {
428
    int centers = centersInverted(quats);
429

    
430
    cornerFromQuats(mCornerPerm,quats);
431
    int corner_perm_num = TablebaseHelpers.computePermutationNum(mCornerPerm);
432

    
433
    edgeFromQuats(mEdgePerm,quats);
434
    int edge_perm_num = TablebaseHelpers.computePermutationNum(mEdgePerm);
435

    
436
    return corner_perm_num + 40320*( centers + 2*edge_perm_num);
437
    }
438
}  
439

    
(5-5/19)