Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverSkewbDiamond.java @ master

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.helpers.OperatingSystemInterface;
16
import org.distorted.objectlib.metadata.ListObjects;
17
import org.distorted.objectlib.main.TwistyObject;
18
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
19
import org.distorted.objectlib.tablebases.TablebaseHelpers;
20
import org.distorted.objectlib.tablebases.TablebasesAbstract;
21

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

    
24
public class SolverSkewbDiamond extends SolverTablebase
25
{
26
  private static final int ERROR_CORNER_FR_MISSING = -1;
27
  private static final int ERROR_CORNER_BR_MISSING = -2;
28
  private static final int ERROR_CORNER_BL_MISSING = -3;
29
  private static final int ERROR_CORNER_FL_MISSING = -4;
30
  private static final int ERROR_CORNER_TO_MISSING = -5;
31
  private static final int ERROR_CORNER_BO_MISSING = -6;
32

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

    
42
  private static final int ERROR_TWO_CORNERS      = -15;
43
  private static final int ERROR_TWO_CENTERS      = -16;
44
  private static final int ERROR_CORNER_TWIST_90  = -17;
45
  private static final int ERROR_CORNER_TWIST_180 = -18;
46
  private static final int ERROR_CORNERS_CANNOT   = -19;
47

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

    
51
  private static final int[] FREE_CENTERS = {0,2,5,7};
52

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

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

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

    
63
  private int retCorner(int[][] corners, int c1, int c2)
64
    {
65
    for(int i=0; i<6; i++)
66
      {
67
      int[] cor = corners[i];
68
      int twist = retCornerTwist(cor,c1,c2);
69
      if( twist>=0 ) return i;
70
      }
71

    
72
    return -1;
73
    }
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

    
77
  private int[] getCornersPermutation(int[][] corners)
78
    {
79
    int[] perm = new int[6];
80

    
81
    perm[0] = retCorner(corners,mFaceColors[1],mFaceColors[4]);
82
    perm[1] = retCorner(corners,mFaceColors[1],mFaceColors[6]);
83
    perm[2] = retCorner(corners,mFaceColors[3],mFaceColors[6]);
84
    perm[3] = retCorner(corners,mFaceColors[3],mFaceColors[4]);
85
    perm[4] = retCorner(corners,mFaceColors[1],mFaceColors[3]);
86
    perm[5] = retCorner(corners,mFaceColors[4],mFaceColors[6]);
87

    
88
    return perm;
89
    }
90

    
91
///////////////////////////////////////////////////////////////////////////////////////////////////
92

    
93
  private int computeCornerTwist(int[] corner, int color )
94
    {
95
    if( corner[3]==color ) return 0;
96
    if( corner[2]==color ) return 1;
97
    if( corner[1]==color ) return 2;
98
    if( corner[0]==color ) return 3;
99

    
100
    return -1;
101
    }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

    
105
  private int[] getCornersTwist(int[] corners_perm, int[][] corners)
106
    {
107
    int[] twist = new int[6];
108

    
109
    twist[0] = computeCornerTwist( corners[corners_perm[0]], mFaceColors[1] );
110
    twist[1] = computeCornerTwist( corners[corners_perm[1]], mFaceColors[1] );
111
    twist[2] = computeCornerTwist( corners[corners_perm[2]], mFaceColors[3] );
112
    twist[3] = computeCornerTwist( corners[corners_perm[3]], mFaceColors[3] );
113
    twist[4] = computeCornerTwist( corners[corners_perm[4]], mFaceColors[1] );
114
    twist[5] = computeCornerTwist( corners[corners_perm[5]], mFaceColors[4] );
115

    
116
    return twist;
117
    }
118

    
119
///////////////////////////////////////////////////////////////////////////////////////////////////
120

    
121
  private int retCenter(int color, int[] centers)
122
    {
123
    for(int i=0; i<4; i++ )
124
      if( centers[FREE_CENTERS[i]]==color ) return i;
125

    
126
    return -1;
127
    }
128

    
129
///////////////////////////////////////////////////////////////////////////////////////////////////
130

    
131
  private int[] getFreeCentersPermutation(int[] centers)
132
    {
133
    int[] perm = new int[4];
134

    
135
    for(int i=0; i<4; i++ )
136
      perm[i] = retCenter(mFaceColors[FREE_CENTERS[i]],centers);
137

    
138
    return perm;
139
    }
140

    
141
///////////////////////////////////////////////////////////////////////////////////////////////////
142

    
143
  private int getTotalTwist(int[] twist)
144
    {
145
    int total = 0;
146
    boolean even = true;
147

    
148
    for(int i=0; i<6; i++)
149
      {
150
      int t= twist[i];
151

    
152
      if( t==1 || t==3 ) return ERROR_CORNER_TWIST_90;
153
      if( t==2 )
154
        {
155
        if( i<5 )
156
          {
157
          total+=(1<<i);
158
          even = !even;
159
          }
160
        else if( even ) return ERROR_CORNER_TWIST_180;
161
        }
162
      }
163

    
164
    return total;
165
    }
166

    
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

    
169
  private int retCornerTwist(int[] corner, int c1, int c2)
170
    {
171
    if( corner[0]==c1 && corner[2]==c2 ) return 1;
172
    if( corner[1]==c1 && corner[3]==c2 ) return 2;
173
    if( corner[2]==c1 && corner[0]==c2 ) return 3;
174
    if( corner[3]==c1 && corner[1]==c2 ) return 0;
175

    
176
    return -1;
177
    }
178

    
179
///////////////////////////////////////////////////////////////////////////////////////////////////
180

    
181
  private int figureOutColor(int[][] corners, int c1, int c2)
182
    {
183
    for(int i=0; i<6; i++)
184
      {
185
      int[] cor = corners[i];
186
      int twist = retCornerTwist(cor,c1,c2);
187
      if( twist>=0 ) return cor[twist];
188
      }
189

    
190
    return -1;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194
// We only move the UR, UR, DR & DB faces --> those centers are fixed and determine the colors of
195
// the faces.
196

    
197
  private int figureOutFaceColors(int[] output, int[] centers, int[][] corners)
198
    {
199
    output[1] = centers[1];
200
    output[3] = centers[3];
201
    output[4] = centers[4];
202
    output[6] = centers[6];
203

    
204
    int color01 = figureOutColor(corners,output[4],output[1]);
205
    if( color01<0 ) return ERROR_CORNER_FR_MISSING;
206
    int color02 = figureOutColor(corners,output[3],output[4]);
207
    if( color02<0 ) return ERROR_CORNER_FL_MISSING;
208
    int color03 = figureOutColor(corners,output[1],output[3]);
209
    if( color03<0 ) return ERROR_CORNER_TO_MISSING;
210
    if( color01!=color02 || color01!=color03 ) return ERROR_CORNERS_CANNOT;
211
    output[0] = color01;
212

    
213
    int color21 = figureOutColor(corners,output[1],output[6]);
214
    if( color21<0 ) return ERROR_CORNER_BR_MISSING;
215
    int color22 = figureOutColor(corners,output[6],output[3]);
216
    if( color22<0 ) return ERROR_CORNER_BL_MISSING;
217
    int color23 = figureOutColor(corners,output[3],output[1]);
218
    if( color23<0 ) return ERROR_CORNER_TO_MISSING;
219
    if( color21!=color22 || color21!=color23 ) return ERROR_CORNERS_CANNOT;
220
    output[2] = color21;
221

    
222
    int color51 = figureOutColor(corners,output[1],output[4]);
223
    if( color51<0 ) return ERROR_CORNER_FR_MISSING;
224
    int color52 = figureOutColor(corners,output[6],output[1]);
225
    if( color52<0 ) return ERROR_CORNER_BR_MISSING;
226
    int color53 = figureOutColor(corners,output[4],output[6]);
227
    if( color53<0 ) return ERROR_CORNER_BO_MISSING;
228
    if( color51!=color52 || color51!=color53 ) return ERROR_CORNERS_CANNOT;
229
    output[5] = color51;
230

    
231
    int color71 = figureOutColor(corners,output[3],output[6]);
232
    if( color71<0 ) return ERROR_CORNER_BL_MISSING;
233
    int color72 = figureOutColor(corners,output[4],output[3]);
234
    if( color72<0 ) return ERROR_CORNER_FL_MISSING;
235
    int color73 = figureOutColor(corners,output[6],output[4]);
236
    if( color73<0 ) return ERROR_CORNER_BO_MISSING;
237
    if( color71!=color72 || color71!=color73 ) return ERROR_CORNERS_CANNOT;
238
    output[7] = color71;
239

    
240
    return 0;
241
    }
242

    
243
///////////////////////////////////////////////////////////////////////////////////////////////////
244

    
245
  private int checkAllColorsDifferent()
246
    {
247
    for(int i=0; i<8; i++)
248
      {
249
      boolean present = false;
250

    
251
      for(int j=0; j<8; j++)
252
        if( mFaceColors[j]==i )
253
          {
254
          present=true;
255
          break;
256
          }
257

    
258
      if( !present ) return ERROR_CORNERS_CANNOT;
259
      }
260

    
261
    return 0;
262
    }
263

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

    
266
  private int checkAllCentersPresent(int[] centers)
267
    {
268
    for(int i=0; i<8; i++)
269
      {
270
      boolean present = false;
271

    
272
      for(int j=0; j<8; j++)
273
        if( centers[j]==i )
274
          {
275
          present=true;
276
          break;
277
          }
278

    
279
      if( !present )
280
        {
281
        switch(i)
282
          {
283
          case 0: return ERROR_CENTER_0_MISSING;
284
          case 1: return ERROR_CENTER_1_MISSING;
285
          case 2: return ERROR_CENTER_2_MISSING;
286
          case 3: return ERROR_CENTER_3_MISSING;
287
          case 4: return ERROR_CENTER_4_MISSING;
288
          case 5: return ERROR_CENTER_5_MISSING;
289
          case 6: return ERROR_CENTER_6_MISSING;
290
          case 7: return ERROR_CENTER_7_MISSING;
291
          }
292
        }
293
      }
294

    
295
    return 0;
296
    }
297

    
298
///////////////////////////////////////////////////////////////////////////////////////////////////
299

    
300
  private void getCorners(TwistyObject object, int[][] corners)
301
    {
302
    corners[0][0] = object.getCubitFaceStickerIndex( 0,5); // FR
303
    corners[0][1] = object.getCubitFaceStickerIndex( 0,4);
304
    corners[0][2] = object.getCubitFaceStickerIndex( 0,0);
305
    corners[0][3] = object.getCubitFaceStickerIndex( 0,1);
306

    
307
    corners[1][0] = object.getCubitFaceStickerIndex( 1,2); // BR
308
    corners[1][1] = object.getCubitFaceStickerIndex( 1,6);
309
    corners[1][2] = object.getCubitFaceStickerIndex( 1,5);
310
    corners[1][3] = object.getCubitFaceStickerIndex( 1,1);
311

    
312
    corners[2][0] = object.getCubitFaceStickerIndex( 2,7); // BL
313
    corners[2][1] = object.getCubitFaceStickerIndex( 2,6);
314
    corners[2][2] = object.getCubitFaceStickerIndex( 2,2);
315
    corners[2][3] = object.getCubitFaceStickerIndex( 2,3);
316

    
317
    corners[3][0] = object.getCubitFaceStickerIndex( 3,0); // FL
318
    corners[3][1] = object.getCubitFaceStickerIndex( 3,4);
319
    corners[3][2] = object.getCubitFaceStickerIndex( 3,7);
320
    corners[3][3] = object.getCubitFaceStickerIndex( 3,3);
321

    
322
    corners[4][0] = object.getCubitFaceStickerIndex( 4,0); // U
323
    corners[4][1] = object.getCubitFaceStickerIndex( 4,3);
324
    corners[4][2] = object.getCubitFaceStickerIndex( 4,2);
325
    corners[4][3] = object.getCubitFaceStickerIndex( 4,1);
326

    
327
    corners[5][0] = object.getCubitFaceStickerIndex( 5,5); // D
328
    corners[5][1] = object.getCubitFaceStickerIndex( 5,6);
329
    corners[5][2] = object.getCubitFaceStickerIndex( 5,7);
330
    corners[5][3] = object.getCubitFaceStickerIndex( 5,4);
331
    }
332

    
333
///////////////////////////////////////////////////////////////////////////////////////////////////
334

    
335
  private void getCenters(TwistyObject object, int[] centers)
336
    {
337
    centers[0] = object.getCubitFaceStickerIndex( 9,0); // UF
338
    centers[1] = object.getCubitFaceStickerIndex( 6,0); // UR
339
    centers[2] = object.getCubitFaceStickerIndex( 7,0); // UB
340
    centers[3] = object.getCubitFaceStickerIndex( 8,0); // UL
341
    centers[4] = object.getCubitFaceStickerIndex(13,0); // DF
342
    centers[5] = object.getCubitFaceStickerIndex(10,1); // DR
343
    centers[6] = object.getCubitFaceStickerIndex(11,0); // DB
344
    centers[7] = object.getCubitFaceStickerIndex(12,0); // DL
345
    }
346

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

    
349
  public int tablebaseIndex(TwistyObject object)
350
    {
351
    int[][] corners = new int[6][4];
352
    int[] centers = new int[8];
353

    
354
    getCorners(object,corners);
355
    getCenters(object,centers);
356

    
357
    int result1 = checkAllCentersPresent(centers);
358
    if( result1<0 ) return result1;
359

    
360
    int result2 = figureOutFaceColors(mFaceColors,centers,corners);
361
    if( result2<0 ) return result2;
362

    
363
    int result3 = checkAllColorsDifferent();
364
    if( result3<0 ) return result3;
365

    
366
    int[] corners_perm = getCornersPermutation(corners);
367
    boolean even1 = TablebaseHelpers.permutationIsEven(corners_perm);
368
    if( !even1 ) return ERROR_TWO_CORNERS;
369

    
370
    int[] free_centers_perm = getFreeCentersPermutation(centers);
371
    boolean even2 = TablebaseHelpers.permutationIsEven(free_centers_perm);
372
    if( !even2 ) return ERROR_TWO_CENTERS;
373

    
374
    int[] corners_twist = getCornersTwist(corners_perm, corners);
375
/*
376
android.util.Log.e("D", "faces: "+mFaceColors[0]+" "+mFaceColors[1]+" "+mFaceColors[2]+" "
377
+mFaceColors[3]+" "+mFaceColors[4]+" "+mFaceColors[5]+" "+mFaceColors[6]+" "+mFaceColors[7]);
378

    
379
android.util.Log.e("D", "corn perm: "+corners_perm[0]+" "+corners_perm[1]+" "+corners_perm[2]+" "
380
+corners_perm[3]+" "+corners_perm[4]+" "+corners_perm[5]);
381

    
382
android.util.Log.e("D", "corn twist: "+corners_twist[0]+" "+corners_twist[1]+" "+corners_twist[2]+" "
383
+corners_twist[3]+" "+corners_twist[4]+" "+corners_twist[5]);
384
*/
385
    int totalTwist = getTotalTwist(corners_twist);
386
    if( totalTwist<0 ) return totalTwist;
387

    
388
    int corners_perm_num = TablebaseHelpers.computeEvenPermutationNum(corners_perm);
389
    int centers_perm_num = TablebaseHelpers.computeEvenPermutationNum(free_centers_perm);
390

    
391
    return centers_perm_num + 12*(totalTwist + 32*corners_perm_num);
392
    }
393

    
394
///////////////////////////////////////////////////////////////////////////////////////////////////
395

    
396
  private int getColorIndex4(int face)
397
    {
398
    switch(mFaceColors[face])
399
      {
400
      case 0: return R.string.color_violet4;
401
      case 1: return R.string.color_grey4;
402
      case 2: return R.string.color_blue4;
403
      case 3: return R.string.color_red4;
404
      case 4: return R.string.color_orange4;
405
      case 5: return R.string.color_green4;
406
      case 6: return R.string.color_white4;
407
      case 7: return R.string.color_yellow4;
408
      }
409

    
410
    return -1;
411
    }
412

    
413
///////////////////////////////////////////////////////////////////////////////////////////////////
414

    
415
  private int getColorIndex3(int face)
416
    {
417
    switch(mFaceColors[face])
418
      {
419
      case 0: return R.string.color_violet3;
420
      case 1: return R.string.color_grey3;
421
      case 2: return R.string.color_blue3;
422
      case 3: return R.string.color_red3;
423
      case 4: return R.string.color_orange3;
424
      case 5: return R.string.color_green3;
425
      case 6: return R.string.color_white3;
426
      case 7: return R.string.color_yellow3;
427
      }
428

    
429
    return -1;
430
    }
431

    
432
///////////////////////////////////////////////////////////////////////////////////////////////////
433

    
434
  private int getColorIndex2(int face)
435
    {
436
    switch(face)
437
      {
438
      case 0: return R.string.color_violet2;
439
      case 1: return R.string.color_grey2;
440
      case 2: return R.string.color_blue2;
441
      case 3: return R.string.color_red2;
442
      case 4: return R.string.color_orange2;
443
      case 5: return R.string.color_green2;
444
      case 6: return R.string.color_white2;
445
      case 7: return R.string.color_yellow2;
446
      }
447

    
448
    return -1;
449
    }
450

    
451
///////////////////////////////////////////////////////////////////////////////////////////////////
452

    
453
  private String centerError(Resources res, int face)
454
    {
455
    String color = res.getString(getColorIndex2(face));
456
    return res.getString(R.string.solver_generic_missing_center,color);
457
    }
458

    
459
///////////////////////////////////////////////////////////////////////////////////////////////////
460

    
461
  private String cornerError(Resources res, int f1, int f2)
462
    {
463
    String c1 = res.getString(getColorIndex3(f1));
464
    String c2 = res.getString(getColorIndex4(f2));
465
    return res.getString(R.string.solver_generic_missing_corner2,c1,c2);
466
    }
467

    
468
///////////////////////////////////////////////////////////////////////////////////////////////////
469

    
470
  public String error(int index, Resources res)
471
    {
472
    switch(index)
473
      {
474
      case ERROR_CORNER_FR_MISSING: return cornerError(res,1,4);
475
      case ERROR_CORNER_BR_MISSING: return cornerError(res,1,6);
476
      case ERROR_CORNER_BL_MISSING: return cornerError(res,3,6);
477
      case ERROR_CORNER_FL_MISSING: return cornerError(res,3,4);
478
      case ERROR_CORNER_TO_MISSING: return cornerError(res,1,3);
479
      case ERROR_CORNER_BO_MISSING: return cornerError(res,4,6);
480

    
481
      case ERROR_CENTER_0_MISSING : return centerError(res,0);
482
      case ERROR_CENTER_1_MISSING : return centerError(res,1);
483
      case ERROR_CENTER_2_MISSING : return centerError(res,2);
484
      case ERROR_CENTER_3_MISSING : return centerError(res,3);
485
      case ERROR_CENTER_4_MISSING : return centerError(res,4);
486
      case ERROR_CENTER_5_MISSING : return centerError(res,5);
487
      case ERROR_CENTER_6_MISSING : return centerError(res,6);
488
      case ERROR_CENTER_7_MISSING : return centerError(res,7);
489

    
490
      case ERROR_TWO_CORNERS      : return res.getString(R.string.solver_generic_two_corners);
491
      case ERROR_TWO_CENTERS      : return res.getString(R.string.solver_generic_two_centers);
492
      case ERROR_CORNER_TWIST_90  : return res.getString(R.string.solver_generic_corner_twist) + " (90)";
493
      case ERROR_CORNER_TWIST_180 : return res.getString(R.string.solver_generic_corner_twist) + " (180)";
494
      case ERROR_CORNERS_CANNOT   : return res.getString(R.string.solver_generic_corners_cannot);
495
      }
496

    
497
    return null;
498
    }
499

    
500
///////////////////////////////////////////////////////////////////////////////////////////////////
501

    
502
  public int[][] solution(int index, OperatingSystemInterface os)
503
    {
504
    if( mSolver==null )
505
      {
506
      mSolver = ImplementedTablebasesList.createPacked(os, ListObjects.DIAM_2.name());
507
      }
508

    
509
    return mSolver!=null ? mSolver.solution(index,null,os) : null;
510
    }
511
}  
512

    
(15-15/16)