Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverTablebaseSKEW2.java @ c65092dd

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 static org.distorted.objectlib.tablebases.TBSkewb.FIXED;
13
import static org.distorted.objectlib.tablebases.TBSkewb.FREE;
14

    
15
import android.content.res.Resources;
16

    
17
import org.distorted.main.R;
18
import org.distorted.objectlib.helpers.OperatingSystemInterface;
19
import org.distorted.objectlib.main.TwistyObject;
20
import org.distorted.objectlib.tablebases.TBSkewb;
21
import org.distorted.objectlib.tablebases.TablebaseHelpers;
22

    
23
///////////////////////////////////////////////////////////////////////////////////////////////////
24

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

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

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

    
48
  private static final int ERROR_FREE_CORNERS_NOT_EVEN    = -19;
49
  private static final int ERROR_FREE_CORNERS_ROTATED     = -20;
50

    
51
  private final int[] mFaceColors;
52

    
53
///////////////////////////////////////////////////////////////////////////////////////////////////
54

    
55
  public SolverTablebaseSKEW2(OperatingSystemInterface os, Resources res, TwistyObject object)
56
    {
57
    super(os,res,object);
58
    mFaceColors = new int[6];
59
    }
60

    
61
///////////////////////////////////////////////////////////////////////////////////////////////////
62

    
63
  private void getCorners(TwistyObject object, int[][] corners)
