Project

General

Profile

Download (13.6 KB) Statistics
| Branch: | Tag: | Revision:

magiccube / src / main / java / org / distorted / solvers / SolverSkewb.java @ da57afae

1 18354673 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
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.solvers;
11
12 b4f45fdc Leszek Koltunski
import static org.distorted.objectlib.tablebases.TBSkewb.FREE;
13
14 18354673 Leszek Koltunski
import android.content.res.Resources;
15
16
import org.distorted.main.R;
17 da57afae Leszek Koltunski
import org.distorted.objectlib.helpers.OperatingSystemInterface;
18 18354673 Leszek Koltunski
import org.distorted.objectlib.main.ObjectSignatures;
19
import org.distorted.objectlib.main.TwistyObject;
20
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
21 c76be0a6 Leszek Koltunski
import org.distorted.objectlib.tablebases.TBSkewb;
22 cff92952 Leszek Koltunski
import org.distorted.objectlib.tablebases.TablebaseHelpers;
23 18354673 Leszek Koltunski
import org.distorted.objectlib.tablebases.TablebasesAbstract;
24
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
27
public class SolverSkewb extends SolverTablebase
28
{
29
  private static final int ERROR_CORNER_135_MISSING = -1;
30
  private static final int ERROR_CORNER_134_MISSING = -2;
31
  private static final int ERROR_CORNER_125_MISSING = -3;
32
  private static final int ERROR_CORNER_124_MISSING = -4;
33
  private static final int ERROR_CORNER_035_MISSING = -5;
34
  private static final int ERROR_CORNER_034_MISSING = -6;
35
  private static final int ERROR_CORNER_025_MISSING = -7;
36
  private static final int ERROR_CORNER_024_MISSING = -8;
37
38
  private static final int ERROR_CENTER_0_MISSING   = -9;
39
  private static final int ERROR_CENTER_1_MISSING   = -10;
40
  private static final int ERROR_CENTER_2_MISSING   = -11;
41
  private static final int ERROR_CENTER_3_MISSING   = -12;
42
  private static final int ERROR_CENTER_4_MISSING   = -13;
43
  private static final int ERROR_CENTER_5_MISSING   = -14;
44
45
  private static final int ERROR_CORNERS_CANNOT     = -15;
46
  private static final int ERROR_CORNER_TWISTED     = -16;
47
  private static final int ERROR_TWO_CENTERS        = -17;
48
  private static final int ERROR_TWO_CORNERS        = -18;
49
50
  private TablebasesAbstract mSolver;
51 cff92952 Leszek Koltunski
  private final int[] mFaceColors;
52 18354673 Leszek Koltunski
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54
55 da57afae Leszek Koltunski
  public SolverSkewb(OperatingSystemInterface os, Resources res, TwistyObject object)
56 18354673 Leszek Koltunski
    {
57 da57afae Leszek Koltunski
    super(os,res,object);
58 cff92952 Leszek Koltunski
    mFaceColors = new int[6];
59 18354673 Leszek Koltunski
    }
60
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62
63
  private void getCorners(TwistyObject object, int[][] corners)
64
    {
65 cff92952 Leszek Koltunski
    for(int i=0; i<8; i++)
66
      for(int j=0; j<3; j++)
67
        corners[i][j] = object.getCubitFaceStickerIndex(i,j);
68
    }
69
70
///////////////////////////////////////////////////////////////////////////////////////////////////
71
72 6a64512e Leszek Koltunski
  private int getCenters(TwistyObject object, int[] output)
73 cff92952 Leszek Koltunski
    {
74 6a64512e Leszek Koltunski
    final int[] map = {4,5,2,3,0,1};
75
    int[] inverted_perm = new int[6];
76
    boolean[] present = new boolean[6];
77 18354673 Leszek Koltunski
78 cff92952 Leszek Koltunski
    for(int i=0; i<6; i++)
79 b4f45fdc Leszek Koltunski
      {
80
      int color = object.getCubitFaceStickerIndex(i+8,0) - 6;
81 6a64512e Leszek Koltunski
      present[color] = true;
82
      inverted_perm[i] = map[mFaceColors[color]];
83 b4f45fdc Leszek Koltunski
      }
84
85 6a64512e Leszek Koltunski
    if( !present[0] ) return ERROR_CENTER_0_MISSING;
86
    if( !present[1] ) return ERROR_CENTER_1_MISSING;
87
    if( !present[2] ) return ERROR_CENTER_2_MISSING;
88
    if( !present[3] ) return ERROR_CENTER_3_MISSING;
89
    if( !present[4] ) return ERROR_CENTER_4_MISSING;
90
    if( !present[5] ) return ERROR_CENTER_5_MISSING;
91
92
    TablebaseHelpers.invertPermutation(inverted_perm,output);
93
    return 0;
94 18354673 Leszek Koltunski
    }
95
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97
98 cff92952 Leszek Koltunski
  private int commonCornerColor(int[] c1, int[] c2)
99 18354673 Leszek Koltunski
    {
100 cff92952 Leszek Koltunski
    int theSame = 0;
101
    int index   = 0;
102
103
    for(int i=0; i<3; i++)
104
      for(int j=0; j<3; j++)
105
        if( c1[i]==c2[j] )
106
          {
107
          index = i;
108
          theSame++;
109
          }
110
111
    return theSame==1 ? c1[index] : ERROR_CORNERS_CANNOT;
112
    }
113
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115
116
  private int computeFaceColors(int[][] corners, int[] output)
117
    {
118 6a64512e Leszek Koltunski
    final int[][] corner_indices = { {0,3},{5,6},{0,5},{6,3},{0,6},{3,5} };
119 cff92952 Leszek Koltunski
120
    for(int i=0; i<6; i++)
121
      {
122 6a64512e Leszek Koltunski
      int c1 = corner_indices[i][0];
123
      int c2 = corner_indices[i][1];
124 cff92952 Leszek Koltunski
      output[i] = commonCornerColor(corners[c1],corners[c2]);
125
      if( output[i]<0 ) return ERROR_CORNERS_CANNOT;
126
      }
127
128 18354673 Leszek Koltunski
    return 0;
129
    }
130
131
///////////////////////////////////////////////////////////////////////////////////////////////////
132
133 6a64512e Leszek Koltunski
  private boolean cornerIs(int[] corner, int f0, int f1, int f2)
134 18354673 Leszek Koltunski
    {
135 6a64512e Leszek Koltunski
    int c0 = mFaceColors[f0];
136
    int c1 = mFaceColors[f1];
137
    int c2 = mFaceColors[f2];
138
139 cff92952 Leszek Koltunski
    return ( (corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) ||
140
             (corner[1]==c0 && corner[2]==c1 && corner[0]==c2 ) ||
141
             (corner[2]==c0 && corner[0]==c1 && corner[1]==c2 )  );
142 18354673 Leszek Koltunski
    }
143
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145
146 cff92952 Leszek Koltunski
  private int checkAllCornersPresent(int[][] corners)
147 18354673 Leszek Koltunski
    {
148 cff92952 Leszek Koltunski
    boolean[] present = new boolean[8];
149
150
    for(int i=0; i<8; i++)
151
      {
152
      if( cornerIs(corners[i],4,2,0) ) present[0]=true;
153
      if( cornerIs(corners[i],2,5,0) ) present[1]=true;
154
      if( cornerIs(corners[i],3,4,0) ) present[2]=true;
155
      if( cornerIs(corners[i],5,3,0) ) present[3]=true;
156
      if( cornerIs(corners[i],1,2,4) ) present[4]=true;
157
      if( cornerIs(corners[i],5,2,1) ) present[5]=true;
158
      if( cornerIs(corners[i],4,3,1) ) present[6]=true;
159
      if( cornerIs(corners[i],1,3,5) ) present[7]=true;
160
      }
161
162
    if( !present[0] ) return ERROR_CORNER_024_MISSING;
163
    if( !present[1] ) return ERROR_CORNER_025_MISSING;
164
    if( !present[2] ) return ERROR_CORNER_034_MISSING;
165
    if( !present[3] ) return ERROR_CORNER_035_MISSING;
166
    if( !present[4] ) return ERROR_CORNER_124_MISSING;
167
    if( !present[5] ) return ERROR_CORNER_125_MISSING;
168
    if( !present[6] ) return ERROR_CORNER_134_MISSING;
169
    if( !present[7] ) return ERROR_CORNER_135_MISSING;
170 18354673 Leszek Koltunski
171 cff92952 Leszek Koltunski
    return 0;
172 18354673 Leszek Koltunski
    }
173
174 cff92952 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
175
176 14cf0761 Leszek Koltunski
  private int retFreeCornerPermutation(int[] perm, int[][] corners)
177 cff92952 Leszek Koltunski
    {
178 14cf0761 Leszek Koltunski
    perm[0] = -1;
179 cff92952 Leszek Koltunski
    perm[1] = -1;
180
    perm[2] = -1;
181 14cf0761 Leszek Koltunski
    perm[3] = -1;
182 cff92952 Leszek Koltunski
183
    for(int i=0; i<4; i++)
184
      {
185 b4f45fdc Leszek Koltunski
      int[] cor = corners[FREE[i]];
186 cff92952 Leszek Koltunski
187 14cf0761 Leszek Koltunski
      if( cornerIs(cor,2,5,0) ) perm[0] = i;
188
      if( cornerIs(cor,3,4,0) ) perm[1] = i;
189
      if( cornerIs(cor,1,2,4) ) perm[2] = i;
190
      if( cornerIs(cor,1,3,5) ) perm[3] = i;
191 cff92952 Leszek Koltunski
      }
192
193 14cf0761 Leszek Koltunski
    if( perm[0]==-1 ) return ERROR_CORNER_025_MISSING;
194
    if( perm[1]==-1 ) return ERROR_CORNER_034_MISSING;
195
    if( perm[2]==-1 ) return ERROR_CORNER_124_MISSING;
196
    if( perm[3]==-1 ) return ERROR_CORNER_135_MISSING;
197 cff92952 Leszek Koltunski
198 18354673 Leszek Koltunski
    return 0;
199
    }
200
201 14cf0761 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
202 cff92952 Leszek Koltunski
203 14cf0761 Leszek Koltunski
  private int retCornerPerm(int index, int[] perm)
204
    {
205
    switch(index)
206
      {
207
      case 0: return 0;
208 b4f45fdc Leszek Koltunski
      case 1: return FREE[perm[0]];
209
      case 2: return FREE[perm[1]];
210 14cf0761 Leszek Koltunski
      case 3: return 3;
211 b4f45fdc Leszek Koltunski
      case 4: return FREE[perm[2]];
212 14cf0761 Leszek Koltunski
      case 5: return 5;
213
      case 6: return 6;
214 b4f45fdc Leszek Koltunski
      case 7: return FREE[perm[3]];
215 14cf0761 Leszek Koltunski
      }
216 cff92952 Leszek Koltunski
217 14cf0761 Leszek Koltunski
    return -1;
218
    }
219 cff92952 Leszek Koltunski
220 14cf0761 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
221 cff92952 Leszek Koltunski
222 14cf0761 Leszek Koltunski
  private void computeCornerQuats(int[] quats, int[][] corners, int[] perm)
223
    {
224 6a64512e Leszek Koltunski
    final int[] zeroeth_face_map = { 4,2,3,5,1,5,4,1 };
225 b4f45fdc Leszek Koltunski
    int[] twist = new int[8];
226 cff92952 Leszek Koltunski
227 14cf0761 Leszek Koltunski
    for(int i=0; i<8; i++)
228 cff92952 Leszek Koltunski
      {
229 6a64512e Leszek Koltunski
      int color = mFaceColors[zeroeth_face_map[i]];
230 14cf0761 Leszek Koltunski
      int[] c = corners[retCornerPerm(i,perm)];
231
232 b4f45fdc Leszek Koltunski
           if( c[0]==color ) twist[i] = 0;
233
      else if( c[1]==color ) twist[i] = 1;
234
      else                   twist[i] = 2;
235 cff92952 Leszek Koltunski
      }
236
237 b4f45fdc Leszek Koltunski
    TBSkewb.fillInQuats(quats,perm,twist);
238 cff92952 Leszek Koltunski
    }
239
240 18354673 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
241
242
  public int tablebaseIndex(TwistyObject object)
243
    {
244 cff92952 Leszek Koltunski
    int[][] corners= new int[8][3];
245
    int[] centers  = new int[6];
246
    int[] twist    = new int[8];
247 14cf0761 Leszek Koltunski
    int[] freePerm = new int[4];
248
    int[] quats    = new int[8];
249 18354673 Leszek Koltunski
250
    getCorners(object,corners);
251
252 cff92952 Leszek Koltunski
    int result1 = computeFaceColors(corners,mFaceColors);
253 18354673 Leszek Koltunski
    if( result1<0 ) return result1;
254
255 cff92952 Leszek Koltunski
    int result2 = checkAllCornersPresent(corners);
256
    if( result2<0 ) return result2;
257 18354673 Leszek Koltunski
258 6a64512e Leszek Koltunski
    int result3 = getCenters(object,centers);
259 cff92952 Leszek Koltunski
    if( result3<0 ) return result3;
260 18354673 Leszek Koltunski
261 cff92952 Leszek Koltunski
    if( !TablebaseHelpers.permutationIsEven(centers) ) return ERROR_TWO_CENTERS;
262
    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(centers);
263 18354673 Leszek Koltunski
264 14cf0761 Leszek Koltunski
    int result4 = retFreeCornerPermutation(freePerm,corners);
265 cff92952 Leszek Koltunski
    if( result4<0 ) return result4;
266
267 14cf0761 Leszek Koltunski
    computeCornerQuats(quats,corners,freePerm);
268 c76be0a6 Leszek Koltunski
    TBSkewb.computeCornerTwists(twist,quats);
269 b4f45fdc Leszek Koltunski
270
    int total = 0;
271
    for(int i=0; i<4; i++) total += twist[FREE[i]];
272 14cf0761 Leszek Koltunski
    if( (total%3)!=0 ) return ERROR_CORNER_TWISTED;
273
    int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
274 cff92952 Leszek Koltunski
275 4fd36883 Leszek Koltunski
    int locationOfFree0 = TBSkewb.computeLocation(0,quats[1]);
276 cff92952 Leszek Koltunski
277 14cf0761 Leszek Koltunski
    return center_perm_num+ 360*(totalTwist + 2187*locationOfFree0);
278 18354673 Leszek Koltunski
    }
279
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281
282
  private int getColorIndex2(int face)
283
    {
284
    switch(mFaceColors[face])
285
      {
286
      case 0: return R.string.color_yellow2;
287
      case 1: return R.string.color_white2;
288
      case 2: return R.string.color_blue2;
289
      case 3: return R.string.color_green2;
290
      case 4: return R.string.color_red2;
291
      case 5: return R.string.color_orange2;
292
      }
293
294
    return -1;
295
    }
296
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298
299
  private int getColorIndex3(int face)
300
    {
301
    switch(mFaceColors[face])
302
      {
303
      case 0: return R.string.color_yellow3;
304
      case 1: return R.string.color_white3;
305
      case 2: return R.string.color_blue3;
306
      case 3: return R.string.color_green3;
307
      case 4: return R.string.color_red3;
308
      case 5: return R.string.color_orange3;
309
      }
310
311
    return -1;
312
    }
313
314
///////////////////////////////////////////////////////////////////////////////////////////////////
315
316
  private int getColorIndex4(int face)
317
    {
318
    switch(mFaceColors[face])
319
      {
320
      case 0: return R.string.color_yellow4;
321
      case 1: return R.string.color_white4;
322
      case 2: return R.string.color_blue4;
323
      case 3: return R.string.color_green4;
324
      case 4: return R.string.color_red4;
325
      case 5: return R.string.color_orange4;
326
      }
327
328
    return -1;
329
    }
330
331
///////////////////////////////////////////////////////////////////////////////////////////////////
332
333
  private String cornerError(Resources res, int face0, int face1, int face2)
334
    {
335
    int j0 = getColorIndex3(face0);
336
    int j1 = getColorIndex3(face1);
337
    int j2 = getColorIndex4(face2);
338
339
    String c0 = res.getString(j0);
340
    String c1 = res.getString(j1);
341
    String c2 = res.getString(j2);
342
343
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
344
    }
345
346
///////////////////////////////////////////////////////////////////////////////////////////////////
347
348
  private String centerError(Resources res, int face)
349
    {
350
    int color = getColorIndex2(face);
351
    String clr= res.getString(color);
352
    return res.getString(R.string.solver_generic_missing_center,clr);
353
    }
354
355
///////////////////////////////////////////////////////////////////////////////////////////////////
356
357
  public String error(int index, Resources res)
358
    {
359
    switch(index)
360
      {
361
      case ERROR_CORNER_135_MISSING: return cornerError(res,1,3,5);
362
      case ERROR_CORNER_134_MISSING: return cornerError(res,1,3,4);
363
      case ERROR_CORNER_125_MISSING: return cornerError(res,1,2,5);
364
      case ERROR_CORNER_124_MISSING: return cornerError(res,1,2,4);
365
      case ERROR_CORNER_035_MISSING: return cornerError(res,0,3,5);
366
      case ERROR_CORNER_034_MISSING: return cornerError(res,0,3,4);
367
      case ERROR_CORNER_025_MISSING: return cornerError(res,0,2,5);
368
      case ERROR_CORNER_024_MISSING: return cornerError(res,0,2,4);
369
370
      case ERROR_CENTER_0_MISSING  : return centerError(res,0);
371
      case ERROR_CENTER_1_MISSING  : return centerError(res,1);
372
      case ERROR_CENTER_2_MISSING  : return centerError(res,2);
373
      case ERROR_CENTER_3_MISSING  : return centerError(res,3);
374
      case ERROR_CENTER_4_MISSING  : return centerError(res,4);
375
      case ERROR_CENTER_5_MISSING  : return centerError(res,5);
376
377
      case ERROR_CORNERS_CANNOT    : return res.getString(R.string.solver_generic_corners_cannot);
378
      case ERROR_CORNER_TWISTED    : return res.getString(R.string.solver_generic_corner_twist);
379
      case ERROR_TWO_CENTERS       : return res.getString(R.string.solver_generic_two_centers);
380
      case ERROR_TWO_CORNERS       : return res.getString(R.string.solver_generic_two_corners);
381
      }
382
383
    return null;
384
    }
385
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387
388 da57afae Leszek Koltunski
  public int[][] solution(int index, OperatingSystemInterface os)
389 18354673 Leszek Koltunski
    {
390
    if( mSolver==null )
391
      {
392 da57afae Leszek Koltunski
      mSolver = ImplementedTablebasesList.createPacked(os,ObjectSignatures.SKEW_2);
393 18354673 Leszek Koltunski
      }
394
395
    return mSolver!=null ? mSolver.solution(index,null) : null;
396
    }
397
}