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.phasedsolver;
|
11
|
|
12
|
import static org.distorted.objectlib.main.TwistyObject.MODE_NORM;
|
13
|
|
14
|
import android.app.Activity;
|
15
|
import android.content.SharedPreferences;
|
16
|
import android.os.Bundle;
|
17
|
import android.view.View;
|
18
|
import android.widget.TextView;
|
19
|
import android.widget.Toast;
|
20
|
|
21
|
import androidx.preference.PreferenceManager;
|
22
|
|
23
|
import org.distorted.library.main.DistortedLibrary;
|
24
|
import org.distorted.library.type.Static3D;
|
25
|
import org.distorted.objectlib.algsolvers.PhaseMitm;
|
26
|
import org.distorted.objectlib.algsolvers.*;
|
27
|
import org.distorted.objectlib.main.InitAssets;
|
28
|
import org.distorted.objectlib.main.ObjectControl;
|
29
|
import org.distorted.objectlib.main.TwistyObject;
|
30
|
import org.distorted.objectlib.metadata.ListObjects;
|
31
|
import org.distorted.os.OSInterface;
|
32
|
|
33
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
34
|
|
35
|
public class SolverActivity extends Activity
|
36
|
{
|
37
|
private InitAssets mAsset;
|
38
|
private SharedPreferences mPreferences;
|
39
|
private SolverLowerPane mLowerPane;
|
40
|
private TextView mText;
|
41
|
private SolvedObject mObject;
|
42
|
private int[][] mMoveTable;
|
43
|
private String mMoves;
|
44
|
private int mNumMoves;
|
45
|
|
46
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
47
|
|
48
|
@Override
|
49
|
protected void onCreate(Bundle icicle)
|
50
|
{
|
51
|
super.onCreate(icicle);
|
52
|
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
53
|
DistortedLibrary.onCreate();
|
54
|
setContentView(R.layout.mainlayout);
|
55
|
SolverSurfaceView view = findViewById(R.id.solverView);
|
56
|
OSInterface os = view.getInterface();
|
57
|
mAsset = new InitAssets(null, null, os);
|
58
|
mLowerPane = new SolverLowerPane(this);
|
59
|
mText = findViewById(R.id.solverMoves);
|
60
|
mMoves = "";
|
61
|
mNumMoves = 0;
|
62
|
}
|
63
|
|
64
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
65
|
|
66
|
@Override
|
67
|
protected void onPause()
|
68
|
{
|
69
|
super.onPause();
|
70
|
SolverSurfaceView view = findViewById(R.id.solverView);
|
71
|
view.onPause();
|
72
|
DistortedLibrary.onPause();
|
73
|
|
74
|
savePreferences();
|
75
|
}
|
76
|
|
77
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
78
|
|
79
|
@Override
|
80
|
protected void onResume()
|
81
|
{
|
82
|
super.onResume();
|
83
|
SolverSurfaceView view = findViewById(R.id.solverView);
|
84
|
view.onResume();
|
85
|
DistortedLibrary.onResume();
|
86
|
|
87
|
restorePreferences();
|
88
|
|
89
|
ObjectControl control = getControl();
|
90
|
control.changeObject(ListObjects.CUBE_3.ordinal(), MODE_NORM, mAsset);
|
91
|
}
|
92
|
|
93
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
94
|
|
95
|
@Override
|
96
|
protected void onDestroy()
|
97
|
{
|
98
|
DistortedLibrary.onDestroy();
|
99
|
super.onDestroy();
|
100
|
}
|
101
|
|
102
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
103
|
|
104
|
ObjectControl getControl()
|
105
|
{
|
106
|
SolverSurfaceView view = findViewById(R.id.solverView);
|
107
|
return view.getObjectControl();
|
108
|
}
|
109
|
|
110
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
111
|
|
112
|
private void savePreferences()
|
113
|
{
|
114
|
SharedPreferences.Editor editor = mPreferences.edit();
|
115
|
SolverSurfaceView view = findViewById(R.id.solverView);
|
116
|
OSInterface os = view.getInterface();
|
117
|
os.setEditor(editor);
|
118
|
view.getObjectControl().savePreferences();
|
119
|
|
120
|
editor.apply();
|
121
|
}
|
122
|
|
123
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
124
|
|
125
|
private void restorePreferences()
|
126
|
{
|
127
|
SolverSurfaceView view = findViewById(R.id.solverView);
|
128
|
OSInterface os = view.getInterface();
|
129
|
os.setPreferences(mPreferences);
|
130
|
view.getObjectControl().restorePreferences();
|
131
|
}
|
132
|
|
133
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
134
|
|
135
|
private void solve(SolverPhased ps, int[] quats)
|
136
|
{
|
137
|
int[][] sol = ps.solution(quats);
|
138
|
int numPhases = sol.length;
|
139
|
int totalLength = 0;
|
140
|
|
141
|
for(int p=0; p<numPhases; p++)
|
142
|
{
|
143
|
int numMoves = sol[p]==null ? -1 : sol[p][0];
|
144
|
|
145
|
if( numMoves<0 )
|
146
|
{
|
147
|
String message = "Phase "+p+": FAIL";
|
148
|
Toast.makeText(this,message,Toast.LENGTH_LONG).show();
|
149
|
return;
|
150
|
}
|
151
|
|
152
|
totalLength += numMoves;
|
153
|
}
|
154
|
|
155
|
int[][] moves = new int[totalLength][];
|
156
|
int index = 0;
|
157
|
|
158
|
for( int[] s : sol )
|
159
|
{
|
160
|
int numMoves = s[0];
|
161
|
|
162
|
for(int m=1; m<=numMoves; m++)
|
163
|
{
|
164
|
int mi = s[m];
|
165
|
moves[index++] = mMoveTable[mi];
|
166
|
// android.util.Log.e("D","move "+m+" : "+mMoveTable[mi][0]+" "+mMoveTable[mi][1]+" "+mMoveTable[mi][2]);
|
167
|
}
|
168
|
}
|
169
|
|
170
|
mLowerPane.setMoves(this,moves);
|
171
|
}
|
172
|
|
173
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
174
|
|
175
|
private void createObject()
|
176
|
{
|
177
|
TwistyObject object = getControl().getObject();
|
178
|
|
179
|
int[] numL = object.getNumLayers();
|
180
|
float[][] pos = object.getCubitPositions(numL);
|
181
|
Static3D[] axis = object.getRotationAxis();
|
182
|
int[][] angles = object.getBasicAngles();
|
183
|
float[][] cuts = object.getCuts(numL);
|
184
|
|
185
|
boolean[] r = {true,false,true};
|
186
|
boolean[][] rot = {r,r,r};//object.getLayerRotatable(numL);
|
187
|
|
188
|
mObject = new SolvedObject(pos,axis,angles,cuts,rot);
|
189
|
mMoveTable = mObject.getMoveTable();
|
190
|
}
|
191
|
|
192
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
193
|
|
194
|
public void Solve(View v)
|
195
|
{
|
196
|
if( mObject==null ) createObject();
|
197
|
|
198
|
TwistyObject object = getControl().getObject();
|
199
|
int[] numL = object.getNumLayers();
|
200
|
float[][] pos = object.getCubitPositions(numL);
|
201
|
|
202
|
int numCubits = pos.length;
|
203
|
int[] qi = new int[numCubits];
|
204
|
for(int i=0; i<numCubits; i++) qi[i] = object.getCubitQuatIndex(i);
|
205
|
|
206
|
int[][] whiteCross = new int[][]{ {12,13,16,17} };
|
207
|
int[][] whiteCorners = new int[][]{ {0},{1},{2},{3} };
|
208
|
int[][] secondLayer = new int[][]{ {8},{9},{10},{11} };
|
209
|
|
210
|
int[][] algsSecondL = { { 6, 3, 8, 3,15, 5,17}, {15, 5,17, 5, 6, 3, 8},
|
211
|
{12, 3,14, 3, 8, 5, 6}, { 8, 5, 6, 5,12, 3,14},
|
212
|
{11, 3, 9, 3,14, 5,12}, {14, 5,12, 5,11, 3, 9},
|
213
|
{17, 3,15, 3, 9, 5,11}, { 9, 5,11, 5,17, 3,15},
|
214
|
{3}
|
215
|
};
|
216
|
|
217
|
int[][] algsEdgeOrie = { {11,17,5,15,3,9},{3} };
|
218
|
int[][] algsEdgePerm = { {6,5,8,5,6,4,8},{3} };
|
219
|
int[][] algsCornPerm = { {5,6,3,9,5,8,3,11},{3} };
|
220
|
int[][] algsCornOrie = { {15,2,17,0,15,2,17,0},{3} };
|
221
|
|
222
|
int[][] moveTable = mObject.getMoveTable();
|
223
|
MoveProviderAll all = new MoveProviderAll(moveTable);
|
224
|
MoveProviderAlgs asl = new MoveProviderAlgs(algsSecondL);
|
225
|
MoveProviderAlgs aeO = new MoveProviderAlgs(algsEdgeOrie);
|
226
|
MoveProviderAlgs aeP = new MoveProviderAlgs(algsEdgePerm);
|
227
|
MoveProviderAlgs acP = new MoveProviderAlgs(algsCornPerm);
|
228
|
MoveProviderAlgs acO = new MoveProviderAlgs(algsCornOrie);
|
229
|
|
230
|
TargetProvider wcr = new TargetProviderAll(whiteCross);
|
231
|
TargetProvider wco = new TargetProviderAll(whiteCorners);
|
232
|
TargetProvider sla = new TargetProviderAll(secondLayer);
|
233
|
TargetProvider oll = new TargetProviderOrie(mObject,14,1);
|
234
|
TargetProvider pll = new TargetProviderPerm(mObject,14,1);
|
235
|
TargetProvider pcl = new TargetProviderPerm(mObject, 4,1);
|
236
|
TargetProvider ocl = new TargetProviderOrie(mObject, 4,1);
|
237
|
|
238
|
Phase[] phases =
|
239
|
{
|
240
|
new PhaseMitm( mObject, all, wcr),
|
241
|
new PhaseMitm( mObject, all, wco),
|
242
|
new PhaseMitm( mObject, asl, sla),
|
243
|
new PhaseMitm( mObject, aeO, oll),
|
244
|
new PhaseMitm( mObject, aeP, pll),
|
245
|
new PhaseMitm( mObject, acP, pcl),
|
246
|
new PhaseMitm( mObject, acO, ocl),
|
247
|
};
|
248
|
|
249
|
SolverPhased ps = new SolverPhased(mObject,phases);
|
250
|
|
251
|
runOnUiThread(new Runnable()
|
252
|
{
|
253
|
@Override
|
254
|
public void run()
|
255
|
{
|
256
|
solve(ps,qi);
|
257
|
}
|
258
|
});
|
259
|
}
|
260
|
|
261
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
262
|
|
263
|
public void Reset(View v)
|
264
|
{
|
265
|
ObjectControl control = getControl();
|
266
|
control.solveObject();
|
267
|
mLowerPane.clearMoves(this);
|
268
|
|
269
|
mNumMoves = 0;
|
270
|
mMoves = "";
|
271
|
mText.setText(mMoves);
|
272
|
}
|
273
|
|
274
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
275
|
|
276
|
int findMove(int ax, int row, int angle)
|
277
|
{
|
278
|
int num = mMoveTable.length;
|
279
|
|
280
|
for( int m=0; m<num; m++)
|
281
|
{
|
282
|
int[] move = mMoveTable[m];
|
283
|
if( ax==move[0] && row==move[1] && angle==move[2] ) return m;
|
284
|
}
|
285
|
|
286
|
return -1;
|
287
|
}
|
288
|
|
289
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
290
|
|
291
|
void addMove(int axis, int row, int angle)
|
292
|
{
|
293
|
if( mObject==null ) createObject();
|
294
|
int move = findMove(axis,row,angle);
|
295
|
mMoves += (" "+move);
|
296
|
mNumMoves++;
|
297
|
|
298
|
if( mNumMoves>10 )
|
299
|
{
|
300
|
int space = mMoves.indexOf(' ');
|
301
|
mMoves = mMoves.substring(space+2);
|
302
|
mNumMoves--;
|
303
|
}
|
304
|
|
305
|
mText.setText(mMoves);
|
306
|
}
|
307
|
|
308
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
309
|
|
310
|
public void Left(View v)
|
311
|
{
|
312
|
mLowerPane.backMove(this);
|
313
|
}
|
314
|
|
315
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
316
|
|
317
|
public void Right(View v)
|
318
|
{
|
319
|
mLowerPane.makeMove(this);
|
320
|
}
|
321
|
}
|