64
    {
65
    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
  private void createCenterPermutation(int[] output, int[] symbols, int[] perm)
73
    {
74
    for(int s=0; s<6; s++)
75
      {
76
      int symbol = symbols[s];
77

    
78
      for(int p=0; p<6; p++)
79
        if( perm[p]==symbol )
80
          {
81
          output[s] = p;
82
          break;
83
          }
84
      }
85
    }
86

    
87
///////////////////////////////////////////////////////////////////////////////////////////////////
88

    
89
  private int getCenters(TwistyObject object, int[] out)
90
    {
91
    final int[] map = {4,5,2,3,0,1};
92
    int[] tmp = new int[6];
93
    int[] mcl = new int[6];
94
    boolean[] present = new boolean[6];
95

    
96
    for(int i=0; i<6; i++)
97
      {
98
      int color = object.getCubitFaceStickerIndex(i+8,0) - 6;
99
      present[color] = true;
100
      tmp[i] = color;
101
      }
102

    
103
    if( !present[0] ) return ERROR_CENTER_0_MISSING;
104
    if( !present[1] ) return ERROR_CENTER_1_MISSING;
105
    if( !present[2] ) return ERROR_CENTER_2_MISSING;
106
    if( !present[3] ) return ERROR_CENTER_3_MISSING;
107
    if( !present[4] ) return ERROR_CENTER_4_MISSING;
108
    if( !present[5] ) return ERROR_CENTER_5_MISSING;
109

    
110
    for(int i=0; i<6; i++) mcl[i] = map[mFaceColors[i]];
111
    createCenterPermutation(out,mcl,tmp);
112

    
113
    return 0;
114
    }
115

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

    
118
  private int commonCornerColor(int[] c1, int[] c2)
119
    {
120
    int theSame = 0;
121
    int index   = 0;
122

    
123
    for(int i=0; i<3; i++)
124
      for(int j=0; j<3; j++)
125
        if( c1[i]==c2[j] )
126
          {
127
          index = i;
128
          theSame++;
129
          }
130

    
131
    return theSame==1 ? c1[index] : ERROR_CORNERS_CANNOT;
132
    }
133

    
134
///////////////////////////////////////////////////////////////////////////////////////////////////
135

    
136
  private int computeFaceColors(int[][] corners, int[] output)
137
    {
138
    final int[][] corner_indices = { {0,3},{5,6},{0,5},{6,3},{0,6},{3,5} };
139

    
140
    for(int i=0; i<6; i++)
141
      {
142
      int c1 = corner_indices[i][0];
143
      int c2 = corner_indices[i][1];
144
      output[i] = commonCornerColor(corners[c1],corners[c2]);
145
      if( output[i]<0 ) return ERROR_CORNERS_CANNOT;
146
      }
147

    
148
    return 0;
149
    }
150

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

    
153
  private boolean cornerIs(int[] corner, int f0, int f1, int f2)
154
    {
155
    int c0 = mFaceColors[f0];
156
    int c1 = mFaceColors[f1];
157
    int c2 = mFaceColors[f2];
158

    
159
    return ( (corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) ||
160
             (corner[1]==c0 && corner[2]==c1 && corner[0]==c2 ) ||
161
             (corner[2]==c0 && corner[0]==c1 && corner[1]==c2 )  );
162
    }
163

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

    
166
  private int checkAllCornersPresent(int[][] corners)
167
    {
168
    boolean[] present = new boolean[8];
169

    
170
    for(int i=0; i<8; i++)
171
      {
172
      if( cornerIs(corners[i],4,2,0) ) present[0]=true;
173
      if( cornerIs(corners[i],2,5,0) ) present[1]=true;
174
      if( cornerIs(corners[i],3,4,0) ) present[2]=true;
175
      if( cornerIs(corners[i],5,3,0) ) present[3]=true;
176
      if( cornerIs(corners[i],1,2,4) ) present[4]=true;
177
      if( cornerIs(corners[i],5,2,1) ) present[5]=true;
178
      if( cornerIs(corners[i],4,3,1) ) present[6]=true;
179
      if( cornerIs(corners[i],1,3,5) ) present[7]=true;
180
      }
181

    
182
    if( !present[0] ) return ERROR_CORNER_024_MISSING;
183
    if( !present[1] ) return ERROR_CORNER_025_MISSING;
184
    if( !present[2] ) return ERROR_CORNER_034_MISSING;
185
    if( !present[3] ) return ERROR_CORNER_035_MISSING;
186
    if( !present[4] ) return ERROR_CORNER_124_MISSING;
187
    if( !present[5] ) return ERROR_CORNER_125_MISSING;
188
    if( !present[6] ) return ERROR_CORNER_134_MISSING;
189
    if( !present[7] ) return ERROR_CORNER_135_MISSING;
190

    
191
    return 0;
192
    }
193

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

    
196
  private int retFreeCornerPermutation(int[] perm, int[][] corners)
197
    {
198
    perm[0] = -1;
199
    perm[1] = -1;
200
    perm[2] = -1;
201
    perm[3] = -1;
202

    
203
    for(int i=0; i<4; i++)
204
      {
205
      int[] cor = corners[FREE[i]];
206

    
207
      if( cornerIs(cor,2,5,0) ) perm[0] = i;
208
      if( cornerIs(cor,3,4,0) ) perm[1] = i;
209
      if( cornerIs(cor,1,2,4) ) perm[2] = i;
210
      if( cornerIs(cor,1,3,5) ) perm[3] = i;
211
      }
212

    
213
    if( perm[0]==-1 ) return ERROR_CORNER_025_MISSING;
214
    if( perm[1]==-1 ) return ERROR_CORNER_034_MISSING;
215
    if( perm[2]==-1 ) return ERROR_CORNER_124_MISSING;
216
    if( perm[3]==-1 ) return ERROR_CORNER_135_MISSING;
217

    
218
    return 0;
219
    }
220

    
221
///////////////////////////////////////////////////////////////////////////////////////////////////
222

    
223
  private void computeCornerQuats(int[] quats, int[][] corners, int[] perm)
224
    {
225
    final int[] zeroeth_face_map = { 4,2,3,5,1,5,4,1 };
226
    int[] twist = new int[8];
227

    
228
    for(int i=0; i<4; i++)
229
      {
230
      int fi = FIXED[i];
231
      int colorFi = mFaceColors[zeroeth_face_map[fi]];
232
      int[] cFi = corners[fi];
233

    
234
           if( cFi[0]==colorFi ) twist[fi] = 0;
235
      else if( cFi[1]==colorFi ) twist[fi] = 1;
236
      else                       twist[fi] = 2;
237
      }
238

    
239
    int[] inv_perm = new int[4];
240
    TablebaseHelpers.invertPermutation(perm,inv_perm);
241

    
242
    int common14 = commonCornerColor(corners[1], corners[4]);
243
    int common27 = commonCornerColor(corners[2], corners[7]);
244
    int common47 = commonCornerColor(corners[4], corners[7]);
245
    int index;
246
    int[] c;
247

    
248
    index = FREE[inv_perm[0]];
249
    c = corners[FREE[0]];
250

    
251
         if(c[0]==common14) twist[index] = 0;
252
    else if(c[1]==common14) twist[index] = 2;
253
    else                    twist[index] = 1;
254

    
255
    index = FREE[inv_perm[1]];
256
    c = corners[FREE[1]];
257

    
258
         if(c[0]==common27) twist[index] = 0;
259
    else if(c[1]==common27) twist[index] = 2;
260
    else                    twist[index] = 1;
261

    
262
    index = FREE[inv_perm[2]];
263
    c = corners[FREE[2]];
264

    
265
         if(c[0]==common47) twist[index] = 0;
266
    else if(c[1]==common47) twist[index] = 2;
267
    else                    twist[index] = 1;
268

    
269
    index = FREE[inv_perm[3]];
270
    c = corners[FREE[3]];
271

    
272
         if(c[0]==common47) twist[index] = 0;
273
    else if(c[1]==common47) twist[index] = 2;
274
    else                    twist[index] = 1;
275

    
276
    TBSkewb.fillInQuats(quats,perm,twist);
277
    }
278

    
279
///////////////////////////////////////////////////////////////////////////////////////////////////
280

    
281
  public int tablebaseIndex(TwistyObject object)
282
    {
283
    int[][] corners= new int[8][3];
284
    int[] centers  = new int[6];
285
    int[] twist    = new int[8];
286
    int[] freePerm = new int[4];
287
    int[] quats    = new int[8];
288

    
289
    getCorners(object,corners);
290

    
291
    int result1 = computeFaceColors(corners,mFaceColors);
292
    if( result1<0 ) return result1;
293

    
294
    int result2 = checkAllCornersPresent(corners);
295
    if( result2<0 ) return result2;
296

    
297
    int result3 = getCenters(object,centers);
298
    if( result3<0 ) return result3;
299

    
300
    if( !TablebaseHelpers.permutationIsEven(centers) ) return ERROR_TWO_CENTERS;
301
    int center_perm_num = TablebaseHelpers.computeEvenPermutationNum(centers);
302

    
303
    int result4 = retFreeCornerPermutation(freePerm,corners);
304
    if( result4<0 ) return result4;
305

    
306
    computeCornerQuats(quats,corners,freePerm);
307

    
308
    int[] freeLoc = new int[4];
309
    for(int f=0; f<4; f++) freeLoc[f] = TBSkewb.computeLocation(f,quats[FREE[f]]);
310
    if( !TablebaseHelpers.permutationIsEven(freeLoc) ) return ERROR_FREE_CORNERS_NOT_EVEN;
311

    
312
    TBSkewb.computeCornerTwists(twist,quats);
313

    
314
    int total = 0;
315
    for(int i=0; i<8; i++) total += twist[i];
316
    if( (total%3)!=0 ) return ERROR_CORNER_TWISTED;
317
    int totalTwist = twist[0]+ 3*(twist[1]+ 3*(twist[2]+ 3*(twist[3]+ 3*(twist[4]+ 3*(twist[5]+ 3*twist[6])))));
318

    
319
    int sumFixedTwists = twist[FIXED[0]]+twist[FIXED[1]]+twist[FIXED[2]]+twist[FIXED[3]];
320
    int freeLoc1 = TBSkewb.permFree1(freeLoc[0],sumFixedTwists);
321
    if( freeLoc[1] != freeLoc1 ) return ERROR_FREE_CORNERS_ROTATED;
322

    
323
    return center_perm_num+ 360*(totalTwist + 2187*freeLoc[0]);
324
    }
325

    
326
///////////////////////////////////////////////////////////////////////////////////////////////////
327

    
328
  private String cornerError(Resources res, int face0, int face1, int face2)
329
    {
330
    int j0 = getHexColor(face0,3);
331
    int j1 = getHexColor(face1,3);
332
    int j2 = getHexColor(face2,4);
333

    
334
    String c0 = res.getString(j0);
335
    String c1 = res.getString(j1);
336
    String c2 = res.getString(j2);
337

    
338
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
339
    }
340

    
341
///////////////////////////////////////////////////////////////////////////////////////////////////
342

    
343
  private String centerError(Resources res, int face)
344
    {
345
    int color = getHexColor(face,2);
346
    String clr= res.getString(color);
347
    return res.getString(R.string.solver_generic_missing_center,clr);
348
    }
349

    
350
///////////////////////////////////////////////////////////////////////////////////////////////////
351

    
352
  public String error(int index, Resources res)
353
    {
354
    switch(index)
355
      {
356
      case ERROR_CORNER_135_MISSING   : return cornerError(res,1,3,5);
357
      case ERROR_CORNER_134_MISSING   : return cornerError(res,1,3,4);
358
      case ERROR_CORNER_125_MISSING   : return cornerError(res,1,2,5);
359
      case ERROR_CORNER_124_MISSING   : return cornerError(res,1,2,4);
360
      case ERROR_CORNER_035_MISSING   : return cornerError(res,0,3,5);
361
      case ERROR_CORNER_034_MISSING   : return cornerError(res,0,3,4);
362
      case ERROR_CORNER_025_MISSING   : return cornerError(res,0,2,5);
363
      case ERROR_CORNER_024_MISSING   : return cornerError(res,0,2,4);
364

    
365
      case ERROR_CENTER_0_MISSING     : return centerError(res,0);
366
      case ERROR_CENTER_1_MISSING     : return centerError(res,1);
367
      case ERROR_CENTER_2_MISSING     : return centerError(res,2);
368
      case ERROR_CENTER_3_MISSING     : return centerError(res,3);
369
      case ERROR_CENTER_4_MISSING     : return centerError(res,4);
370
      case ERROR_CENTER_5_MISSING     : return centerError(res,5);
371

    
372
      case ERROR_CORNERS_CANNOT       : return res.getString(R.string.solver_generic_corners_cannot);
373
      case ERROR_CORNER_TWISTED       : return res.getString(R.string.solver_generic_corner_twist);
374
      case ERROR_TWO_CENTERS          : return res.getString(R.string.solver_generic_two_centers);
375
      case ERROR_TWO_CORNERS          : return res.getString(R.string.solver_generic_two_corners);
376

    
377
      case ERROR_FREE_CORNERS_NOT_EVEN: return res.getString(R.string.solver_generic_free_corners_odd);
378
      case ERROR_FREE_CORNERS_ROTATED : return res.getString(R.string.solver_generic_free_corners_rotated);
379
      }
380

    
381
    return null;
382
    }
383
}  
384

    
(14-14/17)