Project

General

Profile

« Previous | Next » 

Revision 94ce8e53

Added by Leszek Koltunski 10 months ago

Properly define and separate the interface between the App and the 'solver' part of the objectlib. Move the 'position verifiers' to the objectlib.

View differences:

src/main/java/org/distorted/dialogs/RubikDialogSolverView.java
9 9

  
10 10
package org.distorted.dialogs;
11 11

  
12
import android.content.res.Resources;
13 12
import android.util.TypedValue;
14 13
import android.view.View;
15 14
import android.widget.Button;
......
19 18
import org.distorted.main.R;
20 19
import org.distorted.objectlib.helpers.OperatingSystemInterface;
21 20
import org.distorted.objectlib.main.TwistyObject;
22
import org.distorted.solvers.SolvingList;
23
import org.distorted.solvers.SolvingThread;
21
import org.distorted.objectlib.solvers.verifiers.SolverAbstract;
22
import org.distorted.objectlib.solvers.verifiers.SolvingList;
23
import org.distorted.solverui.ScreenList;
24
import org.distorted.solverui.ScreenSolver;
24 25
import org.distorted.solverui.SolverActivity;
25 26

  
26 27
///////////////////////////////////////////////////////////////////////////////////////////////////
......
56 57
        dialog.dismiss();
57 58
        SolvingList list = SolvingList.getSolver(solverOrdinal);
58 59
        OperatingSystemInterface os = act.getInterface();
59
        Resources res = act.getResources();
60 60
        TwistyObject object = act.getObject();
61
        SolvingThread solver = new SolvingThread( os,res,object,list );
62
        solver.start();
61
        SolverAbstract solver = list.create(os,object);
62
        ScreenSolver screen = (ScreenSolver)ScreenList.SVER.getScreenClass();
63

  
64
        if( solver!=null )
65
          {
66
          int[] result = solver.validatePosition(object);
67
          if( result[0]>=0 ) solver.solve(screen,result);
68
          else screen.displayImpossibleDialog(result,solver.getFaceColors());
69
          }
70
        else screen.displayErrorDialog(act.getString(R.string.solver_generic_not_implemented));
63 71
        }
64 72
      });
