Project

General

Profile

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

distorted-objectlib / src / main / java / org / distorted / objectlib / tablebases / TBDino6.java @ 5b9d6595

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 TBDino6 extends TablebasesPruning
22
{
23
  private static final int INDEX_INVERTED = 13379863; // quats (0,10,0,10, 11,11,11,11, 0,10,0,10)
24

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

    
41
  private int[][] mAngles;
42

    
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44

    
45
  public TBDino6()
46
    {
47
    super();
48
    }
49

    
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51

    
52
  public TBDino6(Resources res)
53
    {
54
    super(res,new int[] {R.raw.dino_3_pruning3,R.raw.dino_3_pruning4},new int[] {R.raw.dino_3_pruning10});
55
    }
56

    
57
///////////////////////////////////////////////////////////////////////////////////////////////////
58

    
59
  int[][] getBasicAngles()
60
    {
61
    if( mAngles==null )
62
      {
63
      int[] tmp = {3,3,3};
64
      mAngles = new int[][] { tmp,tmp,tmp,tmp };
65
      }
66

    
67
    return mAngles;
68
    }
69

    
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71

    
72
  Static3D[] getRotationAxis()
73
    {
74
    return new Static3D[]
75
         {
76
           new Static3D( SQ3/3, SQ3/3, SQ3/3),
77
           new Static3D( SQ3/3, SQ3/3,-SQ3/3),
78
           new Static3D( SQ3/3,-SQ3/3, SQ3/3),
79
           new Static3D( SQ3/3,-SQ3/3,-SQ3/3)
80
         };
81
    }
82

    
83
///////////////////////////////////////////////////////////////////////////////////////////////////
84

    
85
  float[][] getPosition()
86
    {
87
    return new float[][]
88
         {
89
             { 0.0f, 1.5f, 1.5f },
90
             { 1.5f, 0.0f, 1.5f },
91
             { 0.0f,-1.5f, 1.5f },
92
             {-1.5f, 0.0f, 1.5f },
93
             { 1.5f, 1.5f, 0.0f },
94
             { 1.5f,-1.5f, 0.0f },
95
             {-1.5f,-1.5f, 0.0f },
96
             {-1.5f, 1.5f, 0.0f },
97
             { 0.0f, 1.5f,-1.5f },
98
             { 1.5f, 0.0f,-1.5f },
99
             { 0.0f,-1.5f,-1.5f },
100
             {-1.5f, 0.0f,-1.5f }
101
         };
102
    }
103

    
104
///////////////////////////////////////////////////////////////////////////////////////////////////
105

    
106
  float[][] getCuts()
107
    {
108
    float[] cut = new float[] { -SQ3/3, SQ3/3 };
109
    return new float[][] { cut,cut,cut,cut };
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113
// exclude the middle layer and movements of edge[0].
114

    
115
  boolean[][] getRotatable()
116
    {
117
    boolean[] tmp = {true,false,true};
118
    return new boolean[][] { tmp,tmp,tmp,tmp };
119
    }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122
// specifically for the tablebase
123
///////////////////////////////////////////////////////////////////////////////////////////////////
124
// two solved positions: original and mirrored (left face swapped with right)
125

    
126
  @Override
127
  int[] getSolvedIndices()
128
    {
129
    return new int[] {0,INDEX_INVERTED};
130
    }
131

    
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133
// ditto
134

    
135
  @Override
136
  boolean isSolved(int index)
137
    {
138
    return index==0 || index==INDEX_INVERTED;
139
    }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142
// we can never really move the top-front edge, because if we do so, we would also rotate the
143
// rotation axis themselves! (see getIndex() where the cubit quats are normalized so that quat[0]
144
// - i.e. the front-top edge - is always 0).
145
// That's why map the moves (0,2,X) to (0,0&1,-X) and (3,0,X) to (3,1&2,-X)
146

    
147
  @Override
148
  int[] newMove(int axis, int layer, int angle)
149
    {
150
    if( axis==0 && layer==2 ) return new int[] { axis, (1<<0)+(1<<1), angle==1 ? 1:-1};
151
    if( axis==3 && layer==0 ) return new int[] { axis, (1<<1)+(1<<2), angle==1 ? 1:-1};
152

    
153
    int maxAngle = mAngles[axis][layer];
154
    angle = maxAngle-angle;
155
    if( angle> 0.5f*maxAngle ) angle -= maxAngle;
156
    return new int[] { axis, (1<<layer), angle };
157
    }
158

    
159
///////////////////////////////////////////////////////////////////////////////////////////////////
160
// here we change back the mapping introduced by 'newMove()'
161

    
162
  @Override
163
  void convertMoves(int[][] moves)
164
    {
165
    for(int[] move : moves )
166
      {
167
      int[] newMove = newMove(move[0],move[1],move[2]);
168

    
169
      move[0] = newMove[0];
170
      move[1] = newMove[1];
171
      move[2] = newMove[2];
172
      }
173
/*
174
    int len = moves.length;
175

    
176
    for(int i=0; i<len; i++)
177
      {
178
      int[] move = moves[i];
179
      if( move[1]==((1<<0)+(1<<1)) || move[1]==((1<<1)+(1<<2)) ) unrollMoves(moves,i);
180
      }
181

    
182
 */
183
    }
184

    
185
///////////////////////////////////////////////////////////////////////////////////////////////////
186

    
187
  private void unrollMoves(int[][] moves, int index)
188
    {
189
    int caseUnroll=0;
190
    int[] move = moves[index];
191

    
192
    if( move[1]==((1<<0)+(1<<1)) )
193
      {
194
      move[1] = (1<<2);
195
      move[2] = -move[2];
196
      caseUnroll = move[2]>0 ? 0:1;
197
      }
198
    else if( move[1]==((1<<1)+(1<<2)) )
199
      {
200
      move[1] = (1<<0);
201
      move[2] = -move[2];
202
      caseUnroll = move[2]>0 ? 2:3;
203
      }
204

    
205
    int len = moves.length;
206
    for(int i=index+1; i<len; i++) unrollMove(moves[i],caseUnroll);
207
    }
208

    
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

    
211
  private void unrollMove(int[] move, int caseUnroll)
212
    {
213
    int ax = move[0];
214
    int la = move[1];
215

    
216
    switch(caseUnroll)
217
      {
218
      case 0: android.util.Log.e("D", "case 0 ax "+ax);
219
              switch(ax)
220
                {
221
                case 0: break;
222
                case 1: move[0]=3; move[1]=negate(la); break;
223
                case 2: move[0]=1; break;
224
                case 3: move[0]=2; move[1]=negate(la); break;
225
                }
226
              break;
227
      case 1: android.util.Log.e("D", "case 1 ax "+ax);
228
              switch(ax)
229
                {
230
                case 0: break;
231
                case 1: move[0]=2; break;
232
                case 2: move[0]=3; move[1]=negate(la); break;
233
                case 3: move[0]=1; move[1]=negate(la); break;
234
                }
235
              break;
236
      case 2: android.util.Log.e("D", "case 2 ax "+ax);
237
              switch(ax)
238
                {
239
                case 0: move[0]=1; move[1]=negate(la); break;
240
                case 1: move[0]=2; break;
241
                case 2: move[0]=0; move[1]=negate(la); break;
242
                case 3: break;
243
                }
244
              break;
245
      case 3: android.util.Log.e("D", "case 3 ax "+ax);
246
              switch(ax)
247
                {
248
                case 0: move[0]=2; move[1]=negate(la); break;
249
                case 1: move[0]=0; move[1]=negate(la); break;
250
                case 2: move[0]=1; break;
251
                case 3: break;
252
                }
253
              break;
254
      }
255
    }
256

    
257
///////////////////////////////////////////////////////////////////////////////////////////////////
258

    
259
  private int negate(int layer)
260
    {
261
    return 7-layer;
262
    }
263

    
264
///////////////////////////////////////////////////////////////////////////////////////////////////
265

    
266
  int getSize()
267
    {
268
    return 19958400;  // see https://www.jaapsch.net/puzzles/dinocube.htm
269
    }
270

    
271
///////////////////////////////////////////////////////////////////////////////////////////////////
272

    
273
  int getMinScramble()
274
    {
275
    return 8;
276
    }
277

    
278
///////////////////////////////////////////////////////////////////////////////////////////////////
279

    
280
  int[] getMidPruningLevels()
281
    {
282
    return new int[] {3,4};
283
    }
284

    
285
///////////////////////////////////////////////////////////////////////////////////////////////////
286

    
287
  int[] getHighPruningLevels()
288
    {
289
    return new int[] {10};
290
    }
291

    
292
///////////////////////////////////////////////////////////////////////////////////////////////////
293

    
294
  int getGodsNumber()
295
    {
296
    return 10;
297
    }
298

    
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300

    
301
  boolean moveCanProceed(int lastA, int lastR, int currA, int currR)
302
    {
303
    return (lastA!=currA) || (lastR!=currR);
304
    }
305

    
306
///////////////////////////////////////////////////////////////////////////////////////////////////
307

    
308
  public static int getIndexFromPerm(int[] perm)
309
    {
310
    int[] perm11 = new int[11];
311
    for(int i=0; i<11; i++) perm11[i] = perm[i+1]-1;
312
    return TablebaseHelpers.computeEvenPermutationNum(perm11);
313
    }
314

    
315
///////////////////////////////////////////////////////////////////////////////////////////////////
316
// in-place!
317

    
318
  private int[] getPermFromQuats(int[] quats)
319
    {
320
    for(int i=0; i<12; i++)
321
      {
322
      int[] Q = QUATS[i];
323
      int quat = quats[i];
324

    
325
      for(int j=0; j<12; j++)
326
        if( Q[j]==quat )
327
          {
328
          quats[i] = j;
329
          break;
330
          }
331
      }
332

    
333
    return quats;
334
    }
335

    
336
///////////////////////////////////////////////////////////////////////////////////////////////////
337
// in-place!
338

    
339
  public static int[] getQuatsFromPerm(int[] perm)
340
    {
341
    for(int i=0; i<12; i++)
342
      {
343
      int p = perm[i];
344
      perm[i] = QUATS[i][p];
345
      }
346

    
347
    return perm;
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351
// we rotate the whole thing so that quat[0] is always 0.
352

    
353
  private void normalizeQuats(int[] quats)
354
    {
355
    if( quats[0]!=0 )
356
      {
357
      int inverted = getInvertedQuat(quats[0]);
358
      quats[0] = 0;
359

    
360
      for(int i=1; i<12; i++)
361
        {
362
        int index = quats[i];
363
        quats[i] = getMultQuat(inverted,index);
364
        }
365
      }
366
    }
367

    
368
///////////////////////////////////////////////////////////////////////////////////////////////////
369

    
370
  int[] getQuats(int index)
371
    {
372
    int[] perm11 = new int[11];
373
    TablebaseHelpers.getEvenPermutationFromNum(perm11,index);
374
    int[] perm = new int[12];
375
    for(int i=1; i<12; i++) perm[i] = perm11[i-1]+1;
376
    return getQuatsFromPerm(perm);
377
    }
378

    
379
///////////////////////////////////////////////////////////////////////////////////////////////////
380

    
381
  int getIndex(int[] quats)
382
    {
383
    normalizeQuats(quats);
384
    int[] perm = getPermFromQuats(quats);
385
    return getIndexFromPerm(perm);
386
    }
387
}  
388

    
(5-5/15)