Project

General

Profile

« Previous | Next » 

Revision 94ce8e53

Added by Leszek Koltunski 1 day 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