65 73

  
src/main/java/org/distorted/dialogs/RubikDialogSolvers.java
23 23
import org.distorted.main.R;
24 24
import org.distorted.objectlib.metadata.ListObjects;
25 25
import org.distorted.solverui.SolverActivity;
26
import org.distorted.solvers.SolvingList;
26
import org.distorted.objectlib.solvers.verifiers.SolvingList;
27 27

  
28 28
///////////////////////////////////////////////////////////////////////////////////////////////////
29 29

  
src/main/java/org/distorted/objects/RubikObject.java
27 27
import org.distorted.objectlib.metadata.ListObjects;
28 28
import org.distorted.objectlib.metadata.Metadata;
29 29
import org.distorted.objectlib.patterns.RubikPatternList;
30
import org.distorted.solvers.SolvingList;
30
import org.distorted.objectlib.solvers.verifiers.SolvingList;
31 31

  
32 32
///////////////////////////////////////////////////////////////////////////////////////////////////
33 33

  
src/main/java/org/distorted/solvers/SolverAlgorithmic.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2024 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.objectlib.algsolvers.SolutionListener;
15
import org.distorted.objectlib.algsolvers.SolvedObject;
16
import org.distorted.objectlib.algsolvers.implemented.PhasedSolver3x3Beginner;
17
import org.distorted.objectlib.algsolvers.implemented.PhasedSolverAbstract;
18
import org.distorted.objectlib.helpers.OperatingSystemInterface;
19
import org.distorted.objectlib.main.TwistyObject;
20
import org.distorted.solverui.ScreenList;
21
import org.distorted.solverui.ScreenPhasedSolution;
22
import org.distorted.solverui.ScreenSolver;
23

  
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25

  
26
public abstract class SolverAlgorithmic implements SolvingInterface, SolutionListener
27
{
28
  private final SolvedObject mSolvedObject;
29
  private final PhasedSolverAbstract mSolver;
30
  private final OperatingSystemInterface mOS;
31
  private final Resources mRes;
32
  private final TwistyObject mObject;
33
  private long mTime;
34
  private ScreenSolver mScreen;
35

  
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37
// PUBLIC API
38
///////////////////////////////////////////////////////////////////////////////////////////////////
39

  
40
  public SolverAlgorithmic(OperatingSystemInterface os, Resources res, TwistyObject object)
41
    {
42
    mOS     = os;
43
    mRes    = res;
44
    mObject = object;
45
    mSolver = new PhasedSolver3x3Beginner();
46
    mSolvedObject = mSolver.getObject();
47
    }
48

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

  
51
  abstract int[] validatePosition(TwistyObject object);
52
  abstract String getError(Resources res);
53

  
54
///////////////////////////////////////////////////////////////////////////////////////////////////
55

  
56
  public void solve(ScreenSolver screen)
57
    {
58
    mScreen = screen;
59
    int[] quats = validatePosition(mObject);
60

  
61
    if( quats!=null )
62
      {
63
      int numPhases = mSolver.getNumPhases();
64
      String[] names = new String[numPhases];
65
      for(int p=0; p<numPhases; p++) names[p] = mSolver.getPhaseName(p);
66
      ScreenPhasedSolution solScreen = (ScreenPhasedSolution) ScreenList.PHAS.getScreenClass();
67
      solScreen.updateNames(names);
68
      mTime = System.currentTimeMillis();
69
      mSolver.solution(this,quats);
70
      }
71
    else
72
      {
73
      String error = getError(mRes);
74
      screen.displayImpossibleDialog(error);
75
      }
76
    }
77

  
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79

  
80
  public void receiveSolution(int[] solution, int phaseNumber)
81
    {
82
    if( solution==null )
83
      {
84
      String message = "Phase "+phaseNumber+": FAIL";
85
      System.out.println(message);
86
      }
87
    else
88
      {
89
      int numMoves = solution[0];
90
      int[][] moves = new int[numMoves][];
91
      int index = 0;
92

  
93
      for(int m=1; m<=numMoves; m++)
94
        moves[index++] = mSolvedObject.findMove(solution[m]);
95

  
96
      int[][] subphases = mSolver.getSubPhases(phaseNumber);
97
      mScreen.setSolved(moves,phaseNumber,subphases);
98
      }
99

  
100
    long time = System.currentTimeMillis();
101
    long diff = time - mTime;
102
    mTime = time;
103

  
104
    System.out.println("Phase "+phaseNumber+" solved in "+diff+"ms. Moves: "+(solution==null ? 0:solution[0]));
105
    }
106
}  
107

  
src/main/java/org/distorted/solvers/SolverAlgorithmicCUBE3.java
1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2024 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.objectlib.helpers.OperatingSystemInterface;
15
import org.distorted.objectlib.main.TwistyObject;
16
import org.distorted.solverui.SolverActivity;
17

  
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

  
20
public class SolverAlgorithmicCUBE3 extends SolverAlgorithmic
21
{
22
  public SolverAlgorithmicCUBE3(OperatingSystemInterface os, Resources res, TwistyObject object)
23
    {
24
    super(os,res,object);
25
    }
26

  
27
///////////////////////////////////////////////////////////////////////////////////////////////////
28

  
29
  int[] validatePosition(TwistyObject object)
30
    {
31
    int numCubits = object.getNumCubits();
32
    int[] ret = new int[numCubits];   // mockup
33
    return ret;
34
    }
35

  
36
///////////////////////////////////////////////////////////////////////////////////////////////////
37

  
38
  String getError(Resources res)
39
    {
40
    return null;
41
    }
42
}  
43

  
src/main/java/org/distorted/solvers/SolverKociembaCUBE3.java
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.solverui.ScreenSolver;
17
import org.distorted.objectlib.main.TwistyObject;
18
import org.distorted.objectlib.kociemba.SolverSearch;
19

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

  
22
public class SolverKociembaCUBE3 implements SolvingInterface
23
{
24
  private final Resources mRes;
25
  private final OperatingSystemInterface mOS;
26
  private final TwistyObject mObject;
27
  private int mColorID;
28

  
29
///////////////////////////////////////////////////////////////////////////////////////////////////
30

  
31
  private int mapCubitToFace(int cubit, int face)
32
    {
33
    if( cubit<8 )
34
      {
35
      switch(face)
36
        {
37
        case 0: return 1;
38
        case 1: if( cubit==2 ) return 5;
39
                if( cubit==1 ) return 3;
40
                return 1;
41
        case 2: return cubit==7 ? 5 : 3;
42
        case 3: if( cubit==1 ) return 1;
43
                return cubit==4 ? 5 : 3;
44
        case 4: return cubit==7 ? 3 : 5;
45
        case 5: if( cubit==2 ) return 1;
46
                if( cubit==4 ) return 3;
47
                return 5;
48
        }
49
      }
50

  
51
    if( cubit>19 ) return 4;
52

  
53
    switch(face)
54
      {
55
      case 0: return cubit==15 || cubit==18 ? 3 : 5;
56
      case 1: return cubit==13 || cubit==16 ? 3 : 5;
57
      case 2: return cubit==10              ? 5 : 3;
58
      case 3: return cubit== 8              ? 3 : 5;
59
      case 4: return cubit== 9              ? 3 : 5;
60
      case 5: return cubit== 8              ? 5 : 3;
61
      }
62

  
63
    return -1;
64
    }
65

  
66
///////////////////////////////////////////////////////////////////////////////////////////////////
67

  
68
  private int checkPosition(String position)
69
    {
70
    int[] numColors = new int[6];
71
    int len = position.length();
72

  
73
    for(int i=0; i<len; i++)
74
      {
75
      char ch = position.charAt(i);
76

  
77
      switch(ch)
78
        {
79
        case 'R': numColors[0]++; break;
80
        case 'L': numColors[1]++; break;
81
        case 'U': numColors[2]++; break;
82
        case 'D': numColors[3]++; break;
83
        case 'F': numColors[4]++; break;
84
        case 'B': numColors[5]++; break;
85
        }
86
      }
87

  
88
    if( numColors[0]<9 ) { mColorID = R.string.color_yellow1; return numColors[0]; }
89
    if( numColors[1]<9 ) { mColorID = R.string.color_white1 ; return numColors[1]; }
90
    if( numColors[2]<9 ) { mColorID = R.string.color_blue1  ; return numColors[2]; }
91
    if( numColors[3]<9 ) { mColorID = R.string.color_green1 ; return numColors[3]; }
92
    if( numColors[4]<9 ) { mColorID = R.string.color_red1   ; return numColors[4]; }
93
    if( numColors[5]<9 ) { mColorID = R.string.color_orange1; return numColors[5]; }
94

  
95
    return -1;
96
    }
97

  
98
///////////////////////////////////////////////////////////////////////////////////////////////////
99
// order: Up --> Right --> Front --> Down --> Left --> Back
100
// (because the first implemented Solver - the two-phase Cube3 one - expects such order)
101
//
102
// Solved 3x3x3 Cube maps to "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB"
103

  
104
  private String preparePosition()
105
    {
106
    StringBuilder objectString = new StringBuilder();
107

  
108
    final int R = 0;
109
    final int L = 1;
110
    final int U = 2;
111
    final int D = 3;
112
    final int F = 4;
113
    final int B = 5;
114

  
115
    // 'I' - interior, theoretically can happen
116
    final char[] FACE_NAMES = { 'R', 'L', 'U', 'D', 'F', 'B', 'I'};
117

  
118
    final int[] U_INDEX = { 2,10, 6,17,22,19, 3,11, 7};
119
    final int[] R_INDEX = { 7,19, 6,15,20,14, 5,18, 4};
120
    final int[] F_INDEX = { 3,11, 7,13,24,15, 1, 9, 5};
121
    final int[] D_INDEX = { 1, 9, 5,16,23,18, 0, 8, 4};
122
    final int[] L_INDEX = { 2,17, 3,12,21,13, 0,16, 1};
123
    final int[] B_INDEX = { 6,10, 2,14,25,12, 4, 8, 0};
124

  
125
    for(int i=0; i<9; i++)
126
      {
127
      int face = mapCubitToFace(U_INDEX[i],U);
128
      int color = mObject.getCubitFaceStickerIndex(U_INDEX[i], face);
129
      objectString.append(FACE_NAMES[color]);
130
      }
131
    for(int i=0; i<9; i++)
132
      {
133
      int face = mapCubitToFace(R_INDEX[i],R);
134
      int color = mObject.getCubitFaceStickerIndex(R_INDEX[i], face);
135
      objectString.append(FACE_NAMES[color]);
136
      }
137
    for(int i=0; i<9; i++)
138
      {
139
      int face = mapCubitToFace(F_INDEX[i],F);
140
      int color = mObject.getCubitFaceStickerIndex(F_INDEX[i], face);
141
      objectString.append(FACE_NAMES[color]);
142
      }
143
    for(int i=0; i<9; i++)
144
      {
145
      int face = mapCubitToFace(D_INDEX[i],D);
146
      int color = mObject.getCubitFaceStickerIndex(D_INDEX[i], face);
147
      objectString.append(FACE_NAMES[color]);
148
      }
149
    for(int i=0; i<9; i++)
150
      {
151
      int face = mapCubitToFace(L_INDEX[i],L);
152
      int color = mObject.getCubitFaceStickerIndex(L_INDEX[i], face);
153
      objectString.append(FACE_NAMES[color]);
154
      }
155
    for(int i=0; i<9; i++)
156
      {
157
      int face = mapCubitToFace(B_INDEX[i],B);
158
      int color = mObject.getCubitFaceStickerIndex(B_INDEX[i], face);
159
      objectString.append(FACE_NAMES[color]);
160
      }
161

  
162
    return objectString.toString();
163
    }
164

  
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166
// PUBLIC API
167
///////////////////////////////////////////////////////////////////////////////////////////////////
168

  
169
  public SolverKociembaCUBE3(OperatingSystemInterface os, Resources res, TwistyObject object)
170
    {
171
    mRes   = res;
172
    mOS    = os;
173
    mObject= object;
174
    }
175

  
176
///////////////////////////////////////////////////////////////////////////////////////////////////
177

  
178
  public void solve(ScreenSolver solver)
179
    {
180
    String result;
181

  
182
    SolverSearch.prepare(mOS);
183
    String objectPosition = preparePosition();
184
    int check = checkPosition(objectPosition);
185

  
186
    if( check<0 )
187
      {
188
      result = SolverSearch.solution(objectPosition, 24, 20);
189

  
190
      if( result.contains("Error") )
191
        {
192
        switch( result.charAt(result.length()-1) )
193
          {
194
          case '1': result = mRes.getString(R.string.solver_cube3_error1); break;
195
          case '2': result = mRes.getString(R.string.solver_cube3_error2); break;
196
          case '3': result = mRes.getString(R.string.solver_generic_edge_twist); break;
197
          case '4': result = mRes.getString(R.string.solver_cube3_error4); break;
198
          case '5': result = mRes.getString(R.string.solver_generic_corner_twist); break;
199
          case '6': result = mRes.getString(R.string.solver_cube3_error6); break;
200
          case '7': result = mRes.getString(R.string.solver_cube3_error7); break;
201
          case '8': result = mRes.getString(R.string.solver_cube3_error8); break;
202
          case '9': result = mRes.getString(R.string.solver_cube3_error9); break;
203
          }
204

  
205
        solver.displayImpossibleDialog(result);
206
        }
207
      else
208
        {
209
        solver.setSolved(result);
210
        }
211
      }
212
    else
213
      {
214
      String color = mRes.getString(mColorID);
215
      result = mRes.getString(R.string.solver_cube3_error1,check,color);
216
      solver.displayImpossibleDialog(result);
217
      }
218
    }
219
}  
220

  
src/main/java/org/distorted/solvers/SolverTablebase.java
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.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.ImplementedTablebasesList;
18
import org.distorted.objectlib.tablebases.TablebasesAbstract;
19
import org.distorted.solverui.ScreenSolver;
20

  
21
///////////////////////////////////////////////////////////////////////////////////////////////////
22

  
23
public abstract class SolverTablebase implements SolvingInterface
24
{
25
  private static final int[][] colorsHex =
26
    {
27
      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
28
      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
29
      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
30
      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
31
      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
32
      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
33
    };
34
  private static final int[][] colorsTet =
35
    {
36
      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
37
      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
38
      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
39
      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
40
    };
41
  private static final int[][] colorsOct =
42
    {
43
      {R.string.color_violet1,R.string.color_violet2,R.string.color_violet3,R.string.color_violet4,R.string.color_violet5,R.string.color_violet6,R.string.color_violet7 },
44
      {R.string.color_grey1  ,R.string.color_grey2  ,R.string.color_grey3  ,R.string.color_grey4  ,R.string.color_grey5  ,R.string.color_grey6  ,R.string.color_grey7   },
45
      {R.string.color_blue1  ,R.string.color_blue2  ,R.string.color_blue3  ,R.string.color_blue4  ,R.string.color_blue5  ,R.string.color_blue6  ,R.string.color_blue7   },
46
      {R.string.color_red1   ,R.string.color_red2   ,R.string.color_red3   ,R.string.color_red4   ,R.string.color_red5   ,R.string.color_red6   ,R.string.color_red7    },
47
      {R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
48
      {R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7  },
49
      {R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7  },
50
      {R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
51
    };
52

  
53
  private final OperatingSystemInterface mOS;
54
  private final Resources mRes;
55
  private final TwistyObject mObject;
56
  private TablebasesAbstract mSolver;
57

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

  
60
  public abstract int tablebaseIndex(TwistyObject object);
61
  public abstract String error(int index, Resources res);
62

  
63
///////////////////////////////////////////////////////////////////////////////////////////////////
64
// PUBLIC API
65
///////////////////////////////////////////////////////////////////////////////////////////////////
66

  
67
  public SolverTablebase(OperatingSystemInterface os, Resources res, TwistyObject object)
68
    {
69
    mOS    = os;
70
    mRes   = res;
71
    mObject= object;
72
    }
73

  
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

  
76
  int getHexColor(int color,int variant) { return colorsHex[color][variant]; }
77
  int getTetColor(int color,int variant) { return colorsTet[color][variant]; }
78
  int getOctColor(int color,int variant) { return colorsOct[color][variant]; }
79
  int[] getExtra() { return null; }
80

  
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

  
83
  public void solve(ScreenSolver screen)
84
    {
85
    int index = tablebaseIndex(mObject);
86

  
87
    if( index>=0 )
88
      {
89
      if( mSolver==null )
90
        {
91
        mSolver = ImplementedTablebasesList.createPacked(mOS, mObject.getShortName() );
92
        }
93

  
94
      mSolver.initialize();
95
      int[][] moves = mSolver!=null ? mSolver.solution(index,getExtra(),mOS) : null;
96
      screen.setSolved(moves);
97
      }
98
    else
99
      {
100
      String error = error(index,mRes);
101
      screen.displayImpossibleDialog(error);
102
      }
103
    }
104
}  
105

  
src/main/java/org/distorted/solvers/SolverTablebaseCU232.java
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.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.TablebaseHelpers;
18

  
19
///////////////////////////////////////////////////////////////////////////////////////////////////
20

  
21
public class SolverTablebaseCU232 extends SolverTablebase
22
{
23
  private static final int ERROR_CORNER_MISSING = -1;
24
  private static final int ERROR_EDGE_MISSING   = -2;
25
  private static final int ERROR_CORNERS_CANNOT = -3;
26
  private static final int ERROR_EDGE_TWISTED   = -4;
27
  private static final int ERROR_CORNER_TWISTED = -5;
28

  
29
  private final int[] mFaceColors;
30
  private int mErrColor1, mErrColor2, mErrColor3;
31

  
32
///////////////////////////////////////////////////////////////////////////////////////////////////
33

  
34
  private int edgeIs(int[] edge, int i0, int i1)
35
    {
36
    int c0 = mFaceColors[i0];
37
    int c1 = mFaceColors[i1];
38

  
39
    if( edge[0]==c0 && edge[1]==c1 ) return 0;
40
    if( edge[0]==c1 && edge[1]==c0 ) return 1;
41
    return 2;
42
    }
43

  
44
///////////////////////////////////////////////////////////////////////////////////////////////////
45

  
46
  private int retEdgePermutation(int[] output, int[][] edges)
47
    {
48
    for(int i=0; i<4; i++) output[i] = -1;
49

  
50
    for(int i=0; i<4; i++)
51
      {
52
      int edge0 = edgeIs(edges[i],1,5);
53
           if( edge0==0 ) output[0]=i;
54
      else if( edge0==1 ) return ERROR_EDGE_TWISTED;
55

  
56
      int edge1 = edgeIs(edges[i],1,4);
57
           if( edge1==0 ) output[1]=i;
58
      else if( edge1==1 ) return ERROR_EDGE_TWISTED;
59

  
60
      int edge2 = edgeIs(edges[i],0,5);
61
           if( edge2==0 ) output[2]=i;
62
      else if( edge2==1 ) return ERROR_EDGE_TWISTED;
63

  
64
      int edge3 = edgeIs(edges[i],0,4);
65
           if( edge3==0 ) output[3]=i;
66
      else if( edge3==1 ) return ERROR_EDGE_TWISTED;
67
      }
68

  
69
    if( output[0]==-1 ) { mErrColor1=1; mErrColor2=5; return ERROR_EDGE_MISSING; }
70
    if( output[1]==-1 ) { mErrColor1=1; mErrColor2=4; return ERROR_EDGE_MISSING; }
71
    if( output[2]==-1 ) { mErrColor1=0; mErrColor2=5; return ERROR_EDGE_MISSING; }
72
    if( output[3]==-1 ) { mErrColor1=0; mErrColor2=4; return ERROR_EDGE_MISSING; }
73

  
74
    return 0;
75
    }
76

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

  
79
  private int cornerIs(int[] corner, int i0, int i1, int i2)
80
    {
81
    int c0 = mFaceColors[i0];
82
    int c1 = mFaceColors[i1];
83
    int c2 = mFaceColors[i2];
84

  
85
    if( corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) return 0;
86

  
87
    if( corner[0]==c0 && corner[1]==c2 && corner[2]==c1 ||
88
        corner[0]==c1 && corner[1]==c0 && corner[2]==c2 ||
89
        corner[0]==c1 && corner[1]==c2 && corner[2]==c0 ||
90
        corner[0]==c2 && corner[1]==c0 && corner[2]==c1 ||
91
        corner[0]==c2 && corner[1]==c1 && corner[2]==c0  ) return 1;
92

  
93
    return 2;
94
    }
95

  
96
///////////////////////////////////////////////////////////////////////////////////////////////////
97

  
98
  private int retCornerPermutation(int[] output, int[][] corners)
99
    {
100
    for(int i=0; i<8; i++) output[i] = -1;
101

  
102
    for(int i=0; i<8; i++)
103
      {
104
      int corner7 = cornerIs(corners[i],2,4,0);
105
           if( corner7==0 ) output[7]=i;
106
      else if( corner7==1 ) return ERROR_CORNER_TWISTED;
107

  
108
      int corner6 = cornerIs(corners[i],2,0,5);
109
           if( corner6==0 ) output[6]=i;
110
      else if( corner6==1 ) return ERROR_CORNER_TWISTED;
111

  
112
      int corner5 = cornerIs(corners[i],3,0,4);
113
           if( corner5==0 ) output[5]=i;
114
      else if( corner5==1 ) return ERROR_CORNER_TWISTED;
115

  
116
      int corner4 = cornerIs(corners[i],3,5,0);
117
           if( corner4==0 ) output[4]=i;
118
      else if( corner4==1 ) return ERROR_CORNER_TWISTED;
119

  
120
      int corner3 = cornerIs(corners[i],2,1,4);
121
           if( corner3==0 ) output[3]=i;
122
      else if( corner3==1 ) return ERROR_CORNER_TWISTED;
123

  
124
      int corner2 = cornerIs(corners[i],2,5,1);
125
           if( corner2==0 ) output[2]=i;
126
      else if( corner2==1 ) return ERROR_CORNER_TWISTED;
127

  
128
      int corner1 = cornerIs(corners[i],3,4,1);
129
           if( corner1==0 ) output[1]=i;
130
      else if( corner1==1 ) return ERROR_CORNER_TWISTED;
131

  
132
      int corner0 = cornerIs(corners[i],3,1,5);
133
           if( corner0==0 ) output[0]=i;
134
      else if( corner0==1 ) return ERROR_CORNER_TWISTED;
135
      }
136

  
137
    if( output[0]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
138
    if( output[1]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
139
    if( output[2]==-1 ) { mErrColor1=1; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
140
    if( output[3]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
141
    if( output[4]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
142
    if( output[5]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
143
    if( output[6]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
144
    if( output[7]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
145

  
146
    return 0;
147
    }
148

  
149
////////////////////////////////////////////////////////////////////////////////////////
150

  
151
  private int computeFaceColors(int[][] corners, int[][] edges)
152
    {
153
    mFaceColors[1] = edges[1][0];
154
    mFaceColors[4] = edges[1][1];
155

  
156
         if( edges[0][0]==mFaceColors[1] ) mFaceColors[5] = edges[0][1];
157
    else if( edges[2][0]==mFaceColors[1] ) mFaceColors[5] = edges[2][1];
158
    else if( edges[3][0]==mFaceColors[1] ) mFaceColors[5] = edges[3][1];
159
    else return ERROR_EDGE_TWISTED;
160

  
161
         if( edges[0][1]==mFaceColors[4] ) mFaceColors[0] = edges[0][0];
162
    else if( edges[2][1]==mFaceColors[4] ) mFaceColors[0] = edges[2][0];
163
    else if( edges[3][1]==mFaceColors[4] ) mFaceColors[0] = edges[3][0];
164
    else return ERROR_EDGE_TWISTED;
165

  
166
    boolean found2 = false;
167
    boolean found3 = false;
168

  
169
    for(int c=0; c<8; c++)
170
      {
171
      if( !found3 && corners[c][1]==mFaceColors[4] && corners[c][2]==mFaceColors[1] )
172
        {
173
        found3=true;
174
        mFaceColors[3] = corners[c][0];
175
        }
176
      if( !found2 && corners[c][1]==mFaceColors[1] && corners[c][2]==mFaceColors[4] )
177
        {
178
        found2=true;
179
        mFaceColors[2] = corners[c][0];
180
        }
181
      }
182

  
183
    if( !found2 || !found3 ) return ERROR_CORNERS_CANNOT;
184

  
185
    for(int i=0; i<6; i++)
186
      for(int j=i+1; j<6; j++)
187
        if( mFaceColors[i]==mFaceColors[j] ) return ERROR_CORNERS_CANNOT;
188

  
189
    return 0;
190
    }
191

  
192
///////////////////////////////////////////////////////////////////////////////////////////////////
193

  
194
  private int[] correctEdgePerm(int[] perm)
195
    {
196
    int[] ret = new int[3];
197

  
198
    ret[0] = perm[0];
199
    ret[1] = perm[2];
200
    ret[2] = perm[3];
201

  
202
    if( ret[0]>1 ) ret[0]--;
203
    if( ret[1]>1 ) ret[1]--;
204
    if( ret[2]>1 ) ret[2]--;
205

  
206
    return ret;
207
    }
208

  
209
///////////////////////////////////////////////////////////////////////////////////////////////////
210

  
211
  public SolverTablebaseCU232(OperatingSystemInterface os, Resources res, TwistyObject object)
212
    {
213
    super(os,res,object);
214
    mFaceColors = new int[6];
215
    }
216

  
217
///////////////////////////////////////////////////////////////////////////////////////////////////
218

  
219
  public int tablebaseIndex(TwistyObject object)
220
    {
221
    int[][] corners= new int[8][3];
222
    int[][] edges  = new int[4][2];
223

  
224
    corners[0][0] = object.getCubitFaceStickerIndex(0,3);
225
    corners[0][1] = object.getCubitFaceStickerIndex(0,1);
226
    corners[0][2] = object.getCubitFaceStickerIndex(0,5);
227

  
228
    corners[1][0] = object.getCubitFaceStickerIndex(1,1);
229
    corners[1][1] = object.getCubitFaceStickerIndex(1,5);
230
    corners[1][2] = object.getCubitFaceStickerIndex(1,3);
231

  
232
    corners[2][0] = object.getCubitFaceStickerIndex(2,3);
233
    corners[2][1] = object.getCubitFaceStickerIndex(2,1);
234
    corners[2][2] = object.getCubitFaceStickerIndex(2,5);
235

  
236
    corners[3][0] = object.getCubitFaceStickerIndex(3,3);
237
    corners[3][1] = object.getCubitFaceStickerIndex(3,1);
238
    corners[3][2] = object.getCubitFaceStickerIndex(3,5);
239

  
240
    corners[4][0] = object.getCubitFaceStickerIndex(4,5);
241
    corners[4][1] = object.getCubitFaceStickerIndex(4,3);
242
    corners[4][2] = object.getCubitFaceStickerIndex(4,1);
243

  
244
    corners[5][0] = object.getCubitFaceStickerIndex(5,3);
245
    corners[5][1] = object.getCubitFaceStickerIndex(5,1);
246
    corners[5][2] = object.getCubitFaceStickerIndex(5,5);
247

  
248
    corners[6][0] = object.getCubitFaceStickerIndex(6,3);
249
    corners[6][1] = object.getCubitFaceStickerIndex(6,1);
250
    corners[6][2] = object.getCubitFaceStickerIndex(6,5);
251

  
252
    corners[7][0] = object.getCubitFaceStickerIndex(7,5);
253
    corners[7][1] = object.getCubitFaceStickerIndex(7,3);
254
    corners[7][2] = object.getCubitFaceStickerIndex(7,1);
255

  
256
    edges[0][0] = object.getCubitFaceStickerIndex(8,5);
257
    edges[0][1] = object.getCubitFaceStickerIndex(8,3);
258
    edges[1][0] = object.getCubitFaceStickerIndex(9,3);
259
    edges[1][1] = object.getCubitFaceStickerIndex(9,5);
260
    edges[2][0] = object.getCubitFaceStickerIndex(10,5);
261
    edges[2][1] = object.getCubitFaceStickerIndex(10,3);
262
    edges[3][0] = object.getCubitFaceStickerIndex(11,3);
263
    edges[3][1] = object.getCubitFaceStickerIndex(11,5);
264

  
265
    int result0 = computeFaceColors(corners, edges);
266
    if( result0<0 ) return result0;
267

  
268
    int[] corner_perm = new int[8];
269
    int result1 = retCornerPermutation(corner_perm,corners);
270
    if( result1<0 ) return result1;
271

  
272
    int[] edge_perm = new int[4];
273
    int result2 = retEdgePermutation(edge_perm,edges);
274
    if( result2<0 ) return result2;
275

  
276
    int[] edge_perm2 = correctEdgePerm(edge_perm); // edge1 is fixed!
277

  
278
    int corner_perm_num = TablebaseHelpers.computePermutationNum(corner_perm);
279
    int edge_perm_num = TablebaseHelpers.computePermutationNum(edge_perm2);
280

  
281
    return edge_perm_num + 6*corner_perm_num;
282
    }
283

  
284
///////////////////////////////////////////////////////////////////////////////////////////////////
285

  
286
  private String edgeError(Resources res, int face0, int face1)
287
    {
288
    int j0 = getHexColor(face0,3);
289
    int j1 = getHexColor(face1,6);
290

  
291
    String c0 = res.getString(j0);
292
    String c1 = res.getString(j1);
293

  
294
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
295
    }
296

  
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

  
299
  private String cornerError(Resources res, int face0, int face1, int face2)
300
    {
301
    int j0 = getHexColor(face0,3);
302
    int j1 = getHexColor(face1,3);
303
    int j2 = getHexColor(face2,4);
304

  
305
    String c0 = res.getString(j0);
306
    String c1 = res.getString(j1);
307
    String c2 = res.getString(j2);
308

  
309
    return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2);
310
    }
311

  
312
///////////////////////////////////////////////////////////////////////////////////////////////////
313

  
314
  public String error(int index, Resources res)
315
    {
316
    switch(index)
317
      {
318
      case ERROR_CORNER_MISSING: return cornerError(res,mErrColor1,mErrColor2,mErrColor3);
319
      case ERROR_EDGE_MISSING  : return edgeError(res,mErrColor1,mErrColor2);
320
      case ERROR_CORNERS_CANNOT: return res.getString(R.string.solver_generic_corners_cannot);
321
      case ERROR_EDGE_TWISTED  : return res.getString(R.string.solver_generic_edge_twist);
322
      case ERROR_CORNER_TWISTED: return res.getString(R.string.solver_generic_corner_twist);
323
      }
324

  
325
    return null;
326
    }
327
}  
328

  
src/main/java/org/distorted/solvers/SolverTablebaseCU323.java
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.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.TBCuboid323;
18
import org.distorted.objectlib.tablebases.TablebaseHelpers;
19

  
20
///////////////////////////////////////////////////////////////////////////////////////////////////
21
// a few cu_323 max (depth 18) indices: 1180633, 1180642, 1182044, 1190482, 128151851, 128190028
22

  
23
public class SolverTablebaseCU323 extends SolverTablebase
24
{
25
  private static final int ERROR_CORNER_MISSING = -1;
26
  private static final int ERROR_EDGE_MISSING   = -2;
27
  private static final int ERROR_CORNERS_CANNOT = -3;
28
  private static final int ERROR_EDGE_TWISTED   = -4;
29
  private static final int ERROR_CORNER_TWISTED = -5;
30

  
31
  private final int[] mFaceColors;
32
  private int mErrColor1, mErrColor2, mErrColor3;
33

  
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35

  
36
  public SolverTablebaseCU323(OperatingSystemInterface os, Resources res, TwistyObject object)
37
    {
38
    super(os,res,object);
39
    mFaceColors = new int[6];
40
    }
41

  
42
////////////////////////////////////////////////////////////////////////////////////////
43

  
44
  private int findCorner(int[][] corners, int c1, int c2)
45
    {
46
    for(int i=0; i<8; i++)
47
      {
48
      int[] c = corners[i];
49

  
50
      if( c[0]==c1 && c[1]==c2 ) return c[2];
51
      if( c[1]==c1 && c[2]==c2 ) return c[0];
52
      if( c[2]==c1 && c[0]==c2 ) return c[1];
53
      }
54

  
55
    return ERROR_CORNERS_CANNOT;
56
    }
57

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

  
60
  private int missingColor()
61
    {
62
    boolean[] present = new boolean[6];
63
    for(int i=0; i<5; i++) present[mFaceColors[i]] = true;
64

  
65
    int indexFalse = -1;
66

  
67
    for(int i=0; i<6; i++)
68
      if( !present[i] )
69
        {
70
        if( indexFalse<0 ) indexFalse=i;
71
        else return ERROR_CORNERS_CANNOT;
72
        }
73

  
74
    return indexFalse;
75
    }
76

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

  
79
  private int edgePresent(int[][] edges, int f0, int f1)
80
    {
81
    int c0 = mFaceColors[f0];
82
    int c1 = mFaceColors[f1];
83

  
84
    for(int i=0; i<8; i++ )
85
      {
86
      int[] edge = edges[i];
87

  
88
      if( edge[0]==c0 && edge[1]==c1 ) return i;
89
      if( edge[0]==c1 && edge[1]==c0 )
90
        {
91
        mErrColor1 = c0;
92
        mErrColor2 = c1;
93
        return ERROR_EDGE_TWISTED;
94
        }
95
      }
96

  
97
    mErrColor1 = c0;
98
    mErrColor2 = c1;
99
    return ERROR_EDGE_MISSING;
100
    }
101

  
102
////////////////////////////////////////////////////////////////////////////////////////
103

  
104
  private int cornerPresent(int[][] corners, int f0, int f1, int f2)
105
    {
106
    int c0 = mFaceColors[f0];
107
    int c1 = mFaceColors[f1];
108
    int c2 = mFaceColors[f2];
109

  
110
    for(int i=0; i<8; i++)
111
      {
112
      int[] corner = corners[i];
113

  
114
      if(  corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) return i;
115
      if( (corner[0]==c1 && corner[1]==c2 && corner[2]==c0 ) ||
116
          (corner[0]==c2 && corner[1]==c0 && corner[2]==c1 )  )
117
        {
118
        mErrColor1 = c0;
119
        mErrColor2 = c1;
120
        mErrColor3 = c2;
121
        return ERROR_CORNER_TWISTED;
122
        }
123
      }
124

  
125
    mErrColor1 = c0;
126
    mErrColor2 = c1;
127
    mErrColor3 = c2;
128
    return ERROR_CORNER_MISSING;
129
    }
130

  
131
////////////////////////////////////////////////////////////////////////////////////////
132

  
133
  private int retEdgePermutation(int[] output, int[][] edges)
134
    {
135
    int[][] e = { {5,3}, {4,3}, {5,2}, {4,2}, {1,3}, {1,2}, {0,3}, {0,2} };
136

  
137
    for(int i=0; i<8; i++)
138
      {
139
      int[] ee = e[i];
140
      output[i] = edgePresent(edges,ee[0],ee[1]);
141
      if( output[i]<0 ) return output[i];
142
      }
143

  
144
    return 0;
145
    }
146

  
147
////////////////////////////////////////////////////////////////////////////////////////
148

  
149
  private int retCornerPermutation(int[] output, int[][] corners)
150
    {
151
    int[][] c = { {5,1,3}, {1,4,3}, {1,5,2}, {4,1,2}, {0,5,3}, {4,0,3}, {5,0,2}, {0,4,2} };
152

  
153
    for(int i=0; i<8; i++)
154
      {
155
      int[] cc = c[i];
156
      output[i] = cornerPresent(corners,cc[0],cc[1],cc[2]);
157
      if( output[i]<0 ) return output[i];
158
      }
159

  
160
    return 0;
161
    }
162

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

  
165
  private int computeFaceColors(int[][] corners, int[][] edges, int[] centers)
166
    {
167
    mFaceColors[4] = edges[1][0];
168
    mFaceColors[3] = edges[1][1];
169

  
170
         if( centers[0]!=mFaceColors[3] ) mFaceColors[2] = centers[0];
171
    else if( centers[1]!=mFaceColors[3] ) mFaceColors[2] = centers[1];
172
    else return ERROR_CORNERS_CANNOT;
173

  
174
    mFaceColors[0] = findCorner(corners,mFaceColors[4],mFaceColors[2]);
175
    if( mFaceColors[0]<0 ) return mFaceColors[0];
176

  
177
    mFaceColors[1] = findCorner(corners,mFaceColors[2],mFaceColors[4]);
178
    if( mFaceColors[1]<0 ) return mFaceColors[1];
179

  
180
    mFaceColors[5] = missingColor();
181
    if( mFaceColors[5]<0 ) return mFaceColors[5];
182

  
183
    return 0;
184
    }
185

  
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

  
188
  private void getCorners(TwistyObject object, int[][] corners)
189
    {
190
    corners[0][0] = object.getCubitFaceStickerIndex(0,5);
191
    corners[0][1] = object.getCubitFaceStickerIndex(0,1);
192
    corners[0][2] = object.getCubitFaceStickerIndex(0,3);
193

  
194
    corners[1][0] = object.getCubitFaceStickerIndex(1,3);
195
    corners[1][1] = object.getCubitFaceStickerIndex(1,5);
196
    corners[1][2] = object.getCubitFaceStickerIndex(1,1);
197

  
198
    corners[2][0] = object.getCubitFaceStickerIndex(2,5);
199
    corners[2][1] = object.getCubitFaceStickerIndex(2,1);
200
    corners[2][2] = object.getCubitFaceStickerIndex(2,3);
201

  
202
    corners[3][0] = object.getCubitFaceStickerIndex(3,5);
203
    corners[3][1] = object.getCubitFaceStickerIndex(3,1);
204
    corners[3][2] = object.getCubitFaceStickerIndex(3,3);
205

  
206
    corners[4][0] = object.getCubitFaceStickerIndex(4,1);
207
    corners[4][1] = object.getCubitFaceStickerIndex(4,3);
208
    corners[4][2] = object.getCubitFaceStickerIndex(4,5);
209

  
210
    corners[5][0] = object.getCubitFaceStickerIndex(5,5);
211
    corners[5][1] = object.getCubitFaceStickerIndex(5,1);
212
    corners[5][2] = object.getCubitFaceStickerIndex(5,3);
213

  
214
    corners[6][0] = object.getCubitFaceStickerIndex(6,5);
215
    corners[6][1] = object.getCubitFaceStickerIndex(6,1);
216
    corners[6][2] = object.getCubitFaceStickerIndex(6,3);
217

  
218
    corners[7][0] = object.getCubitFaceStickerIndex(7,1);
219
    corners[7][1] = object.getCubitFaceStickerIndex(7,3);
220
    corners[7][2] = object.getCubitFaceStickerIndex(7,5);
221
    }
222

  
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

  
225
  private void getEdges(TwistyObject object, int[][] edges)
226
    {
227
    edges[0][0] = object.getCubitFaceStickerIndex(8,5);
228
    edges[0][1] = object.getCubitFaceStickerIndex(8,3);
229
    edges[1][0] = object.getCubitFaceStickerIndex(9,3);
230
    edges[1][1] = object.getCubitFaceStickerIndex(9,5);
231
    edges[2][0] = object.getCubitFaceStickerIndex(10,3);
232
    edges[2][1] = object.getCubitFaceStickerIndex(10,5);
233
    edges[3][0] = object.getCubitFaceStickerIndex(11,5);
234
    edges[3][1] = object.getCubitFaceStickerIndex(11,3);
235
    edges[4][0] = object.getCubitFaceStickerIndex(12,3);
236
    edges[4][1] = object.getCubitFaceStickerIndex(12,5);
237
    edges[5][0] = object.getCubitFaceStickerIndex(13,5);
238
    edges[5][1] = object.getCubitFaceStickerIndex(13,3);
239
    edges[6][0] = object.getCubitFaceStickerIndex(14,3);
240
    edges[6][1] = object.getCubitFaceStickerIndex(14,5);
241
    edges[7][0] = object.getCubitFaceStickerIndex(15,5);
242
    edges[7][1] = object.getCubitFaceStickerIndex(15,3);
243
    }
244

  
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246

  
247
  private void getCenters(TwistyObject object, int[] centers)
248
    {
249
    centers[0] = object.getCubitFaceStickerIndex(16,4);
250
    centers[1] = object.getCubitFaceStickerIndex(17,4);
251
    }
252

  
253
///////////////////////////////////////////////////////////////////////////////////////////////////
254

  
255
  public int tablebaseIndex(TwistyObject object)
256
    {
257
    int[][] corners= new int[8][3];
258
    int[][] edges  = new int[8][2];
259
    int[] centers  = new int[2];
260

  
261
    getCorners(object,corners);
262
    getEdges(object,edges);
263
    getCenters(object,centers);
264

  
265
//for(int i=0; i<8; i++) android.util.Log.e("D", "corner: "+i+" : "+corners[i][0]+" "+corners[i][1]+" "+corners[i][2]);
266
//for(int i=0; i<8; i++) android.util.Log.e("D", "edge: "+i+" : "+edges[i][0]+" "+edges[i][1]);
267

  
268
    int result0 = computeFaceColors(corners, edges, centers);
269
    if( result0<0 ) return result0;
270

  
271
    int[] corner_perm = new int[8];
272
    int result1 = retCornerPermutation(corner_perm,corners);
273
    if( result1<0 ) return result1;
274

  
275
//android.util.Log.e("D", "upper: "+mUpper);
276
//for(int i=0; i<6; i++) android.util.Log.e("D", "face color: "+mFaceColors[i]);
277

  
278
    int[] edge_perm8 = new int[8];
279
    int result2 = retEdgePermutation(edge_perm8,edges);
280
    if( result2<0 ) return result2;
281

  
282
    int[] edge_perm7 = TBCuboid323.edgePermTo7(edge_perm8);
283
/*
284
    TablebaseHelpers.displayTable(corner_perm, "CORNER PERM");
285
    TablebaseHelpers.displayTable(edge_perm8, "EDGE PERM8");
286
    TablebaseHelpers.displayTable(edge_perm7, "EDGE PERM7");
287
*/
288
    int corner_perm_num = TablebaseHelpers.computePermutationNum(corner_perm);
289
    int edge_perm_num = TablebaseHelpers.computePermutationNum(edge_perm7);
290
    int centersInPlace = (centers[0]==mFaceColors[2]) ? 0 : 1;
291

  
292
//android.util.Log.e("D", "corner_perm_num: "+corner_perm_num+" edge_perm_num: "+edge_perm_num+" inPlace: "+centersInPlace);
293
//android.util.Log.e("D", "index="+(corner_perm_num + 40320*( centersInPlace + 2*edge_perm_num)));
294

  
295
    return corner_perm_num + 40320*( centersInPlace + 2*edge_perm_num);
296
    }
297

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

  
300
  private String edgeTwistedError(Resources res, int color0, int color1)
301
    {
302
    int j0 = getHexColor(color0,3);
303
    int j1 = getHexColor(color1,6);
304

  
305
    String c0 = res.getString(j0);
306
    String c1 = res.getString(j1);
307

  
308
    return res.getString(R.string.solver_generic_twisted_edge,c0,c1);
309
    }
310

  
311
///////////////////////////////////////////////////////////////////////////////////////////////////
312

  
313
  private String cornerTwistedError(Resources res, int color0, int color1, int color2)
314
    {
315
    int j0 = getHexColor(color0,3);
316
    int j1 = getHexColor(color1,3);
317
    int j2 = getHexColor(color2,5);
318

  
319
    String c0 = res.getString(j0);
320
    String c1 = res.getString(j1);
321
    String c2 = res.getString(j2);
322

  
323
    return res.getString(R.string.solver_generic_twisted_corner,c0,c1,c2);
324
    }
325

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

  
328
  private String edgeMissingError(Resources res, int color0, int color1)
329
    {
330
    int j0 = getHexColor(color0,3);
331
    int j1 = getHexColor(color1,6);
332

  
333
    String c0 = res.getString(j0);
334
    String c1 = res.getString(j1);
335

  
336
    return res.getString(R.string.solver_generic_missing_edge,c0,c1);
337
    }
338

  
339
///////////////////////////////////////////////////////////////////////////////////////////////////
340

  
341
  private String cornerMissingError(Resources res, int color0, int color1, int color2)
342
    {
343
    int j0 = getHexColor(color0,3);
344
    int j1 = getHexColor(color1,3);
345
    int j2 = getHexColor(color2,4);
346

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

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

  
354
///////////////////////////////////////////////////////////////////////////////////////////////////
355

  
356
  public String error(int index, Resources res)
357
    {
358
    switch(index)
359
      {
360
      case ERROR_CORNER_MISSING : return cornerMissingError(res,mErrColor1,mErrColor2,mErrColor3);
361
      case ERROR_EDGE_MISSING   : return edgeMissingError(res,mErrColor1,mErrColor2);
362
      case ERROR_CORNERS_CANNOT : return res.getString(R.string.solver_generic_corners_cannot);
363
      case ERROR_EDGE_TWISTED   : return edgeTwistedError(res,mErrColor1,mErrColor2);
364
      case ERROR_CORNER_TWISTED : return cornerTwistedError(res,mErrColor1,mErrColor2,mErrColor3);
365
      }
366

  
367
    return null;
368
    }
369
}  
370

  
src/main/java/org/distorted/solvers/SolverTablebaseCUBE2.java
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.main.TwistyObject;
17
import org.distorted.objectlib.tablebases.TablebaseHelpers;
18
import org.distorted.objectlib.tablebases.TBCube2;
19

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

  
22
public class SolverTablebaseCUBE2 extends SolverTablebase
23
{
24
  private static final int ERROR_CORNER_MISSING = -1;
25
  private static final int ERROR_CORNERS_CANNOT = -2;
26
  private static final int ERROR_CORNER_TWISTED = -3;
27

  
28
  private final int[] mFaceColors;
29
  private int mErrColor1, mErrColor2, mErrColor3;
30

  
31
////////////////////////////////////////////////////////////////////////////////////////
32

  
33
  private void fillCornerTwists(int[] output, int[][] corners, int[] perm)
34
    {
35
    for(int i=0; i<8; i++)
36
      {
37
      int[] c = corners[perm[i]];
38

  
39
           if( c[0]==mFaceColors[0] || c[0]==mFaceColors[1] ) output[i] = 0;
40
      else if( c[1]==mFaceColors[0] || c[1]==mFaceColors[1] ) output[i] = 1;
41
      else                                                    output[i] = 2;
42
      }
43
    }
44

  
45
////////////////////////////////////////////////////////////////////////////////////////
46

  
47
  private int cornerIndex(int[][] corners, int i1, int i2, int i3)
48
    {
49
    int c1 = mFaceColors[i1];
50
    int c2 = mFaceColors[i2];
51
    int c3 = mFaceColors[i3];
52

  
53
    for(int i=0; i<8; i++)
54
      {
55
      int[] cor = corners[i];
56

  
57
      if( (cor[0]==c1 && cor[1]==c2 && cor[2]==c3) ||
58
          (cor[0]==c2 && cor[1]==c3 && cor[2]==c1) ||
59
          (cor[0]==c3 && cor[1]==c1 && cor[2]==c2)  ) return i;
60
      }
61

  
62
    return -1;
63
    }
64

  
65
////////////////////////////////////////////////////////////////////////////////////////
66

  
67
  private int retCornerPermutation(int[] output, int[][] corners)
68
    {
69
    for(int i=0; i<8; i++) output[i] = -1;
70

  
71
    output[0] = cornerIndex(corners, 1,2,5);
72
    output[1] = cornerIndex(corners, 1,4,2);
73
    output[2] = cornerIndex(corners, 1,5,3);
74
    output[3] = cornerIndex(corners, 1,3,4);
75
    output[4] = cornerIndex(corners, 0,5,2);
76
    output[5] = cornerIndex(corners, 0,2,4);
77
    output[6] = cornerIndex(corners, 0,3,5);
78
    output[7] = cornerIndex(corners, 0,4,3);
79

  
80
    if( output[0]==-1 ) { mErrColor1=1; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
81
    if( output[1]==-1 ) { mErrColor1=1; mErrColor2=4; mErrColor3=2; return ERROR_CORNER_MISSING; }
82
    if( output[2]==-1 ) { mErrColor1=1; mErrColor2=5; mErrColor3=3; return ERROR_CORNER_MISSING; }
83
    if( output[3]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
84
    if( output[4]==-1 ) { mErrColor1=0; mErrColor2=5; mErrColor3=2; return ERROR_CORNER_MISSING; }
85
    if( output[5]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
86
    if( output[6]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
87
    if( output[7]==-1 ) { mErrColor1=0; mErrColor2=4; mErrColor3=3; return ERROR_CORNER_MISSING; }
88

  
89
    return 0;
90
    }
91

  
92
////////////////////////////////////////////////////////////////////////////////////////
93

  
94
  private int findColor(int[][] corners, int c1, int c2)
95
    {
96
    for(int i=0; i<8; i++)
97
      {
98
      int[] cor = corners[i];
99

  
100
      if( cor[0]==c1 && cor[1]==c2 ) return cor[2];
101
      if( cor[1]==c1 && cor[2]==c2 ) return cor[0];
102
      if( cor[2]==c1 && cor[0]==c2 ) return cor[1];
103
      }
104

  
105
    return -1;
106
    }
107

  
108
////////////////////////////////////////////////////////////////////////////////////////
109

  
110
  private int computeFaceColors(int[][] corners)
111
    {
112
    mFaceColors[1] = corners[1][0];
113
    mFaceColors[2] = corners[1][2];
114
    mFaceColors[4] = corners[1][1];
115

  
116
    mFaceColors[0] = findColor(corners,mFaceColors[2],mFaceColors[4]);
117
    mFaceColors[3] = findColor(corners,mFaceColors[4],mFaceColors[1]);
118
    mFaceColors[5] = findColor(corners,mFaceColors[1],mFaceColors[2]);
119

  
120
    for(int i=0; i<6; i++)
121
      {
122
      int color = mFaceColors[i];
123
      if( color<0 ) return ERROR_CORNERS_CANNOT;
124

  
125
      for(int j=i+1; j<6; j++)
126
        if( mFaceColors[j]==color ) return ERROR_CORNERS_CANNOT;
127
      }
128

  
129
    return 0;
130
    }
131

  
132
///////////////////////////////////////////////////////////////////////////////////////////////////
133

  
134
  public SolverTablebaseCUBE2(OperatingSystemInterface os, Resources res, TwistyObject object)
135
    {
136
    super(os,res,object);
137
    mFaceColors = new int[6];
138
    }
139

  
140
///////////////////////////////////////////////////////////////////////////////////////////////////
141

  
142
  private void getCorners(TwistyObject object, int[][] corners)
143
    {
144
    corners[0][0] = object.getCubitFaceStickerIndex(0,1);
145
    corners[0][1] = object.getCubitFaceStickerIndex(0,3);
146
    corners[0][2] = object.getCubitFaceStickerIndex(0,5);
147

  
148
    corners[1][0] = object.getCubitFaceStickerIndex(1,3);
149
    corners[1][1] = object.getCubitFaceStickerIndex(1,5);
150
    corners[1][2] = object.getCubitFaceStickerIndex(1,1);
151

  
152
    corners[2][0] = object.getCubitFaceStickerIndex(2,5);
153
    corners[2][1] = object.getCubitFaceStickerIndex(2,1);
154
    corners[2][2] = object.getCubitFaceStickerIndex(2,3);
155

  
156
    corners[3][0] = object.getCubitFaceStickerIndex(3,1);
157
    corners[3][1] = object.getCubitFaceStickerIndex(3,3);
158
    corners[3][2] = object.getCubitFaceStickerIndex(3,5);
159

  
160
    corners[4][0] = object.getCubitFaceStickerIndex(4,1);
161
    corners[4][1] = object.getCubitFaceStickerIndex(4,3);
162
    corners[4][2] = object.getCubitFaceStickerIndex(4,5);
163

  
164
    corners[5][0] = object.getCubitFaceStickerIndex(5,1);
165
    corners[5][1] = object.getCubitFaceStickerIndex(5,3);
166
    corners[5][2] = object.getCubitFaceStickerIndex(5,5);
167

  
168
    corners[6][0] = object.getCubitFaceStickerIndex(6,1);
169
    corners[6][1] = object.getCubitFaceStickerIndex(6,3);
170
    corners[6][2] = object.getCubitFaceStickerIndex(6,5);
171

  
172
    corners[7][0] = object.getCubitFaceStickerIndex(7,1);
173
    corners[7][1] = object.getCubitFaceStickerIndex(7,3);
174
    corners[7][2] = object.getCubitFaceStickerIndex(7,5);
175
    }
176

  
177
///////////////////////////////////////////////////////////////////////////////////////////////////
178

  
179
  public int tablebaseIndex(TwistyObject object)
180
    {
181
    int[][] corners= new int[8][3];
182
    getCorners(object,corners);
183

  
184
    int result0 = computeFaceColors(corners);
185
    if( result0<0 ) return result0;
186

  
187
    int[] perm = new int[8];
188
    int result1 = retCornerPermutation(perm,corners);
189
    if( result1<0 ) return result1;
190

  
191
    int[] perm7 = TBCube2.shrinkPerm(perm);
192
    int permNum = TablebaseHelpers.computePermutationNum(perm7);
193
    int[] twist = new int[8];
194
    fillCornerTwists(twist,corners,perm);
195

  
196
    int totalTwist = 0;
197
    for(int i=0; i<8; i++) totalTwist += twist[i];
198
    if( ((totalTwist)%3) != 0 ) return ERROR_CORNER_TWISTED;
199

  
200
    int twistNum = twist[0] + 3*(twist[2] + 3*(twist[3] + 3*(twist[4] + 3*(twist[5] + 3*twist[6]))));
201

  
202
    return twistNum + 729*permNum;
203
    }
204

  
205
///////////////////////////////////////////////////////////////////////////////////////////////////
206

  
207
  private String cornerError(Resources res, int face0, int face1, int face2)
208
    {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff