Project

General

Profile

« Previous | Next » 

Revision 149ee2dc

Added by Leszek Koltunski 9 months ago

Clean up everything.
Algorithmic MoveProviders do nto seem to work yet. (3x3 Beginner's OLL phase does not work)

View differences:

src/main/java/org/distorted/objectlib/algphases/Phase.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.objectlib.algphases;
11

  
12
import org.distorted.objectlib.algsolvers.MitmTable;
13
import org.distorted.objectlib.algsolvers.SolvedObject;
14
import org.distorted.objectlib.algsolvers.TargetQuats;
15

  
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17

  
18
abstract public class Phase
19
{
20
  private static final int[] INDICES = {0};
21

  
22
  protected int[][] mCubitGroups;
23
  protected int mNumGroups;
24
  protected int mNumCubitsInThisPhase;
25
  protected int mNumCubits;
26
  protected TargetQuats mTargetQuats;
27

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

  
30
  Phase(SolvedObject object)
31
    {
32
    float[][] pos = object.getCubitPositions();
33
    mNumCubits = pos.length;
34
    }
35

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

  
38
  abstract public void prepareForSubphases();
39
  abstract public int[] findSolution(SolvedObject object, MitmTable table);
40
  abstract public boolean solveAnySubphase(SolvedObject object, MitmTable table, int[][] solution, int solIndex);
41

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

  
44
  public int numSubphases()
45
    {
46
    return mNumGroups;
47
    }
48

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

  
51
  public int whichSubPhase(int cubit)
52
    {
53
    for(int g=0; g<mNumGroups; g++)
54
      for(int j : mCubitGroups[g])
55
        if( cubit==j ) return g;
56

  
57
    return -1;
58
    }
59

  
60
///////////////////////////////////////////////////////////////////////////////////////////////////
61

  
62
  public int[] endQuatIndices(SolvedObject object, int cubit)
63
    {
64
    return INDICES;
65
    }
66

  
67
///////////////////////////////////////////////////////////////////////////////////////////////////
68

  
69
  public void setTargetQuats(SolvedObject object, boolean[] inPreviousPhases)
70
    {
71
    int len = inPreviousPhases.length;
72

  
73
    int[][] target = new int[len][];
74

  
75
    for(int c=0; c<len; c++)
76
      {
77
      if( inPreviousPhases[c] ) target[c] = INDICES;
78
      else if( contains(c) )    target[c] = endQuatIndices(object,c);
79
      else                      target[c] = null;
80
      }
81

  
82
    mTargetQuats = new TargetQuats(target);
83
    }
84

  
85
///////////////////////////////////////////////////////////////////////////////////////////////////
86

  
87
  public boolean contains(int cubit)
88
    {
89
    for(int g=0; g<mNumGroups; g++)
90
      for(int c : mCubitGroups[g])
91
        if( cubit==c ) return true;
92

  
93
    return false;
94
    }
95
}
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicOrie1.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.objectlib.algphases;
11

  
12
import org.distorted.library.helpers.QuatHelper;
13
import org.distorted.library.type.Static4D;
14
import org.distorted.objectlib.algsolvers.SolvedObject;
15

  
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17

  
18
public class PhaseCyclicOrie1 extends PhaseMitm
19
{
20
  private final int mCyclicQuat;
21

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

  
24
  public PhaseCyclicOrie1(SolvedObject object, int cubit, int quat)
25
    {
26
    super(object);
27

  
28
    Static4D[] objectQuats = object.getQuats();
29
    Static4D q = objectQuats[quat];
30
    double alpha = 2*Math.acos(q.get3());
31
    double numTurns = 2*Math.PI / alpha;
32
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
33

  
34
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
35
    mNumGroups = 1;
36
    mCyclicQuat = quat;
37

  
38
    float[][] positions = object.getCubitPositions();
39
    float[] pos = positions[cubit];
40
    float x = pos[0];
41
    float y = pos[1];
42
    float z = pos[2];
43

  
44
    float[] tmp = new float[4];
45

  
46
    mCubitGroups[0][0] = cubit;
47

  
48
    for(int c=1; c<mNumCubitsInThisPhase; c++)
49
      {
50
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
51
      x = tmp[0];
52
      y = tmp[1];
53
      z = tmp[2];
54

  
55
      mCubitGroups[0][c] = whichPosIsThis(positions,tmp);
56
      }
57
    }
58

  
59
///////////////////////////////////////////////////////////////////////////////////////////////////
60

  
61
  private int whichPosIsThis(float[][] positions, float[] pos)
62
    {
63
    int numPos = positions.length;
64
    float minErr = Float.MAX_VALUE;
65
    int ret=-1;
66

  
67
    for(int i=0; i<numPos; i++)
68
      {
69
      float[] curr = positions[i];
70
      float dx = curr[0] - pos[0];
71
      float dy = curr[1] - pos[1];
72
      float dz = curr[2] - pos[2];
73

  
74
      float err = dx*dx + dy*dy + dz*dz;
75

  
76
      if( err < minErr )
77
        {
78
        minErr = err;
79
        ret = i;
80
        }
81
      }
82

  
83
    return ret;
84
    }
85

  
86
///////////////////////////////////////////////////////////////////////////////////////////////////
87

  
88
  @Override
89
  public int[] endQuatIndices(SolvedObject object, int cubit)
90
    {
91
    int[] retQuats = new int[mNumCubitsInThisPhase];
92
    retQuats[0] = 0;
93
    retQuats[1] = mCyclicQuat;
94

  
95
    for(int i=2; i<mNumCubitsInThisPhase; i++)
96
      {
97
      retQuats[i] = object.getMultQuat(mCyclicQuat,retQuats[i-1]);
98
      }
99

  
100
    return retQuats;
101
    }
102
}
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicOrie2.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.objectlib.algphases;
11

  
12
import org.distorted.library.helpers.QuatHelper;
13
import org.distorted.library.type.Static4D;
14
import org.distorted.objectlib.algsolvers.SolvedObject;
15

  
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17

  
18
public class PhaseCyclicOrie2 extends PhaseMitm
19
{
20
  public PhaseCyclicOrie2(SolvedObject object, int cubit, int quat)
21
    {
22
    super(object);
23

  
24
    Static4D[] objectQuats = object.getQuats();
25
    Static4D q = objectQuats[quat];
26
    double alpha = 2*Math.acos(q.get3());
27
    double numTurns = 2*Math.PI / alpha;
28
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
29

  
30
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
31
    mNumGroups = 1;
32

  
33
    float[][] positions = object.getCubitPositions();
34
    float[] pos = positions[cubit];
35
    float x = pos[0];
36
    float y = pos[1];
37
    float z = pos[2];
38

  
39
    float[] tmp = new float[4];
40

  
41
    mCubitGroups[0][0] = cubit;
42

  
43
    for(int c=1; c<mNumCubitsInThisPhase; c++)
44
      {
45
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
46
      x = tmp[0];
47
      y = tmp[1];
48
      z = tmp[2];
49

  
50
      mCubitGroups[0][c] = whichPosIsThis(positions,tmp);
51
      }
52
    }
53

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

  
56
  private int whichPosIsThis(float[][] positions, float[] pos)
57
    {
58
    int numPos = positions.length;
59
    float minErr = Float.MAX_VALUE;
60
    int ret=-1;
61

  
62
    for(int i=0; i<numPos; i++)
63
      {
64
      float[] curr = positions[i];
65
      float dx = curr[0] - pos[0];
66
      float dy = curr[1] - pos[1];
67
      float dz = curr[2] - pos[2];
68

  
69
      float err = dx*dx + dy*dy + dz*dz;
70

  
71
      if( err < minErr )
72
        {
73
        minErr = err;
74
        ret = i;
75
        }
76
      }
77

  
78
    return ret;
79
    }
80
}
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicPerm1.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.objectlib.algphases;
11

  
12
import org.distorted.library.helpers.QuatHelper;
13
import org.distorted.library.type.Static4D;
14
import org.distorted.objectlib.algsolvers.SolvedObject;
15

  
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17

  
18
public class PhaseCyclicPerm1 extends PhaseMitm
19
{
20
  private final Static4D[] mObjectQuats;
21
  private final float[][] mPositions;
22

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

  
25
  public PhaseCyclicPerm1(SolvedObject object, int cubit, int quat)
26
    {
27
    super(object);
28

  
29
    Static4D[] objectQuats = object.getQuats();
30
    Static4D q = objectQuats[quat];
31
    double alpha = 2*Math.acos(q.get3());
32
    double numTurns = 2*Math.PI / alpha;
33
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
34

  
35
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
36
    mNumGroups = 1;
37
    mObjectQuats = objectQuats;
38

  
39
    float[][] positions = object.getCubitPositions();
40
    mPositions = positions;
41
    float[] pos = positions[cubit];
42
    float x = pos[0];
43
    float y = pos[1];
44
    float z = pos[2];
45

  
46
    float[] tmp = new float[4];
47

  
48
    mCubitGroups[0][0] = cubit;
49

  
50
    for(int c=1; c<mNumCubitsInThisPhase; c++)
51
      {
52
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
53
      x = tmp[0];
54
      y = tmp[1];
55
      z = tmp[2];
56

  
57
      mCubitGroups[0][c] = whichPosIsThis(positions,tmp);
58
      }
59
    }
60

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

  
63
  private int whichPosIsThis(float[][] positions, float[] pos)
64
    {
65
    int numPos = positions.length;
66
    float minErr = Float.MAX_VALUE;
67
    int ret=-1;
68

  
69
    for(int i=0; i<numPos; i++)
70
      {
71
      float[] curr = positions[i];
72
      float dx = curr[0] - pos[0];
73
      float dy = curr[1] - pos[1];
74
      float dz = curr[2] - pos[2];
75

  
76
      float err = dx*dx + dy*dy + dz*dz;
77

  
78
      if( err < minErr )
79
        {
80
        minErr = err;
81
        ret = i;
82
        }
83
      }
84

  
85
    return ret;
86
    }
87

  
88
///////////////////////////////////////////////////////////////////////////////////////////////////
89

  
90
  @Override
91
  public int[] endQuatIndices(SolvedObject object, int cubit)
92
    {
93
    float[] thisPos = mPositions[cubit];
94
    int numQuats = mObjectQuats.length;
95
    int numGoodQuats = 0;
96
    int[] tmpQuats = new int[numQuats];
97
    float[] tmp = new float[4];
98
    float x = thisPos[0];
99
    float y = thisPos[1];
100
    float z = thisPos[2];
101
    final float MAX_ERROR = 0.01f;
102

  
103
    for(int q=0; q<numQuats; q++)
104
      {
105
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,mObjectQuats[q]);
106

  
107
      float dx = tmp[0] - x;
108
      float dy = tmp[1] - y;
109
      float dz = tmp[2] - z;
110
      float err = dx*dx + dy*dy + dz*dz;
111

  
112
      if( err < MAX_ERROR )
113
        {
114
        numGoodQuats++;
115
        tmpQuats[q] = 1;
116
        }
117
      }
118

  
119
    int[] ret = new int[numGoodQuats];
120
    int index = 0;
121

  
122
    for(int q=0; q<numQuats; q++)
123
      if( tmpQuats[q]==1 ) ret[index++] = q;
124

  
125
    return ret;
126
    }
127
}
src/main/java/org/distorted/objectlib/algphases/PhaseCyclicPerm2.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.objectlib.algphases;
11

  
12
import org.distorted.library.helpers.QuatHelper;
13
import org.distorted.library.type.Static4D;
14
import org.distorted.objectlib.algsolvers.SolvedObject;
15

  
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17

  
18
public class PhaseCyclicPerm2 extends PhaseMitm
19
{
20
  public PhaseCyclicPerm2(SolvedObject object, int cubit, int quat)
21
    {
22
    super(object);
23

  
24
    Static4D[] objectQuats = object.getQuats();
25
    Static4D q = objectQuats[quat];
26
    double alpha = 2*Math.acos(q.get3());
27
    double numTurns = 2*Math.PI / alpha;
28
    mNumCubitsInThisPhase = (int)(numTurns+0.5f);
29

  
30
    mCubitGroups  = new int[1][mNumCubitsInThisPhase];
31
    mNumGroups = 1;
32

  
33
    float[][] positions = object.getCubitPositions();
34
    float[] pos = positions[cubit];
35
    float x = pos[0];
36
    float y = pos[1];
37
    float z = pos[2];
38

  
39
    float[] tmp = new float[4];
40

  
41
    mCubitGroups[0][0] = cubit;
42

  
43
    for(int c=1; c<mNumCubitsInThisPhase; c++)
44
      {
45
      QuatHelper.rotateVectorByQuat(tmp,x,y,z,1,q);
46
      x = tmp[0];
47
      y = tmp[1];
48
      z = tmp[2];
49

  
50
      mCubitGroups[0][c] = whichPosIsThis(positions,tmp);
51
      }
52
    }
53

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

  
56
  private int whichPosIsThis(float[][] positions, float[] pos)
57
    {
58
    int numPos = positions.length;
59
    float minErr = Float.MAX_VALUE;
60
    int ret=-1;
61

  
62
    for(int i=0; i<numPos; i++)
63
      {
64
      float[] curr = positions[i];
65
      float dx = curr[0] - pos[0];
66
      float dy = curr[1] - pos[1];
67
      float dz = curr[2] - pos[2];
68

  
69
      float err = dx*dx + dy*dy + dz*dz;
70

  
71
      if( err < minErr )
72
        {
73
        minErr = err;
74
        ret = i;
75
        }
76
      }
77

  
78
    return ret;
79
    }
80
}
src/main/java/org/distorted/objectlib/algphases/PhaseMitm.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.objectlib.algphases;
11

  
12
import org.distorted.objectlib.algsolvers.MitmTable;
13
import org.distorted.objectlib.algsolvers.SolvedObject;
14
import org.distorted.objectlib.algsolvers.TargetQuats;
15

  
16
///////////////////////////////////////////////////////////////////////////////////////////////////
17

  
18
abstract public class PhaseMitm extends Phase
19
{
20
  private final static int MAX_MEMORY    = 6*1024*1024;  // 6MB max for the MitM table
21
  private final static double MAX_SEARCH = 10000000.0;   // max 10mln positions back-searched
22

  
23
  private boolean[] mSolved;
24
  private int[] mWhichSubphase;
25
  private int mForwardDepth, mBackwardDepth;
26

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

  
29
  PhaseMitm(SolvedObject object)
30
    {
31
    super(object);
32
    }
33

  
34
///////////////////////////////////////////////////////////////////////////////////////////////////
35
// Only attempt to find solutions which are not longer than maxlen; if not found, return null.
36
// Otherwise, return an array of moves; each move is an index to the MaveTable (see branchingFactor!)
37
//
38
// Algorithm:
39
// Meet in the Middle: first, do a depth-first search and remember each position in a table; depth of
40
// this search - until we fill out no more than MAX_MEMORY in the table.
41
// Then, from each end position (in general there can be many because in many phases there are many
42
// valid endQuats for a given cubit) do a back-search and try to reach any of the positions from the
43
// table.
44

  
45
  private int[] solve(SolvedObject object, MitmTable table, int depth)
46
    {
47
    float tmp = ((float)(mForwardDepth*depth))/(mForwardDepth+mBackwardDepth);
48
    int tmpForward = (int)Math.ceil(tmp);
49
    int tmpBackward= depth-tmpForward;
50

  
51
    table.build(object,tmpForward);
52
    return table.tryReaching(object,mTargetQuats,tmpBackward,tmpForward);
53
    }
54

  
55
///////////////////////////////////////////////////////////////////////////////////////////////////
56

  
57
  private int prepareForSubPhase(SolvedObject object, MitmTable table)
58
    {
59
    table.prepareForSubPhase(mTargetQuats);
60
    int bytesPerEntry = table.getBytesPerEntry();
61
    int branchingFactor = object.getBranchingFactor();
62

  
63
    mForwardDepth  = computeForwardDepth(bytesPerEntry,branchingFactor);
64
    mBackwardDepth = computeBackwardDepth(branchingFactor);
65

  
66
    return mForwardDepth+mBackwardDepth;
67
    }
68

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

  
71
  private int computeForwardDepth(int bytesPerEntry, int branchingFactor)
72
    {
73
    int numEntries = MAX_MEMORY/bytesPerEntry;
74
    double maxDepth = Math.log(numEntries) / Math.log(branchingFactor);
75
    return (int)maxDepth;
76
    }
77

  
78
///////////////////////////////////////////////////////////////////////////////////////////////////
79
// how deep we can search our tree of moves 'backward' (from any one of the positions described by
80
// 'endQuats')
81

  
82
  private int computeBackwardDepth(int branchingFactor)
83
    {
84
    int multiplier = mTargetQuats.computeNumCombinations();
85
    double maxDepth = Math.log(MAX_SEARCH/multiplier) / Math.log(branchingFactor);
86
    return (int)maxDepth;
87
    }
88

  
89
///////////////////////////////////////////////////////////////////////////////////////////////////
90
// Find solution and modify the non-null initQuats to match the situation after applying it.
91

  
92
  private int[] findSol(SolvedObject object, MitmTable table, int depth)
93
    {
94
    int[] s = solve(object,table,depth);
95

  
96
    if( s!=null )
97
      {
98
      int len = s.length;
99
      for(int m=1; m<len; m++) object.makeMove(s[m]);
100
      }
101

  
102
    return s;
103
    }
104

  
105
///////////////////////////////////////////////////////////////////////////////////////////////////
106

  
107
  @Override
108
  public void prepareForSubphases()
109
    {
110
    mSolved = new boolean[mNumGroups];
111
    mWhichSubphase = new int[mNumCubits];
112

  
113
    for(int c=0; c<mNumCubits; c++) mWhichSubphase[c] = whichSubPhase(c);
114
    for(int s=0; s<mNumGroups; s++) mSolved[s] = false;
115
    }
116

  
117
///////////////////////////////////////////////////////////////////////////////////////////////////
118
// a) find solution moves which take us from 'initQuats' position to a position which satisfies the
119
//    'endQuats' criteria
120
// b) overwrite 'initQuats' with the found position
121
// c) return solution moves
122
//
123
// Of course this works only if there exists a solution with reasonable length (10 moves?) so we
124
// need to define our phases accurately.
125
//
126
// initQuats: quats of the cubits at the start of the phase. Index table to mObjectQuats.
127
// endQuats: describes what the quats should be at the end of the phase.
128
// If endQuat[i]==null, then this mean we do not care about the state of cubit i.
129
// Otherwise, the cubit must end up in state described by one of the ints from array 'endQuats[i]'.
130
//
131
// Here we try to find a single solution in one phase, i.e. solve at once all 'endQuats'.
132
// (example: the white cross phase of the beginner's 3x3 - all four edges solved at once)
133

  
134
  @Override
135
  public int[] findSolution(SolvedObject object, MitmTable table)
136
    {
137
    int maxdepth = prepareForSubPhase(object,table);
138

  
139
    for(int l=0; l<=maxdepth; l++)
140
      {
141
      int[] ret = findSol(object,table,l);
142
      if( ret!=null ) return ret;
143
      }
144

  
145
    return null;
146
    }
147

  
148
///////////////////////////////////////////////////////////////////////////////////////////////////
149

  
150
  @Override
151
  public boolean solveAnySubphase( SolvedObject object, MitmTable table, int[][] solution, int subPhase)
152
    {
153
    int maxDepth = 0;
154
    TargetQuats tmp = new TargetQuats(mTargetQuats);
155

  
156
    for( int d=0; d<=maxDepth; d++)
157
      for(int g=0; g<mNumGroups; g++)
158
        if( !mSolved[g] )
159
          {
160
          for(int q=0; q<mNumCubits; q++)
161
            {
162
            // -1 means that the cubit doesn't belong to the current phase. Cubits belonging to
163
            // the next phase already have their targetQuats set to null (see Phase.setTargetQuats)
164
            // Here we set to null (mark that we do not care about) the quats of all cubits which
165
            // belong to the current phase and haven't been solved yet (except the current subphase!).
166
            int sp = mWhichSubphase[q];
167
            mTargetQuats.set( (sp==-1 || sp==g || mSolved[sp]) ? tmp : null , q);
168
            }
169

  
170
          maxDepth = prepareForSubPhase(object,table);
171
          solution[subPhase] = findSol(object,table,d);
172

  
173
          if( solution[subPhase]!=null )
174
            {
175
            mTargetQuats.set(tmp);
176
            mSolved[g] = true;
177
            return true;
178
            }
179
          }
180

  
181
    mTargetQuats.set(tmp);
182
    return false;
183
    }
184
}
src/main/java/org/distorted/objectlib/algphases/PhaseNotCyclic.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.objectlib.algphases;
11

  
12
import org.distorted.objectlib.algsolvers.SolvedObject;
13

  
14
///////////////////////////////////////////////////////////////////////////////////////////////////
15

  
16
public class PhaseNotCyclic extends PhaseMitm
17
{
18
  public PhaseNotCyclic(SolvedObject object, int[][] cubitgroups)
19
    {
20
    super(object);
21

  
22
    mCubitGroups = cubitgroups;
23
    mNumGroups = cubitgroups.length;
24

  
25
    int numCubits = 0;
26
    for(int g=0; g<mNumGroups; g++) numCubits += mCubitGroups[g].length;
27

  
28
    mNumCubitsInThisPhase = numCubits;
29
    }
30
}
src/main/java/org/distorted/objectlib/algphases/PhaseRegex.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.objectlib.algphases;
11

  
12
import org.distorted.objectlib.algsolvers.MitmTable;
13
import org.distorted.objectlib.algsolvers.MoveRegex;
14
import org.distorted.objectlib.algsolvers.SolvedObject;
15
import org.distorted.objectlib.algsolvers.TargetQuats;
16

  
17
///////////////////////////////////////////////////////////////////////////////////////////////////
18

  
19
public class PhaseRegex extends Phase
20
{
21
  private final MoveRegex mRegex;
22
  private final boolean[] mSolved;
23
  private final int[][] mMoves;
24
  private final int[][] mBasicAngles;
25

  
26
  private int[] mWhichSubphase;
27

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

  
30
  public PhaseRegex(SolvedObject object, String regex, int[][] cubitgroups)
31
    {
32
    super(object);
33

  
34
    mCubitGroups = cubitgroups;
35
    mNumGroups = cubitgroups.length;
36
    mRegex = new MoveRegex(object,regex);
37
    mMoves = object.getMoveTable();
38
    mBasicAngles = object.getBasicAngles();
39

  
40
    int numCubits = 0;
41
    for(int g=0; g<mNumGroups; g++) numCubits += mCubitGroups[g].length;
42

  
43
    mNumCubitsInThisPhase = numCubits;
44

  
45
    mSolved = new boolean[mNumGroups];
46
    }
47

  
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

  
50
  private int findMove(int ax, int row, int angle)
51
    {
52
    int numMoves = mMoves.length;
53

  
54
    for(int m=0; m<numMoves; m++)
55
      {
56
      int[] move = mMoves[m];
57

  
58
      if( move[0]==ax && move[1]==row && move[2]==angle )
59
        return m;
60
      }
61

  
62
    return -1;
63
    }
64

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

  
67
  private int[] collapseMoves(int[] moves, int start, int end)
68
    {
69
    int numCut = end-start;
70
    int len = moves.length;
71
    int[] ret = new int[len-numCut];
72
    ret[0] = len-numCut-1;
73
    int index=1;
74

  
75
    for(int i=1; i<start; i++) ret[index++] = moves[i];
76
    for(int i=end; i<len; i++) ret[index++] = moves[i];
77

  
78
    return ret;
79
    }
80

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

  
83
  private int[] simplifyOnce(int[] moves)
84
    {
85
    int len = moves.length;
86
    int start, end;
87

  
88
    for(start=1; start<len; start++)
89
      {
90
      int[] m1 = mMoves[moves[start]];
91
      int totalAngle = m1[2];
92
      int ax = m1[0];
93
      int row= m1[1];
94

  
95
      for(end=start+1; end<len; end++)
96
        {
97
        int[] m2 = mMoves[moves[end]];
98
        if( ax!=m2[0] || row!=m2[1] ) break;
99
        totalAngle += m2[2];
100
        }
101

  
102
      if( end>start+1 )
103
        {
104
        int basicAngle = mBasicAngles[ax][row];
105
        totalAngle %= basicAngle;
106
        if( totalAngle> basicAngle/2 ) totalAngle -= basicAngle;
107
        if( totalAngle<-basicAngle/2 ) totalAngle += basicAngle;
108

  
109
        if( totalAngle==0 )
110
          {
111
          return collapseMoves(moves,start,end);
112
          }
113
        else
114
          {
115
          moves[start] = findMove(ax,row,totalAngle);
116
          return collapseMoves(moves,start+1,end);
117
          }
118
        }
119
      }
120

  
121
    return moves;
122
    }
123

  
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

  
126
  private int[] simplify(int[] moves)
127
    {
128
    int lenB, lenA;
129

  
130
    do
131
      {
132
      lenB = moves.length;
133
      moves = simplifyOnce(moves);
134
      lenA = moves.length;
135
      }
136
    while(lenB>lenA);
137

  
138
    return moves;
139
    }
140

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

  
143
  public void prepareForSubphases()
144
    {
145
    mWhichSubphase = new int[mNumCubits];
146

  
147
    for(int c=0; c<mNumCubits; c++) mWhichSubphase[c] = whichSubPhase(c);
148
    for(int s=0; s<mNumGroups; s++) mSolved[s] = false;
149
    }
150

  
151
///////////////////////////////////////////////////////////////////////////////////////////////////
152
// take the object, the regex and try to reach one of the mEndQuats
153

  
154
  public int[] findSolution(SolvedObject object, MitmTable table)
155
    {
156
    int[] moveSeq = mRegex.getFirst();
157
    int[] quats = object.getCopiedCubitQuats();
158

  
159
    do
160
      {
161
      int numMoves = (moveSeq==null ? 0 : moveSeq.length);
162
      for(int m=1; m<numMoves; m++) object.makeMove(moveSeq[m]);
163
      int[] qts = object.getCubitQuats();
164
      boolean solved = mTargetQuats.matchesQuats(qts);
165
      object.setUpStartingQuats(quats);
166
      if( solved ) return simplify(moveSeq);
167
      moveSeq = mRegex.getNext();
168
      }
169
    while( moveSeq!=null );
170

  
171
    return null;
172
    }
173

  
174
///////////////////////////////////////////////////////////////////////////////////////////////////
175

  
176
  public boolean solveAnySubphase(SolvedObject object, MitmTable table, int[][] solution, int solIndex)
177
    {
178
    TargetQuats tmp = new TargetQuats(mTargetQuats);
179

  
180
    for(int g=0; g<mNumGroups; g++)
181
      if( !mSolved[g] )
182
        {
183
        for(int q=0; q<mNumCubits; q++)
184
          {
185
          // -1 means that the cubit belongs to the previous (or next) phase. Cubits belonging to the
186
          // next phase already have their endQuats set to null (see PhasedSolver.figureOutEndQuatIndices)
187
          // Here we set to null (i.e. - mark that we do not care about) the quats of all cubits which
188
          // belong to the current phase and haven't been solved yet (except the current subphase!).
189
          int sp = mWhichSubphase[q];
190
          mTargetQuats.set( (sp==-1 || sp==g || mSolved[sp]) ? tmp : null , q);
191
          }
192

  
193
        solution[solIndex] = findSolution(object,table);
194

  
195
        if( solution[solIndex]!=null )
196
          {
197
          mTargetQuats.set(tmp);
198
          mSolved[g] = true;
199
          return true;
200
          }
201
        }
202

  
203
    mTargetQuats.set(tmp);
204
    return false;
205
    }
206
}
src/main/java/org/distorted/objectlib/algsolvers/MitmTable.java
11 11

  
12 12
///////////////////////////////////////////////////////////////////////////////////////////////////
13 13

  
14
public class MitmTable
14
class MitmTable
15 15
{
16 16
  private final int mBitsPerQuat;
17 17
  private final int mNumCubits;
......
24 24

  
25 25
///////////////////////////////////////////////////////////////////////////////////////////////////
26 26

  
27
  public MitmTable(int numCubits, int numQuats)
27
  MitmTable(int numCubits, int numQuats)
28 28
    {
29 29
    mBuildDepth= -1;
30 30
    mNumCubits = numCubits;
......
64 64

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

  
67
  public static String getQuatString(int[] quats)
67
  static String getQuatString(int[] quats)
68 68
    {
69 69
    StringBuilder sb = new StringBuilder();
70 70

  
......
79 79

  
80 80
///////////////////////////////////////////////////////////////////////////////////////////////////
81 81

  
82
  public static String getMultiQuatString(int[][] quats)
82
  static String getMultiQuatString(int[][] quats)
83 83
    {
84 84
    StringBuilder sb = new StringBuilder();
85 85

  
......
102 102

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

  
105
  public static String getSigString(byte[] sig)
105
  static String getSigString(byte[] sig)
106 106
    {
107 107
    StringBuilder sb = new StringBuilder();
108 108

  
......
117 117

  
118 118
///////////////////////////////////////////////////////////////////////////////////////////////////
119 119

  
120
  public int getBytesPerEntry()
120
  int getBytesPerEntry()
121 121
    {
122 122
    return mBytesPerEntry;
123 123
    }
124 124

  
125 125
///////////////////////////////////////////////////////////////////////////////////////////////////
126 126

  
127
  public void prepareForSubPhase(TargetQuats quats)
127
  void prepareForSubPhase(TargetQuats quats)
128 128
    {
129 129
    int numUsedCubits = quats.computeUsedCubitTable(mUseCubit);
130 130
    double numBytes = numUsedCubits*mBitsPerQuat/8.0;
......
134 134

  
135 135
///////////////////////////////////////////////////////////////////////////////////////////////////
136 136

  
137
  public void build(SolvedObject object, int depth)
137
  void build(SolvedObject object, MoveProvider provider, int depth)
138 138
    {
139 139
    if( mBuildDepth<depth )
140 140
      {
141
      int branchingFactor = object.getBranchingFactor();
142 141
      mData.clear();
143
      buildRecursive(object,branchingFactor,-1,depth);
142
      buildRecursive(object,provider,-1,depth);
144 143
      mBuildDepth = depth;
145 144
      }
146 145
    }
147 146

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

  
149
  private void buildRecursive(SolvedObject object, MoveProvider provider, int previousMove, int depth)
150
    {
151
    int[] quats = object.getCubitQuats();
152
    byte[] signature = pack(quats);
153
    mData.add(signature);
154

  
155
    if( depth>0 )
156
      {
157
      int pos = provider.getPosition();
158
      int mv = provider.firstPointer(previousMove);
159
      int[] move = provider.getCurrent();
160

  
161
      while( move!=null )
162
        {
163
        for(int m : move) object.makeMove(m);
164
        buildRecursive(object,provider,mv,depth-1);
165
        for(int m : move) object.backMove(m);
166
        mv = provider.nextPointer(previousMove);
167
        move = provider.getCurrent();
168
        }
169

  
170
      provider.setPosition(pos);
171
      }
172
    }
173

  
148 174
///////////////////////////////////////////////////////////////////////////////////////////////////
149 175
// Having built the MiTM table, try to reach it working backwards from each of the positions
150 176
// described by 'endQuats'.
......
155 181
// {0} means solution found and it's empty (position already solved)
156 182
// {2,1,3} means the solution is 2 moves long, and the indices of moves to make are 1 and 3.
157 183

  
158
  public int[] tryReaching(SolvedObject object, TargetQuats target, int lenb, int lenf)
184
  int[] tryReaching(SolvedObject object, MoveProvider provider, TargetQuats target, int lenb, int lenf)
159 185
    {
160
    int branching = object.getBranchingFactor();
161 186
    int[] backward = new int[lenb];
162 187
    int[] rem = object.getCopiedCubitQuats();
163 188
    int[] quats = target.getFirst();
......
165 190
    do
166 191
      {
167 192
      object.setUpStartingQuats(quats);
168
      byte[] reached = tryReachingRecursive(object,branching,lenb,backward);
193
      byte[] reached = tryReachingRecursive(object,provider,lenb,backward);
169 194

  
170 195
      if( reached!=null )
171 196
        {
172 197
        object.setUpStartingQuats(rem);
173 198
        int[] forward = new int[lenf];
174
        int numMoves = reachForward(object,reached,forward,lenf);
199
        int numMoves = reachForward(object,provider,reached,forward,lenf);
175 200
        return joinSequences(forward,numMoves,backward);
176 201
        }
177 202

  
......
180 205
    while( quats!=null );
181 206

  
182 207
    object.setUpStartingQuats(rem);
208

  
183 209
    return null;
184 210
    }
185 211

  
186 212
///////////////////////////////////////////////////////////////////////////////////////////////////
187 213

  
188
  private byte[] tryReachingRecursive(SolvedObject object, int branching, int len, int[] ret)
214
  private byte[] tryReachingRecursive(SolvedObject object, MoveProvider provider, int len, int[] ret)
189 215
    {
190 216
    int[] quats = object.getCubitQuats();
191 217
    byte[] signature = pack(quats);
......
194 220

  
195 221
    if( len>0 )
196 222
      {
223
      int pos = provider.getPosition();
197 224
      int previousMove = len<ret.length ? ret[len] : -1;
225
      ret[len-1] = provider.firstPointer(previousMove);
226
      int[] move = provider.getCurrent();
198 227

  
199
      for(int m=0; m<branching; m++)
200
        if( object.movesDontClash(m,previousMove) )
201
          {
202
          object.backMove(m);
203
          ret[len-1] = m;
204
          byte[] reached = tryReachingRecursive(object,branching,len-1,ret);
205
          object.makeMove(m);
228
      while( move!=null )
229
        {
230
        for(int m : move) object.backMove(m);
231
        byte[] reached = tryReachingRecursive(object,provider,len-1,ret);
232
        for(int m : move) object.makeMove(m);
206 233

  
207
          if( reached!=null ) return reached;
234
        if( reached!=null )
235
          {
236
          provider.setPosition(pos);
237
          return reached;
208 238
          }
239

  
240
        ret[len-1] = provider.nextPointer(previousMove);
241
        move = provider.getCurrent();
242
        }
243
      provider.setPosition(pos);
209 244
      }
210 245

  
211 246
    return null;
......
213 248

  
214 249
///////////////////////////////////////////////////////////////////////////////////////////////////
215 250

  
216
  private int reachForward(SolvedObject object, byte[] signature, int[] ret, int len)
251
  private int reachForward(SolvedObject object, MoveProvider provider, byte[] signature, int[] ret, int len)
217 252
    {
218 253
    int[] quats = unpack(signature);
219 254
    int[] objqs = object.getCubitQuats();
......
222 257

  
223 258
    if( len>0 )
224 259
      {
225
      int branching = object.getBranchingFactor();
260
      int pos = provider.getPosition();
261
      ret[0] = provider.firstPointer(-1);
262
      int[] move = provider.getCurrent();
226 263

  
227
      for(int m=0; m<branching; m++)
264
      while( move!=null )
228 265
        {
229
        object.makeMove(m);
230
        ret[0] = m;
231
        int numMoves = reachForwardRecursive(object,quats,ret,1,len-1);
232
        object.backMove(m);
233
        if( numMoves>=0 ) return numMoves+1;
266
        for(int m : move) object.makeMove(m);
267
        int numMoves = reachForwardRecursive(object,provider,quats,ret,1,len-1);
268
        for(int m : move) object.backMove(m);
269

  
270
        if( numMoves>=0 )
271
          {
272
          provider.setPosition(pos);
273
          return numMoves+1;
274
          }
275

  
276
        ret[0] = provider.nextPointer(-1);
277
        move = provider.getCurrent();
234 278
        }
279
      provider.setPosition(pos);
235 280
      }
236 281

  
237 282
    System.out.println("ERROR in reachForward: returning -1");
......
241 286

  
242 287
///////////////////////////////////////////////////////////////////////////////////////////////////
243 288

  
244
  private int reachForwardRecursive(SolvedObject object, int[] quats, int[] ret, int index, int len)
289
  private int reachForwardRecursive(SolvedObject object, MoveProvider provider, int[] quats, int[] ret, int index, int len)
245 290
    {
246 291
    int[] objqs = object.getCubitQuats();
247 292
    if( quatsMatch(quats,objqs) ) return 0;
248 293

  
249 294
    if( len>0 )
250 295
      {
251
      int branching = object.getBranchingFactor();
252
      int previousM = ret[index-1];
296
      int pos = provider.getPosition();
297
      int previousMove = ret[index-1];
298
      ret[index] = provider.firstPointer(previousMove);
299
      int[] move = provider.getCurrent();
253 300

  
254
      for(int m=0; m<branching; m++)
255
        if(object.movesDontClash(m,previousM) )
256
          {
257
          object.makeMove(m);
258
          ret[index] = m;
259
          int numMoves = reachForwardRecursive(object,quats,ret,index+1,len-1);
260
          object.backMove(m);
301
      while( move!=null )
302
        {
303
        for(int m : move) object.makeMove(m);
304
        int numMoves = reachForwardRecursive(object,provider,quats,ret,index+1,len-1);
305
        for(int m : move) object.backMove(m);
261 306

  
262
          if( numMoves>=0 ) return numMoves+1;
307
        if( numMoves>=0 )
308
          {
309
          provider.setPosition(pos);
310
          return numMoves+1;
263 311
          }
312

  
313
        ret[index] = provider.nextPointer(previousMove);
314
        move = provider.getCurrent();
315
        }
316

  
317
      provider.setPosition(pos);
264 318
      }
265 319

  
266 320
    return -1;
......
304 358
    return ret;
305 359
    }
306 360

  
307
///////////////////////////////////////////////////////////////////////////////////////////////////
308

  
309
  private void buildRecursive(SolvedObject object, int branching, int previousMove, int depth)
310
    {
311
    int[] quats = object.getCubitQuats();
312
    byte[] signature = pack(quats);
313
    mData.add(signature);
314

  
315
    if( depth>0 )
316
      for(int m=0; m<branching; m++)
317
        if( object.movesDontClash(m,previousMove) )
318
          {
319
          object.makeMove(m);
320
          buildRecursive(object,branching,m,depth-1);
321
          object.backMove(m);
322
          }
323
    }
324

  
325 361
///////////////////////////////////////////////////////////////////////////////////////////////////
326 362
// Find index'th entry in the table 'output'; it contains 8 bits. Write 'value' to it, but only
327 363
// its 'toBeWritten' first bits (out of the 'remaining' bits), and at offset 'offset' in the table.
src/main/java/org/distorted/objectlib/algsolvers/MitmTableDataStructure.java
29 29

  
30 30
///////////////////////////////////////////////////////////////////////////////////////////////////
31 31

  
32
  MitmTableDataStructure()
33
    {
34
    mData = new HashSet<>();
35
    }
36

  
37
///////////////////////////////////////////////////////////////////////////////////////////////////
38

  
39
  void clear()
40
    {
41
    mData.clear();
42
    }
43

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

  
46
  boolean contains(byte[] bytes)
47
    {
48
    return mData.contains(new ByteArray(bytes));
49
    }
50

  
51
///////////////////////////////////////////////////////////////////////////////////////////////////
52

  
53
  void add(byte[] bytes)
54
    {
55
    mData.add(new ByteArray(bytes));
56
    }
32
  MitmTableDataStructure()       { mData = new HashSet<>(); }
33
  void clear()                   { mData.clear(); }
34
  boolean contains(byte[] bytes) { return mData.contains(new ByteArray(bytes)); }
35
  void add(byte[] bytes)         { mData.add(new ByteArray(bytes)); }
57 36
}
src/main/java/org/distorted/objectlib/algsolvers/MoveProvider.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.objectlib.algsolvers;
11

  
12
///////////////////////////////////////////////////////////////////////////////////////////////////
13

  
14
abstract public class MoveProvider
15
{
16
  protected int mNumMoves;
17
  protected int mCurrentMove;
18

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

  
21
  MoveProvider(int numMoves)
22
    {
23
    mNumMoves = numMoves;
24
    mCurrentMove = 0;
25
    }
26

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

  
29
  int getPosition()          { return mCurrentMove; }
30
  void setPosition(int pos)  { mCurrentMove = pos; }
31

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

  
34
  abstract int firstPointer(int previousMove);
35
  abstract int nextPointer(int previousMove);
36
  abstract int[] getCurrent();
37
}
src/main/java/org/distorted/objectlib/algsolvers/MoveProviderAlgs.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.objectlib.algsolvers;
11

  
12
///////////////////////////////////////////////////////////////////////////////////////////////////
13

  
14
public class MoveProviderAlgs extends MoveProvider
15
{
16
  private final int[][] mAlgorithms;
17

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

  
20
  public MoveProviderAlgs(int[][] algorithms)
21
    {
22
    super(algorithms.length);
23
    mAlgorithms = algorithms;
24
    }
25

  
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27

  
28
  int firstPointer(int previousMove)
29
    {
30
    mCurrentMove = 0;
31
    return 0;
32
    }
33

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

  
36
  int nextPointer(int previousMove)
37
    {
38
    mCurrentMove++;
39
    if( mCurrentMove>=mNumMoves ) mCurrentMove = -1;
40
    return mCurrentMove;
41
    }
42

  
43
///////////////////////////////////////////////////////////////////////////////////////////////////
44

  
45
  int[] getCurrent()
46
    {
47
    return mCurrentMove>=0 ? mAlgorithms[mCurrentMove] : null;
48
    }
49
}
src/main/java/org/distorted/objectlib/algsolvers/MoveProviderAll.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.objectlib.algsolvers;
11

  
12
///////////////////////////////////////////////////////////////////////////////////////////////////
13

  
14
public class MoveProviderAll extends MoveProvider
15
{
16
  private final int[][] mMoveTable;
17

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

  
20
  public MoveProviderAll(int[][] moveTable)
21
    {
22
    super(moveTable.length);
23
    mMoveTable = moveTable;
24
    }
25

  
26
///////////////////////////////////////////////////////////////////////////////////////////////////
27
// moves clash iff they are both along the same axis and the same row
28

  
29
  private boolean movesClash(int move1, int move2)
30
    {
31
    if( move1>=0 && move2>=0 )
32
      {
33
      int[] m1 = mMoveTable[move1];
34
      int[] m2 = mMoveTable[move2];
35

  
36
      return ( m1[0]==m2[0] && m1[1]==m2[1] );
37
      }
38

  
39
    return false;
40
    }
41

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

  
44
  int firstPointer(int previousMove)
45
    {
46
    mCurrentMove = 0;
47
    return 0;
48
    }
49

  
50
///////////////////////////////////////////////////////////////////////////////////////////////////
51

  
52
  int nextPointer(int previousMove)
53
    {
54
    mCurrentMove++;
55

  
56
    if( mCurrentMove>=mNumMoves )
57
      {
58
      mCurrentMove = -1;
59
      return mCurrentMove;
60
      }
61

  
62
    while( movesClash(previousMove,mCurrentMove) )
63
      {
64
      mCurrentMove++;
65

  
66
      if( mCurrentMove>=mNumMoves )
67
        {
68
        mCurrentMove = -1;
69
        break;
70
        }
71
      }
72

  
73
    return mCurrentMove;
74
    }
75

  
76
///////////////////////////////////////////////////////////////////////////////////////////////////
77

  
78
  int[] getCurrent()
79
    {
80
    return mCurrentMove>=0 ? new int[] { mCurrentMove } : null;
81
    }
82
}
src/main/java/org/distorted/objectlib/algsolvers/MoveRegex.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      //
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff