Project

General

Profile

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

magiccube / src / main / java / org / distorted / solvers / SolverPyraminx.java @ f41d2652

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.ObjectType;
16
import org.distorted.objectlib.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
18
import org.distorted.objectlib.tablebases.TablebasesAbstract;
19

    
20
///////////////////////////////////////////////////////////////////////////////////////////////////
21

    
22
public class SolverPyraminx extends SolverTablebase
23
{
24
  private static final int ERROR_CORNER_GYB_MISSING = -1;
25
  private static final int ERROR_CORNER_GYR_MISSING = -2;
26
  private static final int ERROR_CORNER_GBR_MISSING = -3;
27
  private static final int ERROR_CORNER_YBR_MISSING = -4;
28

    
29
  private static final int ERROR_VERTEX_GYB_MISSING = -5;
30
  private static final int ERROR_VERTEX_GYR_MISSING = -6;
31
  private static final int ERROR_VERTEX_GBR_MISSING = -7;
32
  private static final int ERROR_VERTEX_YBR_MISSING = -8;
33

    
34
  private static final int ERROR_EDGE_RB_MISSING = -9;
35
  private static final int ERROR_EDGE_RY_MISSING = -10;
36
  private static final int ERROR_EDGE_RG_MISSING = -11;
37
  private static final int ERROR_EDGE_YB_MISSING = -12;
38
  private static final int ERROR_EDGE_GB_MISSING = -13;
39
  private static final int ERROR_EDGE_GY_MISSING = -14;
40

    
41
  private static final int ERROR_CORNERS_CANNOT   = -15;
42
  private static final int ERROR_VERTICES_CANNOT  = -16;
43
  private static final int ERROR_CORNER_TWISTED   = -17;
44
  private static final int ERROR_EDGE_TWISTED     = -18;
45
  private static final int ERROR_C_V_DONT_MATCH   = -19;
46

    
47
  TablebasesAbstract mSolver;
48

    
49
///////////////////////////////////////////////////////////////////////////////////////////////////
50

    
51
  private boolean pieceEqual3(int[] piece, int c1, int c2, int c3)
52
    {
53
    return ( (piece[0]==c1 && piece[1]==c2 && piece[2]==c3) ||
54
             (piece[0]==c1 && piece[2]==c2 && piece[1]==c3) ||
55
             (piece[1]==c1 && piece[0]==c2 && piece[2]==c3) ||
56
             (piece[1]==c1 && piece[2]==c2 && piece[0]==c3) ||
57
             (piece[2]==c1 && piece[1]==c2 && piece[0]==c3) ||
58
             (piece[2]==c1 && piece[0]==c2 && piece[1]==c3)  );
59
    }
60

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

    
63
  private boolean pieceEqual2(int[] piece, int c1, int c2)
64
    {
65
    return ( (piece[0]==c1 && piece[1]==c2) ||
66
             (piece[0]==c2 && piece[1]==c1)  );
67
    }
68

    
69
///////////////////////////////////////////////////////////////////////////////////////////////////
70

    
71
  private int checkAllCornersPresent(int[][] corners)
72
    {
73
    boolean ybr = false;
74
    boolean gbr = false;
75
    boolean gyr = false;
76
    boolean gyb = false;
77

    
78
    for(int i=0; i<4; i++)
79
      {
80
      if( pieceEqual3(corners[i],0,1,2) ) gyb = true;
81
      if( pieceEqual3(corners[i],0,1,3) ) gyr = true;
82
      if( pieceEqual3(corners[i],0,2,3) ) gbr = true;
83
      if( pieceEqual3(corners[i],1,2,3) ) ybr = true;
84
      }
85

    
86
    if( !ybr ) return ERROR_CORNER_YBR_MISSING;
87
    if( !gbr ) return ERROR_CORNER_GBR_MISSING;
88
    if( !gyr ) return ERROR_CORNER_GYR_MISSING;
89
    if( !gyb ) return ERROR_CORNER_GYB_MISSING;
90

    
91
    return 0;
92
    }
93

    
94
///////////////////////////////////////////////////////////////////////////////////////////////////
95

    
96
  private int checkAllVerticesPresent(int[][] vertex)
97
    {
98
    boolean ybr = false;
99
    boolean gbr = false;
100
    boolean gyr = false;
101
    boolean gyb = false;
102

    
103
    for(int i=0; i<4; i++)
104
      {
105
      if( pieceEqual3(vertex[i],0,1,2) ) gyb = true;
106
      if( pieceEqual3(vertex[i],0,1,3) ) gyr = true;
107
      if( pieceEqual3(vertex[i],0,2,3) ) gbr = true;
108
      if( pieceEqual3(vertex[i],1,2,3) ) ybr = true;
109
      }
110

    
111
    if( !ybr ) return ERROR_VERTEX_YBR_MISSING;
112
    if( !gbr ) return ERROR_VERTEX_GBR_MISSING;
113
    if( !gyr ) return ERROR_VERTEX_GYR_MISSING;
114
    if( !gyb ) return ERROR_VERTEX_GYB_MISSING;
115

    
116
    return 0;
117
    }
118

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

    
121
  private int checkAllEdgesPresent(int[][] edges)
122
    {
123
    boolean rb = false;
124
    boolean ry = false;
125
    boolean rg = false;
126
    boolean yb = false;
127
    boolean gb = false;
128
    boolean gy = false;
129

    
130
    for(int i=0; i<6; i++)
131
      {
132
      if( pieceEqual2(edges[i],3,2) ) rb = true;
133
      if( pieceEqual2(edges[i],3,1) ) ry = true;
134
      if( pieceEqual2(edges[i],3,0) ) rg = true;
135
      if( pieceEqual2(edges[i],2,1) ) yb = true;
136
      if( pieceEqual2(edges[i],2,0) ) gb = true;
137
      if( pieceEqual2(edges[i],1,0) ) gy = true;
138
      }
139

    
140
    if( !rb ) return ERROR_EDGE_RB_MISSING;
141
    if( !ry ) return ERROR_EDGE_RY_MISSING;
142
    if( !rg ) return ERROR_EDGE_RG_MISSING;
143
    if( !yb ) return ERROR_EDGE_YB_MISSING;
144
    if( !gb ) return ERROR_EDGE_GB_MISSING;
145
    if( !gy ) return ERROR_EDGE_GY_MISSING;
146

    
147
    return 0;
148
    }
149

    
150
///////////////////////////////////////////////////////////////////////////////////////////////////
151

    
152
  private int[] computeFaceColors(int[][] corners)
153
    {
154
    int[] ret = new int[4];
155

    
156
    for(int i=0; i<4; i++)
157
      for(int j=0; j<4; j++)
158
        if( corners[i][0]!=j && corners[i][1]!=j && corners[i][2]!=j ) ret[i]=j;
159

    
160
    return ret;
161
    }
162

    
163
///////////////////////////////////////////////////////////////////////////////////////////////////
164

    
165
  private int checkAgreement(int[] faces1, int[] faces2)
166
    {
167
    for(int i=0; i<4; i++)
168
      if( faces1[i]!=faces2[i] ) return ERROR_C_V_DONT_MATCH;
169

    
170
    return 0;
171
    }
172

    
173
///////////////////////////////////////////////////////////////////////////////////////////////////
174

    
175
  private int computePieceTwist(int index, int[] corner, int[] faceColor)
176
    {
177
    int twist1=0, twist2=0, twist3=0;
178

    
179
    switch(index)
180
      {
181
      case 0: if( corner[1]==faceColor[1] ) twist1=1;
182
              if( corner[2]==faceColor[1] ) twist1=2;
183
              if( corner[0]==faceColor[2] ) twist2=2;
184
              if( corner[2]==faceColor[2] ) twist2=1;
185
              if( corner[0]==faceColor[3] ) twist3=1;
186
              if( corner[1]==faceColor[3] ) twist3=2;
187
              break;
188
      case 1: if( corner[1]==faceColor[0] ) twist1=1;
189
              if( corner[2]==faceColor[0] ) twist1=2;
190
              if( corner[0]==faceColor[2] ) twist2=1;
191
              if( corner[1]==faceColor[2] ) twist2=2;
192
              if( corner[0]==faceColor[3] ) twist3=2;
193
              if( corner[2]==faceColor[3] ) twist3=1;
194
              break;
195
      case 2: if( corner[1]==faceColor[0] ) twist1=1;
196
              if( corner[2]==faceColor[0] ) twist1=2;
197
              if( corner[0]==faceColor[1] ) twist2=2;
198
              if( corner[2]==faceColor[1] ) twist2=1;
199
              if( corner[0]==faceColor[3] ) twist3=1;
200
              if( corner[1]==faceColor[3] ) twist3=2;
201
              break;
202
      case 3: if( corner[1]==faceColor[0] ) twist1=1;
203
              if( corner[2]==faceColor[0] ) twist1=2;
204
              if( corner[0]==faceColor[1] ) twist2=1;
205
              if( corner[1]==faceColor[1] ) twist2=2;
206
              if( corner[0]==faceColor[2] ) twist3=2;
207
              if( corner[2]==faceColor[2] ) twist3=1;
208
              break;
209
      }
210

    
211
    return ( twist1!=twist2 || twist1!=twist3 ) ? -1 : twist1;
212
    }
213

    
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215

    
216
  private int computeEdgePermutation(int[] edge_permutation, int[][] edges)
217
    {
218

    
219
    }
220

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

    
223
  public SolverPyraminx(Resources res, TwistyObject object)
224
    {
225
    super(res,object);
226
    }
227

    
228
///////////////////////////////////////////////////////////////////////////////////////////////////
229

    
230
  private void getCorners(TwistyObject object, int[][] corners)
231
    {
232
    corners[0][0] = object.getCubitFaceStickerIndex(6,3);  // R
233
    corners[0][1] = object.getCubitFaceStickerIndex(6,2);  // B
234
    corners[0][2] = object.getCubitFaceStickerIndex(6,1);  // Y
235

    
236
    corners[1][0] = object.getCubitFaceStickerIndex(4,3);  // R
237
    corners[1][1] = object.getCubitFaceStickerIndex(4,0);  // G
238
    corners[1][2] = object.getCubitFaceStickerIndex(4,2);  // B
239

    
240
    corners[2][0] = object.getCubitFaceStickerIndex(13,3);  // R
241
    corners[2][1] = object.getCubitFaceStickerIndex(13,1);  // Y
242
    corners[2][2] = object.getCubitFaceStickerIndex(13,0);  // G
243

    
244
    corners[3][0] = object.getCubitFaceStickerIndex(11,0);  // G
245
    corners[3][1] = object.getCubitFaceStickerIndex(11,1);  // Y
246
    corners[3][2] = object.getCubitFaceStickerIndex(11,2);  // B
247
    }
248

    
249
///////////////////////////////////////////////////////////////////////////////////////////////////
250

    
251
  private void getVertices(TwistyObject object, int[][] vertex)
252
    {
253
    vertex[0][0] = object.getCubitFaceStickerIndex(1,5);  // R
254
    vertex[0][1] = object.getCubitFaceStickerIndex(1,7);  // B
255
    vertex[0][2] = object.getCubitFaceStickerIndex(1,2);  // Y
256

    
257
    vertex[1][0] = object.getCubitFaceStickerIndex(0,5);  // R
258
    vertex[1][1] = object.getCubitFaceStickerIndex(0,0);  // G
259
    vertex[1][2] = object.getCubitFaceStickerIndex(0,7);  // B
260

    
261
    vertex[2][0] = object.getCubitFaceStickerIndex(3,5);  // R
262
    vertex[2][1] = object.getCubitFaceStickerIndex(3,2);  // Y
263
    vertex[2][2] = object.getCubitFaceStickerIndex(3,0);  // G
264

    
265
    vertex[3][0] = object.getCubitFaceStickerIndex(2,0);  // G
266
    vertex[3][1] = object.getCubitFaceStickerIndex(2,2);  // Y
267
    vertex[3][2] = object.getCubitFaceStickerIndex(2,7);  // B
268
    }
269

    
270
///////////////////////////////////////////////////////////////////////////////////////////////////
271

    
272
  private void getEdges(TwistyObject object, int[][] edges)
273
    {
274
    edges[0][0] = object.getCubitFaceStickerIndex(5,3);  // R
275
    edges[0][1] = object.getCubitFaceStickerIndex(5,2);  // B
276

    
277
    edges[1][0] = object.getCubitFaceStickerIndex(10,3); // R
278
    edges[1][1] = object.getCubitFaceStickerIndex(10,1); // Y
279

    
280
    edges[2][0] = object.getCubitFaceStickerIndex(9,3);  // R
281
    edges[2][1] = object.getCubitFaceStickerIndex(9,0);  // G
282

    
283
    edges[3][0] = object.getCubitFaceStickerIndex(8,1);  // Y
284
    edges[3][1] = object.getCubitFaceStickerIndex(8,2);  // B
285

    
286
    edges[4][0] = object.getCubitFaceStickerIndex(7,0);  // G
287
    edges[4][1] = object.getCubitFaceStickerIndex(7,2);  // B
288

    
289
    edges[5][0] = object.getCubitFaceStickerIndex(12,0); // G
290
    edges[5][1] = object.getCubitFaceStickerIndex(12,1); // Y
291
    }
292

    
293
///////////////////////////////////////////////////////////////////////////////////////////////////
294

    
295
  public int tablebaseIndex(TwistyObject object)
296
    {
297
    int[][] corners = new int[4][3];
298
    int[][] edges   = new int[6][2];
299
    int[][] vertices= new int[4][3];
300
    int[] corner_twist = new int[4];
301
    int[] vertex_twist = new int[4];
302

    
303
    getCorners(object,corners);
304
    getVertices(object,vertices);
305
    getEdges(object,edges);
306

    
307
    int result1 = checkAllCornersPresent(corners);
308
    if( result1<0 ) return result1;
309

    
310
    int result2 = checkAllVerticesPresent(vertices);
311
    if( result2<0 ) return result2;
312

    
313
    int result3 = checkAllEdgesPresent(edges);
314
    if( result3<0 ) return result3;
315

    
316
    int[] faces1 = computeFaceColors(corners);
317
    int[] faces2 = computeFaceColors(vertices);
318

    
319
    int result4 = checkAgreement(faces1,faces2);
320
    if( result4<0 ) return result4;
321

    
322
    for(int i=0; i<4; i++)
323
      {
324
      corner_twist[i] = computePieceTwist(i,corners[i],faces1);
325
      if( corner_twist[i]<0 ) return ERROR_CORNERS_CANNOT;
326
      }
327

    
328
    for(int i=0; i<4; i++)
329
      {
330
      vertex_twist[i] = computePieceTwist(i,vertices[i],faces1);
331
      if( vertex_twist[i]<0 ) return ERROR_VERTICES_CANNOT;
332
      }
333

    
334
    int[] edge_permutation = new int[6];
335
    int result5 = computeEdgePermutation(edge_permutation,edges);
336
    if( result5<0 ) return result5;
337

    
338
    return 0;
339
    }
340

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

    
343
  private int getColorIndex3(int color)
344
    {
345
    switch(color)
346
      {
347
      case 0: return R.string.color_green3;
348
      case 1: return R.string.color_yellow3;
349
      case 2: return R.string.color_blue3;
350
      case 3: return R.string.color_red3;
351
      }
352

    
353
    return -1;
354
    }
355

    
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357

    
358
  private int getColorIndex4(int color)
359
    {
360
    switch(color)
361
      {
362
      case 0: return R.string.color_green4;
363
      case 1: return R.string.color_yellow4;
364
      case 2: return R.string.color_blue4;
365
      case 3: return R.string.color_red4;
366
      }
367

    
368
    return -1;
369
    }
370

    
371
///////////////////////////////////////////////////////////////////////////////////////////////////
372

    
373
  private int getColorIndex6(int color)
374
    {
375
    switch(color)
376
      {
377
      case 0: return R.string.color_green6;
378
      case 1: return R.string.color_yellow6;
379
      case 2: return R.string.color_blue6;
380
      case 3: return R.string.color_red6;
381
      }
382

    
383
    return -1;
384
    }
385

    
386
///////////////////////////////////////////////////////////////////////////////////////////////////
387

    
388
  private String cornerError(Resources res, int color0, int color1, int color2)
389
    {
390
    int j0 = getColorIndex3(color0);
391
    int j1 = getColorIndex3(color1);
392
    int j2 = getColorIndex4(color2);
393

    
394
    String c0 = res.getString(j0);
395
    String c1 = res.getString(j1);
396
    String c2 = res.getString(j2);
397

    
398
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
399
    }
400

    
401
///////////////////////////////////////////////////////////////////////////////////////////////////
402

    
403
  private String vertexError(Resources res, int color0, int color1, int color2)
404
    {
405
    int j0 = getColorIndex3(color0);
406
    int j1 = getColorIndex3(color1);
407
    int j2 = getColorIndex4(color2);
408

    
409
    String c0 = res.getString(j0);
410
    String c1 = res.getString(j1);
411
    String c2 = res.getString(j2);
412

    
413
    return res.getString(R.string.solver_generic_missing_vertex,c0,c1,c2);
414
    }
415

    
416
///////////////////////////////////////////////////////////////////////////////////////////////////
417

    
418
  private String edgeError(Resources res, int color0, int color1)
419
    {
420
    int j0 = getColorIndex3(color0);
421
    int j1 = getColorIndex6(color1);
422

    
423
    String c0 = res.getString(j0);
424
    String c1 = res.getString(j1);
425

    
426
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
427
    }
428

    
429
///////////////////////////////////////////////////////////////////////////////////////////////////
430

    
431
  public String error(int index, Resources res)
432
    {
433
    switch(index)
434
      {
435
      case ERROR_CORNER_YBR_MISSING: return cornerError(res,3,2,1);
436
      case ERROR_CORNER_GBR_MISSING: return cornerError(res,3,2,0);
437
      case ERROR_CORNER_GYR_MISSING: return cornerError(res,3,1,0);
438
      case ERROR_CORNER_GYB_MISSING: return cornerError(res,2,1,0);
439
      case ERROR_VERTEX_YBR_MISSING: return vertexError(res,3,2,1);
440
      case ERROR_VERTEX_GBR_MISSING: return vertexError(res,3,2,0);
441
      case ERROR_VERTEX_GYR_MISSING: return vertexError(res,3,1,0);
442
      case ERROR_VERTEX_GYB_MISSING: return vertexError(res,2,1,0);
443
      case ERROR_EDGE_RB_MISSING   : return edgeError(res,3,2);
444
      case ERROR_EDGE_RY_MISSING   : return edgeError(res,3,1);
445
      case ERROR_EDGE_RG_MISSING   : return edgeError(res,3,0);
446
      case ERROR_EDGE_YB_MISSING   : return edgeError(res,2,1);
447
      case ERROR_EDGE_GB_MISSING   : return edgeError(res,2,0);
448
      case ERROR_EDGE_GY_MISSING   : return edgeError(res,1,0);
449
      case ERROR_CORNER_TWISTED    : return res.getString(R.string.solver_generic_corner_twist);
450
      case ERROR_EDGE_TWISTED      : return res.getString(R.string.solver_generic_edge_twist);
451
      case ERROR_CORNERS_CANNOT    : return res.getString(R.string.solver_generic_corners_cannot);
452
      case ERROR_VERTICES_CANNOT   : return res.getString(R.string.solver_generic_vertices_cannot);
453
      case ERROR_C_V_DONT_MATCH    : return res.getString(R.string.solver_generic_c_v_dont_match);
454

    
455
      }
456

    
457
    return null;
458
    }
459

    
460
///////////////////////////////////////////////////////////////////////////////////////////////////
461

    
462
  public int[][] solution(int index, Resources res)
463
    {
464
    if( mSolver==null )
465
      {
466
      //mSolver = ImplementedTablebasesList.createPacked(res,ObjectType.PYRA_3);
467
      mSolver = ImplementedTablebasesList.createUnpacked(ObjectType.PYRA_3);
468
      if( mSolver!=null ) mSolver.createTablebase();
469
      }
470

    
471
    return mSolver!=null ? mSolver.solution(index) : null;
472
    }
473
}  
474

    
(6-6/8)