Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverSkewb.java @ 4fd36883

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.solvers;
11

    
12
import android.content.res.Resources;
13

    
14
import org.distorted.main.R;
15
import org.distorted.objectlib.main.ObjectSignatures;
16
import org.distorted.objectlib.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
18
import org.distorted.objectlib.tablebases.TBSkewb;
19
import org.distorted.objectlib.tablebases.TablebaseHelpers;
20
import org.distorted.objectlib.tablebases.TablebasesAbstract;
21

    
22
///////////////////////////////////////////////////////////////////////////////////////////////////
23

    
24
public class SolverSkewb extends SolverTablebase
25
{
26
  private static final int ERROR_CORNER_135_MISSING = -1;
27
  private static final int ERROR_CORNER_134_MISSING = -2;
28
  private static final int ERROR_CORNER_125_MISSING = -3;
29
  private static final int ERROR_CORNER_124_MISSING = -4;
30
  private static final int ERROR_CORNER_035_MISSING = -5;
31
  private static final int ERROR_CORNER_034_MISSING = -6;
32
  private static final int ERROR_CORNER_025_MISSING = -7;
33
  private static final int ERROR_CORNER_024_MISSING = -8;
34

    
35
  private static final int ERROR_CENTER_0_MISSING   = -9;
36
  private static final int ERROR_CENTER_1_MISSING   = -10;
37
  private static final int ERROR_CENTER_2_MISSING   = -11;
38
  private static final int ERROR_CENTER_3_MISSING   = -12;
39
  private static final int ERROR_CENTER_4_MISSING   = -13;
40
  private static final int ERROR_CENTER_5_MISSING   = -14;
41

    
42
  private static final int ERROR_CORNERS_CANNOT     = -15;
43
  private static final int ERROR_CORNER_TWISTED     = -16;
44
  private static final int ERROR_TWO_CENTERS        = -17;
45
  private static final int ERROR_TWO_CORNERS        = -18;
46

    
47
  private TablebasesAbstract mSolver;
48
  private final int[] mFaceColors;
49

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

    
52
  public SolverSkewb(Resources res, TwistyObject object)
53
    {
54
    super(res,object);
55
    mFaceColors = new int[6];
56
    }
57

    
58
///////////////////////////////////////////////////////////////////////////////////////////////////
59

    
60
  private void getCorners(TwistyObject object, int[][] corners)
61
    {
62
    for(int i=0; i<8; i++)
63
      for(int j=0; j<3; j++)
64
        corners[i][j] = object.getCubitFaceStickerIndex(i,j);
65
    }
66

    
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

    
69
  private void getCenters(TwistyObject object, int[] centers)
70
    {
71
    int[] map = {12,13,10,11,8,9};
72

    
73
    for(int i=0; i<6; i++)
74
      centers[i] = object.getCubitFaceStickerIndex(map[i],0) - 6;
75
    }
76

    
77
///////////////////////////////////////////////////////////////////////////////////////////////////
78

    
79
  private int commonCornerColor(int[] c1, int[] c2)
80
    {
81
    int theSame = 0;
82
    int index   = 0;
83

    
84
    for(int i=0; i<3; i++)
85
      for(int j=0; j<3; j++)
86
        if( c1[i]==c2[j] )
87
          {
88
          index = i;
89
          theSame++;
90
          }
91

    
92
    return theSame==1 ? c1[index] : ERROR_CORNERS_CANNOT;
93
    }
94

    
95
///////////////////////////////////////////////////////////////////////////////////////////////////
96

    
97
  private int computeFaceColors(int[][] corners, int[] output)
98
    {
99
    final int[][] map = { {0,3},{5,6},{0,5},{6,3},{0,6},{3,5} };
100

    
101
    for(int i=0; i<6; i++)
102
      {
103
      int c1 = map[i][0];
104
      int c2 = map[i][1];
105
      output[i] = commonCornerColor(corners[c1],corners[c2]);
106
      if( output[i]<0 ) return ERROR_CORNERS_CANNOT;
107
      }
108

    
109
    return 0;
110
    }
111

    
112
///////////////////////////////////////////////////////////////////////////////////////////////////
113

    
114
  private boolean cornerIs(int[] corner, int c0, int c1, int c2)
115
    {
116
    return ( (corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) ||
117
             (corner[1]==c0 && corner[2]==c1 && corner[0]==c2 ) ||
118
             (corner[2]==c0 && corner[0]==c1 && corner[1]==c2 )  );
119
    }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
  private int checkAllCornersPresent(int[][] corners)
124
    {
125
    boolean[] present = new boolean[8];
126

    
127
    for(int i=0; i<8; i++)
128
      {
129
      if( cornerIs(corners[i],4,2,0) ) present[0]=true;
130
      if( cornerIs(corners[i],2,5,0) ) present[1]=true;
131
      if( cornerIs(corners[i],3,4,0) ) present[2]=true;
132
      if( cornerIs(corners[i],5,3,0) ) present[3]=true;
133
      if( cornerIs(corners[i],1,2,4) ) present[4]=true;
134
      if( cornerIs(corners[i],5,2,1) ) present[5]=true;
135
      if( cornerIs(corners[i],4,3,1) ) present[6]=true;
136
      if( cornerIs(corners[i],1,3,5) ) present[7]=true;
137
      }
138

    
139
    if( !present[0] ) return ERROR_CORNER_024_MISSING;
140
    if( !present[1] ) return ERROR_CORNER_025_MISSING;
141
    if( !present[2] ) return ERROR_CORNER_034_MISSING;
142
    if( !present[3] ) return ERROR_CORNER_035_MISSING;
143
    if( !present[4] ) return ERROR_CORNER_124_MISSING;
144
    if( !present[5] ) return ERROR_CORNER_125_MISSING;
145
    if( !present[6] ) return ERROR_CORNER_134_MISSING;
146
    if( !present[7] ) return ERROR_CORNER_135_MISSING;
147

    
148
    return 0;
149
    }
150

    
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152

    
153
  private int checkAllCentersPresent(int[] centers)
154
    {
155
    boolean[] present = new boolean[6];
156
    for(int i=0; i<6; i++) present[centers[i]]= true;
157

    
158
    if( !present[0] ) return ERROR_CENTER_4_MISSING;
159
    if( !present[1] ) return ERROR_CENTER_5_MISSING;
160
    if( !present[2] ) return ERROR_CENTER_2_MISSING;
161
    if( !present[3] ) return ERROR_CENTER_3_MISSING;
162
    if( !present[4] ) return ERROR_CENTER_0_MISSING;
163
    if( !present[5] ) return ERROR_CENTER_1_MISSING;
164

    
165
    return 0;
166
    }
167

    
168
///////////////////////////////////////////////////////////////////////////////////////////////////
169
// free corners: 1,2,4,7
170

    
171
  private int retFreeCornerPermutation(int[] perm, int[][] corners)
172
    {
173
    int[] map = {1,2,4,7};
174

    
175
    perm[0] = -1;
176
    perm[1] = -1;
177
    perm[2] = -1;
178
    perm[3] = -1;
179

    
180
    for(int i=0; i<4; i++)
181
      {
182
      int[] cor = corners[map[i]];
183

    
184
      if( cornerIs(cor,2,5,0) ) perm[0] = i;
185
      if( cornerIs(cor,3,4,0) ) perm[1] = i;
186
      if( cornerIs(cor,1,2,4) ) perm[2] = i;
187
      if( cornerIs(cor,1,3,5) ) perm[3] = i;
188
      }
189

    
190
    if( perm[0]==-1 ) return ERROR_CORNER_025_MISSING;
191
    if( perm[1]==-1 ) return ERROR_CORNER_034_MISSING;
192
    if( perm[2]==-1 ) return ERROR_CORNER_124_MISSING;
193
    if( perm[3]==-1 ) return ERROR_CORNER_135_MISSING;
194

    
195
    return 0;
196
    }
197

    
198
///////////////////////////////////////////////////////////////////////////////////////////////////
199

    
200
  private int retCornerPerm(int index, int[] perm)
201
    {
202
    int[] free = {1,2,4,7};
203

    
204
    switch(index)
205
      {
206
      case 0: return 0;
207
      case 1: return free[perm[0]];
208
      case 2: return free[perm[1]];
209
      case 3: return 3;
210
      case 4: return free[perm[2]];
211
      case 5: return 5;
212
      case 6: return 6;
213
      case 7: return free[perm[3]];
214
      }
215

    
216
    return -1;
217
    }
218

    
219
///////////////////////////////////////////////////////////////////////////////////////////////////
220

    
221
  private void computeCornerQuats(int[] quats, int[][] corners, int[] perm)
222
    {
223
    final int[] map = { 4,2,3,5,1,5,4,1 };
224
    int[] twists = new int[8];
225

    
226
    for(int i=0; i<8; i++)
227
      {
228
      int color = mFaceColors[map[i]];
229
      int[] c = corners[retCornerPerm(i,perm)];
230

    
231
           if( c[0]==color ) twists[i] = 0;
232
      else if( c[1]==color ) twists[i] = 1;
233
      else                   twists[i] = 2;
234
      }
235

    
236
    TBSkewb.fillInQuats(quats,perm,twists);
237
    }
238

    
239
///////////////////////////////////////////////////////////////////////////////////////////////////
240

    
241
  public int tablebaseIndex(TwistyObject object)
242
    {
243
    int[][] corners= new int[8][3];
244
    int[] centers  = new int[6];
245
    int[] twist    = new int[8];
246
    int[] freePerm = new int[4];
247
    int[] quats    = new int[8];
248

    
249
    getCorners(object,corners);
250

    
251
    int result1 = computeFaceColors(corners,mFaceColors);
252
    if( result1<0 ) return result1;
253

    
254
    int result2 = checkAllCornersPresent(corners);
255
    if( result2<0 ) return result2;
256

    
257
    getCenters(object,centers);
258
    int result3 = checkAllCentersPresent(centers);
259
    if( result3<0 ) return result3;
260
/*
261
for(int i=0; i<8; i++)
262
  for(int j=0; j<3; j++) android.util.Log.e("D", "corner "+i+" face "+j+" : "+corners[i][j]);
263

    
264
for(int i=0; i<6; i++) android.util.Log.e("D", "center "+i+" : "+centers[i]);
265
for(int i=0; i<6; i++) android.util.Log.e("D", "face "+i+" : "+mFaceColors[i]);
266
*/
267
    if( !TablebaseHelpers.permutationIsEven(centers) ) return ERROR_TWO_CENTERS;
268
    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(centers);
269

    
270
    int result4 = retFreeCornerPermutation(freePerm,corners);
271
    if( result4<0 ) return result4;
272

    
273
    computeCornerQuats(quats,corners,freePerm);
274
    TBSkewb.computeCornerTwists(twist,quats);
275
/*
276
for(int i=0; i<4; i++) android.util.Log.e("D", "perm "+i+" : "+freePerm[i]);
277
for(int i=0; i<8; i++) android.util.Log.e("D", "quat "+i+" : "+quats[i]);
278
for(int i=0; i<8; i++) android.util.Log.e("D", "twist "+i+" : "+twist[i]);
279
*/
280
    int total = twist[1]+twist[2]+twist[4]+twist[7];
281
    if( (total%3)!=0 ) return ERROR_CORNER_TWISTED;
282
    int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
283

    
284
    int locationOfFree0 = TBSkewb.computeLocation(0,quats[1]);
285

    
286
    return center_perm_num+ 360*(totalTwist + 2187*locationOfFree0);
287
    }
288

    
289
///////////////////////////////////////////////////////////////////////////////////////////////////
290

    
291
  private int getColorIndex2(int face)
292
    {
293
    switch(mFaceColors[face])
294
      {
295
      case 0: return R.string.color_yellow2;
296
      case 1: return R.string.color_white2;
297
      case 2: return R.string.color_blue2;
298
      case 3: return R.string.color_green2;
299
      case 4: return R.string.color_red2;
300
      case 5: return R.string.color_orange2;
301
      }
302

    
303
    return -1;
304
    }
305

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

    
308
  private int getColorIndex3(int face)
309
    {
310
    switch(mFaceColors[face])
311
      {
312
      case 0: return R.string.color_yellow3;
313
      case 1: return R.string.color_white3;
314
      case 2: return R.string.color_blue3;
315
      case 3: return R.string.color_green3;
316
      case 4: return R.string.color_red3;
317
      case 5: return R.string.color_orange3;
318
      }
319

    
320
    return -1;
321
    }
322

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

    
325
  private int getColorIndex4(int face)
326
    {
327
    switch(mFaceColors[face])
328
      {
329
      case 0: return R.string.color_yellow4;
330
      case 1: return R.string.color_white4;
331
      case 2: return R.string.color_blue4;
332
      case 3: return R.string.color_green4;
333
      case 4: return R.string.color_red4;
334
      case 5: return R.string.color_orange4;
335
      }
336

    
337
    return -1;
338
    }
339

    
340
///////////////////////////////////////////////////////////////////////////////////////////////////
341

    
342
  private String cornerError(Resources res, int face0, int face1, int face2)
343
    {
344
    int j0 = getColorIndex3(face0);
345
    int j1 = getColorIndex3(face1);
346
    int j2 = getColorIndex4(face2);
347

    
348
    String c0 = res.getString(j0);
349
    String c1 = res.getString(j1);
350
    String c2 = res.getString(j2);
351

    
352
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
353
    }
354

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

    
357
  private String centerError(Resources res, int face)
358
    {
359
    int color = getColorIndex2(face);
360
    String clr= res.getString(color);
361
    return res.getString(R.string.solver_generic_missing_center,clr);
362
    }
363

    
364
///////////////////////////////////////////////////////////////////////////////////////////////////
365

    
366
  public String error(int index, Resources res)
367
    {
368
    switch(index)
369
      {
370
      case ERROR_CORNER_135_MISSING: return cornerError(res,1,3,5);
371
      case ERROR_CORNER_134_MISSING: return cornerError(res,1,3,4);
372
      case ERROR_CORNER_125_MISSING: return cornerError(res,1,2,5);
373
      case ERROR_CORNER_124_MISSING: return cornerError(res,1,2,4);
374
      case ERROR_CORNER_035_MISSING: return cornerError(res,0,3,5);
375
      case ERROR_CORNER_034_MISSING: return cornerError(res,0,3,4);
376
      case ERROR_CORNER_025_MISSING: return cornerError(res,0,2,5);
377
      case ERROR_CORNER_024_MISSING: return cornerError(res,0,2,4);
378

    
379
      case ERROR_CENTER_0_MISSING  : return centerError(res,0);
380
      case ERROR_CENTER_1_MISSING  : return centerError(res,1);
381
      case ERROR_CENTER_2_MISSING  : return centerError(res,2);
382
      case ERROR_CENTER_3_MISSING  : return centerError(res,3);
383
      case ERROR_CENTER_4_MISSING  : return centerError(res,4);
384
      case ERROR_CENTER_5_MISSING  : return centerError(res,5);
385

    
386
      case ERROR_CORNERS_CANNOT    : return res.getString(R.string.solver_generic_corners_cannot);
387
      case ERROR_CORNER_TWISTED    : return res.getString(R.string.solver_generic_corner_twist);
388
      case ERROR_TWO_CENTERS       : return res.getString(R.string.solver_generic_two_centers);
389
      case ERROR_TWO_CORNERS       : return res.getString(R.string.solver_generic_two_corners);
390
      }
391

    
392
    return null;
393
    }
394

    
395
///////////////////////////////////////////////////////////////////////////////////////////////////
396

    
397
  public int[][] solution(int index, Resources res)
398
    {
399
    if( mSolver==null )
400
      {
401
      mSolver = ImplementedTablebasesList.createPacked(res,ObjectSignatures.SKEW_2);
402
/*
403
      if( mSolver!=null )
404
        {
405
        mSolver.createTablebase(-1);
406
        mSolver.pack();
407
       //mSolver.test();
408
        }
409

    
410
 */
411
      }
412

    
413
    return mSolver!=null ? mSolver.solution(index,null) : null;
414
    }
415
}  
416

    
(10-10/12)